]>
git.ipfire.org Git - thirdparty/hostap.git/blob - src/ap/eth_p_oui.c
2 * hostapd / IEEE 802 OUI Extended EtherType 88-B7
3 * Copyright (c) 2016, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "l2_packet/l2_packet.h"
15 #include "eth_p_oui.h"
18 * See IEEE Std 802-2014, Clause 9.2.4 for the definition of the OUI Extended
19 * EtherType 88-B7. This file implements this with OUI 00:13:74 and
20 * vendor-specific subtype 0x0001.
22 static const u8 global_oui
[] = { 0x00, 0x13, 0x74, 0x00, 0x01 };
24 struct eth_p_oui_iface
{
26 char ifname
[IFNAMSIZ
+ 1];
27 struct l2_packet_data
*l2
;
28 struct dl_list receiver
;
31 struct eth_p_oui_ctx
{
33 struct eth_p_oui_iface
*iface
;
34 /* all data needed to deliver and unregister */
35 u8 oui_suffix
; /* last byte of OUI */
36 void (*rx_callback
)(void *ctx
, const u8
*src_addr
,
37 const u8
*dst_addr
, u8 oui_suffix
,
38 const u8
*buf
, size_t len
);
39 void *rx_callback_ctx
;
43 void eth_p_oui_deliver(struct eth_p_oui_ctx
*ctx
, const u8
*src_addr
,
44 const u8
*dst_addr
, const u8
*buf
, size_t len
)
46 ctx
->rx_callback(ctx
->rx_callback_ctx
, src_addr
, dst_addr
,
47 ctx
->oui_suffix
, buf
, len
);
51 static void eth_p_rx(void *ctx
, const u8
*src_addr
, const u8
*buf
, size_t len
)
53 struct eth_p_oui_iface
*iface
= ctx
;
54 struct eth_p_oui_ctx
*receiver
;
55 const struct l2_ethhdr
*ethhdr
;
57 if (len
< sizeof(*ethhdr
) + sizeof(global_oui
) + 1) {
58 /* too short packet */
62 ethhdr
= (struct l2_ethhdr
*) buf
;
63 /* trim eth_hdr from buf and len */
64 buf
+= sizeof(*ethhdr
);
65 len
-= sizeof(*ethhdr
);
67 /* verify OUI and vendor-specific subtype match */
68 if (os_memcmp(buf
, global_oui
, sizeof(global_oui
)) != 0)
70 buf
+= sizeof(global_oui
);
71 len
-= sizeof(global_oui
);
73 dl_list_for_each(receiver
, &iface
->receiver
,
74 struct eth_p_oui_ctx
, list
) {
75 if (buf
[0] != receiver
->oui_suffix
)
78 eth_p_oui_deliver(receiver
, ethhdr
->h_source
, ethhdr
->h_dest
,
84 struct eth_p_oui_ctx
*
85 eth_p_oui_register(struct hostapd_data
*hapd
, const char *ifname
, u8 oui_suffix
,
86 void (*rx_callback
)(void *ctx
, const u8
*src_addr
,
87 const u8
*dst_addr
, u8 oui_suffix
,
88 const u8
*buf
, size_t len
),
89 void *rx_callback_ctx
)
91 struct eth_p_oui_iface
*iface
;
92 struct eth_p_oui_ctx
*receiver
;
94 struct hapd_interfaces
*interfaces
;
96 receiver
= os_zalloc(sizeof(*receiver
));
100 receiver
->oui_suffix
= oui_suffix
;
101 receiver
->rx_callback
= rx_callback
;
102 receiver
->rx_callback_ctx
= rx_callback_ctx
;
104 interfaces
= hapd
->iface
->interfaces
;
106 dl_list_for_each(iface
, &interfaces
->eth_p_oui
, struct eth_p_oui_iface
,
108 if (os_strcmp(iface
->ifname
, ifname
) != 0)
115 iface
= os_zalloc(sizeof(*iface
));
119 os_strlcpy(iface
->ifname
, ifname
, sizeof(iface
->ifname
));
120 iface
->l2
= l2_packet_init(ifname
, NULL
, ETH_P_OUI
, eth_p_rx
,
126 dl_list_init(&iface
->receiver
);
128 dl_list_add_tail(&interfaces
->eth_p_oui
, &iface
->list
);
131 dl_list_add_tail(&iface
->receiver
, &receiver
->list
);
132 receiver
->iface
= iface
;
141 void eth_p_oui_unregister(struct eth_p_oui_ctx
*ctx
)
143 struct eth_p_oui_iface
*iface
;
150 dl_list_del(&ctx
->list
);
153 if (dl_list_empty(&iface
->receiver
)) {
154 dl_list_del(&iface
->list
);
155 l2_packet_deinit(iface
->l2
);
161 int eth_p_oui_send(struct eth_p_oui_ctx
*ctx
, const u8
*src_addr
,
162 const u8
*dst_addr
, const u8
*buf
, size_t len
)
164 struct eth_p_oui_iface
*iface
= ctx
->iface
;
168 struct l2_ethhdr
*ethhdr
;
170 packet_len
= sizeof(*ethhdr
) + sizeof(global_oui
) + 1 + len
;
171 packet
= os_zalloc(packet_len
);
176 ethhdr
= (struct l2_ethhdr
*) packet
;
177 os_memcpy(ethhdr
->h_source
, src_addr
, ETH_ALEN
);
178 os_memcpy(ethhdr
->h_dest
, dst_addr
, ETH_ALEN
);
179 ethhdr
->h_proto
= host_to_be16(ETH_P_OUI
);
180 p
+= sizeof(*ethhdr
);
182 os_memcpy(p
, global_oui
, sizeof(global_oui
));
183 p
[sizeof(global_oui
)] = ctx
->oui_suffix
;
184 p
+= sizeof(global_oui
) + 1;
186 os_memcpy(p
, buf
, len
);
188 ret
= l2_packet_send(iface
->l2
, NULL
, 0, packet
, packet_len
);