1159781Smlaier/*-
2159781Smlaier * Copyright (c) 2006 Max Laier. All rights reserved.
3159781Smlaier *
4159781Smlaier * Redistribution and use in source and binary forms, with or without
5159781Smlaier * modification, are permitted provided that the following conditions
6159781Smlaier * are met:
7159781Smlaier * 1. Redistributions of source code must retain the above copyright
8159781Smlaier *    notice, this list of conditions and the following disclaimer.
9159781Smlaier * 2. Redistributions in binary form must reproduce the above copyright
10159781Smlaier *    notice, this list of conditions and the following disclaimer in the
11159781Smlaier *    documentation and/or other materials provided with the distribution.
12159781Smlaier *
13159781Smlaier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14159781Smlaier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15159781Smlaier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16159781Smlaier * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17159781Smlaier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18159781Smlaier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19159781Smlaier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20159781Smlaier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21159781Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22159781Smlaier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23159781Smlaier * SUCH DAMAGE.
24159781Smlaier */
25159781Smlaier
26159781Smlaier#ifndef lint
27159781Smlaierstatic const char rcsid[] =
28159781Smlaier  "$FreeBSD$";
29159781Smlaier#endif /* not lint */
30159781Smlaier
31159781Smlaier#include <sys/types.h>
32159781Smlaier#include <sys/ioctl.h>
33159781Smlaier#include <sys/socket.h>
34159781Smlaier#include <net/if.h>
35159781Smlaier
36159781Smlaier#include <ctype.h>
37159781Smlaier#include <err.h>
38159781Smlaier#include <errno.h>
39159781Smlaier#include <stdio.h>
40159781Smlaier#include <stdlib.h>
41159781Smlaier#include <string.h>
42159781Smlaier#include <unistd.h>
43159781Smlaier
44159781Smlaier#include "ifconfig.h"
45159781Smlaier
46159781Smlaier/* ARGSUSED */
47159781Smlaierstatic void
48159781Smlaiersetifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
49159781Smlaier{
50159781Smlaier	struct ifgroupreq ifgr;
51159781Smlaier
52159781Smlaier	memset(&ifgr, 0, sizeof(ifgr));
53159781Smlaier	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
54159781Smlaier
55159781Smlaier	if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
56159781Smlaier		errx(1, "setifgroup: group names may not end in a digit");
57159781Smlaier
58159781Smlaier	if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
59159781Smlaier		errx(1, "setifgroup: group name too long");
60262556Sdes	if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST)
61159781Smlaier		err(1," SIOCAIFGROUP");
62159781Smlaier}
63159781Smlaier
64159781Smlaier/* ARGSUSED */
65159781Smlaierstatic void
66159781Smlaierunsetifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
67159781Smlaier{
68159781Smlaier	struct ifgroupreq ifgr;
69159781Smlaier
70159781Smlaier	memset(&ifgr, 0, sizeof(ifgr));
71159781Smlaier	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
72159781Smlaier
73159781Smlaier	if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
74159781Smlaier		errx(1, "unsetifgroup: group names may not end in a digit");
75159781Smlaier
76159781Smlaier	if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
77159781Smlaier		errx(1, "unsetifgroup: group name too long");
78262556Sdes	if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT)
79159781Smlaier		err(1, "SIOCDIFGROUP");
80159781Smlaier}
81159781Smlaier
82159781Smlaierstatic void
83159781Smlaiergetifgroups(int s)
84159781Smlaier{
85159781Smlaier	int			 len, cnt;
86159781Smlaier	struct ifgroupreq	 ifgr;
87159781Smlaier	struct ifg_req		*ifg;
88159781Smlaier
89159781Smlaier	if (!verbose)
90159781Smlaier		return;
91159781Smlaier
92159781Smlaier	memset(&ifgr, 0, sizeof(ifgr));
93159781Smlaier	strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
94159781Smlaier
95159781Smlaier	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
96159781Smlaier		if (errno == EINVAL || errno == ENOTTY)
97159781Smlaier			return;
98159781Smlaier		else
99159781Smlaier			err(1, "SIOCGIFGROUP");
100159781Smlaier	}
101159781Smlaier
102159781Smlaier	len = ifgr.ifgr_len;
103159781Smlaier	ifgr.ifgr_groups =
104159781Smlaier	    (struct ifg_req *)calloc(len / sizeof(struct ifg_req),
105159781Smlaier	    sizeof(struct ifg_req));
106159781Smlaier	if (ifgr.ifgr_groups == NULL)
107159781Smlaier		err(1, "getifgroups");
108159781Smlaier	if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
109159781Smlaier		err(1, "SIOCGIFGROUP");
110159781Smlaier
111159781Smlaier	cnt = 0;
112159781Smlaier	ifg = ifgr.ifgr_groups;
113159781Smlaier	for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
114159781Smlaier		len -= sizeof(struct ifg_req);
115159781Smlaier		if (strcmp(ifg->ifgrq_group, "all")) {
116159781Smlaier			if (cnt == 0)
117159781Smlaier				printf("\tgroups: ");
118159781Smlaier			cnt++;
119159781Smlaier			printf("%s ", ifg->ifgrq_group);
120159781Smlaier		}
121159781Smlaier	}
122159781Smlaier	if (cnt)
123159781Smlaier		printf("\n");
124159781Smlaier}
125159781Smlaier
126159781Smlaierstatic void
127166804Ssamprintgroup(const char *groupname)
128159781Smlaier{
129159781Smlaier	struct ifgroupreq	 ifgr;
130159781Smlaier	struct ifg_req		*ifg;
131159781Smlaier	int			 len, cnt = 0;
132159781Smlaier	int			 s;
133159781Smlaier
134189864Sjamie	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
135159781Smlaier	if (s == -1)
136189864Sjamie		err(1, "socket(AF_LOCAL,SOCK_DGRAM)");
137159781Smlaier	bzero(&ifgr, sizeof(ifgr));
138159781Smlaier	strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name));
139159781Smlaier	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
140159781Smlaier		if (errno == EINVAL || errno == ENOTTY ||
141159781Smlaier		    errno == ENOENT)
142159781Smlaier			exit(0);
143159781Smlaier		else
144159781Smlaier			err(1, "SIOCGIFGMEMB");
145159781Smlaier	}
146159781Smlaier
147159781Smlaier	len = ifgr.ifgr_len;
148159781Smlaier	if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
149159781Smlaier		err(1, "printgroup");
150159781Smlaier	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
151159781Smlaier		err(1, "SIOCGIFGMEMB");
152159781Smlaier
153159781Smlaier	for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
154159781Smlaier	    ifg++) {
155159781Smlaier		len -= sizeof(struct ifg_req);
156159781Smlaier		printf("%s\n", ifg->ifgrq_member);
157159781Smlaier		cnt++;
158159781Smlaier	}
159159781Smlaier	free(ifgr.ifgr_groups);
160159781Smlaier
161159781Smlaier	exit(0);
162159781Smlaier}
163159781Smlaier
164159781Smlaierstatic struct cmd group_cmds[] = {
165159781Smlaier	DEF_CMD_ARG("group",	setifgroup),
166159781Smlaier	DEF_CMD_ARG("-group",	unsetifgroup),
167159781Smlaier};
168159781Smlaierstatic struct afswtch af_group = {
169159781Smlaier	.af_name	= "af_group",
170159781Smlaier	.af_af		= AF_UNSPEC,
171159781Smlaier	.af_other_status = getifgroups,
172159781Smlaier};
173159781Smlaierstatic struct option group_gopt = { "g:", "[-g groupname]", printgroup };
174159781Smlaier
175159781Smlaierstatic __constructor void
176159781Smlaiergroup_ctor(void)
177159781Smlaier{
178159781Smlaier#define	N(a)	(sizeof(a) / sizeof(a[0]))
179159781Smlaier	int i;
180159781Smlaier
181159781Smlaier	for (i = 0; i < N(group_cmds);  i++)
182159781Smlaier		cmd_register(&group_cmds[i]);
183159781Smlaier	af_register(&af_group);
184159781Smlaier	opt_register(&group_gopt);
185159781Smlaier#undef N
186159781Smlaier}
187