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