comparison toys/pending/ifconfig.c @ 841:cb0c3a773437

Kyungwan Han submitted ifconfig.
author Rob Landley <rob@landley.net>
date Tue, 02 Apr 2013 01:58:18 -0500
parents
children af5aab6e6678
comparison
equal deleted inserted replaced
-1:000000000000 0:a806e9922ac2
1 /* ifconfig.c - Configure network interface.
2 *
3 * Copyright 2012 Ranjan Kumar <ranjankumar.bth@gmail.com>, Kyungwan Han <asura321@gamil.com>
4 * Reviewed by Kyungsu Kim, Kyungwan Han <asura321@gamil.com>
5 *
6 * Not in SUSv4.
7 *
8 USE_IFCONFIG(NEWTOY(ifconfig, "?a", TOYFLAG_BIN))
9 config IFCONFIG
10 bool "ifconfig"
11 default y
12 help
13 usage: ifconfig [-a] interface [address]
14
15 Configure network interface.
16
17 [add ADDRESS[/PREFIXLEN]]
18 [del ADDRESS[/PREFIXLEN]]
19 [[-]broadcast [ADDRESS]] [[-]pointopoint [ADDRESS]]
20 [netmask ADDRESS] [dstaddr ADDRESS]
21 [outfill NN] [keepalive NN]
22 [hw ether|infiniband ADDRESS] [metric NN] [mtu NN]
23 [[-]trailers] [[-]arp] [[-]allmulti]
24 [multicast] [[-]promisc] [txqueuelen NN] [[-]dynamic]
25 [mem_start NN] [io_addr NN] [irq NN]
26 [up|down] ...
27 */
28
29 #define FOR_ifconfig
30 #include "toys.h"
31 #include "toynet.h"
32 #include <net/route.h>
33 #include <stddef.h>
34 #include <sys/un.h>
35 #include <net/if.h>
36 #include <net/if_arp.h>
37 #include <net/ethernet.h>
38 #include <alloca.h>
39
40 #define TRUE ((int) 1)
41 #define HTTP_DEFAULT_PORT 80
42 #define FTP_DEFAULT_PORT 21
43
44 #ifndef MAX_PORT_VALUE
45 #define MAX_PORT_VALUE 65535
46 #endif
47
48 typedef struct sockaddr_with_len {
49 union {
50 struct sockaddr sock;
51 struct sockaddr_in sock_in;
52 struct sockaddr_in6 sock_in6;
53 }sock_u;
54 socklen_t socklen;
55 }sockaddr_with_len;
56
57 //Function Declaration.
58 int get_hostname(const char *, struct sockaddr_in *);
59 int get_addrinfo(const char *, struct sockaddr_in6 *);
60 void get_flag_value(char **, int);
61 void display_routes(int, int);
62 unsigned getport(const char *, const char *, unsigned);
63 void setport(struct sockaddr *, unsigned);
64 int connect_to_stream(const sockaddr_with_len *);
65 unsigned get_strtou(const char *, char **, int);
66 char *address_to_name(const struct sockaddr *);
67 sockaddr_with_len *get_sockaddr(const char *, int, sa_family_t);
68
69 //Structure Declaration
70 typedef struct _proc_net_dev_info {
71 char ifrname[IFNAMSIZ]; //interface name.
72 unsigned long long receive_bytes; //total bytes received
73 unsigned long long receive_packets; //total packets received
74 unsigned long receive_errors; //bad packets received
75 unsigned long receive_drop; //no space in linux buffers
76 unsigned long receive_fifo; //receiver fifo overrun
77 unsigned long receive_frame; //received frame alignment error
78 unsigned long receive_compressed;
79 unsigned long receive_multicast; //multicast packets received
80
81 unsigned long long transmit_bytes; //total bytes transmitted
82 unsigned long long transmit_packets; //total packets transmitted
83 unsigned long transmit_errors; //packet transmit problems
84 unsigned long transmit_drop; //no space available in linux
85 unsigned long transmit_fifo;
86 unsigned long transmit_colls;
87 unsigned long transmit_carrier;
88 unsigned long transmit_compressed; //num_tr_compressed;
89 }PROC_NET_DEV_INFO;
90
91 //man netdevice
92 typedef struct _iface_list {
93 int hw_type;
94 short ifrflags; //used for addr, broadcast, and mask.
95 short ifaddr; //if set print ifraddr, irrdstaddr, ifrbroadaddr and ifrnetmask.
96 struct sockaddr ifraddr;
97 struct sockaddr ifrdstaddr;
98 struct sockaddr ifrbroadaddr;
99 struct sockaddr ifrnetmask;
100 struct sockaddr ifrhwaddr;
101 int ifrmtu;
102 int ifrmetric;
103 PROC_NET_DEV_INFO dev_info;
104 int txqueuelen;
105 struct ifmap ifrmap;
106 struct _iface_list *next; //, *prev;
107 }IFACE_LIST;
108
109
110 #define HW_NAME_LEN 20
111 #define HW_TITLE_LEN 30
112
113 typedef struct _hw_info {
114 char hw_name[HW_NAME_LEN];
115 char hw_title[HW_TITLE_LEN];
116 int hw_addrlen;
117 }HW_INFO;
118
119 static const char *const field_format[] = {
120 "%n%llu%u%u%u%u%n%n%n%llu%u%u%u%u%u",
121 "%llu%llu%u%u%u%u%n%n%llu%llu%u%u%u%u%u",
122 "%llu%llu%u%u%u%u%u%u%llu%llu%u%u%u%u%u%u"
123 };
124
125 #define PROC_NET_DEV "/proc/net/dev"
126 #define PROC_NET_IFINET6 "/proc/net/if_inet6"
127 #define NO_RANGE -1
128 #define IO_MAP_INDEX 0x100
129
130 static int show_iface(char *iface_name);
131 static void print_ip6_addr(IFACE_LIST *l_ptr);
132 static void clear_list(void);
133
134 //from /net/if.h
135 static char *iface_flags_str[] = {
136 "UP",
137 "BROADCAST",
138 "DEBUG",
139 "LOOPBACK",
140 "POINTOPOINT",
141 "NOTRAILERS",
142 "RUNNING",
143 "NOARP",
144 "PROMISC",
145 "ALLMULTI",
146 "MASTER",
147 "SLAVE",
148 "MULTICAST",
149 "PORTSEL",
150 "AUTOMEDIA",
151 "DYNAMIC",
152 NULL
153 };
154 //from /usr/include/linux/netdevice.h
155 #ifdef IFF_PORTSEL
156 //Media selection options.
157 # ifndef IF_PORT_UNKNOWN
158 enum {
159 IF_PORT_UNKNOWN = 0,
160 IF_PORT_10BASE2,
161 IF_PORT_10BASET,
162 IF_PORT_AUI,
163 IF_PORT_100BASET,
164 IF_PORT_100BASETX,
165 IF_PORT_100BASEFX
166 };
167 # endif
168 #endif
169
170 //from kernel header ipv6.h
171 #define IPV6_ADDR_ANY 0x0000U
172 #define IPV6_ADDR_LOOPBACK 0x0010U
173 #define IPV6_ADDR_LINKLOCAL 0x0020U
174 #define IPV6_ADDR_SITELOCAL 0x0040U
175 #define IPV6_ADDR_COMPATv4 0x0080U
176
177 //==================================================================================
178 //for the param settings.
179
180 //for ipv6 add/del
181 struct ifreq_inet6 {
182 struct in6_addr ifrinte6_addr;
183 uint32_t ifrinet6_prefixlen;
184 int ifrinet6_ifindex;
185 };
186
187 #ifndef SIOCSKEEPALIVE
188 # define SIOCSKEEPALIVE (SIOCDEVPRIVATE) /* Set keepalive timeout in sec */
189 # define SIOCGKEEPALIVE (SIOCDEVPRIVATE+1) /* Get keepalive timeout */
190 #endif
191
192 #ifndef SIOCSOUTFILL
193 # define SIOCSOUTFILL (SIOCDEVPRIVATE+2) /* Set outfill timeout */
194 # define SIOCGOUTFILL (SIOCDEVPRIVATE+3) /* Get outfill timeout */
195 #endif
196
197 #ifndef INFINIBAND_ALEN
198 # define INFINIBAND_ALEN 20
199 #endif
200
201 static void set_data(int sockfd, struct ifreq *ifre, char *kval, int request, const char *req_name);
202 static void set_flags(int sockfd, struct ifreq *ifre, int arg_flag, int flag); //verify
203 static void set_mtu(int sockfd, struct ifreq *ifre, const char *mtu); //verify
204 static void set_metric(int sockfd, struct ifreq *ifre, const char *metric); //verify
205 static void set_qlen(int sockfd, struct ifreq *ifre, const char *qlen); //verify
206 static void set_address(int sockfd, const char *host_name, struct ifreq *ifre, int request, const char *req_name);
207 static void set_hw_address(int sockfd, char ***argv, struct ifreq *ifre, int request, const char *req_name);
208 static void set_ipv6_addr(int sockfd, struct ifreq *ifre, const char *ipv6_addr, int request, const char *req_name);
209 static void set_memstart(int sockfd, struct ifreq *ifre, const char *start_addr, int request, const char *req_name);
210 static void set_ioaddr(int sockfd, struct ifreq *ifre, const char *baddr, int request, const char *req_name);
211 static void set_irq(int sockfd, struct ifreq *ifre, const char *irq_val, int request, const char *req_name);
212
213 char *omit_whitespace(const char *s)
214 {
215 while(*s == ' ' || (unsigned char)(*s - 9) <= (13 - 9)) s++;
216 return (char *) s;
217 }
218
219 char *safe_strncpy(char *dst, const char *src, size_t size)
220 {
221 if(!size) return dst;
222 dst[--size] = '\0';
223 return strncpy(dst, src, size);
224 }
225
226 /*
227 * used to get the host name from the given ip.
228 */
229 int get_hostname(const char *ipstr, struct sockaddr_in *sockin)
230 {
231 struct hostent *host;
232 sockin->sin_family = AF_INET;
233 sockin->sin_port = 0;
234
235 if(strcmp(ipstr, "default") == 0) {
236 sockin->sin_addr.s_addr = INADDR_ANY;
237 return 1;
238 }
239
240 if(inet_aton(ipstr, &sockin->sin_addr)) return 0;
241
242 host = gethostbyname(ipstr);
243 if(host == NULL) return -1;
244 memcpy(&sockin->sin_addr, host->h_addr_list[0], sizeof(struct in_addr));
245 return 0;
246 }
247
248 /*
249 * used to extract the address info from the given ip.
250 */
251 int get_addrinfo(const char *ip, struct sockaddr_in6 *sock_in6)
252 {
253 struct addrinfo hints, *result;
254 int status = 0;
255
256 memset(&hints, 0, sizeof(struct addrinfo));
257 hints.ai_family = AF_INET6;
258 if((status = getaddrinfo(ip, NULL, &hints, &result)) != 0) {
259 perror_msg("getaddrinfo: %s", gai_strerror(status));
260 return -1;
261 }
262 if(result) {
263 memcpy(sock_in6, result->ai_addr, sizeof(*sock_in6));
264 freeaddrinfo(result);
265 }
266 return 0;
267 }
268
269 /*
270 * used to get the flag values for route command.
271 */
272 void get_flag_value(char **flagstr, int flags)
273 {
274 int i = 0;
275 char *str = *flagstr;
276 static const char flagchars[] = "GHRDMDAC";
277 static const unsigned flagarray[] = {
278 RTF_GATEWAY,
279 RTF_HOST,
280 RTF_REINSTATE,
281 RTF_DYNAMIC,
282 RTF_MODIFIED,
283 RTF_DEFAULT,
284 RTF_ADDRCONF,
285 RTF_CACHE
286 };
287 *str++ = 'U';
288 while( (*str = flagchars[i]) != 0) {
289 if(flags & flagarray[i++]) ++str;
290 }
291 }
292
293 /*
294 * extract inet4 route info from /proc/net/route file and display it.
295 */
296 void display_routes(int is_more_info, int notresolve)
297 {
298 #define IPV4_MASK (RTF_GATEWAY|RTF_HOST|RTF_REINSTATE|RTF_DYNAMIC|RTF_MODIFIED)
299 unsigned long dest, gate, mask;
300 int flags, ref, use, metric, mss, win, irtt;
301 char iface[64]={0,};
302 char buf[BUFSIZ] = {0,};
303 char *flag_val = xzalloc(10); //there are 9 flags "UGHRDMDAC" for route.
304
305 FILE *fp = xfopen("/proc/net/route", "r");
306
307 xprintf("Kernel IP routing table\n"
308 "Destination Gateway Genmask Flags %s Iface\n",
309 is_more_info ? " MSS Window irtt" : "Metric Ref Use");
310 fgets(buf, BUFSIZ, fp); //skip 1st line.
311 while(fgets(buf, BUFSIZ, fp)) {
312 int nitems = 0;
313 char *destip = NULL, *gateip = NULL, *maskip = NULL;
314 memset(flag_val, 0, 10);
315
316 nitems = sscanf(buf, "%63s%lx%lx%X%d%d%d%lx%d%d%d\n",
317 iface, &dest, &gate, &flags, &ref, &use, &metric, &mask, &mss, &win, &irtt);
318 if(nitems != 11) {//EOF with no (nonspace) chars read...
319 if((nitems < 0) && feof(fp)) break;
320 perror_exit("fscanf");
321 }
322 //skip down interfaces...
323 if(!(flags & RTF_UP)) continue;
324
325 //For Destination
326 if(dest){
327 if(inet_ntop(AF_INET, &dest, buf, BUFSIZ) > 0) destip = xstrdup(buf);
328 }
329 else {
330 if(!notresolve) destip = xstrdup("default");
331 else destip = xstrdup("0.0.0.0");
332 }
333 //For Gateway
334 if(gate){
335 if(inet_ntop(AF_INET, &gate, buf, BUFSIZ) > 0) gateip = xstrdup(buf);
336 }
337 else {
338 if(!notresolve) gateip = xstrdup("*");
339 else gateip = xstrdup("0.0.0.0");
340 }
341 //For Mask
342 if(inet_ntop(AF_INET, &mask, buf, BUFSIZ) > 0) maskip = xstrdup(buf);
343
344 //Get flag Values
345 get_flag_value(&flag_val, (flags & IPV4_MASK));
346 if(flags & RTF_REJECT) flag_val[0] = '!';
347 xprintf("%-15.15s %-15.15s %-16s%-6s", destip, gateip, maskip, flag_val);
348 if(destip) free(destip);
349 if(gateip) free(gateip);
350 if(maskip) free(maskip);
351 if(is_more_info) xprintf("%5d %-5d %6d %s\n", mss, win, irtt, iface);
352 else xprintf("%-6d %-2d %7d %s\n", metric, ref, use, iface);
353 }//end of while...
354 fclose(fp);
355 if(flag_val) free(flag_val);
356 #undef IPV4_MASK
357 return;
358 }
359
360 /*
361 * verify the host is local unix path.
362 * if so, set the swl input param accordingly.
363 */
364 static int is_host_unix(const char *host, sockaddr_with_len **swl)
365 {
366 if(strncmp(host, "local:", 6) == 0) {
367 struct sockaddr_un *sockun;
368 *swl = xzalloc(sizeof(struct sockaddr_with_len));
369 (*swl)->socklen = sizeof(struct sockaddr_un);
370 (*swl)->sock_u.sock.sa_family = AF_UNIX;
371 sockun = (struct sockaddr_un *)&(*swl)->sock_u.sock;
372 safe_strncpy(sockun->sun_path, host + 6, sizeof(sockun->sun_path));
373 return 1;
374 }
375 return 0;
376 }
377
378 /*
379 * validate the input param (host) for valid ipv6 ip and extract port number (if there).
380 */
381 static void get_host_and_port(char **host, int *port)
382 {
383 char *ch_ptr;
384 const char *org_host = *host;
385 if(*host[0] == '[') {
386 (*host)++;
387 ch_ptr = strchr(*host, ']');
388 if(!ch_ptr || (ch_ptr[1] != ':' && ch_ptr[1] != '\0'))
389 error_exit("bad address '%s'", org_host);
390 }
391 else {
392 ch_ptr = strrchr(*host, ':');
393 //There is more than one ':' like "::1"
394 if(ch_ptr && strchr(*host, ':') != ch_ptr)
395 ch_ptr = NULL;
396 }
397 if(ch_ptr) { //pointer to ":" or "]:"
398 int size = ch_ptr - (*host) + 1;
399 safe_strncpy(*host, *host, size);
400 if(*ch_ptr != ':') {
401 ch_ptr++; //skip ']'
402 //[nn] without port
403 if(*ch_ptr == '\0')
404 return;
405 }
406 ch_ptr++; //skip ':' to get the port number.
407 *port = get_strtou(ch_ptr, NULL, 10);
408 if(errno || (unsigned)*port > MAX_PORT_VALUE)
409 error_exit("bad port spec '%s'", org_host);
410 }
411 return;
412 }
413
414 /*
415 * used to extract the address info from the given host ip
416 * and update the swl param accordingly.
417 */
418 static int get_socket_stream(const char *host, sa_family_t af, sockaddr_with_len **swl)
419 {
420 struct addrinfo hints;
421 struct addrinfo *result, *rp;
422 int status = 0;
423
424 memset(&hints, 0 , sizeof(struct addrinfo));
425 hints.ai_family = af;
426 hints.ai_socktype = SOCK_STREAM;
427
428 if((status = getaddrinfo(host, NULL, &hints, &result)) != 0) {
429 perror_exit("bad address '%s' : %s", host, gai_strerror(status));
430 return status;
431 }
432
433 for(rp = result; rp != NULL; rp = rp->ai_next) {
434 if( (rp->ai_family == AF_INET) || (rp->ai_family == AF_INET6)) {
435 *swl = xmalloc(sizeof(struct sockaddr_with_len));
436 (*swl)->socklen = rp->ai_addrlen;
437 memcpy(&((*swl)->sock_u.sock), rp->ai_addr, rp->ai_addrlen);
438 break;
439 }
440 }
441 freeaddrinfo(result);
442 return ((!rp)? -1: status);
443 }
444
445 /*
446 * use to get the socket address with the given host ip.
447 */
448 sockaddr_with_len *get_sockaddr(const char *host, int port, sa_family_t af)
449 {
450 sockaddr_with_len *swl = NULL;
451 int status = 0;
452
453 //for unix
454 int is_unix = is_host_unix(host, &swl);
455 if(is_unix && swl) return swl;
456
457 //[IPV6_ip]:port_num
458 if(host[0] == '[' || strrchr(host, ':')) get_host_and_port((char **)&host, &port);
459
460 //for the socket streams.
461 status = get_socket_stream(host, af, &swl);
462 if(status) return NULL;
463
464 setport(&swl->sock_u.sock, htons(port));
465 return swl;
466 }
467
468 /*
469 * get the numeric hostname and service name, for a given socket address.
470 */
471 char *address_to_name(const struct sockaddr *sock)
472 {
473 //man page of getnameinfo.
474 char hbuf[NI_MAXHOST] = {0,}, sbuf[NI_MAXSERV] = {0,};
475 int status = 0;
476 if(sock->sa_family == AF_INET) {
477 socklen_t len = sizeof(struct sockaddr_in);
478 if((status = getnameinfo(sock, len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0)
479 return xmsprintf("%s:%s", hbuf, sbuf);
480 else {
481 fprintf(stderr, "getnameinfo: %s\n", gai_strerror(status));
482 return NULL;
483 }
484 }
485 else if(sock->sa_family == AF_INET6) {
486 socklen_t len = sizeof(struct sockaddr_in6);
487 if((status = getnameinfo(sock, len, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) == 0) {
488 //verification for resolved hostname.
489 if(strchr(hbuf, ':')) return xmsprintf("[%s]:%s", hbuf, sbuf);
490 else return xmsprintf("%s:%s", hbuf, sbuf);
491 }
492 else {
493 fprintf(stderr, "getnameinfo: %s\n", gai_strerror(status));
494 return NULL;
495 }
496 }
497 else if(sock->sa_family == AF_UNIX) {
498 struct sockaddr_un *sockun = (void*)sock;
499 return xmsprintf("local:%.*s", (int) sizeof(sockun->sun_path), sockun->sun_path);
500 }
501 else
502 return NULL;
503 }
504
505 /*
506 * used to set the port number for ipv4 / ipv6 addresses.
507 */
508 void setport(struct sockaddr *sock, unsigned port_num)
509 {
510 //for ipv4
511 if(sock->sa_family == AF_INET) {
512 struct sockaddr_in *sock_in = (void*)sock;
513 sock_in->sin_port = port_num;
514 }
515 //for ipv6
516 else if(sock->sa_family == AF_INET6) {
517 struct sockaddr_in6 *sock_in6 = (void*)sock;
518 sock_in6->sin6_port = port_num;
519 }
520 return;
521 }
522
523 /*
524 * used to get the port number for ftp and http.
525 */
526 unsigned getport(const char *port, const char *protocol, unsigned defport)
527 {
528 #define RANGE_STR "Port Number should be in [1-65535] range"
529 long v;
530 char *endptr = NULL;
531
532 unsigned portnum = defport;
533 if(port) {
534 errno = 0;
535 v = strtol(port, &endptr, 10);
536 if((v > 0) && (!*endptr)) {//for numeric like 123
537 portnum = v;
538 if(portnum > MAX_PORT_VALUE) error_exit("Invalid Port Number '%s' "RANGE_STR, port);
539 }
540 else if((v == 0) && (endptr != NULL)) {
541 switch(defport) {
542 case FTP_DEFAULT_PORT:
543 if(strcmp(endptr, "ftp") == 0) portnum = defport; //for "ftp" string.
544 else goto ERROR_EXIT;
545 break;
546 case HTTP_DEFAULT_PORT:
547 if(strcmp(endptr, "http") == 0) portnum = defport;//for "HTTP" string.
548 else goto ERROR_EXIT;
549 break;
550 default:
551 ERROR_EXIT:
552 error_exit("Invalid Port");
553 break;
554 }
555 }
556 else perror_exit("Invalid Port Number: '%s' "RANGE_STR, port);
557 }
558 #undef RANGE_STR
559 return (uint16_t)portnum;
560 }
561
562 /*
563 * used to connect with the socket.
564 */
565 int connect_to_stream(const sockaddr_with_len *swl)
566 {
567 int sockfd;
568 if((sockfd = socket(swl->sock_u.sock.sa_family, SOCK_STREAM, 0)) < 0)
569 perror_exit("cannot open control socket");
570 if(connect(sockfd, &swl->sock_u.sock, swl->socklen) < 0) {
571 close(sockfd);
572 perror_exit("can't connect to remote host");
573 }
574 return sockfd;
575 }
576
577 /*
578 * used to converts string into int and validate the input str for invalid int value or out-of-range.
579 */
580 unsigned get_strtou(const char *str, char **endp, int base)
581 {
582 unsigned long uli;
583 char *endptr;
584
585 if(!isalnum(str[0])) {
586 errno = ERANGE;
587 return UINT_MAX;
588 }
589 errno = 0;
590 uli = strtoul(str, &endptr, base);
591 if(uli > UINT_MAX) {
592 errno = ERANGE;
593 return UINT_MAX;
594 }
595
596 if(endp) *endp = endptr;
597 if(endptr[0]) {
598 if(isalnum(endptr[0]) || errno) { //"123abc" or out-of-range
599 errno = ERANGE;
600 return UINT_MAX;
601 }
602 errno = EINVAL;
603 }
604 return uli;
605 }
606
607
608 IFACE_LIST *iface_list_head;
609
610 /*
611 * display help info and exit from application.
612 */
613 static void show_help(void)
614 {
615 char **arg = xzalloc(sizeof(char*) *3);
616 arg[0] = "help";
617 arg[1] = xstrdup(toys.which->name);
618 toy_exec(arg);
619 }
620
621 void ifconfig_main(void)
622 {
623 char **argv = toys.optargs;
624
625 if(argv[0] && (strcmp(argv[0], "--help") == 0))
626 show_help();
627
628 //"ifconfig" / "ifconfig eth0"
629 if(!argv[0] || !argv[1]) { //one or no argument
630 toys.exitval = show_iface(argv[0]);
631 //free allocated memory.
632 clear_list();
633 return;
634 }
635
636 //set ifconfig params.
637 {
638 struct ifreq ifre;
639 int sockfd = 0;
640 //get interface name
641 memset(&ifre, 0, sizeof(struct ifreq));
642 strncpy(ifre.ifr_name, *argv, IFNAMSIZ);
643 ifre.ifr_name[IFNAMSIZ-1] = 0;
644 if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
645 perror_exit("cannot open control socket\n", 1);
646
647 while(*++argv != NULL) {
648 /* flags settings */
649 if(strcmp(argv[0], "up") == 0)
650 set_flags(sockfd, &ifre, IFF_UP | IFF_RUNNING, 0);
651 else if(strcmp(argv[0], "down") == 0)
652 set_flags(sockfd, &ifre, 0, IFF_UP);
653
654 else if(strcmp(argv[0], "arp") == 0)
655 set_flags(sockfd, &ifre, 0, IFF_NOARP);
656 else if(strcmp(argv[0], "-arp") == 0)
657 set_flags(sockfd, &ifre, IFF_NOARP, 0);
658 else if(strcmp(argv[0], "trailers") == 0)
659 set_flags(sockfd, &ifre, 0, IFF_NOTRAILERS);
660 else if(strcmp(argv[0], "-trailers") == 0)
661 set_flags(sockfd, &ifre, IFF_NOTRAILERS, 0);
662
663 else if(strcmp(argv[0], "promisc") == 0)
664 set_flags(sockfd, &ifre, IFF_PROMISC, 0);
665 else if(strcmp(argv[0], "-promisc") == 0)
666 set_flags(sockfd, &ifre, 0, IFF_PROMISC);
667 else if(strcmp(argv[0], "allmulti") == 0)
668 set_flags(sockfd, &ifre, IFF_ALLMULTI, 0);
669 else if(strcmp(argv[0], "-allmulti") == 0)
670 set_flags(sockfd, &ifre, 0, IFF_ALLMULTI);
671 else if(strcmp(argv[0], "multicast") == 0)
672 set_flags(sockfd, &ifre, IFF_MULTICAST, 0);
673 else if(strcmp(argv[0], "-multicast") == 0)
674 set_flags(sockfd, &ifre, 0, IFF_MULTICAST);
675 else if(strcmp(argv[0], "dynamic") == 0)
676 set_flags(sockfd, &ifre, IFF_DYNAMIC, 0);
677 else if(strcmp(argv[0], "-dynamic") == 0)
678 set_flags(sockfd, &ifre, 0, IFF_DYNAMIC);
679 else if(strcmp(argv[0], "-pointopoint") == 0)
680 set_flags(sockfd, &ifre, 0, IFF_POINTOPOINT);
681 /*value setup */
682 else if(strcmp(argv[0], "pointopoint") == 0) {
683 if(*++argv == NULL) {
684 errno = EINVAL;
685 show_help();
686 }
687 set_address(sockfd, *argv, &ifre, SIOCSIFDSTADDR, "SIOCSIFDSTADDR");
688 set_flags(sockfd, &ifre, IFF_POINTOPOINT, 0);
689 }
690 else if(strcmp(argv[0], "netmask") == 0) {
691 if(*++argv == NULL) {
692 errno = EINVAL;
693 show_help();
694 }
695 set_address(sockfd, *argv, &ifre, SIOCSIFNETMASK, "SIOCSIFNETMASK");
696 }
697 else if(strcmp(argv[0], "-broadcast") == 0) {
698 set_flags(sockfd, &ifre, 0, IFF_BROADCAST);
699 }
700 else if(strcmp(argv[0], "broadcast") == 0) {
701 if(*++argv == NULL) {
702 errno = EINVAL;
703 show_help();
704 }
705 set_address(sockfd, *argv, &ifre, SIOCSIFBRDADDR, "SIOCSIFBRDADDR");
706 set_flags(sockfd, &ifre, IFF_BROADCAST, 0);
707 }
708 else if(strcmp(argv[0], "dstaddr") == 0) {
709 if(*++argv == NULL) {
710 errno = EINVAL;
711 show_help();
712 }
713 set_address(sockfd, *argv, &ifre, SIOCSIFDSTADDR, "SIOCSIFDSTADDR");
714 }
715 else if(strcmp(argv[0], "hw") == 0) {
716 if(*++argv == NULL) {
717 errno = EINVAL;
718 show_help();
719 }
720 set_hw_address(sockfd, &argv, &ifre, SIOCSIFHWADDR, "SIOCSIFHWADDR");
721 }
722 else if(strcmp(argv[0], "mtu") == 0) {
723 if(*++argv == NULL) {
724 errno = EINVAL;
725 show_help();
726 }
727 set_mtu(sockfd, &ifre, argv[0]);
728 }//end of mtu
729 else if(strcmp(argv[0], "metric") == 0) {
730 if(*++argv == NULL) {
731 errno = EINVAL;
732 show_help();
733 }
734 set_metric(sockfd, &ifre, argv[0]);
735 }//end of metric
736 else if(strcmp(argv[0], "txqueuelen") == 0) {
737 if(*++argv == NULL) {
738 errno = EINVAL;
739 show_help();
740 }
741 set_qlen(sockfd, &ifre, argv[0]);
742 }//end of txqueuelen
743 else if(strcmp(argv[0], "keepalive") == 0) {
744 if(*++argv == NULL) {
745 errno = EINVAL;
746 show_help();
747 }
748 set_data(sockfd, &ifre, argv[0], SIOCSKEEPALIVE, "SIOCSKEEPALIVE");
749 }//end of keepalive
750 else if(strcmp(argv[0], "outfill") == 0) {
751 if(*++argv == NULL) {
752 errno = EINVAL;
753 show_help();
754 }
755 set_data(sockfd, &ifre, argv[0], SIOCSOUTFILL, "SIOCSOUTFILL");
756 }//end of outfill
757 else if(strcmp(argv[0], "add") == 0) {
758 if(*++argv == NULL) {
759 errno = EINVAL;
760 show_help();
761 }
762 set_ipv6_addr(sockfd, &ifre, argv[0], SIOCSIFADDR, "SIOCSIFADDR");
763 }//end of add ipv6 addr
764 else if(strcmp(argv[0], "del") == 0) {
765 if(*++argv == NULL) {
766 errno = EINVAL;
767 show_help();
768 }
769 set_ipv6_addr(sockfd, &ifre, argv[0], SIOCDIFADDR, "SIOCDIFADDR");
770 }//end of del ipv6 addr
771 else if(strcmp(argv[0], "mem_start") == 0) {
772 if(*++argv == NULL) {
773 errno = EINVAL;
774 show_help();
775 }
776 set_memstart(sockfd, &ifre, argv[0], SIOCSIFMAP, "SIOCSIFMAP");
777 }//end of mem_start
778 else if(strcmp(argv[0], "io_addr") == 0) {
779 if(*++argv == NULL) {
780 errno = EINVAL;
781 show_help();
782 }
783 set_ioaddr(sockfd, &ifre, argv[0], SIOCSIFMAP, "SIOCSIFMAP");
784 }//end of io_addr
785 else if(strcmp(argv[0], "irq") == 0) {
786 if(*++argv == NULL) {
787 errno = EINVAL;
788 show_help();
789 }
790 set_irq(sockfd, &ifre, argv[0], SIOCSIFMAP, "SIOCSIFMAP");
791 }//end of irq
792 else {
793 if(isdigit(argv[0][0]) || (strcmp(argv[0], "default") == 0)) {
794 char *iface_name = ifre.ifr_name;
795 short int is_colon = 0;
796 set_address(sockfd, *argv, &ifre, SIOCSIFADDR, "SIOCSIFADDR");
797 while(*iface_name) {
798 if(*iface_name == ':') {
799 is_colon = 1;
800 break;
801 }
802 iface_name++;
803 }
804 //if the interface name is not an alias; set the flag and continue.
805 if(!is_colon)
806 set_flags(sockfd, &ifre, IFF_UP | IFF_RUNNING, 0);
807 }
808 else if((strcmp(argv[0], "inet") == 0) || (strcmp(argv[0], "inet6") == 0))
809 continue;
810 else {
811 errno = EINVAL;
812 show_help();
813 }
814 }//set ip for an interface.
815
816 }//end of while.
817 if(sockfd > 0)
818 close(sockfd);
819 }
820 return;
821 }//End of main function.
822
823
824 static void set_flags(int sockfd, struct ifreq *ifre, int set_flag, int reset_flag)
825 {
826 if(ioctl(sockfd, SIOCGIFFLAGS, ifre) < 0)
827 perror_exit("SIOCGIFFLAGS");
828 ifre->ifr_flags = (ifre->ifr_flags & (~reset_flag)) | set_flag;
829 if(ioctl(sockfd, SIOCSIFFLAGS, ifre) < 0)
830 perror_exit("SIOCSIFFLAGS");
831 return;
832 }
833
834 static void set_data(int sockfd, struct ifreq *ifre, char *kval, int request, const char *req_name)
835 {
836 unsigned long val = xstrtoul(kval, NULL, 0);
837 char *ptr;
838 ptr = ((char *) ifre) + offsetof(struct ifreq, ifr_data);
839 (*(__caddr_t *)ptr) = (__caddr_t)val;
840
841 if(ioctl(sockfd, request, ifre) < 0) {
842 perror_exit((char *)req_name);
843 }
844 return;
845 }
846 static void set_mtu(int sockfd, struct ifreq *ifre, const char *mtu)
847 {
848 ifre->ifr_mtu = strtoul(mtu, NULL, 0);
849 if(ioctl(sockfd, SIOCSIFMTU, ifre) < 0)
850 perror_exit("SIOCSIFMTU");
851 return;
852 }
853
854 static void set_metric(int sockfd, struct ifreq *ifre, const char *metric)
855 {
856 ifre->ifr_metric = strtoul(metric, NULL, 0);
857 if(ioctl(sockfd, SIOCSIFMETRIC, ifre) < 0)
858 perror_exit("SIOCSIFMETRIC");
859 return;
860 }
861
862 static void set_qlen(int sockfd, struct ifreq *ifre, const char *qlen)
863 {
864 ifre->ifr_qlen = strtoul(qlen, NULL, 0);
865 if(ioctl(sockfd, SIOCSIFTXQLEN, ifre) < 0)
866 perror_exit("SIOCSIFTXQLEN");
867 return;
868 }
869
870 static void set_ipv6_addr(int sockfd, struct ifreq *ifre, const char *ipv6_addr, int request, const char *req_name)
871 {
872 char *prefix;
873 int plen = 0;
874 sockaddr_with_len *swl = NULL;
875
876 prefix = strchr(ipv6_addr, '/');
877 if(prefix) {
878 plen = get_int_value(prefix + 1, 0, 128);
879 *prefix = '\0';
880 }
881 swl = get_sockaddr(ipv6_addr, 0, AF_INET6);
882 if(!swl) error_exit("error in resolving host name");
883 int sockfd6;
884 struct ifreq_inet6 ifre6;
885 memcpy((char *) &ifre6.ifrinte6_addr,
886 (char *) &(swl->sock_u.sock_in6.sin6_addr),
887 sizeof(struct in6_addr));
888 //Create a channel to the NET kernel.
889 if( (sockfd6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
890 perror_exit("AF_INET6 SOCK_DGRAM", 0);
891 if(ioctl(sockfd6, SIOGIFINDEX, ifre) < 0)
892 perror_exit("SIOGIFINDEX");
893 ifre6.ifrinet6_ifindex = ifre->ifr_ifindex;
894 ifre6.ifrinet6_prefixlen = plen;
895
896 if(ioctl(sockfd6, request, &ifre6) < 0)
897 perror_exit((char *)req_name);
898 if(swl != NULL) {
899 free(swl);
900 swl = NULL;
901 }
902 return;
903 }
904
905 static void set_address(int sockfd, const char *host_name, struct ifreq *ifre, int request, const char *req_name)
906 {
907 struct sockaddr_in sock_in;
908 sockaddr_with_len *swl = NULL;
909 sock_in.sin_family = AF_INET;
910 sock_in.sin_port = 0;
911
912 //Default 0.0.0.0
913 if(strcmp(host_name, "default") == 0)
914 sock_in.sin_addr.s_addr = INADDR_ANY;
915 else {
916 swl = get_sockaddr(host_name, 0, AF_INET);
917 if(!swl) error_exit("error in resolving host name");
918
919 sock_in.sin_addr = swl->sock_u.sock_in.sin_addr;
920 }
921 memcpy((char *)&ifre->ifr_addr, (char *) &sock_in, sizeof(struct sockaddr));
922 if(ioctl(sockfd, request, ifre) < 0)
923 perror_exit((char *)req_name);
924
925 if(swl != NULL) {
926 free(swl);
927 swl = NULL;
928 }
929 return;
930 }
931
932 static int hex_to_binary(const char *hw_addr, struct sockaddr *sock, int count)
933 {
934 int i = 0, j = 0;
935 unsigned char nib_val;
936 unsigned char ch;
937
938 char *ptr = (char *) sock->sa_data;
939 if(count == ETH_ALEN)
940 sock->sa_family = ARPHRD_ETHER;
941 else if(count == INFINIBAND_ALEN)
942 sock->sa_family = ARPHRD_INFINIBAND;
943 else
944 return -1;
945 //e.g. hw_addr "62:2D:A6:9E:2D:BE"
946 for(; *hw_addr && (i < count); i++) {
947 if(*hw_addr == ':')
948 hw_addr++;
949 j = nib_val = 0;
950 for(;j < 2; j++) {
951 ch = *hw_addr;
952 //0-9 = 10 chars.
953 if(((unsigned char)(ch - '0')) < 10)
954 ch = (ch - '0');
955 //a-f = 6 chars.
956 else if(((unsigned char)((ch) - 'a')) < 6)
957 ch = (ch - ('a'-10));
958 //A-F = 6 chars.
959 else if(((unsigned char)((ch) - 'A')) < 6)
960 ch = (ch - ('A'-10));
961 else if(j && (ch == ':' || ch == 0))
962 break;
963 else
964 return -1;
965 hw_addr++;
966 nib_val <<= 4;
967 nib_val += ch;
968 }
969 *ptr++ = nib_val;
970 }
971 if(*hw_addr)
972 return -1;
973 return 0;
974 }
975
976 static void set_hw_address(int sockfd, char ***argv, struct ifreq *ifre, int request, const char *req_name)
977 {
978 int hw_class = 0;
979 char *hw_addr;
980 struct sockaddr sock;
981 char *ptr;
982 char *hw_class_strings[] = {
983 "ether",
984 "infiniband",
985 NULL
986 };
987
988 if(strcmp(hw_class_strings[0], **argv) == 0)
989 hw_class = 1;
990 else if(strcmp(hw_class_strings[1], **argv) == 0)
991 hw_class = 2;
992 if(!hw_class || !(*argv += 1))
993 show_help();
994
995 memset(&sock, 0, sizeof(struct sockaddr));
996 hw_addr = **argv;
997 if(hw_class == 1) {
998 if(hex_to_binary(hw_addr, &sock, ETH_ALEN))
999 error_exit("invalid hw-addr %s", hw_addr);
1000 }
1001 else {
1002 if(hex_to_binary(hw_addr, &sock, INFINIBAND_ALEN))
1003 error_exit("invalid hw-addr %s", hw_addr);
1004 }
1005 ptr = (char *)&sock;
1006 memcpy( ((char *) ifre) + offsetof(struct ifreq, ifr_hwaddr), ptr, sizeof(struct sockaddr));
1007 if(ioctl(sockfd, request, ifre) < 0)
1008 perror_exit((char *)req_name);
1009 return;
1010 }
1011
1012 static void set_memstart(int sockfd, struct ifreq *ifre, const char *start_addr, int request, const char *req_name)
1013 {
1014 unsigned long mem_start = strtoul(start_addr, NULL, 0);
1015
1016 if(ioctl(sockfd, SIOCGIFMAP, ifre) < 0)
1017 perror_exit("SIOCGIFMAP");
1018 ifre->ifr_map.mem_start = mem_start;
1019 if(ioctl(sockfd, request, ifre) < 0)
1020 perror_exit((char *)req_name);
1021 return;
1022 }
1023
1024 static void set_ioaddr(int sockfd, struct ifreq *ifre, const char *baddr, int request, const char *req_name)
1025 {
1026 unsigned short int base_addr = strtoul(baddr, NULL, 0);
1027 if(ioctl(sockfd, SIOCGIFMAP, ifre) < 0)
1028 perror_exit("SIOCGIFMAP");
1029 ifre->ifr_map.base_addr = base_addr;
1030 if(ioctl(sockfd, request, ifre) < 0)
1031 perror_exit((char *)req_name);
1032 return;
1033 }
1034
1035 static void set_irq(int sockfd, struct ifreq *ifre, const char *irq_val, int request, const char *req_name)
1036 {
1037 unsigned short int irq = strtoul(irq_val, NULL, 0);
1038 char *ptr;
1039 struct ifmap *map;
1040
1041 if(ioctl(sockfd, SIOCGIFMAP, ifre) < 0)
1042 perror_exit("SIOCGIFMAP");
1043
1044 ptr = ((char *) ifre) + offsetof(struct ifreq, ifr_map);
1045 map = (struct ifmap *)ptr;
1046 map->irq = irq;
1047 if(ioctl(sockfd, request, ifre) < 0)
1048 perror_exit((char *)req_name);
1049 return;
1050 }
1051
1052 /* Display ifconfig info. */
1053 static void get_proc_info(char *buff, IFACE_LIST *l_ptr, int version)
1054 {
1055 char *name;
1056 memset(&l_ptr->dev_info, 0, sizeof(PROC_NET_DEV_INFO));
1057
1058 buff = omit_whitespace(buff);
1059 name = strsep(&buff, ":");
1060 if(!buff)
1061 error_exit("error in getting the device name:");
1062
1063 if(strlen(name) < (IFNAMSIZ)) {
1064 strncpy(l_ptr->dev_info.ifrname, name, IFNAMSIZ-1);
1065 l_ptr->dev_info.ifrname[IFNAMSIZ-1] = '\0';
1066 }
1067 else {
1068 l_ptr->dev_info.ifrname[0] = '\0';
1069 }
1070
1071 sscanf(buff, field_format[version],
1072 &l_ptr->dev_info.receive_bytes,
1073 &l_ptr->dev_info.receive_packets,
1074 &l_ptr->dev_info.receive_errors,
1075 &l_ptr->dev_info.receive_drop,
1076 &l_ptr->dev_info.receive_fifo,
1077 &l_ptr->dev_info.receive_frame,
1078 &l_ptr->dev_info.receive_compressed,
1079 &l_ptr->dev_info.receive_multicast,
1080 &l_ptr->dev_info.transmit_bytes,
1081 &l_ptr->dev_info.transmit_packets,
1082 &l_ptr->dev_info.transmit_errors,
1083 &l_ptr->dev_info.transmit_drop,
1084 &l_ptr->dev_info.transmit_fifo,
1085 &l_ptr->dev_info.transmit_colls,
1086 &l_ptr->dev_info.transmit_carrier,
1087 &l_ptr->dev_info.transmit_compressed
1088 );
1089
1090 if(version == 0)
1091 l_ptr->dev_info.receive_bytes = l_ptr->dev_info.transmit_bytes = 0;
1092 if(version == 1)
1093 l_ptr->dev_info.receive_multicast = l_ptr->dev_info.receive_compressed = l_ptr->dev_info.transmit_compressed = 0;
1094 return;
1095 }
1096
1097 static void add_iface_to_list(IFACE_LIST *newnode)
1098 {
1099 IFACE_LIST *head_ref = iface_list_head;
1100
1101 if((head_ref == NULL) || strcmp(newnode->dev_info.ifrname, head_ref->dev_info.ifrname) < 0) {
1102 newnode->next = head_ref;
1103 head_ref = newnode;
1104 }
1105 else {
1106 IFACE_LIST *current = head_ref;
1107 while(current->next != NULL && (strcmp(current->next->dev_info.ifrname, newnode->dev_info.ifrname)) < 0)
1108 current = current->next;
1109 newnode->next = current->next;
1110 current->next = newnode;
1111 }
1112 iface_list_head = head_ref;
1113 return;
1114 }
1115
1116 static int get_device_info(IFACE_LIST *l_ptr)
1117 {
1118 struct ifreq ifre;
1119 char *ifrname = l_ptr->dev_info.ifrname;
1120 int sokfd;
1121
1122 sokfd = socket(AF_INET, SOCK_DGRAM, 0);
1123 if(sokfd < 0)
1124 return sokfd;
1125 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1126 if(ioctl(sokfd, SIOCGIFFLAGS, &ifre) < 0) {
1127 close(sokfd);
1128 return NO_RANGE;
1129 }
1130 l_ptr->ifrflags = ifre.ifr_flags;
1131
1132 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1133 if(ioctl(sokfd, SIOCGIFHWADDR, &ifre) >= 0)
1134 memcpy(l_ptr->ifrhwaddr.sa_data, ifre.ifr_hwaddr.sa_data, sizeof(l_ptr->ifrhwaddr.sa_data));
1135
1136 l_ptr->hw_type = ifre.ifr_hwaddr.sa_family;
1137
1138 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1139 if(ioctl(sokfd, SIOCGIFMETRIC, &ifre) >= 0)
1140 l_ptr->ifrmetric = ifre.ifr_metric;
1141
1142 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1143 if(ioctl(sokfd, SIOCGIFMTU, &ifre) >= 0)
1144 l_ptr->ifrmtu = ifre.ifr_mtu;
1145
1146 #ifdef SIOCGIFMAP
1147 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1148 if(ioctl(sokfd, SIOCGIFMAP, &ifre) == 0)
1149 l_ptr->ifrmap = ifre.ifr_map;
1150 #endif
1151
1152 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1153 l_ptr->txqueuelen = NO_RANGE;
1154 if(ioctl(sokfd, SIOCGIFTXQLEN, &ifre) >= 0)
1155 l_ptr->txqueuelen = ifre.ifr_qlen;
1156
1157 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1158 ifre.ifr_addr.sa_family = AF_INET;
1159
1160 if(ioctl(sokfd, SIOCGIFADDR, &ifre) == 0) {
1161 l_ptr->ifaddr = 1;
1162 l_ptr->ifraddr = ifre.ifr_addr;
1163 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1164 if(ioctl(sokfd, SIOCGIFDSTADDR, &ifre) >= 0)
1165 l_ptr->ifrdstaddr = ifre.ifr_dstaddr;
1166
1167 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1168 if(ioctl(sokfd, SIOCGIFBRDADDR, &ifre) >= 0)
1169 l_ptr->ifrbroadaddr = ifre.ifr_broadaddr;
1170
1171 strncpy(ifre.ifr_name, ifrname, IFNAMSIZ);
1172 if(ioctl(sokfd, SIOCGIFNETMASK, &ifre) >= 0)
1173 l_ptr->ifrnetmask = ifre.ifr_netmask;
1174 }
1175 close(sokfd);
1176 return 0;
1177 }
1178
1179 static void get_ifconfig_info(void)
1180 {
1181 IFACE_LIST *l_ptr;
1182 char buff[BUFSIZ] = {0,};
1183 int version_num = 0;
1184
1185 FILE *fp = fopen(PROC_NET_DEV, "r");
1186 if(fp == NULL)
1187 return;
1188
1189 fgets(buff, sizeof(buff), fp); //skip 1st header line.
1190 fgets(buff, sizeof(buff), fp); //skip 2nd header line.
1191
1192 if(strstr(buff, "compressed"))
1193 version_num = 2;
1194 else if(strstr(buff, "bytes"))
1195 version_num = 1;
1196 else
1197 version_num = 0;
1198
1199 while(fgets(buff, BUFSIZ, fp)) {
1200 l_ptr = xzalloc(sizeof(IFACE_LIST));
1201 get_proc_info(buff, l_ptr, version_num);
1202 add_iface_to_list(l_ptr);
1203 errno = 0;
1204 if(get_device_info(l_ptr) < 0) {
1205 const char *errstr = strerror(errno);
1206 fclose(fp);
1207 fp = NULL;
1208 clear_list();
1209 perror_exit("%s: error getting interface info: %s", l_ptr->dev_info.ifrname, errstr);
1210 }
1211 }//end of while.
1212 fclose(fp);
1213 fp = NULL;
1214 return;
1215 }
1216
1217 static void get_hw_info(int hw_type, HW_INFO *hw_info)
1218 {
1219 #define HW_UNSPEC -1
1220 switch(hw_type) {
1221 case ARPHRD_LOOPBACK: //Loopback device.
1222 strncpy(hw_info->hw_name, "loop", HW_NAME_LEN);
1223 strncpy(hw_info->hw_title, "Local Loopback", HW_TITLE_LEN);
1224 hw_info->hw_addrlen = 0;
1225 break;
1226 case ARPHRD_ETHER: //Ethernet
1227 strncpy(hw_info->hw_name, "ether", HW_NAME_LEN);
1228 strncpy(hw_info->hw_title, "Ethernet", HW_TITLE_LEN);
1229 hw_info->hw_addrlen = ETH_ALEN;
1230 break;
1231 case ARPHRD_PPP: //ARPHRD_PPP
1232 strncpy(hw_info->hw_name, "ppp", HW_NAME_LEN);
1233 strncpy(hw_info->hw_title, "Point-to-Point Protocol", HW_TITLE_LEN);
1234 hw_info->hw_addrlen = 0;
1235 break;
1236 case ARPHRD_INFINIBAND: //InfiniBand
1237 strncpy(hw_info->hw_name, "infiniband", HW_NAME_LEN);
1238 strncpy(hw_info->hw_title, "InfiniBand", HW_TITLE_LEN);
1239 hw_info->hw_addrlen = 20;
1240 break;
1241 case ARPHRD_SIT: //sit0 device - IPv6-in-IPv4
1242 strncpy(hw_info->hw_name, "sit", HW_NAME_LEN);
1243 strncpy(hw_info->hw_title, "IPv6-in-IPv4", HW_TITLE_LEN);
1244 hw_info->hw_addrlen = 0;
1245 break;
1246 case HW_UNSPEC: //UNSPEC
1247 strncpy(hw_info->hw_name, "unspec", HW_NAME_LEN);
1248 strncpy(hw_info->hw_title, "UNSPEC", HW_TITLE_LEN);
1249 hw_info->hw_addrlen = 0;
1250 break;
1251 default:
1252 break;
1253 }
1254 #undef HW_UNSPEC
1255 return;
1256 }
1257
1258 static void print_hw_addr(int hw_type, HW_INFO hw_info, IFACE_LIST *l_ptr)
1259 {
1260 unsigned char *address = (unsigned char *) l_ptr->ifrhwaddr.sa_data;
1261 if(!address || (hw_info.hw_addrlen == 0))
1262 return;
1263 xprintf("HWaddr ");
1264 if(hw_type == ARPHRD_ETHER)
1265 xprintf("%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1], address[2],
1266 address[3], address[4], address[5]);
1267 return;
1268 }
1269
1270 static const char *get_ip_addr(struct sockaddr *skaddr)
1271 {
1272 static char *ip_str = NULL;
1273 struct sockaddr_in *sin;
1274
1275 if(skaddr->sa_family == 0xFFFF || skaddr->sa_family == 0)
1276 return "[NOT SET]";
1277 sin = (struct sockaddr_in *)skaddr;
1278 if(sin->sin_family != AF_INET) {
1279 errno = EAFNOSUPPORT;
1280 return NULL;
1281 }
1282 if( (ip_str = inet_ntoa(sin->sin_addr)) != NULL)
1283 return ip_str;
1284
1285 return NULL;
1286 }
1287
1288 static void print_ip_addr(IFACE_LIST *l_ptr)
1289 {
1290 const char *af_name;
1291 int af = l_ptr->ifraddr.sa_family;
1292 if(af == AF_INET)
1293 af_name = "inet";
1294 else if(af == AF_INET6)
1295 af_name = "inet6";
1296 else if(af == AF_UNSPEC)
1297 af_name = "unspec";
1298
1299 xprintf("%10s%s addr:%s ", " ", af_name, get_ip_addr(&l_ptr->ifraddr));
1300 if(l_ptr->ifrflags & IFF_POINTOPOINT)
1301 xprintf(" P-t-P:%s ", get_ip_addr(&l_ptr->ifrdstaddr));
1302 if(l_ptr->ifrflags & IFF_BROADCAST)
1303 xprintf(" Bcast:%s ", get_ip_addr(&l_ptr->ifrbroadaddr));
1304 xprintf(" Mask:%s\n", get_ip_addr(&l_ptr->ifrnetmask));
1305 return;
1306 }
1307
1308 static void print_iface_flags(IFACE_LIST *l_ptr)
1309 {
1310 if(l_ptr->ifrflags != 0) {
1311 unsigned short mask = 1;
1312 char **str = iface_flags_str;
1313 for(; *str != NULL; str++) {
1314 if(l_ptr->ifrflags & mask)
1315 xprintf("%s ", *str);
1316 mask = mask << 1;
1317 }
1318 }
1319 else
1320 xprintf("[NO FLAGS] ");
1321 return;
1322 }
1323
1324 static void print_media(IFACE_LIST *l_ptr)
1325 {
1326 #ifdef IFF_PORTSEL
1327 if(l_ptr->ifrflags & IFF_PORTSEL) {
1328 xprintf("Media:");
1329 if(l_ptr->ifrmap.port == IF_PORT_UNKNOWN)
1330 xprintf("%s", "unknown");
1331 else if(l_ptr->ifrmap.port == IF_PORT_10BASE2)
1332 xprintf("%s", "10base2");
1333 else if(l_ptr->ifrmap.port == IF_PORT_10BASET)
1334 xprintf("%s", "10baseT");
1335 else if(l_ptr->ifrmap.port == IF_PORT_AUI)
1336 xprintf("%s", "AUI");
1337 else if(l_ptr->ifrmap.port == IF_PORT_100BASET)
1338 xprintf("%s", "100baseT");
1339 else if(l_ptr->ifrmap.port == IF_PORT_100BASETX)
1340 xprintf("%s", "100baseTX");
1341 else if(l_ptr->ifrmap.port == IF_PORT_100BASEFX)
1342 xprintf("%s", "100baseFX");
1343 if(l_ptr->ifrflags & IFF_AUTOMEDIA)
1344 xprintf("(auto)");
1345 }
1346 #endif
1347 return;
1348 }
1349
1350 static void print_ip6_addr(IFACE_LIST *l_ptr)
1351 {
1352 char iface_name[IFNAMSIZ] = {0,};
1353 char buf[BUFSIZ] = {0,};
1354 int plen, scope;
1355
1356 FILE *fp = fopen(PROC_NET_IFINET6, "r");
1357 if(fp == NULL)
1358 return;
1359
1360 while(fgets(buf, BUFSIZ, fp)) {
1361 int nitems = 0;
1362 char ipv6_addr[40] = {0,};
1363 nitems = sscanf(buf, "%32s %*08x %02x %02x %*02x %16s\n",
1364 ipv6_addr+7, &plen, &scope, iface_name);
1365 if(nitems != 4) {
1366 if((nitems < 0) && feof(fp))
1367 break;
1368 perror_exit("sscanf");
1369 }
1370 if(strcmp(l_ptr->dev_info.ifrname,iface_name) == 0) {
1371 int i = 0;
1372 struct sockaddr_in6 sock_in6;
1373 int len = sizeof(ipv6_addr) / (sizeof ipv6_addr[0]);
1374 char *ptr = ipv6_addr+7;
1375 while((i < len-2) && (*ptr)) {
1376 ipv6_addr[i++] = *ptr++;
1377 //put ':' after 4th bit
1378 if(!((i+1) % 5))
1379 ipv6_addr[i++] = ':';
1380 }
1381 ipv6_addr[i+1] = '\0';
1382 if(inet_pton(AF_INET6, ipv6_addr, (struct sockaddr *) &sock_in6.sin6_addr) > 0) {
1383 sock_in6.sin6_family = AF_INET6;
1384 memset(buf, 0, (sizeof(buf) /sizeof(buf[0])));
1385 if(inet_ntop(AF_INET6, &sock_in6.sin6_addr, buf, BUFSIZ) > 0) {
1386 xprintf("%10sinet6 addr: %s/%d", " ", buf, plen);
1387 xprintf(" Scope:");
1388 if(scope == IPV6_ADDR_ANY) xprintf(" Global");
1389 else if(scope == IPV6_ADDR_LOOPBACK) xprintf(" Host");
1390 else if(scope == IPV6_ADDR_LINKLOCAL) xprintf(" Link");
1391 else if(scope == IPV6_ADDR_SITELOCAL) xprintf(" Site");
1392 else if(scope == IPV6_ADDR_COMPATv4) xprintf(" Compat");
1393 else xprintf("Unknown");
1394 xprintf("\n");
1395 }
1396 }
1397 }
1398 }//end of while.
1399 fclose(fp);
1400 fp = NULL;
1401 return;
1402 }
1403
1404 static void display_ifconfig(IFACE_LIST *l_ptr)
1405 {
1406 HW_INFO hw_info;
1407 int hw_type = l_ptr->hw_type;
1408
1409 memset(&hw_info, 0, sizeof(HW_INFO));
1410
1411 get_hw_info(hw_type, &hw_info);
1412 xprintf("%-9s Link encap:%s ", l_ptr->dev_info.ifrname, hw_info.hw_title);
1413 print_hw_addr(hw_type, hw_info, l_ptr);
1414
1415 print_media(l_ptr);
1416
1417 xprintf("\n");
1418 if(l_ptr->ifaddr)
1419 print_ip_addr(l_ptr); //print addr, p-p addr, broadcast addr and mask addr.
1420
1421 //for ipv6 to do.
1422 print_ip6_addr(l_ptr);
1423 xprintf("%10s", " ");
1424 //print flags
1425 print_iface_flags(l_ptr);
1426 if(!l_ptr->ifrmetric)
1427 l_ptr->ifrmetric = 1;
1428 xprintf(" MTU:%d Metric:%d", l_ptr->ifrmtu, l_ptr->ifrmetric);
1429 xprintf("\n%10s", " ");
1430 xprintf("RX packets:%llu errors:%lu dropped:%lu overruns:%lu frame:%lu\n",
1431 l_ptr->dev_info.receive_packets, l_ptr->dev_info.receive_errors,
1432 l_ptr->dev_info.receive_drop, l_ptr->dev_info.receive_fifo,
1433 l_ptr->dev_info.receive_frame);
1434 //Dummy types for non ARP hardware.
1435 if((hw_type == ARPHRD_CSLIP) || (hw_type == ARPHRD_CSLIP6))
1436 xprintf("%10scompressed:%lu\n", " ", l_ptr->dev_info.receive_compressed);
1437 xprintf("%10sTX packets:%llu errors:%lu dropped:%lu overruns:%lu carrier:%lu\n", " ",
1438 l_ptr->dev_info.transmit_packets, l_ptr->dev_info.transmit_errors,
1439 l_ptr->dev_info.transmit_drop, l_ptr->dev_info.transmit_fifo,
1440 l_ptr->dev_info.transmit_carrier);
1441 xprintf("%10scollisions:%lu ", " ", l_ptr->dev_info.transmit_colls);
1442 //Dummy types for non ARP hardware.
1443 if((hw_type == ARPHRD_CSLIP) || (hw_type == ARPHRD_CSLIP6))
1444 xprintf("compressed:%lu ", l_ptr->dev_info.transmit_compressed);
1445 if(l_ptr->txqueuelen != NO_RANGE)
1446 xprintf("txqueuelen:%d ", l_ptr->txqueuelen);
1447
1448 xprintf("\n%10s", " ");
1449 xprintf("RX bytes:%llu ", l_ptr->dev_info.receive_bytes);
1450 xprintf("TX bytes:%llu\n", l_ptr->dev_info.transmit_bytes);
1451 if(l_ptr->ifrmap.irq || l_ptr->ifrmap.mem_start || l_ptr->ifrmap.dma || l_ptr->ifrmap.base_addr) {
1452 xprintf("%10s", " ");
1453 if(l_ptr->ifrmap.irq)
1454 xprintf("Interrupt:%d ", l_ptr->ifrmap.irq);
1455 if(l_ptr->ifrmap.base_addr >= IO_MAP_INDEX)
1456 xprintf("Base address:0x%lx ", l_ptr->ifrmap.base_addr);
1457 if(l_ptr->ifrmap.mem_start)
1458 xprintf("Memory:%lx-%lx ", l_ptr->ifrmap.mem_start, l_ptr->ifrmap.mem_end);
1459 if(l_ptr->ifrmap.dma)
1460 xprintf("DMA chan:%x ", l_ptr->ifrmap.dma);
1461 xprintf("\n");
1462 }
1463 xprintf("\n");
1464 return;
1465 }
1466
1467 static int show_iface(char *iface_name)
1468 {
1469 get_ifconfig_info();
1470 if(iface_name) {
1471 IFACE_LIST *l_ptr;
1472 int is_dev_found = 0;
1473 for(l_ptr = iface_list_head; l_ptr; l_ptr = l_ptr->next) {
1474 if(strcmp(l_ptr->dev_info.ifrname, iface_name) == 0) {
1475 is_dev_found = 1;
1476 display_ifconfig(l_ptr);
1477 break;
1478 }
1479 }
1480 if(!is_dev_found) {
1481 error_msg("%s: error getting interface info.", iface_name);
1482 return 1;
1483 }
1484 }
1485 else {
1486 IFACE_LIST *l_ptr;
1487 for(l_ptr = iface_list_head; l_ptr; l_ptr = l_ptr->next) {
1488 if((l_ptr->ifrflags & IFF_UP) || (toys.optflags & FLAG_a))
1489 display_ifconfig(l_ptr);
1490 }
1491 }
1492 return 0;
1493 }
1494
1495 static void clear_list(void)
1496 {
1497 IFACE_LIST *temp_ptr;
1498 while(iface_list_head != NULL) {
1499 temp_ptr = iface_list_head->next;
1500 free(iface_list_head);
1501 iface_list_head = temp_ptr;
1502 }
1503 return;
1504 }