ifclone.c revision 300285
1178828Sdfr/*
2233294Sstas * Copyright (c) 1983, 1993
372450Sassar *	The Regents of the University of California.  All rights reserved.
456067Smarkm *
556067Smarkm * Redistribution and use in source and binary forms, with or without
672450Sassar * modification, are permitted provided that the following conditions
7102649Snectar * are met:
8102649Snectar * 1. Redistributions of source code must retain the above copyright
972450Sassar *    notice, this list of conditions and the following disclaimer.
1056067Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1172450Sassar *    notice, this list of conditions and the following disclaimer in the
1272450Sassar *    documentation and/or other materials provided with the distribution.
1372450Sassar * 4. Neither the name of the University nor the names of its contributors
1456067Smarkm *    may be used to endorse or promote products derived from this software
1556067Smarkm *    without specific prior written permission.
1656067Smarkm *
17178828Sdfr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19178828Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20233294Sstas * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23178828Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24178828Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27178828Sdfr * SUCH DAMAGE.
28178828Sdfr */
29178828Sdfr
30178828Sdfr#ifndef lint
31178828Sdfrstatic const char rcsid[] =
32178828Sdfr  "$FreeBSD: stable/10/sbin/ifconfig/ifclone.c 300285 2016-05-20 07:14:03Z truckman $";
33233294Sstas#endif /* not lint */
34178828Sdfr
35233294Sstas#include <sys/param.h>
36233294Sstas#include <sys/ioctl.h>
37233294Sstas#include <sys/queue.h>
38178828Sdfr#include <sys/socket.h>
39178828Sdfr#include <net/if.h>
40233294Sstas
41233294Sstas#include <err.h>
42178828Sdfr#include <stdio.h>
43178828Sdfr#include <stdlib.h>
44178828Sdfr#include <string.h>
45178828Sdfr#include <unistd.h>
46178828Sdfr
47233294Sstas#include "ifconfig.h"
48233294Sstas
49233294Sstasstatic void
50233294Sstaslist_cloners(void)
51233294Sstas{
52233294Sstas	struct if_clonereq ifcr;
53233294Sstas	char *cp, *buf;
54233294Sstas	int idx;
55233294Sstas	int s;
56233294Sstas
57233294Sstas	s = socket(AF_LOCAL, SOCK_DGRAM, 0);
58233294Sstas	if (s == -1)
59233294Sstas		err(1, "socket(AF_LOCAL,SOCK_DGRAM)");
60233294Sstas
61233294Sstas	memset(&ifcr, 0, sizeof(ifcr));
6272450Sassar
6372450Sassar	if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
6456067Smarkm		err(1, "SIOCIFGCLONERS for count");
65178828Sdfr
66178828Sdfr	buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
67178828Sdfr	if (buf == NULL)
6872450Sassar		err(1, "unable to allocate cloner name buffer");
6972450Sassar
7056067Smarkm	ifcr.ifcr_count = ifcr.ifcr_total;
7172450Sassar	ifcr.ifcr_buffer = buf;
7272450Sassar
7356067Smarkm	if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
7472450Sassar		err(1, "SIOCIFGCLONERS for names");
7572450Sassar
7656067Smarkm	/*
7772450Sassar	 * In case some disappeared in the mean time, clamp it down.
7872450Sassar	 */
7956067Smarkm	if (ifcr.ifcr_count > ifcr.ifcr_total)
80233294Sstas		ifcr.ifcr_count = ifcr.ifcr_total;
81233294Sstas
82233294Sstas	for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) {
83178828Sdfr		if (idx > 0)
84178828Sdfr			putchar(' ');
85178828Sdfr		printf("%s", cp);
86178828Sdfr	}
87233294Sstas
88178828Sdfr	putchar('\n');
8972450Sassar	free(buf);
9072450Sassar}
9156067Smarkm
9272450Sassarstruct clone_defcb {
9372450Sassar	char ifprefix[IFNAMSIZ];
9456067Smarkm	clone_callback_func *clone_cb;
9572450Sassar	SLIST_ENTRY(clone_defcb) next;
9672450Sassar};
9756067Smarkm
9872450Sassarstatic SLIST_HEAD(, clone_defcb) clone_defcbh =
9972450Sassar   SLIST_HEAD_INITIALIZER(clone_defcbh);
100233294Sstas
10156067Smarkmvoid
10272450Sassarclone_setdefcallback(const char *ifprefix, clone_callback_func *p)
10372450Sassar{
10472450Sassar	struct clone_defcb *dcp;
10556067Smarkm
10672450Sassar	dcp = malloc(sizeof(*dcp));
10772450Sassar	strlcpy(dcp->ifprefix, ifprefix, IFNAMSIZ-1);
10872450Sassar	dcp->clone_cb = p;
10956067Smarkm	SLIST_INSERT_HEAD(&clone_defcbh, dcp, next);
11072450Sassar}
11172450Sassar
11272450Sassar/*
11356067Smarkm * Do the actual clone operation.  Any parameters must have been
114102649Snectar * setup by now.  If a callback has been setup to do the work
115102649Snectar * then defer to it; otherwise do a simple create operation with
116102649Snectar * no parameters.
117178828Sdfr */
118178828Sdfrstatic void
119102649Snectarifclonecreate(int s, void *arg)
120102649Snectar{
12172450Sassar	struct ifreq ifr;
12256067Smarkm	struct clone_defcb *dcp;
123102649Snectar	clone_callback_func *clone_cb = NULL;
12472450Sassar
12572450Sassar	memset(&ifr, 0, sizeof(ifr));
126102649Snectar	(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
12772450Sassar
12872450Sassar	if (clone_cb == NULL) {
129102649Snectar		/* Try to find a default callback */
13072450Sassar		SLIST_FOREACH(dcp, &clone_defcbh, next) {
13172450Sassar			if (strncmp(dcp->ifprefix, ifr.ifr_name,
132233294Sstas			    strlen(dcp->ifprefix)) == 0) {
133233294Sstas				clone_cb = dcp->clone_cb;
134233294Sstas				break;
135102649Snectar			}
13656067Smarkm		}
13756067Smarkm	}
138102649Snectar	if (clone_cb == NULL) {
13956067Smarkm		/* NB: no parameters */
14056067Smarkm		if (ioctl(s, SIOCIFCREATE2, &ifr) < 0)
141102649Snectar			err(1, "SIOCIFCREATE2");
142102649Snectar	} else {
143102649Snectar		clone_cb(s, &ifr);
144233294Sstas	}
145233294Sstas
146233294Sstas	/*
147102649Snectar	 * If we get a different name back than we put in, update record and
14872450Sassar	 * indicate it should be printed later.
14972450Sassar	 */
150102649Snectar	if (strncmp(name, ifr.ifr_name, sizeof(name)) != 0) {
15172450Sassar		strlcpy(name, ifr.ifr_name, sizeof(name));
15272450Sassar		printifname = 1;
153102649Snectar	}
15478550Sassar}
15578550Sassar
156102649Snectarstatic
15778550SassarDECL_CMD_FUNC(clone_create, arg, d)
15878550Sassar{
159102649Snectar	callback_register(ifclonecreate, NULL);
16072450Sassar}
16172450Sassar
162233294Sstasstatic
163233294SstasDECL_CMD_FUNC(clone_destroy, arg, d)
164233294Sstas{
165102649Snectar	(void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
166103427Snectar	if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
16756067Smarkm		err(1, "SIOCIFDESTROY");
168102649Snectar}
16956067Smarkm
17056067Smarkmstatic struct cmd clone_cmds[] = {
171102649Snectar	DEF_CLONE_CMD("create",	0,	clone_create),
17256067Smarkm	DEF_CMD("destroy",	0,	clone_destroy),
17356067Smarkm	DEF_CLONE_CMD("plumb",	0,	clone_create),
174178828Sdfr	DEF_CMD("unplumb",	0,	clone_destroy),
175233294Sstas};
176178828Sdfr
177233294Sstasstatic void
178233294Sstasclone_Copt_cb(const char *optarg __unused)
179233294Sstas{
180233294Sstas	list_cloners();
181233294Sstas	exit(0);
182233294Sstas}
183102649Snectarstatic struct option clone_Copt = { .opt = "C", .opt_usage = "[-C]", .cb = clone_Copt_cb };
18472450Sassar
18572450Sassarstatic __constructor void
186102649Snectarclone_ctor(void)
18756067Smarkm{
18856067Smarkm	size_t i;
189102649Snectar
19056067Smarkm	for (i = 0; i < nitems(clone_cmds);  i++)
19156067Smarkm		cmd_register(&clone_cmds[i]);
192102649Snectar	opt_register(&clone_Copt);
19372450Sassar}
19472450Sassar