l2_packet_linux.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 #include <sys/ioctl.h>
00018 #include <netpacket/packet.h>
00019 #include <net/if.h>
00020 
00021 #include "common.h"
00022 #include "eloop.h"
00023 #include "l2_packet.h"
00024 
00025 
00026 struct l2_packet_data {
00027         int fd; /* packet socket for EAPOL frames */
00028         char ifname[IFNAMSIZ + 1];
00029         int ifindex;
00030         u8 own_addr[ETH_ALEN];
00031         void (*rx_callback)(void *ctx, const u8 *src_addr,
00032                             const u8 *buf, size_t len);
00033         void *rx_callback_ctx;
00034         int l2_hdr; /* whether to include layer 2 (Ethernet) header data
00035                      * buffers */
00036 };
00037 
00038 
00039 int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
00040 {
00041         os_memcpy(addr, l2->own_addr, ETH_ALEN);
00042         return 0;
00043 }
00044 
00045 
00046 int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
00047                    const u8 *buf, size_t len)
00048 {
00049         int ret;
00050         if (l2 == NULL)
00051                 return -1;
00052         if (l2->l2_hdr) {
00053                 ret = send(l2->fd, buf, len, 0);
00054                 if (ret < 0)
00055                         perror("l2_packet_send - send");
00056         } else {
00057                 struct sockaddr_ll ll;
00058                 os_memset(&ll, 0, sizeof(ll));
00059                 ll.sll_family = AF_PACKET;
00060                 ll.sll_ifindex = l2->ifindex;
00061                 ll.sll_protocol = htons(proto);
00062                 ll.sll_halen = ETH_ALEN;
00063                 os_memcpy(ll.sll_addr, dst_addr, ETH_ALEN);
00064                 ret = sendto(l2->fd, buf, len, 0, (struct sockaddr *) &ll,
00065                              sizeof(ll));
00066                 if (ret < 0)
00067                         perror("l2_packet_send - sendto");
00068         }
00069         return ret;
00070 }
00071 
00072 
00073 static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
00074 {
00075         struct l2_packet_data *l2 = eloop_ctx;
00076         u8 buf[2300];
00077         int res;
00078         struct sockaddr_ll ll;
00079         socklen_t fromlen;
00080 
00081         os_memset(&ll, 0, sizeof(ll));
00082         fromlen = sizeof(ll);
00083         res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
00084                        &fromlen);
00085         if (res < 0) {
00086                 perror("l2_packet_receive - recvfrom");
00087                 return;
00088         }
00089 
00090         l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
00091 }
00092 
00093 
00094 struct l2_packet_data * l2_packet_init(
00095         const char *ifname, const u8 *own_addr, unsigned short protocol,
00096         void (*rx_callback)(void *ctx, const u8 *src_addr,
00097                             const u8 *buf, size_t len),
00098         void *rx_callback_ctx, int l2_hdr)
00099 {
00100         struct l2_packet_data *l2;
00101         struct ifreq ifr;
00102         struct sockaddr_ll ll;
00103 
00104         l2 = os_zalloc(sizeof(struct l2_packet_data));
00105         if (l2 == NULL)
00106                 return NULL;
00107         os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname));
00108         l2->rx_callback = rx_callback;
00109         l2->rx_callback_ctx = rx_callback_ctx;
00110         l2->l2_hdr = l2_hdr;
00111 
00112         l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM,
00113                         htons(protocol));
00114         if (l2->fd < 0) {
00115                 perror("socket(PF_PACKET)");
00116                 os_free(l2);
00117                 return NULL;
00118         }
00119         os_memset(&ifr, 0, sizeof(ifr));
00120         os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
00121         if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) {
00122                 perror("ioctl[SIOCGIFINDEX]");
00123                 close(l2->fd);
00124                 os_free(l2);
00125                 return NULL;
00126         }
00127         l2->ifindex = ifr.ifr_ifindex;
00128 
00129         os_memset(&ll, 0, sizeof(ll));
00130         ll.sll_family = PF_PACKET;
00131         ll.sll_ifindex = ifr.ifr_ifindex;
00132         ll.sll_protocol = htons(protocol);
00133         if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
00134                 perror("bind[PF_PACKET]");
00135                 close(l2->fd);
00136                 os_free(l2);
00137                 return NULL;
00138         }
00139 
00140         if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) < 0) {
00141                 perror("ioctl[SIOCGIFHWADDR]");
00142                 close(l2->fd);
00143                 os_free(l2);
00144                 return NULL;
00145         }
00146         os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
00147 
00148         eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
00149 
00150         return l2;
00151 }
00152 
00153 
00154 void l2_packet_deinit(struct l2_packet_data *l2)
00155 {
00156         if (l2 == NULL)
00157                 return;
00158 
00159         if (l2->fd >= 0) {
00160                 eloop_unregister_read_sock(l2->fd);
00161                 close(l2->fd);
00162         }
00163                 
00164         os_free(l2);
00165 }
00166 
00167 
00168 int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
00169 {
00170         int s;
00171         struct ifreq ifr;
00172         struct sockaddr_in *saddr;
00173         size_t res;
00174 
00175         s = socket(PF_INET, SOCK_DGRAM, 0);
00176         if (s < 0) {
00177                 perror("socket");
00178                 return -1;
00179         }
00180         os_memset(&ifr, 0, sizeof(ifr));
00181         os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
00182         if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
00183                 if (errno != EADDRNOTAVAIL)
00184                         perror("ioctl[SIOCGIFADDR]");
00185                 close(s);
00186                 return -1;
00187         }
00188         close(s);
00189         saddr = aliasing_hide_typecast(&ifr.ifr_addr, struct sockaddr_in);
00190         if (saddr->sin_family != AF_INET)
00191                 return -1;
00192         res = os_strlcpy(buf, inet_ntoa(saddr->sin_addr), len);
00193         if (res >= len)
00194                 return -1;
00195         return 0;
00196 }
00197 
00198 
00199 void l2_packet_notify_auth_start(struct l2_packet_data *l2)
00200 {
00201 }
00202 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:52 2009 for hostapd by  doxygen 1.6.1