Annotation of embedaddon/iftop/addrs_ioctl.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * addrs_ioctl.c:
                      3:  *
                      4:  * Provides the get_addrs_ioctl() function for use on systems that
                      5:  * support a simple socket ioctl for acquiring low-level ethernet
                      6:  * information about interfaces.
                      7:  *
                      8:  */
                      9: 
                     10: #include <stdio.h>
                     11: #include <stdlib.h>
                     12: #include <unistd.h>
                     13: #include <string.h>
                     14: 
                     15: #include <sys/types.h>
                     16: #include <sys/ioctl.h>
                     17: #include <sys/socket.h>
                     18: #include <net/if.h>
                     19: #include <netinet/in.h>
                     20: 
1.1.1.2 ! misho      21: #if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ \
        !            22:       || ( defined __GLIBC__ && ! defined __linux__ )
1.1       misho      23: #include <sys/param.h>
                     24: #include <sys/sysctl.h>
                     25: #include <net/if_dl.h>
                     26: #endif
                     27: 
1.1.1.2 ! misho      28: #ifdef USE_GETIFADDRS
        !            29: #include <ifaddrs.h>
        !            30: #endif
        !            31: 
1.1       misho      32: #include "iftop.h"
                     33: 
                     34: /*
                     35:  * This function identifies the IP address and ethernet address for the requested
                     36:  * interface
                     37:  *
                     38:  * This function returns -1 on catastrophic failure, or a bitwise OR of the
                     39:  * following values:
                     40:  *
                     41:  * 1 - Was able to get the ethernet address
                     42:  * 2 - Was able to get the IP address
                     43:  *
                     44:  * This function should return 3 if all information was found
                     45:  */
                     46: 
                     47: int
1.1.1.2 ! misho      48: get_addrs_ioctl(char *interface, char if_hw_addr[], struct in_addr *if_ip_addr, struct in6_addr *if_ip6_addr)
1.1       misho      49: {
                     50:   int s;
                     51:   struct ifreq ifr = {};
                     52:   int got_hw_addr = 0;
                     53:   int got_ip_addr = 0;
1.1.1.2 ! misho      54:   int got_ip6_addr = 0;
        !            55: #ifdef USE_GETIFADDRS
        !            56:   struct ifaddrs *ifa, *ifas;
        !            57: #endif
1.1       misho      58: 
                     59:   /* -- */
                     60: 
1.1.1.2 ! misho      61:   s = socket(AF_INET, SOCK_DGRAM, 0); /* any sort of IP socket will do */
1.1       misho      62: 
                     63:   if (s == -1) {
                     64:     perror("socket");
                     65:     return -1;
                     66:   }
                     67: 
                     68:   fprintf(stderr,"interface: %s\n", interface);
                     69: 
                     70:   memset(if_hw_addr, 0, 6);
                     71:   strncpy(ifr.ifr_name, interface, IFNAMSIZ);
                     72: 
                     73: #ifdef SIOCGIFHWADDR
                     74:   if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
                     75:     fprintf(stderr, "Error getting hardware address for interface: %s\n", interface); 
                     76:     perror("ioctl(SIOCGIFHWADDR)");
                     77:   }
                     78:   else {
                     79:     memcpy(if_hw_addr, ifr.ifr_hwaddr.sa_data, 6);
                     80:     got_hw_addr = 1;
                     81:   }
                     82: #else
1.1.1.2 ! misho      83: #if defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__ \
        !            84:       || ( defined __GLIBC__ && ! defined __linux__ )
1.1       misho      85:   {
                     86:     int sysctlparam[6] = {CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0};
                     87:     size_t needed = 0;
                     88:     char *buf = NULL;
                     89:     struct if_msghdr *msghdr = NULL;
                     90:     sysctlparam[5] = if_nametoindex(interface);
                     91:     if (sysctlparam[5] == 0) {
                     92:       fprintf(stderr, "Error getting hardware address for interface: %s\n", interface);
                     93:     }
1.1.1.2 ! misho      94:     else if (sysctl(sysctlparam, 6, NULL, &needed, NULL, 0) < 0) {
1.1       misho      95:       fprintf(stderr, "Error getting hardware address for interface: %s\n", interface);
                     96:     }
1.1.1.2 ! misho      97:     else if ((buf = malloc(needed)) == NULL) {
1.1       misho      98:       fprintf(stderr, "Error getting hardware address for interface: %s\n", interface);
                     99:     }
1.1.1.2 ! misho     100:     else if (sysctl(sysctlparam, 6, buf, &needed, NULL, 0) < 0) {
1.1       misho     101:       fprintf(stderr, "Error getting hardware address for interface: %s\n", interface);
                    102:       free(buf);
                    103:     }
1.1.1.2 ! misho     104:     else {
        !           105:       msghdr = (struct if_msghdr *) buf;
        !           106:       memcpy(if_hw_addr, LLADDR((struct sockaddr_dl *)(buf + sizeof(struct if_msghdr) - sizeof(struct if_data) + sizeof(struct if_data))), 6);
        !           107:       free(buf);
        !           108:       got_hw_addr = 1;
        !           109:     }
1.1       misho     110:   }
                    111: #else
                    112:   fprintf(stderr, "Cannot obtain hardware address on this platform\n");
                    113: #endif
                    114: #endif
                    115:   
                    116:   /* Get the IP address of the interface */
1.1.1.2 ! misho     117: #ifdef USE_GETIFADDRS
        !           118:   if (getifaddrs(&ifas) == -1) {
        !           119:     fprintf(stderr, "Unable to get IP address for interface: %s\n", interface); 
        !           120:     perror("getifaddrs()");
        !           121:   }
        !           122:   else {
        !           123:      for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
        !           124:         if (got_ip_addr && got_ip6_addr)
        !           125:            break; /* Search is already complete. */
        !           126: 
        !           127:         if (strcmp(ifa->ifa_name, interface))
        !           128:            continue; /* Not our interface. */
        !           129: 
        !           130:         if (ifa->ifa_addr == NULL)
        !           131:            continue; /* Skip NULL interface address. */
        !           132: 
        !           133:         if ( (ifa->ifa_addr->sa_family != AF_INET)
        !           134:               && (ifa->ifa_addr->sa_family != AF_INET6) )
        !           135:            continue; /* AF_PACKET is beyond our scope. */
        !           136: 
        !           137:         if ( (ifa->ifa_addr->sa_family == AF_INET)
        !           138:               && !got_ip_addr ) {
        !           139:            got_ip_addr = 2;
        !           140:            memcpy(if_ip_addr,
        !           141:                  &(((struct sockaddr_in *) ifa->ifa_addr)->sin_addr),
        !           142:                  sizeof(*if_ip_addr));
        !           143:            continue;
        !           144:         }
        !           145:         /* Must be a IPv6 address at this point. */
        !           146:         struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) ifa->ifa_addr;
        !           147: 
        !           148:         if ( IN6_IS_ADDR_LINKLOCAL(&(sa6->sin6_addr))
        !           149:               || IN6_IS_ADDR_SITELOCAL(&(sa6->sin6_addr)) )
        !           150:            continue;
        !           151: 
        !           152:         /* A useful IPv6 address. */
        !           153:         memcpy(if_ip6_addr, &(sa6->sin6_addr), sizeof(*if_ip6_addr));
        !           154:         got_ip6_addr = 4;
        !           155:      }
        !           156:      freeifaddrs(ifas);
        !           157:   } /* getifaddrs() */
        !           158: #elif defined(SIOCGIFADDR)
1.1       misho     159:   (*(struct sockaddr_in *) &ifr.ifr_addr).sin_family = AF_INET;
                    160:   if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
                    161:     fprintf(stderr, "Unable to get IP address for interface: %s\n", interface); 
                    162:     perror("ioctl(SIOCGIFADDR)");
                    163:   }
                    164:   else {
                    165:     memcpy(if_ip_addr, &((*(struct sockaddr_in *) &ifr.ifr_addr).sin_addr), sizeof(struct in_addr));
                    166:     got_ip_addr = 2;
                    167:   }
                    168: #else
                    169:   fprintf(stderr, "Cannot obtain IP address on this platform\n");
                    170: #endif
                    171:   
                    172:   close(s);
                    173: 
1.1.1.2 ! misho     174:   return got_hw_addr + got_ip_addr + got_ip6_addr;
1.1       misho     175: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>