xref: /dflybsd-src/test/udp/tos/udp_tos.c (revision a45b89791953e820c4b27fafe78163c88a3f5d53)
1544d23f4SSepherosa Ziehau #include <sys/types.h>
2544d23f4SSepherosa Ziehau #include <sys/socket.h>
3544d23f4SSepherosa Ziehau 
4544d23f4SSepherosa Ziehau #include <arpa/inet.h>
5544d23f4SSepherosa Ziehau #include <netinet/in.h>
6544d23f4SSepherosa Ziehau 
7544d23f4SSepherosa Ziehau #include <err.h>
8544d23f4SSepherosa Ziehau #include <stdio.h>
9544d23f4SSepherosa Ziehau #include <stdint.h>
10544d23f4SSepherosa Ziehau #include <stdlib.h>
11544d23f4SSepherosa Ziehau #include <string.h>
12544d23f4SSepherosa Ziehau #include <unistd.h>
13544d23f4SSepherosa Ziehau 
14544d23f4SSepherosa Ziehau static void
usage(const char * cmd)15544d23f4SSepherosa Ziehau usage(const char *cmd)
16544d23f4SSepherosa Ziehau {
17*a45b8979SSepherosa Ziehau 	fprintf(stderr, "%s -4 ip4 -p port [-t tos [-c]]\n", cmd);
18544d23f4SSepherosa Ziehau 	exit(1);
19544d23f4SSepherosa Ziehau }
20544d23f4SSepherosa Ziehau 
21544d23f4SSepherosa Ziehau int
main(int argc,char * argv[])22544d23f4SSepherosa Ziehau main(int argc, char *argv[])
23544d23f4SSepherosa Ziehau {
24544d23f4SSepherosa Ziehau 	struct sockaddr_in in;
25*a45b8979SSepherosa Ziehau 	int s, opt, n, tos, cmsg_tos;
26544d23f4SSepherosa Ziehau 	uint8_t buf[18];
27*a45b8979SSepherosa Ziehau 	struct msghdr msg;
28*a45b8979SSepherosa Ziehau 	struct iovec iov;
29*a45b8979SSepherosa Ziehau 	struct cmsghdr *cm;
30*a45b8979SSepherosa Ziehau 	union {
31*a45b8979SSepherosa Ziehau 		struct cmsghdr cm;
32*a45b8979SSepherosa Ziehau 		uint8_t data[CMSG_SPACE(sizeof(u_char))];
33*a45b8979SSepherosa Ziehau 	} ctrl;
34544d23f4SSepherosa Ziehau 
35544d23f4SSepherosa Ziehau 	memset(&in, 0, sizeof(in));
36544d23f4SSepherosa Ziehau 	in.sin_family = AF_INET;
37544d23f4SSepherosa Ziehau 	tos = -1;
38*a45b8979SSepherosa Ziehau 	cmsg_tos = 0;
39544d23f4SSepherosa Ziehau 
40*a45b8979SSepherosa Ziehau 	while ((opt = getopt(argc, argv, "4:cp:t:")) != -1) {
41544d23f4SSepherosa Ziehau 		switch (opt) {
42544d23f4SSepherosa Ziehau 		case '4':
43544d23f4SSepherosa Ziehau 			if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
44544d23f4SSepherosa Ziehau 				usage(argv[0]);
45544d23f4SSepherosa Ziehau 			break;
46544d23f4SSepherosa Ziehau 
47*a45b8979SSepherosa Ziehau 		case 'c':
48*a45b8979SSepherosa Ziehau 			cmsg_tos = 1;
49*a45b8979SSepherosa Ziehau 			break;
50*a45b8979SSepherosa Ziehau 
51544d23f4SSepherosa Ziehau 		case 'p':
52544d23f4SSepherosa Ziehau 			in.sin_port = strtol(optarg, NULL, 10);
53544d23f4SSepherosa Ziehau 			in.sin_port = htons(in.sin_port);
54544d23f4SSepherosa Ziehau 			break;
55544d23f4SSepherosa Ziehau 
56544d23f4SSepherosa Ziehau 		case 't':
57544d23f4SSepherosa Ziehau 			tos = strtol(optarg, NULL, 10);
58544d23f4SSepherosa Ziehau 			break;
59544d23f4SSepherosa Ziehau 
60544d23f4SSepherosa Ziehau 		default:
61544d23f4SSepherosa Ziehau 			usage(argv[0]);
62544d23f4SSepherosa Ziehau 		}
63544d23f4SSepherosa Ziehau 	}
64544d23f4SSepherosa Ziehau 
65544d23f4SSepherosa Ziehau 	if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0)
66544d23f4SSepherosa Ziehau 		usage(argv[0]);
67544d23f4SSepherosa Ziehau 
68544d23f4SSepherosa Ziehau 	s = socket(AF_INET, SOCK_DGRAM, 0);
69544d23f4SSepherosa Ziehau 	if (s < 0)
70544d23f4SSepherosa Ziehau 		err(2, "socket failed");
71544d23f4SSepherosa Ziehau 
72544d23f4SSepherosa Ziehau 	if (tos >= 0) {
73*a45b8979SSepherosa Ziehau 		if (!cmsg_tos) {
74*a45b8979SSepherosa Ziehau 			if (setsockopt(s, IPPROTO_IP, IP_TOS,
75*a45b8979SSepherosa Ziehau 			    &tos, sizeof(tos)) < 0)
76544d23f4SSepherosa Ziehau 				err(2, "setsockopt IP_TOS %d failed", tos);
77544d23f4SSepherosa Ziehau 
78544d23f4SSepherosa Ziehau 			if (sendto(s, buf, sizeof(buf), 0,
79544d23f4SSepherosa Ziehau 			    (const struct sockaddr *)&in, sizeof(in)) < 0)
80544d23f4SSepherosa Ziehau 				err(2, "sendto failed");
81544d23f4SSepherosa Ziehau 		} else {
82*a45b8979SSepherosa Ziehau 			iov.iov_base = buf;
83*a45b8979SSepherosa Ziehau 			iov.iov_len = sizeof(buf);
84*a45b8979SSepherosa Ziehau 
85*a45b8979SSepherosa Ziehau 			memset(&msg, 0, sizeof(msg));
86*a45b8979SSepherosa Ziehau 			msg.msg_name = &in;
87*a45b8979SSepherosa Ziehau 			msg.msg_namelen = sizeof(in);
88*a45b8979SSepherosa Ziehau 			msg.msg_iov = &iov;
89*a45b8979SSepherosa Ziehau 			msg.msg_iovlen = 1;
90*a45b8979SSepherosa Ziehau 			msg.msg_control = ctrl.data;
91*a45b8979SSepherosa Ziehau 			msg.msg_controllen = sizeof(ctrl.data);
92*a45b8979SSepherosa Ziehau 
93*a45b8979SSepherosa Ziehau 			memset(&ctrl, 0, sizeof(ctrl));
94*a45b8979SSepherosa Ziehau 			cm = CMSG_FIRSTHDR(&msg);
95*a45b8979SSepherosa Ziehau 			cm->cmsg_len = CMSG_LEN(sizeof(u_char));
96*a45b8979SSepherosa Ziehau 			cm->cmsg_level = IPPROTO_IP;
97*a45b8979SSepherosa Ziehau 			cm->cmsg_type = IP_TOS;
98*a45b8979SSepherosa Ziehau 			*((u_char *)CMSG_DATA(cm)) = tos;
99*a45b8979SSepherosa Ziehau 
100*a45b8979SSepherosa Ziehau 			fprintf(stderr, "sendmsg tos %d\n", tos);
101*a45b8979SSepherosa Ziehau 			if (sendmsg(s, &msg, MSG_SYNC) < 0)
102*a45b8979SSepherosa Ziehau 				err(2, "sendmsg failed");
103*a45b8979SSepherosa Ziehau 		}
104*a45b8979SSepherosa Ziehau 	} else {
105544d23f4SSepherosa Ziehau 		const int on = 1;
106544d23f4SSepherosa Ziehau 
107544d23f4SSepherosa Ziehau 		if (bind(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
108544d23f4SSepherosa Ziehau 			err(2, "bind failed");
109544d23f4SSepherosa Ziehau 
110544d23f4SSepherosa Ziehau 		if (setsockopt(s, IPPROTO_IP, IP_RECVTOS, &on, sizeof(on)) < 0)
111544d23f4SSepherosa Ziehau 			err(2, "setsockopt IP_RECVTOS failed");
112544d23f4SSepherosa Ziehau 
113544d23f4SSepherosa Ziehau 		iov.iov_base = buf;
114544d23f4SSepherosa Ziehau 		iov.iov_len = sizeof(buf);
115544d23f4SSepherosa Ziehau 
116544d23f4SSepherosa Ziehau 		memset(&msg, 0, sizeof(msg));
117544d23f4SSepherosa Ziehau 		msg.msg_iov = &iov;
118544d23f4SSepherosa Ziehau 		msg.msg_iovlen = 1;
119544d23f4SSepherosa Ziehau 		msg.msg_control = ctrl.data;
120544d23f4SSepherosa Ziehau 		msg.msg_controllen = sizeof(ctrl.data);
121544d23f4SSepherosa Ziehau 
122544d23f4SSepherosa Ziehau 		n = recvmsg(s, &msg, MSG_WAITALL);
123544d23f4SSepherosa Ziehau 		if (n < 0)
124544d23f4SSepherosa Ziehau 			err(1, "recvmsg failed");
125544d23f4SSepherosa Ziehau 		else if (n != sizeof(buf))
126544d23f4SSepherosa Ziehau 			errx(1, "recvmsg received %d", n);
127544d23f4SSepherosa Ziehau 
128544d23f4SSepherosa Ziehau 		cm = CMSG_FIRSTHDR(&msg);
129544d23f4SSepherosa Ziehau 		if (cm == NULL)
130544d23f4SSepherosa Ziehau 			errx(1, "no cmsg");
131544d23f4SSepherosa Ziehau 		if (cm->cmsg_len != CMSG_LEN(sizeof(u_char)))
132544d23f4SSepherosa Ziehau 			errx(1, "cmsg len mismatch");
133544d23f4SSepherosa Ziehau 		if (cm->cmsg_level != IPPROTO_IP)
134544d23f4SSepherosa Ziehau 			errx(1, "cmsg level mismatch");
135544d23f4SSepherosa Ziehau 		if (cm->cmsg_type != IP_RECVTOS)
136544d23f4SSepherosa Ziehau 			errx(1, "cmsg type mismatch");
137544d23f4SSepherosa Ziehau 
138544d23f4SSepherosa Ziehau 		tos = *((u_char *)CMSG_DATA(cm));
139544d23f4SSepherosa Ziehau 
140544d23f4SSepherosa Ziehau 		fprintf(stderr, "TOS: %d\n", tos);
141544d23f4SSepherosa Ziehau 	}
142544d23f4SSepherosa Ziehau 
143544d23f4SSepherosa Ziehau 	exit(0);
144544d23f4SSepherosa Ziehau }
145