1 /* $NetBSD: siocXmulti.c,v 1.3 2021/08/19 03:36:42 yamaguchi Exp $ */ 2 3 /* 4 * Copyright (c) 2021 Internet Initiative Japan Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __RCSID("$NetBSD: siocXmulti.c,v 1.3 2021/08/19 03:36:42 yamaguchi Exp $"); 31 32 #include <sys/socket.h> 33 #include <sys/ioctl.h> 34 35 #include <net/if.h> 36 #include <netinet/in.h> 37 #include <arpa/inet.h> 38 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <strings.h> 43 #include <unistd.h> 44 #include <err.h> 45 46 enum{ 47 ARG_PROG = 0, 48 ARG_OP, 49 ARG_IFNAME, 50 ARG_ADDR, 51 ARG_NUM 52 }; 53 54 static void 55 usage(void) 56 { 57 58 printf("%s <add|del> <ifname> <IPv4 addr>\n", 59 getprogname()); 60 exit(1); 61 } 62 63 int 64 main(int argc, char *argv[]) 65 { 66 int fd, rv; 67 unsigned long req; 68 struct ifreq ifr; 69 unsigned int ifidx; 70 struct sockaddr_in *sin; 71 struct sockaddr_in6 *sin6; 72 73 bzero(&ifr, sizeof(ifr)); 74 75 if (argc != ARG_NUM) 76 usage(); 77 78 if (strcmp(argv[ARG_OP], "add") == 0) 79 req = SIOCADDMULTI; 80 else if (strcmp(argv[ARG_OP], "del") == 0) 81 req = SIOCDELMULTI; 82 else 83 usage(); 84 85 ifidx = if_nametoindex(argv[ARG_IFNAME]); 86 if (ifidx == 0) 87 err(1, "if_nametoindex(%s)", argv[ARG_IFNAME]); 88 89 strncpy(ifr.ifr_name, argv[ARG_IFNAME], sizeof(ifr.ifr_name) - 1); 90 ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; 91 92 sin = (struct sockaddr_in *)&ifr.ifr_addr; 93 sin->sin_family = AF_INET; 94 sin->sin_len = sizeof(*sin); 95 rv = inet_pton(AF_INET, argv[ARG_ADDR], &sin->sin_addr); 96 97 if (rv != 1) { 98 sin6 = (struct sockaddr_in6 *)&ifr.ifr_addr; 99 sin6->sin6_family = AF_INET6; 100 sin6->sin6_len = sizeof(*sin6); 101 rv = inet_pton(AF_INET6, argv[ARG_ADDR], &sin6->sin6_addr); 102 103 if (rv != 1) 104 errx(1, "inet_pton(%s)", argv[ARG_ADDR]); 105 } 106 107 fd = socket(AF_INET, SOCK_DGRAM, 0); 108 if (fd < 0) 109 err(1, "socket"); 110 111 if (ioctl(fd, req, (caddr_t)&ifr) < 0) { 112 err(1, "ioctl(%s)", 113 (req == SIOCADDMULTI) ? "SIOCADDMULTI" : "SIOCDELMULTI"); 114 } 115 116 close(fd); 117 118 return 0; 119 } 120