Mercurial > hg > toybox
comparison toys/pending/ifconfig.c @ 921:6a37f642b572
Yet more ifconfig cleanup.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sat, 08 Jun 2013 14:11:41 -0500 |
parents | a186f9a1406d |
children | 1ec29d7540e2 |
comparison
equal
deleted
inserted
replaced
920:74b5cf0309fc | 921:6a37f642b572 |
---|---|
8 | 8 |
9 USE_IFCONFIG(NEWTOY(ifconfig, "?a", TOYFLAG_BIN)) | 9 USE_IFCONFIG(NEWTOY(ifconfig, "?a", TOYFLAG_BIN)) |
10 | 10 |
11 config IFCONFIG | 11 config IFCONFIG |
12 bool "ifconfig" | 12 bool "ifconfig" |
13 default n | 13 default y |
14 help | 14 help |
15 usage: ifconfig [-a] interface [address] | 15 usage: ifconfig [-a] interface [address] |
16 | 16 |
17 Configure network interface. | 17 Configure network interface. |
18 | 18 |
35 #include <net/if_arp.h> | 35 #include <net/if_arp.h> |
36 #include <net/ethernet.h> | 36 #include <net/ethernet.h> |
37 | 37 |
38 GLOBALS( | 38 GLOBALS( |
39 void *if_list; | 39 void *if_list; |
40 | |
41 int sockfd; | |
40 ) | 42 ) |
41 | 43 |
42 typedef struct sockaddr_with_len { | 44 typedef struct sockaddr_with_len { |
43 union { | 45 union { |
44 struct sockaddr sock; | 46 struct sockaddr sock; |
69 struct in6_addr ifrinte6_addr; | 71 struct in6_addr ifrinte6_addr; |
70 uint32_t ifrinet6_prefixlen; | 72 uint32_t ifrinet6_prefixlen; |
71 int ifrinet6_ifindex; | 73 int ifrinet6_ifindex; |
72 }; | 74 }; |
73 | 75 |
74 #ifndef SIOCSKEEPALIVE | |
75 # define SIOCSKEEPALIVE (SIOCDEVPRIVATE) /* Set keepalive timeout in sec */ | |
76 # define SIOCGKEEPALIVE (SIOCDEVPRIVATE+1) /* Get keepalive timeout */ | |
77 #endif | |
78 | |
79 #ifndef SIOCSOUTFILL | |
80 # define SIOCSOUTFILL (SIOCDEVPRIVATE+2) /* Set outfill timeout */ | |
81 # define SIOCGOUTFILL (SIOCDEVPRIVATE+3) /* Get outfill timeout */ | |
82 #endif | |
83 | |
84 /* | |
85 * used to extract the address info from the given host ip | |
86 * and update the swl param accordingly. | |
87 */ | |
88 static int get_socket_stream(char *host, sa_family_t af, sockaddr_with_len **swl) | |
89 { | |
90 struct addrinfo hints, *result, *rp; | |
91 int status; | |
92 | |
93 memset(&hints, 0 , sizeof(struct addrinfo)); | |
94 hints.ai_family = af; | |
95 hints.ai_socktype = SOCK_STREAM; | |
96 | |
97 status = getaddrinfo(host, NULL, &hints, &result); | |
98 if (status) error_exit("bad address '%s' : %s", host, gai_strerror(status)); | |
99 | |
100 for (rp = result; rp; rp = rp->ai_next) { | |
101 if (rp->ai_family == AF_INET || rp->ai_family == AF_INET6) { | |
102 *swl = xmalloc(sizeof(struct sockaddr_with_len)); | |
103 (*swl)->socklen = rp->ai_addrlen; | |
104 memcpy(&((*swl)->sock_u.sock), rp->ai_addr, rp->ai_addrlen); | |
105 break; | |
106 } | |
107 } | |
108 freeaddrinfo(result); | |
109 return rp ? 0 : -1; | |
110 } | |
111 | |
112 /* | 76 /* |
113 * use to get the socket address with the given host ip. | 77 * use to get the socket address with the given host ip. |
114 */ | 78 */ |
115 sockaddr_with_len *get_sockaddr(char *host, int port, sa_family_t af) | 79 sockaddr_with_len *get_sockaddr(char *host, int port, sa_family_t af) |
116 { | 80 { |
117 sockaddr_with_len *swl = NULL; | 81 sockaddr_with_len *swl = NULL; |
118 in_port_t port_num = htons(port); | 82 in_port_t port_num = htons(port); |
83 struct addrinfo hints, *result, *rp; | |
84 int status; | |
119 char *s; | 85 char *s; |
120 | 86 |
121 if (!strncmp(host, "local:", 6)) { | 87 if (!strncmp(host, "local:", 6)) { |
122 struct sockaddr_un *sockun; | 88 struct sockaddr_un *sockun; |
123 | 89 |
140 if (!s || s[1] != ':') error_exit("bad address '%s'", host-1); | 106 if (!s || s[1] != ':') error_exit("bad address '%s'", host-1); |
141 s++; | 107 s++; |
142 } | 108 } |
143 } else { | 109 } else { |
144 s = strrchr(host, ':'); | 110 s = strrchr(host, ':'); |
145 if (s && strchr(host, ':') != s) s = 0; | 111 if (strchr(host, ':') != s) s = 0; |
146 } | 112 } |
147 | 113 |
148 if (s++) { | 114 if (s++) { |
149 char *ss; | 115 char *ss; |
150 unsigned long p = strtoul(s, &ss, 0); | 116 unsigned long p = strtoul(s, &ss, 0); |
151 if (*ss || p > 65535) error_exit("bad port '%s'", s); | 117 if (*ss || p > 65535) error_exit("bad port '%s'", s); |
152 port = p; | 118 port = p; |
153 } | 119 } |
154 | 120 |
155 if (get_socket_stream(host, af, &swl)) return NULL; | 121 memset(&hints, 0 , sizeof(struct addrinfo)); |
122 hints.ai_family = af; | |
123 hints.ai_socktype = SOCK_STREAM; | |
124 | |
125 status = getaddrinfo(host, NULL, &hints, &result); | |
126 if (status) error_exit("bad address '%s' : %s", host, gai_strerror(status)); | |
127 | |
128 for (rp = result; rp; rp = rp->ai_next) { | |
129 if (rp->ai_family == AF_INET || rp->ai_family == AF_INET6) { | |
130 swl = xmalloc(sizeof(struct sockaddr_with_len)); | |
131 swl->socklen = rp->ai_addrlen; | |
132 memcpy(&swl->sock_u.sock, rp->ai_addr, rp->ai_addrlen); | |
133 break; | |
134 } | |
135 } | |
136 freeaddrinfo(result); | |
137 if (!rp) error_exit("bad host name"); | |
138 | |
156 | 139 |
157 if(swl->sock_u.sock.sa_family == AF_INET) | 140 if(swl->sock_u.sock.sa_family == AF_INET) |
158 swl->sock_u.sock_in.sin_port = port_num; | 141 swl->sock_u.sock_in.sin_port = port_num; |
159 else if(swl->sock_u.sock.sa_family == AF_INET6) | 142 else if(swl->sock_u.sock.sa_family == AF_INET6) |
160 swl->sock_u.sock_in6.sin6_port = port_num; | 143 swl->sock_u.sock_in6.sin6_port = port_num; |
193 struct sockaddr_un *sockun = (void*)sock; | 176 struct sockaddr_un *sockun = (void*)sock; |
194 return xmsprintf("local:%.*s", (int) sizeof(sockun->sun_path), sockun->sun_path); | 177 return xmsprintf("local:%.*s", (int) sizeof(sockun->sun_path), sockun->sun_path); |
195 } else return NULL; | 178 } else return NULL; |
196 } | 179 } |
197 | 180 |
198 static void set_ipv6_addr(int sockfd, struct ifreq *ifre, char *ipv6_addr, int request) | 181 static void set_address(char *host_name, struct ifreq *ifre, int request) |
199 { | 182 { |
200 char *prefix; | 183 struct sockaddr_in *sock_in = (struct sockaddr_in *)&ifre->ifr_addr; |
201 int plen = 0; | |
202 sockaddr_with_len *swl = NULL; | 184 sockaddr_with_len *swl = NULL; |
203 | 185 |
204 prefix = strchr(ipv6_addr, '/'); | 186 memset(sock_in, 0, sizeof(struct sockaddr_in)); |
205 if(prefix) { | 187 sock_in->sin_family = AF_INET; |
206 plen = get_int_value(prefix + 1, 0, 128); | |
207 *prefix = '\0'; | |
208 } | |
209 swl = get_sockaddr(ipv6_addr, 0, AF_INET6); | |
210 if(!swl) error_exit("error in resolving host name"); | |
211 int sockfd6; | |
212 struct ifreq_inet6 ifre6; | |
213 memcpy((char *) &ifre6.ifrinte6_addr, | |
214 (char *) &(swl->sock_u.sock_in6.sin6_addr), | |
215 sizeof(struct in6_addr)); | |
216 //Create a channel to the NET kernel. | |
217 sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0); | |
218 xioctl(sockfd6, SIOGIFINDEX, ifre); | |
219 ifre6.ifrinet6_ifindex = ifre->ifr_ifindex; | |
220 ifre6.ifrinet6_prefixlen = plen; | |
221 | |
222 xioctl(sockfd6, request, &ifre6); | |
223 free(swl); | |
224 } | |
225 | |
226 static void set_address(int sockfd, char *host_name, struct ifreq *ifre, int request) | |
227 { | |
228 struct sockaddr_in sock_in; | |
229 sockaddr_with_len *swl = NULL; | |
230 sock_in.sin_family = AF_INET; | |
231 sock_in.sin_port = 0; | |
232 | 188 |
233 //Default 0.0.0.0 | 189 //Default 0.0.0.0 |
234 if(strcmp(host_name, "default") == 0) sock_in.sin_addr.s_addr = INADDR_ANY; | 190 if(strcmp(host_name, "default") == 0) sock_in->sin_addr.s_addr = INADDR_ANY; |
235 else { | 191 else { |
236 swl = get_sockaddr(host_name, 0, AF_INET); | 192 swl = get_sockaddr(host_name, 0, AF_INET); |
237 if(!swl) error_exit("error in resolving host name"); | 193 sock_in->sin_addr = swl->sock_u.sock_in.sin_addr; |
238 | |
239 sock_in.sin_addr = swl->sock_u.sock_in.sin_addr; | |
240 } | |
241 memcpy((char *)&ifre->ifr_addr, (char *) &sock_in, sizeof(struct sockaddr)); | |
242 xioctl(sockfd, request, ifre); | |
243 | |
244 if(swl != NULL) { | |
245 free(swl); | 194 free(swl); |
246 swl = NULL; | 195 } |
247 } | 196 xioctl(TT.sockfd, request, ifre); |
248 } | 197 } |
249 | 198 |
250 static void add_iface_to_list(struct if_list *newnode) | 199 static void add_iface_to_list(struct if_list *newnode) |
251 { | 200 { |
252 struct if_list *head_ref = TT.if_list; | 201 struct if_list *head_ref = TT.if_list; |
266 | 215 |
267 static void get_device_info(struct if_list *il) | 216 static void get_device_info(struct if_list *il) |
268 { | 217 { |
269 struct ifreq ifre; | 218 struct ifreq ifre; |
270 char *name = il->name; | 219 char *name = il->name; |
271 int sokfd; | |
272 | 220 |
273 il->txqueuelen = -1; | 221 il->txqueuelen = -1; |
274 | 222 |
275 sokfd = xsocket(AF_INET, SOCK_DGRAM, 0); | |
276 xstrncpy(ifre.ifr_name, name, IFNAMSIZ); | 223 xstrncpy(ifre.ifr_name, name, IFNAMSIZ); |
277 if (ioctl(sokfd, SIOCGIFFLAGS, &ifre)<0) perror_exit("%s", il->name); | 224 if (ioctl(TT.sockfd, SIOCGIFFLAGS, &ifre)<0) perror_exit("%s", il->name); |
278 il->flags = ifre.ifr_flags; | 225 il->flags = ifre.ifr_flags; |
279 | 226 |
280 if (ioctl(sokfd, SIOCGIFHWADDR, &ifre) >= 0) | 227 if (ioctl(TT.sockfd, SIOCGIFHWADDR, &ifre) >= 0) |
281 memcpy(il->hwaddr.sa_data, ifre.ifr_hwaddr.sa_data, sizeof(il->hwaddr.sa_data)); | 228 memcpy(il->hwaddr.sa_data, ifre.ifr_hwaddr.sa_data, sizeof(il->hwaddr.sa_data)); |
282 il->hw_type = ifre.ifr_hwaddr.sa_family; | 229 il->hw_type = ifre.ifr_hwaddr.sa_family; |
283 | 230 |
284 if (ioctl(sokfd, SIOCGIFMETRIC, &ifre) >= 0) il->metric = ifre.ifr_metric; | 231 if (ioctl(TT.sockfd, SIOCGIFMETRIC, &ifre) >= 0) |
285 if (ioctl(sokfd, SIOCGIFMTU, &ifre) >= 0) il->mtu = ifre.ifr_mtu; | 232 il->metric = ifre.ifr_metric; |
286 if (ioctl(sokfd, SIOCGIFMAP, &ifre) == 0) il->map = ifre.ifr_map; | 233 if (ioctl(TT.sockfd, SIOCGIFMTU, &ifre) >= 0) il->mtu = ifre.ifr_mtu; |
287 if (ioctl(sokfd, SIOCGIFTXQLEN, &ifre) >= 0) il->txqueuelen = ifre.ifr_qlen; | 234 if (ioctl(TT.sockfd, SIOCGIFMAP, &ifre) == 0) il->map = ifre.ifr_map; |
235 if (ioctl(TT.sockfd, SIOCGIFTXQLEN, &ifre) >= 0) | |
236 il->txqueuelen = ifre.ifr_qlen; | |
288 | 237 |
289 // If an address is assigned record that. | 238 // If an address is assigned record that. |
290 | 239 |
291 ifre.ifr_addr.sa_family = AF_INET; | 240 ifre.ifr_addr.sa_family = AF_INET; |
292 if (!ioctl(sokfd, SIOCGIFADDR, &ifre)) il->addr = ifre.ifr_addr; | 241 if (!ioctl(TT.sockfd, SIOCGIFADDR, &ifre)) il->addr = ifre.ifr_addr; |
293 if (ioctl(sokfd, SIOCGIFDSTADDR, &ifre) >= 0) il->dstaddr = ifre.ifr_dstaddr; | 242 if (ioctl(TT.sockfd, SIOCGIFDSTADDR, &ifre) >= 0) |
294 if (ioctl(sokfd, SIOCGIFBRDADDR, &ifre) >= 0) il->broadaddr = ifre.ifr_broadaddr; | 243 il->dstaddr = ifre.ifr_dstaddr; |
295 if (ioctl(sokfd, SIOCGIFNETMASK, &ifre) >= 0) il->netmask = ifre.ifr_netmask; | 244 if (ioctl(TT.sockfd, SIOCGIFBRDADDR, &ifre) >= 0) |
296 close(sokfd); | 245 il->broadaddr = ifre.ifr_broadaddr; |
297 } | 246 if (ioctl(TT.sockfd, SIOCGIFNETMASK, &ifre) >= 0) |
298 | 247 il->netmask = ifre.ifr_netmask; |
299 static void print_ip6_addr(struct if_list *il) | |
300 { | |
301 char iface_name[IFNAMSIZ] = {0,}; | |
302 int plen, scope; | |
303 FILE *fp; | |
304 | |
305 if(!(fp = fopen("/proc/net/if_net6", "r"))) return; | |
306 | |
307 while(fgets(toybuf, sizeof(toybuf), fp)) { | |
308 int nitems = 0; | |
309 char ipv6_addr[40] = {0,}; | |
310 nitems = sscanf(toybuf, "%32s %*08x %02x %02x %*02x %15s\n", | |
311 ipv6_addr+7, &plen, &scope, iface_name); | |
312 if(nitems != 4) { | |
313 if((nitems < 0) && feof(fp)) break; | |
314 perror_exit("sscanf"); | |
315 } | |
316 if(strcmp(il->name, iface_name) == 0) { | |
317 int i = 0; | |
318 struct sockaddr_in6 sock_in6; | |
319 int len = sizeof(ipv6_addr) / (sizeof ipv6_addr[0]); | |
320 char *ptr = ipv6_addr+7; | |
321 | |
322 while((i < len-2) && (*ptr)) { | |
323 ipv6_addr[i++] = *ptr++; | |
324 //put ':' after 4th bit | |
325 if(!((i+1) % 5)) ipv6_addr[i++] = ':'; | |
326 } | |
327 ipv6_addr[i+1] = '\0'; | |
328 if(inet_pton(AF_INET6, ipv6_addr, (struct sockaddr *) &sock_in6.sin6_addr) > 0) { | |
329 sock_in6.sin6_family = AF_INET6; | |
330 if(inet_ntop(AF_INET6, &sock_in6.sin6_addr, toybuf, BUFSIZ)) { | |
331 char *names[] = {"Global","Host","Link","Site","Compat"}, | |
332 *name = "Unknown"; | |
333 int j; | |
334 | |
335 for (j=0; j < sizeof(names)/sizeof(*names); j++) | |
336 if (scope == (!!j)<<(j+3)) name = names[j]; | |
337 xprintf("%10cinet6 addr: %s/%d Scope: %s\n", ' ', toybuf, plen, name); | |
338 } | |
339 } | |
340 } | |
341 } | |
342 fclose(fp); | |
343 } | 248 } |
344 | 249 |
345 static void display_ifconfig(struct if_list *il) | 250 static void display_ifconfig(struct if_list *il) |
346 { | 251 { |
347 struct { | 252 struct { |
352 {ARPHRD_PPP, "Point-to-Point Protocol"}, {ARPHRD_INFINIBAND, "InfiniBand"}, | 257 {ARPHRD_PPP, "Point-to-Point Protocol"}, {ARPHRD_INFINIBAND, "InfiniBand"}, |
353 {ARPHRD_SIT, "IPv6-in-IPv4"}, {-1, "UNSPEC"} | 258 {ARPHRD_SIT, "IPv6-in-IPv4"}, {-1, "UNSPEC"} |
354 }; | 259 }; |
355 int i; | 260 int i; |
356 char *p; | 261 char *p; |
262 FILE *fp; | |
357 | 263 |
358 for (i=0; i < (sizeof(types)/sizeof(*types))-1; i++) | 264 for (i=0; i < (sizeof(types)/sizeof(*types))-1; i++) |
359 if (il->hw_type == types[i].type) break; | 265 if (il->hw_type == types[i].type) break; |
360 | 266 |
361 xprintf("%-9s Link encap:%s ", il->name, types[i].title); | 267 xprintf("%-9s Link encap:%s ", il->name, types[i].title); |
392 } | 298 } |
393 | 299 |
394 xputc('\n'); | 300 xputc('\n'); |
395 } | 301 } |
396 | 302 |
397 print_ip6_addr(il); | 303 fp = fopen("/proc/net/if_net6", "r"); |
304 if (fp) { | |
305 char iface_name[IFNAMSIZ] = {0,}; | |
306 int plen, scope; | |
307 | |
308 while(fgets(toybuf, sizeof(toybuf), fp)) { | |
309 int nitems = 0; | |
310 char ipv6_addr[40] = {0,}; | |
311 nitems = sscanf(toybuf, "%32s %*08x %02x %02x %*02x %15s\n", | |
312 ipv6_addr+7, &plen, &scope, iface_name); | |
313 if(nitems != 4) { | |
314 if((nitems < 0) && feof(fp)) break; | |
315 perror_exit("sscanf"); | |
316 } | |
317 if(strcmp(il->name, iface_name) == 0) { | |
318 int i = 0; | |
319 struct sockaddr_in6 sock_in6; | |
320 int len = sizeof(ipv6_addr) / (sizeof ipv6_addr[0]); | |
321 char *ptr = ipv6_addr+7; | |
322 | |
323 while((i < len-2) && (*ptr)) { | |
324 ipv6_addr[i++] = *ptr++; | |
325 //put ':' after 4th bit | |
326 if(!((i+1) % 5)) ipv6_addr[i++] = ':'; | |
327 } | |
328 ipv6_addr[i+1] = '\0'; | |
329 if(inet_pton(AF_INET6, ipv6_addr, (struct sockaddr *) &sock_in6.sin6_addr) > 0) { | |
330 sock_in6.sin6_family = AF_INET6; | |
331 if(inet_ntop(AF_INET6, &sock_in6.sin6_addr, toybuf, BUFSIZ)) { | |
332 char *names[] = {"Global","Host","Link","Site","Compat"}, | |
333 *name = "Unknown"; | |
334 int j; | |
335 | |
336 for (j=0; j < sizeof(names)/sizeof(*names); j++) | |
337 if (scope == (!!j)<<(j+3)) name = names[j]; | |
338 xprintf("%10cinet6 addr: %s/%d Scope: %s\n", ' ', toybuf, plen, name); | |
339 } | |
340 } | |
341 } | |
342 } | |
343 fclose(fp); | |
344 } | |
345 | |
398 xprintf("%10c", ' '); | 346 xprintf("%10c", ' '); |
399 | 347 |
400 if (il->flags) { | 348 if (il->flags) { |
401 unsigned short mask = 1; | 349 unsigned short mask = 1; |
402 char **s, *str[] = { | 350 char **s, *str[] = { |
447 | 395 |
448 static void readconf(void) | 396 static void readconf(void) |
449 { | 397 { |
450 struct ifconf ifcon; | 398 struct ifconf ifcon; |
451 struct ifreq *ifre; | 399 struct ifreq *ifre; |
452 int num, sokfd; | 400 int num; |
453 | |
454 sokfd = xsocket(AF_INET, SOCK_DGRAM, 0); | |
455 | 401 |
456 // Loop until buffer's big enough | 402 // Loop until buffer's big enough |
457 ifcon.ifc_buf = NULL; | 403 ifcon.ifc_buf = NULL; |
458 for (num = 30;;num += 10) { | 404 for (num = 30;;num += 10) { |
459 ifcon.ifc_len = sizeof(struct ifreq)*num; | 405 ifcon.ifc_len = sizeof(struct ifreq)*num; |
460 ifcon.ifc_buf = xrealloc(ifcon.ifc_buf, ifcon.ifc_len); | 406 ifcon.ifc_buf = xrealloc(ifcon.ifc_buf, ifcon.ifc_len); |
461 xioctl(sokfd, SIOCGIFCONF, &ifcon); | 407 xioctl(TT.sockfd, SIOCGIFCONF, &ifcon); |
462 if (ifcon.ifc_len != sizeof(struct ifreq)*num) break; | 408 if (ifcon.ifc_len != sizeof(struct ifreq)*num) break; |
463 } | 409 } |
464 | 410 |
465 ifre = ifcon.ifc_req; | 411 ifre = ifcon.ifc_req; |
466 for(num = 0; num < ifcon.ifc_len && ifre; num += sizeof(struct ifreq), ifre++) | 412 for(num = 0; num < ifcon.ifc_len && ifre; num += sizeof(struct ifreq), ifre++) |
476 add_iface_to_list(il); | 422 add_iface_to_list(il); |
477 get_device_info(il); | 423 get_device_info(il); |
478 } | 424 } |
479 } | 425 } |
480 | 426 |
481 close(sokfd); | |
482 free(ifcon.ifc_buf); | 427 free(ifcon.ifc_buf); |
483 } | 428 } |
484 | 429 |
485 static void show_iface(char *iface_name) | 430 static void show_iface(char *iface_name) |
486 { | 431 { |
505 for (j=0; j<16 && !errno; j++) il->val[j] = strtoll(buf, &buf, 0); | 450 for (j=0; j<16 && !errno; j++) il->val[j] = strtoll(buf, &buf, 0); |
506 if (errno) perror_exit("bad %s at %s", name, buf); | 451 if (errno) perror_exit("bad %s at %s", name, buf); |
507 | 452 |
508 add_iface_to_list(il); | 453 add_iface_to_list(il); |
509 il->non_virtual_iface = 1; | 454 il->non_virtual_iface = 1; |
510 errno = 0; | |
511 get_device_info(il); | 455 get_device_info(il); |
512 } | 456 } |
513 fclose(fp); | 457 fclose(fp); |
514 | 458 |
515 if (iface_name) { | 459 if (iface_name) { |
521 } | 465 } |
522 //if the given interface is not in the list. | 466 //if the given interface is not in the list. |
523 if(!il) { | 467 if(!il) { |
524 il = xzalloc(sizeof(struct if_list)); | 468 il = xzalloc(sizeof(struct if_list)); |
525 xstrncpy(il->name, iface_name, IFNAMSIZ); | 469 xstrncpy(il->name, iface_name, IFNAMSIZ); |
526 errno = 0; | |
527 get_device_info(il); | 470 get_device_info(il); |
528 display_ifconfig(il); | 471 display_ifconfig(il); |
529 free(il); | 472 free(il); |
530 } | 473 } |
531 } else { | 474 } else { |
543 | 486 |
544 void ifconfig_main(void) | 487 void ifconfig_main(void) |
545 { | 488 { |
546 char **argv = toys.optargs; | 489 char **argv = toys.optargs; |
547 struct ifreq ifre; | 490 struct ifreq ifre; |
548 int i, sockfd = 0; | 491 int i; |
549 | 492 |
550 if(*argv && (strcmp(*argv, "--help") == 0)) show_help(); | 493 if(*argv && (strcmp(*argv, "--help") == 0)) show_help(); |
551 | 494 |
495 TT.sockfd = xsocket(AF_INET, SOCK_DGRAM, 0); | |
552 if(toys.optc < 2) { | 496 if(toys.optc < 2) { |
553 show_iface(*argv); | 497 show_iface(*argv); |
554 return; | 498 return; |
555 } | 499 } |
556 | 500 |
557 // Open interface | 501 // Open interface |
558 memset(&ifre, 0, sizeof(struct ifreq)); | 502 memset(&ifre, 0, sizeof(struct ifreq)); |
559 xstrncpy(ifre.ifr_name, *argv, IFNAMSIZ); | 503 xstrncpy(ifre.ifr_name, *argv, IFNAMSIZ); |
560 sockfd = xsocket(AF_INET, SOCK_DGRAM, 0); | |
561 | 504 |
562 // Perform operations on interface | 505 // Perform operations on interface |
563 while(*++argv) { | 506 while(*++argv) { |
564 struct argh { | 507 struct argh { |
565 char *name; | 508 char *name; |
576 {"pointopoint", IFF_POINTOPOINT, SIOCSIFDSTADDR}, | 519 {"pointopoint", IFF_POINTOPOINT, SIOCSIFDSTADDR}, |
577 {"broadcast", IFF_BROADCAST, SIOCSIFBRDADDR}, | 520 {"broadcast", IFF_BROADCAST, SIOCSIFBRDADDR}, |
578 {"netmask", 0, SIOCSIFNETMASK}, | 521 {"netmask", 0, SIOCSIFNETMASK}, |
579 {"dstaddr", 0, SIOCSIFDSTADDR}, | 522 {"dstaddr", 0, SIOCSIFDSTADDR}, |
580 {"mtu", IFREQ_OFFSZ(ifr_mtu), SIOCSIFMTU}, | 523 {"mtu", IFREQ_OFFSZ(ifr_mtu), SIOCSIFMTU}, |
581 {"keepalive", IFREQ_OFFSZ(ifr_data), SIOCSKEEPALIVE}, | 524 {"keepalive", IFREQ_OFFSZ(ifr_data), SIOCDEVPRIVATE}, // SIOCSKEEPALIVE |
582 {"outfill", IFREQ_OFFSZ(ifr_data), SIOCSOUTFILL}, | 525 {"outfill", IFREQ_OFFSZ(ifr_data), SIOCDEVPRIVATE+2}, // SIOCSOUTFILL |
583 {"metric", IFREQ_OFFSZ(ifr_metric), SIOCSIFMETRIC}, | 526 {"metric", IFREQ_OFFSZ(ifr_metric), SIOCSIFMETRIC}, |
584 {"txqueuelen", IFREQ_OFFSZ(ifr_qlen), SIOCSIFTXQLEN}, | 527 {"txqueuelen", IFREQ_OFFSZ(ifr_qlen), SIOCSIFTXQLEN}, |
585 {"mem_start", IFREQ_OFFSZ(ifr_map.mem_start), SIOCSIFMAP}, | 528 {"mem_start", IFREQ_OFFSZ(ifr_map.mem_start), SIOCSIFMAP}, |
586 {"io_addr", IFREQ_OFFSZ(ifr_map.base_addr), SIOCSIFMAP}, | 529 {"io_addr", IFREQ_OFFSZ(ifr_map.base_addr), SIOCSIFMAP}, |
587 {"irq", IFREQ_OFFSZ(ifr_map.irq), SIOCSIFMAP}, | 530 {"irq", IFREQ_OFFSZ(ifr_map.irq), SIOCSIFMAP}, |
606 | 549 |
607 // Assign value to ifre field and call ioctl? (via IFREQ_OFFSZ.) | 550 // Assign value to ifre field and call ioctl? (via IFREQ_OFFSZ.) |
608 if (on < 0) { | 551 if (on < 0) { |
609 long l = strtoul(*argv, 0, 0); | 552 long l = strtoul(*argv, 0, 0); |
610 | 553 |
611 if (off == SIOCSIFMAP) xioctl(sockfd, SIOCGIFMAP, &ifre); | 554 if (off == SIOCSIFMAP) xioctl(TT.sockfd, SIOCGIFMAP, &ifre); |
612 on = -on; | 555 on = -on; |
613 poke((on>>16) + (char *)&ifre, l, on&15); | 556 poke((on>>16) + (char *)&ifre, l, on&15); |
614 xioctl(sockfd, off, &ifre); | 557 xioctl(TT.sockfd, off, &ifre); |
615 break; | 558 break; |
616 } else set_address(sockfd, *argv, &ifre, off); | 559 } else set_address(*argv, &ifre, off); |
617 } | 560 } |
618 off = 0; | 561 off = 0; |
619 } | 562 } |
620 | 563 |
621 // Set flags | 564 // Set flags |
622 if (on || off) { | 565 if (on || off) { |
623 xioctl(sockfd, SIOCGIFFLAGS, &ifre); | 566 xioctl(TT.sockfd, SIOCGIFFLAGS, &ifre); |
624 ifre.ifr_flags &= ~(rev ? on : off); | 567 ifre.ifr_flags &= ~(rev ? on : off); |
625 ifre.ifr_flags |= (rev ? off : on); | 568 ifre.ifr_flags |= (rev ? off : on); |
626 xioctl(sockfd, SIOCSIFFLAGS, &ifre); | 569 xioctl(TT.sockfd, SIOCSIFFLAGS, &ifre); |
627 } | 570 } |
628 | 571 |
629 break; | 572 break; |
630 } | 573 } |
631 if (i != sizeof(try)/sizeof(*try)) continue; | 574 if (i != sizeof(try)/sizeof(*try)) continue; |
660 *p++ = val; | 603 *p++ = val; |
661 } | 604 } |
662 | 605 |
663 if ((p-ptr) != count || *hw_addr) | 606 if ((p-ptr) != count || *hw_addr) |
664 error_exit("bad hw-addr '%s'", hw_addr ? hw_addr : ""); | 607 error_exit("bad hw-addr '%s'", hw_addr ? hw_addr : ""); |
665 xioctl(sockfd, SIOCSIFHWADDR, &ifre); | 608 xioctl(TT.sockfd, SIOCSIFHWADDR, &ifre); |
609 | |
610 // Add/remove ipv6 address to interface | |
666 | 611 |
667 } else if (!strcmp(*argv, "add") || !strcmp(*argv, "del")) { | 612 } else if (!strcmp(*argv, "add") || !strcmp(*argv, "del")) { |
613 sockaddr_with_len *swl = NULL; | |
614 struct ifreq_inet6 ifre6; | |
615 char *prefix; | |
616 int plen = 0, sockfd6 = xsocket(AF_INET6, SOCK_DGRAM, 0); | |
617 | |
668 if (!argv[1]) show_help(); | 618 if (!argv[1]) show_help(); |
669 set_ipv6_addr(sockfd, &ifre, argv[1], | 619 |
670 **argv=='a' ? SIOCSIFADDR : SIOCDIFADDR); | 620 prefix = strchr(argv[1], '/'); |
621 if (prefix) { | |
622 plen = get_int_value(prefix + 1, 0, 128); | |
623 *prefix = 0; | |
624 } | |
625 swl = get_sockaddr(argv[1], 0, AF_INET6); | |
626 ifre6.ifrinte6_addr = swl->sock_u.sock_in6.sin6_addr; | |
627 xioctl(sockfd6, SIOCGIFINDEX, &ifre); | |
628 ifre6.ifrinet6_ifindex = ifre.ifr_ifindex; | |
629 ifre6.ifrinet6_prefixlen = plen; | |
630 xioctl(sockfd6, **argv=='a' ? SIOCSIFADDR : SIOCDIFADDR, &ifre6); | |
631 | |
632 free(swl); | |
633 close(sockfd6); | |
634 | |
671 argv++; | 635 argv++; |
672 } else if (isdigit(**argv) || !strcmp(*argv, "default")) { | 636 } else if (isdigit(**argv) || !strcmp(*argv, "default")) { |
673 set_address(sockfd, *argv, &ifre, SIOCSIFADDR); | 637 set_address(*argv, &ifre, SIOCSIFADDR); |
674 //if the interface name is not an alias; set the flag and continue. | 638 //if the interface name is not an alias; set the flag and continue. |
675 if(!strchr(ifre.ifr_name, ':')) { | 639 if(!strchr(ifre.ifr_name, ':')) { |
676 xioctl(sockfd, SIOCGIFFLAGS, &ifre); | 640 xioctl(TT.sockfd, SIOCGIFFLAGS, &ifre); |
677 ifre.ifr_flags |= IFF_UP|IFF_RUNNING; | 641 ifre.ifr_flags |= IFF_UP|IFF_RUNNING; |
678 xioctl(sockfd, SIOCSIFFLAGS, &ifre); | 642 xioctl(TT.sockfd, SIOCSIFFLAGS, &ifre); |
679 } | 643 } |
680 | 644 |
681 } else { | 645 } else { |
682 errno = EINVAL; | 646 errno = EINVAL; |
683 toys.exithelp++; | 647 toys.exithelp++; |
684 error_exit("bad argument '%s'", *argv); | 648 error_exit("bad argument '%s'", *argv); |
685 } | 649 } |
686 } | 650 } |
687 if (CFG_TOYBOX_FREE && sockfd > 0) close(sockfd); | 651 close(TT.sockfd); |
688 } | 652 } |