1*78a70485Syamaguchi /* $NetBSD: siocXmulti.c,v 1.3 2021/08/19 03:36:42 yamaguchi Exp $ */
2*78a70485Syamaguchi
3*78a70485Syamaguchi /*
4*78a70485Syamaguchi * Copyright (c) 2021 Internet Initiative Japan Inc.
5*78a70485Syamaguchi * All rights reserved.
6*78a70485Syamaguchi *
7*78a70485Syamaguchi * Redistribution and use in source and binary forms, with or without
8*78a70485Syamaguchi * modification, are permitted provided that the following conditions
9*78a70485Syamaguchi * are met:
10*78a70485Syamaguchi * 1. Redistributions of source code must retain the above copyright
11*78a70485Syamaguchi * notice, this list of conditions and the following disclaimer.
12*78a70485Syamaguchi * 2. Redistributions in binary form must reproduce the above copyright
13*78a70485Syamaguchi * notice, this list of conditions and the following disclaimer in the
14*78a70485Syamaguchi * documentation and/or other materials provided with the distribution.
15*78a70485Syamaguchi *
16*78a70485Syamaguchi * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17*78a70485Syamaguchi * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18*78a70485Syamaguchi * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19*78a70485Syamaguchi * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20*78a70485Syamaguchi * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*78a70485Syamaguchi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*78a70485Syamaguchi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*78a70485Syamaguchi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*78a70485Syamaguchi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*78a70485Syamaguchi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*78a70485Syamaguchi * POSSIBILITY OF SUCH DAMAGE.
27*78a70485Syamaguchi */
28*78a70485Syamaguchi
29*78a70485Syamaguchi #include <sys/cdefs.h>
30*78a70485Syamaguchi __RCSID("$NetBSD: siocXmulti.c,v 1.3 2021/08/19 03:36:42 yamaguchi Exp $");
319de5f4c0Syamaguchi
329de5f4c0Syamaguchi #include <sys/socket.h>
339de5f4c0Syamaguchi #include <sys/ioctl.h>
349de5f4c0Syamaguchi
359de5f4c0Syamaguchi #include <net/if.h>
369de5f4c0Syamaguchi #include <netinet/in.h>
379de5f4c0Syamaguchi #include <arpa/inet.h>
389de5f4c0Syamaguchi
399de5f4c0Syamaguchi #include <stdio.h>
409de5f4c0Syamaguchi #include <stdlib.h>
419de5f4c0Syamaguchi #include <string.h>
429de5f4c0Syamaguchi #include <strings.h>
439de5f4c0Syamaguchi #include <unistd.h>
449de5f4c0Syamaguchi #include <err.h>
459de5f4c0Syamaguchi
469de5f4c0Syamaguchi enum{
479de5f4c0Syamaguchi ARG_PROG = 0,
489de5f4c0Syamaguchi ARG_OP,
499de5f4c0Syamaguchi ARG_IFNAME,
509de5f4c0Syamaguchi ARG_ADDR,
519de5f4c0Syamaguchi ARG_NUM
529de5f4c0Syamaguchi };
539de5f4c0Syamaguchi
549de5f4c0Syamaguchi static void
usage(void)559de5f4c0Syamaguchi usage(void)
569de5f4c0Syamaguchi {
579de5f4c0Syamaguchi
589de5f4c0Syamaguchi printf("%s <add|del> <ifname> <IPv4 addr>\n",
599de5f4c0Syamaguchi getprogname());
609de5f4c0Syamaguchi exit(1);
619de5f4c0Syamaguchi }
629de5f4c0Syamaguchi
639de5f4c0Syamaguchi int
main(int argc,char * argv[])649de5f4c0Syamaguchi main(int argc, char *argv[])
659de5f4c0Syamaguchi {
669de5f4c0Syamaguchi int fd, rv;
679de5f4c0Syamaguchi unsigned long req;
689de5f4c0Syamaguchi struct ifreq ifr;
699de5f4c0Syamaguchi unsigned int ifidx;
709de5f4c0Syamaguchi struct sockaddr_in *sin;
719de5f4c0Syamaguchi struct sockaddr_in6 *sin6;
729de5f4c0Syamaguchi
739de5f4c0Syamaguchi bzero(&ifr, sizeof(ifr));
749de5f4c0Syamaguchi
759de5f4c0Syamaguchi if (argc != ARG_NUM)
769de5f4c0Syamaguchi usage();
779de5f4c0Syamaguchi
789de5f4c0Syamaguchi if (strcmp(argv[ARG_OP], "add") == 0)
799de5f4c0Syamaguchi req = SIOCADDMULTI;
809de5f4c0Syamaguchi else if (strcmp(argv[ARG_OP], "del") == 0)
819de5f4c0Syamaguchi req = SIOCDELMULTI;
829de5f4c0Syamaguchi else
839de5f4c0Syamaguchi usage();
849de5f4c0Syamaguchi
859de5f4c0Syamaguchi ifidx = if_nametoindex(argv[ARG_IFNAME]);
869de5f4c0Syamaguchi if (ifidx == 0)
879de5f4c0Syamaguchi err(1, "if_nametoindex(%s)", argv[ARG_IFNAME]);
889de5f4c0Syamaguchi
894e545ef7Smrg strncpy(ifr.ifr_name, argv[ARG_IFNAME], sizeof(ifr.ifr_name) - 1);
904e545ef7Smrg ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
919de5f4c0Syamaguchi
929de5f4c0Syamaguchi sin = (struct sockaddr_in *)&ifr.ifr_addr;
939de5f4c0Syamaguchi sin->sin_family = AF_INET;
949de5f4c0Syamaguchi sin->sin_len = sizeof(*sin);
959de5f4c0Syamaguchi rv = inet_pton(AF_INET, argv[ARG_ADDR], &sin->sin_addr);
969de5f4c0Syamaguchi
979de5f4c0Syamaguchi if (rv != 1) {
989de5f4c0Syamaguchi sin6 = (struct sockaddr_in6 *)&ifr.ifr_addr;
999de5f4c0Syamaguchi sin6->sin6_family = AF_INET6;
1009de5f4c0Syamaguchi sin6->sin6_len = sizeof(*sin6);
1019de5f4c0Syamaguchi rv = inet_pton(AF_INET6, argv[ARG_ADDR], &sin6->sin6_addr);
1029de5f4c0Syamaguchi
1039de5f4c0Syamaguchi if (rv != 1)
1049de5f4c0Syamaguchi errx(1, "inet_pton(%s)", argv[ARG_ADDR]);
1059de5f4c0Syamaguchi }
1069de5f4c0Syamaguchi
1079de5f4c0Syamaguchi fd = socket(AF_INET, SOCK_DGRAM, 0);
1089de5f4c0Syamaguchi if (fd < 0)
1099de5f4c0Syamaguchi err(1, "socket");
1109de5f4c0Syamaguchi
1119de5f4c0Syamaguchi if (ioctl(fd, req, (caddr_t)&ifr) < 0) {
1129de5f4c0Syamaguchi err(1, "ioctl(%s)",
1139de5f4c0Syamaguchi (req == SIOCADDMULTI) ? "SIOCADDMULTI" : "SIOCDELMULTI");
1149de5f4c0Syamaguchi }
1159de5f4c0Syamaguchi
1169de5f4c0Syamaguchi close(fd);
1179de5f4c0Syamaguchi
1189de5f4c0Syamaguchi return 0;
1199de5f4c0Syamaguchi }
120