siocXmulti.c revision 1.1.4.1 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