1 /* $NetBSD: ether.c,v 1.3 2018/12/21 08:58:08 msaitoh 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.3 2018/12/21 08:58:08 msaitoh 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 #if 0 /* notyet */ 68 IFKW("vlan-hwfilter", ETHERCAP_VLAN_HWFILTER) 69 #endif 70 IFKW("eee", ETHERCAP_EEE) 71 }; 72 73 struct pkw ethercaps = PKW_INITIALIZER(ðercaps, "ethercaps", setethercaps, 74 "ethercap", ethercapskw, __arraycount(ethercapskw), 75 &command_root.pb_parser); 76 77 void 78 do_setethercaps(prop_dictionary_t env) 79 { 80 struct eccapreq eccr; 81 prop_data_t d; 82 83 d = (prop_data_t )prop_dictionary_get(env, "ethercaps"); 84 if (d == NULL) 85 return; 86 87 assert(sizeof(eccr) == prop_data_size(d)); 88 89 memcpy(&eccr, prop_data_data_nocopy(d), sizeof(eccr)); 90 if (direct_ioctl(env, SIOCSETHERCAP, &eccr) == -1) 91 err(EXIT_FAILURE, "SIOCSETHERCAP"); 92 } 93 94 static int 95 getethercaps(prop_dictionary_t env, prop_dictionary_t oenv, 96 struct eccapreq *oeccr) 97 { 98 bool rc; 99 struct eccapreq eccr; 100 const struct eccapreq *tmpeccr; 101 prop_data_t capdata; 102 103 capdata = (prop_data_t)prop_dictionary_get(env, "ethercaps"); 104 105 if (capdata != NULL) { 106 tmpeccr = prop_data_data_nocopy(capdata); 107 *oeccr = *tmpeccr; 108 return 0; 109 } 110 111 (void)direct_ioctl(env, SIOCGETHERCAP, &eccr); 112 *oeccr = eccr; 113 114 capdata = prop_data_create_data(&eccr, sizeof(eccr)); 115 116 rc = prop_dictionary_set(oenv, "ethercaps", capdata); 117 118 prop_object_release((prop_object_t)capdata); 119 120 return rc ? 0 : -1; 121 } 122 123 static int 124 setethercaps(prop_dictionary_t env, prop_dictionary_t oenv) 125 { 126 int64_t ethercap; 127 bool rc; 128 prop_data_t capdata; 129 struct eccapreq eccr; 130 131 rc = prop_dictionary_get_int64(env, "ethercap", ðercap); 132 assert(rc); 133 134 if (getethercaps(env, oenv, &eccr) == -1) 135 return -1; 136 137 if (ethercap < 0) { 138 ethercap = -ethercap; 139 eccr.eccr_capenable &= ~ethercap; 140 } else 141 eccr.eccr_capenable |= ethercap; 142 143 if ((capdata = prop_data_create_data(&eccr, sizeof(eccr))) == NULL) 144 return -1; 145 146 rc = prop_dictionary_set(oenv, "ethercaps", capdata); 147 prop_object_release((prop_object_t)capdata); 148 149 return rc ? 0 : -1; 150 } 151 152 void 153 ether_status(prop_dictionary_t env, prop_dictionary_t oenv) 154 { 155 struct eccapreq eccr; 156 char fbuf[BUFSIZ]; 157 char *bp; 158 159 memset(&eccr, 0, sizeof(eccr)); 160 161 if (direct_ioctl(env, SIOCGETHERCAP, &eccr) == -1) 162 return; 163 164 if (eccr.eccr_capabilities != 0) { 165 (void)snprintb_m(fbuf, sizeof(fbuf), ECCAPBITS, 166 eccr.eccr_capabilities, MAX_PRINT_LEN); 167 bp = fbuf; 168 while (*bp != '\0') { 169 printf("\tec_capabilities=%s\n", &bp[2]); 170 bp += strlen(bp) + 1; 171 } 172 (void)snprintb_m(fbuf, sizeof(fbuf), ECCAPBITS, 173 eccr.eccr_capenable, MAX_PRINT_LEN); 174 bp = fbuf; 175 while (*bp != '\0') { 176 printf("\tec_enabled=%s\n", &bp[2]); 177 bp += strlen(bp) + 1; 178 } 179 } 180 } 181 182 static void 183 ether_constructor(void) 184 { 185 186 cmdloop_branch_init(&branch, ðercaps.pk_parser); 187 register_cmdloop_branch(&branch); 188 status_func_init(&status, ether_status); 189 register_status(&status); 190 } 191