xref: /netbsd-src/tests/net/if_vlan/siocXmulti.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 
2 #include <sys/socket.h>
3 #include <sys/ioctl.h>
4 
5 #include <net/if.h>
6 #include <netinet/in.h>
7 #include <arpa/inet.h>
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <unistd.h>
14 #include <err.h>
15 
16 enum{
17 	ARG_PROG = 0,
18 	ARG_OP,
19 	ARG_IFNAME,
20 	ARG_ADDR,
21 	ARG_NUM
22 };
23 
24 static void
25 usage(void)
26 {
27 
28 	printf("%s <add|del> <ifname> <IPv4 addr>\n",
29 	    getprogname());
30 	exit(1);
31 }
32 
33 int
34 main(int argc, char *argv[])
35 {
36 	int			 fd, rv;
37 	unsigned long		 req;
38 	struct ifreq		 ifr;
39 	unsigned int		 ifidx;
40 	struct sockaddr_in	*sin;
41 	struct sockaddr_in6	*sin6;
42 
43 	bzero(&ifr, sizeof(ifr));
44 
45 	if (argc != ARG_NUM)
46 		usage();
47 
48 	if (strcmp(argv[ARG_OP], "add") == 0)
49 		req = SIOCADDMULTI;
50 	else if (strcmp(argv[ARG_OP], "del") == 0)
51 		req = SIOCDELMULTI;
52 	else
53 		usage();
54 
55 	ifidx = if_nametoindex(argv[ARG_IFNAME]);
56 	if (ifidx == 0)
57 		err(1, "if_nametoindex(%s)", argv[ARG_IFNAME]);
58 
59 	strncpy(ifr.ifr_name, argv[ARG_IFNAME], sizeof(ifr.ifr_name) - 1);
60 	ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
61 
62 	sin = (struct sockaddr_in *)&ifr.ifr_addr;
63 	sin->sin_family = AF_INET;
64 	sin->sin_len = sizeof(*sin);
65 	rv = inet_pton(AF_INET, argv[ARG_ADDR], &sin->sin_addr);
66 
67 	if (rv != 1) {
68 		sin6 = (struct sockaddr_in6 *)&ifr.ifr_addr;
69 		sin6->sin6_family = AF_INET6;
70 		sin6->sin6_len = sizeof(*sin6);
71 		rv = inet_pton(AF_INET6, argv[ARG_ADDR], &sin6->sin6_addr);
72 
73 		if (rv != 1)
74 			errx(1, "inet_pton(%s)", argv[ARG_ADDR]);
75 	}
76 
77 	fd = socket(AF_INET, SOCK_DGRAM, 0);
78 	if (fd < 0)
79 		err(1, "socket");
80 
81 	if (ioctl(fd, req, (caddr_t)&ifr) < 0) {
82 		err(1, "ioctl(%s)",
83 		    (req == SIOCADDMULTI) ? "SIOCADDMULTI" : "SIOCDELMULTI");
84 	}
85 
86 	close(fd);
87 
88 	return 0;
89 }
90