GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/hostapd/iapp.c Lines: 0 126 0.0 %
Date: 2017-11-07 Branches: 0 66 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: iapp.c,v 1.19 2015/01/16 06:40:17 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/ioctl.h>
20
#include <sys/types.h>
21
#include <sys/socket.h>
22
#include <sys/time.h>
23
#include <sys/uio.h>
24
25
#include <net/if.h>
26
#include <net/if_dl.h>
27
#include <net/if_media.h>
28
#include <net/if_arp.h>
29
#include <net/if_llc.h>
30
#include <net/bpf.h>
31
32
#include <netinet/in.h>
33
#include <netinet/if_ether.h>
34
#include <arpa/inet.h>
35
36
#include <fcntl.h>
37
#include <stdlib.h>
38
#include <string.h>
39
#include <unistd.h>
40
#include <limits.h>
41
42
#include "hostapd.h"
43
#include "iapp.h"
44
45
void
46
hostapd_iapp_init(struct hostapd_config *cfg)
47
{
48
	struct hostapd_apme *apme;
49
	struct hostapd_iapp *iapp = &cfg->c_iapp;
50
51
	if ((cfg->c_flags & HOSTAPD_CFG_F_APME) == 0)
52
		return;
53
54
	TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) {
55
		/* Get Host AP's BSSID */
56
		hostapd_priv_apme_bssid(apme);
57
		hostapd_log(HOSTAPD_LOG,
58
		    "%s/%s: attached Host AP interface with BSSID %s",
59
		    apme->a_iface, iapp->i_iface,
60
		    etheraddr_string(apme->a_bssid));
61
62
		/* Deauthenticate all stations on startup */
63
		(void)hostapd_apme_deauth(apme);
64
	}
65
}
66
67
void
68
hostapd_iapp_term(struct hostapd_config *cfg)
69
{
70
	struct hostapd_apme *apme;
71
	struct hostapd_iapp *iapp = &cfg->c_iapp;
72
73
	if ((cfg->c_flags & HOSTAPD_CFG_F_APME) == 0)
74
		return;
75
76
	TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) {
77
		hostapd_log(HOSTAPD_LOG_VERBOSE,
78
		    "%s/%s: detaching from Host AP",
79
		    apme->a_iface, iapp->i_iface);
80
	}
81
}
82
83
int
84
hostapd_iapp_add_notify(struct hostapd_apme *apme, struct hostapd_node *node)
85
{
86
	struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
87
	struct hostapd_iapp *iapp = &cfg->c_iapp;
88
	struct sockaddr_in *addr;
89
	struct {
90
		struct ieee80211_iapp_frame hdr;
91
		struct ieee80211_iapp_add_notify add;
92
	} __packed frame;
93
94
	if ((iapp->i_flags & HOSTAPD_IAPP_F_ADD_NOTIFY) == 0)
95
		return (0);
96
97
	/*
98
	 * Send an ADD.notify message to other access points to notify
99
	 * about a new association on our Host AP.
100
	 */
101
	bzero(&frame, sizeof(frame));
102
103
	frame.hdr.i_version = IEEE80211_IAPP_VERSION;
104
	frame.hdr.i_command = IEEE80211_IAPP_FRAME_ADD_NOTIFY;
105
	frame.hdr.i_identifier = htons(iapp->i_cnt++);
106
	frame.hdr.i_length = sizeof(struct ieee80211_iapp_add_notify);
107
108
	frame.add.a_length = IEEE80211_ADDR_LEN;
109
	frame.add.a_seqnum = htons(node->ni_rxseq);
110
	bcopy(node->ni_macaddr, frame.add.a_macaddr, IEEE80211_ADDR_LEN);
111
112
	if (cfg->c_flags & HOSTAPD_CFG_F_BRDCAST)
113
		addr = &iapp->i_broadcast;
114
	else
115
		addr = &iapp->i_multicast;
116
117
	if (sendto(iapp->i_udp, &frame, sizeof(frame),
118
	    0, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) == -1) {
119
		hostapd_log(HOSTAPD_LOG,
120
		    "%s: failed to send ADD notification: %s",
121
		    iapp->i_iface, strerror(errno));
122
		return (errno);
123
	}
124
125
	hostapd_log(HOSTAPD_LOG, "%s/%s: sent ADD notification for %s",
126
	    apme->a_iface, iapp->i_iface,
127
	    etheraddr_string(frame.add.a_macaddr));
128
129
	/* Send a LLC XID frame, see llc.c for details */
130
	return (hostapd_priv_llc_xid(cfg, node));
131
}
132
133
int
134
hostapd_iapp_radiotap(struct hostapd_apme *apme, u_int8_t *buf,
135
    const u_int len)
136
{
137
	struct hostapd_config *cfg = (struct hostapd_config *)apme->a_cfg;
138
	struct hostapd_iapp *iapp = &cfg->c_iapp;
139
	struct sockaddr_in *addr;
140
	struct ieee80211_iapp_frame hdr;
141
	struct msghdr msg;
142
	struct iovec iov[2];
143
144
	/*
145
	 * Send an HOSTAPD.pcap/radiotap message to other access points
146
	 * with an appended network dump. This is an hostapd extension to
147
	 * IAPP.
148
	 */
149
	bzero(&hdr, sizeof(hdr));
150
151
	hdr.i_version = IEEE80211_IAPP_VERSION;
152
	if (cfg->c_apme_dlt == DLT_IEEE802_11_RADIO)
153
		hdr.i_command = IEEE80211_IAPP_FRAME_HOSTAPD_RADIOTAP;
154
	else if (cfg->c_apme_dlt == DLT_IEEE802_11)
155
		hdr.i_command = IEEE80211_IAPP_FRAME_HOSTAPD_PCAP;
156
	else
157
		return (EINVAL);
158
	hdr.i_identifier = htons(iapp->i_cnt++);
159
	hdr.i_length = len;
160
161
	if (cfg->c_flags & HOSTAPD_CFG_F_BRDCAST)
162
		addr = &iapp->i_broadcast;
163
	else
164
		addr = &iapp->i_multicast;
165
166
	iov[0].iov_base = &hdr;
167
	iov[0].iov_len = sizeof(hdr);
168
	iov[1].iov_base = buf;
169
	iov[1].iov_len = len;
170
	msg.msg_name = (caddr_t)addr;
171
	msg.msg_namelen = sizeof(struct sockaddr_in);
172
	msg.msg_iov = iov;
173
	msg.msg_iovlen = 2;
174
	msg.msg_control = 0;
175
	msg.msg_controllen = 0;
176
	msg.msg_flags = 0;
177
178
	if (sendmsg(iapp->i_udp, &msg, 0) == -1) {
179
		hostapd_log(HOSTAPD_LOG,
180
		    "%s: failed to send HOSTAPD %s: %s",
181
		    iapp->i_iface, cfg->c_apme_dlt ==
182
		    DLT_IEEE802_11_RADIO ? "radiotap" : "pcap",
183
		    strerror(errno));
184
		return (errno);
185
	}
186
187
	return (0);
188
}
189
190
void
191
hostapd_iapp_input(int fd, short sig, void *arg)
192
{
193
	struct hostapd_config *cfg = (struct hostapd_config *)arg;
194
	struct hostapd_iapp *iapp = &cfg->c_iapp;
195
	struct hostapd_apme *apme;
196
	struct sockaddr_in addr;
197
	socklen_t addr_len;
198
	ssize_t len;
199
	u_int8_t buf[IAPP_MAXSIZE];
200
	struct hostapd_node node;
201
	struct ieee80211_iapp_recv {
202
		struct ieee80211_iapp_frame hdr;
203
		union {
204
			struct ieee80211_iapp_add_notify add;
205
			u_int8_t buf[1];
206
		} u;
207
	} __packed *frame;
208
	u_int dlt;
209
	int ret = 0;
210
211
	/* Ignore invalid signals */
212
	if (sig != EV_READ)
213
		return;
214
215
	/*
216
	 * Listen to possible messages from other IAPP
217
	 */
218
	bzero(buf, sizeof(buf));
219
220
	if ((len = recvfrom(fd, buf, sizeof(buf), 0,
221
	    (struct sockaddr*)&addr, &addr_len)) < 1)
222
		return;
223
224
	if (bcmp(&iapp->i_addr.sin_addr, &addr.sin_addr,
225
	    sizeof(addr.sin_addr)) == 0)
226
		return;
227
228
	frame = (struct ieee80211_iapp_recv*)buf;
229
230
	/* Validate the IAPP version */
231
	if (len < (ssize_t)sizeof(struct ieee80211_iapp_frame) ||
232
	    frame->hdr.i_version != IEEE80211_IAPP_VERSION ||
233
	    addr_len < sizeof(struct sockaddr_in))
234
		return;
235
236
	cfg->c_stats.cn_rx_iapp++;
237
238
	/*
239
	 * Process the IAPP frame
240
	 */
241
	switch (frame->hdr.i_command) {
242
	case IEEE80211_IAPP_FRAME_ADD_NOTIFY:
243
		/* Short frame */
244
		if (len < (ssize_t)(sizeof(struct ieee80211_iapp_frame) +
245
		    sizeof(struct ieee80211_iapp_add_notify)))
246
			return;
247
248
		/* Don't support non-48bit MAC addresses, yet */
249
		if (frame->u.add.a_length != IEEE80211_ADDR_LEN)
250
			return;
251
252
		node.ni_rxseq = frame->u.add.a_seqnum;
253
		bcopy(frame->u.add.a_macaddr, node.ni_macaddr,
254
		    IEEE80211_ADDR_LEN);
255
256
		/*
257
		 * Try to remove a node from our Host AP and to free
258
		 * any allocated resources. Otherwise the received
259
		 * ADD.notify message will be ignored.
260
		 */
261
		if (iapp->i_flags & HOSTAPD_IAPP_F_ADD &&
262
		    cfg->c_flags & HOSTAPD_CFG_F_APME) {
263
			TAILQ_FOREACH(apme, &cfg->c_apmes, a_entries) {
264
				if (iapp->i_flags & HOSTAPD_IAPP_F_ROAMING)
265
					(void)hostapd_roaming_del(apme, &node);
266
				if (iapp->i_flags & HOSTAPD_IAPP_F_ADD_NOTIFY &&
267
				    (ret = hostapd_apme_delnode(apme,
268
				    &node)) == 0)
269
					cfg->c_stats.cn_tx_apme++;
270
			}
271
		} else
272
			ret = 0;
273
274
		hostapd_log(iapp->i_flags & HOSTAPD_IAPP_F_ADD ?
275
		    HOSTAPD_LOG : HOSTAPD_LOG_VERBOSE,
276
		    "%s: %s ADD notification for %s at %s",
277
		    iapp->i_iface, ret == 0 ?
278
		    "received" : "ignored",
279
		    etheraddr_string(node.ni_macaddr),
280
		    inet_ntoa(addr.sin_addr));
281
		break;
282
283
	case IEEE80211_IAPP_FRAME_HOSTAPD_PCAP:
284
	case IEEE80211_IAPP_FRAME_HOSTAPD_RADIOTAP:
285
		if ((iapp->i_flags & HOSTAPD_IAPP_F_RADIOTAP) == 0)
286
			return;
287
288
		/* Short frame */
289
		if (len <= (ssize_t)sizeof(struct ieee80211_iapp_frame) ||
290
		    frame->hdr.i_length < sizeof(struct ieee80211_frame))
291
			return;
292
293
		dlt = frame->hdr.i_command ==
294
		    IEEE80211_IAPP_FRAME_HOSTAPD_PCAP ?
295
		    DLT_IEEE802_11 : DLT_IEEE802_11_RADIO;
296
297
		hostapd_print_ieee80211(dlt, 1, (u_int8_t *)frame->u.buf,
298
		    len - sizeof(struct ieee80211_iapp_frame));
299
		return;
300
301
	case IEEE80211_IAPP_FRAME_MOVE_NOTIFY:
302
	case IEEE80211_IAPP_FRAME_MOVE_RESPONSE:
303
	case IEEE80211_IAPP_FRAME_SEND_SECURITY_BLOCK:
304
	case IEEE80211_IAPP_FRAME_ACK_SECURITY_BLOCK:
305
	case IEEE80211_IAPP_FRAME_CACHE_NOTIFY:
306
	case IEEE80211_IAPP_FRAME_CACHE_RESPONSE:
307
308
		/*
309
		 * XXX TODO
310
		 */
311
312
		hostapd_log(HOSTAPD_LOG_VERBOSE,
313
		    "%s: received unsupported IAPP message %d",
314
		    iapp->i_iface, frame->hdr.i_command);
315
		return;
316
317
	default:
318
		return;
319
	}
320
}