xref: /freebsd/sbin/ifconfig/ifgroup.c (revision eba230afba4932f02a1ca44efc797cf7499a5cb0)
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