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 27 static const char rcsid[] = 28 "$FreeBSD$"; 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 */ 47 static void 48 setifgroup(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 */ 65 static void 66 unsetifgroup(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 82 static void 83 getifgroups(int s) 84 { 85 int len, cnt; 86 struct ifgroupreq ifgr; 87 struct ifg_req *ifg; 88 89 memset(&ifgr, 0, sizeof(ifgr)); 90 strlcpy(ifgr.ifgr_name, name, IFNAMSIZ); 91 92 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) { 93 if (errno == EINVAL || errno == ENOTTY) 94 return; 95 else 96 err(1, "SIOCGIFGROUP"); 97 } 98 99 len = ifgr.ifgr_len; 100 ifgr.ifgr_groups = 101 (struct ifg_req *)calloc(len / sizeof(struct ifg_req), 102 sizeof(struct ifg_req)); 103 if (ifgr.ifgr_groups == NULL) 104 err(1, "getifgroups"); 105 if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) 106 err(1, "SIOCGIFGROUP"); 107 108 cnt = 0; 109 ifg = ifgr.ifgr_groups; 110 for (; ifg && len >= sizeof(struct ifg_req); ifg++) { 111 len -= sizeof(struct ifg_req); 112 if (strcmp(ifg->ifgrq_group, "all")) { 113 if (cnt == 0) 114 printf("\tgroups: "); 115 cnt++; 116 printf("%s ", ifg->ifgrq_group); 117 } 118 } 119 if (cnt) 120 printf("\n"); 121 122 free(ifgr.ifgr_groups); 123 } 124 125 static void 126 printgroup(const char *groupname) 127 { 128 struct ifgroupreq ifgr; 129 struct ifg_req *ifg; 130 int len, cnt = 0; 131 int s; 132 133 s = socket(AF_LOCAL, SOCK_DGRAM, 0); 134 if (s == -1) 135 err(1, "socket(AF_LOCAL,SOCK_DGRAM)"); 136 bzero(&ifgr, sizeof(ifgr)); 137 strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name)); 138 if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) { 139 if (errno == EINVAL || errno == ENOTTY || 140 errno == ENOENT) 141 exit(0); 142 else 143 err(1, "SIOCGIFGMEMB"); 144 } 145 146 len = ifgr.ifgr_len; 147 if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) 148 err(1, "printgroup"); 149 if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) 150 err(1, "SIOCGIFGMEMB"); 151 152 for (ifg = ifgr.ifgr_groups; 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(0); 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 }; 173 174 static __constructor void 175 group_ctor(void) 176 { 177 #define N(a) (sizeof(a) / sizeof(a[0])) 178 int i; 179 180 for (i = 0; i < N(group_cmds); i++) 181 cmd_register(&group_cmds[i]); 182 af_register(&af_group); 183 opt_register(&group_gopt); 184 #undef N 185 } 186