You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdenetwork/lanbrowsing/kcmlisa/findnic.cpp

299 lines
7.2 KiB

/*
* findnic.cpp
*
* Copyright (c) 2001 Alexander Neundorf <neundorf@kde.org>
*
* 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 <config.h>
#ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#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 <net/if.h>
#ifdef USE_SOLARIS
#undef map
#endif
#include <sys/ioctl.h>
#ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
#undef HAVE_GETNAMEINFO
#undef HAVE_GETIFADDRS
#endif
#if defined(HAVE_GETNAMEINFO) && defined(HAVE_GETIFADDRS)
#include <ifaddrs.h>
#include <netdb.h>
#include <tqstring.h>
TQString flags_tos (unsigned int flags);
#endif
#include "findnic.h"
#include <tdelocale.h>
#include <ksockaddr.h>
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