1 /* $NetBSD: ether.c,v 1.9 2020/06/07 06:02:58 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __RCSID("$NetBSD: ether.c,v 1.9 2020/06/07 06:02:58 thorpej Exp $"); 35 #endif /* not lint */ 36 37 #include <sys/param.h> 38 #include <sys/ioctl.h> 39 40 #include <net/if.h> 41 #include <net/if_ether.h> 42 43 #include <assert.h> 44 #include <ctype.h> 45 #include <err.h> 46 #include <errno.h> 47 #include <string.h> 48 #include <stdlib.h> 49 #include <stdio.h> 50 #include <util.h> 51 52 #include "env.h" 53 #include "parse.h" 54 #include "extern.h" 55 #include "prog_ops.h" 56 57 static void ether_status(prop_dictionary_t, prop_dictionary_t); 58 static void ether_constructor(void) __attribute__((constructor)); 59 static int setethercaps(prop_dictionary_t, prop_dictionary_t); 60 61 static status_func_t status; 62 static cmdloop_branch_t branch; 63 64 #define MAX_PRINT_LEN 55 65 66 static const struct kwinst ethercapskw[] = { 67 IFKW("vlan-hwfilter", ETHERCAP_VLAN_HWFILTER), 68 IFKW("vlan-hwtagging", ETHERCAP_VLAN_HWTAGGING), 69 IFKW("eee", ETHERCAP_EEE) 70 }; 71 72 struct pkw ethercaps = PKW_INITIALIZER(ðercaps, "ethercaps", setethercaps, 73 "ethercap", ethercapskw, __arraycount(ethercapskw), 74 &command_root.pb_parser); 75 76 void 77 do_setethercaps(prop_dictionary_t env) 78 { 79 struct eccapreq eccr; 80 prop_data_t d; 81 82 d = (prop_data_t )prop_dictionary_get(env, "ethercaps"); 83 if (d == NULL) 84 return; 85 86 assert(sizeof(eccr) == prop_data_size(d)); 87 88 memcpy(&eccr, prop_data_value(d), sizeof(eccr)); 89 if (direct_ioctl(env, SIOCSETHERCAP, &eccr) == -1) 90 err(EXIT_FAILURE, "SIOCSETHERCAP"); 91 } 92 93 static int 94 getethercaps(prop_dictionary_t env, prop_dictionary_t oenv, 95 struct eccapreq *oeccr) 96 { 97 bool rc; 98 struct eccapreq eccr; 99 const struct eccapreq *tmpeccr; 100 prop_data_t capdata; 101 102 capdata = (prop_data_t)prop_dictionary_get(env, "ethercaps"); 103 104 if (capdata != NULL) { 105 tmpeccr = prop_data_value(capdata); 106 *oeccr = *tmpeccr; 107 return 0; 108 } 109 110 (void)direct_ioctl(env, SIOCGETHERCAP, &eccr); 111 *oeccr = eccr; 112 113 capdata = prop_data_create_copy(&eccr, sizeof(eccr)); 114 115 rc = prop_dictionary_set(oenv, "ethercaps", capdata); 116 117 prop_object_release((prop_object_t)capdata); 118 119 return rc ? 0 : -1; 120 } 121 122 static int 123 setethercaps(prop_dictionary_t env, prop_dictionary_t oenv) 124 { 125 int64_t ethercap; 126 bool rc; 127 prop_data_t capdata; 128 struct eccapreq eccr; 129 130 rc = prop_dictionary_get_int64(env, "ethercap", ðercap); 131 assert(rc); 132 133 if (getethercaps(env, oenv, &eccr) == -1) 134 return -1; 135 136 if (ethercap < 0) { 137 ethercap = -ethercap; 138 eccr.eccr_capenable &= ~ethercap; 139 } else 140 eccr.eccr_capenable |= ethercap; 141 142 if ((capdata = prop_data_create_copy(&eccr, sizeof(eccr))) == NULL) 143 return -1; 144 145 rc = prop_dictionary_set(oenv, "ethercaps", capdata); 146 prop_object_release((prop_object_t)capdata); 147 148 return rc ? 0 : -1; 149 } 150 151 void 152 ether_status(prop_dictionary_t env, prop_dictionary_t oenv) 153 { 154 struct eccapreq eccr; 155 char fbuf[BUFSIZ]; 156 char *bp; 157 158 memset(&eccr, 0, sizeof(eccr)); 159 160 if (direct_ioctl(env, SIOCGETHERCAP, &eccr) == -1) 161 return; 162 163 if (eccr.eccr_capabilities != 0) { 164 (void)snprintb_m(fbuf, sizeof(fbuf), ECCAPBITS, 165 eccr.eccr_capabilities, MAX_PRINT_LEN); 166 bp = fbuf; 167 while (*bp != '\0') { 168 printf("\tec_capabilities=%s\n", bp); 169 bp += strlen(bp) + 1; 170 } 171 (void)snprintb_m(fbuf, sizeof(fbuf), ECCAPBITS, 172 eccr.eccr_capenable, MAX_PRINT_LEN); 173 bp = fbuf; 174 while (*bp != '\0') { 175 printf("\tec_enabled=%s\n", bp); 176 bp += strlen(bp) + 1; 177 } 178 } 179 } 180 181 static void 182 ether_constructor(void) 183 { 184 185 cmdloop_branch_init(&branch, ðercaps.pk_parser); 186 register_cmdloop_branch(&branch); 187 status_func_init(&status, ether_status); 188 register_status(&status); 189 } 190