/* netscanner.cpp * * Copyright (c) 2000, Alexander Neundorf, * neundorf@kde.org * * You may distribute under the terms of the GNU General Public * License as specified in the COPYING file. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include "config.h" #include "netscanner.h" #include "ipaddress.h" #include "lisadefines.h" #include #ifdef LISA_DEBUG #undef LISA_DEBUG #endif #define LISA_DEBUG 0 #ifdef dcerr #undef dcerr #endif #ifdef mdcerr #undef mdcerr #endif #define dcerr if (LISA_DEBUG==1) std::cerr<<"NetScanner::" #define mdcerr if (LISA_DEBUG==1) std::cerr< #include #include #ifdef __osf__ #undef BYTE_ORDER #define _OSF_SOURCE #undef _MACHINE_ENDIAN_H_ #undef __STDC__ #define __STDC__ 0 #include #undef __STDC__ #define __STDC__ 1 #endif #include #include #include #ifndef INADDR_NONE #define INADDR_NONE -1 #endif struct ICMPEchoRequest { unsigned char type; unsigned char code; unsigned short int checkSum; unsigned short id; unsigned short seqNumber; }; unsigned short in_cksum(unsigned short *addr, int len) { int nleft = len; int sum(0); unsigned short *w = addr; unsigned short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* 4mop up an odd byte, if necessary */ if (nleft == 1) { *(unsigned char *)(&answer) = *(unsigned char *)w ; sum += answer; } /* 4add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer); } NetScanner::NetScanner(int& rawSocketFD, int strictMode) :procId("") ,m_firstWait(5) ,m_secondWait(15) ,m_strictMode(strictMode) ,m_rawSocketFD(rawSocketFD) ,validator() ,ipRangeStr(";") ,m_maxPings(256) ,m_deliverUnnamedHosts(0) ,m_useNmblookup(0) ,hostList(0) ,tmpIPRange("") {} NetScanner::~NetScanner() { // std::cerr<<"----------- Netscanner dtor "<=STRICTMODEMAXHOSTS)) break; memcpy(&server_addr, hp->h_addr, sizeof(server_addr)); char *ip=inet_ntoa(server_addr); mdcerr<<"configure(): looking up "<1024) m_maxPings=1024; //on some systems (Solaris ?) select() doesn't work correctly // if the microseconds are more than 1.000.000 if (m_firstWait>99) m_firstWait=99; if (m_secondWait>99) m_secondWait=99; mdcerr<<"configure(): "<toIP) { tmpIndex+=1+toIP-fromIP; indexLeft=indexLeft-(1+toIP-fromIP); //mdcerr<<"i: "<h_name<h_name; } void NetScanner::nmblookupScan(std::list* newList) { mdcerr<<"nmblookupScan()"<clear(); FILE * nmblookupFile=popen("nmblookup \"*\"","r"); //no success if (nmblookupFile==0) { mdcerr<<"nmblookupScan(): could not start nmblookup"<=3) done=1; } else if (result>0) { //read stuff int bytesRead=::read(nmblookupFd,tmpBuf,16*1024); //pipe closed if (bytesRead==0) done=1; else { char *newBuf=new char[bufferSize+bytesRead]; if (receiveBuffer!=0) { memcpy(newBuf,receiveBuffer,bufferSize); delete [] receiveBuffer; } memcpy(newBuf+bufferSize,tmpBuf,bytesRead); receiveBuffer=newBuf; bufferSize+=bytesRead; } } } while (!done); // Warning: The return value of pclose may be incorrect due to the // SIGCHLD handler that is installed. Ignore it! pclose(nmblookupFile); delete [] tmpBuf; //we received nothing if (receiveBuffer==0) return; //check for a terrminating '\0' if (receiveBuffer[bufferSize-1]=='\0') receiveBuffer[bufferSize-1]='\0'; //std::cerr<0) { //mdcerr<<"bytesLeft: "<1000) break; bytesLeft=bytesLeft-strLength-1; if (bufferState==0) { if (isdigit(tmpBuf[0])) bufferState=1; } //yes, no else ! if (bufferState==1) { char tmpIP[1024]; //std::cerr<<"tmpBuf: -"<\n",tmpIP) == 1) { mdcerr<<"nmblookupScan: tmpIP: -"<push_back(Node(dummy,addr.sin_addr.s_addr)); } } } } tmpBuf=endOfLine+1; }; mdcerr<<"nmblookupScan: finished"<* newList) //the ping-version { mdcerr<<"pingScan()"<clear(); MyString dummy(""); mdcerr<<"pingScan: m_maxPings: "<0) { ::recvfrom(m_rawSocketFD,(char*)&receiveBuf,16*1024,0,0,0); tv1.tv_sec = 0; tv1.tv_usec = 0; FD_ZERO(&clearSet); FD_SET(m_rawSocketFD,&clearSet); } //now the buffer should be empty //wait a moment for answers tv1.tv_sec = 0; tv1.tv_usec = m_firstWait*10*1000;//0.5 sec int loopCount(2); if (m_secondWait<0) loopCount=1; for (int repeatOnce=0; repeatOnce0) { received=recvfrom(m_rawSocketFD, (char*)&receiveBuf, 16*1024, 0, (sockaddr*)&fromAddr, &length); if (received!=-1) { // mdcerr<<"pingScan: received from "<ip_hl)*4; icmp *recIcmpFrame=(icmp*)(receiveBuf+icmpOffset); int iType=recIcmpFrame->icmp_type; //if its a ICMP echo reply if ((iType==ICMP_ECHOREPLY) //to an echo request we sent && (recIcmpFrame->icmp_id==pid) //and the host is not yet in the list && (!hostAlreadyInList(fromAddr.sin_addr.s_addr,newList))) { //this is an answer to our request :-) // mdcerr<<"pingScan: adding "<push_back(Node(dummy,fromAddr.sin_addr.s_addr)); } } tv1.tv_sec=0; tv1.tv_usec=0; FD_ZERO(&sockFDset); FD_SET(m_rawSocketFD,&sockFDset); //FD_SET(sockFD,&sockFDset); } } tv1.tv_sec = 0; tv1.tv_usec = m_secondWait*10*1000;//0.5 sec } mdcerr<<"pingScan() ends"<* tmpPingList=new std::list; mdcerr<<"doScan: created list"<* nodes) { for (std::list::iterator node = nodes->begin(); node != nodes->end(); node++) { if (node->ip==ip) return 1; } return 0; } void NetScanner::removeUnnamedHosts(std::list* nodes) { nodes->remove_if(is_unnamed_node()); } void NetScanner::completeNames(std::list* nodes) { struct sockaddr_in tmpAddr; //for every host for (std::list::iterator node = nodes->begin(); node != nodes->end(); node++) { tmpAddr.sin_addr.s_addr=node->ip; mdcerr<<"completeNames: looking up "<::iterator oldNode=hostList->begin(); oldNode!=hostList->end(); oldNode++) { if (node->ip==oldNode->ip) { mdcerr<<"completeNames: cached: "<name<<" :-)"<name=oldNode->name; done=1; break; } } //otherwise do a name lookup if (!done) { //IPAddress tmpAddress(node->ip); //mdcerr<<"NetScanner::completeNames: doing actual lookup"<name=ip2Name(tmpAddr.sin_addr); mdcerr<<"completeNames: resolved: "<name<