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