Changeset 801
- Timestamp:
- Oct 20, 2010, 1:09:45 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/network/kernel/qnetworkinterface_os2.cpp
r783 r801 54 54 #include <sys/sockio.h> 55 55 #include <net/if.h> 56 56 57 57 58 #include <qplatformdefs.h> 58 59 59 60 QT_BEGIN_NAMESPACE 60 61 static QHostAddress addressFromSockaddr(sockaddr *sa)62 {63 QHostAddress address;64 if (!sa)65 return address;66 67 if (sa->sa_family == AF_INET)68 address.setAddress(htonl(((sockaddr_in *)sa)->sin_addr.s_addr));69 return address;70 71 }72 61 73 62 static QNetworkInterface::InterfaceFlags convertFlags(uint rawFlags) … … 78 67 flags |= (rawFlags & IFF_BROADCAST) ? QNetworkInterface::CanBroadcast : QNetworkInterface::InterfaceFlag(0); 79 68 flags |= (rawFlags & IFF_LOOPBACK) ? QNetworkInterface::IsLoopBack : QNetworkInterface::InterfaceFlag(0); 80 #ifdef IFF_POINTOPOINT //cygwin doesn't define IFF_POINTOPOINT81 69 flags |= (rawFlags & IFF_POINTOPOINT) ? QNetworkInterface::IsPointToPoint : QNetworkInterface::InterfaceFlag(0); 82 #endif83 84 #ifdef IFF_MULTICAST85 70 flags |= (rawFlags & IFF_MULTICAST) ? QNetworkInterface::CanMulticast : QNetworkInterface::InterfaceFlag(0); 86 #endif87 71 return flags; 88 }89 90 static const int STORAGEBUFFER_GROWTH = 256;91 92 static QSet<QByteArray> interfaceNames(int socket)93 {94 QSet<QByteArray> result;95 QByteArray storageBuffer;96 struct ifconf interfaceList;97 98 forever {99 // grow the storage buffer100 storageBuffer.resize(storageBuffer.size() + STORAGEBUFFER_GROWTH);101 interfaceList.ifc_buf = storageBuffer.data();102 interfaceList.ifc_len = storageBuffer.size();103 104 // get the interface list105 if (::ioctl(socket, SIOCGIFCONF, &interfaceList) >= 0) {106 if (int(interfaceList.ifc_len + sizeof(ifreq) + 64) < storageBuffer.size()) {107 // if the buffer was big enough, break108 storageBuffer.resize(interfaceList.ifc_len);109 break;110 }111 } else {112 // internal error113 return result;114 }115 if (storageBuffer.size() > 100000) {116 // out of space117 return result;118 }119 }120 121 int interfaceCount = interfaceList.ifc_len / sizeof(ifreq);122 for (int i = 0; i < interfaceCount; ++i) {123 // for some reason, this ioctl returns garbage entries (names starting124 // with characters like 0x00, 0x06, 0x14 and even 0x22). Filter those125 // out by requiring the first character to be a latin letter.126 if (!isalpha(interfaceList.ifc_req[i].ifr_name[0]))127 continue;128 result << QByteArray(interfaceList.ifc_req[i].ifr_name);129 }130 131 return result;132 }133 134 static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfacePrivate *> &interfaces,135 struct ifreq &req)136 {137 QNetworkInterfacePrivate *iface = 0;138 int ifindex = 0;139 140 // Search by name141 QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin();142 for ( ; if_it != interfaces.end(); ++if_it)143 if ((*if_it)->name == QLatin1String(req.ifr_name)) {144 // existing interface145 iface = *if_it;146 break;147 }148 149 if (!iface) {150 // new interface, create data:151 iface = new QNetworkInterfacePrivate;152 iface->index = ifindex;153 interfaces << iface;154 155 #ifdef SIOCGIFNAME156 // Get the canonical name157 QByteArray oldName = req.ifr_name;158 if (::ioctl(socket, SIOCGIFNAME, &req) >= 0) {159 iface->name = QString::fromLatin1(req.ifr_name);160 161 // reset the name:162 memcpy(req.ifr_name, oldName, qMin<int>(oldName.length() + 1, sizeof(req.ifr_name) - 1));163 } else164 #endif165 {166 // use this name anyways167 iface->name = QString::fromLatin1(req.ifr_name);168 }169 170 // Get interface flags171 if (::ioctl(socket, SIOCGIFFLAGS, &req) >= 0) {172 iface->flags = convertFlags(req.ifr_flags);173 }174 175 #ifdef SIOCGIFHWADDR176 // Get the HW address177 if (::ioctl(socket, SIOCGIFHWADDR, &req) >= 0) {178 uchar *addr = (uchar *)&req.ifr_addr;179 iface->hardwareAddress = iface->makeHwAddress(6, addr);180 }181 #endif182 }183 184 return iface;185 72 } 186 73 187 74 static QList<QNetworkInterfacePrivate *> interfaceListing() 188 75 { 76 77 78 79 80 189 81 QList<QNetworkInterfacePrivate *> interfaces; 190 82 … … 193 85 return interfaces; // error 194 86 195 QSet<QByteArray> names = interfaceNames(socket); 196 QSet<QByteArray>::ConstIterator it = names.constBegin(); 197 for ( ; it != names.constEnd(); ++it) { 87 // rumors say that the address buffer should be at least 65536 bytes long 88 char addrBuf[65536]; 89 short naddrs; 90 statatreq *addrs; 91 92 ifmib ifmibget; 93 // zero the interface table because garbage will be returned in interface 94 // names otherwise 95 memset(&ifmibget,0, sizeof(ifmib)); 96 97 int rc; 98 99 // get available interfaces 100 rc = ::os2_ioctl(socket, SIOSTATIF, (char*)&ifmibget, sizeof(ifmib)); 101 if (rc == -1) { 102 ::close(socket); 103 return interfaces; 104 } 105 106 // get IP addresses 107 rc = ::os2_ioctl(socket, SIOSTATAT, addrBuf, sizeof(addrBuf)); 108 if (rc == -1) { 109 ::close(socket); 110 return interfaces; 111 } 112 naddrs = *(short *)addrBuf; 113 addrs = (statatreq *)(addrBuf + sizeof(unsigned short)); 114 115 // loop over interfaces 116 int idx = 0; 117 for (int i = 0; i < IFMIB_ENTRIES && idx < ifmibget.ifNumber; ++i) { 118 // skip empty interface entries 119 if (ifmibget.iftable[i].iftType == 0) 120 continue; 121 122 QNetworkInterfacePrivate *iface = new QNetworkInterfacePrivate; 123 iface->index = ifmibget.iftable[i].iftIndex; 124 125 // Derive the interface name. Not perfect, but there seems to be no 126 // other documented way (taken from Odin sources) 127 if (iface->index >= 0 && iface->index < 9) {// lanX 128 iface->name = QString(QLatin1String("lan%1")).arg(iface->index); 129 } else if (strstr(ifmibget.iftable[i].iftDescr, "back")) { // loopback 130 iface->name = QLatin1String("lo"); 131 } 132 else if (strstr(ifmibget.iftable[i].iftDescr, "ace ppp")) {// pppX 133 iface->name = QLatin1String(strstr(ifmibget.iftable[i].iftDescr, "ppp")); 134 } else if (strstr(ifmibget.iftable[i].iftDescr,"ace sl")) { // slX 135 iface->name = QLatin1String(strstr(ifmibget.iftable[i].iftDescr, "sl")); 136 } else if (strstr(ifmibget.iftable[i].iftDescr,"ace dod")) { // dodX 137 iface->name = QLatin1String(strstr(ifmibget.iftable[i].iftDescr, "dod")); 138 } else { // something else... 139 iface->name = QString(QLatin1String("unk%1")).arg(iface->index); 140 } 141 142 iface->friendlyName = QString::fromLocal8Bit(ifmibget.iftable[i].iftDescr); 143 iface->hardwareAddress = 144 iface->makeHwAddress(sizeof(ifmibget.iftable[i].iftPhysAddr), 145 (uchar *)&ifmibget.iftable[i].iftPhysAddr[0]); 146 147 // get interface flags 198 148 ifreq req; 199 149 memset(&req, 0, sizeof(ifreq)); 200 memcpy(req.ifr_name, *it, qMin<int>(it->length() + 1, sizeof(req.ifr_name) - 1)); 150 strncpy(req.ifr_name, iface->name.toLatin1(), sizeof(req.ifr_name)); 151 if (::ioctl(socket, SIOCGIFFLAGS, &req) != -1) { 152 iface->flags = convertFlags(req.ifr_flags); 153 } 201 154 202 QNetworkInterfacePrivate *iface = findInterface(socket, interfaces, req);203 204 // Get the interface broadcast address205 QNetworkAddressEntry entry;206 if (iface->flags & QNetworkInterface::CanBroadcast) {207 if (::ioctl(socket, SIOCGIFBRDADDR, &req) >= 0) {208 sockaddr *sa = &req.ifr_addr;209 if (sa->sa_family == AF_INET)210 entry.setBroadcast(addressFromSockaddr(sa));155 156 for (int j = 0; j < naddrs; ++j) { 157 158 QNetworkAddressEntry entry; 159 160 161 ; 162 163 ; 211 164 } 212 165 } 213 166 214 // Get the interface netmask 215 if (::ioctl(socket, SIOCGIFNETMASK, &req) >= 0) { 216 sockaddr *sa = &req.ifr_addr; 217 entry.setNetmask(addressFromSockaddr(sa)); 218 } 219 220 // Get the address of the interface 221 if (::ioctl(socket, SIOCGIFADDR, &req) >= 0) { 222 sockaddr *sa = &req.ifr_addr; 223 entry.setIp(addressFromSockaddr(sa)); 224 } 225 226 iface->addressEntries << entry; 167 // store the interface 168 interfaces << iface; 227 169 } 228 170
Note:
See TracChangeset
for help on using the changeset viewer.