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