1 /* 2 * WPA Supplicant - Layer2 packet handling with Linux packet sockets 3 * Copyright (c) 2003-2015, Jouni Malinen <j (at) w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 #include <sys/ioctl.h> 11 #include <netpacket/packet.h> 12 #include <net/if.h> 13 #include <linux/filter.h> 14 15 #include "common.h" 16 #include "eloop.h" 17 #include "crypto/sha1.h" 18 #include "crypto/crypto.h" 19 #include "l2_packet.h" 20 21 22 struct l2_packet_data { 23 int fd; /* packet socket for EAPOL frames */ 24 char ifname[IFNAMSIZ + 1]; 25 int ifindex; 26 u8 own_addr[ETH_ALEN]; 27 void (*rx_callback)(void *ctx, const u8 *src_addr, 28 const u8 *buf, size_t len); 29 void *rx_callback_ctx; 30 int l2_hdr; /* whether to include layer 2 (Ethernet) header data 31 * buffers */ 32 33 #ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR 34 /* For working around Linux packet socket behavior and regression. */ 35 int fd_br_rx; 36 int last_from_br, last_from_br_prev; 37 u8 last_hash[SHA1_MAC_LEN]; 38 u8 last_hash_prev[SHA1_MAC_LEN]; 39 unsigned int num_rx_br; 40 #endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */ 41 }; 42 43 /* Generated by 'sudo tcpdump -s 3000 -dd greater 278 and ip and udp and 44 * src port bootps and dst port bootpc' 45 */ 46 static struct sock_filter dhcp_sock_filter_insns[] = { 47 { 0x80, 0, 0, 0x00000000 }, 48 { 0x35, 0, 12, 0x00000116 }, 49 { 0x28, 0, 0, 0x0000000c }, 50 { 0x15, 0, 10, 0x00000800 }, 51 { 0x30, 0, 0, 0x00000017 }, 52 { 0x15, 0, 8, 0x00000011 }, 53 { 0x28, 0, 0, 0x00000014 }, 54 { 0x45, 6, 0, 0x00001fff }, 55 { 0xb1, 0, 0, 0x0000000e }, 56 { 0x48, 0, 0, 0x0000000e }, 57 { 0x15, 0, 3, 0x00000043 }, 58 { 0x48, 0, 0, 0x00000010 }, 59 { 0x15, 0, 1, 0x00000044 }, 60 { 0x6, 0, 0, 0x00000bb8 }, 61 { 0x6, 0, 0, 0x00000000 }, 62 }; 63 64 static const struct sock_fprog dhcp_sock_filter = { 65 .len = ARRAY_SIZE(dhcp_sock_filter_insns), 66 .filter = dhcp_sock_filter_insns, 67 }; 68 69 70 /* Generated by 'sudo tcpdump -dd -s 1500 multicast and ip6[6]=58' */ 71 static struct sock_filter ndisc_sock_filter_insns[] = { 72 { 0x30, 0, 0, 0x00000000 }, 73 { 0x45, 0, 5, 0x00000001 }, 74 { 0x28, 0, 0, 0x0000000c }, 75 { 0x15, 0, 3, 0x000086dd }, 76 { 0x30, 0, 0, 0x00000014 }, 77 { 0x15, 0, 1, 0x0000003a }, 78 { 0x6, 0, 0, 0x000005dc }, 79 { 0x6, 0, 0, 0x00000000 }, 80 }; 81 82 static const struct sock_fprog ndisc_sock_filter = { 83 .len = ARRAY_SIZE(ndisc_sock_filter_insns), 84 .filter = ndisc_sock_filter_insns, 85 }; 86 87 88 int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) 89 { 90 os_memcpy(addr, l2->own_addr, ETH_ALEN); 91 return 0; 92 } 93 94 95 int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, 96 const u8 *buf, size_t len) 97 { 98 int ret; 99 if (l2 == NULL) 100 return -1; 101 if (l2->l2_hdr) { 102 ret = send(l2->fd, buf, len, 0); 103 if (ret < 0) 104 wpa_printf(MSG_ERROR, "l2_packet_send - send: %s", 105 strerror(errno)); 106 } else { 107 struct sockaddr_ll ll; 108 os_memset(&ll, 0, sizeof(ll)); 109 ll.sll_family = AF_PACKET; 110 ll.sll_ifindex = l2->ifindex; 111 ll.sll_protocol = htons(proto); 112 ll.sll_halen = ETH_ALEN; 113 os_memcpy(ll.sll_addr, dst_addr, ETH_ALEN); 114 ret = sendto(l2->fd, buf, len, 0, (struct sockaddr *) &ll, 115 sizeof(ll)); 116 if (ret < 0) { 117 wpa_printf(MSG_ERROR, "l2_packet_send - sendto: %s", 118 strerror(errno)); 119 } 120 } 121 return ret; 122 } 123 124 125 static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) 126 { 127 struct l2_packet_data *l2 = eloop_ctx; 128 u8 buf[2300]; 129 int res; 130 struct sockaddr_ll ll; 131 socklen_t fromlen; 132 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 - recvfrom: %s", 139 strerror(errno)); 140 return; 141 } 142 143 wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d", 144 __func__, MAC2STR(ll.sll_addr), (int) res); 145 146 #ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR 147 if (l2->fd_br_rx >= 0) { 148 u8 hash[SHA1_MAC_LEN]; 149 const u8 *addr[1]; 150 size_t len[1]; 151 152 /* 153 * Close the workaround socket if the kernel version seems to be 154 * able to deliver packets through the packet socket before 155 * authorization has been completed (in dormant state). 156 */ 157 if (l2->num_rx_br <= 1) { 158 wpa_printf(MSG_DEBUG, 159 "l2_packet_receive: Main packet socket for %s seems to have working RX - close workaround bridge socket", 160 l2->ifname); 161 eloop_unregister_read_sock(l2->fd_br_rx); 162 close(l2->fd_br_rx); 163 l2->fd_br_rx = -1; 164 } 165 166 addr[0] = buf; 167 len[0] = res; 168 sha1_vector(1, addr, len, hash); 169 if (l2->last_from_br && 170 os_memcmp(hash, l2->last_hash, SHA1_MAC_LEN) == 0) { 171 wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", 172 __func__); 173 return; 174 } 175 if (l2->last_from_br_prev && 176 os_memcmp(hash, l2->last_hash_prev, SHA1_MAC_LEN) == 0) { 177 wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX(prev)", 178 __func__); 179 return; 180 } 181 os_memcpy(l2->last_hash_prev, l2->last_hash, SHA1_MAC_LEN); 182 l2->last_from_br_prev = l2->last_from_br; 183 os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN); 184 } 185 186 l2->last_from_br = 0; 187 #endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */ 188 l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); 189 } 190 191 192 #ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR 193 static void l2_packet_receive_br(int sock, void *eloop_ctx, void *sock_ctx) 194 { 195 struct l2_packet_data *l2 = eloop_ctx; 196 u8 buf[2300]; 197 int res; 198 struct sockaddr_ll ll; 199 socklen_t fromlen; 200 u8 hash[SHA1_MAC_LEN]; 201 const u8 *addr[1]; 202 size_t len[1]; 203 204 l2->num_rx_br++; 205 os_memset(&ll, 0, sizeof(ll)); 206 fromlen = sizeof(ll); 207 res = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *) &ll, 208 &fromlen); 209 if (res < 0) { 210 wpa_printf(MSG_DEBUG, "l2_packet_receive_br - recvfrom: %s", 211 strerror(errno)); 212 return; 213 } 214 215 wpa_printf(MSG_DEBUG, "%s: src=" MACSTR " len=%d", 216 __func__, MAC2STR(ll.sll_addr), (int) res); 217 218 if (os_memcmp(ll.sll_addr, l2->own_addr, ETH_ALEN) == 0) { 219 wpa_printf(MSG_DEBUG, "%s: Drop RX of own frame", __func__); 220 return; 221 } 222 223 addr[0] = buf; 224 len[0] = res; 225 sha1_vector(1, addr, len, hash); 226 if (!l2->last_from_br && 227 os_memcmp(hash, l2->last_hash, SHA1_MAC_LEN) == 0) { 228 wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX", __func__); 229 return; 230 } 231 if (!l2->last_from_br_prev && 232 os_memcmp(hash, l2->last_hash_prev, SHA1_MAC_LEN) == 0) { 233 wpa_printf(MSG_DEBUG, "%s: Drop duplicate RX(prev)", __func__); 234 return; 235 } 236 os_memcpy(l2->last_hash_prev, l2->last_hash, SHA1_MAC_LEN); 237 l2->last_from_br_prev = l2->last_from_br; 238 l2->last_from_br = 1; 239 os_memcpy(l2->last_hash, hash, SHA1_MAC_LEN); 240 l2->rx_callback(l2->rx_callback_ctx, ll.sll_addr, buf, res); 241 } 242 #endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */ 243 244 245 struct l2_packet_data * l2_packet_init( 246 const char *ifname, const u8 *own_addr, unsigned short protocol, 247 void (*rx_callback)(void *ctx, const u8 *src_addr, 248 const u8 *buf, size_t len), 249 void *rx_callback_ctx, int l2_hdr) 250 { 251 struct l2_packet_data *l2; 252 struct ifreq ifr; 253 struct sockaddr_ll ll; 254 255 l2 = os_zalloc(sizeof(struct l2_packet_data)); 256 if (l2 == NULL) 257 return NULL; 258 os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); 259 l2->rx_callback = rx_callback; 260 l2->rx_callback_ctx = rx_callback_ctx; 261 l2->l2_hdr = l2_hdr; 262 #ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR 263 l2->fd_br_rx = -1; 264 #endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */ 265 266 l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, 267 htons(protocol)); 268 if (l2->fd < 0) { 269 wpa_printf(MSG_ERROR, "%s: socket(PF_PACKET): %s", 270 __func__, strerror(errno)); 271 os_free(l2); 272 return NULL; 273 } 274 os_memset(&ifr, 0, sizeof(ifr)); 275 os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); 276 if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) { 277 wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFINDEX]: %s", 278 __func__, strerror(errno)); 279 close(l2->fd); 280 os_free(l2); 281 return NULL; 282 } 283 l2->ifindex = ifr.ifr_ifindex; 284 285 os_memset(&ll, 0, sizeof(ll)); 286 ll.sll_family = PF_PACKET; 287 ll.sll_ifindex = ifr.ifr_ifindex; 288 ll.sll_protocol = htons(protocol); 289 if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) { 290 wpa_printf(MSG_ERROR, "%s: bind[PF_PACKET]: %s", 291 __func__, strerror(errno)); 292 close(l2->fd); 293 os_free(l2); 294 return NULL; 295 } 296 297 if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) < 0) { 298 wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFHWADDR]: %s", 299 __func__, strerror(errno)); 300 close(l2->fd); 301 os_free(l2); 302 return NULL; 303 } 304 os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); 305 306 eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); 307 308 return l2; 309 } 310 311 312 struct l2_packet_data * l2_packet_init_bridge( 313 const char *br_ifname, const char *ifname, const u8 *own_addr, 314 unsigned short protocol, 315 void (*rx_callback)(void *ctx, const u8 *src_addr, 316 const u8 *buf, size_t len), 317 void *rx_callback_ctx, int l2_hdr) 318 { 319 struct l2_packet_data *l2; 320 #ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR 321 struct sock_filter ethertype_sock_filter_insns[] = { 322 /* Load ethertype */ 323 BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 2 * ETH_ALEN), 324 /* Jump over next statement if ethertype does not match */ 325 BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, protocol, 0, 1), 326 /* Ethertype match - return all */ 327 BPF_STMT(BPF_RET | BPF_K, ~0), 328 /* No match - drop */ 329 BPF_STMT(BPF_RET | BPF_K, 0) 330 }; 331 const struct sock_fprog ethertype_sock_filter = { 332 .len = ARRAY_SIZE(ethertype_sock_filter_insns), 333 .filter = ethertype_sock_filter_insns, 334 }; 335 struct sockaddr_ll ll; 336 #endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */ 337 338 l2 = l2_packet_init(br_ifname, own_addr, protocol, rx_callback, 339 rx_callback_ctx, l2_hdr); 340 if (!l2) 341 return NULL; 342 343 #ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR 344 /* 345 * The Linux packet socket behavior has changed over the years and there 346 * is an inconvenient regression in it that breaks RX for a specific 347 * protocol from interfaces in a bridge when that interface is not in 348 * fully operation state (i.e., when in station mode and not completed 349 * authorization). To work around this, register ETH_P_ALL version of 350 * the packet socket bound to the real netdev and use socket filter to 351 * match the ethertype value. This version is less efficient, but 352 * required for functionality with many kernel version. If the main 353 * packet socket is found to be working, this less efficient version 354 * gets closed automatically. 355 */ 356 357 l2->fd_br_rx = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM, 358 htons(ETH_P_ALL)); 359 if (l2->fd_br_rx < 0) { 360 wpa_printf(MSG_DEBUG, "%s: socket(PF_PACKET-fd_br_rx): %s", 361 __func__, strerror(errno)); 362 /* try to continue without the workaround RX socket */ 363 return l2; 364 } 365 366 os_memset(&ll, 0, sizeof(ll)); 367 ll.sll_family = PF_PACKET; 368 ll.sll_ifindex = if_nametoindex(ifname); 369 ll.sll_protocol = htons(ETH_P_ALL); 370 if (bind(l2->fd_br_rx, (struct sockaddr *) &ll, sizeof(ll)) < 0) { 371 wpa_printf(MSG_DEBUG, "%s: bind[PF_PACKET-fd_br_rx]: %s", 372 __func__, strerror(errno)); 373 /* try to continue without the workaround RX socket */ 374 close(l2->fd_br_rx); 375 l2->fd_br_rx = -1; 376 return l2; 377 } 378 379 if (setsockopt(l2->fd_br_rx, SOL_SOCKET, SO_ATTACH_FILTER, 380 ðertype_sock_filter, sizeof(struct sock_fprog))) { 381 wpa_printf(MSG_DEBUG, 382 "l2_packet_linux: setsockopt(SO_ATTACH_FILTER) failed: %s", 383 strerror(errno)); 384 /* try to continue without the workaround RX socket */ 385 close(l2->fd_br_rx); 386 l2->fd_br_rx = -1; 387 return l2; 388 } 389 390 eloop_register_read_sock(l2->fd_br_rx, l2_packet_receive_br, l2, NULL); 391 #endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */ 392 393 return l2; 394 } 395 396 397 void l2_packet_deinit(struct l2_packet_data *l2) 398 { 399 if (l2 == NULL) 400 return; 401 402 if (l2->fd >= 0) { 403 eloop_unregister_read_sock(l2->fd); 404 close(l2->fd); 405 } 406 407 #ifndef CONFIG_NO_LINUX_PACKET_SOCKET_WAR 408 if (l2->fd_br_rx >= 0) { 409 eloop_unregister_read_sock(l2->fd_br_rx); 410 close(l2->fd_br_rx); 411 } 412 #endif /* CONFIG_NO_LINUX_PACKET_SOCKET_WAR */ 413 414 os_free(l2); 415 } 416 417 418 int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) 419 { 420 int s; 421 struct ifreq ifr; 422 struct sockaddr_in *saddr; 423 size_t res; 424 425 s = socket(PF_INET, SOCK_DGRAM, 0); 426 if (s < 0) { 427 wpa_printf(MSG_ERROR, "%s: socket: %s", 428 __func__, strerror(errno)); 429 return -1; 430 } 431 os_memset(&ifr, 0, sizeof(ifr)); 432 os_strlcpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name)); 433 if (ioctl(s, SIOCGIFADDR, &ifr) < 0) { 434 if (errno != EADDRNOTAVAIL) 435 wpa_printf(MSG_ERROR, "%s: ioctl[SIOCGIFADDR]: %s", 436 __func__, strerror(errno)); 437 close(s); 438 return -1; 439 } 440 close(s); 441 saddr = aliasing_hide_typecast(&ifr.ifr_addr, struct sockaddr_in); 442 if (saddr->sin_family != AF_INET) 443 return -1; 444 res = os_strlcpy(buf, inet_ntoa(saddr->sin_addr), len); 445 if (res >= len) 446 return -1; 447 return 0; 448 } 449 450 451 void l2_packet_notify_auth_start(struct l2_packet_data *l2) 452 { 453 } 454 455 456 int l2_packet_set_packet_filter(struct l2_packet_data *l2, 457 enum l2_packet_filter_type type) 458 { 459 const struct sock_fprog *sock_filter; 460 461 switch (type) { 462 case L2_PACKET_FILTER_DHCP: 463 sock_filter = &dhcp_sock_filter; 464 break; 465 case L2_PACKET_FILTER_NDISC: 466 sock_filter = &ndisc_sock_filter; 467 break; 468 default: 469 return -1; 470 } 471 472 if (setsockopt(l2->fd, SOL_SOCKET, SO_ATTACH_FILTER, 473 sock_filter, sizeof(struct sock_fprog))) { 474 wpa_printf(MSG_ERROR, 475 "l2_packet_linux: setsockopt(SO_ATTACH_FILTER) failed: %s", 476 strerror(errno)); 477 return -1; 478 } 479 480 return 0; 481 } 482