xref: /f-stack/tools/ifconfig/ifgroup.c (revision d4a07e70)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2006 Max Laier. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #ifndef lint
29 static const char rcsid[] =
30   "$FreeBSD$";
31 #endif /* not lint */
32 
33 #include <sys/param.h>
34 #include <sys/ioctl.h>
35 #include <sys/socket.h>
36 #include <net/if.h>
37 
38 #include <ctype.h>
39 #include <err.h>
40 #include <errno.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 
46 #include "ifconfig.h"
47 
48 #ifdef FSTACK
49 #include "ff_ipc.h"
50 #endif
51 
52 /* ARGSUSED */
53 static void
setifgroup(const char * group_name,int d,int s,const struct afswtch * rafp)54 setifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
55 {
56 	struct ifgroupreq ifgr;
57 
58 	memset(&ifgr, 0, sizeof(ifgr));
59 	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
60 
61 	if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
62 		errx(1, "setifgroup: group names may not end in a digit");
63 
64 	if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
65 		errx(1, "setifgroup: group name too long");
66 	if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST)
67 		err(1," SIOCAIFGROUP");
68 }
69 
70 /* ARGSUSED */
71 static void
unsetifgroup(const char * group_name,int d,int s,const struct afswtch * rafp)72 unsetifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
73 {
74 	struct ifgroupreq ifgr;
75 
76 	memset(&ifgr, 0, sizeof(ifgr));
77 	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
78 
79 	if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
80 		errx(1, "unsetifgroup: group names may not end in a digit");
81 
82 	if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
83 		errx(1, "unsetifgroup: group name too long");
84 	if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT)
85 		err(1, "SIOCDIFGROUP");
86 }
87 
88 static void
getifgroups(int s)89 getifgroups(int s)
90 {
91 	int			 len, cnt;
92 	struct ifgroupreq	 ifgr;
93 	struct ifg_req		*ifg;
94 
95 	memset(&ifgr, 0, sizeof(ifgr));
96 	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
97 
98 	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
99 		if (errno == EINVAL || errno == ENOTTY)
100 			return;
101 		else
102 			err(1, "SIOCGIFGROUP");
103 	}
104 
105 	len = ifgr.ifgr_len;
106 	ifgr.ifgr_groups =
107 	    (struct ifg_req *)calloc(len / sizeof(struct ifg_req),
108 	    sizeof(struct ifg_req));
109 	if (ifgr.ifgr_groups == NULL)
110 		err(1, "getifgroups");
111 #ifndef FSTACK
112 	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
113 #else
114 	size_t offset = (char *)&(ifgr.ifgr_groups) - (char *)&(ifgr);
115 	size_t clen = len;
116 	if (ioctl_va(s, SIOCGIFGROUP, (caddr_t)&ifgr, 3, offset, ifgr.ifgr_groups, clen) == -1)
117 #endif
118 		err(1, "SIOCGIFGROUP");
119 
120 	cnt = 0;
121 	ifg = ifgr.ifgr_groups;
122 	for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
123 		len -= sizeof(struct ifg_req);
124 		if (strcmp(ifg->ifgrq_group, "all")) {
125 			if (cnt == 0)
126 				printf("\tgroups:");
127 			cnt++;
128 			printf(" %s", ifg->ifgrq_group);
129 		}
130 	}
131 	if (cnt)
132 		printf("\n");
133 
134 	free(ifgr.ifgr_groups);
135 }
136 
137 static void
printgroup(const char * groupname)138 printgroup(const char *groupname)
139 {
140 	struct ifgroupreq	 ifgr;
141 	struct ifg_req		*ifg;
142 	int			 len, cnt = 0;
143 	int			 s;
144 
145 	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
146 	if (s == -1)
147 		err(1, "socket(AF_LOCAL,SOCK_DGRAM)");
148 	bzero(&ifgr, sizeof(ifgr));
149 	strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name));
150 	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
151 		if (errno == EINVAL || errno == ENOTTY ||
152 		    errno == ENOENT)
153 #ifdef FSTACK
154 		{
155 			ff_ipc_exit();
156 			exit(exit_code);
157 		}
158 #else
159 			exit(exit_code);
160 #endif
161 		else
162 			err(1, "SIOCGIFGMEMB");
163 	}
164 
165 	len = ifgr.ifgr_len;
166 	if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
167 		err(1, "printgroup");
168 
169 #ifndef FSTACK
170 	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
171 #else
172 	size_t offset = (char *)&(ifgr.ifgr_groups) - (char *)&(ifgr);
173 	size_t clen = len;
174 	if (ioctl_va(s, SIOCGIFGMEMB, (caddr_t)&ifgr, 3, offset, ifgr.ifgr_groups, clen) == -1)
175 #endif
176 		err(1, "SIOCGIFGMEMB");
177 
178 	for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
179 	    ifg++) {
180 		len -= sizeof(struct ifg_req);
181 		printf("%s\n", ifg->ifgrq_member);
182 		cnt++;
183 	}
184 	free(ifgr.ifgr_groups);
185 
186 #ifdef FSTACK
187 	ff_ipc_exit();
188 #endif
189 	exit(exit_code);
190 }
191 
192 static struct cmd group_cmds[] = {
193 	DEF_CMD_ARG("group",	setifgroup),
194 	DEF_CMD_ARG("-group",	unsetifgroup),
195 };
196 static struct afswtch af_group = {
197 	.af_name	= "af_group",
198 	.af_af		= AF_UNSPEC,
199 	.af_other_status = getifgroups,
200 };
201 static struct option group_gopt = { "g:", "[-g groupname]", printgroup };
202 
203 static __constructor void
group_ctor(void)204 group_ctor(void)
205 {
206 	int i;
207 
208 	for (i = 0; i < nitems(group_cmds);  i++)
209 		cmd_register(&group_cmds[i]);
210 	af_register(&af_group);
211 	opt_register(&group_gopt);
212 }
213