1 /*
2   *  Copyright (c) 2007, 2008, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3   *
4   *  OS dependent API for using card via network.
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
8   *  the Free Software Foundation; either version 2 of the License, or
9   *  (at your option) any later version.
10   *
11   *  This program is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   *  GNU General Public License for more details.
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19   */
20 
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <assert.h>
30 #include <sys/select.h>
31 #include <errno.h>
32 
33 #include "osdep.h"
34 #include "network.h"
35 
36 #define QUEUE_MAX 666
37 
38 struct netqueue
39 {
40 	unsigned char q_buf[2048];
41 	int q_len;
42 
43 	struct netqueue * q_next;
44 	struct netqueue * q_prev;
45 };
46 
47 struct priv_net
48 {
49 	int pn_s;
50 	struct netqueue pn_queue;
51 	struct netqueue pn_queue_free;
52 	int pn_queue_len;
53 };
54 
net_send(int s,int command,void * arg,int len)55 EXPORT int net_send(int s, int command, void * arg, int len)
56 {
57 	struct net_hdr * pnh;
58 	char * pktbuf;
59 	size_t pktlen;
60 
61 	// Validate command value
62 	assert(command >= NET_RC || command <= HIGHEST_NET_COMMAND);
63 	if (command < NET_RC || command > HIGHEST_NET_COMMAND)
64 	{
65 		return -1;
66 	}
67 
68 	pktlen = sizeof(struct net_hdr) + len;
69 
70 	pktbuf = (char *) calloc(sizeof(char), pktlen);
71 	if (pktbuf == NULL)
72 	{
73 		perror("calloc");
74 		goto net_send_error;
75 	}
76 
77 	pnh = (struct net_hdr *) pktbuf;
78 	pnh->nh_type = command;
79 	pnh->nh_len = htonl(len);
80 
81 	memcpy(pktbuf + sizeof(struct net_hdr), arg, len);
82 
83 	for (;;)
84 	{
85 		ssize_t rc = send(s, pktbuf, pktlen, 0);
86 
87 		if ((size_t) rc == pktlen) break;
88 
89 		if (rc == EAGAIN || rc == EWOULDBLOCK || rc == EINTR) continue;
90 
91 		if (rc == ECONNRESET)
92 			printf("Connection reset while sending packet!\n");
93 
94 		goto net_send_error;
95 	}
96 
97 	free(pktbuf);
98 	return 0;
99 
100 net_send_error:
101 	free(pktbuf);
102 	return -1;
103 }
104 
net_read_exact(int s,void * arg,int len)105 EXPORT int net_read_exact(int s, void * arg, int len)
106 {
107 	ssize_t rc;
108 	int rlen = 0;
109 	char * buf = (char *) arg;
110 	while (rlen < len)
111 	{
112 		rc = recv(s, buf, (len - rlen), 0);
113 
114 		if (rc < 1)
115 		{
116 			if (rc == -1 && (errno == EAGAIN || errno == EINTR))
117 			{
118 				usleep(100);
119 				continue;
120 			}
121 
122 			return -1;
123 		}
124 
125 		buf += rc;
126 		rlen += rc;
127 	}
128 
129 	return 0;
130 }
131 
net_get(int s,void * arg,int * len)132 EXPORT int net_get(int s, void * arg, int * len)
133 {
134 	struct net_hdr nh;
135 	int plen;
136 
137 	if (net_read_exact(s, &nh, sizeof(nh)) == -1)
138 	{
139 		return -1;
140 	}
141 
142 	plen = ntohl(nh.nh_len);
143 	assert(plen <= *len && plen >= 0);
144 
145 	*len = plen;
146 	if ((*len) && (net_read_exact(s, arg, *len) == -1))
147 	{
148 		return -1;
149 	}
150 
151 	return nh.nh_type;
152 }
153 
queue_del(struct netqueue * q)154 static void queue_del(struct netqueue * q)
155 {
156 	q->q_prev->q_next = q->q_next;
157 	q->q_next->q_prev = q->q_prev;
158 }
159 
queue_add(struct netqueue * head,struct netqueue * q)160 static void queue_add(struct netqueue * head, struct netqueue * q)
161 {
162 	struct netqueue * pos = head->q_prev;
163 
164 	q->q_prev = pos;
165 	q->q_next = pos->q_next;
166 	q->q_next->q_prev = q;
167 	pos->q_next = q;
168 }
169 
170 #if 0
171 static int queue_len(struct netqueue *head)
172 {
173 	struct netqueue *q = head->q_next;
174 	int i = 0;
175 
176 	while (q != head) {
177 		i++;
178 		q = q->q_next;
179 	}
180 
181 	return i;
182 }
183 #endif
184 
queue_get_slot(struct priv_net * pn)185 static struct netqueue * queue_get_slot(struct priv_net * pn)
186 {
187 	struct netqueue * q = pn->pn_queue_free.q_next;
188 
189 	if (q != &pn->pn_queue_free)
190 	{
191 		queue_del(q);
192 		return q;
193 	}
194 
195 	if (pn->pn_queue_len++ > QUEUE_MAX) return NULL;
196 
197 	return malloc(sizeof(*q));
198 }
199 
net_enque(struct priv_net * pn,void * buf,int len)200 static void net_enque(struct priv_net * pn, void * buf, int len)
201 {
202 	struct netqueue * q;
203 
204 	q = queue_get_slot(pn);
205 	if (!q) return;
206 
207 	q->q_len = len;
208 	assert((int) sizeof(q->q_buf) >= q->q_len);
209 	memcpy(q->q_buf, buf, q->q_len);
210 	queue_add(&pn->pn_queue, q);
211 }
212 
net_get_nopacket(struct priv_net * pn,void * arg,int * len)213 static int net_get_nopacket(struct priv_net * pn, void * arg, int * len)
214 {
215 	unsigned char buf[2048];
216 	int l = sizeof(buf);
217 	int c;
218 
219 	while (1)
220 	{
221 		l = sizeof(buf);
222 		c = net_get(pn->pn_s, buf, &l);
223 		if (c < 0) return c;
224 
225 		if (c != NET_PACKET && c > 0) break;
226 
227 		if (c > 0) net_enque(pn, buf, l);
228 	}
229 
230 	assert(l <= *len);
231 	memcpy(arg, buf, l);
232 	*len = l;
233 
234 	return c;
235 }
236 
net_cmd(struct priv_net * pn,int command,void * arg,int alen)237 static int net_cmd(struct priv_net * pn, int command, void * arg, int alen)
238 {
239 	uint32_t rc;
240 	int len;
241 	int cmd;
242 
243 	if (net_send(pn->pn_s, command, arg, alen) == -1)
244 	{
245 		return -1;
246 	}
247 
248 	len = sizeof(rc);
249 	cmd = net_get_nopacket(pn, &rc, &len);
250 	if (cmd == -1)
251 	{
252 		return -1;
253 	}
254 	assert(cmd == NET_RC);
255 	assert(len == sizeof(rc));
256 
257 	return ntohl(rc);
258 }
259 
queue_get(struct priv_net * pn,void * buf,int len)260 static int queue_get(struct priv_net * pn, void * buf, int len)
261 {
262 	struct netqueue * head = &pn->pn_queue;
263 	struct netqueue * q = head->q_next;
264 
265 	if (q == head) return 0;
266 
267 	assert(q->q_len <= len);
268 	memcpy(buf, q->q_buf, q->q_len);
269 
270 	queue_del(q);
271 	queue_add(&pn->pn_queue_free, q);
272 
273 	return q->q_len;
274 }
275 
276 static int
net_read(struct wif * wi,unsigned char * h80211,int len,struct rx_info * ri)277 net_read(struct wif * wi, unsigned char * h80211, int len, struct rx_info * ri)
278 {
279 	struct priv_net * pn = wi_priv(wi);
280 	uint32_t buf[512]; // 512 * 4 = 2048
281 	unsigned char * bufc = (unsigned char *) buf;
282 	int cmd;
283 	int sz = sizeof(*ri);
284 	int l;
285 	int ret;
286 
287 	/* try queue */
288 	l = queue_get(pn, buf, sizeof(buf));
289 	if (!l)
290 	{
291 		/* try reading form net */
292 		l = sizeof(buf);
293 		cmd = net_get(pn->pn_s, buf, &l);
294 
295 		if (cmd == -1) return -1;
296 		if (cmd == NET_RC)
297 		{
298 			ret = ntohl((buf[0]));
299 			return ret;
300 		}
301 		assert(cmd == NET_PACKET);
302 	}
303 
304 	/* XXX */
305 	if (ri)
306 	{
307 		// re-assemble 64-bit integer
308 		ri->ri_mactime = __be64_to_cpu(((uint64_t) buf[0] << 32 || buf[1]));
309 		ri->ri_power = __be32_to_cpu(buf[2]);
310 		ri->ri_noise = __be32_to_cpu(buf[3]);
311 		ri->ri_channel = __be32_to_cpu(buf[4]);
312 		ri->ri_freq = __be32_to_cpu(buf[5]);
313 		ri->ri_rate = __be32_to_cpu(buf[6]);
314 		ri->ri_antenna = __be32_to_cpu(buf[7]);
315 	}
316 	l -= sz;
317 	assert(l > 0);
318 	if (l > len) l = len;
319 	memcpy(h80211, &bufc[sz], l);
320 
321 	return l;
322 }
323 
net_get_mac(struct wif * wi,unsigned char * mac)324 static int net_get_mac(struct wif * wi, unsigned char * mac)
325 {
326 	struct priv_net * pn = wi_priv(wi);
327 	uint32_t buf[2]; // only need 6 bytes, this provides 8
328 	int cmd;
329 	int sz = 6;
330 
331 	if (net_send(pn->pn_s, NET_GET_MAC, NULL, 0) == -1) return -1;
332 
333 	cmd = net_get_nopacket(pn, buf, &sz);
334 	if (cmd == -1) return -1;
335 	if (cmd == NET_RC) return ntohl(buf[0]);
336 	assert(cmd == NET_MAC);
337 	assert(sz == 6);
338 
339 	memcpy(mac, buf, 6);
340 
341 	return 0;
342 }
343 
344 static int
net_write(struct wif * wi,unsigned char * h80211,int len,struct tx_info * ti)345 net_write(struct wif * wi, unsigned char * h80211, int len, struct tx_info * ti)
346 {
347 	struct priv_net * pn = wi_priv(wi);
348 	int sz = sizeof(*ti);
349 	unsigned char buf[2048];
350 	unsigned char * ptr = buf;
351 
352 	/* XXX */
353 	if (ti)
354 		memcpy(ptr, ti, sz);
355 	else
356 		memset(ptr, 0, sizeof(*ti));
357 
358 	ptr += sz;
359 	memcpy(ptr, h80211, len);
360 	sz += len;
361 
362 	return net_cmd(pn, NET_WRITE, buf, sz);
363 }
364 
net_set_channel(struct wif * wi,int chan)365 static int net_set_channel(struct wif * wi, int chan)
366 {
367 	uint32_t c = htonl(chan);
368 
369 	return net_cmd(wi_priv(wi), NET_SET_CHAN, &c, sizeof(c));
370 }
371 
net_get_channel(struct wif * wi)372 static int net_get_channel(struct wif * wi)
373 {
374 	struct priv_net * pn = wi_priv(wi);
375 
376 	return net_cmd(pn, NET_GET_CHAN, NULL, 0);
377 }
378 
net_set_rate(struct wif * wi,int rate)379 static int net_set_rate(struct wif * wi, int rate)
380 {
381 	uint32_t c = htonl(rate);
382 
383 	return net_cmd(wi_priv(wi), NET_SET_RATE, &c, sizeof(c));
384 }
385 
net_get_rate(struct wif * wi)386 static int net_get_rate(struct wif * wi)
387 {
388 	struct priv_net * pn = wi_priv(wi);
389 
390 	return net_cmd(pn, NET_GET_RATE, NULL, 0);
391 }
392 
net_get_monitor(struct wif * wi)393 static int net_get_monitor(struct wif * wi)
394 {
395 	return net_cmd(wi_priv(wi), NET_GET_MONITOR, NULL, 0);
396 }
397 
do_net_free(struct wif * wi)398 static void do_net_free(struct wif * wi)
399 {
400 	assert(wi->wi_priv);
401 	free(wi->wi_priv);
402 	wi->wi_priv = 0;
403 	free(wi);
404 }
405 
net_close(struct wif * wi)406 static void net_close(struct wif * wi)
407 {
408 	struct priv_net * pn = wi_priv(wi);
409 
410 	close(pn->pn_s);
411 	do_net_free(wi);
412 }
413 
get_ip_port(char * iface,char * ip,const int ipsize)414 static int get_ip_port(char * iface, char * ip, const int ipsize)
415 {
416 	char * host;
417 	char * ptr;
418 	int port = -1;
419 	struct in_addr addr;
420 
421 	host = strdup(iface);
422 	if (!host) return -1;
423 
424 	ptr = strchr(host, ':');
425 	if (!ptr) goto out;
426 
427 	*ptr++ = 0;
428 
429 	if (!inet_aton(host, &addr)) goto out; /* XXX resolve hostname */
430 
431 	assert(strlen(host) <= 15);
432 	strncpy(ip, host, ipsize);
433 	port = atoi(ptr);
434 
435 out:
436 	free(host);
437 	return port;
438 }
439 
handshake(int s)440 static int handshake(int s)
441 {
442 	if (s)
443 	{
444 	} /* XXX unused */
445 	/* XXX do a handshake */
446 	return 0;
447 }
448 
do_net_open(char * iface)449 static int do_net_open(char * iface)
450 {
451 	int s, port;
452 	char ip[16];
453 	struct sockaddr_in s_in;
454 
455 	port = get_ip_port(iface, ip, sizeof(ip) - 1);
456 	if (port == -1) return -1;
457 
458 	memset(&s_in, 0, sizeof(struct sockaddr_in));
459 	s_in.sin_family = PF_INET;
460 	s_in.sin_port = htons(port);
461 	if (!inet_aton(ip, &s_in.sin_addr)) return -1;
462 
463 	if ((s = socket(s_in.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
464 		return -1;
465 
466 	printf("Connecting to %s port %d...\n", ip, port);
467 
468 	if (connect(s, (struct sockaddr *) &s_in, sizeof(s_in)) == -1)
469 	{
470 		close(s);
471 
472 		printf("Failed to connect\n");
473 
474 		return -1;
475 	}
476 
477 	if (handshake(s) == -1)
478 	{
479 		close(s);
480 
481 		printf("Failed to connect - handshake failed\n");
482 
483 		return -1;
484 	}
485 
486 	printf("Connection successful\n");
487 
488 	return s;
489 }
490 
net_fd(struct wif * wi)491 static int net_fd(struct wif * wi)
492 {
493 	struct priv_net * pn = wi_priv(wi);
494 
495 	return pn->pn_s;
496 }
497 
net_open(char * iface)498 EXPORT struct wif * net_open(char * iface)
499 {
500 	struct wif * wi;
501 	struct priv_net * pn;
502 	int s;
503 
504 	/* setup wi struct */
505 	wi = wi_alloc(sizeof(*pn));
506 	if (!wi) return NULL;
507 	wi->wi_read = net_read;
508 	wi->wi_write = net_write;
509 	wi->wi_set_channel = net_set_channel;
510 	wi->wi_get_channel = net_get_channel;
511 	wi->wi_set_rate = net_set_rate;
512 	wi->wi_get_rate = net_get_rate;
513 	wi->wi_close = net_close;
514 	wi->wi_fd = net_fd;
515 	wi->wi_get_mac = net_get_mac;
516 	wi->wi_get_monitor = net_get_monitor;
517 
518 	/* setup iface */
519 	s = do_net_open(iface);
520 	if (s == -1)
521 	{
522 		do_net_free(wi);
523 		return NULL;
524 	}
525 
526 	/* setup private state */
527 	pn = wi_priv(wi);
528 	pn->pn_s = s;
529 	pn->pn_queue.q_next = pn->pn_queue.q_prev = &pn->pn_queue;
530 	pn->pn_queue_free.q_next = pn->pn_queue_free.q_prev = &pn->pn_queue_free;
531 
532 	return wi;
533 }
534