aboutsummaryrefslogtreecommitdiff
path: root/networking
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-12-24 14:09:19 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-12-24 14:09:19 +0000
commitf7be20e70c27b0bed505710393a99d1b6f821ff1 (patch)
tree151940c339bd35b64734053bb656488c9dbc3daa /networking
parentfcfb5c04bbaa52ae7df5d45bc3ddadcc9e935fa1 (diff)
downloadbusybox-w32-f7be20e70c27b0bed505710393a99d1b6f821ff1.tar.gz
busybox-w32-f7be20e70c27b0bed505710393a99d1b6f821ff1.tar.bz2
busybox-w32-f7be20e70c27b0bed505710393a99d1b6f821ff1.zip
nameif: extended matching (Nico Erfurth <masta@perlgolf.de>)
*: whitespace fixes function old new delta prepend_new_eth_table - 304 +304 nameif_main 620 684 +64 cc_macaddr 51 - -51 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/0 up/down: 368/-51) Total: 317 bytes
Diffstat (limited to 'networking')
-rw-r--r--networking/Config.in13
-rw-r--r--networking/nameif.c230
2 files changed, 166 insertions, 77 deletions
diff --git a/networking/Config.in b/networking/Config.in
index b50aacf9f..5a766046a 100644
--- a/networking/Config.in
+++ b/networking/Config.in
@@ -549,6 +549,19 @@ config NAMEIF
549 # Comment 549 # Comment
550 new_interface_name XX:XX:XX:XX:XX:XX 550 new_interface_name XX:XX:XX:XX:XX:XX
551 551
552config FEATURE_NAMEIF_EXTENDED
553 bool "Extended nameif"
554 default n
555 depends on NAMEIF
556 help
557 This extends the nameif syntax to support the bus_info and driver
558 checks. The syntax is compatible to the normal nameif.
559 File format:
560 new_interface_name driver=asix bus=usb-0000:00:08.2-3
561 new_interface_name bus=usb-0000:00:08.2-3 00:80:C8:38:91:B5
562 new_interface_name mac=00:80:C8:38:91:B5
563 new_interface_name 00:80:C8:38:91:B5
564
552config NC 565config NC
553 bool "nc" 566 bool "nc"
554 default n 567 default n
diff --git a/networking/nameif.c b/networking/nameif.c
index a951970c2..66376a500 100644
--- a/networking/nameif.c
+++ b/networking/nameif.c
@@ -13,7 +13,7 @@
13#include <syslog.h> 13#include <syslog.h>
14#include <net/if.h> 14#include <net/if.h>
15#include <netinet/ether.h> 15#include <netinet/ether.h>
16 16#include <linux/sockios.h>
17 17
18/* Older versions of net/if.h do not appear to define IF_NAMESIZE. */ 18/* Older versions of net/if.h do not appear to define IF_NAMESIZE. */
19#ifndef IF_NAMESIZE 19#ifndef IF_NAMESIZE
@@ -34,138 +34,214 @@
34#define ifr_newname ifr_ifru.ifru_slave 34#define ifr_newname ifr_ifru.ifru_slave
35#endif 35#endif
36 36
37typedef struct mactable_s { 37typedef struct ethtable_s {
38 struct mactable_s *next; 38 struct ethtable_s *next;
39 struct mactable_s *prev; 39 struct ethtable_s *prev;
40 char *ifname; 40 char *ifname;
41 struct ether_addr *mac; 41 struct ether_addr *mac;
42} mactable_t; 42#if ENABLE_FEATURE_NAMEIF_EXTENDED
43 char *bus_info;
44 char *driver;
45#endif
46} ethtable_t;
47
48#if ENABLE_FEATURE_NAMEIF_EXTENDED
49/* Cut'n'paste from ethtool.h */
50#define ETHTOOL_BUSINFO_LEN 32
51/* these strings are set to whatever the driver author decides... */
52struct ethtool_drvinfo {
53 __u32 cmd;
54 char driver[32]; /* driver short name, "tulip", "eepro100" */
55 char version[32]; /* driver version string */
56 char fw_version[32]; /* firmware version string, if applicable */
57 char bus_info[ETHTOOL_BUSINFO_LEN]; /* Bus info for this IF. */
58 /* For PCI devices, use pci_dev->slot_name. */
59 char reserved1[32];
60 char reserved2[16];
61 __u32 n_stats; /* number of u64's from ETHTOOL_GSTATS */
62 __u32 testinfo_len;
63 __u32 eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */
64 __u32 regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */
65};
66#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */
67#endif
68
43 69
44/* Check ascii str_macaddr, convert and copy to *mac */ 70static void nameif_parse_selector(ethtable_t *ch, char *selector)
45static struct ether_addr *cc_macaddr(const char *str_macaddr)
46{ 71{
47 struct ether_addr *lmac, *mac; 72 struct ether_addr *lmac;
73#if ENABLE_FEATURE_NAMEIF_EXTENDED
74 int found_selector = 0;
48 75
49 lmac = ether_aton(str_macaddr); 76 while (*selector) {
50 if (lmac == NULL) 77 char *next;
51 bb_error_msg_and_die("cannot parse MAC %s", str_macaddr); 78#endif
52 mac = xmalloc(ETH_ALEN); 79 selector = skip_whitespace(selector);
53 memcpy(mac, lmac, ETH_ALEN); 80#if ENABLE_FEATURE_NAMEIF_EXTENDED
81 if (*selector == '\0')
82 break;
83 /* Search for the end .... */
84 next = skip_non_whitespace(selector);
85 if (*next)
86 *next++ = '\0';
87 /* Check for selectors, mac= is assumed */
88 if (strncmp(selector, "bus=", 4) == 0) {
89 ch->bus_info = xstrdup(selector + 4);
90 found_selector++;
91 } else if (strncmp(selector, "driver=", 7) == 0) {
92 ch->driver = xstrdup(selector + 7);
93 found_selector++;
94 } else {
95#endif
96 lmac = ether_aton(selector + (strncmp(selector, "mac=", 4) == 0 ? 4 : 0));
97 /* Check ascii selector, convert and copy to *mac */
98 if (lmac == NULL)
99 bb_error_msg_and_die("cannot parse %s", selector);
100 ch->mac = xmalloc(ETH_ALEN);
101 memcpy(ch->mac, lmac, ETH_ALEN);
102#if ENABLE_FEATURE_NAMEIF_EXTENDED
103 found_selector++;
104 };
105 selector = next;
106 }
107 if (found_selector == 0)
108 bb_error_msg_and_die("no selectors found for %s", ch->ifname);
109#endif
110}
54 111
55 return mac; 112static void prepend_new_eth_table(ethtable_t **clist, char *ifname, char *selector)
113{
114 ethtable_t *ch;
115 if (strlen(ifname) >= IF_NAMESIZE)
116 bb_error_msg_and_die("interface name '%s' too long", ifname);
117 ch = xzalloc(sizeof(*ch));
118 ch->ifname = ifname;
119 nameif_parse_selector(ch, selector);
120 ch->next = *clist;
121 if (*clist)
122 (*clist)->prev = ch;
123 *clist = ch;
56} 124}
57 125
58int nameif_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 126int nameif_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
59int nameif_main(int argc, char **argv) 127int nameif_main(int argc, char **argv)
60{ 128{
61 mactable_t *clist = NULL; 129 ethtable_t *clist = NULL;
62 FILE *ifh; 130 FILE *ifh;
63 const char *fname = "/etc/mactab"; 131 const char *fname = "/etc/mactab";
64 char *line; 132 char *line;
133 char *line_ptr;
134 int linenum;
65 int ctl_sk; 135 int ctl_sk;
66 int if_index = 1; 136 ethtable_t *ch;
67 mactable_t *ch;
68 137
69 if (1 & getopt32(argv, "sc:", &fname)) { 138 if (1 & getopt32(argv, "sc:", &fname)) {
70 openlog(applet_name, 0, LOG_LOCAL0); 139 openlog(applet_name, 0, LOG_LOCAL0);
71 logmode = LOGMODE_SYSLOG; 140 logmode = LOGMODE_SYSLOG;
72 } 141 }
142 argc -= optind;
143 argv += optind;
73 144
74 if ((argc - optind) & 1) 145 if (argc & 1)
75 bb_show_usage(); 146 bb_show_usage();
76 147
77 if (optind < argc) { 148 if (argc) {
78 char **a = argv + optind; 149 while (*argv) {
79 150 char *ifname = xstrdup(*argv++);
80 while (*a) { 151 prepend_new_eth_table(&clist, ifname, *argv++);
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;
91 } 152 }
92 } else { 153 } else {
93 ifh = xfopen(fname, "r"); 154 ifh = xfopen(fname, "r");
94
95 while ((line = xmalloc_fgets(ifh)) != NULL) { 155 while ((line = xmalloc_fgets(ifh)) != NULL) {
96 char *line_ptr; 156 char *next;
97 size_t name_length;
98 157
99 line_ptr = line + strspn(line, " \t"); 158 line_ptr = skip_whitespace(line);
100 if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) { 159 if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) {
101 free(line); 160 free(line);
102 continue; 161 continue;
103 } 162 }
104 name_length = strcspn(line_ptr, " \t"); 163 next = skip_non_whitespace(line_ptr);
105 ch = xzalloc(sizeof(mactable_t)); 164 if (*next)
106 ch->ifname = xstrndup(line_ptr, name_length); 165 *next++ = '\0';
107 if (name_length > IF_NAMESIZE) 166 prepend_new_eth_table(&clist, line_ptr, next);
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); 167 free(line);
120 } 168 }
121 fclose(ifh); 169 fclose(ifh);
122 } 170 }
123 171
124 ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0); 172 ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0);
173 ifh = xfopen("/proc/net/dev", "r");
125 174
175 linenum = 0;
126 while (clist) { 176 while (clist) {
127 struct ifreq ifr; 177 struct ifreq ifr;
178#if ENABLE_FEATURE_NAMEIF_EXTENDED
179 struct ethtool_drvinfo drvinfo;
180#endif
128 181
129 memset(&ifr, 0, sizeof(struct ifreq)); 182 line = xmalloc_fgets(ifh);
130 if_index++; 183 if (line == NULL)
131 ifr.ifr_ifindex = if_index; 184 break; /* Seems like we're done */
132 185 if (linenum++ < 2 )
133 /* Get ifname by index or die */ 186 goto next_line; /* Skip the first two lines */
134 if (ioctl(ctl_sk, SIOCGIFNAME, &ifr))
135 break;
136
137 /* Has this device hwaddr? */
138 if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr))
139 continue;
140 187
141 /* Search for mac like in ifr.ifr_hwaddr.sa_data */ 188 /* Find the current interface name and copy it to ifr.ifr_name */
142 for (ch = clist; ch; ch = ch->next) 189 line_ptr = skip_whitespace(line);
143 if (!memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN)) 190 *skip_non_whitespace(line_ptr) = '\0';
144 break;
145 191
146 /* Nothing found for current ifr.ifr_hwaddr.sa_data */ 192 memset(&ifr, 0, sizeof(struct ifreq));
147 if (ch == NULL) 193 strncpy(ifr.ifr_name, line_ptr, sizeof(ifr.ifr_name));
148 continue; 194
195#if ENABLE_FEATURE_NAMEIF_EXTENDED
196 /* Check for driver etc. */
197 memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
198 drvinfo.cmd = ETHTOOL_GDRVINFO;
199 ifr.ifr_data = (caddr_t) &drvinfo;
200 /* Get driver and businfo first, so we have it in drvinfo */
201 ioctl(ctl_sk, SIOCETHTOOL, &ifr);
202#endif
203 ioctl(ctl_sk, SIOCGIFHWADDR, &ifr);
149 204
150 strcpy(ifr.ifr_newname, ch->ifname); 205 /* Search the list for a matching device */
151 ioctl_or_perror_and_die(ctl_sk, SIOCSIFNAME, &ifr, 206 for (ch = clist; ch; ch = ch->next) {
207#if ENABLE_FEATURE_NAMEIF_EXTENDED
208 if (ch->bus_info && strcmp(ch->bus_info, drvinfo.bus_info) != 0)
209 continue;
210 if (ch->driver && strcmp(ch->driver, drvinfo.driver) != 0)
211 continue;
212#endif
213 if (ch->mac && memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN) != 0)
214 continue;
215 /* if we came here, all selectors have matched */
216 goto found;
217 }
218 /* Nothing found for current interface */
219 goto next_line;
220 found:
221 if (strcmp(ifr.ifr_name, ch->ifname) != 0) {
222 strcpy(ifr.ifr_newname, ch->ifname);
223 ioctl_or_perror_and_die(ctl_sk, SIOCSIFNAME, &ifr,
152 "cannot change ifname %s to %s", 224 "cannot change ifname %s to %s",
153 ifr.ifr_name, ch->ifname); 225 ifr.ifr_name, ch->ifname);
154 226 }
155 /* Remove list entry of renamed interface */ 227 /* Remove list entry of renamed interface */
156 if (ch->prev != NULL) { 228 if (ch->prev != NULL)
157 (ch->prev)->next = ch->next; 229 ch->prev->next = ch->next;
158 } else { 230 else
159 clist = ch->next; 231 clist = ch->next;
160 }
161 if (ch->next != NULL) 232 if (ch->next != NULL)
162 (ch->next)->prev = ch->prev; 233 ch->next->prev = ch->prev;
163 if (ENABLE_FEATURE_CLEAN_UP) { 234 if (ENABLE_FEATURE_CLEAN_UP) {
164 free(ch->ifname); 235 free(ch->ifname);
165 free(ch->mac); 236 free(ch->mac);
166 free(ch); 237 free(ch);
167 } 238 }
239 next_line:
240 free(line);
168 } 241 }
242 if (ENABLE_FEATURE_CLEAN_UP) {
243 fclose(ifh);
244 };
169 245
170 return 0; 246 return 0;
171} 247}