l2_packet_linux.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /*
  2. * WPA Supplicant - Layer2 packet handling with Linux packet sockets
  3. * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "includes.h"
  9. #include <sys/ioctl.h>
  10. #include <netpacket/packet.h>
  11. #include <net/if.h>
  12. #include <linux/filter.h>
  13. #include "common.h"
  14. #include "eloop.h"
  15. #include "l2_packet.h"
  16. struct l2_packet_data {
  17. int fd; /* packet socket for EAPOL frames */
  18. char ifname[IFNAMSIZ + 1];
  19. int ifindex;
  20. u8 own_addr[ETH_ALEN];
  21. void (*rx_callback)(void *ctx, const u8 *src_addr,
  22. const u8 *buf, size_t len);
  23. void *rx_callback_ctx;
  24. int l2_hdr; /* whether to include layer 2 (Ethernet) header data
  25. * buffers */
  26. /* For working around Linux packet socket behavior and regression. */
  27. int fd_br_rx;
  28. };
  29. /* Generated by 'sudo tcpdump -s 3000 -dd greater 278 and ip and udp and
  30. * src port bootps and dst port bootpc'
  31. */
  32. static struct sock_filter dhcp_sock_filter_insns[] = {
  33. { 0x80, 0, 0, 0x00000000 },
  34. { 0x35, 0, 12, 0x00000116 },
  35. { 0x28, 0, 0, 0x0000000c },
  36. { 0x15, 0, 10, 0x00000800 },
  37. { 0x30, 0, 0, 0x00000017 },
  38. { 0x15, 0, 8, 0x00000011 },
  39. { 0x28, 0, 0, 0x00000014 },
  40. { 0x45, 6, 0, 0x00001fff },
  41. { 0xb1, 0, 0, 0x0000000e },
  42. { 0x48, 0, 0, 0x0000000e },
  43. { 0x15, 0, 3, 0x00000043 },
  44. { 0x48, 0, 0, 0x00000010 },
  45. { 0x15, 0, 1, 0x00000044 },
  46. { 0x6, 0, 0, 0x00000bb8 },
  47. { 0x6, 0, 0, 0x00000000 },
  48. };
  49. static const struct sock_fprog dhcp_sock_filter = {
  50. .len = ARRAY_SIZE(dhcp_sock_filter_insns),
  51. .filter = dhcp_sock_filter_insns,
  52. };
  53. /* Generated by 'sudo tcpdump -dd -s 1500 multicast and ip6[6]=58' */
  54. static struct sock_filter ndisc_sock_filter_insns[] = {
  55. { 0x30, 0, 0, 0x00000000 },
  56. { 0x45, 0, 5, 0x00000001 },
  57. { 0x28, 0, 0, 0x0000000c },
  58. { 0x15, 0, 3, 0x000086dd },
  59. { 0x30, 0, 0, 0x00000014 },
  60. { 0x15, 0, 1, 0x0000003a },
  61. { 0x6, 0, 0, 0x000005dc },
  62. { 0x6, 0, 0, 0x00000000 },
  63. };
  64. static const struct sock_fprog ndisc_sock_filter = {
  65. .len = ARRAY_SIZE(ndisc_sock_filter_insns),
  66. .filter = ndisc_sock_filter_insns,
  67. };
  68. int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
  69. {
  70. os_memcpy(addr, l2->own_addr, ETH_ALEN);
  71. return 0;
  72. }
  73. int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
  74. const u8 *buf, size_t len)
  75. {
  76. int ret;
  77. if (l2 == NULL)
  78. return -1;
  79. if (l2->l2_hdr) {
  80. ret = send(l2->fd, buf, len, 0);
  81. if (ret < 0)
  82. wpa_printf(MSG_ERROR, "l2_packet_send - send: %s",
  83. strerror(errno));
  84. } else {
  85. struct sockaddr_ll ll;
  86. os_memset(&ll, 0, sizeof(ll));
  87. ll.sll_family = AF_PACKET;
  88. ll.sll_ifindex = l2->ifindex;
  89. ll.sll_protocol = htons(proto);
  90. ll.sll_halen = ETH_ALEN;
  91. os_memcpy(ll.sll_addr, dst_addr, ETH_ALEN);
  92. ret = sendto(l2->fd, buf, len, 0, (struct sockaddr *) &ll,
  93. sizeof(ll));
  94. if (ret < 0) {
  95. wpa_printf(MSG_ERROR, "l2_packet_send - sendto: %s",
  96. strerror(errno));
  97. }
  98. }
  99. return ret;
  100. }
  101. static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
  102. {
  103. struct l2_packet_data *l2 = eloop_ctx;
  104. u8 buf[2300];
  105. int res;
  106. struct sockaddr_ll ll;
  107. socklen_t fromlen;
  108. os_memset(&ll, 0, sizeof(ll));
  109. fromlen = sizeof(ll);
  110. res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
  111. &fromlen);
  112. if (res < 0) {
  113. wpa_printf(MSG_DEBUG, "l2_packet_receive - recvfrom: %s",
  114. strerror(errno));
  115. return;
  116. }
  117. l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
  118. if (l2->fd_br_rx >= 0) {
  119. wpa_printf(MSG_DEBUG, "l2_packet_receive: Main packet socket for %s seems to have working RX - close workaround bridge socket",
  120. l2->ifname);
  121. eloop_unregister_read_sock(l2->fd_br_rx);
  122. close(l2->fd_br_rx);
  123. l2->fd_br_rx = -1;
  124. }
  125. }
  126. static void l2_packet_receive_br(int sock, void *eloop_ctx, void *sock_ctx)
  127. {
  128. struct l2_packet_data *l2 = eloop_ctx;
  129. u8 buf[2300];
  130. int res;
  131. struct sockaddr_ll ll;
  132. socklen_t fromlen;
  133. os_memset(&ll, 0, sizeof(ll));
  134. fromlen = sizeof(ll);
  135. res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll,
  136. &fromlen);
  137. if (res < 0) {
  138. wpa_printf(MSG_DEBUG, "l2_packet_receive_br - recvfrom: %s",
  139. strerror(errno));
  140. return;
  141. }
  142. l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res);
  143. }
  144. struct l2_packet_data * l2_packet_init(
  145. const char *ifname, const u8 *own_addr, unsigned short protocol,
  146. void (*rx_callback)(void *ctx, const u8 *src_addr,
  147. const u8 *buf, size_t len),
  148. void *rx_callback_ctx, int l2_hdr)
  149. {
  150. struct l2_packet_data *l2;
  151. struct ifreq ifr;
  152. struct sockaddr_ll ll;
  153. l2 = os_zalloc(sizeof(struct l2_packet_data));
  154. if (l2 == NULL)
  155. return NULL;
  156. os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname));
  157. l2->rx_callback = rx_callback;
  158. l2->rx_callback_ctx = rx_callback_ctx;
  159. l2->l2_hdr = l2_hdr;
  160. l2->fd_br_rx = -1;
  161. l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM,
  162. htons(protocol));
  163. if (l2->fd < 0) {
  164. wpa_printf(MSG_ERROR, "%s: socket(PF_PACKET): %s",
  165. __func__, strerror(errno));
  166. os_free(l2);
  167. return NULL;
  168. }
  169. os_memset(&ifr, 0, sizeof(ifr));
  170. os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
  171. if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) {
  172. wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFINDEX]: %s",
  173. __func__, strerror(errno));
  174. close(l2->fd);
  175. os_free(l2);
  176. return NULL;
  177. }
  178. l2->ifindex = ifr.ifr_ifindex;
  179. os_memset(&ll, 0, sizeof(ll));
  180. ll.sll_family = PF_PACKET;
  181. ll.sll_ifindex = ifr.ifr_ifindex;
  182. ll.sll_protocol = htons(protocol);
  183. if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
  184. wpa_printf(MSG_ERROR, "%s: bind[PF_PACKET]: %s",
  185. __func__, strerror(errno));
  186. close(l2->fd);
  187. os_free(l2);
  188. return NULL;
  189. }
  190. if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) < 0) {
  191. wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFHWADDR]: %s",
  192. __func__, strerror(errno));
  193. close(l2->fd);
  194. os_free(l2);
  195. return NULL;
  196. }
  197. os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
  198. eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
  199. return l2;
  200. }
  201. struct l2_packet_data * l2_packet_init_bridge(
  202. const char *br_ifname, const char *ifname, const u8 *own_addr,
  203. unsigned short protocol,
  204. void (*rx_callback)(void *ctx, const u8 *src_addr,
  205. const u8 *buf, size_t len),
  206. void *rx_callback_ctx, int l2_hdr)
  207. {
  208. struct l2_packet_data *l2;
  209. struct sock_filter ethertype_sock_filter_insns[] = {
  210. /* Load ethertype */
  211. BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 2 * ETH_ALEN),
  212. /* Jump over next statement if ethertype does not match */
  213. BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, protocol, 0, 1),
  214. /* Ethertype match - return all */
  215. BPF_STMT(BPF_RET | BPF_K, ~0),
  216. /* No match - drop */
  217. BPF_STMT(BPF_RET | BPF_K, 0)
  218. };
  219. const struct sock_fprog ethertype_sock_filter = {
  220. .len = ARRAY_SIZE(ethertype_sock_filter_insns),
  221. .filter = ethertype_sock_filter_insns,
  222. };
  223. struct sockaddr_ll ll;
  224. l2 = l2_packet_init(br_ifname, own_addr, protocol, rx_callback,
  225. rx_callback_ctx, l2_hdr);
  226. if (!l2)
  227. return NULL;
  228. /*
  229. * The Linux packet socket behavior has changed over the years and there
  230. * is an inconvenient regression in it that breaks RX for a specific
  231. * protocol from interfaces in a bridge when that interface is not in
  232. * fully operation state (i.e., when in station mode and not completed
  233. * authorization). To work around this, register ETH_P_ALL version of
  234. * the packet socket bound to the real netdev and use socket filter to
  235. * match the ethertype value. This version is less efficient, but
  236. * required for functionality with many kernel version. If the main
  237. * packet socket is found to be working, this less efficient version
  238. * gets closed automatically.
  239. */
  240. l2->fd_br_rx = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM,
  241. htons(ETH_P_ALL));
  242. if (l2->fd_br_rx < 0) {
  243. wpa_printf(MSG_DEBUG, "%s: socket(PF_PACKET-fd_br_rx): %s",
  244. __func__, strerror(errno));
  245. /* try to continue without the workaround RX socket */
  246. return l2;
  247. }
  248. os_memset(&ll, 0, sizeof(ll));
  249. ll.sll_family = PF_PACKET;
  250. ll.sll_ifindex = if_nametoindex(ifname);
  251. ll.sll_protocol = htons(ETH_P_ALL);
  252. if (bind(l2->fd_br_rx, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
  253. wpa_printf(MSG_DEBUG, "%s: bind[PF_PACKET-fd_br_rx]: %s",
  254. __func__, strerror(errno));
  255. /* try to continue without the workaround RX socket */
  256. close(l2->fd_br_rx);
  257. l2->fd_br_rx = -1;
  258. return l2;
  259. }
  260. if (setsockopt(l2->fd_br_rx, SOL_SOCKET, SO_ATTACH_FILTER,
  261. &ethertype_sock_filter, sizeof(struct sock_fprog))) {
  262. wpa_printf(MSG_DEBUG,
  263. "l2_packet_linux: setsockopt(SO_ATTACH_FILTER) failed: %s",
  264. strerror(errno));
  265. /* try to continue without the workaround RX socket */
  266. close(l2->fd_br_rx);
  267. l2->fd_br_rx = -1;
  268. return l2;
  269. }
  270. eloop_register_read_sock(l2->fd_br_rx, l2_packet_receive_br, l2, NULL);
  271. return l2;
  272. }
  273. void l2_packet_deinit(struct l2_packet_data *l2)
  274. {
  275. if (l2 == NULL)
  276. return;
  277. if (l2->fd >= 0) {
  278. eloop_unregister_read_sock(l2->fd);
  279. close(l2->fd);
  280. }
  281. if (l2->fd_br_rx >= 0) {
  282. eloop_unregister_read_sock(l2->fd_br_rx);
  283. close(l2->fd_br_rx);
  284. }
  285. os_free(l2);
  286. }
  287. int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
  288. {
  289. int s;
  290. struct ifreq ifr;
  291. struct sockaddr_in *saddr;
  292. size_t res;
  293. s = socket(PF_INET, SOCK_DGRAM, 0);
  294. if (s < 0) {
  295. wpa_printf(MSG_ERROR, "%s: socket: %s",
  296. __func__, strerror(errno));
  297. return -1;
  298. }
  299. os_memset(&ifr, 0, sizeof(ifr));
  300. os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
  301. if (ioctl(s, SIOCGIFADDR, &ifr) < 0) {
  302. if (errno != EADDRNOTAVAIL)
  303. wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFADDR]: %s",
  304. __func__, strerror(errno));
  305. close(s);
  306. return -1;
  307. }
  308. close(s);
  309. saddr = aliasing_hide_typecast(&ifr.ifr_addr, struct sockaddr_in);
  310. if (saddr->sin_family != AF_INET)
  311. return -1;
  312. res = os_strlcpy(buf, inet_ntoa(saddr->sin_addr), len);
  313. if (res >= len)
  314. return -1;
  315. return 0;
  316. }
  317. void l2_packet_notify_auth_start(struct l2_packet_data *l2)
  318. {
  319. }
  320. int l2_packet_set_packet_filter(struct l2_packet_data *l2,
  321. enum l2_packet_filter_type type)
  322. {
  323. const struct sock_fprog *sock_filter;
  324. switch (type) {
  325. case L2_PACKET_FILTER_DHCP:
  326. sock_filter = &dhcp_sock_filter;
  327. break;
  328. case L2_PACKET_FILTER_NDISC:
  329. sock_filter = &ndisc_sock_filter;
  330. break;
  331. default:
  332. return -1;
  333. }
  334. if (setsockopt(l2->fd, SOL_SOCKET, SO_ATTACH_FILTER,
  335. sock_filter, sizeof(struct sock_fprog))) {
  336. wpa_printf(MSG_ERROR,
  337. "l2_packet_linux: setsockopt(SO_ATTACH_FILTER) failed: %s",
  338. strerror(errno));
  339. return -1;
  340. }
  341. return 0;
  342. }