00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00017
00018
00019 #include <arpa/inet.h>
00020 #include <linux/if.h>
00021 #include <linux/if_tun.h>
00022 #include <sys/ioctl.h>
00023 #include <sys/socket.h>
00024 #include <errno.h>
00025 #include <fcntl.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 #include "netdevice.h"
00030 #include "iwc_print.h"
00031
00032 #define PROC_IFINET6 "/proc/net/if_inet6"
00033 #define IPV6_ADDR_LOOPBACK 0x0010U
00034 #define IPV6_ADDR_LINKLOCAL 0x0020U
00035 #define IPV6_ADDR_SITELOCAL 0x0040U
00036 #define IPV6_ADDR_COMPATv4 0x0080U
00037
00038
00039
00040
00041 extern int ip_family;
00042 int skfd = -1;
00043
00044
00045
00046
00051 int
00052 init_udp_socket(void)
00053 {
00054 if ((skfd = socket(ip_family, SOCK_DGRAM, 0)) == -1)
00055 iwc_error("Failed to open socket (%s)\n", strerror(errno));
00056
00057 return skfd;
00058 }
00059
00066 int
00067 get_mac_by_dev(unsigned char *mac, const char *dev_name)
00068 {
00069 struct ifreq ifr;
00070
00071 strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);
00072 if (ioctl(skfd, SIOCGIFHWADDR, &ifr) != 0)
00073 {
00074 if (errno == ENODEV)
00075 iwc_error("No such device (%s)\n", ifr.ifr_name);
00076 else
00077 iwc_error("Failed to get MAC address of %s (%s)\n",
00078 dev_name, strerror(errno));
00079 return -1;
00080 }
00081 memmove(mac, ifr.ifr_hwaddr.sa_data, 6);
00082
00083 return 0;
00084 }
00085
00092 int
00093 get_ip_by_dev(addr_storage *addr, const char *dev_name)
00094 {
00095 struct ifreq ifr = { .ifr_mtu = 0 };
00096 FILE *f = NULL;
00097 int plen, scope, dad_status, if_idx;
00098 static char flags[200];
00099 char addr6p[8][5];
00100 char addr6[40], name[IFNAMSIZ];
00101
00102 switch (ip_family)
00103 {
00104 case AF_INET:
00105 strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);
00106 if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0)
00107 {
00108 if (errno == ENODEV)
00109 iwc_error("No such device (%s)\n", ifr.ifr_name);
00110 else
00111 iwc_error("Failed to get IP address of %s (%s)\n",
00112 dev_name, strerror(errno));
00113 return -1;
00114 }
00115
00116 if (addr != NULL)
00117 {
00118 struct sockaddr_in *sockaddr =
00119 (struct sockaddr_in *) &(ifr.ifr_addr);
00120 memmove(addr, &(*sockaddr).sin_addr, sizeof(struct in_addr));
00121 }
00122 break;
00123
00124
00125
00126 case AF_INET6:
00127 if ((f = fopen(PROC_IFINET6, "r")) != NULL)
00128 {
00129 while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
00130 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
00131 addr6p[4], addr6p[5], addr6p[6], addr6p[7],
00132 &if_idx, &plen, &scope, &dad_status, name) != EOF)
00133 {
00134 if (!strcmp(dev_name, name))
00135 {
00136 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s",
00137 addr6p[0], addr6p[1], addr6p[2], addr6p[3],
00138 addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
00139 if (addr != NULL)
00140 inet_pton(AF_INET6, addr6, addr);
00141
00142
00143
00144 flags[0] = '<'; flags[1] = 0;
00145 if (scope & IPV6_ADDR_COMPATv4) {
00146 strcat(flags, "compat,");
00147 scope -= IPV6_ADDR_COMPATv4;
00148 }
00149 if (scope == 0)
00150 strcat(flags, "global,");
00151 if (scope & IPV6_ADDR_LINKLOCAL)
00152 strcat(flags, "link,");
00153 if (scope & IPV6_ADDR_SITELOCAL)
00154 strcat(flags, "site,");
00155 if (scope & IPV6_ADDR_LOOPBACK)
00156 strcat(flags, "host,");
00157 if (flags[strlen(flags)-1] == ',')
00158 flags[strlen(flags)-1] = '>';
00159 else
00160 flags[strlen(flags)-1] = 0;
00161
00162 }
00163 }
00164 } else {
00165 iwc_error("Kernel doesn't support IPv6 (%s): %s\n",
00166 PROC_IFINET6, strerror(errno));
00167 return -1;
00168 }
00169 break;
00170 }
00171
00172 return 0;
00173 }
00174
00180 int
00181 get_mtu_by_dev(const char *dev_name)
00182 {
00183 struct ifreq ifr;
00184
00185 strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);
00186 if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
00187 {
00188 if (errno == ENODEV)
00189 iwc_error("No such device (%s)\n", ifr.ifr_name);
00190 else
00191 iwc_error("Failed to get MTU size of %s (%s)\n", \
00192 dev_name, strerror(errno));
00193 return -1;
00194 }
00195
00196
00197 return ifr.ifr_mtu;
00198 }
00199
00205 int
00206 bind_net_socket(const struct addrinfo *addr)
00207 {
00208 int fd = -1;
00209
00210 if ((fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol)) < 0)
00211 {
00212 iwc_error("Failed to open socket (%s)\n", strerror(errno));
00213 return -1;
00214 }
00215
00216 if (bind(fd, (struct sockaddr *) addr->ai_addr, addr->ai_addrlen) == -1)
00217 {
00218 close(fd);
00219 iwc_error("Couldn't bind to local interface (%s)\n", strerror(errno));
00220 return -1;
00221 }
00222
00223 return fd;
00224 }
00225
00231 int
00232 open_tap_socket(const char *dev_name)
00233 {
00234 int fd = 0, err = 0;
00235 struct ifreq ifr;
00236
00237 if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
00238 {
00239 iwc_error("Failed to open /dev/net/tun (%s)\n", strerror(errno));
00240 return -1;
00241 }
00242 memset(&ifr, 0, sizeof(ifr));
00243 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
00244
00245 if (*dev_name)
00246 memmove(ifr.ifr_name, dev_name, IFNAMSIZ);
00247 err = ioctl(fd, TUNSETIFF, (void *) &ifr);
00248 err |= ioctl(fd, TUNSETNOCSUM, 1);
00249 if (err != 0)
00250 {
00251 close(fd);
00252 iwc_error("Ioctl() on device %s failed (%s)\n",
00253 dev_name, strerror(errno));
00254 return -1;
00255 }
00256
00257 return fd;
00258 }