xref: /netbsd-src/tests/net/if_vlan/siocXmulti.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
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));
60 
61 	sin = (struct sockaddr_in *)&ifr.ifr_addr;
62 	sin->sin_family = AF_INET;
63 	sin->sin_len = sizeof(*sin);
64 	rv = inet_pton(AF_INET, argv[ARG_ADDR], &sin->sin_addr);
65 
66 	if (rv != 1) {
67 		sin6 = (struct sockaddr_in6 *)&ifr.ifr_addr;
68 		sin6->sin6_family = AF_INET6;
69 		sin6->sin6_len = sizeof(*sin6);
70 		rv = inet_pton(AF_INET6, argv[ARG_ADDR], &sin6->sin6_addr);
71 
72 		if (rv != 1)
73 			errx(1, "inet_pton(%s)", argv[ARG_ADDR]);
74 	}
75 
76 	fd = socket(AF_INET, SOCK_DGRAM, 0);
77 	if (fd < 0)
78 		err(1, "socket");
79 
80 	if (ioctl(fd, req, (caddr_t)&ifr) < 0) {
81 		err(1, "ioctl(%s)",
82 		    (req == SIOCADDMULTI) ? "SIOCADDMULTI" : "SIOCDELMULTI");
83 	}
84 
85 	close(fd);
86 
87 	return 0;
88 }
89