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