• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *	wmediumd, wireless medium simulator for mac80211_hwsim kernel module
3  *	Copyright (c) 2011 cozybit Inc.
4  *	Copyright (C) 2020 Intel Corporation
5  *
6  *	Author:	Javier Lopez	<jlopex@cozybit.com>
7  *		Javier Cardona	<javier@cozybit.com>
8  *
9  *	This program is free software; you can redistribute it and/or
10  *	modify it under the terms of the GNU General Public License
11  *	as published by the Free Software Foundation; either version 2
12  *	of the License, or (at your option) any later version.
13  *
14  *	This program is distributed in the hope that it will be useful,
15  *	but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *	GNU General Public License for more details.
18  *
19  *	You should have received a copy of the GNU General Public License
20  *	along with this program; if not, write to the Free Software
21  *	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  *	02110-1301, USA.
23  */
24 
25 #include <netlink/netlink.h>
26 #include <netlink/genl/genl.h>
27 #include <netlink/genl/ctrl.h>
28 #include <netlink/genl/family.h>
29 #include <assert.h>
30 #include <stdint.h>
31 #include <getopt.h>
32 #include <signal.h>
33 #include <math.h>
34 #include <sys/syslog.h>
35 #include <sys/timerfd.h>
36 #include <errno.h>
37 #include <limits.h>
38 #include <time.h>
39 #include <unistd.h>
40 #include <stdarg.h>
41 #include <endian.h>
42 #include <sys/msg.h>
43 #include <usfstl/loop.h>
44 #include <usfstl/sched.h>
45 #include <usfstl/schedctrl.h>
46 #include <usfstl/vhost.h>
47 #include <usfstl/uds.h>
48 
49 #include "wmediumd.h"
50 #include "ieee80211.h"
51 #include "config.h"
52 #include "api.h"
53 #include "pmsr.h"
54 #include "grpc.h"
55 
56 USFSTL_SCHEDULER(scheduler);
57 
58 static void wmediumd_deliver_frame(struct usfstl_job *job);
59 
60 enum {
61 	HWSIM_VQ_TX,
62 	HWSIM_VQ_RX,
63 	HWSIM_NUM_VQS,
64 };
65 
stpcpy_safe(char * dst,const char * src)66 static char *stpcpy_safe(char *dst, const char *src) {
67 	if (dst == NULL) {
68 		return NULL;
69 	}
70 
71 	if (src == NULL) {
72 		*dst = '\0';
73 		return dst;
74 	}
75 
76 	return stpcpy(dst, src);
77 }
78 
strlen_safe(const char * src)79 static int strlen_safe(const char *src) {
80 	return src == NULL ? 0 : strlen(src);
81 }
82 
div_round(int a,int b)83 static inline int div_round(int a, int b)
84 {
85 	return (a + b - 1) / b;
86 }
87 
sec_to_ns(time_t sec)88 static inline u64 sec_to_ns(time_t sec)
89 {
90 	return sec * 1000 * 1000 * 1000;
91 }
92 
ns_to_us(u64 ns)93 static inline u64 ns_to_us(u64 ns)
94 {
95 	return ns / 1000L;
96 }
97 
ts_to_ns(struct timespec ts)98 static inline u64 ts_to_ns(struct timespec ts)
99 {
100 	return sec_to_ns(ts.tv_sec) + ts.tv_nsec;
101 }
102 
distance_to_rtt(double distance)103 static inline double distance_to_rtt(double distance)
104 {
105 	const long light_speed = 299792458L;
106 	return distance / light_speed;
107 }
108 
sec_to_ps(double sec)109 static inline double sec_to_ps(double sec)
110 {
111 	return sec * 1000 * 1000 * 1000;
112 }
113 
meter_to_mm(double meter)114 static inline double meter_to_mm(double meter)
115 {
116 	return meter * 1000;
117 }
118 
pkt_duration(int len,int rate)119 static inline int pkt_duration(int len, int rate)
120 {
121 	/* preamble + signal + t_sym * n_sym, rate in 100 kbps */
122 	return 16 + 4 + 4 * div_round((16 + 8 * len + 6) * 10, 4 * rate);
123 }
124 
w_logf(struct wmediumd * ctx,u8 level,const char * format,...)125 int w_logf(struct wmediumd *ctx, u8 level, const char *format, ...)
126 {
127 	va_list(args);
128 	va_start(args, format);
129 	if (ctx->log_lvl >= level) {
130 		return vprintf(format, args);
131 	}
132 	return -1;
133 }
134 
w_flogf(struct wmediumd * ctx,u8 level,FILE * stream,const char * format,...)135 int w_flogf(struct wmediumd *ctx, u8 level, FILE *stream, const char *format, ...)
136 {
137 	va_list(args);
138 	va_start(args, format);
139 	if (ctx->log_lvl >= level) {
140 		return vfprintf(stream, format, args);
141 	}
142 	return -1;
143 }
144 
wqueue_init(struct wqueue * wqueue,int cw_min,int cw_max)145 static void wqueue_init(struct wqueue *wqueue, int cw_min, int cw_max)
146 {
147 	INIT_LIST_HEAD(&wqueue->frames);
148 	wqueue->cw_min = cw_min;
149 	wqueue->cw_max = cw_max;
150 }
151 
station_init_queues(struct station * station)152 void station_init_queues(struct station *station)
153 {
154 	wqueue_init(&station->queues[IEEE80211_AC_BK], 15, 1023);
155 	wqueue_init(&station->queues[IEEE80211_AC_BE], 15, 1023);
156 	wqueue_init(&station->queues[IEEE80211_AC_VI], 7, 15);
157 	wqueue_init(&station->queues[IEEE80211_AC_VO], 3, 7);
158 }
159 
frame_has_a4(struct frame * frame)160 static inline bool frame_has_a4(struct frame *frame)
161 {
162 	struct ieee80211_hdr *hdr = (void *)frame->data;
163 
164 	return (hdr->frame_control[1] & (FCTL_TODS | FCTL_FROMDS)) ==
165 		(FCTL_TODS | FCTL_FROMDS);
166 }
167 
frame_is_mgmt(struct frame * frame)168 static inline bool frame_is_mgmt(struct frame *frame)
169 {
170 	struct ieee80211_hdr *hdr = (void *)frame->data;
171 
172 	return (hdr->frame_control[0] & FCTL_FTYPE) == FTYPE_MGMT;
173 }
174 
frame_is_data(struct frame * frame)175 static inline bool frame_is_data(struct frame *frame)
176 {
177 	struct ieee80211_hdr *hdr = (void *)frame->data;
178 
179 	return (hdr->frame_control[0] & FCTL_FTYPE) == FTYPE_DATA;
180 }
181 
frame_is_data_qos(struct frame * frame)182 static inline bool frame_is_data_qos(struct frame *frame)
183 {
184 	struct ieee80211_hdr *hdr = (void *)frame->data;
185 
186 	return (hdr->frame_control[0] & (FCTL_FTYPE | STYPE_QOS_DATA)) ==
187 		(FTYPE_DATA | STYPE_QOS_DATA);
188 }
189 
frame_is_probe_req(struct frame * frame)190 static inline bool frame_is_probe_req(struct frame *frame)
191 {
192 	struct ieee80211_hdr *hdr = (void *)frame->data;
193 
194 	return (hdr->frame_control[0] & (FCTL_FTYPE | STYPE_PROBE_REQ)) ==
195 		(FTYPE_MGMT | STYPE_PROBE_REQ);
196 }
197 
frame_has_zero_rates(const struct frame * frame)198 static inline bool frame_has_zero_rates(const struct frame *frame)
199 {
200 	for (int i = 0; i < frame->tx_rates_count; i++) {
201 		if (frame->tx_rates[i].idx < 0)
202 			break;
203 
204 		if (frame->tx_rates[i].count > 0) {
205 			return false;
206 		}
207 	}
208 
209 	return true;
210 }
211 
fill_tx_rates(struct frame * frame)212 static inline void fill_tx_rates(struct frame *frame)
213 {
214 	if (frame->tx_rates_count <= 0) {
215 		return;
216 	}
217 
218 	int max_index = get_max_index();
219 
220 	/* Starting from OFDM rate (See per.c#rateset) */
221 	const int basic_rate_start = 4; /* 6 mbps */
222 
223 	int i;
224 	int rate_count = min(max_index - basic_rate_start + 1, frame->tx_rates_count);
225 
226 	for (i = 0; i < rate_count; i++) {
227 		frame->tx_rates[i].idx = basic_rate_start + rate_count - i - 1;
228 		frame->tx_rates[i].count = 4;
229 	}
230 
231 	for (; i < frame->tx_rates_count; i++) {
232 		frame->tx_rates[i].idx = -1;
233 		frame->tx_rates[i].count = 0;
234 	}
235 }
236 
frame_get_qos_ctl(struct frame * frame)237 static inline u8 *frame_get_qos_ctl(struct frame *frame)
238 {
239 	struct ieee80211_hdr *hdr = (void *)frame->data;
240 
241 	if (frame_has_a4(frame))
242 		return (u8 *)hdr + 30;
243 	else
244 		return (u8 *)hdr + 24;
245 }
246 
frame_select_queue_80211(struct frame * frame)247 static enum ieee80211_ac_number frame_select_queue_80211(struct frame *frame)
248 {
249 	u8 *p;
250 	int priority;
251 
252 	if (!frame_is_data(frame))
253 		return IEEE80211_AC_VO;
254 
255 	if (!frame_is_data_qos(frame))
256 		return IEEE80211_AC_BE;
257 
258 	p = frame_get_qos_ctl(frame);
259 	priority = *p & QOS_CTL_TAG1D_MASK;
260 
261 	return ieee802_1d_to_ac[priority];
262 }
263 
dBm_to_milliwatt(int decibel_intf)264 static double dBm_to_milliwatt(int decibel_intf)
265 {
266 #define INTF_LIMIT (31)
267 	int intf_diff = NOISE_LEVEL - decibel_intf;
268 
269 	if (intf_diff >= INTF_LIMIT)
270 		return 0.001;
271 
272 	if (intf_diff <= -INTF_LIMIT)
273 		return 1000.0;
274 
275 	return pow(10.0, -intf_diff / 10.0);
276 }
277 
milliwatt_to_dBm(double value)278 static double milliwatt_to_dBm(double value)
279 {
280 	return 10.0 * log10(value);
281 }
282 
set_interference_duration(struct wmediumd * ctx,int src_idx,int duration,int signal)283 static int set_interference_duration(struct wmediumd *ctx, int src_idx,
284 				     int duration, int signal)
285 {
286 	int i;
287 
288 	if (!ctx->intf)
289 		return 0;
290 
291 	if (signal >= CCA_THRESHOLD)
292 		return 0;
293 
294 	for (i = 0; i < ctx->num_stas; i++) {
295 		ctx->intf[ctx->num_stas * src_idx + i].duration += duration;
296 		// use only latest value
297 		ctx->intf[ctx->num_stas * src_idx + i].signal = signal;
298 	}
299 
300 	return 1;
301 }
302 
get_signal_offset_by_interference(struct wmediumd * ctx,int src_idx,int dst_idx)303 static int get_signal_offset_by_interference(struct wmediumd *ctx, int src_idx,
304 					     int dst_idx)
305 {
306 	int i;
307 	double intf_power;
308 
309 	if (!ctx->intf)
310 		return 0;
311 
312 	intf_power = 0.0;
313 	for (i = 0; i < ctx->num_stas; i++) {
314 		if (i == src_idx || i == dst_idx)
315 			continue;
316 		if (drand48() < ctx->intf[i * ctx->num_stas + dst_idx].prob_col)
317 			intf_power += dBm_to_milliwatt(
318 				ctx->intf[i * ctx->num_stas + dst_idx].signal);
319 	}
320 
321 	if (intf_power <= 1.0)
322 		return 0;
323 
324 	return (int)(milliwatt_to_dBm(intf_power) + 0.5);
325 }
326 
is_multicast_ether_addr(const u8 * addr)327 static bool is_multicast_ether_addr(const u8 *addr)
328 {
329 	return 0x01 & addr[0];
330 }
331 
get_station_by_addr(struct wmediumd * ctx,u8 * addr)332 static struct station *get_station_by_addr(struct wmediumd *ctx, u8 *addr)
333 {
334 	struct station *station;
335 
336 	list_for_each_entry(station, &ctx->stations, list) {
337 		if (memcmp(station->addr, addr, ETH_ALEN) == 0)
338 			return station;
339 	}
340 	return NULL;
341 }
342 
station_has_addr(struct station * station,const u8 * addr)343 static bool station_has_addr(struct station *station, const u8 *addr)
344 {
345 	unsigned int i;
346 
347 	if (memcmp(station->addr, addr, ETH_ALEN) == 0)
348 		return true;
349 
350 	for (i = 0; i < station->n_addrs; i++) {
351 		if (memcmp(station->addrs[i].addr, addr, ETH_ALEN) == 0)
352 			return true;
353 	}
354 
355 	return false;
356 }
357 
get_station_by_used_addr(struct wmediumd * ctx,u8 * addr)358 static struct station *get_station_by_used_addr(struct wmediumd *ctx, u8 *addr)
359 {
360 	struct station *station;
361 
362 	list_for_each_entry(station, &ctx->stations, list) {
363 		if (station_has_addr(station, addr))
364 			return station;
365 	}
366 	return NULL;
367 }
368 
wmediumd_wait_for_client_ack(struct wmediumd * ctx,struct client * client)369 static void wmediumd_wait_for_client_ack(struct wmediumd *ctx,
370 					 struct client *client)
371 {
372 	client->wait_for_ack = true;
373 
374 	while (client->wait_for_ack)
375 		usfstl_loop_wait_and_handle();
376 }
377 
378 static void wmediumd_remove_client(struct wmediumd *ctx, struct client *client);
379 
wmediumd_notify_frame_start(struct usfstl_job * job)380 static void wmediumd_notify_frame_start(struct usfstl_job *job)
381 {
382 	struct frame *frame = container_of(job, struct frame, start_job);
383 	struct wmediumd *ctx = job->data;
384 	struct client *client, *tmp;
385 	struct {
386 		struct wmediumd_message_header hdr;
387 		struct wmediumd_tx_start start;
388 	} __attribute__((packed)) msg = {
389 		.hdr.type = WMEDIUMD_MSG_TX_START,
390 		.hdr.data_len = sizeof(msg.start),
391 		.start.freq = frame->freq,
392 	};
393 
394 	if (ctx->ctrl)
395 		usfstl_sched_ctrl_sync_to(ctx->ctrl);
396 
397 	list_for_each_entry_safe(client, tmp, &ctx->clients, list) {
398 		if (!(client->flags & WMEDIUMD_CTL_NOTIFY_TX_START))
399 			continue;
400 
401 		if (client == frame->src)
402 			msg.start.cookie = frame->cookie;
403 		else
404 			msg.start.cookie = 0;
405 
406 		/* must be API socket since flags cannot otherwise be set */
407 		assert(client->type == CLIENT_API_SOCK);
408 
409 		if (write(client->loop.fd, &msg, sizeof(msg)) < sizeof(msg)) {
410 			usfstl_loop_unregister(&client->loop);
411 			wmediumd_remove_client(ctx, client);
412 			continue;
413 		}
414 
415 		wmediumd_wait_for_client_ack(ctx, client);
416 	}
417 }
418 
log2pcap(struct wmediumd * ctx,struct frame * frame,uint64_t ts)419 static void log2pcap(struct wmediumd *ctx, struct frame *frame, uint64_t ts)
420 {
421 	struct {
422 		uint8_t it_version;
423 		uint8_t it_pad;
424 		uint16_t it_len;
425 		uint32_t it_present;
426 		struct {
427 			uint16_t freq, flags;
428 		} channel;
429 		uint8_t signal;
430 	} __attribute__((packed)) radiotap_hdr = {
431 		.it_len = htole16(sizeof(radiotap_hdr)),
432 		.it_present = htole32(1 << 3 /* channel */ |
433 				      1 << 5 /* signal dBm */),
434 		.channel.freq = htole16(frame->freq),
435 		.signal = frame->signal,
436 	};
437 	struct {
438 		uint32_t type, blocklen, ifidx, ts_hi, ts_lo, caplen, pktlen;
439 	} __attribute__((packed)) blockhdr = {
440 		.type = 6,
441 		.ts_hi = ts / (1ULL << 32),
442 		.ts_lo = ts,
443 		.caplen = frame->data_len + sizeof(radiotap_hdr),
444 		.pktlen = frame->data_len + sizeof(radiotap_hdr),
445 	};
446 	static const uint8_t pad[3];
447 	uint32_t sz, align;
448 
449 	sz = blockhdr.caplen + sizeof(blockhdr) + sizeof(uint32_t);
450 	blockhdr.blocklen = (sz + 3) & ~3;
451 	align = blockhdr.blocklen - sz;
452 
453 	fwrite(&blockhdr, sizeof(blockhdr), 1, ctx->pcap_file);
454 	fwrite(&radiotap_hdr, sizeof(radiotap_hdr), 1, ctx->pcap_file);
455 	fwrite(frame->data, frame->data_len, 1, ctx->pcap_file);
456 	fwrite(pad, align, 1, ctx->pcap_file);
457 	fwrite(&blockhdr.blocklen, sizeof(blockhdr.blocklen), 1, ctx->pcap_file);
458 	fflush(ctx->pcap_file);
459 }
460 
queue_frame(struct wmediumd * ctx,struct station * station,struct frame * frame)461 static void queue_frame(struct wmediumd *ctx, struct station *station,
462 			struct frame *frame)
463 {
464 	struct ieee80211_hdr *hdr = (void *)frame->data;
465 	u8 *dest = hdr->addr1;
466 	uint64_t target;
467 	struct wqueue *queue;
468 	struct frame *tail;
469 	struct station *tmpsta, *deststa;
470 	int send_time;
471 	int cw;
472 	double error_prob;
473 	bool is_acked = false;
474 	bool noack = false;
475 	int i, j;
476 	int rate_idx;
477 	int ac;
478 
479 	/* TODO configure phy parameters */
480 	int slot_time = 9;
481 	int sifs = 16;
482 	int difs = 2 * slot_time + sifs;
483 
484 	int retries = 0;
485 
486 	int ack_time_usec = pkt_duration(14, index_to_rate(0, frame->freq)) +
487 	                    sifs;
488 
489 	/*
490 	 * To determine a frame's expiration time, we compute the
491 	 * number of retries we might have to make due to radio conditions
492 	 * or contention, and add backoff time accordingly.  To that, we
493 	 * add the expiration time of the previous frame in the queue.
494 	 */
495 
496 	ac = frame_select_queue_80211(frame);
497 	queue = &station->queues[ac];
498 
499 	/* try to "send" this frame at each of the rates in the rateset */
500 	send_time = 0;
501 	cw = queue->cw_min;
502 
503 	int snr = SNR_DEFAULT;
504 
505 	if (is_multicast_ether_addr(dest)) {
506 		deststa = NULL;
507 	} else {
508 		deststa = get_station_by_used_addr(ctx, dest);
509 		if (deststa) {
510 			snr = ctx->get_link_snr(ctx, station, deststa) -
511 				get_signal_offset_by_interference(ctx,
512 					station->index, deststa->index);
513 			snr += ctx->get_fading_signal(ctx);
514 		}
515 	}
516 	frame->signal = snr + NOISE_LEVEL;
517 
518 	noack = is_multicast_ether_addr(dest);
519 
520 	/*
521 	 * TODO(b/211353765) Remove this when fundamenal solution is applied
522 	 *
523 	 *   Temporary workaround for relaying probe_req frame.
524 	 */
525 	if (frame_is_probe_req(frame) && frame_has_zero_rates(frame)) {
526 		fill_tx_rates(frame);
527 	}
528 
529 	double choice = drand48();
530 
531 	for (i = 0; i < frame->tx_rates_count && !is_acked; i++) {
532 
533 		rate_idx = frame->tx_rates[i].idx;
534 
535 		/* no more rates in MRR */
536 		if (rate_idx < 0)
537 			break;
538 
539 		error_prob = ctx->get_error_prob(ctx, snr, rate_idx,
540 						 frame->freq, frame->data_len,
541 						 station, deststa);
542 		for (j = 0; j < frame->tx_rates[i].count; j++) {
543 			send_time += difs + pkt_duration(frame->data_len,
544 				index_to_rate(rate_idx, frame->freq));
545 
546 			retries++;
547 
548 			/* skip ack/backoff/retries for noack frames */
549 			if (noack) {
550 				is_acked = true;
551 				break;
552 			}
553 
554 			/* TODO TXOPs */
555 
556 			/* backoff */
557 			if (j > 0) {
558 				send_time += (cw * slot_time) / 2;
559 				cw = (cw << 1) + 1;
560 				if (cw > queue->cw_max)
561 					cw = queue->cw_max;
562 			}
563 
564 			send_time += ack_time_usec;
565 
566 			if (choice > error_prob) {
567 				is_acked = true;
568 				break;
569 			}
570 
571 			if (!use_fixed_random_value(ctx))
572 				choice = drand48();
573 		}
574 	}
575 
576 	if (is_acked) {
577 		frame->tx_rates[i-1].count = j + 1;
578 		for (; i < frame->tx_rates_count; i++) {
579 			frame->tx_rates[i].idx = -1;
580 			frame->tx_rates[i].count = -1;
581 		}
582 		frame->flags |= HWSIM_TX_STAT_ACK;
583 	}
584 
585 	/*
586 	 * delivery time starts after any equal or higher prio frame
587 	 * (or now, if none).
588 	 */
589 	target = scheduler.current_time;
590 	for (i = 0; i <= ac; i++) {
591 		list_for_each_entry(tmpsta, &ctx->stations, list) {
592 			tail = list_last_entry_or_null(&tmpsta->queues[i].frames,
593 						       struct frame, list);
594 			if (tail && target < tail->job.start)
595 				target = tail->job.start;
596 		}
597 	}
598 
599 	if (ctx->pcap_file) {
600 		log2pcap(ctx, frame, target);
601 
602 		if (is_acked && !noack) {
603 			struct {
604 				struct frame frame;
605 				uint16_t fc;
606 				uint16_t dur;
607 				uint8_t ra[6];
608 			} __attribute__((packed, aligned(8))) ack = {
609 				.fc = htole16(0xd4),
610 				.dur = htole16(ack_time_usec),
611 			};
612 
613 			memcpy(&ack.frame, frame, sizeof(ack.frame));
614 			ack.frame.data_len = 10;
615 			memcpy(ack.ra, frame->data + 10, 6);
616 
617 			log2pcap(ctx, &ack.frame,
618 				 target + send_time - ack_time_usec);
619 		}
620 	}
621 
622 	target += send_time;
623 
624 	frame->duration = send_time;
625 	frame->src = station->client;
626 
627 	if (ctx->need_start_notify) {
628 		frame->start_job.start = target - send_time;
629 		frame->start_job.callback = wmediumd_notify_frame_start;
630 		frame->start_job.data = ctx;
631 		frame->start_job.name = "frame-start";
632 		usfstl_sched_add_job(&scheduler, &frame->start_job);
633 	}
634 
635 	frame->job.start = target;
636 	frame->job.callback = wmediumd_deliver_frame;
637 	frame->job.data = ctx;
638 	frame->job.name = "frame";
639 	usfstl_sched_add_job(&scheduler, &frame->job);
640 	list_add_tail(&frame->list, &queue->frames);
641 }
642 
wmediumd_send_to_client(struct wmediumd * ctx,struct client * client,struct nl_msg * msg)643 static void wmediumd_send_to_client(struct wmediumd *ctx,
644 				    struct client *client,
645 				    struct nl_msg *msg)
646 {
647 	struct wmediumd_message_header hdr;
648 	size_t len;
649 	int ret;
650 
651 	switch (client->type) {
652 	case CLIENT_NETLINK:
653 		ret = nl_send_auto_complete(ctx->sock, msg);
654 		if (ret < 0)
655 			w_logf(ctx, LOG_ERR, "%s: nl_send_auto failed\n", __func__);
656 		break;
657 	case CLIENT_VHOST_USER:
658 		len = nlmsg_total_size(nlmsg_datalen(nlmsg_hdr(msg)));
659 		usfstl_vhost_user_dev_notify(client->dev, HWSIM_VQ_RX,
660 					     (void *)nlmsg_hdr(msg), len);
661 		break;
662 	case CLIENT_API_SOCK:
663 		len = nlmsg_total_size(nlmsg_datalen(nlmsg_hdr(msg)));
664 		hdr.type = WMEDIUMD_MSG_NETLINK;
665 		hdr.data_len = len;
666 
667 		if (write(client->loop.fd, &hdr, sizeof(hdr)) < sizeof(hdr))
668 			goto disconnect;
669 
670 		if (write(client->loop.fd, (void *)nlmsg_hdr(msg), len) < len)
671 			goto disconnect;
672 
673 		wmediumd_wait_for_client_ack(ctx, client);
674 		break;
675 	}
676 
677 	return;
678 
679 	disconnect:
680 	usfstl_loop_unregister(&client->loop);
681 	wmediumd_remove_client(ctx, client);
682 }
683 
wmediumd_remove_client(struct wmediumd * ctx,struct client * client)684 static void wmediumd_remove_client(struct wmediumd *ctx, struct client *client)
685 {
686 	struct frame *frame, *tmp;
687 	struct wqueue *queue;
688 	struct station *station;
689 	int ac;
690 
691 	list_for_each_entry(station, &ctx->stations, list) {
692 		if (station->client == client)
693 			station->client = NULL;
694 	}
695 
696 	list_for_each_entry(station, &ctx->stations, list) {
697 		for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
698 			queue = &station->queues[ac];
699 			list_for_each_entry_safe(frame, tmp, &queue->frames,
700 						 list) {
701 				if (frame->src == client) {
702 					list_del(&frame->list);
703 					usfstl_sched_del_job(&frame->job);
704 					free(frame);
705 				}
706 			}
707 		}
708 	}
709 
710 	if (!list_empty(&client->list))
711 		list_del(&client->list);
712 	list_add(&client->list, &ctx->clients_to_free);
713 
714 	if (client->flags & WMEDIUMD_CTL_NOTIFY_TX_START)
715 		ctx->need_start_notify--;
716 
717 	client->wait_for_ack = false;
718 }
719 
720 /*
721  * Report transmit status to the kernel.
722  */
send_tx_info_frame_nl(struct wmediumd * ctx,struct frame * frame)723 static void send_tx_info_frame_nl(struct wmediumd *ctx, struct frame *frame)
724 {
725 	struct nl_msg *msg;
726 
727 	msg = nlmsg_alloc();
728 	if (!msg) {
729 		w_logf(ctx, LOG_ERR, "Error allocating new message MSG!\n");
730 		return;
731 	}
732 
733 	if (genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ctx->family_id,
734 			0, NLM_F_REQUEST, HWSIM_CMD_TX_INFO_FRAME,
735 			VERSION_NR) == NULL) {
736 		w_logf(ctx, LOG_ERR, "%s: genlmsg_put failed\n", __func__);
737 		goto out;
738 	}
739 
740 	if (nla_put(msg, HWSIM_ATTR_ADDR_TRANSMITTER, ETH_ALEN,
741 		    frame->sender->hwaddr) ||
742 	    nla_put_u32(msg, HWSIM_ATTR_FLAGS, frame->flags) ||
743 	    nla_put_u32(msg, HWSIM_ATTR_SIGNAL, frame->signal) ||
744 	    nla_put(msg, HWSIM_ATTR_TX_INFO,
745 		    frame->tx_rates_count * sizeof(struct hwsim_tx_rate),
746 		    frame->tx_rates) ||
747 	    nla_put_u64(msg, HWSIM_ATTR_COOKIE, frame->cookie)) {
748 		w_logf(ctx, LOG_ERR, "%s: Failed to fill a payload\n", __func__);
749 		goto out;
750 	}
751 
752 	if (ctx->ctrl)
753 		usfstl_sched_ctrl_sync_to(ctx->ctrl);
754 	wmediumd_send_to_client(ctx, frame->src, msg);
755 
756 out:
757 	nlmsg_free(msg);
758 }
759 
760 /*
761  * Send a data frame to the kernel for reception at a specific radio.
762  */
send_cloned_frame_msg(struct wmediumd * ctx,struct client * src,struct station * dst,u8 * data,int data_len,int rate_idx,int signal,int freq,uint64_t cookie)763 static void send_cloned_frame_msg(struct wmediumd *ctx, struct client *src,
764 				  struct station *dst, u8 *data, int data_len,
765 				  int rate_idx, int signal, int freq,
766 				  uint64_t cookie)
767 {
768 	struct client *client, *tmp;
769 	struct nl_msg *msg, *cmsg = NULL;
770 
771 	msg = nlmsg_alloc();
772 	if (!msg) {
773 		w_logf(ctx, LOG_ERR, "Error allocating new message MSG!\n");
774 		return;
775 	}
776 
777 	if (genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ctx->family_id,
778 			0, NLM_F_REQUEST, HWSIM_CMD_FRAME,
779 			VERSION_NR) == NULL) {
780 		w_logf(ctx, LOG_ERR, "%s: genlmsg_put failed\n", __func__);
781 		goto out;
782 	}
783 
784 	if (nla_put(msg, HWSIM_ATTR_ADDR_RECEIVER, ETH_ALEN,
785 		    dst->hwaddr) ||
786 	    nla_put(msg, HWSIM_ATTR_FRAME, data_len, data) ||
787 	    nla_put_u32(msg, HWSIM_ATTR_RX_RATE, 1) ||
788 	    nla_put_u32(msg, HWSIM_ATTR_FREQ, freq) ||
789 	    nla_put_u32(msg, HWSIM_ATTR_SIGNAL, signal)) {
790 		w_logf(ctx, LOG_ERR, "%s: Failed to fill a payload\n", __func__);
791 		goto out;
792 	}
793 
794 	w_logf(ctx, LOG_DEBUG, "cloned msg dest " MAC_FMT " (radio: " MAC_FMT ") len %d\n",
795 		   MAC_ARGS(dst->addr), MAC_ARGS(dst->hwaddr), data_len);
796 
797 	if (ctx->ctrl)
798 		usfstl_sched_ctrl_sync_to(ctx->ctrl);
799 
800 	list_for_each_entry_safe(client, tmp, &ctx->clients, list) {
801 		if (client->flags & WMEDIUMD_CTL_RX_ALL_FRAMES) {
802 			if (src == client && !cmsg) {
803 				struct nlmsghdr *nlh = nlmsg_hdr(msg);
804 
805 				cmsg = nlmsg_inherit(nlh);
806 				nlmsg_append(cmsg, nlmsg_data(nlh), nlmsg_datalen(nlh), 0);
807 				assert(nla_put_u64(cmsg, HWSIM_ATTR_COOKIE, cookie) == 0);
808 			}
809 			wmediumd_send_to_client(ctx, client,
810 						src == client ? cmsg : msg);
811 		} else if (!dst->client || dst->client == client) {
812 			wmediumd_send_to_client(ctx, client, msg);
813 		}
814 	}
815 
816 out:
817 	nlmsg_free(msg);
818 	if (cmsg)
819 		nlmsg_free(cmsg);
820 }
821 
wmediumd_deliver_frame(struct usfstl_job * job)822 static void wmediumd_deliver_frame(struct usfstl_job *job)
823 {
824 	struct wmediumd *ctx = job->data;
825 	struct frame *frame = container_of(job, struct frame, job);
826 	struct ieee80211_hdr *hdr = (void *) frame->data;
827 	struct station *station;
828 	u8 *dest = hdr->addr1;
829 	u8 *src = frame->sender->addr;
830 
831 	list_del(&frame->list);
832 
833 	if (frame->flags & HWSIM_TX_STAT_ACK) {
834 		/* rx the frame on the dest interface */
835 		list_for_each_entry(station, &ctx->stations, list) {
836 			if (memcmp(src, station->addr, ETH_ALEN) == 0)
837 				continue;
838 
839 			if (is_multicast_ether_addr(dest) && station->client != NULL) {
840 				int snr, rate_idx, signal;
841 				double error_prob;
842 
843 				/*
844 				 * we may or may not receive this based on
845 				 * reverse link from sender -- check for
846 				 * each receiver.
847 				 */
848 				snr = ctx->get_link_snr(ctx, frame->sender,
849 							station);
850 				snr += ctx->get_fading_signal(ctx);
851 				signal = snr + NOISE_LEVEL;
852 				if (signal < CCA_THRESHOLD)
853 					continue;
854 
855 				if (set_interference_duration(ctx,
856 					frame->sender->index, frame->duration,
857 					signal))
858 					continue;
859 
860 				snr -= get_signal_offset_by_interference(ctx,
861 					frame->sender->index, station->index);
862 				rate_idx = frame->tx_rates[0].idx;
863 				error_prob = ctx->get_error_prob(ctx,
864 					(double)snr, rate_idx, frame->freq,
865 					frame->data_len, frame->sender,
866 					station);
867 
868 				if (drand48() <= error_prob) {
869 					w_logf(ctx, LOG_INFO, "Dropped mcast from "
870 						   MAC_FMT " to " MAC_FMT " at receiver\n",
871 						   MAC_ARGS(src), MAC_ARGS(station->addr));
872 					continue;
873 				}
874 
875 				send_cloned_frame_msg(ctx, frame->sender->client,
876 						      station,
877 						      frame->data,
878 						      frame->data_len,
879 						      1, signal,
880 						      frame->freq,
881 						      frame->cookie);
882 
883 			} else if (station_has_addr(station, dest)) {
884 				if (set_interference_duration(ctx,
885 					frame->sender->index, frame->duration,
886 					frame->signal))
887 					continue;
888 
889 				send_cloned_frame_msg(ctx, frame->sender->client,
890 						      station,
891 						      frame->data,
892 						      frame->data_len,
893 						      1, frame->signal,
894 						      frame->freq,
895 						      frame->cookie);
896 			}
897 		}
898 	} else
899 		set_interference_duration(ctx, frame->sender->index,
900 					  frame->duration, frame->signal);
901 
902 	send_tx_info_frame_nl(ctx, frame);
903 
904 	free(frame);
905 }
906 
wmediumd_intf_update(struct usfstl_job * job)907 static void wmediumd_intf_update(struct usfstl_job *job)
908 {
909 	struct wmediumd *ctx = job->data;
910 	int i, j;
911 
912 	for (i = 0; i < ctx->num_stas; i++)
913 		for (j = 0; j < ctx->num_stas; j++) {
914 			if (i == j)
915 				continue;
916 			// probability is used for next calc
917 			ctx->intf[i * ctx->num_stas + j].prob_col =
918 				ctx->intf[i * ctx->num_stas + j].duration /
919 				(double)10000;
920 			ctx->intf[i * ctx->num_stas + j].duration = 0;
921 		}
922 
923 	job->start += 10000;
924 	usfstl_sched_add_job(&scheduler, job);
925 }
926 
927 static
nl_err_cb(struct sockaddr_nl * nla,struct nlmsgerr * nlerr,void * arg)928 int nl_err_cb(struct sockaddr_nl *nla, struct nlmsgerr *nlerr, void *arg)
929 {
930 	struct genlmsghdr *gnlh = nlmsg_data(&nlerr->msg);
931 	struct wmediumd *ctx = arg;
932 
933 	w_flogf(ctx, LOG_ERR, stderr, "nl: cmd %d, seq %d: %s\n", gnlh->cmd,
934 			nlerr->msg.nlmsg_seq, strerror(abs(nlerr->error)));
935 
936 	return NL_SKIP;
937 }
938 
send_pmsr_result_ftm(struct nl_msg * msg,struct pmsr_request_ftm * req,struct wmediumd * ctx,struct station * sender,struct station * receiver)939 static int send_pmsr_result_ftm(struct nl_msg *msg,
940 				struct pmsr_request_ftm *req,
941 				struct wmediumd *ctx,
942 				struct station *sender,
943 				struct station *receiver)
944 {
945 	struct nlattr *ftm;
946 	int err;
947 
948 	ftm = nla_nest_start(msg, NL80211_PMSR_TYPE_FTM);
949 	if (!ftm)
950 		return -ENOMEM;
951 
952 	if (!receiver) {
953 		err = nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON,
954 				  NL80211_PMSR_FTM_FAILURE_NO_RESPONSE);
955 		goto out;
956 	}
957 
958 	double distance =
959 		sqrt(pow(sender->x - receiver->x, 2) + pow(sender->y - receiver->y, 2));
960 	double distance_in_mm = meter_to_mm(distance);
961 	double rtt_in_ps = sec_to_ps(distance_to_rtt(distance));
962 	if (distance_in_mm > UINT64_MAX || rtt_in_ps > UINT64_MAX) {
963 		w_logf(ctx, LOG_WARNING,
964 		       "%s: Devices are too far away", __func__);
965 		return nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON,
966 				   NL80211_PMSR_FTM_FAILURE_NO_RESPONSE);
967 	}
968 
969 	int rssi = receiver->tx_power -
970 		   ctx->calc_path_loss(NULL, sender, receiver);
971 
972 	if (nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_ATTEMPTS,
973 			req->ftmr_retries) ||
974 		nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_NUM_FTMR_SUCCESSES,
975 			req->ftmr_retries) ||
976 		nla_put_u8(msg, NL80211_PMSR_FTM_RESP_ATTR_NUM_BURSTS_EXP,
977 			req->num_bursts_exp) ||
978 		nla_put_u8(msg, NL80211_PMSR_FTM_RESP_ATTR_BURST_DURATION,
979 			 req->burst_duration) ||
980 		nla_put_u8(msg, NL80211_PMSR_FTM_RESP_ATTR_FTMS_PER_BURST,
981 			 req->ftms_per_burst) ||
982 		nla_put_s32(msg, NL80211_PMSR_FTM_RESP_ATTR_RSSI_AVG, rssi) ||
983 		nla_put_s32(msg, NL80211_PMSR_FTM_RESP_ATTR_RSSI_SPREAD, 0) ||
984 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_RTT_AVG,
985 			  (uint64_t)rtt_in_ps) ||
986 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_RTT_VARIANCE, 0) ||
987 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_RTT_SPREAD, 0) ||
988 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_DIST_AVG,
989 			 (uint64_t)distance_in_mm) ||
990 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_DIST_VARIANCE, 0) ||
991 		nla_put_u64(msg, NL80211_PMSR_FTM_RESP_ATTR_DIST_SPREAD, 0)) {
992 		w_logf(ctx, LOG_ERR, "%s: Failed to fill a payload\n", __func__);
993 		return -ENOMEM;
994 	}
995 
996 	if (req->request_lci && receiver->lci) {
997 		nla_put_string(msg, NL80211_PMSR_FTM_RESP_ATTR_LCI,
998 			       receiver->lci);
999 	}
1000 
1001 	if (req->request_civicloc && receiver->civicloc) {
1002 		nla_put_string(msg, NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC,
1003 			       receiver->civicloc);
1004 	}
1005 
1006 out:
1007 	if (ftm)
1008 		nla_nest_end(msg, ftm);
1009 
1010 	return 0;
1011 }
1012 
send_pmsr_result_peer(struct nl_msg * msg,struct pmsr_request_peer * req,struct wmediumd * ctx,struct station * sender)1013 static int send_pmsr_result_peer(struct nl_msg *msg,
1014 				 struct pmsr_request_peer *req,
1015 				 struct wmediumd *ctx,
1016 				 struct station *sender)
1017 {
1018 	struct nlattr *peer, *resp, *data;
1019 	struct station *receiver;
1020 	int status;
1021 	struct timespec ts;
1022 	u64 host_time_ns;
1023 	u64 ap_tsf_us;
1024 	int err;
1025 
1026 	peer = nla_nest_start(msg, 1);
1027 	if (!peer)
1028 		return -ENOMEM;
1029 
1030 	receiver = get_station_by_addr(ctx, req->addr);
1031 	if (receiver)
1032 		status = NL80211_PMSR_STATUS_SUCCESS;
1033 	else {
1034 		w_logf(ctx, LOG_WARNING, "%s: unknown pmsr target " MAC_FMT "\n",
1035 		       __func__, MAC_ARGS(req->addr));
1036 		status = NL80211_PMSR_STATUS_FAILURE;
1037 	}
1038 
1039 	if (clock_gettime(CLOCK_BOOTTIME, &ts)) {
1040 		w_logf(ctx, LOG_ERR, "%s: clock_gettime() failed\n", __func__);
1041 		return -EINVAL;
1042 	}
1043 
1044 	host_time_ns = ts_to_ns(ts);
1045 	ap_tsf_us = ns_to_us(ts_to_ns(ts));
1046 
1047 	err = nla_put(msg, NL80211_PMSR_PEER_ATTR_ADDR, ETH_ALEN, req->addr);
1048 	if (err)
1049 		return err;
1050 
1051 	resp = nla_nest_start(msg, NL80211_PMSR_PEER_ATTR_RESP);
1052 	if (!resp)
1053 		return -ENOMEM;
1054 
1055 	if (nla_put_u32(msg, NL80211_PMSR_RESP_ATTR_STATUS, status) ||
1056 		nla_put_u64(msg, NL80211_PMSR_RESP_ATTR_HOST_TIME, host_time_ns) ||
1057 		nla_put_u64(msg, NL80211_PMSR_RESP_ATTR_AP_TSF, ap_tsf_us) ||
1058 		nla_put_flag(msg, NL80211_PMSR_RESP_ATTR_FINAL)) {
1059 		w_logf(ctx, LOG_ERR, "%s: Failed to fill a payload\n", __func__);
1060 		return -ENOMEM;
1061 	}
1062 
1063 	data = nla_nest_start(msg, NL80211_PMSR_RESP_ATTR_DATA);
1064 	if (!data)
1065 		return -ENOMEM;
1066 
1067 	err = send_pmsr_result_ftm(msg, &req->ftm, ctx, sender, receiver);
1068 
1069 	nla_nest_end(msg, data);
1070 	nla_nest_end(msg, resp);
1071 	nla_nest_end(msg, peer);
1072 
1073 	return err;
1074 }
1075 
send_pmsr_result(struct pmsr_request * request,struct wmediumd * ctx,struct station * sender,struct client * client)1076 static void send_pmsr_result(struct pmsr_request* request, struct wmediumd *ctx,
1077 			     struct station *sender, struct client *client)
1078 {
1079 	struct nl_msg *msg;
1080 	struct nlattr *pmsr, *peers;
1081 	struct pmsr_request_peer *peer;
1082 	int cnt;
1083 	int err;
1084 
1085 	msg = nlmsg_alloc();
1086 	if (!msg) {
1087 		w_logf(ctx, LOG_ERR, "%s: nlmsg_alloc failed\n", __func__);
1088 		return;
1089 	}
1090 
1091 	if (!genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ctx->family_id,
1092 			 0, NLM_F_REQUEST, HWSIM_CMD_REPORT_PMSR, VERSION_NR)) {
1093 		w_logf(ctx, LOG_ERR, "%s: genlmsg_put failed\n", __func__);
1094 		goto out;
1095 	}
1096 
1097 	err = nla_put(msg, HWSIM_ATTR_ADDR_TRANSMITTER,
1098 		      ETH_ALEN, sender->hwaddr);
1099 
1100 	pmsr = nla_nest_start(msg, HWSIM_ATTR_PMSR_RESULT);
1101 	if (!pmsr)
1102 		goto out;
1103 
1104 	peers = nla_nest_start(msg, NL80211_PMSR_ATTR_PEERS);
1105 	if (!peers)
1106 		goto out;
1107 
1108 	list_for_each_entry(peer, &request->peers, list) {
1109 		err = send_pmsr_result_peer(msg, peer, ctx, sender);
1110 		if (err) {
1111 			w_logf(ctx, LOG_ERR,
1112 			       "%s: Failed to send pmsr result from " MAC_FMT \
1113 			       " to " MAC_FMT ". Stopping\n", __func__,
1114 			       MAC_ARGS(sender->addr),
1115 			       MAC_ARGS(peer->addr));
1116 			break;
1117 		}
1118 	}
1119 
1120 	nla_nest_end(msg, peers);
1121 	nla_nest_end(msg, pmsr);
1122 
1123 	wmediumd_send_to_client(ctx, client, msg);
1124 
1125 out:
1126 	nlmsg_free(msg);
1127 }
1128 
process_start_pmsr(struct nlattr * attrs[],struct wmediumd * ctx,struct client * client)1129 static void process_start_pmsr(struct nlattr *attrs[], struct wmediumd *ctx,
1130 			       struct client *client)
1131 {
1132 	u8 *hwaddr;
1133 	struct station *sender;
1134 
1135 	struct pmsr_request request;
1136 	struct pmsr_request_peer *peer, *tmp;
1137 	int err;
1138 
1139 	if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER]) {
1140 		w_logf(ctx, LOG_ERR, "%s: Missing sender information\n",
1141 		       __func__);
1142 	}
1143 
1144 	hwaddr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
1145 	sender = get_station_by_addr(ctx, hwaddr);
1146 	if (!sender) {
1147 		w_logf(ctx, LOG_ERR, "%s: Unknown sender " MAC_FMT "\n",
1148 		       __func__, MAC_ARGS(hwaddr));
1149 		return;
1150 	}
1151 
1152 	err = parse_pmsr_request(attrs[HWSIM_ATTR_PMSR_REQUEST], &request);
1153 	if (err)
1154 		goto out;
1155 
1156 	send_pmsr_result(&request, ctx, sender, client);
1157 
1158 out:
1159 	list_for_each_entry_safe(peer, tmp, &request.peers, list) {
1160 		list_del(&peer->list);
1161 		free(peer);
1162 	}
1163 }
1164 
1165 /*
1166  * Handle events from the kernel.  Process CMD_FRAME events and queue them
1167  * for later delivery with the scheduler.
1168  */
_process_messages(struct nl_msg * msg,struct wmediumd * ctx,struct client * client)1169 static void _process_messages(struct nl_msg *msg,
1170 			      struct wmediumd *ctx,
1171 			      struct client *client)
1172 {
1173 	struct nlattr *attrs[HWSIM_ATTR_MAX+1];
1174 	/* netlink header */
1175 	struct nlmsghdr *nlh = nlmsg_hdr(msg);
1176 	/* generic netlink header*/
1177 	struct genlmsghdr *gnlh = nlmsg_data(nlh);
1178 
1179 	struct station *sender;
1180 	struct frame *frame;
1181 	struct ieee80211_hdr *hdr;
1182 	u8 *src, *hwaddr, *addr;
1183 	void *new_addrs;
1184 	unsigned int i;
1185 
1186 	genlmsg_parse(nlh, 0, attrs, HWSIM_ATTR_MAX, NULL);
1187 
1188 	switch (gnlh->cmd) {
1189 	case HWSIM_CMD_FRAME:
1190 		if (attrs[HWSIM_ATTR_ADDR_TRANSMITTER]) {
1191 			hwaddr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
1192 
1193 			unsigned int data_len =
1194 				nla_len(attrs[HWSIM_ATTR_FRAME]);
1195 			char *data = (char *)nla_data(attrs[HWSIM_ATTR_FRAME]);
1196 			unsigned int flags =
1197 				nla_get_u32(attrs[HWSIM_ATTR_FLAGS]);
1198 			unsigned int tx_rates_len =
1199 				nla_len(attrs[HWSIM_ATTR_TX_INFO]);
1200 			struct hwsim_tx_rate *tx_rates =
1201 				(struct hwsim_tx_rate *)
1202 				nla_data(attrs[HWSIM_ATTR_TX_INFO]);
1203 			u64 cookie = nla_get_u64(attrs[HWSIM_ATTR_COOKIE]);
1204 			u32 freq;
1205 
1206 			freq = attrs[HWSIM_ATTR_FREQ] ?
1207 				nla_get_u32(attrs[HWSIM_ATTR_FREQ]) : 2412;
1208 
1209 			hdr = (struct ieee80211_hdr *)data;
1210 			src = hdr->addr2;
1211 
1212 			if (data_len < 6 + 6 + 4)
1213 				return;
1214 
1215 			sender = get_station_by_addr(ctx, hwaddr);
1216 			if (!sender) {
1217 				sender = get_station_by_used_addr(ctx, src);
1218 				if (!sender) {
1219 					w_flogf(ctx, LOG_ERR, stderr,
1220 						"Unable to find sender station by src=" MAC_FMT " nor hwaddr=" MAC_FMT "\n",
1221 						MAC_ARGS(src), MAC_ARGS(hwaddr));
1222 					return;
1223 				}
1224 				memcpy(sender->hwaddr, hwaddr, ETH_ALEN);
1225 			}
1226 
1227 			if (!sender->client)
1228 				sender->client = client;
1229 
1230 			frame = calloc(1, sizeof(*frame) + data_len);
1231 			if (!frame)
1232 				return;
1233 
1234 			memcpy(frame->data, data, data_len);
1235 			frame->data_len = data_len;
1236 			frame->flags = flags;
1237 			frame->cookie = cookie;
1238 			frame->freq = freq;
1239 			frame->sender = sender;
1240 			frame->tx_rates_count =
1241 				tx_rates_len / sizeof(struct hwsim_tx_rate);
1242 			memcpy(frame->tx_rates, tx_rates,
1243 			       min(tx_rates_len, sizeof(frame->tx_rates)));
1244 			queue_frame(ctx, sender, frame);
1245 		}
1246 		break;
1247 	case HWSIM_CMD_ADD_MAC_ADDR:
1248 		if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
1249 		    !attrs[HWSIM_ATTR_ADDR_RECEIVER])
1250 			break;
1251 		hwaddr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
1252 		addr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_RECEIVER]);
1253 		sender = get_station_by_addr(ctx, hwaddr);
1254 		if (!sender)
1255 			break;
1256 		for (i = 0; i < sender->n_addrs; i++) {
1257 			if (memcmp(sender->addrs[i].addr, addr, ETH_ALEN) == 0) {
1258 				sender->addrs[i].count += 1;
1259 				return;
1260 			}
1261 		}
1262 		new_addrs = realloc(sender->addrs, sizeof(struct addr) * (sender->n_addrs + 1));
1263 		if (!new_addrs)
1264 			break;
1265 		sender->addrs = new_addrs;
1266 		sender->addrs[sender->n_addrs].count = 1;
1267 		memcpy(sender->addrs[sender->n_addrs].addr, addr, ETH_ALEN);
1268 		sender->n_addrs += 1;
1269 		break;
1270 	case HWSIM_CMD_DEL_MAC_ADDR:
1271 		if (!attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
1272 		    !attrs[HWSIM_ATTR_ADDR_RECEIVER])
1273 			break;
1274 		hwaddr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_TRANSMITTER]);
1275 		addr = (u8 *)nla_data(attrs[HWSIM_ATTR_ADDR_RECEIVER]);
1276 		sender = get_station_by_addr(ctx, hwaddr);
1277 		if (!sender)
1278 			break;
1279 		for (i = 0; i < sender->n_addrs; i++) {
1280 			if (memcmp(sender->addrs[i].addr, addr, ETH_ALEN))
1281 				continue;
1282 			sender->addrs[i].count -= 1;
1283 			if (sender->addrs[i].count <= 0) {
1284 				sender->n_addrs -= 1;
1285 				memmove(&sender->addrs[i],
1286 					&sender->addrs[sender->n_addrs],
1287 					sizeof(struct addr));
1288 			}
1289 			break;
1290 		}
1291 		break;
1292 	case HWSIM_CMD_START_PMSR:
1293 		process_start_pmsr(attrs, ctx, client);
1294 		break;
1295 
1296 	case HWSIM_CMD_ABORT_PMSR:
1297 		// Do nothing. Too late to abort any PMSR.
1298 		break;
1299 	}
1300 }
1301 
process_messages_cb(struct nl_msg * msg,void * arg)1302 static int process_messages_cb(struct nl_msg *msg, void *arg)
1303 {
1304 	struct wmediumd *ctx = arg;
1305 
1306 	_process_messages(msg, ctx, &ctx->nl_client);
1307 	return 0;
1308 }
1309 
wmediumd_vu_connected(struct usfstl_vhost_user_dev * dev)1310 static void wmediumd_vu_connected(struct usfstl_vhost_user_dev *dev)
1311 {
1312 	struct wmediumd *ctx = dev->server->data;
1313 	struct client *client;
1314 
1315 	client = calloc(1, sizeof(*client));
1316 	dev->data = client;
1317 	client->type = CLIENT_VHOST_USER;
1318 	client->dev = dev;
1319 	list_add(&client->list, &ctx->clients);
1320 }
1321 
wmediumd_vu_handle(struct usfstl_vhost_user_dev * dev,struct usfstl_vhost_user_buf * buf,unsigned int vring)1322 static void wmediumd_vu_handle(struct usfstl_vhost_user_dev *dev,
1323 			       struct usfstl_vhost_user_buf *buf,
1324 			       unsigned int vring)
1325 {
1326 	struct nl_msg *nlmsg;
1327 	char data[4096];
1328 	size_t len;
1329 
1330 	len = iov_read(data, sizeof(data), buf->out_sg, buf->n_out_sg);
1331 
1332 	if (!nlmsg_ok((const struct nlmsghdr *)data, len))
1333 		return;
1334 	nlmsg = nlmsg_convert((struct nlmsghdr *)data);
1335 	if (!nlmsg)
1336 		return;
1337 
1338 	_process_messages(nlmsg, dev->server->data, dev->data);
1339 
1340 	nlmsg_free(nlmsg);
1341 }
1342 
wmediumd_vu_disconnected(struct usfstl_vhost_user_dev * dev)1343 static void wmediumd_vu_disconnected(struct usfstl_vhost_user_dev *dev)
1344 {
1345 	struct client *client = dev->data;
1346 
1347 	dev->data = NULL;
1348 	wmediumd_remove_client(dev->server->data, client);
1349 }
1350 
process_set_snr_message(struct wmediumd * ctx,struct wmediumd_set_snr * set_snr)1351 static int process_set_snr_message(struct wmediumd *ctx, struct wmediumd_set_snr *set_snr) {
1352 	struct station *node1 = get_station_by_addr(ctx, set_snr->node1_mac);
1353 	struct station *node2 = get_station_by_addr(ctx, set_snr->node2_mac);
1354 
1355 	if (node1 == NULL || node2 == NULL) {
1356 		return -1;
1357 	}
1358 
1359 	ctx->snr_matrix[ctx->num_stas * node2->index + node1->index] = set_snr->snr;
1360 	ctx->snr_matrix[ctx->num_stas * node1->index + node2->index] = set_snr->snr;
1361 
1362 	return 0;
1363 }
1364 
process_reload_config_message(struct wmediumd * ctx,struct wmediumd_reload_config * reload_config)1365 static int process_reload_config_message(struct wmediumd *ctx,
1366 					 struct wmediumd_reload_config *reload_config) {
1367 	char *config_path;
1368 	int result = 0;
1369 
1370 	config_path = reload_config->config_path;
1371 
1372 	if (validate_config(config_path)) {
1373 		clear_config(ctx);
1374 		load_config(ctx, config_path, NULL);
1375 	} else {
1376 		result = -1;
1377 	}
1378 
1379 	return result;
1380 }
1381 
process_reload_current_config_message(struct wmediumd * ctx)1382 static int process_reload_current_config_message(struct wmediumd *ctx) {
1383 	char *config_path;
1384 	int result = 0;
1385 
1386 	config_path = strdup(ctx->config_path);
1387 
1388 	if (validate_config(config_path)) {
1389 		clear_config(ctx);
1390 		load_config(ctx, config_path, NULL);
1391 	} else {
1392 		result = -1;
1393 	}
1394 
1395 	free(config_path);
1396 
1397 	return result;
1398 }
1399 
process_get_stations_message(struct wmediumd * ctx,ssize_t * response_len,unsigned char ** response_data)1400 static int process_get_stations_message(struct wmediumd *ctx, ssize_t *response_len, unsigned char **response_data) {
1401 	struct station *station;
1402 	int station_count = 0;
1403 	int extra_data_len = 0;
1404 
1405 	// *reponse_data contains struct wmediumd_station_infos
1406 	// and then lci and civiclocs for each station follows afterwards.
1407 	list_for_each_entry(station, &ctx->stations, list) {
1408 		if (station->client != NULL) {
1409 			++station_count;
1410 			extra_data_len += strlen_safe(station->lci) + 1;
1411 			extra_data_len += strlen_safe(station->civicloc) + 1;
1412 		}
1413 	}
1414 
1415 	int station_len = sizeof(uint32_t) + sizeof(struct wmediumd_station_info) * station_count;
1416 	*response_len = station_len + extra_data_len;
1417 	*response_data = malloc(*response_len);
1418 
1419 	if (*response_data == NULL) {
1420 		w_logf(ctx, LOG_ERR, "%s: failed allocate response data\n", __func__);
1421 		return -1;
1422 	}
1423 
1424 	struct wmediumd_station_infos *station_infos = (struct wmediumd_station_infos *)*response_data;
1425 	station_infos->count = station_count;
1426 	int station_index = 0;
1427 	// Pointer to the memory after structs wmediumd_station_infos
1428 	// to write lci and civicloc for each station.
1429 	char *extra_data_cursor = (char *)&(station_infos->stations[station_count]);
1430 
1431 	list_for_each_entry(station, &ctx->stations, list) {
1432 		if (station->client != NULL) {
1433 			struct wmediumd_station_info *station_info = &station_infos->stations[station_index];
1434 			memcpy(station_info->addr, station->addr, ETH_ALEN);
1435 			memcpy(station_info->hwaddr, station->hwaddr, ETH_ALEN);
1436 
1437 			station_info->x = station->x;
1438 			station_info->y = station->y;
1439 			station_info->lci_offset = extra_data_cursor - (char *)station_info;
1440 			extra_data_cursor = stpcpy_safe(extra_data_cursor, station->lci) + 1;
1441 			station_info->civicloc_offset = extra_data_cursor - (char *)station_info;
1442 			extra_data_cursor = stpcpy_safe(extra_data_cursor, station->civicloc) + 1;
1443 			station_info->tx_power = station->tx_power;
1444 			station_index++;
1445 		}
1446 	}
1447 
1448 	return 0;
1449 }
1450 
process_set_position_message(struct wmediumd * ctx,struct wmediumd_set_position * set_position)1451 static int process_set_position_message(struct wmediumd *ctx, struct wmediumd_set_position *set_position) {
1452 	struct station *node = get_station_by_addr(ctx, set_position->mac);
1453 
1454 	if (node == NULL) {
1455 		return -1;
1456 	}
1457 
1458 	node->x = set_position->x;
1459 	node->y = set_position->y;
1460 
1461 	calc_path_loss(ctx);
1462 
1463 	return 0;
1464 }
1465 
process_set_lci_message(struct wmediumd * ctx,struct wmediumd_set_lci * set_lci,size_t data_len)1466 static int process_set_lci_message(struct wmediumd *ctx, struct wmediumd_set_lci *set_lci, size_t data_len) {
1467 	struct station *node = get_station_by_addr(ctx, set_lci->mac);
1468 
1469 	if (node == NULL) {
1470 		return -1;
1471 	}
1472 	int expected_len = data_len - offsetof(struct wmediumd_set_lci, lci) - 1;
1473 	if (set_lci->lci[expected_len] != '\0') {
1474 		return -1;
1475 	}
1476 
1477 	if (node->lci) {
1478 		free(node->lci);
1479 	}
1480 	node->lci = strdup(set_lci->lci);
1481 
1482 	return node->lci != NULL;
1483 }
1484 
process_set_civicloc_message(struct wmediumd * ctx,struct wmediumd_set_civicloc * set_civicloc,size_t data_len)1485 static int process_set_civicloc_message(struct wmediumd *ctx, struct wmediumd_set_civicloc *set_civicloc, size_t data_len) {
1486 	struct station *node = get_station_by_addr(ctx, set_civicloc->mac);
1487 
1488 	if (node == NULL) {
1489 		return -1;
1490 	}
1491 	int expected_len = data_len - offsetof(struct wmediumd_set_civicloc, civicloc) - 1;
1492 	if (set_civicloc->civicloc[expected_len] != '\0') {
1493 		return -1;
1494 	}
1495 
1496 	if (node->civicloc) {
1497 		free(node->civicloc);
1498 	}
1499 	node->civicloc = strdup(set_civicloc->civicloc);
1500 
1501 	return node->civicloc != NULL;
1502 }
1503 
1504 static const struct usfstl_vhost_user_ops wmediumd_vu_ops = {
1505 	.connected = wmediumd_vu_connected,
1506 	.handle = wmediumd_vu_handle,
1507 	.disconnected = wmediumd_vu_disconnected,
1508 };
1509 
close_pcapng(struct wmediumd * ctx)1510 static void close_pcapng(struct wmediumd *ctx) {
1511 	if (ctx->pcap_file == NULL) {
1512 		return;
1513 	}
1514 
1515 	fflush(ctx->pcap_file);
1516 	fclose(ctx->pcap_file);
1517 
1518 	ctx->pcap_file = NULL;
1519 }
1520 
1521 static void init_pcapng(struct wmediumd *ctx, const char *filename);
1522 
wmediumd_grpc_service_handler(struct usfstl_loop_entry * entry)1523 static void wmediumd_grpc_service_handler(struct usfstl_loop_entry *entry) {
1524 	struct wmediumd *ctx = entry->data;
1525 
1526 	// Receive request type from WmediumdService
1527 	uint64_t request_type;
1528 	read(entry->fd, &request_type, sizeof(uint64_t));
1529 
1530 	struct wmediumd_grpc_message request_body;
1531 	uint64_t response_type;
1532 
1533 	// Receive request body from WmediumdService and do the task.
1534 	// TODO(273384914): Support more request types.
1535 	switch (request_type) {
1536 	case REQUEST_SET_POSITION:
1537 		if (msgrcv(ctx->msq_id, &request_body, sizeof(struct wmediumd_set_position), GRPC_REQUEST, 0) != sizeof(struct wmediumd_set_position)) {
1538 			w_logf(ctx, LOG_ERR, "%s: failed to get set_position request body\n", __func__);
1539 		}
1540 
1541 		if (process_set_position_message(ctx, (struct wmediumd_set_position *)(request_body.data)) < 0) {
1542 			w_logf(ctx, LOG_ERR, "%s: failed to execute set_position\n", __func__);
1543 			response_type = RESPONSE_INVALID;
1544 		}
1545 		response_type = RESPONSE_ACK;
1546 		break;
1547 	default:
1548 		w_logf(ctx, LOG_ERR, "%s: unknown request type\n", __func__);
1549 		response_type = RESPONSE_INVALID;
1550 		break;
1551 	}
1552 
1553 	// TODO(273384914): Send response with response_type
1554 	return;
1555 }
1556 
1557 // TODO(273384914): Deprecate messages used in wmediumd_control after
1558 // implementing in wmediumd_grpc_service_handler to be used in the command
1559 // 'cvd env'.
wmediumd_api_handler(struct usfstl_loop_entry * entry)1560 static void wmediumd_api_handler(struct usfstl_loop_entry *entry)
1561 {
1562 	struct client *client = container_of(entry, struct client, loop);
1563 	struct wmediumd *ctx = entry->data;
1564 	struct wmediumd_message_header hdr;
1565 	enum wmediumd_message response = WMEDIUMD_MSG_ACK;
1566 	struct wmediumd_message_control control = {};
1567 	struct nl_msg *nlmsg;
1568 	unsigned char *data;
1569 	ssize_t response_len = 0;
1570 	unsigned char *response_data = NULL;
1571 	ssize_t len;
1572 
1573 	len = read(entry->fd, &hdr, sizeof(hdr));
1574 	if (len != sizeof(hdr)) {
1575 		if (len > 0) {
1576 			// Skipping log if the fd is closed.
1577 			w_logf(ctx, LOG_ERR, "%s: failed to read header\n", __func__);
1578 		}
1579 		goto disconnect;
1580 	}
1581 
1582 	/* safety valve */
1583 	if (hdr.data_len > 1024 * 1024) {
1584 		w_logf(ctx, LOG_ERR, "%s: too large data\n", __func__);
1585 		goto disconnect;
1586 	}
1587 
1588 	data = malloc(hdr.data_len);
1589 	if (!data) {
1590 		w_logf(ctx, LOG_ERR, "%s: failed to malloc\n", __func__);
1591 		goto disconnect;
1592 	}
1593 
1594 	len = read(entry->fd, data, hdr.data_len);
1595 	if (len != hdr.data_len) {
1596 		w_logf(ctx, LOG_ERR, "%s: failed to read data\n", __func__);
1597 		goto disconnect;
1598 	}
1599 
1600 	switch (hdr.type) {
1601 	case WMEDIUMD_MSG_REGISTER:
1602 		if (!list_empty(&client->list)) {
1603 			response = WMEDIUMD_MSG_INVALID;
1604 			break;
1605 		}
1606 		list_add(&client->list, &ctx->clients);
1607 		break;
1608 	case WMEDIUMD_MSG_UNREGISTER:
1609 		if (list_empty(&client->list)) {
1610 			response = WMEDIUMD_MSG_INVALID;
1611 			break;
1612 		}
1613 		list_del_init(&client->list);
1614 		break;
1615 	case WMEDIUMD_MSG_NETLINK:
1616 		if (ctx->ctrl)
1617 			usfstl_sched_ctrl_sync_from(ctx->ctrl);
1618 
1619 		if (!nlmsg_ok((const struct nlmsghdr *)data, len)) {
1620 			response = WMEDIUMD_MSG_INVALID;
1621 			break;
1622 		}
1623 
1624 		nlmsg = nlmsg_convert((struct nlmsghdr *)data);
1625 		if (!nlmsg)
1626 			break;
1627 
1628 		_process_messages(nlmsg, ctx, client);
1629 
1630 		nlmsg_free(nlmsg);
1631 		break;
1632 	case WMEDIUMD_MSG_SET_CONTROL:
1633 		/* copy what we get and understand, leave the rest zeroed */
1634 		memcpy(&control, data,
1635 		       min(sizeof(control), hdr.data_len));
1636 
1637 		if (client->flags & WMEDIUMD_CTL_NOTIFY_TX_START)
1638 			ctx->need_start_notify--;
1639 		if (control.flags & WMEDIUMD_CTL_NOTIFY_TX_START)
1640 			ctx->need_start_notify++;
1641 
1642 		client->flags = control.flags;
1643 		break;
1644 	case WMEDIUMD_MSG_GET_STATIONS:
1645 		if (process_get_stations_message(ctx, &response_len, &response_data) < 0) {
1646 			response = WMEDIUMD_MSG_INVALID;
1647 		}
1648 		response = WMEDIUMD_MSG_STATIONS_LIST;
1649 		break;
1650 	case WMEDIUMD_MSG_SET_SNR:
1651 		if (process_set_snr_message(ctx, (struct wmediumd_set_snr *)data) < 0) {
1652 			response = WMEDIUMD_MSG_INVALID;
1653 		}
1654 		break;
1655 	case WMEDIUMD_MSG_RELOAD_CONFIG:
1656 		if (process_reload_config_message(ctx,
1657 				(struct wmediumd_reload_config *)data) < 0) {
1658 			response = WMEDIUMD_MSG_INVALID;
1659 		}
1660 		break;
1661 	case WMEDIUMD_MSG_RELOAD_CURRENT_CONFIG:
1662 		if (process_reload_current_config_message(ctx) < 0) {
1663 			response = WMEDIUMD_MSG_INVALID;
1664 		}
1665 		break;
1666 	case WMEDIUMD_MSG_START_PCAP:
1667 		init_pcapng(ctx, ((struct wmediumd_start_pcap *)data)->pcap_path);
1668 		break;
1669 	case WMEDIUMD_MSG_STOP_PCAP:
1670 		close_pcapng(ctx);
1671 		break;
1672 	case WMEDIUMD_MSG_SET_POSITION:
1673 		if (process_set_position_message(ctx, (struct wmediumd_set_position *)data) < 0) {
1674 			response = WMEDIUMD_MSG_INVALID;
1675 		}
1676 		break;
1677 	case WMEDIUMD_MSG_SET_LCI:
1678 		if (process_set_lci_message(ctx,
1679 				(struct wmediumd_set_lci *)data,
1680 				hdr.data_len) < 0) {
1681 			response = WMEDIUMD_MSG_INVALID;
1682 		}
1683 		break;
1684 	case WMEDIUMD_MSG_SET_CIVICLOC:
1685 		if (process_set_civicloc_message(ctx,
1686 				(struct wmediumd_set_civicloc *)data,
1687 				hdr.data_len) < 0) {
1688 			response = WMEDIUMD_MSG_INVALID;
1689 		}
1690 		break;
1691 	case WMEDIUMD_MSG_ACK:
1692 		assert(client->wait_for_ack == true);
1693 		assert(hdr.data_len == 0);
1694 		client->wait_for_ack = false;
1695 		/* don't send a response to a response, of course */
1696 		return;
1697 	default:
1698 		w_logf(ctx, LOG_ERR, "%s: unknown message\n", __func__);
1699 		response = WMEDIUMD_MSG_INVALID;
1700 		break;
1701 	}
1702 
1703 	/* return a response */
1704 	hdr.type = response;
1705 	hdr.data_len = response_len;
1706 	len = write(entry->fd, &hdr, sizeof(hdr));
1707 	if (len != sizeof(hdr)) {
1708 		w_logf(ctx, LOG_ERR, "%s: failed to write response header\n", __func__);
1709 		goto disconnect;
1710 	}
1711 
1712 	if (response_data != NULL) {
1713 		if (response_len != 0) {
1714 			len = write(entry->fd, response_data, response_len);
1715 
1716 			if (len != response_len) {
1717 				free(response_data);
1718 				w_logf(ctx, LOG_ERR, "%s: failed to write response data\n", __func__);
1719 				goto disconnect;
1720 			}
1721 		}
1722 
1723 		free(response_data);
1724 		response_data = NULL;
1725 	}
1726 
1727 	return;
1728 disconnect:
1729 	usfstl_loop_unregister(&client->loop);
1730 	wmediumd_remove_client(ctx, client);
1731 }
1732 
wmediumd_api_connected(int fd,void * data)1733 static void wmediumd_api_connected(int fd, void *data)
1734 {
1735 	struct wmediumd *ctx = data;
1736 	struct client *client;
1737 
1738 	client = calloc(1, sizeof(*client));
1739 	client->type = CLIENT_API_SOCK;
1740 	client->loop.fd = fd;
1741 	client->loop.data = ctx;
1742 	client->loop.handler = wmediumd_api_handler;
1743 	usfstl_loop_register(&client->loop);
1744 	INIT_LIST_HEAD(&client->list);
1745 }
1746 
1747 /*
1748  * Register with the kernel to start receiving new frames.
1749  */
send_register_msg(struct wmediumd * ctx)1750 static int send_register_msg(struct wmediumd *ctx)
1751 {
1752 	struct nl_sock *sock = ctx->sock;
1753 	struct nl_msg *msg;
1754 	int ret;
1755 
1756 	msg = nlmsg_alloc();
1757 	if (!msg) {
1758 		w_logf(ctx, LOG_ERR, "Error allocating new message MSG!\n");
1759 		return -1;
1760 	}
1761 
1762 	if (genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, ctx->family_id,
1763 			0, NLM_F_REQUEST, HWSIM_CMD_REGISTER,
1764 			VERSION_NR) == NULL) {
1765 		w_logf(ctx, LOG_ERR, "%s: genlmsg_put failed\n", __func__);
1766 		ret = -1;
1767 		goto out;
1768 	}
1769 
1770 	ret = nl_send_auto_complete(sock, msg);
1771 	if (ret < 0) {
1772 		w_logf(ctx, LOG_ERR, "%s: nl_send_auto failed\n", __func__);
1773 		ret = -1;
1774 		goto out;
1775 	}
1776 	ret = 0;
1777 
1778 out:
1779 	nlmsg_free(msg);
1780 	return ret;
1781 }
1782 
sock_event_cb(struct usfstl_loop_entry * entry)1783 static void sock_event_cb(struct usfstl_loop_entry *entry)
1784 {
1785 	struct wmediumd *ctx = entry->data;
1786 
1787 	nl_recvmsgs_default(ctx->sock);
1788 }
1789 
1790 /*
1791  * Setup netlink socket and callbacks.
1792  */
init_netlink(struct wmediumd * ctx)1793 static int init_netlink(struct wmediumd *ctx)
1794 {
1795 	struct nl_sock *sock;
1796 	int ret;
1797 
1798 	ctx->cb = nl_cb_alloc(NL_CB_CUSTOM);
1799 	if (!ctx->cb) {
1800 		w_logf(ctx, LOG_ERR, "Error allocating netlink callbacks\n");
1801 		return -1;
1802 	}
1803 
1804 	sock = nl_socket_alloc_cb(ctx->cb);
1805 	if (!sock) {
1806 		w_logf(ctx, LOG_ERR, "Error allocating netlink socket\n");
1807 		return -1;
1808 	}
1809 
1810 	ctx->sock = sock;
1811 
1812 	ret = genl_connect(sock);
1813 	if (ret < 0) {
1814 		w_logf(ctx, LOG_ERR, "Error connecting netlink socket ret=%d\n", ret);
1815 		return -1;
1816 	}
1817 
1818 	ctx->family_id = genl_ctrl_resolve(sock, "MAC80211_HWSIM");
1819 	if (ctx->family_id < 0) {
1820 		w_logf(ctx, LOG_ERR, "Family MAC80211_HWSIM not registered\n");
1821 		return -1;
1822 	}
1823 
1824 	nl_cb_set(ctx->cb, NL_CB_MSG_IN, NL_CB_CUSTOM, process_messages_cb, ctx);
1825 	nl_cb_err(ctx->cb, NL_CB_CUSTOM, nl_err_cb, ctx);
1826 
1827 	return 0;
1828 }
1829 
1830 /*
1831  *	Print the CLI help
1832  */
print_help(int exval)1833 static void print_help(int exval)
1834 {
1835 	printf("wmediumd v%s - a wireless medium simulator\n", VERSION_STR);
1836 	printf("wmediumd [-h] [-V] [-l LOG_LVL] [-x FILE] -c FILE \n\n");
1837 
1838 	printf("  -h              print this help and exit\n");
1839 	printf("  -V              print version and exit\n\n");
1840 
1841 	printf("  -l LOG_LVL      set the logging level\n");
1842 	printf("                  LOG_LVL: RFC 5424 severity, values 0 - 7\n");
1843 	printf("                  >= 3: errors are logged\n");
1844 	printf("                  >= 5: startup msgs are logged\n");
1845 	printf("                  >= 6: dropped packets are logged (default)\n");
1846 	printf("                  == 7: all packets will be logged\n");
1847 	printf("  -c FILE         set input config file\n");
1848 	printf("  -x FILE         set input PER file\n");
1849 	printf("  -t socket       set the time control socket\n");
1850 	printf("  -u socket       expose vhost-user socket, don't use netlink\n");
1851 	printf("  -a socket       expose wmediumd API socket\n");
1852 	printf("  -n              force netlink use even with vhost-user\n");
1853 	printf("  -p FILE         log packets to pcapng file FILE\n");
1854 
1855 	exit(exval);
1856 }
1857 
init_pcapng(struct wmediumd * ctx,const char * filename)1858 static void init_pcapng(struct wmediumd *ctx, const char *filename)
1859 {
1860 	struct {
1861 		uint32_t type, blocklen, byte_order;
1862 		uint16_t ver_maj, ver_min;
1863 		uint64_t seclen;
1864 		uint32_t blocklen2;
1865 	} __attribute__((packed)) blockhdr = {
1866 		.type = 0x0A0D0D0A,
1867 		.blocklen = sizeof(blockhdr),
1868 		.byte_order = 0x1A2B3C4D,
1869 		.ver_maj = 1,
1870 		.ver_min = 0,
1871 		.seclen = -1,
1872 		.blocklen2 = sizeof(blockhdr),
1873 	};
1874 	struct {
1875 		uint32_t type, blocklen;
1876 		uint16_t linktype, reserved;
1877 		uint32_t snaplen;
1878 		struct {
1879 			uint16_t code, len;
1880 			uint8_t val, pad[3];
1881 		} opt_if_tsresol;
1882 		struct {
1883 			uint16_t code, len;
1884 		} opt_endofopt;
1885 		uint32_t blocklen2;
1886 	} __attribute__((packed)) idb = {
1887 		.type = 1,
1888 		.blocklen = sizeof(idb),
1889 		.linktype = 127, // radiotap
1890 		.snaplen = -1,
1891 		.opt_if_tsresol.code = 9,
1892 		.opt_if_tsresol.len = 1,
1893 		.opt_if_tsresol.val = 6, // usec
1894 		.blocklen2 = sizeof(idb),
1895 	};
1896 
1897 	if (ctx->pcap_file != NULL) {
1898 		close_pcapng(ctx);
1899 	}
1900 
1901 	if (!filename)
1902 		return;
1903 
1904 	ctx->pcap_file = fopen(filename, "w+");
1905 	fwrite(&blockhdr, sizeof(blockhdr), 1, ctx->pcap_file);
1906 	fwrite(&idb, sizeof(idb), 1, ctx->pcap_file);
1907 }
1908 
1909 #ifndef VIRTIO_F_VERSION_1
1910 #define VIRTIO_F_VERSION_1 32
1911 #endif
1912 
wmediumd_main(int argc,char * argv[],int event_fd,int msq_id)1913 int wmediumd_main(int argc, char *argv[], int event_fd, int msq_id)
1914 {
1915 	int opt;
1916 	struct wmediumd ctx = {};
1917 	char *config_file = NULL;
1918 	char *per_file = NULL;
1919 	const char *time_socket = NULL, *api_socket = NULL;
1920 	struct usfstl_sched_ctrl ctrl = {};
1921 	struct usfstl_vhost_user_server vusrv = {
1922 		.ops = &wmediumd_vu_ops,
1923 		.max_queues = HWSIM_NUM_VQS,
1924 		.input_queues = 1 << HWSIM_VQ_TX,
1925 		.features = 1ULL << VIRTIO_F_VERSION_1,
1926 		.protocol_features =
1927 			1ULL << VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS,
1928 		.data = &ctx,
1929 	};
1930 	bool use_netlink, force_netlink = false;
1931 
1932 	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
1933 
1934 	if (argc == 1) {
1935 		fprintf(stderr, "This program needs arguments....\n\n");
1936 		print_help(EXIT_FAILURE);
1937 	}
1938 
1939 	ctx.log_lvl = 6;
1940 	unsigned long int parse_log_lvl;
1941 	char* parse_end_token;
1942 
1943 	while ((opt = getopt(argc, argv, "hVc:l:x:t:u:a:np:")) != -1) {
1944 		switch (opt) {
1945 		case 'h':
1946 			print_help(EXIT_SUCCESS);
1947 			break;
1948 		case 'V':
1949 			printf("wmediumd v%s - a wireless medium simulator "
1950 			       "for mac80211_hwsim\n", VERSION_STR);
1951 			exit(EXIT_SUCCESS);
1952 			break;
1953 		case 'c':
1954 			config_file = optarg;
1955 			break;
1956 		case 'x':
1957 			printf("Input packet error rate file: %s\n", optarg);
1958 			per_file = optarg;
1959 			break;
1960 		case ':':
1961 			printf("wmediumd: Error - Option `%c' "
1962 			       "needs a value\n\n", optopt);
1963 			print_help(EXIT_FAILURE);
1964 			break;
1965 		case 'l':
1966 			parse_log_lvl = strtoul(optarg, &parse_end_token, 10);
1967 			if ((parse_log_lvl == ULONG_MAX && errno == ERANGE) ||
1968 			     optarg == parse_end_token || parse_log_lvl > 7) {
1969 				printf("wmediumd: Error - Invalid RFC 5424 severity level: "
1970 							   "%s\n\n", optarg);
1971 				print_help(EXIT_FAILURE);
1972 			}
1973 			ctx.log_lvl = parse_log_lvl;
1974 			break;
1975 		case 't':
1976 			time_socket = optarg;
1977 			break;
1978 		case 'u':
1979 			vusrv.socket = optarg;
1980 			break;
1981 		case 'a':
1982 			api_socket = optarg;
1983 			break;
1984 		case 'n':
1985 			force_netlink = true;
1986 			break;
1987 		case 'p':
1988 			init_pcapng(&ctx, optarg);
1989 			break;
1990 		case '?':
1991 			printf("wmediumd: Error - No such option: "
1992 			       "`%c'\n\n", optopt);
1993 			print_help(EXIT_FAILURE);
1994 			break;
1995 		}
1996 
1997 	}
1998 
1999 	if (optind < argc)
2000 		print_help(EXIT_FAILURE);
2001 
2002 	if (!config_file) {
2003 		printf("%s: config file must be supplied\n", argv[0]);
2004 		print_help(EXIT_FAILURE);
2005 	}
2006 
2007 	w_logf(&ctx, LOG_NOTICE, "Input configuration file: %s\n", config_file);
2008 
2009 	INIT_LIST_HEAD(&ctx.stations);
2010 	INIT_LIST_HEAD(&ctx.clients);
2011 	INIT_LIST_HEAD(&ctx.clients_to_free);
2012 
2013 	if (load_config(&ctx, config_file, per_file))
2014 		return EXIT_FAILURE;
2015 
2016 	use_netlink = force_netlink || !vusrv.socket;
2017 
2018 	/* init netlink */
2019 	if (use_netlink && init_netlink(&ctx) < 0)
2020 		return EXIT_FAILURE;
2021 
2022 	if (ctx.intf) {
2023 		ctx.intf_job.start = 10000; // usec
2024 		ctx.intf_job.name = "interference update";
2025 		ctx.intf_job.data = &ctx;
2026 		ctx.intf_job.callback = wmediumd_intf_update;
2027 		usfstl_sched_add_job(&scheduler, &ctx.intf_job);
2028 	}
2029 
2030 	if (vusrv.socket)
2031 		usfstl_vhost_user_server_start(&vusrv);
2032 
2033 	if (use_netlink) {
2034 		ctx.nl_client.type = CLIENT_NETLINK;
2035 		list_add(&ctx.nl_client.list, &ctx.clients);
2036 
2037 		ctx.nl_loop.handler = sock_event_cb;
2038 		ctx.nl_loop.data = &ctx;
2039 		ctx.nl_loop.fd = nl_socket_get_fd(ctx.sock);
2040 		usfstl_loop_register(&ctx.nl_loop);
2041 
2042 		/* register for new frames */
2043 		if (send_register_msg(&ctx) == 0)
2044 			w_logf(&ctx, LOG_NOTICE, "REGISTER SENT!\n");
2045 	}
2046 
2047 	if (api_socket) {
2048 		signal(SIGPIPE, SIG_IGN);
2049 		usfstl_uds_create(api_socket, wmediumd_api_connected, &ctx);
2050 	}
2051 
2052 	if (time_socket) {
2053 		usfstl_sched_ctrl_start(&ctrl, time_socket,
2054 				      1000 /* nsec per usec */,
2055 				      (uint64_t)-1 /* no ID */,
2056 				      &scheduler);
2057 		vusrv.scheduler = &scheduler;
2058 		vusrv.ctrl = &ctrl;
2059 		ctx.ctrl = &ctrl;
2060 	} else {
2061 		usfstl_sched_wallclock_init(&scheduler, 1000);
2062 	}
2063 
2064 	// Control event_fd to communicate WmediumdService.
2065 	ctx.grpc_loop.handler = wmediumd_grpc_service_handler;
2066 	ctx.grpc_loop.data = &ctx;
2067 	ctx.grpc_loop.fd = event_fd;
2068 	usfstl_loop_register(&ctx.grpc_loop);
2069 	ctx.msq_id = msq_id;
2070 
2071 	while (1) {
2072 		if (time_socket) {
2073 			usfstl_sched_next(&scheduler);
2074 		} else {
2075 			usfstl_sched_wallclock_wait_and_handle(&scheduler);
2076 
2077 			if (usfstl_sched_next_pending(&scheduler, NULL))
2078 				usfstl_sched_next(&scheduler);
2079 		}
2080 
2081 		while (!list_empty(&ctx.clients_to_free)) {
2082 			struct client *client;
2083 
2084 			client = list_first_entry(&ctx.clients_to_free,
2085 						  struct client, list);
2086 
2087 			list_del(&client->list);
2088 			free(client);
2089 		}
2090 	}
2091 
2092 	free(ctx.sock);
2093 	free(ctx.cb);
2094 	free(ctx.intf);
2095 	free(ctx.per_matrix);
2096 
2097 	return EXIT_SUCCESS;
2098 }
2099