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