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 * $FreeBSD: head/sbin/ifconfig/ifgroup.c 326276 2017-11-27 15:37:16Z pfg $ 28 */ 29 30 #include <sys/param.h> 31 #include <sys/ioctl.h> 32 #include <sys/socket.h> 33 #include <net/if.h> 34 35 #include <ctype.h> 36 #include <err.h> 37 #include <errno.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include "ifconfig.h" 44 45 static void 46 setifgroup(const char *group_name, int d __unused, int s, 47 const struct afswtch *rafp __unused) 48 { 49 struct ifgroupreq ifgr; 50 51 memset(&ifgr, 0, sizeof(ifgr)); 52 strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); 53 54 if (group_name[0] && isdigit(group_name[strlen(group_name) - 1])) 55 errx(1, "setifgroup: group names may not end in a digit"); 56 57 if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ) 58 errx(1, "setifgroup: group name too long"); 59 if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1 && errno != EEXIST) 60 err(1," SIOCAIFGROUP"); 61 } 62 63 static void 64 unsetifgroup(const char *group_name, int d __unused, int s, 65 const struct afswtch *rafp __unused) 66 { 67 struct ifgroupreq ifgr; 68 69 memset(&ifgr, 0, sizeof(ifgr)); 70 strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); 71 72 if (group_name[0] && isdigit(group_name[strlen(group_name) - 1])) 73 errx(1, "unsetifgroup: group names may not end in a digit"); 74 75 if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ) 76 errx(1, "unsetifgroup: group name too long"); 77 if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1 && errno != ENOENT) 78 err(1, "SIOCDIFGROUP"); 79 } 80 81 static void 82 getifgroups(int s) 83 { 84 struct ifgroupreq ifgr; 85 struct ifg_req *ifg; 86 size_t len, cnt; 87 88 memset(&ifgr, 0, sizeof(ifgr)); 89 strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); 90 91 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { 92 if (errno == EINVAL || errno == ENOTTY) 93 return; 94 else 95 err(1, "SIOCGIFGROUP"); 96 } 97 98 len = ifgr.ifgr_len; 99 ifgr.ifgr_groups = calloc(len / sizeof(struct ifg_req), 100 sizeof(struct ifg_req)); 101 if (ifgr.ifgr_groups == NULL) 102 err(1, "getifgroups"); 103 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 104 err(1, "SIOCGIFGROUP"); 105 106 cnt = 0; 107 ifg = ifgr.ifgr_groups; 108 for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 109 len -= sizeof(struct ifg_req); 110 if (strcmp(ifg->ifgrq_group, "all") != 0) { 111 if (cnt == 0) 112 printf("\tgroups:"); 113 cnt++; 114 printf(" %s", ifg->ifgrq_group); 115 } 116 } 117 if (cnt) 118 printf("\n"); 119 120 free(ifgr.ifgr_groups); 121 } 122 123 static void 124 printgroup(const char *groupname) 125 { 126 struct ifgroupreq ifgr; 127 struct ifg_req *ifg; 128 size_t len, cnt = 0; 129 int s; 130 131 s = socket(AF_LOCAL, SOCK_DGRAM, 0); 132 if (s == -1) 133 err(1, "socket(AF_LOCAL,SOCK_DGRAM)"); 134 135 memset(&ifgr, 0, sizeof(ifgr)); 136 strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); 137 if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { 138 if (errno == EINVAL || errno == ENOTTY || 139 errno == ENOENT) 140 exit(exit_code); 141 else 142 err(1, "SIOCGIFGMEMB"); 143 } 144 145 len = ifgr.ifgr_len; 146 if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 147 err(1, "printgroup"); 148 if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 149 err(1, "SIOCGIFGMEMB"); 150 151 for (ifg = ifgr.ifgr_groups; 152 ifg && len >= sizeof(struct ifg_req); 153 ifg++) { 154 len -= sizeof(struct ifg_req); 155 printf("%s\n", ifg->ifgrq_member); 156 cnt++; 157 } 158 free(ifgr.ifgr_groups); 159 160 exit(exit_code); 161 } 162 163 static struct cmd group_cmds[] = { 164 DEF_CMD_ARG("group", setifgroup), 165 DEF_CMD_ARG("-group", unsetifgroup), 166 }; 167 static struct afswtch af_group = { 168 .af_name = "af_group", 169 .af_af = AF_UNSPEC, 170 .af_other_status = getifgroups, 171 }; 172 static struct option group_gopt = { "g:", "[-g groupname]", printgroup, NULL }; 173 174 static __constructor(101) void 175 group_ctor(void) 176 { 177 size_t i; 178 179 for (i = 0; i < nitems(group_cmds); i++) 180 cmd_register(&group_cmds[i]); 181 af_register(&af_group); 182 opt_register(&group_gopt); 183 } 184