2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Sun elects to license this software under the BSD license.
9 * See README for more details.
12 #pragma ident "%Z%%M% %I% %E% SMI"
19 #include <sys/ethernet.h>
20 #include <netinet/in.h>
24 #include "l2_packet.h"
27 link_init(struct l2_packet_data
*l2
)
30 uint8_t paddr
[DLPI_PHYSADDR_MAX
];
31 size_t paddrlen
= sizeof (paddr
);
33 retval
= dlpi_bind(l2
->dh
, DLPI_ANY_SAP
, NULL
);
34 if (retval
!= DLPI_SUCCESS
) {
35 wpa_printf(MSG_ERROR
, "cannot bind on %s: %s",
36 l2
->ifname
, dlpi_strerror(retval
));
40 retval
= dlpi_promiscon(l2
->dh
, DL_PROMISC_SAP
);
41 if (retval
!= DLPI_SUCCESS
) {
42 wpa_printf(MSG_ERROR
, "cannot enable promiscous"
43 " mode (SAP) on %s: %s",
44 l2
->ifname
, dlpi_strerror(retval
));
48 retval
= dlpi_get_physaddr(l2
->dh
, DL_CURR_PHYS_ADDR
, paddr
, &paddrlen
);
49 if (retval
!= DLPI_SUCCESS
) {
50 wpa_printf(MSG_ERROR
, "cannot get physical address for %s: %s",
51 l2
->ifname
, dlpi_strerror(retval
));
54 if (paddrlen
!= sizeof (l2
->own_addr
)) {
55 wpa_printf(MSG_ERROR
, "physical address for %s is not %d bytes",
56 l2
->ifname
, sizeof (l2
->own_addr
));
59 (void) memcpy(l2
->own_addr
, paddr
, sizeof (l2
->own_addr
));
65 * layer2 packet handling.
68 l2_packet_get_own_addr(struct l2_packet_data
*l2
, uint8_t *addr
)
70 (void) memcpy(addr
, l2
->own_addr
, sizeof (l2
->own_addr
));
75 l2_packet_send(struct l2_packet_data
*l2
, uint8_t *buf
, size_t buflen
)
79 retval
= dlpi_send(l2
->dh
, NULL
, 0, buf
, buflen
, NULL
);
80 if (retval
!= DLPI_SUCCESS
) {
81 wpa_printf(MSG_ERROR
, "l2_packet_send: cannot send "
82 "message on %s: %s", l2
->ifname
, dlpi_strerror(retval
));
90 l2_packet_receive(int fd
, void *eloop_ctx
, void *sock_ctx
)
92 struct l2_packet_data
*l2
= eloop_ctx
;
93 uint64_t buf
[IEEE80211_MTU_MAX
/ sizeof (uint64_t)];
94 size_t buflen
= sizeof (buf
);
95 struct l2_ethhdr
*ethhdr
;
98 retval
= dlpi_recv(l2
->dh
, NULL
, NULL
, buf
, &buflen
, 0, NULL
);
99 if (retval
!= DLPI_SUCCESS
) {
100 wpa_printf(MSG_ERROR
, "l2_packet_receive: cannot receive "
101 "message on %s: %s", l2
->ifname
, dlpi_strerror(retval
));
105 ethhdr
= (struct l2_ethhdr
*)buf
;
106 if (buflen
< sizeof (*ethhdr
) ||
107 (ntohs(ethhdr
->h_proto
) != ETHERTYPE_EAPOL
&&
108 ntohs(ethhdr
->h_proto
) != ETHERTYPE_RSN_PREAUTH
))
111 l2
->rx_callback(l2
->rx_callback_ctx
, ethhdr
->h_source
,
112 (unsigned char *)(ethhdr
+ 1), buflen
- sizeof (*ethhdr
));
116 struct l2_packet_data
*
117 l2_packet_init(const char *ifname
, unsigned short protocol
,
118 void (*rx_callback
)(void *, unsigned char *, unsigned char *, size_t),
119 void *rx_callback_ctx
)
122 struct l2_packet_data
*l2
;
124 l2
= calloc(1, sizeof (struct l2_packet_data
));
128 (void) strlcpy(l2
->ifname
, ifname
, sizeof (l2
->ifname
));
129 l2
->rx_callback
= rx_callback
;
130 l2
->rx_callback_ctx
= rx_callback_ctx
;
132 retval
= dlpi_open(l2
->ifname
, &l2
->dh
, DLPI_RAW
);
133 if (retval
!= DLPI_SUCCESS
) {
134 wpa_printf(MSG_ERROR
, "unable to open DLPI link %s: %s",
135 l2
->ifname
, dlpi_strerror(retval
));
140 /* NOTE: link_init() sets l2->own_addr */
141 if (link_init(l2
) < 0) {
147 (void) eloop_register_read_sock(dlpi_fd(l2
->dh
), l2_packet_receive
, l2
,
154 l2_packet_deinit(struct l2_packet_data
*l2
)
159 eloop_unregister_read_sock(dlpi_fd(l2
->dh
));