atm_sys.c revision 310903
1157016Sdes/* 2137015Sdes * Copyright (c) 2001-2002 3137015Sdes * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4137015Sdes * All rights reserved. 5137015Sdes * Copyright (c) 2003-2004 6137015Sdes * Hartmut Brandt. 7137015Sdes * All rights reserved. 8137015Sdes * 9137015Sdes * Author: Hartmut Brandt <harti@freebsd.org> 10137015Sdes * 11137015Sdes * Redistribution and use in source and binary forms, with or without 12137015Sdes * modification, are permitted provided that the following conditions 13137015Sdes * are met: 14137015Sdes * 1. Redistributions of source code must retain the above copyright 15137015Sdes * notice, this list of conditions and the following disclaimer. 16137015Sdes * 2. Redistributions in binary form must reproduce the above copyright 17204861Sdes * notice, this list of conditions and the following disclaimer in the 18204861Sdes * documentation and/or other materials provided with the distribution. 19137015Sdes * 20137015Sdes * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21137015Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22137015Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23218767Sdes * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 24137015Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25137015Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26137015Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27137015Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28137015Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29137015Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30137015Sdes * SUCH DAMAGE. 31137015Sdes * 32137015Sdes * $FreeBSD: stable/10/usr.sbin/bsnmpd/modules/snmp_atm/atm_sys.c 310903 2016-12-31 10:34:09Z ngie $ 33137015Sdes * 34137015Sdes * SNMP module for ATM hardware interfaces - FreeBSD/Ng specific part. 35137015Sdes */ 36218767Sdes 37218767Sdes#include "atm.h" 38218767Sdes#include "atm_tree.h" 39137015Sdes#include "atm_oid.h" 40137015Sdes 41137015Sdes#include <stdlib.h> 42137015Sdes#include <syslog.h> 43137015Sdes#include <string.h> 44137015Sdes 45137015Sdes#include <net/if_atm.h> 46137015Sdes 47137015Sdes#include <bsnmp/snmp_netgraph.h> 48137015Sdes#include <netgraph/ng_message.h> 49137015Sdes#include <netgraph/atm/ng_atm.h> 50137015Sdes 51137015Sdesstatic const struct hwinfo { 52137015Sdes const char *device; 53137015Sdes const char *vendor; 54137015Sdes} hwinfo[] = { 55137015Sdes ATM_DEVICE_NAMES 56137015Sdes}; 57137015Sdes 58137015Sdesstruct atmif_sys { 59137015Sdes ng_ID_t atm_node; 60137015Sdes void *regc; /* cookie registration */ 61137015Sdes}; 62137015Sdes 63137015Sdes/* 64137015Sdes * Find the interface for a given node 65137015Sdes */ 66137015Sdesstruct atmif * 67137015Sdesatm_node2if(u_int node) 68137015Sdes{ 69137015Sdes struct atmif_priv *aif; 70137015Sdes 71137015Sdes if (node != 0) 72137015Sdes TAILQ_FOREACH(aif, &atmif_list, link) 73137015Sdes if (aif->sys->atm_node == node) 74137015Sdes return (&aif->pub); 75137015Sdes return (NULL); 76137015Sdes} 77137015Sdes 78137015Sdesu_int 79137015Sdesatm_if2node(struct atmif *pub) 80137015Sdes{ 81137015Sdes struct atmif_priv *aif = (struct atmif_priv *)pub; 82137015Sdes 83137015Sdes return (aif->sys->atm_node); 84137015Sdes} 85137015Sdes 86137015Sdes/* 87137015Sdes * Destroy system dependend stuff. 88137015Sdes */ 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