Mercurial > hg > toybox
comparison toys/pending/ifconfig.c @ 957:1ec29d7540e2
Another round of ifconfig cleanup.
author | Rob Landley <rob@landley.net> |
---|---|
date | Fri, 19 Jul 2013 05:33:36 -0500 |
parents | 6a37f642b572 |
children | 019f54d50c8b |
comparison
equal
deleted
inserted
replaced
956:caa05719070f | 957:1ec29d7540e2 |
---|---|
34 | 34 |
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; | |
40 | |
41 int sockfd; | 39 int sockfd; |
42 ) | 40 ) |
43 | 41 |
44 typedef struct sockaddr_with_len { | 42 typedef struct sockaddr_with_len { |
45 union { | 43 union { |
46 struct sockaddr sock; | 44 struct sockaddr sock; |
47 struct sockaddr_in sock_in; | 45 struct sockaddr_in sock_in; |
48 struct sockaddr_in6 sock_in6; | 46 struct sockaddr_in6 sock_in6; |
49 }sock_u; | 47 } sock_u; |
50 socklen_t socklen; | |
51 } sockaddr_with_len; | 48 } sockaddr_with_len; |
52 | 49 |
53 // man netdevice | 50 // man netdevice |
54 struct if_list { | 51 struct if_list { |
55 struct if_list *next; | 52 struct if_list *next; |
86 | 83 |
87 if (!strncmp(host, "local:", 6)) { | 84 if (!strncmp(host, "local:", 6)) { |
88 struct sockaddr_un *sockun; | 85 struct sockaddr_un *sockun; |
89 | 86 |
90 swl = xzalloc(sizeof(struct sockaddr_with_len)); | 87 swl = xzalloc(sizeof(struct sockaddr_with_len)); |
91 swl->socklen = sizeof(struct sockaddr_un); | |
92 swl->sock_u.sock.sa_family = AF_UNIX; | 88 swl->sock_u.sock.sa_family = AF_UNIX; |
93 sockun = (struct sockaddr_un *)&swl->sock_u.sock; | 89 sockun = (struct sockaddr_un *)&swl->sock_u.sock; |
94 xstrncpy(sockun->sun_path, host + 6, sizeof(sockun->sun_path)); | 90 xstrncpy(sockun->sun_path, host + 6, sizeof(sockun->sun_path)); |
95 | 91 |
96 return swl; | 92 return swl; |
126 if (status) error_exit("bad address '%s' : %s", host, gai_strerror(status)); | 122 if (status) error_exit("bad address '%s' : %s", host, gai_strerror(status)); |
127 | 123 |
128 for (rp = result; rp; rp = rp->ai_next) { | 124 for (rp = result; rp; rp = rp->ai_next) { |
129 if (rp->ai_family == AF_INET || rp->ai_family == AF_INET6) { | 125 if (rp->ai_family == AF_INET || rp->ai_family == AF_INET6) { |
130 swl = xmalloc(sizeof(struct sockaddr_with_len)); | 126 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); | 127 memcpy(&swl->sock_u.sock, rp->ai_addr, rp->ai_addrlen); |
133 break; | 128 break; |
134 } | 129 } |
135 } | 130 } |
136 freeaddrinfo(result); | 131 freeaddrinfo(result); |
137 if (!rp) error_exit("bad host name"); | 132 if (!rp) error_exit("bad host name"); |
138 | |
139 | 133 |
140 if(swl->sock_u.sock.sa_family == AF_INET) | 134 if(swl->sock_u.sock.sa_family == AF_INET) |
141 swl->sock_u.sock_in.sin_port = port_num; | 135 swl->sock_u.sock_in.sin_port = port_num; |
142 else if(swl->sock_u.sock.sa_family == AF_INET6) | 136 else if(swl->sock_u.sock.sa_family == AF_INET6) |
143 swl->sock_u.sock_in6.sin6_port = port_num; | 137 swl->sock_u.sock_in6.sin6_port = port_num; |
144 | 138 |
145 return swl; | 139 return swl; |
146 } | |
147 | |
148 /* | |
149 * get the numeric hostname and service name, for a given socket address. | |
150 */ | |
151 char *address_to_name(struct sockaddr *sock) | |
152 { | |
153 //man page of getnameinfo. | |
154 char hbuf[NI_MAXHOST] = {0,}, sbuf[NI_MAXSERV] = {0,}; | |
155 int status = 0; | |
156 | |
157 if(sock->sa_family == AF_INET) { | |
158 socklen_t len = sizeof(struct sockaddr_in); | |
159 if((status = getnameinfo(sock, len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0) | |
160 return xmsprintf("%s:%s", hbuf, sbuf); | |
161 else { | |
162 fprintf(stderr, "getnameinfo: %s\n", gai_strerror(status)); | |
163 return NULL; | |
164 } | |
165 } else if(sock->sa_family == AF_INET6) { | |
166 socklen_t len = sizeof(struct sockaddr_in6); | |
167 if((status = getnameinfo(sock, len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0) { | |
168 //verification for resolved hostname. | |
169 if(strchr(hbuf, ':')) return xmsprintf("[%s]:%s", hbuf, sbuf); | |
170 else return xmsprintf("%s:%s", hbuf, sbuf); | |
171 } else { | |
172 fprintf(stderr, "getnameinfo: %s\n", gai_strerror(status)); | |
173 return NULL; | |
174 } | |
175 } else if(sock->sa_family == AF_UNIX) { | |
176 struct sockaddr_un *sockun = (void*)sock; | |
177 return xmsprintf("local:%.*s", (int) sizeof(sockun->sun_path), sockun->sun_path); | |
178 } else return NULL; | |
179 } | 140 } |
180 | 141 |
181 static void set_address(char *host_name, struct ifreq *ifre, int request) | 142 static void set_address(char *host_name, struct ifreq *ifre, int request) |
182 { | 143 { |
183 struct sockaddr_in *sock_in = (struct sockaddr_in *)&ifre->ifr_addr; | 144 struct sockaddr_in *sock_in = (struct sockaddr_in *)&ifre->ifr_addr; |
194 free(swl); | 155 free(swl); |
195 } | 156 } |
196 xioctl(TT.sockfd, request, ifre); | 157 xioctl(TT.sockfd, request, ifre); |
197 } | 158 } |
198 | 159 |
199 static void add_iface_to_list(struct if_list *newnode) | 160 static void get_device_info(char *name, struct if_list *il) |
200 { | |
201 struct if_list *head_ref = TT.if_list; | |
202 | |
203 if(!head_ref || strcmp(newnode->name, head_ref->name) < 0) { | |
204 newnode->next = head_ref; | |
205 head_ref = newnode; | |
206 } else { | |
207 struct if_list *current = head_ref; | |
208 while(current->next && strcmp(current->next->name, newnode->name) < 0) | |
209 current = current->next; | |
210 newnode->next = current->next; | |
211 current->next = newnode; | |
212 } | |
213 TT.if_list = (void *)head_ref; | |
214 } | |
215 | |
216 static void get_device_info(struct if_list *il) | |
217 { | 161 { |
218 struct ifreq ifre; | 162 struct ifreq ifre; |
219 char *name = il->name; | |
220 | 163 |
221 il->txqueuelen = -1; | 164 il->txqueuelen = -1; |
222 | 165 |
223 xstrncpy(ifre.ifr_name, name, IFNAMSIZ); | 166 xstrncpy(ifre.ifr_name, name, IFNAMSIZ); |
224 if (ioctl(TT.sockfd, SIOCGIFFLAGS, &ifre)<0) perror_exit("%s", il->name); | 167 if (ioctl(TT.sockfd, SIOCGIFFLAGS, &ifre)<0) perror_exit("%s", il->name); |
245 il->broadaddr = ifre.ifr_broadaddr; | 188 il->broadaddr = ifre.ifr_broadaddr; |
246 if (ioctl(TT.sockfd, SIOCGIFNETMASK, &ifre) >= 0) | 189 if (ioctl(TT.sockfd, SIOCGIFNETMASK, &ifre) >= 0) |
247 il->netmask = ifre.ifr_netmask; | 190 il->netmask = ifre.ifr_netmask; |
248 } | 191 } |
249 | 192 |
250 static void display_ifconfig(struct if_list *il) | 193 static void display_ifconfig(char *name, struct if_list *il) |
251 { | 194 { |
252 struct { | 195 struct { |
253 int type; | 196 int type; |
254 char *title; | 197 char *title; |
255 } types[] = { | 198 } types[] = { |
262 FILE *fp; | 205 FILE *fp; |
263 | 206 |
264 for (i=0; i < (sizeof(types)/sizeof(*types))-1; i++) | 207 for (i=0; i < (sizeof(types)/sizeof(*types))-1; i++) |
265 if (il->hw_type == types[i].type) break; | 208 if (il->hw_type == types[i].type) break; |
266 | 209 |
267 xprintf("%-9s Link encap:%s ", il->name, types[i].title); | 210 xprintf("%-9s Link encap:%s ", name, types[i].title); |
268 if(il->hwaddr.sa_data && il->hw_type == ARPHRD_ETHER) { | 211 if(il->hwaddr.sa_data && il->hw_type == ARPHRD_ETHER) { |
269 xprintf("HWaddr "); | 212 xprintf("HWaddr "); |
270 for (i=0; i<6; i++) xprintf(":%02X"+!i, il->hwaddr.sa_data[i]); | 213 for (i=0; i<6; i++) xprintf(":%02X"+!i, il->hwaddr.sa_data[i]); |
271 } | 214 } |
272 xputc('\n'); | 215 xputc('\n'); |
301 } | 244 } |
302 | 245 |
303 fp = fopen("/proc/net/if_net6", "r"); | 246 fp = fopen("/proc/net/if_net6", "r"); |
304 if (fp) { | 247 if (fp) { |
305 char iface_name[IFNAMSIZ] = {0,}; | 248 char iface_name[IFNAMSIZ] = {0,}; |
306 int plen, scope; | 249 int plen, iscope; |
307 | 250 |
308 while(fgets(toybuf, sizeof(toybuf), fp)) { | 251 while(fgets(toybuf, sizeof(toybuf), fp)) { |
309 int nitems = 0; | 252 int nitems = 0; |
310 char ipv6_addr[40] = {0,}; | 253 char ipv6_addr[40] = {0,}; |
311 nitems = sscanf(toybuf, "%32s %*08x %02x %02x %*02x %15s\n", | 254 nitems = sscanf(toybuf, "%32s %*08x %02x %02x %*02x %15s\n", |
312 ipv6_addr+7, &plen, &scope, iface_name); | 255 ipv6_addr+7, &plen, &iscope, iface_name); |
313 if(nitems != 4) { | 256 if(nitems != 4) { |
314 if((nitems < 0) && feof(fp)) break; | 257 if((nitems < 0) && feof(fp)) break; |
315 perror_exit("sscanf"); | 258 perror_exit("sscanf"); |
316 } | 259 } |
317 if(strcmp(il->name, iface_name) == 0) { | 260 if(strcmp(name, iface_name) == 0) { |
318 int i = 0; | 261 int i = 0; |
319 struct sockaddr_in6 sock_in6; | 262 struct sockaddr_in6 sock_in6; |
320 int len = sizeof(ipv6_addr) / (sizeof ipv6_addr[0]); | 263 int len = sizeof(ipv6_addr) / (sizeof ipv6_addr[0]); |
321 char *ptr = ipv6_addr+7; | 264 char *ptr = ipv6_addr+7; |
322 | 265 |
327 } | 270 } |
328 ipv6_addr[i+1] = '\0'; | 271 ipv6_addr[i+1] = '\0'; |
329 if(inet_pton(AF_INET6, ipv6_addr, (struct sockaddr *) &sock_in6.sin6_addr) > 0) { | 272 if(inet_pton(AF_INET6, ipv6_addr, (struct sockaddr *) &sock_in6.sin6_addr) > 0) { |
330 sock_in6.sin6_family = AF_INET6; | 273 sock_in6.sin6_family = AF_INET6; |
331 if(inet_ntop(AF_INET6, &sock_in6.sin6_addr, toybuf, BUFSIZ)) { | 274 if(inet_ntop(AF_INET6, &sock_in6.sin6_addr, toybuf, BUFSIZ)) { |
332 char *names[] = {"Global","Host","Link","Site","Compat"}, | 275 char *scopes[] = {"Global","Host","Link","Site","Compat"}, |
333 *name = "Unknown"; | 276 *scope = "Unknown"; |
334 int j; | 277 int j; |
335 | 278 |
336 for (j=0; j < sizeof(names)/sizeof(*names); j++) | 279 for (j=0; j < sizeof(scopes)/sizeof(*scopes); j++) |
337 if (scope == (!!j)<<(j+3)) name = names[j]; | 280 if (iscope == (!!j)<<(j+3)) scope = scopes[j]; |
338 xprintf("%10cinet6 addr: %s/%d Scope: %s\n", ' ', toybuf, plen, name); | 281 xprintf("%10cinet6 addr: %s/%d Scope: %s\n", ' ', toybuf, plen, scope); |
339 } | 282 } |
340 } | 283 } |
341 } | 284 } |
342 } | 285 } |
343 fclose(fp); | 286 fclose(fp); |
391 xputc('\n'); | 334 xputc('\n'); |
392 } | 335 } |
393 xputc('\n'); | 336 xputc('\n'); |
394 } | 337 } |
395 | 338 |
396 static void readconf(void) | |
397 { | |
398 struct ifconf ifcon; | |
399 struct ifreq *ifre; | |
400 int num; | |
401 | |
402 // Loop until buffer's big enough | |
403 ifcon.ifc_buf = NULL; | |
404 for (num = 30;;num += 10) { | |
405 ifcon.ifc_len = sizeof(struct ifreq)*num; | |
406 ifcon.ifc_buf = xrealloc(ifcon.ifc_buf, ifcon.ifc_len); | |
407 xioctl(TT.sockfd, SIOCGIFCONF, &ifcon); | |
408 if (ifcon.ifc_len != sizeof(struct ifreq)*num) break; | |
409 } | |
410 | |
411 ifre = ifcon.ifc_req; | |
412 for(num = 0; num < ifcon.ifc_len && ifre; num += sizeof(struct ifreq), ifre++) | |
413 { | |
414 struct if_list *il; | |
415 | |
416 // Skip duplicates | |
417 for(il = TT.if_list; il; il = il->next) | |
418 if(!strcmp(ifre->ifr_name, il->name)) break; | |
419 if(!il) { | |
420 il = xzalloc(sizeof(struct if_list)); | |
421 xstrncpy(il->name, ifre->ifr_name, IFNAMSIZ); | |
422 add_iface_to_list(il); | |
423 get_device_info(il); | |
424 } | |
425 } | |
426 | |
427 free(ifcon.ifc_buf); | |
428 } | |
429 | |
430 static void show_iface(char *iface_name) | 339 static void show_iface(char *iface_name) |
431 { | 340 { |
432 struct if_list *il; | 341 char *name; |
342 struct if_list il; | |
343 struct string_list *ifaces = 0, *sl; | |
433 int i, j; | 344 int i, j; |
434 FILE *fp; | 345 FILE *fp; |
435 | 346 |
436 fp = xfopen("/proc/net/dev", "r"); | 347 fp = xfopen("/proc/net/dev", "r"); |
437 | 348 |
438 for (i=0; fgets(toybuf, sizeof(toybuf), fp); i++) { | 349 for (i=0; fgets(toybuf, sizeof(toybuf), fp); i++) { |
439 char *name, *buf; | 350 char *buf = toybuf; |
440 | 351 |
441 if (i<2) continue; | 352 if (i<2) continue; |
442 | 353 |
443 il = xzalloc(sizeof(struct if_list)); | 354 while (isspace(*buf)) buf++; |
444 for (buf = toybuf; isspace(*buf); buf++); | |
445 name = strsep(&buf, ":"); | 355 name = strsep(&buf, ":"); |
446 if(!buf) error_exit("bad name %s", name); | 356 if(!buf) error_exit("bad name %s", name); |
447 xstrncpy(il->name, name, IFNAMSIZ); | |
448 | 357 |
449 errno = 0; | 358 errno = 0; |
450 for (j=0; j<16 && !errno; j++) il->val[j] = strtoll(buf, &buf, 0); | 359 for (j=0; j<16 && !errno; j++) il.val[j] = strtoll(buf, &buf, 0); |
451 if (errno) perror_exit("bad %s at %s", name, buf); | 360 if (errno) perror_exit("bad %s at %s", name, buf); |
452 | 361 |
453 add_iface_to_list(il); | 362 il.non_virtual_iface = 1; |
454 il->non_virtual_iface = 1; | 363 |
455 get_device_info(il); | 364 if (iface_name) { |
365 if (!strcmp(iface_name, name)) { | |
366 get_device_info(name, &il); | |
367 display_ifconfig(name, &il); | |
368 | |
369 return; | |
370 } | |
371 } else { | |
372 sl = xmalloc(sizeof(*sl)+strlen(name)+1); | |
373 strcpy(sl->str, name); | |
374 sl->next = ifaces; | |
375 ifaces = sl; | |
376 | |
377 get_device_info(name, &il); | |
378 if ((il.flags & IFF_UP) || (toys.optflags & FLAG_a)) | |
379 display_ifconfig(name, &il); | |
380 } | |
456 } | 381 } |
457 fclose(fp); | 382 fclose(fp); |
458 | 383 |
459 if (iface_name) { | 384 if (iface_name) { |
460 for(il = TT.if_list; il; il = il->next) { | 385 get_device_info(iface_name, &il); |
461 if(!strcmp(il->name, iface_name)) { | 386 display_ifconfig(iface_name, &il); |
462 display_ifconfig(il); | 387 } else { |
463 break; | 388 struct ifconf ifcon; |
389 struct ifreq *ifre; | |
390 int num; | |
391 | |
392 // Loop until buffer's big enough | |
393 ifcon.ifc_buf = NULL; | |
394 for (num = 30;;num += 10) { | |
395 ifcon.ifc_len = sizeof(struct ifreq)*num; | |
396 ifcon.ifc_buf = xrealloc(ifcon.ifc_buf, ifcon.ifc_len); | |
397 xioctl(TT.sockfd, SIOCGIFCONF, &ifcon); | |
398 if (ifcon.ifc_len != sizeof(struct ifreq)*num) break; | |
399 } | |
400 | |
401 ifre = ifcon.ifc_req; | |
402 for(num = 0; num < ifcon.ifc_len && ifre; num += sizeof(struct ifreq), ifre++) | |
403 { | |
404 // Skip duplicates | |
405 for(sl = ifaces; sl; sl = sl->next) | |
406 if(!strcmp(sl->str, ifre->ifr_name)) break; | |
407 | |
408 if(!sl) { | |
409 get_device_info(ifre->ifr_name, &il); | |
410 if ((il.flags & IFF_UP) || (toys.optflags & FLAG_a)) | |
411 display_ifconfig(ifre->ifr_name, &il); | |
464 } | 412 } |
465 } | 413 } |
466 //if the given interface is not in the list. | 414 |
467 if(!il) { | 415 free(ifcon.ifc_buf); |
468 il = xzalloc(sizeof(struct if_list)); | 416 } |
469 xstrncpy(il->name, iface_name, IFNAMSIZ); | 417 |
470 get_device_info(il); | 418 llist_traverse(ifaces, free); |
471 display_ifconfig(il); | |
472 free(il); | |
473 } | |
474 } else { | |
475 readconf(); | |
476 for(il = TT.if_list; il; il = il->next) | |
477 if((il->flags & IFF_UP) || (toys.optflags & FLAG_a)) | |
478 display_ifconfig(il); | |
479 } | |
480 | |
481 if (CFG_TOYBOX_FREE) llist_traverse(TT.if_list, free); | |
482 } | 419 } |
483 | 420 |
484 // Encode offset and size of field into an int, and make result negative | 421 // Encode offset and size of field into an int, and make result negative |
485 #define IFREQ_OFFSZ(x) -(int)((offsetof(struct ifreq, x)<<16) + sizeof(ifre.x)) | 422 #define IFREQ_OFFSZ(x) -(int)((offsetof(struct ifreq, x)<<16) + sizeof(ifre.x)) |
486 | 423 |