network.cc
1 /* 2 * network.cc 3 * 4 * This scan uses the same IOCTLs as ethtool, ifconfig or mii-diag to report 5 * information about network interfaces like: 6 * - medium type (ethernet, token ring, PPP, etc.) 7 * - hardware address (MAC address) 8 * - link status (link detected, in error, etc.) 9 * - speed (10Mbits, 100Mbits, etc.) 10 * - IP addressing 11 * 12 * As network interfaces can be plugged on PCI, PCMCIA, ISA, USB, etc. this 13 * scan should be executed after all bus-related scans. 14 * 15 */ 16 17 #include "version.h" 18 #include "config.h" 19 #include "network.h" 20 #include "osutils.h" 21 #include "sysfs.h" 22 #include "options.h" 23 #include "heuristics.h" 24 #include <sys/socket.h> 25 #include <sys/ioctl.h> 26 #include <netinet/in.h> 27 #include <arpa/inet.h> 28 #include <net/if_arp.h> 29 #include <linux/sockios.h> 30 #include <net/if.h> 31 #include <fcntl.h> 32 #include <unistd.h> 33 #include <stdio.h> 34 #include <stdint.h> 35 #include <string.h> 36 #include <string> 37 #include <sys/types.h> 38 using namespace std; 39 40 __ID("@(#) $Id$"); 41 42 #ifndef ARPHRD_IEEE1394 43 #define ARPHRD_IEEE1394 24 44 #endif 45 #ifndef ARPHRD_SIT 46 #define ARPHRD_SIT 776 47 #endif 48 49 #ifndef SIOCETHTOOL 50 #define SIOCETHTOOL 0x8946 51 #endif 52 typedef unsigned long long u64; 53 typedef uint32_t u32; 54 typedef uint16_t u16; 55 typedef uint8_t u8; 56 typedef int8_t s8; 57 58 struct ethtool_cmd 59 { 60 u32 cmd; 61 u32 supported; /* Features this interface supports */ 62 u32 advertising; /* Features this interface advertises */ 63 u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ 64 u8 duplex; /* Duplex, half or full */ 65 u8 port; /* Which connector port */ 66 u8 phy_address; 67 u8 transceiver; /* Which tranceiver to use */ 68 u8 autoneg; /* Enable or disable autonegotiation */ 69 u32 maxtxpkt; /* Tx pkts before generating tx int */ 70 u32 maxrxpkt; /* Rx pkts before generating rx int */ 71 u32 reserved[4]; 72 }; 73 74 #define MAX_LINK_MODE_MASK_SIZE 64 75 struct ethtool_link_settings 76 { 77 u32 cmd; 78 u32 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ 79 u8 duplex; /* Duplex, half or full */ 80 u8 port; /* Which connector port */ 81 u8 phy_address; 82 u8 autoneg; /* Enable or disable autonegotiation */ 83 u8 mdio_support; 84 u8 eth_tp_mdix; 85 u8 eth_tp_mdix_ctrl; 86 s8 link_mode_masks_nwords; 87 u8 transceiver; /* Which tranceiver to use */ 88 u8 master_slave_cfg; 89 u8 master_slave_state; 90 u8 reserved1[1]; 91 u32 reserved[7]; 92 u32 link_mode_masks[3 * MAX_LINK_MODE_MASK_SIZE]; /* Link mode mask fields for modes: 93 supported, advertised, peer advertised. */ 94 }; 95 96 /* Recognized module eeprom standards. */ 97 #define ETH_MODULE_SFF_8079 0x1 98 #define ETH_MODULE_SFF_8472 0x2 99 #define ETH_MODULE_SFF_8636 0x3 100 #define ETH_MODULE_SFF_8436 0x4 101 102 struct ethtool_modinfo { 103 u32 cmd; 104 u32 type; /* SFF standard used in module */ 105 u32 eeprom_len; /* Length of module eeprom */ 106 u32 reserved[8]; 107 }; 108 109 /* Known id types. */ 110 #define SFF_8024_ID_SOLDERED 0x2 111 #define SFF_8024_ID_SFP 0x3 112 #define SFF_8024_EXT_ID_DEFINED_BY_2WIRE_ID 0x4 113 114 /* Common connector types. */ 115 #define SFF_8024_CONNECTOR_SC 0x1 116 #define SFF_8024_CONNECTOR_LC 0x7 117 #define SFF_8024_CONNECTOR_OPTICAL_PIGTAIL 0xb 118 #define SFF_8024_CONNECTOR_COPPER_PIGTAIL 0x21 119 #define SFF_8024_CONNECTOR_RJ45 0x22 120 #define SFF_8024_CONNECTOR_NON_SEPARABLE 0x23 121 122 #define MAX_EEPROM_SIZE 256 123 struct ethtool_eeprom { 124 u32 cmd; 125 u32 magic; /* Only used for eeprom writes */ 126 u32 offset; /* Read or write offset */ 127 u32 len; /* Length of read/write */ 128 u8 data[MAX_EEPROM_SIZE]; /* Buffer */ 129 }; 130 131 #ifndef IFNAMSIZ 132 #define IFNAMSIZ 32 133 #endif 134 #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ 135 /* SIOCGIWNAME is used to verify the presence of Wireless Extensions. 136 * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... */ 137 138 #define ETHTOOL_BUSINFO_LEN 32 139 /* these strings are set to whatever the driver author decides... */ 140 struct ethtool_drvinfo 141 { 142 u32 cmd; 143 char driver[32]; /* driver short name, "tulip", "eepro100" */ 144 char version[32]; /* driver version string */ 145 char fw_version[32]; /* firmware version string, if applicable */ 146 char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ 147 /* 148 * For PCI devices, use pci_dev->slot_name. 149 */ 150 char reserved1[32]; 151 char reserved2[16]; 152 u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */ 153 u32 testinfo_len; 154 u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ 155 u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ 156 }; 157 158 /* for passing single values */ 159 struct ethtool_value 160 { 161 u32 cmd; 162 u32 data; 163 }; 164 165 /* CMDs currently supported */ 166 #define ETHTOOL_GSET 0x00000001 /* Get settings. */ 167 #define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ 168 #define ETHTOOL_GLINK 0x0000000a /* Get link status (ethtool_value) */ 169 #define ETHTOOL_GMODULEINFO 0x00000042 /* Get plug-in module information */ 170 #define ETHTOOL_GMODULEEEPROM 0x00000043 /* Get plug-in module eeprom */ 171 #define ETHTOOL_GLINKSETTINGS 0x0000004c /* Get link mode settings. */ 172 173 /* Indicates what features are supported by the interface. */ 174 #define SUPPORTED_10baseT_Half (1 << 0) 175 #define SUPPORTED_10baseT_Full (1 << 1) 176 #define SUPPORTED_100baseT_Half (1 << 2) 177 #define SUPPORTED_100baseT_Full (1 << 3) 178 #define SUPPORTED_1000baseT_Half (1 << 4) 179 #define SUPPORTED_1000baseT_Full (1 << 5) 180 #define SUPPORTED_Autoneg (1 << 6) 181 #define SUPPORTED_TP (1 << 7) 182 #define SUPPORTED_AUI (1 << 8) 183 #define SUPPORTED_MII (1 << 9) 184 #define SUPPORTED_FIBRE (1 << 10) 185 #define SUPPORTED_BNC (1 << 11) 186 #define SUPPORTED_10000baseT_Full (1 << 12) 187 #define SUPPORTED_2500baseX_Full (1 << 15) 188 #define SUPPORTED_1000baseKX_Full (1 << 17) 189 #define SUPPORTED_10000baseKX4_Full (1 << 18) 190 #define SUPPORTED_10000baseKR_Full (1 << 19) 191 #define SUPPORTED_10000baseR_FEC (1 << 20) 192 #define SUPPORTED_20000baseMLD2_Full (1 << 21) 193 #define SUPPORTED_20000baseKR2_Full (1 << 22) 194 #define SUPPORTED_40000baseKR4_Full (1 << 23) 195 #define SUPPORTED_40000baseCR4_Full (1 << 24) 196 #define SUPPORTED_40000baseSR4_Full (1 << 25) 197 #define SUPPORTED_40000baseLR4_Full (1 << 26) 198 #define SUPPORTED_56000baseKR4_Full (1 << 27) 199 #define SUPPORTED_56000baseCR4_Full (1 << 28) 200 #define SUPPORTED_56000baseSR4_Full (1 << 29) 201 #define SUPPORTED_56000baseLR4_Full (1 << 30) 202 #define SUPPORTED_25000baseCR_Full (1 << 31) 203 #define SUPPORTED_25000baseKR_Full (1 << 32) 204 #define SUPPORTED_25000baseSR_Full (1 << 33) 205 #define SUPPORTED_50000baseCR2_Full (1 << 34) 206 #define SUPPORTED_50000baseKR2_Full (1 << 35) 207 #define SUPPORTED_100000baseKR4_Full (1 << 36) 208 #define SUPPORTED_100000baseSR4_Full (1 << 37) 209 #define SUPPORTED_100000baseCR4_Full (1 << 38) 210 #define SUPPORTED_100000baseLR4_ER4_Full (1 << 39) 211 #define SUPPORTED_50000baseSR2_Full (1 << 40) 212 #define SUPPORTED_1000baseX_Full (1 << 41) 213 #define SUPPORTED_10000baseCR_Full (1 << 42) 214 #define SUPPORTED_10000baseSR_Full (1 << 43) 215 #define SUPPORTED_10000baseLR_Full (1 << 44) 216 #define SUPPORTED_10000baseLRM_Full (1 << 45) 217 #define SUPPORTED_10000baseER_Full (1 << 46) 218 #define SUPPORTED_2500baseT_Full (1 << 47) 219 #define SUPPORTED_5000baseT_Full (1 << 48) 220 221 /* Indicates what features are supported by the interface, 222 * in the second word of the extended bitmap. */ 223 #define SUPPORTED2_25000baseKR_Full (1 << 0) 224 #define SUPPORTED2_25000baseSR_Full (1 << 1) 225 #define SUPPORTED2_100000baseKR4_Full (1 << 4) 226 #define SUPPORTED2_100000baseSR4_Full (1 << 5) 227 #define SUPPORTED2_100000baseCR4_Full (1 << 6) 228 #define SUPPORTED2_100000baseLR4_ER4_Full (1 << 7) 229 #define SUPPORTED2_1000baseX_Full (1 << 9) 230 #define SUPPORTED2_10000baseCR_Full (1 << 10) 231 #define SUPPORTED2_10000baseSR_Full (1 << 11) 232 #define SUPPORTED2_10000baseLR_Full (1 << 12) 233 #define SUPPORTED2_10000baseLRM_Full (1 << 13) 234 #define SUPPORTED2_10000baseER_Full (1 << 14) 235 #define SUPPORTED2_2500baseT_Full (1 << 15) 236 #define SUPPORTED2_5000baseT_Full (1 << 16) 237 238 /* The forced speed, 10Mb, 100Mb, gigabit, 2.5GbE, 5GbE, 10GbE and up. */ 239 #define SPEED_10 10 240 #define SPEED_100 100 241 #define SPEED_1000 1000 242 #define SPEED_2500 2500 243 #define SPEED_5000 5000 244 #define SPEED_10000 10000 245 #define SPEED_25000 25000 246 #define SPEED_40000 40000 247 #define SPEED_100000 100000 248 249 /* Duplex, half or full. */ 250 #define DUPLEX_HALF 0x00 251 #define DUPLEX_FULL 0x01 252 253 /* Which connector port. */ 254 #define PORT_TP 0x00 255 #define PORT_AUI 0x01 256 #define PORT_MII 0x02 257 #define PORT_FIBRE 0x03 258 #define PORT_BNC 0x04 259 260 /* Which tranceiver to use. */ 261 #define XCVR_INTERNAL 0x00 262 #define XCVR_EXTERNAL 0x01 263 #define XCVR_DUMMY1 0x02 264 #define XCVR_DUMMY2 0x03 265 #define XCVR_DUMMY3 0x04 266 267 #define AUTONEG_DISABLE 0x00 268 #define AUTONEG_ENABLE 0x01 269 270 bool load_interfaces(vector < string > &interfaces) 271 { 272 vector < string > procnetdev; 273 274 interfaces.clear(); 275 if (!loadfile("/proc/net/dev", procnetdev)) 276 return false; 277 278 if (procnetdev.size() <= 2) 279 return false; 280 281 // get rid of header (2 lines) 282 procnetdev.erase(procnetdev.begin()); 283 procnetdev.erase(procnetdev.begin()); 284 285 for (unsigned int i = 0; i < procnetdev.size(); i++) 286 { 287 // extract interfaces names 288 size_t pos = procnetdev[i].find(':'); 289 290 if (pos != string::npos) 291 interfaces.push_back(hw::strip(procnetdev[i].substr(0, pos))); 292 } 293 294 return true; 295 } 296 297 static int maclen(unsigned family = ARPHRD_ETHER) 298 { 299 switch(family) 300 { 301 case ARPHRD_INFINIBAND: 302 return 20; 303 case ARPHRD_ETHER: 304 return 6; 305 default: 306 return 14; 307 } 308 } 309 310 static string getmac(const unsigned char *mac, unsigned family = ARPHRD_ETHER) 311 { 312 char buff[5]; 313 string result = ""; 314 bool valid = false; 315 316 for (int i = 0; i < maclen(family); i++) 317 { 318 snprintf(buff, sizeof(buff), "%02x", mac[i]); 319 320 valid |= (mac[i] != 0); 321 322 if (i == 0) 323 result = string(buff); 324 else 325 result += ":" + string(buff); 326 } 327 328 if (valid) 329 return result; 330 else 331 return ""; 332 } 333 334 335 static const char *hwname(int t) 336 { 337 switch (t) 338 { 339 case ARPHRD_ETHER: 340 return _("Ethernet"); 341 case ARPHRD_SLIP: 342 return _("SLIP"); 343 case ARPHRD_LOOPBACK: 344 return _("loopback"); 345 case ARPHRD_FDDI: 346 return _("FDDI"); 347 case ARPHRD_IEEE1394: 348 return _("IEEE1394"); 349 case ARPHRD_IRDA: 350 return _("IRDA"); 351 case ARPHRD_PPP: 352 return _("PPP"); 353 case ARPHRD_X25: 354 return _("X25"); 355 case ARPHRD_TUNNEL: 356 return _("IPtunnel"); 357 case ARPHRD_DLCI: 358 return _("Framerelay.DLCI"); 359 case ARPHRD_FRAD: 360 return _("Framerelay.AD"); 361 case ARPHRD_TUNNEL6: 362 return _("IP6tunnel"); 363 case ARPHRD_SIT: 364 return _("IP6inIP4"); 365 default: 366 return ""; 367 } 368 } 369 370 371 static string print_ip(struct sockaddr_in *in) 372 { 373 return string(inet_ntoa(in->sin_addr)); 374 } 375 376 377 static void scan_ip(hwNode & interface) 378 { 379 int fd = socket(AF_INET, SOCK_DGRAM, 0); 380 381 if (fd >= 0) 382 { 383 struct ifreq ifr; 384 385 // get IP address 386 memset(&ifr, 0, sizeof(ifr)); 387 strcpy(ifr.ifr_name, interface.getLogicalName().c_str()); 388 ifr.ifr_addr.sa_family = AF_INET; 389 if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) 390 { 391 // IP address is in ifr.ifr_addr 392 interface.setConfig("ip", ::enabled("output:sanitize")?REMOVED:print_ip((sockaddr_in *) (&ifr.ifr_addr))); 393 strcpy(ifr.ifr_name, interface.getLogicalName().c_str()); 394 if ((interface.getConfig("point-to-point") == "yes") 395 && (ioctl(fd, SIOCGIFDSTADDR, &ifr) == 0)) 396 { 397 // remote PPP address is in ifr.ifr_dstaddr 398 interface.setConfig("remoteip", 399 print_ip((sockaddr_in *) & ifr.ifr_dstaddr)); 400 } 401 } 402 403 close(fd); 404 } 405 } 406 407 408 static bool isVirtual(const string & MAC) 409 { 410 if (MAC.length() < 8) 411 return false; 412 413 string manufacturer = uppercase(MAC.substr(0, 8)); 414 415 if ((manufacturer == "00:05:69") || 416 (manufacturer == "00:0C:29") || (manufacturer == "00:50:56")) 417 return true; // VMware 418 if (manufacturer == "00:1C:42") 419 return true; // Parallels 420 if (manufacturer == "0A:00:27") 421 return true; // VirtualBox 422 423 return false; 424 } 425 426 427 // Get data for connected transceiver module. 428 static void scan_module(hwNode & interface, int fd) 429 { 430 struct ifreq ifr; 431 struct ethtool_modinfo emodinfo; 432 struct ethtool_eeprom eeeprom; 433 434 emodinfo.cmd = ETHTOOL_GMODULEINFO; 435 memset(&ifr, 0, sizeof(ifr)); 436 strcpy(ifr.ifr_name, interface.getLogicalName().c_str()); 437 ifr.ifr_data = (caddr_t) &emodinfo; 438 // Skip interface if module info not supported. 439 if (ioctl(fd, SIOCETHTOOL, &ifr) != 0) 440 return; 441 442 eeeprom.cmd = ETHTOOL_GMODULEEEPROM; 443 eeeprom.offset = 0; 444 eeeprom.len = emodinfo.eeprom_len; 445 if (eeeprom.len > MAX_EEPROM_SIZE) 446 eeeprom.len = MAX_EEPROM_SIZE; 447 memset(&ifr, 0, sizeof(ifr)); 448 strcpy(ifr.ifr_name, interface.getLogicalName().c_str()); 449 ifr.ifr_data = (caddr_t) &eeeprom; 450 if (ioctl(fd, SIOCETHTOOL, &ifr) != 0) 451 return; 452 453 switch (emodinfo.type) 454 { 455 /* SFF 8472 eeprom layout starts with same data as SFF 8079. */ 456 case ETH_MODULE_SFF_8079: 457 case ETH_MODULE_SFF_8472: 458 if ((eeeprom.data[0] == SFF_8024_ID_SOLDERED || eeeprom.data[0] == SFF_8024_ID_SFP) && 459 eeeprom.data[1] == SFF_8024_EXT_ID_DEFINED_BY_2WIRE_ID) 460 { 461 char buffer[32]; 462 /* Get part number (padded with space). String is stripped inside setConfig. */ 463 interface.setConfig("module", string((const char*)&eeeprom.data[40], 16)); 464 int wavelength = eeeprom.data[60] << 8 | eeeprom.data[61]; 465 /* Skip wavelength for SFP+ cables, they use byte 60 for other data. */ 466 if ((eeeprom.data[8] & 0x0C) == 0 && wavelength > 0) 467 { 468 snprintf(buffer, sizeof(buffer), "%dnm", wavelength); 469 interface.setConfig("wavelength", buffer); 470 } 471 int max_length = 0; 472 int length; 473 length = eeeprom.data[14] * 1000; /* SMF, km */ 474 if (length > max_length) max_length = length; 475 length = eeeprom.data[15] * 100; /* SMF, meter */ 476 if (length > max_length) max_length = length; 477 length = eeeprom.data[16] * 10; /* 50um (OM2), meter */ 478 if (length > max_length) max_length = length; 479 length = eeeprom.data[17] * 10; /* 62.5um (OM1), meter */ 480 if (length > max_length) max_length = length; 481 length = eeeprom.data[18]; /* Copper, meter */ 482 if (length > max_length) max_length = length; 483 length = eeeprom.data[19] * 10; /* OM3, meter */ 484 if (length > max_length) max_length = length; 485 if (max_length > 0) 486 { 487 snprintf(buffer, sizeof(buffer), "%dm", max_length); 488 interface.setConfig("maxlength", buffer); 489 } 490 switch (eeeprom.data[2]) 491 { 492 case SFF_8024_CONNECTOR_SC: 493 interface.setConfig("connector", "SC"); 494 break; 495 case SFF_8024_CONNECTOR_LC: 496 interface.setConfig("connector", "LC"); 497 break; 498 case SFF_8024_CONNECTOR_OPTICAL_PIGTAIL: 499 interface.setConfig("connector", "optical pigtail"); 500 break; 501 case SFF_8024_CONNECTOR_COPPER_PIGTAIL: 502 interface.setConfig("connector", "copper pigtail"); 503 break; 504 case SFF_8024_CONNECTOR_RJ45: 505 interface.setConfig("connector", "RJ45"); 506 break; 507 case SFF_8024_CONNECTOR_NON_SEPARABLE: 508 interface.setConfig("connector", "non separable"); 509 break; 510 } 511 } 512 break; 513 } 514 } 515 516 517 static void updateCapabilities(hwNode & interface, u32 supported, u32 supported2, u32 speed, u8 duplex, u8 port, u8 autoneg) 518 { 519 if(supported & SUPPORTED_TP) 520 interface.addCapability("tp", _("twisted pair")); 521 if(supported & SUPPORTED_AUI) 522 interface.addCapability("aui", _("AUI")); 523 if(supported & SUPPORTED_BNC) 524 interface.addCapability("bnc", _("BNC")); 525 if(supported & SUPPORTED_MII) 526 interface.addCapability("mii", _("Media Independent Interface")); 527 if(supported & SUPPORTED_FIBRE) 528 interface.addCapability("fibre",_( "optical fibre")); 529 if(supported & SUPPORTED_10baseT_Half) 530 { 531 interface.addCapability("10bt", _("10Mbit/s")); 532 interface.setCapacity(10000000ULL); 533 } 534 if(supported & SUPPORTED_10baseT_Full) 535 { 536 interface.addCapability("10bt-fd", _("10Mbit/s (full duplex)")); 537 interface.setCapacity(10000000ULL); 538 } 539 if(supported & SUPPORTED_100baseT_Half) 540 { 541 interface.addCapability("100bt", _("100Mbit/s")); 542 interface.setCapacity(100000000ULL); 543 } 544 if(supported & SUPPORTED_100baseT_Full) 545 { 546 interface.addCapability("100bt-fd", _("100Mbit/s (full duplex)")); 547 interface.setCapacity(100000000ULL); 548 } 549 if(supported & SUPPORTED_1000baseT_Half) 550 { 551 interface.addCapability("1000bt", "1Gbit/s"); 552 interface.setCapacity(1000000000ULL); 553 } 554 if(supported & SUPPORTED_1000baseT_Full) 555 { 556 interface.addCapability("1000bt-fd", _("1Gbit/s (full duplex)")); 557 interface.setCapacity(1000000000ULL); 558 } 559 if((supported & SUPPORTED_1000baseKX_Full) || (supported2 & SUPPORTED2_1000baseX_Full)) 560 { 561 interface.addCapability("1000bx-fd", _("1Gbit/s (full duplex)")); 562 interface.setCapacity(1000000000ULL); 563 } 564 if(supported & SUPPORTED_2500baseX_Full) 565 { 566 interface.addCapability("2500bx-fd", _("2.5Gbit/s (full duplex)")); 567 interface.setCapacity(2500000000ULL); 568 } 569 if(supported & SUPPORTED_2500baseT_Full) 570 { 571 interface.addCapability("2500bt-fd", _("2500Mbit/s (full duplex)")); 572 interface.setCapacity(2500000000ULL); 573 } 574 if(supported & SUPPORTED_5000baseT_Full) 575 { 576 interface.addCapability("5000bt-fd", _("5Gbit/s (full duplex)")); 577 interface.setCapacity(5000000000ULL); 578 } 579 if(supported2 & SUPPORTED2_2500baseT_Full) 580 { 581 interface.addCapability("2500bt-fd", _("2.5Gbit/s (full duplex)")); 582 interface.setCapacity(2500000000ULL); 583 } 584 if(supported2 & SUPPORTED2_5000baseT_Full) 585 { 586 interface.addCapability("5000bt-fd", _("5Gbit/s (full duplex)")); 587 interface.setCapacity(5000000000ULL); 588 } 589 if(supported & SUPPORTED_10000baseT_Full) 590 { 591 interface.addCapability("10000bt-fd", _("10Gbit/s (full duplex)")); 592 interface.setCapacity(10000000000ULL); 593 } 594 if((supported & (SUPPORTED_10000baseKX4_Full | SUPPORTED_10000baseKR_Full)) || 595 (supported2 & (SUPPORTED2_10000baseCR_Full | SUPPORTED2_10000baseSR_Full | SUPPORTED2_10000baseLR_Full | 596 SUPPORTED2_10000baseLRM_Full | SUPPORTED2_10000baseER_Full))) 597 { 598 interface.addCapability("10000bx-fd", _("10Gbit/s (full duplex)")); 599 interface.setCapacity(10000000000ULL); 600 } 601 if(supported & SUPPORTED_10000baseR_FEC) 602 { 603 interface.addCapability("10000bt-fd", _("10Gbit/s (full duplex)")); 604 interface.setCapacity(10000000000ULL); 605 } 606 if(supported & SUPPORTED_10000baseCR_Full) 607 { 608 interface.addCapability("10000bt-fd", _("10Gbit/s (full duplex)")); 609 interface.setCapacity(10000000000ULL); 610 } 611 if(supported & SUPPORTED_10000baseSR_Full) 612 { 613 interface.addCapability("10000bt-fd", _("10Gbit/s (full duplex)")); 614 interface.setCapacity(10000000000ULL); 615 } 616 if(supported & SUPPORTED_10000baseLR_Full) 617 { 618 interface.addCapability("10000bt-fd", _("10Gbit/s (full duplex)")); 619 interface.setCapacity(10000000000ULL); 620 } 621 if(supported & SUPPORTED_10000baseLRM_Full) 622 { 623 interface.addCapability("10000bt-fd", _("10Gbit/s (full duplex)")); 624 interface.setCapacity(10000000000ULL); 625 } 626 if(supported & SUPPORTED_10000baseER_Full) 627 { 628 interface.addCapability("10000bt-fd", _("10Gbit/s (full duplex)")); 629 interface.setCapacity(10000000000ULL); 630 } 631 if(supported & SUPPORTED_20000baseMLD2_Full) 632 { 633 interface.addCapability("20000bt-fd", _("20Gbit/s (full duplex)")); 634 interface.setCapacity(20000000000ULL); 635 } 636 if(supported & SUPPORTED_20000baseKR2_Full) 637 { 638 interface.addCapability("20000bt-fd", _("20Gbit/s (full duplex)")); 639 interface.setCapacity(20000000000ULL); 640 } 641 if((supported & SUPPORTED_25000baseCR_Full) || 642 (supported2 & (SUPPORTED2_25000baseKR_Full | SUPPORTED2_25000baseSR_Full))) 643 { 644 interface.addCapability("25000bx-fd", _("25Gbit/s (full duplex)")); 645 interface.setCapacity(25000000000ULL); 646 } 647 if(supported & SUPPORTED_25000baseKR_Full) 648 { 649 interface.addCapability("25000bt-fd", _("25Gbit/s (full duplex)")); 650 interface.setCapacity(25000000000ULL); 651 } 652 if(supported & SUPPORTED_25000baseSR_Full) 653 { 654 interface.addCapability("25000bt-fd", _("25Gbit/s (full duplex)")); 655 interface.setCapacity(25000000000ULL); 656 } 657 if(supported & (SUPPORTED_40000baseKR4_Full | SUPPORTED_40000baseCR4_Full | 658 SUPPORTED_40000baseSR4_Full | SUPPORTED_40000baseLR4_Full)) 659 { 660 interface.addCapability("40000bx-fd", _("40Gbit/s (full duplex)")); 661 interface.setCapacity(40000000000ULL); 662 } 663 if(supported & (SUPPORTED_50000baseCR2_Full | SUPPORTED_50000baseKR2_Full | 664 SUPPORTED_50000baseSR2_Full)) 665 { 666 interface.addCapability("50000bt-fd", _("50Gbit/s (full duplex)")); 667 interface.setCapacity(50000000000ULL); 668 } 669 if(supported & (SUPPORTED_56000baseCR4_Full | SUPPORTED_56000baseSR4_Full | 670 SUPPORTED_56000baseLR4_Full | SUPPORTED_56000baseKR4_Full)) 671 { 672 interface.addCapability("56000bt-fd", _("56Gbit/s (full duplex)")); 673 interface.setCapacity(56000000000ULL); 674 } 675 if(supported2 & (SUPPORTED2_100000baseKR4_Full | SUPPORTED2_100000baseSR4_Full | 676 SUPPORTED2_100000baseCR4_Full | SUPPORTED2_100000baseLR4_ER4_Full)) 677 { 678 interface.addCapability("100000bx-fd", _("100Gbit/s (full duplex)")); 679 interface.setCapacity(100000000000ULL); 680 } 681 if(supported & SUPPORTED_Autoneg) 682 interface.addCapability("autonegotiation", _("Auto-negotiation")); 683 684 switch(speed) 685 { 686 case SPEED_10: 687 interface.setConfig("speed", "10Mbit/s"); 688 interface.setSize(10000000ULL); 689 break; 690 case SPEED_100: 691 interface.setConfig("speed", "100Mbit/s"); 692 interface.setSize(100000000ULL); 693 break; 694 case SPEED_1000: 695 interface.setConfig("speed", "1Gbit/s"); 696 interface.setSize(1000000000ULL); 697 break; 698 case SPEED_2500: 699 interface.setConfig("speed", "2.5Gbit/s"); 700 interface.setSize(2500000000ULL); 701 break; 702 case SPEED_5000: 703 interface.setConfig("speed", "5Gbit/s"); 704 interface.setSize(5000000000ULL); 705 break; 706 case SPEED_10000: 707 interface.setConfig("speed", "10Gbit/s"); 708 interface.setSize(10000000000ULL); 709 break; 710 case SPEED_25000: 711 interface.setConfig("speed", "25Gbit/s"); 712 interface.setSize(25000000000ULL); 713 break; 714 case SPEED_40000: 715 interface.setConfig("speed", "40Gbit/s"); 716 interface.setSize(40000000000ULL); 717 break; 718 case SPEED_100000: 719 interface.setConfig("speed", "100Gbit/s"); 720 interface.setSize(100000000000ULL); 721 break; 722 } 723 switch(duplex) 724 { 725 case DUPLEX_HALF: 726 interface.setConfig("duplex", "half"); 727 break; 728 case DUPLEX_FULL: 729 interface.setConfig("duplex", "full"); 730 break; 731 } 732 switch(port) 733 { 734 case PORT_TP: 735 interface.setConfig("port", "twisted pair"); 736 break; 737 case PORT_AUI: 738 interface.setConfig("port", "AUI"); 739 break; 740 case PORT_BNC: 741 interface.setConfig("port", "BNC"); 742 break; 743 case PORT_MII: 744 interface.setConfig("port", "MII"); 745 break; 746 case PORT_FIBRE: 747 interface.setConfig("port", "fibre"); 748 break; 749 } 750 interface.setConfig("autonegotiation", (autoneg == AUTONEG_DISABLE) ? "off" : "on"); 751 } 752 753 754 static void scan_modes(hwNode & interface, int fd) 755 { 756 struct ifreq ifr; 757 struct ethtool_cmd ecmd; 758 struct ethtool_link_settings elink; 759 s8 mask_size; 760 761 elink.cmd = ETHTOOL_GLINKSETTINGS; 762 elink.link_mode_masks_nwords = 0; 763 memset(&ifr, 0, sizeof(ifr)); 764 strcpy(ifr.ifr_name, interface.getLogicalName().c_str()); 765 ifr.ifr_data = (caddr_t) &elink; 766 // Probe link mode mask count. 767 if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) 768 { 769 mask_size = -elink.link_mode_masks_nwords; 770 if (mask_size > 1 && mask_size <= MAX_LINK_MODE_MASK_SIZE) 771 { 772 elink.cmd = ETHTOOL_GLINKSETTINGS; 773 elink.link_mode_masks_nwords = mask_size; 774 memset(&ifr, 0, sizeof(ifr)); 775 strcpy(ifr.ifr_name, interface.getLogicalName().c_str()); 776 ifr.ifr_data = (caddr_t) &elink; 777 // Read link mode settings. 778 if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) 779 { 780 updateCapabilities(interface, elink.link_mode_masks[0], elink.link_mode_masks[1], 781 elink.speed, elink.duplex, elink.port, elink.autoneg); 782 return; 783 } 784 } 785 } 786 787 ecmd.cmd = ETHTOOL_GSET; 788 memset(&ifr, 0, sizeof(ifr)); 789 strcpy(ifr.ifr_name, interface.getLogicalName().c_str()); 790 ifr.ifr_data = (caddr_t) &ecmd; 791 if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) 792 { 793 updateCapabilities(interface, ecmd.supported, 0, ecmd.speed, ecmd.duplex, ecmd.port, ecmd.autoneg); 794 } 795 } 796 797 798 bool scan_network(hwNode & n) 799 { 800 vector < string > interfaces; 801 char buffer[2 * IFNAMSIZ + 1]; 802 803 if (!load_interfaces(interfaces)) 804 return false; 805 806 int fd = socket(PF_INET, SOCK_DGRAM, 0); 807 808 if (fd >= 0) 809 { 810 struct ifreq ifr; 811 struct ethtool_drvinfo drvinfo; 812 struct ethtool_value edata; 813 814 for (unsigned int i = 0; i < interfaces.size(); i++) 815 { 816 hwNode *existing; 817 hwNode interface("network", 818 hw::network); 819 820 interface.setLogicalName(interfaces[i]); 821 interface.claim(); 822 interface.addHint("icon", string("network")); 823 824 string businfo = sysfs::entry::byClass("net", interface.getLogicalName()).leaf().businfo(); 825 if (businfo!="") 826 interface.setBusInfo(businfo); 827 interface.setModalias(sysfs::entry::byClass("net", interface.getLogicalName()).leaf().modalias()); 828 829 //scan_mii(fd, interface); 830 scan_ip(interface); 831 832 memset(&ifr, 0, sizeof(ifr)); 833 strcpy(ifr.ifr_name, interfaces[i].c_str()); 834 if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) 835 { 836 #ifdef IFF_PORTSEL 837 if (ifr.ifr_flags & IFF_PORTSEL) 838 { 839 if (ifr.ifr_flags & IFF_AUTOMEDIA) 840 interface.setConfig("automedia", "yes"); 841 } 842 #endif 843 844 if (ifr.ifr_flags & IFF_UP) 845 interface.enable(); 846 else 847 interface.disable(); 848 if (ifr.ifr_flags & IFF_BROADCAST) 849 interface.setConfig("broadcast", "yes"); 850 if (ifr.ifr_flags & IFF_DEBUG) 851 interface.setConfig("debug", "yes"); 852 if (ifr.ifr_flags & IFF_LOOPBACK) 853 interface.setConfig("loopback", "yes"); 854 if (ifr.ifr_flags & IFF_POINTOPOINT) 855 interface.setConfig("point-to-point", "yes"); 856 if (ifr.ifr_flags & IFF_PROMISC) 857 interface.setConfig("promiscuous", "yes"); 858 if (ifr.ifr_flags & IFF_SLAVE) 859 interface.setConfig("slave", "yes"); 860 if (ifr.ifr_flags & IFF_MASTER) 861 interface.setConfig("master", "yes"); 862 if (ifr.ifr_flags & IFF_MULTICAST) 863 interface.setConfig("multicast", "yes"); 864 } 865 866 memset(&ifr, 0, sizeof(ifr)); 867 strcpy(ifr.ifr_name, interfaces[i].c_str()); 868 // get MAC address 869 if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) 870 { 871 string hwaddr = getmac((unsigned char *) ifr.ifr_hwaddr.sa_data, ifr.ifr_hwaddr.sa_family); 872 interface.addCapability(hwname(ifr.ifr_hwaddr.sa_family)); 873 if (ifr.ifr_hwaddr.sa_family >= 256) 874 interface.addCapability("logical", _("Logical interface")); 875 else 876 interface.addCapability("physical", _("Physical interface")); 877 interface.setDescription(string(hwname(ifr.ifr_hwaddr.sa_family)) + 878 " interface"); 879 interface.setSerial(hwaddr); 880 881 if (isVirtual(interface.getSerial())) 882 interface.addCapability("logical", _("Logical interface")); 883 } 884 885 // check for wireless extensions 886 memset(buffer, 0, sizeof(buffer)); 887 strncpy(buffer, interfaces[i].c_str(), sizeof(buffer)); 888 if (ioctl(fd, SIOCGIWNAME, &buffer) == 0) 889 { 890 interface.addCapability("wireless", _("Wireless-LAN")); 891 interface.setConfig("wireless", hw::strip(buffer + IFNAMSIZ)); 892 interface.setDescription(_("Wireless interface")); 893 interface.addHint("icon", string("wifi")); 894 interface.addHint("bus.icon", string("radio")); 895 } 896 897 edata.cmd = ETHTOOL_GLINK; 898 memset(&ifr, 0, sizeof(ifr)); 899 strcpy(ifr.ifr_name, interfaces[i].c_str()); 900 ifr.ifr_data = (caddr_t) &edata; 901 if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) 902 { 903 interface.setConfig("link", edata.data ? "yes":"no"); 904 } 905 906 scan_modes(interface, fd); 907 scan_module(interface, fd); 908 909 drvinfo.cmd = ETHTOOL_GDRVINFO; 910 memset(&ifr, 0, sizeof(ifr)); 911 strcpy(ifr.ifr_name, interfaces[i].c_str()); 912 ifr.ifr_data = (caddr_t) & drvinfo; 913 if (ioctl(fd, SIOCETHTOOL, &ifr) == 0) 914 { 915 interface.setConfig("driver", drvinfo.driver); 916 interface.setConfig("driverversion", drvinfo.version); 917 interface.setConfig("firmware", drvinfo.fw_version); 918 if (interface.getBusInfo() == "") 919 interface.setBusInfo(guessBusInfo(drvinfo.bus_info)); 920 } 921 922 if(sysfs::entry::byClass("net", interface.getLogicalName()).isvirtual()) 923 interface.addCapability("logical", _("Logical interface")); 924 925 existing = n.findChildByBusInfo(interface.getBusInfo()); 926 // Multiple NICs can exist on one PCI function. 927 928 if (existing && !existing->getBusInfo().empty() && (interface.getBusInfo() == existing->getBusInfo()) && interface.getProduct().empty()) 929 interface.setProduct(existing->getProduct()); 930 931 // Only merge if MACs also match. 932 if (existing && (existing->getSerial() == "" || interface.getSerial() == existing->getSerial())) 933 { 934 existing->merge(interface); 935 if(interface.getDescription()!="") 936 existing->setDescription(interface.getDescription()); 937 } 938 else 939 { 940 existing = n.findChildByLogicalName(interface.getLogicalName()); 941 if (existing) 942 { 943 existing->merge(interface); 944 } 945 else 946 { 947 // we don't care about loopback and "logical" interfaces 948 if (!interface.isCapable("loopback") && 949 !interface.isCapable("logical")) 950 n.addChild(interface); 951 } 952 } 953 } 954 955 close(fd); 956 return true; 957 } 958 else 959 return false; 960 }