xref: /dragonfly/test/udp/mcastconn/mcastconn.c (revision 9348a738)
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 
4 #include <arpa/inet.h>
5 #include <netinet/in.h>
6 
7 #include <err.h>
8 #include <stdint.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 
14 static void
15 usage(const char *cmd)
16 {
17 	fprintf(stderr, "%s -m addr -p port -i addr "
18 	    "-r remote_ip4 -P remote_port\n", cmd);
19 	exit(1);
20 }
21 
22 static int
23 create_sock(const struct sockaddr_in *in, const struct in_addr *iface)
24 {
25 	struct ip_mreq mreq;
26 	int s, on;
27 
28 	s = socket(AF_INET, SOCK_DGRAM, 0);
29 	if (s < 0)
30 		err(2, "socket failed");
31 
32 	on = 1;
33 	if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
34 		err(2, "setsockopt SO_REUSEPORT failed");
35 
36 	if (bind(s, (const struct sockaddr *)in, sizeof(*in)) < 0)
37 		err(2, "bind failed");
38 
39 	memset(&mreq, 0, sizeof(mreq));
40 	mreq.imr_multiaddr = in->sin_addr;
41 	mreq.imr_interface = *iface;
42 	if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
43 	    &mreq, sizeof(mreq)) < 0)
44 		err(2, "setsockopt IP_ADD_MEMBERSHIP failed");
45 
46 	return s;
47 }
48 
49 int
50 main(int argc, char *argv[])
51 {
52 	struct sockaddr_in in, remote_in;
53 	struct in_addr iface;
54 	int s1, s2, opt, n;
55 	uint8_t buf[18];
56 
57 	memset(&in, 0, sizeof(in));
58 	in.sin_family = AF_INET;
59 
60 	memset(&remote_in, 0, sizeof(remote_in));
61 	remote_in.sin_family = AF_INET;
62 
63 	memset(&iface, 0, sizeof(iface));
64 
65 	while ((opt = getopt(argc, argv, "P:i:m:p:r:")) != -1) {
66 		switch (opt) {
67 		case 'P':
68 			remote_in.sin_port = strtol(optarg, NULL, 10);
69 			remote_in.sin_port = htons(remote_in.sin_port);
70 			break;
71 
72 		case 'i':
73 			if (inet_pton(AF_INET, optarg, &iface) <= 0)
74 				usage(argv[0]);
75 			break;
76 
77 		case 'm':
78 			if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0)
79 				usage(argv[0]);
80 			break;
81 
82 		case 'p':
83 			in.sin_port = strtol(optarg, NULL, 10);
84 			in.sin_port = htons(in.sin_port);
85 			break;
86 
87 		case 'r':
88 			if (inet_pton(AF_INET, optarg,
89 			    &remote_in.sin_addr) <= 0)
90 				usage(argv[0]);
91 			break;
92 
93 		default:
94 			usage(argv[0]);
95 		}
96 	}
97 
98 	if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0 ||
99 	    iface.s_addr == INADDR_ANY ||
100 	    remote_in.sin_addr.s_addr == INADDR_ANY ||
101 	    remote_in.sin_port == 0)
102 		usage(argv[0]);
103 
104 	s1 = create_sock(&in, &iface);
105 	s2 = create_sock(&in, &iface);
106 
107 	if (connect(s2, (const struct sockaddr *)&remote_in,
108 	    sizeof(remote_in)) < 0)
109 		err(2, "connect failed");
110 
111 	n = read(s1, buf, sizeof(buf));
112 	if (n < 0)
113 		err(2, "read 1 failed");
114 	fprintf(stderr, "read 1 got %d\n", n);
115 
116 	n = read(s2, buf, sizeof(buf));
117 	if (n < 0)
118 		err(2, "read 2 failed");
119 	fprintf(stderr, "read 2 got %d\n", n);
120 
121 	exit(0);
122 }
123