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