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) 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) 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 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 126 static void 127 printgroup(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_INET, SOCK_DGRAM, 0); 135 if (s == -1) 136 err(1, "socket(AF_INET,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 164 static struct cmd group_cmds[] = { 165 DEF_CMD_ARG("group", setifgroup), 166 DEF_CMD_ARG("-group", unsetifgroup), 167 }; 168 static struct afswtch af_group = { 169 .af_name = "af_group", 170 .af_af = AF_UNSPEC, 171 .af_other_status = getifgroups, 172 }; 173 static struct option group_gopt = { "g:", "[-g groupname]", printgroup }; 174 175 static __constructor void 176 group_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