diff options
-rw-r--r-- | networking/nameif.c | 132 |
1 files changed, 68 insertions, 64 deletions
diff --git a/networking/nameif.c b/networking/nameif.c index 4b2d090ca..a9d422110 100644 --- a/networking/nameif.c +++ b/networking/nameif.c | |||
@@ -22,21 +22,20 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | |||
25 | #include <sys/syslog.h> | 26 | #include <sys/syslog.h> |
26 | #include <sys/socket.h> | 27 | #include <sys/socket.h> |
27 | #include <sys/ioctl.h> | 28 | #include <sys/ioctl.h> |
28 | |||
29 | #include <errno.h> | 29 | #include <errno.h> |
30 | #include <getopt.h> | 30 | #include <getopt.h> |
31 | #include <stdlib.h> | 31 | #include <stdlib.h> |
32 | #include <string.h> | 32 | #include <string.h> |
33 | #include <net/if.h> | 33 | #include <net/if.h> |
34 | #include <netinet/ether.h> | 34 | #include <netinet/ether.h> |
35 | #include <linux/sockios.h> | ||
35 | 36 | ||
36 | #include "busybox.h" | 37 | #include "busybox.h" |
37 | 38 | ||
38 | /* set interface name, from <linux/sockios.h> */ | ||
39 | #define SIOCSIFNAME 0x8923 | ||
40 | /* Octets in one ethernet addr, from <linux/if_ether.h> */ | 39 | /* Octets in one ethernet addr, from <linux/if_ether.h> */ |
41 | #define ETH_ALEN 6 | 40 | #define ETH_ALEN 6 |
42 | 41 | ||
@@ -46,12 +45,12 @@ | |||
46 | 45 | ||
47 | typedef struct mactable_s { | 46 | typedef struct mactable_s { |
48 | struct mactable_s *next; | 47 | struct mactable_s *next; |
49 | struct mactable_s **pprev; | 48 | struct mactable_s *prev; |
50 | char *ifname; | 49 | char *ifname; |
51 | struct ether_addr *mac; | 50 | struct ether_addr *mac; |
52 | } mactable_t; | 51 | } mactable_t; |
53 | 52 | ||
54 | static void serror_msg_and_die(const char use_syslog, const char *s, ...) | 53 | static void serror(const char use_syslog, const char *s, ...) |
55 | { | 54 | { |
56 | va_list ap; | 55 | va_list ap; |
57 | 56 | ||
@@ -67,20 +66,35 @@ static void serror_msg_and_die(const char use_syslog, const char *s, ...) | |||
67 | } | 66 | } |
68 | 67 | ||
69 | va_end(ap); | 68 | va_end(ap); |
70 | 69 | ||
71 | exit(EXIT_FAILURE); | 70 | exit(EXIT_FAILURE); |
72 | } | 71 | } |
73 | 72 | ||
73 | /* Check ascii str_macaddr, convert and copy to *mac */ | ||
74 | struct ether_addr *cc_macaddr(char *str_macaddr, unsigned char use_syslog) | ||
75 | { | ||
76 | struct ether_addr *lmac, *mac; | ||
77 | |||
78 | lmac = ether_aton(str_macaddr); | ||
79 | if (lmac == NULL) | ||
80 | serror(use_syslog, "cannot parse MAC %s", str_macaddr); | ||
81 | mac = xcalloc(1, ETH_ALEN); | ||
82 | memcpy(mac, lmac, ETH_ALEN); | ||
83 | |||
84 | return mac; | ||
85 | } | ||
86 | |||
74 | int nameif_main(int argc, char **argv) | 87 | int nameif_main(int argc, char **argv) |
75 | { | 88 | { |
76 | mactable_t *clist = NULL; | 89 | mactable_t *clist = NULL; |
77 | FILE *ifh; | 90 | FILE *ifh; |
78 | char *fname = "/etc/mactab"; | 91 | char *fname = "/etc/mactab"; |
79 | char *line; | 92 | char *line; |
80 | unsigned short linenum = 0; | ||
81 | unsigned char use_syslog = 0; | 93 | unsigned char use_syslog = 0; |
82 | int ctl_sk = -1; | 94 | int ctl_sk = -1; |
83 | int opt; | 95 | int opt; |
96 | int if_index = 1; | ||
97 | mactable_t *ch = NULL; | ||
84 | 98 | ||
85 | static struct option opts[] = { | 99 | static struct option opts[] = { |
86 | {"syslog", 0, NULL, 's'}, | 100 | {"syslog", 0, NULL, 's'}, |
@@ -101,40 +115,33 @@ int nameif_main(int argc, char **argv) | |||
101 | } | 115 | } |
102 | } | 116 | } |
103 | 117 | ||
104 | if ((argc - optind) & 1) { | 118 | if ((argc - optind) & 1) |
105 | show_usage(); | 119 | show_usage(); |
106 | } | ||
107 | 120 | ||
108 | if (optind < argc) { | 121 | if (optind < argc) { |
109 | while (optind < argc) { | 122 | while (optind < argc) { |
110 | struct ether_addr *mac; | ||
111 | mactable_t *ch; | ||
112 | 123 | ||
113 | if (strlen(argv[optind]) > IF_NAMESIZE) { | 124 | if (strlen(argv[optind]) > IF_NAMESIZE) |
114 | serror_msg_and_die(use_syslog, "interface name `%s' too long", argv[optind]); | 125 | serror(use_syslog, "interface name `%s' too long", |
115 | } | 126 | argv[optind]); |
116 | optind++; | 127 | optind++; |
117 | mac = ether_aton(argv[optind]); | 128 | |
118 | if (mac == NULL) { | ||
119 | serror_msg_and_die(use_syslog, "cannot parse MAC %s", argv[optind]); | ||
120 | } | ||
121 | ch = xcalloc(1, sizeof(mactable_t)); | 129 | ch = xcalloc(1, sizeof(mactable_t)); |
130 | ch->next = NULL; | ||
131 | ch->prev = NULL; | ||
122 | ch->ifname = strdup(argv[optind - 1]); | 132 | ch->ifname = strdup(argv[optind - 1]); |
123 | ch->mac = xcalloc(1, ETH_ALEN); | 133 | ch->mac = cc_macaddr(argv[optind], use_syslog); |
124 | memcpy(ch->mac, mac, ETH_ALEN); | ||
125 | optind++; | 134 | optind++; |
126 | if (clist) | 135 | if (clist) |
127 | clist->pprev = &ch->next; | 136 | clist->prev = ch->next; |
128 | ch->next = clist; | 137 | ch->next = clist; |
129 | ch->pprev = &clist; | 138 | ch->prev = clist; |
130 | clist = ch; | 139 | clist = ch; |
131 | } | 140 | } |
132 | } else { | 141 | } else { |
133 | ifh = xfopen(fname, "r"); | 142 | ifh = xfopen(fname, "r"); |
134 | 143 | ||
135 | while ((line = get_line_from_file(ifh)) != NULL) { | 144 | while ((line = get_line_from_file(ifh)) != NULL) { |
136 | struct ether_addr *mac; | ||
137 | mactable_t *ch; | ||
138 | char *line_ptr; | 145 | char *line_ptr; |
139 | unsigned short name_length; | 146 | unsigned short name_length; |
140 | 147 | ||
@@ -142,74 +149,71 @@ int nameif_main(int argc, char **argv) | |||
142 | if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) | 149 | if ((line_ptr[0] == '#') || (line_ptr[0] == '\n')) |
143 | continue; | 150 | continue; |
144 | name_length = strcspn(line_ptr, " \t"); | 151 | name_length = strcspn(line_ptr, " \t"); |
145 | if (name_length > IF_NAMESIZE) { | 152 | if (name_length > IF_NAMESIZE) |
146 | serror_msg_and_die(use_syslog, "interface name `%s' too long", argv[optind]); | 153 | serror(use_syslog, "interface name `%s' too long", |
147 | } | 154 | argv[optind]); |
148 | ch = xcalloc(1, sizeof(mactable_t)); | 155 | ch = xcalloc(1, sizeof(mactable_t)); |
156 | ch->next = NULL; | ||
157 | ch->prev = NULL; | ||
149 | ch->ifname = strndup(line_ptr, name_length); | 158 | ch->ifname = strndup(line_ptr, name_length); |
150 | line_ptr += name_length; | 159 | line_ptr += name_length; |
151 | line_ptr += strspn(line_ptr, " \t"); | 160 | line_ptr += strspn(line_ptr, " \t"); |
152 | name_length = strspn(line_ptr, "0123456789ABCDEFabcdef:"); | 161 | name_length = strspn(line_ptr, "0123456789ABCDEFabcdef:"); |
153 | line_ptr[name_length] = '\0'; | 162 | line_ptr[name_length] = '\0'; |
154 | mac = ether_aton(line_ptr); | 163 | ch->mac = cc_macaddr(line_ptr, use_syslog); |
155 | if (mac == NULL) { | ||
156 | serror_msg_and_die(use_syslog, "cannot parse MAC %s", argv[optind]); | ||
157 | } | ||
158 | ch->mac = xcalloc(1, ETH_ALEN); | ||
159 | memcpy(ch->mac, mac, ETH_ALEN); | ||
160 | if (clist) | 164 | if (clist) |
161 | clist->pprev = &ch->next; | 165 | clist->prev = ch; |
162 | ch->next = clist; | 166 | ch->next = clist; |
163 | ch->pprev = &clist; | ||
164 | clist = ch; | 167 | clist = ch; |
165 | free(line); | 168 | free(line); |
166 | } | 169 | } |
167 | fclose(ifh); | 170 | fclose(ifh); |
168 | } | 171 | } |
169 | 172 | ||
170 | ifh = xfopen("/proc/net/dev", "r"); | 173 | if ((ctl_sk = socket(PF_INET, SOCK_DGRAM, 0)) == -1) |
171 | while ((line = get_line_from_file(ifh)) != NULL) { | 174 | serror(use_syslog, "socket: %s", strerror(errno)); |
172 | char *line_ptr; | 175 | |
173 | unsigned short iface_name_length; | 176 | while (clist) { |
174 | struct ifreq ifr; | 177 | struct ifreq ifr; |
175 | mactable_t *ch = NULL; | ||
176 | 178 | ||
177 | linenum++; | 179 | bzero(&ifr, sizeof(struct ifreq)); |
178 | if (linenum < 3) | 180 | if_index++; |
179 | continue; | 181 | ifr.ifr_ifindex = if_index; |
180 | line_ptr = line + strspn(line, " \t"); | 182 | |
181 | if (line_ptr[0] == '\n') | 183 | /* Get ifname by index or die */ |
182 | continue; | 184 | if (ioctl(ctl_sk, SIOCGIFNAME, &ifr)) |
183 | iface_name_length = strcspn(line_ptr, ":"); | 185 | break; |
184 | if (ctl_sk < 0) | 186 | |
185 | ctl_sk = socket(PF_INET, SOCK_DGRAM, 0); | 187 | /* Has this device hwaddr? */ |
186 | memset(&ifr, 0, sizeof(struct ifreq)); | 188 | if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr)) |
187 | strncpy(ifr.ifr_name, line_ptr, iface_name_length); | ||
188 | if (ioctl(ctl_sk, SIOCGIFHWADDR, &ifr) < 0) { | ||
189 | // serror_msg(use_syslog, "cannot read hardware address of %s: %s", ifr.ifr_name, strerror(errno)); | ||
190 | continue; | 189 | continue; |
191 | } | 190 | |
191 | /* Search for mac like in ifr.ifr_hwaddr.sa_data */ | ||
192 | for (ch = clist; ch; ch = ch->next) | 192 | for (ch = clist; ch; ch = ch->next) |
193 | if (!memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN)) | 193 | if (!memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN)) |
194 | break; | 194 | break; |
195 | if (ch == NULL) { | 195 | |
196 | /* Nothing found for current ifr.ifr_hwaddr.sa_data */ | ||
197 | if (ch == NULL) | ||
196 | continue; | 198 | continue; |
197 | } | ||
198 | 199 | ||
199 | strcpy(ifr.ifr_newname, ch->ifname); | 200 | strcpy(ifr.ifr_newname, ch->ifname); |
200 | 201 | if (ioctl(ctl_sk, SIOCSIFNAME, &ifr) < 0) | |
201 | if (ioctl(ctl_sk, SIOCSIFNAME, &ifr) < 0) {; | 202 | serror(use_syslog, "cannot change ifname %s to %s: %s", |
202 | serror_msg_and_die(use_syslog, "cannot change name of %s to %s: %s", ifr.ifr_name, ch->ifname, strerror(errno)); | 203 | ifr.ifr_name, ch->ifname, strerror(errno)); |
204 | |||
205 | /* Remove list entry of renamed interface */ | ||
206 | if (ch->prev != NULL) { | ||
207 | (ch->prev)->next = ch->next; | ||
208 | } else { | ||
209 | clist = ch->next; | ||
203 | } | 210 | } |
204 | *ch->pprev = ch->next; | 211 | if (ch->next != NULL) |
212 | (ch->next)->prev = ch->prev; | ||
205 | free(ch); | 213 | free(ch); |
206 | free(line); | ||
207 | } | 214 | } |
208 | fclose(ifh); | ||
209 | 215 | ||
210 | while (clist) { | 216 | while (clist) { |
211 | mactable_t *ch; | ||
212 | |||
213 | ch = clist; | 217 | ch = clist; |
214 | clist = clist->next; | 218 | clist = clist->next; |
215 | free(ch); | 219 | free(ch); |