10dad3f0eSMax Laier /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
40dad3f0eSMax Laier * Copyright (c) 2006 Max Laier. All rights reserved.
50dad3f0eSMax Laier *
60dad3f0eSMax Laier * Redistribution and use in source and binary forms, with or without
70dad3f0eSMax Laier * modification, are permitted provided that the following conditions
80dad3f0eSMax Laier * are met:
90dad3f0eSMax Laier * 1. Redistributions of source code must retain the above copyright
100dad3f0eSMax Laier * notice, this list of conditions and the following disclaimer.
110dad3f0eSMax Laier * 2. Redistributions in binary form must reproduce the above copyright
120dad3f0eSMax Laier * notice, this list of conditions and the following disclaimer in the
130dad3f0eSMax Laier * documentation and/or other materials provided with the distribution.
140dad3f0eSMax Laier *
150dad3f0eSMax Laier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
160dad3f0eSMax Laier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
170dad3f0eSMax Laier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
180dad3f0eSMax Laier * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
190dad3f0eSMax Laier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
200dad3f0eSMax Laier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
210dad3f0eSMax Laier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
220dad3f0eSMax Laier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
230dad3f0eSMax Laier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
240dad3f0eSMax Laier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
250dad3f0eSMax Laier * SUCH DAMAGE.
260dad3f0eSMax Laier */
270dad3f0eSMax Laier
28abd71050SEnji Cooper #include <sys/param.h>
290dad3f0eSMax Laier #include <sys/ioctl.h>
300dad3f0eSMax Laier #include <sys/socket.h>
310dad3f0eSMax Laier #include <net/if.h>
320dad3f0eSMax Laier
330dad3f0eSMax Laier #include <ctype.h>
340dad3f0eSMax Laier #include <err.h>
350dad3f0eSMax Laier #include <errno.h>
360dad3f0eSMax Laier #include <stdio.h>
370dad3f0eSMax Laier #include <stdlib.h>
380dad3f0eSMax Laier #include <string.h>
390dad3f0eSMax Laier #include <unistd.h>
400dad3f0eSMax Laier
4164bacab1SRyan Moeller #include <libifconfig.h>
4264bacab1SRyan Moeller
430dad3f0eSMax Laier #include "ifconfig.h"
440dad3f0eSMax Laier
450dad3f0eSMax Laier static void
setifgroup(if_ctx * ctx,const char * group_name,int dummy __unused)466e3a9d7fSAlexander V. Chernikov setifgroup(if_ctx *ctx, const char *group_name, int dummy __unused)
470dad3f0eSMax Laier {
48*85e0016aSAlexander V. Chernikov struct ifgroupreq ifgr = {};
490dad3f0eSMax Laier
50*85e0016aSAlexander V. Chernikov strlcpy(ifgr.ifgr_name, ctx->ifname, IFNAMSIZ);
510dad3f0eSMax Laier
520dad3f0eSMax Laier if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
530dad3f0eSMax Laier errx(1, "setifgroup: group names may not end in a digit");
540dad3f0eSMax Laier
550dad3f0eSMax Laier if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
560dad3f0eSMax Laier errx(1, "setifgroup: group name too long");
576e3a9d7fSAlexander V. Chernikov if (ioctl_ctx(ctx, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST)
580dad3f0eSMax Laier err(1," SIOCAIFGROUP");
590dad3f0eSMax Laier }
600dad3f0eSMax Laier
610dad3f0eSMax Laier static void
unsetifgroup(if_ctx * ctx,const char * group_name,int dummy __unused)626e3a9d7fSAlexander V. Chernikov unsetifgroup(if_ctx *ctx, const char *group_name, int dummy __unused)
630dad3f0eSMax Laier {
64*85e0016aSAlexander V. Chernikov struct ifgroupreq ifgr = {};
650dad3f0eSMax Laier
66*85e0016aSAlexander V. Chernikov strlcpy(ifgr.ifgr_name, ctx->ifname, IFNAMSIZ);
670dad3f0eSMax Laier
680dad3f0eSMax Laier if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
690dad3f0eSMax Laier errx(1, "unsetifgroup: group names may not end in a digit");
700dad3f0eSMax Laier
710dad3f0eSMax Laier if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
720dad3f0eSMax Laier errx(1, "unsetifgroup: group name too long");
736e3a9d7fSAlexander V. Chernikov if (ioctl_ctx(ctx, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT)
740dad3f0eSMax Laier err(1, "SIOCDIFGROUP");
750dad3f0eSMax Laier }
760dad3f0eSMax Laier
770dad3f0eSMax Laier static void
getifgroups(if_ctx * ctx)78*85e0016aSAlexander V. Chernikov getifgroups(if_ctx *ctx)
790dad3f0eSMax Laier {
800dad3f0eSMax Laier struct ifgroupreq ifgr;
8164bacab1SRyan Moeller size_t cnt;
820dad3f0eSMax Laier
83*85e0016aSAlexander V. Chernikov if (ifconfig_get_groups(lifh, ctx->ifname, &ifgr) == -1)
848b222425SRyan Moeller return;
850dad3f0eSMax Laier
860dad3f0eSMax Laier cnt = 0;
8764bacab1SRyan Moeller for (size_t i = 0; i < ifgr.ifgr_len / sizeof(struct ifg_req); ++i) {
8864bacab1SRyan Moeller struct ifg_req *ifg = &ifgr.ifgr_groups[i];
8964bacab1SRyan Moeller
900dad3f0eSMax Laier if (strcmp(ifg->ifgrq_group, "all")) {
910dad3f0eSMax Laier if (cnt == 0)
920dad3f0eSMax Laier printf("\tgroups:");
930dad3f0eSMax Laier cnt++;
940dad3f0eSMax Laier printf(" %s", ifg->ifgrq_group);
950dad3f0eSMax Laier }
960dad3f0eSMax Laier }
970dad3f0eSMax Laier if (cnt)
980dad3f0eSMax Laier printf("\n");
9946ad509bSMark Felder
10046ad509bSMark Felder free(ifgr.ifgr_groups);
1010dad3f0eSMax Laier }
1020dad3f0eSMax Laier
1030dad3f0eSMax Laier static void
printgroup(const char * groupname)104aa388b9dSSam Leffler printgroup(const char *groupname)
1050dad3f0eSMax Laier {
1060dad3f0eSMax Laier struct ifgroupreq ifgr;
1070dad3f0eSMax Laier struct ifg_req *ifg;
10844cd85d4SAlexander V. Chernikov unsigned int len;
1090dad3f0eSMax Laier int s;
1100dad3f0eSMax Laier
111a9948a71SJamie Gritton s = socket(AF_LOCAL, SOCK_DGRAM, 0);
1120dad3f0eSMax Laier if (s == -1)
113a9948a71SJamie Gritton err(1, "socket(AF_LOCAL,SOCK_DGRAM)");
1140dad3f0eSMax Laier bzero(&ifgr, sizeof(ifgr));
1150dad3f0eSMax Laier strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name));
1160dad3f0eSMax Laier if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
1170dad3f0eSMax Laier if (errno == EINVAL || errno == ENOTTY ||
1180dad3f0eSMax Laier errno == ENOENT)
11947528c67SAndrew Gallatin exit(exit_code);
1200dad3f0eSMax Laier else
1210dad3f0eSMax Laier err(1, "SIOCGIFGMEMB");
1220dad3f0eSMax Laier }
1230dad3f0eSMax Laier
1240dad3f0eSMax Laier len = ifgr.ifgr_len;
1250dad3f0eSMax Laier if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
1260dad3f0eSMax Laier err(1, "printgroup");
1270dad3f0eSMax Laier if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
1280dad3f0eSMax Laier err(1, "SIOCGIFGMEMB");
1290dad3f0eSMax Laier
1300dad3f0eSMax Laier for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
1310dad3f0eSMax Laier ifg++) {
1320dad3f0eSMax Laier len -= sizeof(struct ifg_req);
1330dad3f0eSMax Laier printf("%s\n", ifg->ifgrq_member);
1340dad3f0eSMax Laier }
1350dad3f0eSMax Laier free(ifgr.ifgr_groups);
1360dad3f0eSMax Laier
13747528c67SAndrew Gallatin exit(exit_code);
1380dad3f0eSMax Laier }
1390dad3f0eSMax Laier
1400dad3f0eSMax Laier static struct cmd group_cmds[] = {
1410dad3f0eSMax Laier DEF_CMD_ARG("group", setifgroup),
1420dad3f0eSMax Laier DEF_CMD_ARG("-group", unsetifgroup),
1430dad3f0eSMax Laier };
14444cd85d4SAlexander V. Chernikov
1450dad3f0eSMax Laier static struct afswtch af_group = {
1460dad3f0eSMax Laier .af_name = "af_group",
1470dad3f0eSMax Laier .af_af = AF_UNSPEC,
1480dad3f0eSMax Laier .af_other_status = getifgroups,
1490dad3f0eSMax Laier };
15044cd85d4SAlexander V. Chernikov
15144cd85d4SAlexander V. Chernikov static struct option group_gopt = {
15244cd85d4SAlexander V. Chernikov .opt = "g:",
15344cd85d4SAlexander V. Chernikov .opt_usage = "[-g groupname]",
15444cd85d4SAlexander V. Chernikov .cb = printgroup,
15544cd85d4SAlexander V. Chernikov };
1560dad3f0eSMax Laier
1570dad3f0eSMax Laier static __constructor void
group_ctor(void)1580dad3f0eSMax Laier group_ctor(void)
1590dad3f0eSMax Laier {
16044cd85d4SAlexander V. Chernikov for (size_t i = 0; i < nitems(group_cmds); i++)
1610dad3f0eSMax Laier cmd_register(&group_cmds[i]);
1620dad3f0eSMax Laier af_register(&af_group);
1630dad3f0eSMax Laier opt_register(&group_gopt);
1640dad3f0eSMax Laier }
165