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 }