1/* 2 * Copyright (c) 2001-2002 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * Copyright (c) 2003-2004 6 * Hartmut Brandt. 7 * All rights reserved. 8 * 9 * Author: Hartmut Brandt <harti@freebsd.org> 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD: stable/10/usr.sbin/bsnmpd/modules/snmp_atm/atm_sys.c 310903 2016-12-31 10:34:09Z ngie $ 33 * 34 * SNMP module for ATM hardware interfaces - FreeBSD/Ng specific part. 35 */ 36 37#include "atm.h" 38#include "atm_tree.h" 39#include "atm_oid.h" 40 41#include <stdlib.h> 42#include <syslog.h> 43#include <string.h> 44 45#include <net/if_atm.h> 46 47#include <bsnmp/snmp_netgraph.h> 48#include <netgraph/ng_message.h> 49#include <netgraph/atm/ng_atm.h> 50 51static const struct hwinfo { 52 const char *device; 53 const char *vendor; 54} hwinfo[] = { 55 ATM_DEVICE_NAMES 56}; 57 58struct atmif_sys { 59 ng_ID_t atm_node; 60 void *regc; /* cookie registration */ 61}; 62 63/* 64 * Find the interface for a given node 65 */ 66struct atmif * 67atm_node2if(u_int node) 68{ 69 struct atmif_priv *aif; 70 71 if (node != 0) 72 TAILQ_FOREACH(aif, &atmif_list, link) 73 if (aif->sys->atm_node == node) 74 return (&aif->pub); 75 return (NULL); 76} 77 78u_int 79atm_if2node(struct atmif *pub) 80{ 81 struct atmif_priv *aif = (struct atmif_priv *)pub; 82 83 return (aif->sys->atm_node); 84} 85 86/* 87 * Destroy system dependend stuff. 88 */ 89void 90atmif_sys_destroy(struct atmif_priv *aif) 91{ 92 93 ng_unregister_cookie(aif->sys->regc); 94 free(aif->sys); 95 free(aif->pub.mib); 96} 97 98/* 99 * Handle a message from the ATM node 100 */ 101static void 102handle_atm_message(const struct ng_mesg *mesg, const char *path __unused, 103 ng_ID_t node, void *uarg) 104{ 105 struct atmif_priv *aif = uarg; 106 enum atmif_carrier_state ost; 107 108 switch (mesg->header.cmd) { 109 110 case NGM_ATM_IF_CHANGE: 111 { 112 const struct ngm_atm_if_change *arg; 113 114 ost = aif->pub.carrier; 115 if (mesg->header.arglen != sizeof(*arg)) { 116 syslog(LOG_ERR, "ATM_IF_CHANGE: wrong size"); 117 atmif_check_carrier(aif); 118 return; 119 } 120 arg = (const struct ngm_atm_if_change *) 121 (const void *)mesg->data; 122 123 if (arg->carrier) 124 aif->pub.carrier = ATMIF_CARRIER_ON; 125 else 126 aif->pub.carrier = ATMIF_CARRIER_OFF; 127 128 if (ost != aif->pub.carrier) 129 atmif_send_notification(aif, ATMIF_NOTIFY_CARRIER, 130 (uintptr_t)ost); 131 return; 132 } 133 134 case NGM_ATM_VCC_CHANGE: 135 { 136 const struct ngm_atm_vcc_change *arg; 137 138 if (mesg->header.arglen != sizeof(*arg)) { 139 syslog(LOG_ERR, "ATM_VCC_CHANGE: wrong size"); 140 return; 141 } 142 arg = (const struct ngm_atm_vcc_change *) 143 (const void *)mesg->data; 144 atmif_send_notification(aif, ATMIF_NOTIFY_VCC, 145 (uintptr_t)(((arg->vpi & 0xff) << 24) | 146 ((arg->vci & 0xffff) << 8) | (arg->state & 1))); 147 return; 148 } 149 } 150 syslog(LOG_WARNING, "spurious message %u from node [%x]", 151 mesg->header.cmd, node); 152} 153 154/* 155 * Attach to an ATM interface 156 */ 157int 158atmif_sys_attach_if(struct atmif_priv *aif) 159{ 160 struct ng_mesg *resp, *resp1; 161 struct namelist *list; 162 u_int i; 163 164 if ((aif->sys = malloc(sizeof(*aif->sys))) == NULL) { 165 syslog(LOG_CRIT, "out of memory"); 166 return (-1); 167 } 168 memset(aif->sys, 0, sizeof(*aif->sys)); 169 170 if ((aif->pub.mib = malloc(sizeof(*aif->pub.mib))) == NULL) { 171 free(aif->sys); 172 syslog(LOG_CRIT, "out of memory"); 173 return (-1); 174 } 175 176 atmif_sys_fill_mib(aif); 177 178 /* 179 * Get ATM node Id. Must do it the hard way by scanning all nodes 180 * because the name may be wrong. 181 */ 182 if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, NGM_LISTNODES, 183 NULL, 0)) == NULL) { 184 syslog(LOG_ERR, "cannot fetch node list: %m"); 185 free(aif->sys); 186 return (-1); 187 } 188 list = (struct namelist *)(void *)resp->data; 189 190 for (i = 0; i < list->numnames; i++) { 191 if (strcmp(list->nodeinfo[i].type, NG_ATM_NODE_TYPE) != 0) 192 continue; 193 if ((resp1 = ng_dialog_id(list->nodeinfo[i].id, 194 NGM_ATM_COOKIE, NGM_ATM_GET_IFNAME, NULL, 0)) == NULL) 195 continue; 196 if (strcmp(resp1->data, aif->pub.ifp->name) == 0) { 197 free(resp1); 198 break; 199 } 200 free(resp1); 201 } 202 if (i == list->numnames) 203 aif->sys->atm_node = 0; 204 else 205 aif->sys->atm_node = list->nodeinfo[i].id; 206 207 free(resp); 208 209 if ((aif->sys->regc = ng_register_cookie(module, NGM_ATM_COOKIE, 210 aif->sys->atm_node, handle_atm_message, aif)) == NULL) { 211 syslog(LOG_ERR, "cannot register cookie: %m"); 212 free(aif->sys); 213 return (-1); 214 } 215 return (0); 216} 217 218/* 219 * Table of all ATM interfaces - Ng part 220 */ 221int 222op_atmif_ng(struct snmp_context *ctx __unused, struct snmp_value *value, 223 u_int sub, u_int vindex __unused, enum snmp_op op) 224{ 225 struct atmif_priv *aif; 226 int err; 227 228 if ((err = atmif_get_aif(value, sub, op, &aif)) != SNMP_ERR_NOERROR) 229 return (err); 230 231 if (op == SNMP_OP_SET) { 232 switch (value->var.subs[sub - 1]) { 233 234 default: 235 return (SNMP_ERR_NOT_WRITEABLE); 236 } 237 } 238 239 switch (value->var.subs[sub - 1]) { 240 241 case LEAF_begemotAtmIfNodeId: 242 value->v.uint32 = aif->sys->atm_node; 243 return (SNMP_ERR_NOERROR); 244 } 245 abort(); 246} 247 248/* 249 * Get vendor string 250 */ 251int 252atm_sys_get_hw_vendor(struct atmif_priv *aif, struct snmp_value *value) 253{ 254 255 if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0])) 256 return (string_get(value, "unknown", -1)); 257 return (string_get(value, hwinfo[aif->pub.mib->device].vendor, -1)); 258} 259 260/* 261 * Get device string 262 */ 263int 264atm_sys_get_hw_device(struct atmif_priv *aif, struct snmp_value *value) 265{ 266 267 if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0])) 268 return (string_get(value, "unknown", -1)); 269 return (string_get(value, hwinfo[aif->pub.mib->device].device, -1)); 270} 271 272/* 273 * Extract the ATM MIB from the interface's private MIB 274 */ 275void 276atmif_sys_fill_mib(struct atmif_priv *aif) 277{ 278 struct ifatm_mib *mib; 279 280 if (aif->pub.ifp->specmiblen != sizeof(struct ifatm_mib)) { 281 syslog(LOG_ERR, "atmif MIB has wrong size %zu", 282 aif->pub.ifp->specmiblen); 283 memset(aif->pub.mib, 0, sizeof(*aif->pub.mib)); 284 aif->pub.mib->version = 0; 285 return; 286 } 287 mib = (struct ifatm_mib *)aif->pub.ifp->specmib; 288 289 aif->pub.mib->device = mib->device; 290 aif->pub.mib->serial = mib->serial; 291 aif->pub.mib->hw_version = mib->hw_version; 292 aif->pub.mib->sw_version = mib->sw_version; 293 aif->pub.mib->media = mib->media; 294 295 memcpy(aif->pub.mib->esi, mib->esi, 6); 296 aif->pub.mib->pcr = mib->pcr; 297 aif->pub.mib->vpi_bits = mib->vpi_bits; 298 aif->pub.mib->vci_bits = mib->vci_bits; 299 aif->pub.mib->max_vpcs = mib->max_vpcs; 300 aif->pub.mib->max_vccs = mib->max_vccs; 301} 302