1*4126Szf162725 /* 2*4126Szf162725 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3*4126Szf162725 * Use is subject to license terms. 4*4126Szf162725 */ 5*4126Szf162725 6*4126Szf162725 /* 7*4126Szf162725 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> 8*4126Szf162725 * Sun elects to license this software under the BSD license. 9*4126Szf162725 * See README for more details. 10*4126Szf162725 */ 11*4126Szf162725 12*4126Szf162725 #pragma ident "%Z%%M% %I% %E% SMI" 13*4126Szf162725 14*4126Szf162725 #include <stdio.h> 15*4126Szf162725 #include <stdlib.h> 16*4126Szf162725 #include <string.h> 17*4126Szf162725 #include <unistd.h> 18*4126Szf162725 #include <libdlpi.h> 19*4126Szf162725 #include <sys/ethernet.h> 20*4126Szf162725 #include <netinet/in.h> 21*4126Szf162725 22*4126Szf162725 #include "wpa_impl.h" 23*4126Szf162725 #include "eloop.h" 24*4126Szf162725 #include "l2_packet.h" 25*4126Szf162725 26*4126Szf162725 static int 27*4126Szf162725 link_init(struct l2_packet_data *l2) 28*4126Szf162725 { 29*4126Szf162725 int retval; 30*4126Szf162725 uint8_t paddr[DLPI_PHYSADDR_MAX]; 31*4126Szf162725 size_t paddrlen = sizeof (paddr); 32*4126Szf162725 33*4126Szf162725 retval = dlpi_bind(l2->dh, DLPI_ANY_SAP, NULL); 34*4126Szf162725 if (retval != DLPI_SUCCESS) { 35*4126Szf162725 wpa_printf(MSG_ERROR, "cannot bind on %s: %s", 36*4126Szf162725 l2->ifname, dlpi_strerror(retval)); 37*4126Szf162725 return (-1); 38*4126Szf162725 } 39*4126Szf162725 40*4126Szf162725 retval = dlpi_promiscon(l2->dh, DL_PROMISC_SAP); 41*4126Szf162725 if (retval != DLPI_SUCCESS) { 42*4126Szf162725 wpa_printf(MSG_ERROR, "cannot enable promiscous" 43*4126Szf162725 " mode (SAP) on %s: %s", 44*4126Szf162725 l2->ifname, dlpi_strerror(retval)); 45*4126Szf162725 return (-1); 46*4126Szf162725 } 47*4126Szf162725 48*4126Szf162725 retval = dlpi_get_physaddr(l2->dh, DL_CURR_PHYS_ADDR, paddr, &paddrlen); 49*4126Szf162725 if (retval != DLPI_SUCCESS) { 50*4126Szf162725 wpa_printf(MSG_ERROR, "cannot get physical address for %s: %s", 51*4126Szf162725 l2->ifname, dlpi_strerror(retval)); 52*4126Szf162725 return (-1); 53*4126Szf162725 } 54*4126Szf162725 if (paddrlen != sizeof (l2->own_addr)) { 55*4126Szf162725 wpa_printf(MSG_ERROR, "physical address for %s is not %d bytes", 56*4126Szf162725 l2->ifname, sizeof (l2->own_addr)); 57*4126Szf162725 return (-1); 58*4126Szf162725 } 59*4126Szf162725 (void) memcpy(l2->own_addr, paddr, sizeof (l2->own_addr)); 60*4126Szf162725 61*4126Szf162725 return (0); 62*4126Szf162725 } 63*4126Szf162725 64*4126Szf162725 /* 65*4126Szf162725 * layer2 packet handling. 66*4126Szf162725 */ 67*4126Szf162725 int 68*4126Szf162725 l2_packet_get_own_addr(struct l2_packet_data *l2, uint8_t *addr) 69*4126Szf162725 { 70*4126Szf162725 (void) memcpy(addr, l2->own_addr, sizeof (l2->own_addr)); 71*4126Szf162725 return (0); 72*4126Szf162725 } 73*4126Szf162725 74*4126Szf162725 int 75*4126Szf162725 l2_packet_send(struct l2_packet_data *l2, uint8_t *buf, size_t buflen) 76*4126Szf162725 { 77*4126Szf162725 int retval; 78*4126Szf162725 79*4126Szf162725 retval = dlpi_send(l2->dh, NULL, 0, buf, buflen, NULL); 80*4126Szf162725 if (retval != DLPI_SUCCESS) { 81*4126Szf162725 wpa_printf(MSG_ERROR, "l2_packet_send: cannot send " 82*4126Szf162725 "message on %s: %s", l2->ifname, dlpi_strerror(retval)); 83*4126Szf162725 return (-1); 84*4126Szf162725 } 85*4126Szf162725 return (0); 86*4126Szf162725 } 87*4126Szf162725 88*4126Szf162725 /* ARGSUSED */ 89*4126Szf162725 static void 90*4126Szf162725 l2_packet_receive(int fd, void *eloop_ctx, void *sock_ctx) 91*4126Szf162725 { 92*4126Szf162725 struct l2_packet_data *l2 = eloop_ctx; 93*4126Szf162725 uint64_t buf[IEEE80211_MTU_MAX / sizeof (uint64_t)]; 94*4126Szf162725 size_t buflen = sizeof (buf); 95*4126Szf162725 struct l2_ethhdr *ethhdr; 96*4126Szf162725 int retval; 97*4126Szf162725 98*4126Szf162725 retval = dlpi_recv(l2->dh, NULL, NULL, buf, &buflen, 0, NULL); 99*4126Szf162725 if (retval != DLPI_SUCCESS) { 100*4126Szf162725 wpa_printf(MSG_ERROR, "l2_packet_receive: cannot receive " 101*4126Szf162725 "message on %s: %s", l2->ifname, dlpi_strerror(retval)); 102*4126Szf162725 return; 103*4126Szf162725 } 104*4126Szf162725 105*4126Szf162725 ethhdr = (struct l2_ethhdr *)buf; 106*4126Szf162725 if (buflen < sizeof (*ethhdr) || 107*4126Szf162725 (ntohs(ethhdr->h_proto) != ETHERTYPE_EAPOL && 108*4126Szf162725 ntohs(ethhdr->h_proto) != ETHERTYPE_RSN_PREAUTH)) 109*4126Szf162725 return; 110*4126Szf162725 111*4126Szf162725 l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, 112*4126Szf162725 (unsigned char *)(ethhdr + 1), buflen - sizeof (*ethhdr)); 113*4126Szf162725 } 114*4126Szf162725 115*4126Szf162725 /* ARGSUSED */ 116*4126Szf162725 struct l2_packet_data * 117*4126Szf162725 l2_packet_init(const char *ifname, unsigned short protocol, 118*4126Szf162725 void (*rx_callback)(void *, unsigned char *, unsigned char *, size_t), 119*4126Szf162725 void *rx_callback_ctx) 120*4126Szf162725 { 121*4126Szf162725 int retval; 122*4126Szf162725 struct l2_packet_data *l2; 123*4126Szf162725 124*4126Szf162725 l2 = calloc(1, sizeof (struct l2_packet_data)); 125*4126Szf162725 if (l2 == NULL) 126*4126Szf162725 return (NULL); 127*4126Szf162725 128*4126Szf162725 (void) strlcpy(l2->ifname, ifname, sizeof (l2->ifname)); 129*4126Szf162725 l2->rx_callback = rx_callback; 130*4126Szf162725 l2->rx_callback_ctx = rx_callback_ctx; 131*4126Szf162725 132*4126Szf162725 retval = dlpi_open(l2->ifname, &l2->dh, DLPI_RAW); 133*4126Szf162725 if (retval != DLPI_SUCCESS) { 134*4126Szf162725 wpa_printf(MSG_ERROR, "unable to open DLPI link %s: %s", 135*4126Szf162725 l2->ifname, dlpi_strerror(retval)); 136*4126Szf162725 free(l2); 137*4126Szf162725 return (NULL); 138*4126Szf162725 } 139*4126Szf162725 140*4126Szf162725 /* NOTE: link_init() sets l2->own_addr */ 141*4126Szf162725 if (link_init(l2) < 0) { 142*4126Szf162725 dlpi_close(l2->dh); 143*4126Szf162725 free(l2); 144*4126Szf162725 return (NULL); 145*4126Szf162725 } 146*4126Szf162725 147*4126Szf162725 (void) eloop_register_read_sock(dlpi_fd(l2->dh), l2_packet_receive, l2, 148*4126Szf162725 NULL); 149*4126Szf162725 150*4126Szf162725 return (l2); 151*4126Szf162725 } 152*4126Szf162725 153*4126Szf162725 void 154*4126Szf162725 l2_packet_deinit(struct l2_packet_data *l2) 155*4126Szf162725 { 156*4126Szf162725 if (l2 == NULL) 157*4126Szf162725 return; 158*4126Szf162725 159*4126Szf162725 eloop_unregister_read_sock(dlpi_fd(l2->dh)); 160*4126Szf162725 dlpi_close(l2->dh); 161*4126Szf162725 free(l2); 162*4126Szf162725 } 163