Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/networking/nameif.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 816 - (hide annotations) (download)
Fri Apr 24 18:33:46 2009 UTC (15 years, 1 month ago) by niro
File MIME type: text/plain
File size: 6187 byte(s)
-updated to busybox-1.13.4
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * nameif.c - Naming Interfaces based on MAC address for busybox.
4     *
5     * Written 2000 by Andi Kleen.
6     * Busybox port 2002 by Nick Fedchik <nick@fedchik.org.ua>
7 niro 816 * Glenn McGrath
8     * Extended matching support 2008 by Nico Erfurth <masta@perlgolf.de>
9 niro 532 *
10     * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
11     */
12    
13 niro 816 #include "libbb.h"
14 niro 532 #include <syslog.h>
15     #include <net/if.h>
16     #include <netinet/ether.h>
17 niro 816 #include <linux/sockios.h>
18 niro 532
19 niro 816 #ifndef IFNAMSIZ
20     #define IFNAMSIZ 16
21 niro 532 #endif
22    
23 niro 816 /* Taken from linux/sockios.h */
24 niro 532 #define SIOCSIFNAME 0x8923 /* set interface name */
25    
26     /* Octets in one Ethernet addr, from <linux/if_ether.h> */
27     #define ETH_ALEN 6
28    
29     #ifndef ifr_newname
30     #define ifr_newname ifr_ifru.ifru_slave
31     #endif
32    
33 niro 816 typedef struct ethtable_s {
34     struct ethtable_s *next;
35     struct ethtable_s *prev;
36 niro 532 char *ifname;
37     struct ether_addr *mac;
38 niro 816 #if ENABLE_FEATURE_NAMEIF_EXTENDED
39     char *bus_info;
40     char *driver;
41     #endif
42     } ethtable_t;
43 niro 532
44 niro 816 #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 niro 532 {
68 niro 816 struct ether_addr *lmac;
69     #if ENABLE_FEATURE_NAMEIF_EXTENDED
70     int found_selector = 0;
71 niro 532
72 niro 816 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 : 4), lmac);
94     if (ch->mac == NULL)
95     bb_error_msg_and_die("cannot 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
104     }
105 niro 532
106 niro 816 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 niro 532 }
119    
120 niro 816 #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;
136 niro 532 int nameif_main(int argc, char **argv)
137     {
138 niro 816 ethtable_t *clist = NULL;
139 niro 532 const char *fname = "/etc/mactab";
140     int ctl_sk;
141 niro 816 ethtable_t *ch;
142     parser_t *parser;
143     char *token[2];
144 niro 532
145 niro 816 if (1 & getopt32(argv, "sc:", &fname)) {
146 niro 532 openlog(applet_name, 0, LOG_LOCAL0);
147     logmode = LOGMODE_SYSLOG;
148     }
149 niro 816 argc -= optind;
150     argv += optind;
151 niro 532
152 niro 816 if (argc & 1)
153 niro 532 bb_show_usage();
154    
155 niro 816 if (argc) {
156     while (*argv) {
157     char *ifname = xstrdup(*argv++);
158     prepend_new_eth_table(&clist, ifname, *argv++);
159 niro 532 }
160     } else {
161 niro 816 parser = config_open(fname);
162     while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL))
163     prepend_new_eth_table(&clist, token[0], token[1]);
164     config_close(parser);
165 niro 532 }
166    
167     ctl_sk = xsocket(PF_INET, SOCK_DGRAM, 0);
168 niro 816 parser = config_open2("/proc/net/dev", xfopen_for_read);
169 niro 532
170 niro 816 while (clist && config_read(parser, token, 2, 2, "\0: \t", PARSE_NORMAL)) {
171 niro 532 struct ifreq ifr;
172 niro 816 #if ENABLE_FEATURE_NAMEIF_EXTENDED
173     struct ethtool_drvinfo drvinfo;
174     #endif
175     if (parser->lineno < 2)
176     continue; /* Skip the first two lines */
177 niro 532
178 niro 816 /* Find the current interface name and copy it to ifr.ifr_name */
179 niro 532 memset(&ifr, 0, sizeof(struct ifreq));
180 niro 816 strncpy(ifr.ifr_name, token[0], sizeof(ifr.ifr_name));
181 niro 532
182 niro 816 #if ENABLE_FEATURE_NAMEIF_EXTENDED
183     /* Check for driver etc. */
184     memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo));
185     drvinfo.cmd = ETHTOOL_GDRVINFO;
186     ifr.ifr_data = (caddr_t) &drvinfo;
187     /* Get driver and businfo first, so we have it in drvinfo */
188     ioctl(ctl_sk, SIOCETHTOOL, &ifr);
189     #endif
190     ioctl(ctl_sk, SIOCGIFHWADDR, &ifr);
191    
192     /* Search the list for a matching device */
193     for (ch = clist; ch; ch = ch->next) {
194     #if ENABLE_FEATURE_NAMEIF_EXTENDED
195     if (ch->bus_info && strcmp(ch->bus_info, drvinfo.bus_info) != 0)
196     continue;
197     if (ch->driver && strcmp(ch->driver, drvinfo.driver) != 0)
198     continue;
199     #endif
200     if (ch->mac && memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN) != 0)
201     continue;
202     /* if we came here, all selectors have matched */
203 niro 532 break;
204 niro 816 }
205     /* Nothing found for current interface */
206     if (!ch)
207 niro 532 continue;
208    
209 niro 816 if (strcmp(ifr.ifr_name, ch->ifname) != 0) {
210     strcpy(ifr.ifr_newname, ch->ifname);
211     ioctl_or_perror_and_die(ctl_sk, SIOCSIFNAME, &ifr,
212     "cannot change ifname %s to %s",
213     ifr.ifr_name, ch->ifname);
214     }
215 niro 532 /* Remove list entry of renamed interface */
216 niro 816 if (ch->prev != NULL)
217     ch->prev->next = ch->next;
218     else
219 niro 532 clist = ch->next;
220     if (ch->next != NULL)
221 niro 816 ch->next->prev = ch->prev;
222     if (ENABLE_FEATURE_CLEAN_UP)
223     delete_eth_table(ch);
224 niro 532 }
225 niro 816 if (ENABLE_FEATURE_CLEAN_UP) {
226     for (ch = clist; ch; ch = ch->next)
227     delete_eth_table(ch);
228     config_close(parser);
229     };
230 niro 532
231     return 0;
232     }