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