Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/networking/nameif.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/networking/nameif.c
r1765 r2725 5 5 * Written 2000 by Andi Kleen. 6 6 * Busybox port 2002 by Nick Fedchik <nick@fedchik.org.ua> 7 * Glenn McGrath <bug1@iinet.net.au> 7 * Glenn McGrath 8 * Extended matching support 2008 by Nico Erfurth <masta@perlgolf.de> 8 9 * 9 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 10 11 */ 11 12 … … 14 15 #include <net/if.h> 15 16 #include <netinet/ether.h> 16 17 18 /* Older versions of net/if.h do not appear to define IF_NAMESIZE. */ 19 #ifndef IF_NAMESIZE 20 # ifdef IFNAMSIZ 21 # define IF_NAMESIZE IFNAMSIZ 22 # else 23 # define IF_NAMESIZE 16 24 # endif 25 #endif 26 27 /* take from linux/sockios.h */ 28 #define SIOCSIFNAME 0x8923 /* set interface name */ 17 #include <linux/sockios.h> 18 19 #ifndef IFNAMSIZ 20 #define IFNAMSIZ 16 21 #endif 22 23 /* Taken from linux/sockios.h */ 24 #define SIOCSIFNAME 0x8923 /* set interface name */ 29 25 30 26 /* Octets in one Ethernet addr, from <linux/if_ether.h> */ 31 #define ETH_ALEN 27 #define ETH_ALEN 6 32 28 33 29 #ifndef ifr_newname … … 35 31 #endif 36 32 37 typedef struct mactable_s {38 struct mactable_s *next;39 struct mactable_s *prev;33 typedef struct ethtable_s { 34 struct ethtable_s *next; 35 struct ethtable_s *prev; 40 36 char *ifname; 41 37 struct ether_addr *mac; 42 } mactable_t; 43 44 /* Check ascii str_macaddr, convert and copy to *mac */ 45 static struct ether_addr *cc_macaddr(const char *str_macaddr) 46 { 47 struct ether_addr *lmac, *mac; 48 49 lmac = ether_aton(str_macaddr); 50 if (lmac == NULL) 51 bb_error_msg_and_die("cannot parse MAC %s", str_macaddr); 52 mac = xmalloc(ETH_ALEN); 53 memcpy(mac, lmac, ETH_ALEN); 54 55 return mac; 38 #if ENABLE_FEATURE_NAMEIF_EXTENDED 39 char *bus_info; 40 char *driver; 41 #endif 42 } ethtable_t; 43 44 #if ENABLE_FEATURE_NAMEIF_EXTENDED 45 /* Cut'n'paste from ethtool.h */ 46 #define ETHTOOL_BUSINFO_LEN 32 47 /* these strings are set to whatever the driver author decides... */ 48 struct ethtool_drvinfo { 49 uint32_t cmd; 50 char driver[32]; /* driver short name, "tulip", "eepro100" */ 51 char version[32]; /* driver version string */ 52 char fw_version[32]; /* firmware version string, if applicable */ 53 char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */ 54 /* For PCI devices, use pci_dev->slot_name. */ 55 char reserved1[32]; 56 char reserved2[16]; 57 uint32_t n_stats; /* number of u64's from ETHTOOL_GSTATS */ 58 uint32_t testinfo_len; 59 uint32_t eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ 60 uint32_t regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ 61 }; 62 #define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ 63 #endif 64 65 66 static void nameif_parse_selector(ethtable_t *ch, char *selector) 67 { 68 struct ether_addr *lmac; 69 #if ENABLE_FEATURE_NAMEIF_EXTENDED 70 int found_selector = 0; 71 72 while (*selector) { 73 char *next; 74 #endif 75 selector = skip_whitespace(selector); 76 #if ENABLE_FEATURE_NAMEIF_EXTENDED 77 if (*selector == '\0') 78 break; 79 /* Search for the end .... */ 80 next = skip_non_whitespace(selector); 81 if (*next) 82 *next++ = '\0'; 83 /* Check for selectors, mac= is assumed */ 84 if (strncmp(selector, "bus=", 4) == 0) { 85 ch->bus_info = xstrdup(selector + 4); 86 found_selector++; 87 } else if (strncmp(selector, "driver=", 7) == 0) { 88 ch->driver = xstrdup(selector + 7); 89 found_selector++; 90 } else { 91 #endif 92 lmac = xmalloc(ETH_ALEN); 93 ch->mac = ether_aton_r(selector + (strncmp(selector, "mac=", 4) != 0 ? 0 : 4), lmac); 94 if (ch->mac == NULL) 95 bb_error_msg_and_die("can't parse %s", selector); 96 #if ENABLE_FEATURE_NAMEIF_EXTENDED 97 found_selector++; 98 }; 99 selector = next; 100 } 101 if (found_selector == 0) 102 bb_error_msg_and_die("no selectors found for %s", ch->ifname); 103 #endif 56 104 } 57 105 58 int nameif_main(int argc, char **argv); 106 static void prepend_new_eth_table(ethtable_t **clist, char *ifname, char *selector) 107 { 108 ethtable_t *ch; 109 if (strlen(ifname) >= IFNAMSIZ) 110 bb_error_msg_and_die("interface name '%s' too long", ifname); 111 ch = xzalloc(sizeof(*ch)); 112 ch->ifname = xstrdup(ifname); 113 nameif_parse_selector(ch, selector); 114 ch->next = *clist; 115 if (*clist) 116 (*clist)->prev = ch; 117 *clist = ch; 118 } 119 120 #if ENABLE_FEATURE_CLEAN_UP 121 static void delete_eth_table(ethtable_t *ch) 122 { 123 free(ch->ifname); 124 #if ENABLE_FEATURE_NAMEIF_EXTENDED 125 free(ch->bus_info); 126 free(ch->driver); 127 #endif 128 free(ch->mac); 129 free(ch); 130 }; 131 #else 132 void delete_eth_table(ethtable_t *ch); 133 #endif 134 135 int nameif_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 59 136 int nameif_main(int argc, char **argv) 60 137 { 61 mactable_t *clist = NULL; 62 FILE *ifh; 138 ethtable_t *clist = NULL; 63 139 const char *fname = "/etc/mactab"; 64 char *line;65 140 int ctl_sk; 66 int if_index = 1; 67 mactable_t *ch; 141 ethtable_t *ch; 142 parser_t *parser; 143 char *token[2]; 68 144 69 145 if (1 & getopt32(argv, "sc:", &fname)) { 70 146 openlog(applet_name, 0, LOG_LOCAL0); 71 logmode = LOGMODE_SYSLOG; 72 } 73 74 if ((argc - optind) & 1) 147 /* Why not just "="? I assume logging to stderr 148 * can't hurt. 2>/dev/null if you don't like it: */ 149 logmode |= LOGMODE_SYSLOG; 150 } 151 argc -= optind; 152 argv += optind; 153 154 if (argc & 1) 75 155 bb_show_usage(); 76 156 77 if (optind < argc) { 78 char **a = argv + optind; 79 80 while (*a) { 81 if (strlen(*a) > IF_NAMESIZE) 82 bb_error_msg_and_die("interface name '%s' " 83 "too long", *a); 84 ch = xzalloc(sizeof(mactable_t)); 85 ch->ifname = xstrdup(*a++); 86 ch->mac = cc_macaddr(*a++); 87 if (clist) 88 clist->prev = ch; 89 ch->next = clist; 90 clist = ch; 157 if (argc) { 158 while (*argv) { 159 char *ifname = xstrdup(*argv++); 160 prepend_new_eth_table(&clist, ifname, *argv++); 91 161 } 92 162 } else { 93 ifh = xfopen(fname, "r"); 94 95 while ((line = xmalloc_fgets(ifh)) != NULL) { 96 char *line_ptr; 97 size_t name_length; 98 99 line_ptr = line + strspn(line, " \t"); 100 if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) { 101 free(line); 163 parser = config_open(fname); 164 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) 165 prepend_new_eth_table(&clist, token[0], token[1]); 166 config_close(parser); 167 } 168 169 ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0); 170 parser = config_open2("/proc/net/dev", xfopen_for_read); 171 172 while (clist && config_read(parser, token, 2, 2, "\0: \t", PARSE_NORMAL)) { 173 struct ifreq ifr; 174 #if ENABLE_FEATURE_NAMEIF_EXTENDED 175 struct ethtool_drvinfo drvinfo; 176 #endif 177 if (parser->lineno < 2) 178 continue; /* Skip the first two lines */ 179 180 /* Find the current interface name and copy it to ifr.ifr_name */ 181 memset(&ifr, 0, sizeof(struct ifreq)); 182 strncpy_IFNAMSIZ(ifr.ifr_name, token[0]); 183 184 #if ENABLE_FEATURE_NAMEIF_EXTENDED 185 /* Check for driver etc. */ 186 memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo)); 187 drvinfo.cmd = ETHTOOL_GDRVINFO; 188 ifr.ifr_data = (caddr_t) &drvinfo; 189 /* Get driver and businfo first, so we have it in drvinfo */ 190 ioctl(ctl_sk, SIOCETHTOOL, &ifr); 191 #endif 192 ioctl(ctl_sk, SIOCGIFHWADDR, &ifr); 193 194 /* Search the list for a matching device */ 195 for (ch = clist; ch; ch = ch->next) { 196 #if ENABLE_FEATURE_NAMEIF_EXTENDED 197 if (ch->bus_info && strcmp(ch->bus_info, drvinfo.bus_info) != 0) 102 198 continue; 103 } 104 name_length = strcspn(line_ptr, " \t"); 105 ch = xzalloc(sizeof(mactable_t)); 106 ch->ifname = xstrndup(line_ptr, name_length); 107 if (name_length > IF_NAMESIZE) 108 bb_error_msg_and_die("interface name '%s' " 109 "too long", ch->ifname); 110 line_ptr += name_length; 111 line_ptr += strspn(line_ptr, " \t"); 112 name_length = strspn(line_ptr, "0123456789ABCDEFabcdef:"); 113 line_ptr[name_length] = '\0'; 114 ch->mac = cc_macaddr(line_ptr); 115 if (clist) 116 clist->prev = ch; 117 ch->next = clist; 118 clist = ch; 119 free(line); 199 if (ch->driver && strcmp(ch->driver, drvinfo.driver) != 0) 200 continue; 201 #endif 202 if (ch->mac && memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN) != 0) 203 continue; 204 /* if we came here, all selectors have matched */ 205 break; 120 206 } 121 fclose(ifh); 122 } 123 124 ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0); 125 126 while (clist) { 127 struct ifreq ifr; 128 129 memset(&ifr, 0, sizeof(struct ifreq)); 130 if_index++; 131 ifr.ifr_ifindex = if_index; 132 133 /* Get ifname by index or die */ 134 if (ioctl(ctl_sk, SIOCGIFNAME, &ifr)) 135 break; 136 137 /* Has this device hwaddr? */ 138 if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr)) 207 /* Nothing found for current interface */ 208 if (!ch) 139 209 continue; 140 210 141 /* Search for mac like in ifr.ifr_hwaddr.sa_data */ 211 if (strcmp(ifr.ifr_name, ch->ifname) != 0) { 212 strcpy(ifr.ifr_newname, ch->ifname); 213 ioctl_or_perror_and_die(ctl_sk, SIOCSIFNAME, &ifr, 214 "can't change ifname %s to %s", 215 ifr.ifr_name, ch->ifname); 216 } 217 /* Remove list entry of renamed interface */ 218 if (ch->prev != NULL) 219 ch->prev->next = ch->next; 220 else 221 clist = ch->next; 222 if (ch->next != NULL) 223 ch->next->prev = ch->prev; 224 if (ENABLE_FEATURE_CLEAN_UP) 225 delete_eth_table(ch); 226 } 227 if (ENABLE_FEATURE_CLEAN_UP) { 142 228 for (ch = clist; ch; ch = ch->next) 143 if (!memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN)) 144 break; 145 146 /* Nothing found for current ifr.ifr_hwaddr.sa_data */ 147 if (ch == NULL) 148 continue; 149 150 strcpy(ifr.ifr_newname, ch->ifname); 151 ioctl_or_perror_and_die(ctl_sk, SIOCSIFNAME, &ifr, 152 "cannot change ifname %s to %s", 153 ifr.ifr_name, ch->ifname); 154 155 /* Remove list entry of renamed interface */ 156 if (ch->prev != NULL) { 157 (ch->prev)->next = ch->next; 158 } else { 159 clist = ch->next; 160 } 161 if (ch->next != NULL) 162 (ch->next)->prev = ch->prev; 163 if (ENABLE_FEATURE_CLEAN_UP) { 164 free(ch->ifname); 165 free(ch->mac); 166 free(ch); 167 } 168 } 229 delete_eth_table(ch); 230 config_close(parser); 231 }; 169 232 170 233 return 0;
Note:
See TracChangeset
for help on using the changeset viewer.