diff options
-rw-r--r-- | mdk-stage1/doc/TECH-INFOS | 1 | ||||
-rw-r--r-- | mdk-stage1/network.c | 47 |
2 files changed, 48 insertions, 0 deletions
diff --git a/mdk-stage1/doc/TECH-INFOS b/mdk-stage1/doc/TECH-INFOS index e66c9daa5..e52134da5 100644 --- a/mdk-stage1/doc/TECH-INFOS +++ b/mdk-stage1/doc/TECH-INFOS @@ -37,6 +37,7 @@ if nfs/ftp/http: if multiple interfaces detected: `interface' <- (list-of-detected-interfaces) + (if "auto", use the first interface with a link beat) fi diff --git a/mdk-stage1/network.c b/mdk-stage1/network.c index 29ea5dc10..513c4784b 100644 --- a/mdk-stage1/network.c +++ b/mdk-stage1/network.c @@ -598,6 +598,45 @@ static enum return_type bringup_networking(struct interface_info * intf) } +static char * auto_select_up_intf(void) +{ +#define SIOCETHTOOL 0x8946 +#define ETHTOOL_GLINK 0x0000000a /* Get link status (ethtool_value) */ + + struct ethtool_value { + uint32_t cmd; + uint32_t data; + }; + + char ** interfaces, ** ptr; + interfaces = get_net_devices(); + + int s; + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s < 0) { + return NULL; + } + + ptr = interfaces; + while (ptr && *ptr) { + struct ifreq ifr; + struct ethtool_value edata; + strncpy(ifr.ifr_name, *ptr, IFNAMSIZ); + edata.cmd = ETHTOOL_GLINK; + ifr.ifr_data = (caddr_t)&edata; + if (ioctl(s, SIOCETHTOOL, &ifr) == 0 && edata.data) { + close(s); + return *ptr; + } + ptr++; + } + + close(s); + + return NULL; +} + + static char * interface_select(void) { char ** interfaces, ** ptr; @@ -626,6 +665,14 @@ static char * interface_select(void) if (count == 1) return *interfaces; + /* this can't be done in ask_from_list_comments_auto because "auto" isn't in the interfaces list */ + choice = get_auto_value("interface"); + if (choice && streq(choice, "auto")) { + choice = auto_select_up_intf(); + if (choice) + return choice; + } + i = 0; while (interfaces[i]) { descriptions[i] = get_net_intf_description(interfaces[i]); |