1 /*
2  * Copyright (c) 2015 Intel Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /* Listen UDP (unicast or multicast) and TCP messages from tun device and send
18  * them back to client that is running in qemu.
19  */
20 
21 #include <stdio.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <poll.h>
25 #include <errno.h>
26 #include <arpa/inet.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdbool.h>
30 #include <sys/ioctl.h>
31 #include <net/if.h>
32 #include <linux/ipv6.h>
33 #include <ifaddrs.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 
37 #define SERVER_PORT  4242
38 #define MAX_BUF_SIZE 1280	/* min IPv6 MTU, the actual data is smaller */
39 #define MAX_TIMEOUT  3		/* in seconds */
40 
41 static bool do_reverse;
42 
reverse(unsigned char * buf,int len)43 static inline void reverse(unsigned char *buf, int len)
44 {
45 	int i, last = len - 1;
46 
47 	for(i = 0; i < len/2; i++) {
48 		unsigned char tmp = buf[i];
49 		buf[i] = buf[last - i];
50 		buf[last - i] = tmp;
51 	}
52 }
53 
get_ifindex(const char * name)54 static int get_ifindex(const char *name)
55 {
56 	struct ifreq ifr;
57 	int sk, err;
58 
59 	if (!name)
60 		return -1;
61 
62 	sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
63 	if (sk < 0)
64 		return -1;
65 
66 	memset(&ifr, 0, sizeof(ifr));
67 	strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
68 
69 	err = ioctl(sk, SIOCGIFINDEX, &ifr);
70 
71 	close(sk);
72 
73 	if (err < 0)
74 		return -1;
75 
76 	return ifr.ifr_ifindex;
77 }
78 
get_socket(int family,int proto)79 static int get_socket(int family, int proto)
80 {
81 	int fd;
82 
83 	fd = socket(family, proto == IPPROTO_TCP ? SOCK_STREAM : SOCK_DGRAM,
84 		    proto);
85 	if (fd < 0) {
86 		perror("socket");
87 		exit(-errno);
88 	}
89 	return fd;
90 }
91 
bind_device(int fd,const char * interface,void * addr,int len,int family)92 static int bind_device(int fd, const char *interface, void *addr, int len,
93 		       int family)
94 {
95 	struct ifreq ifr;
96 	int ret, val = 1;
97 
98 	memset(&ifr, 0, sizeof(ifr));
99 	snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", interface);
100 
101 	if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
102 		       (void *)&ifr, sizeof(ifr)) < 0) {
103 		perror("SO_BINDTODEVICE");
104 		exit(-errno);
105 	}
106 
107 	setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
108 
109 	switch (family) {
110 		struct sockaddr_in6 *addr6;
111 		struct sockaddr_in *addr4;
112 		char addr_buf[INET6_ADDRSTRLEN];
113 
114 	case AF_INET:
115 		addr4 = ((struct sockaddr_in *)addr);
116 		printf("Socket %d binding to %s\n", fd,
117 		       inet_ntop(AF_INET, &addr4->sin_addr,
118 				 addr_buf, sizeof(addr_buf)));
119 		break;
120 	case AF_INET6:
121 		addr6 = ((struct sockaddr_in6 *)addr);
122 		printf("Socket %d binding to %s\n", fd,
123 		       inet_ntop(AF_INET6, &addr6->sin6_addr,
124 				 addr_buf, sizeof(addr_buf)));
125 		break;
126 	}
127 
128 	ret = bind(fd, (struct sockaddr *)addr, len);
129 	if (ret < 0) {
130 		perror("bind");
131 	}
132 }
133 
receive(int fd,unsigned char * buf,int buflen,struct sockaddr * addr,socklen_t * addrlen,int proto)134 static int receive(int fd, unsigned char *buf, int buflen,
135 		   struct sockaddr *addr, socklen_t *addrlen, int proto)
136 {
137 	int ret;
138 
139 	if (proto == IPPROTO_UDP) {
140 		ret = recvfrom(fd, buf, buflen, 0, addr, addrlen);
141 		if (ret < 0) {
142 			perror("recv");
143 			return ret;
144 		}
145 	} else if (proto == IPPROTO_TCP) {
146 		ret = read(fd, buf, buflen);
147 		if (ret < 0) {
148 			perror("read");
149 			return ret;
150 		}
151 	} else {
152 		printf("Invalid protocol %d\n", proto);
153 		return -EPROTONOSUPPORT;
154 	}
155 
156 	return ret;
157 }
158 
reply(int fd,unsigned char * buf,int buflen,struct sockaddr * addr,socklen_t addrlen,int proto)159 static int reply(int fd, unsigned char *buf, int buflen,
160 		 struct sockaddr *addr, socklen_t addrlen, int proto)
161 {
162 	int ret;
163 
164 	if (proto == IPPROTO_UDP) {
165 		ret = sendto(fd, buf, buflen, 0, addr, addrlen);
166 		if (ret < 0)
167 			perror("send");
168 
169 	} else if (proto == IPPROTO_TCP) {
170 		int sent = 0;
171 
172 		do {
173 			ret = write(fd, buf + sent, buflen - sent);
174 			if (ret <= 0)
175 				break;
176 
177 			sent += ret;
178 		} while (sent < buflen);
179 
180 	} else {
181 		printf("Invalid protocol %d\n", proto);
182 		return -EPROTONOSUPPORT;
183 	}
184 
185 	return ret;
186 }
187 
udp_receive_and_reply(fd_set * rfds,int fd_recv,int fd_send,unsigned char * buf,int buflen,int proto,bool do_reverse)188 static int udp_receive_and_reply(fd_set *rfds, int fd_recv, int fd_send,
189 				 unsigned char *buf, int buflen, int proto,
190 				 bool do_reverse)
191 {
192 	if (FD_ISSET(fd_recv, rfds)) {
193 		struct sockaddr_in6 from = { 0 };
194 		socklen_t fromlen = sizeof(from);
195 		int ret;
196 
197 		ret = receive(fd_recv, buf, buflen,
198 			      (struct sockaddr *)&from, &fromlen, proto);
199 		if (ret < 0)
200 			return ret;
201 
202 		if (do_reverse)
203 			reverse(buf, ret);
204 
205 		ret = reply(fd_send, buf, ret,
206 			    (struct sockaddr *)&from, fromlen, proto);
207 		if (ret < 0)
208 			return ret;
209 
210 		fprintf(stderr, ".");
211 	}
212 
213 	return 0;
214 }
215 
tcp_receive_and_reply(fd_set * rfds,fd_set * errfds,int fd_recv,int fd_send,unsigned char * buf,int buflen,int proto)216 static int tcp_receive_and_reply(fd_set *rfds, fd_set *errfds,
217 				 int fd_recv, int fd_send,
218 				 unsigned char *buf, int buflen, int proto)
219 {
220 	struct sockaddr_in6 from = { 0 };
221 	socklen_t fromlen = sizeof(from);
222 	int ret = 0;
223 
224 	if (FD_ISSET(fd_recv, rfds)) {
225 		ret = receive(fd_recv, buf, buflen,
226 			      (struct sockaddr *)&from, &fromlen, proto);
227 		if (ret < 0)
228 			return ret;
229 
230 		ret = reply(fd_send, buf, ret,
231 			    (struct sockaddr *)&from, fromlen, proto);
232 		if (ret < 0) {
233 			return ret;
234 		} else if (ret == 0) {
235 			close(fd_recv);
236 			printf("Connection closed fd %d\n", fd_recv);
237 		}
238 
239 		fprintf(stderr, ".");
240 	}
241 
242 	return ret;
243 }
244 
245 #define MY_MCAST_ADDR6 \
246 	{ { { 0xff,0x84,0,0,0,0,0,0,0,0,0,0,0,0,0,0x2 } } } /* ff84::2 */
247 
248 #define MY_MCAST_ADDR4 "239.192.0.2"
249 
family_to_level(int family)250 int family_to_level(int family)
251 {
252 	switch (family) {
253 	case AF_INET:
254 		return IPPROTO_IP;
255 	case AF_INET6:
256 		return IPPROTO_IPV6;
257 	default:
258 		return -1;
259 	}
260 }
261 
join_mc_group(int sock,int ifindex,int family,void * addr,int addr_len)262 static int join_mc_group(int sock, int ifindex, int family, void *addr,
263 		       int addr_len)
264 {
265 	struct group_req req;
266 	int ret, off = 0;
267 
268 	memset(&req, 0, sizeof(req));
269 
270 	req.gr_interface = ifindex;
271 	memcpy(&req.gr_group, addr, addr_len);
272 
273 	ret = setsockopt(sock, family_to_level(family), MCAST_JOIN_GROUP,
274 			 &req, sizeof(req));
275 	if (ret < 0)
276 		perror("setsockopt(MCAST_JOIN_GROUP)");
277 
278 	switch (family) {
279 	case AF_INET:
280 		ret = setsockopt(sock, family_to_level(family),
281 				 IP_MULTICAST_LOOP, &off, sizeof(off));
282 		break;
283 	case AF_INET6:
284 		ret = setsockopt(sock, family_to_level(family),
285 				 IPV6_MULTICAST_LOOP, &off, sizeof(off));
286 		break;
287 	}
288 	return ret;
289 }
290 
find_address(int family,struct ifaddrs * if_address,const char * if_name,void * address)291 static int find_address(int family, struct ifaddrs *if_address,
292 			const char *if_name, void *address)
293 {
294 	struct ifaddrs *tmp;
295 	int error = -ENOENT;
296 
297 	for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
298 		if (tmp->ifa_addr &&
299 		    !strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
300 		    tmp->ifa_addr->sa_family == family) {
301 
302 			switch (family) {
303 			case AF_INET: {
304 				struct sockaddr_in *in4 =
305 					(struct sockaddr_in *)tmp->ifa_addr;
306 				if (in4->sin_addr.s_addr == INADDR_ANY)
307 					continue;
308 				if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
309 						((in_addr_t)0xa9fe0000))
310 					continue;
311 				memcpy(address, &in4->sin_addr,
312 				       sizeof(struct in_addr));
313 				error = 0;
314 				goto out;
315 			}
316 			case AF_INET6: {
317 				struct sockaddr_in6 *in6 =
318 					(struct sockaddr_in6 *)tmp->ifa_addr;
319 				if (!memcmp(&in6->sin6_addr, &in6addr_any,
320 					    sizeof(struct in6_addr)))
321 					continue;
322 				if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
323 					continue;
324 
325 				memcpy(address, &in6->sin6_addr,
326 				       sizeof(struct in6_addr));
327 				error = 0;
328 				goto out;
329 			}
330 			default:
331 				error = -EINVAL;
332 				goto out;
333 			}
334 		}
335 	}
336 
337 out:
338 	return error;
339 }
340 
get_address(const char * if_name,int family,void * address)341 static int get_address(const char *if_name, int family, void *address)
342 {
343 	struct ifaddrs *if_address;
344 	int err;
345 
346 	if (getifaddrs(&if_address) < 0) {
347 		err = -errno;
348 		fprintf(stderr, "Cannot get interface addresses for "
349 			"interface %s error %d/%s",
350 			if_name, err, strerror(-err));
351 		return err;
352 	}
353 
354 	err = find_address(family, if_address, if_name, address);
355 
356 	freeifaddrs(if_address);
357 
358 	return err;
359 }
360 
361 extern int optind, opterr, optopt;
362 extern char *optarg;
363 
364 /* The application returns:
365  *    < 0 : connection or similar error
366  *      0 : no errors, all tests passed
367  *    > 0 : could not send all the data to server
368  */
main(int argc,char ** argv)369 int main(int argc, char**argv)
370 {
371 	int c, ret, fd4 = 0, fd6 = 0, fd4m = 0, fd6m = 0, tcp4 = 0, tcp6 = 0,
372 		i = 0, timeout = 0;
373 	int port = SERVER_PORT;
374 	int accepted4 = -1, accepted6 = -1;
375 	struct sockaddr_in6 addr6_recv = { 0 }, maddr6 = { 0 };
376 	struct in6_addr mcast6_addr = MY_MCAST_ADDR6;
377 	struct in_addr mcast4_addr = { 0 };
378 	struct sockaddr_in addr4_recv = { 0 }, maddr4 = { 0 };
379 	int family;
380 	unsigned char buf[MAX_BUF_SIZE];
381 	char addr_buf[INET6_ADDRSTRLEN];
382 	const struct in6_addr any = IN6ADDR_ANY_INIT;
383 	const char *interface = NULL;
384 	fd_set rfds, errfds;
385 	struct timeval tv = {};
386 	int ifindex = -1;
387 	int opt = 1;
388 
389 	opterr = 0;
390 
391 	while ((c = getopt(argc, argv, "i:p:r")) != -1) {
392 		switch (c) {
393 		case 'i':
394 			interface = optarg;
395 			break;
396 		case 'p':
397 			port = atoi(optarg);
398 			break;
399 		case 'r':
400 			do_reverse = true;
401 			break;
402 		}
403 	}
404 
405 	if (!interface) {
406 		printf("usage: %s [-r] -i <iface> [-p <port>]\n", argv[0]);
407 		printf("\t-r Reverse the sent UDP data.\n");
408 		printf("\t-i Use this network interface.\n");
409 		printf("\t-p Use this port (default is %d)\n", SERVER_PORT);
410 		exit(-EINVAL);
411 	}
412 
413 	ifindex = get_ifindex(interface);
414 	if (ifindex < 0) {
415 		printf("Invalid interface %s\n", interface);
416 		exit(-EINVAL);
417 	}
418 
419 	addr4_recv.sin_family = AF_INET;
420 	addr4_recv.sin_port = htons(port);
421 
422 	/* We want to bind to global unicast address here so that
423 	 * we can listen correct addresses. We do not want to listen
424 	 * link local addresses in this test.
425 	 */
426 	get_address(interface, AF_INET, &addr4_recv.sin_addr);
427 	printf("IPv4: binding to %s\n",
428 	       inet_ntop(AF_INET, &addr4_recv.sin_addr,
429 			 addr_buf, sizeof(addr_buf)));
430 
431 	addr6_recv.sin6_family = AF_INET6;
432 	addr6_recv.sin6_port = htons(port);
433 
434 	/* Bind to global unicast address instead of ll address */
435 	get_address(interface, AF_INET6, &addr6_recv.sin6_addr);
436 	printf("IPv6: binding to %s\n",
437 	       inet_ntop(AF_INET6, &addr6_recv.sin6_addr,
438 			 addr_buf, sizeof(addr_buf)));
439 
440 	memcpy(&maddr6.sin6_addr, &mcast6_addr, sizeof(struct in6_addr));
441 	maddr6.sin6_family = AF_INET6;
442 	maddr6.sin6_port = htons(port);
443 
444 	mcast4_addr.s_addr = inet_addr(MY_MCAST_ADDR4);
445 	memcpy(&maddr4.sin_addr, &mcast4_addr, sizeof(struct in_addr));
446 	maddr4.sin_family = AF_INET;
447 	maddr4.sin_port = htons(port);
448 
449 restart:
450 	if (fd4)
451 		close(fd4);
452 	if (fd6)
453 		close(fd6);
454 	if (fd4m)
455 		close(fd4m);
456 	if (fd6m)
457 		close(fd6m);
458 	if (tcp4)
459 		close(tcp4);
460 	if (tcp6)
461 		close(tcp6);
462 
463 	fd4 = get_socket(AF_INET, IPPROTO_UDP);
464 	fd6 = get_socket(AF_INET6, IPPROTO_UDP);
465 	fd4m = get_socket(AF_INET, IPPROTO_UDP);
466 	fd6m = get_socket(AF_INET6, IPPROTO_UDP);
467 	tcp4 = get_socket(AF_INET, IPPROTO_TCP);
468 	tcp6 = get_socket(AF_INET6, IPPROTO_TCP);
469 
470 	printf("Sockets: UPD IPv4 %d IPv6 %d, mcast IPv4 %d IPv6 %d, "
471 	       "TCP IPv4 %d IPv6 %d\n",
472 	       fd4, fd6, fd4m, fd6m, tcp4, tcp6);
473 
474 	bind_device(fd4, interface, &addr4_recv, sizeof(addr4_recv), AF_INET);
475 	bind_device(fd6, interface, &addr6_recv, sizeof(addr6_recv), AF_INET6);
476 
477 	bind_device(fd4m, interface, &maddr4, sizeof(maddr4), AF_INET);
478 	bind_device(fd6m, interface, &maddr6, sizeof(maddr6), AF_INET6);
479 
480 	join_mc_group(fd4m, ifindex, AF_INET, &maddr4, sizeof(maddr4));
481 	join_mc_group(fd6m, ifindex, AF_INET6, &maddr6, sizeof(maddr6));
482 
483 	ret = setsockopt(tcp4, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
484 	if (ret < 0) {
485 		perror("setsockopt TCP v4");
486 	}
487 	ret = setsockopt(tcp6, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
488 	if (ret < 0) {
489 		perror("setsockopt TCP v6");
490 	}
491 	bind_device(tcp4, interface, &addr4_recv, sizeof(addr4_recv), AF_INET);
492 	bind_device(tcp6, interface, &addr6_recv, sizeof(addr6_recv), AF_INET6);
493 
494 	if (listen(tcp4, 0) < 0) {
495 		perror("IPv4 TCP listen");
496 	}
497 	if (listen(tcp6, 0) < 0) {
498 		perror("IPv6 TCP listen");
499 	}
500 
501 	if (fcntl(tcp4, F_SETFL, O_NONBLOCK) < 0) {
502 		perror("IPv4 TCP non blocking");
503 	}
504 
505 	if (fcntl(tcp6, F_SETFL, O_NONBLOCK) < 0) {
506 		perror("IPv6 TCP non blocking");
507 	}
508 
509 #define MAX(a,b) ((a) > (b) ? (a) : (b))
510 
511 	while (1) {
512 		int addr4len = sizeof(addr4_recv);
513 		int addr6len = sizeof(addr6_recv);
514 		int fd;
515 
516 		FD_ZERO(&rfds);
517 		FD_SET(fd4, &rfds);
518 		FD_SET(fd6, &rfds);
519 		FD_SET(fd4m, &rfds);
520 		FD_SET(fd6m, &rfds);
521 		FD_SET(tcp4, &rfds);
522 		FD_SET(tcp6, &rfds);
523 
524 		FD_ZERO(&errfds);
525 		FD_SET(tcp4, &errfds);
526 		FD_SET(tcp6, &errfds);
527 
528 		fd = MAX(tcp4, tcp6);
529 
530 		if (accepted4 >= 0) {
531 			FD_SET(accepted4, &rfds);
532 			FD_SET(accepted4, &errfds);
533 			fd = MAX(fd, accepted4);
534 		}
535 		if (accepted6 >= 0) {
536 			FD_SET(accepted6, &rfds);
537 			FD_SET(accepted6, &errfds);
538 			fd = MAX(fd, accepted6);
539 		}
540 
541 		ret = select(fd + 1, &rfds, NULL,
542 			     &errfds, NULL);
543 		if (ret < 0) {
544 			perror("select");
545 			break;
546 		} else if (ret == 0) {
547 			continue;
548 		}
549 
550 		if (accepted4 < 0) {
551 			accepted4 = accept(tcp4, (struct sockaddr *)&addr4_recv,
552 					   &addr4len);
553 			if (accepted4 < 0 &&
554 			    (errno != EAGAIN && errno != EWOULDBLOCK)) {
555 				perror("accept IPv4");
556 				break;
557 			} else if (accepted4 >= 0) {
558 				FD_SET(accepted4, &errfds);
559 				FD_SET(accepted4, &rfds);
560 			}
561 		}
562 
563 		if (accepted6 < 0) {
564 			accepted6 = accept(tcp6, (struct sockaddr *)&addr6_recv,
565 					   &addr6len);
566 			if (accepted6 < 0 &&
567 			    (errno != EAGAIN && errno != EWOULDBLOCK)) {
568 				perror("accept IPv6");
569 				break;
570 			} else if (accepted6 >= 0) {
571 				FD_SET(accepted6, &errfds);
572 				FD_SET(accepted6, &rfds);
573 
574 				printf("New connection fd %d\n", accepted6);
575 			}
576 		}
577 
578 		/* Unicast IPv4 */
579 		if (udp_receive_and_reply(&rfds, fd4, fd4, buf, sizeof(buf),
580 					  IPPROTO_UDP, do_reverse) < 0)
581 			goto restart;
582 
583 		/* Unicast IPv6 */
584 		if (udp_receive_and_reply(&rfds, fd6, fd6, buf, sizeof(buf),
585 					  IPPROTO_UDP, do_reverse) < 0)
586 			goto restart;
587 
588 		/* Multicast IPv4 */
589 		if (udp_receive_and_reply(&rfds, fd4m, fd4, buf, sizeof(buf),
590 					  IPPROTO_UDP, do_reverse) < 0)
591 			goto restart;
592 
593 		/* Multicast IPv6 */
594 		if (udp_receive_and_reply(&rfds, fd6m, fd6, buf, sizeof(buf),
595 					  IPPROTO_UDP, do_reverse) < 0)
596 			goto restart;
597 
598 		/* TCP IPv4 */
599 		ret = tcp_receive_and_reply(&rfds, &errfds,
600 					    accepted4, accepted4,
601 					    buf, sizeof(buf),
602 					    IPPROTO_TCP);
603 		if (ret < 0)
604 			goto restart;
605 		else if (ret == 0)
606 			accepted4 = -1;
607 
608 		/* TCP IPv6 */
609 		ret = tcp_receive_and_reply(&rfds, &errfds,
610 					    accepted6, accepted6,
611 					    buf, sizeof(buf),
612 					    IPPROTO_TCP);
613 		if (ret < 0)
614 			goto restart;
615 		else if (ret == 0)
616 			accepted6 = -1;
617 	}
618 
619 	close(fd4);
620 	close(fd6);
621 	close(fd4m);
622 	close(fd6m);
623 	close(tcp4);
624 	close(tcp6);
625 
626 	printf("\n");
627 
628 	exit(0);
629 }
630