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