/* * findnic.cpp * * Copyright (c) 2001 Alexander Neundorf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * 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. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #ifdef HAVE_SYS_SOCKIO_H #include #endif #include #include #include #include #include #include #include #ifdef USE_SOLARIS /* net/if.h is incompatible with STL on Solaris 2.6 - 2.8, redefine map in the header file because we don't need it. -- Simon Josefsson */ #define map junkmap #endif # include #ifdef USE_SOLARIS #undef map #endif #include #ifndef HAVE_STRUCT_SOCKADDR_SA_LEN #undef HAVE_GETNAMEINFO #undef HAVE_GETIFADDRS #endif #if defined(HAVE_GETNAMEINFO) && defined(HAVE_GETIFADDRS) #include #include #include TQString flags_tos (unsigned int flags); #endif #include "findnic.h" #include #include NICList* findNICs() { NICList* nl=new NICList; nl->setAutoDelete(true); #if !defined(HAVE_GETIFADDRS) && !defined(HAVE_GETNAMEINFO) int sockfd = socket(AF_INET, SOCK_DGRAM, 0); char buf[8*1024]; struct ifconf ifc; ifc.ifc_len = sizeof(buf); ifc.ifc_req = (struct ifreq *) buf; int result=ioctl(sockfd, SIOCGIFCONF, &ifc); for (char* ptr = buf; ptr < buf + ifc.ifc_len; ) { struct ifreq *ifr =(struct ifreq *) ptr; int len = sizeof(struct sockaddr); #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN if (ifr->ifr_addr.sa_len > len) len = ifr->ifr_addr.sa_len; /* length > 16 */ #endif ptr += sizeof(ifr->ifr_name) + len; /* for next one in buffer */ int flags; struct sockaddr_in *sinptr; MyNIC *tmp=0; switch (ifr->ifr_addr.sa_family) { case AF_INET: sinptr = (struct sockaddr_in *) &ifr->ifr_addr; flags=0; struct ifreq ifcopy; ifcopy=*ifr; result=ioctl(sockfd,SIOCGIFFLAGS,&ifcopy); flags=ifcopy.ifr_flags; tmp=new MyNIC; tmp->name=ifr->ifr_name; if ((flags & IFF_UP) == IFF_UP) tmp->state=i18n("Up"); else tmp->state=i18n("Down"); if ((flags & IFF_BROADCAST) == IFF_BROADCAST) tmp->type=i18n("Broadcast"); else if ((flags & IFF_POINTOPOINT) == IFF_POINTOPOINT) tmp->type=i18n("Point to Point"); #ifndef _AIX else if ((flags & IFF_MULTICAST) == IFF_MULTICAST) tmp->type=i18n("Multicast"); #endif else if ((flags & IFF_LOOPBACK) == IFF_LOOPBACK) tmp->type=i18n("Loopback"); else tmp->type=i18n("Unknown"); tmp->addr=inet_ntoa(sinptr->sin_addr); ifcopy=*ifr; result=ioctl(sockfd,SIOCGIFNETMASK,&ifcopy); if (result==0) { sinptr = (struct sockaddr_in *) &ifcopy.ifr_addr; tmp->netmask=inet_ntoa(sinptr->sin_addr); } else tmp->netmask=i18n("Unknown"); nl->append(tmp); break; default: break; } } #else struct ifaddrs *ifap, *ifa; if (getifaddrs(&ifap) != 0) { return nl; } MyNIC *tmp=0; for (ifa = ifap; ifa; ifa = ifa->ifa_next) { switch (ifa->ifa_addr->sa_family) { case AF_INET6: case AF_INET: { tmp = new MyNIC; tmp->name = ifa->ifa_name; char buf[128]; bzero(buf, 128); getnameinfo(ifa->ifa_addr, ifa->ifa_addr->sa_len, buf, 127, 0, 0, NI_NUMERICHOST); tmp->addr = buf; if (ifa->ifa_netmask != NULL) { #ifdef Q_OS_FREEBSD struct sockaddr_in *sinptr = (struct sockaddr_in *)ifa->ifa_netmask; tmp->netmask=inet_ntoa(sinptr->sin_addr); #else bzero(buf, 128); getnameinfo(ifa->ifa_netmask, ifa->ifa_netmask->sa_len, buf, 127, 0, 0, NI_NUMERICHOST); tmp->netmask = buf; #endif } if (ifa->ifa_flags & IFF_UP) tmp->state=i18n("Up"); else tmp->state=i18n("Down"); tmp->type = flags_tos(ifa->ifa_flags); nl->append(tmp); break; } default: break; } } freeifaddrs(ifap); #endif return nl; } void suggestSettingsForAddress(const TQString& addrMask, LisaConfigInfo& lci) { TQString ip=addrMask.left(addrMask.find("/")); TQString mask=addrMask.mid(addrMask.find("/")+1); if (mask[mask.length()-1]==';') mask=mask.left(mask.length()-1); MyNIC tmpNic; KInetSocketAddress::stringToAddr(AF_INET, mask.latin1(), &tmpNic.netmask); KInetSocketAddress::stringToAddr(AF_INET, ip.latin1(), &tmpNic.addr); suggestSettingsForNic(&tmpNic,lci); } void suggestSettingsForNic(MyNIC* nic, LisaConfigInfo& lci) { lci.clear(); if (nic==0) return; TQString address = nic->addr; TQString netmask = nic->netmask; TQString addrMask(address+"/"+netmask+";"); struct in_addr tmpaddr; inet_aton(nic->netmask.latin1(), &tmpaddr); unsigned int tmp= ntohl(tmpaddr.s_addr); //if the host part is less than 20 bits simply take it //this might be a problem on 64 bit machines if (tmp>0xfffff000) { lci.pingAddresses=addrMask; lci.broadcastNetwork=addrMask; lci.allowedAddresses=addrMask; lci.secondWait=0; lci.secondScan=false; lci.firstWait=30; lci.maxPingsAtOnce=256; lci.updatePeriod=300; lci.useNmblookup=false; lci.unnamedHosts=false; } else { lci.pingAddresses=""; lci.broadcastNetwork=addrMask; lci.allowedAddresses=addrMask; lci.secondWait=0; lci.secondScan=false; lci.firstWait=30; lci.maxPingsAtOnce=256; lci.updatePeriod=300; lci.useNmblookup=true; lci.unnamedHosts=false; } } LisaConfigInfo::LisaConfigInfo() { clear(); } void LisaConfigInfo::clear() { pingAddresses=""; broadcastNetwork=""; allowedAddresses=""; secondWait=0; firstWait=0; secondScan=false; maxPingsAtOnce=256; updatePeriod=0; useNmblookup=false; unnamedHosts=false; } #if defined(HAVE_GETNAMEINFO) && defined(HAVE_GETIFADDRS) TQString flags_tos (unsigned int flags) { TQString tmp; if (flags & IFF_POINTOPOINT) { tmp += i18n("Point to Point"); } if (flags & IFF_BROADCAST) { if (tmp.length()) { tmp += TQString::fromLatin1(", "); } tmp += i18n("Broadcast"); } if (flags & IFF_MULTICAST) { if (tmp.length()) { tmp += TQString::fromLatin1(", "); } tmp += i18n("Multicast"); } if (flags & IFF_LOOPBACK) { if (tmp.length()) { tmp += TQString::fromLatin1(", "); } tmp += i18n("Loopback"); } return tmp; } #endif