1133391Sharti/* 2133391Sharti * Copyright (c) 2001-2002 3133391Sharti * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4133391Sharti * All rights reserved. 5133391Sharti * Copyright (c) 2003-2004 6133391Sharti * Hartmut Brandt. 7133391Sharti * All rights reserved. 8133391Sharti * 9133391Sharti * Author: Hartmut Brandt <harti@freebsd.org> 10133391Sharti * 11133391Sharti * Redistribution and use in source and binary forms, with or without 12133391Sharti * modification, are permitted provided that the following conditions 13133391Sharti * are met: 14133391Sharti * 1. Redistributions of source code must retain the above copyright 15133391Sharti * notice, this list of conditions and the following disclaimer. 16133391Sharti * 2. Redistributions in binary form must reproduce the above copyright 17133391Sharti * notice, this list of conditions and the following disclaimer in the 18133391Sharti * documentation and/or other materials provided with the distribution. 19133391Sharti * 20133391Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21133391Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22133391Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23133391Sharti * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 24133391Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25133391Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26133391Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27133391Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28133391Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29133391Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30133391Sharti * SUCH DAMAGE. 31133391Sharti * 32133391Sharti * $FreeBSD$ 33133391Sharti * 34133391Sharti * SNMP module for ATM hardware interfaces - FreeBSD/Ng specific part. 35133391Sharti */ 36133391Sharti 37133391Sharti#include "atm.h" 38133391Sharti#include "atm_tree.h" 39133391Sharti#include "atm_oid.h" 40133391Sharti 41133391Sharti#include <stdlib.h> 42133391Sharti#include <syslog.h> 43133391Sharti#include <string.h> 44133391Sharti 45133391Sharti#include <net/if_atm.h> 46133391Sharti 47133391Sharti#include <bsnmp/snmp_netgraph.h> 48133391Sharti#include <netgraph/ng_message.h> 49133391Sharti#include <netgraph/atm/ng_atm.h> 50133391Sharti 51133391Shartistatic const struct hwinfo { 52133391Sharti const char *device; 53133391Sharti const char *vendor; 54133391Sharti} hwinfo[] = { 55133391Sharti ATM_DEVICE_NAMES 56133391Sharti}; 57133391Sharti 58133391Shartistruct atmif_sys { 59133391Sharti ng_ID_t atm_node; 60133391Sharti void *regc; /* cookie registration */ 61133391Sharti}; 62133391Sharti 63133391Sharti/* 64133391Sharti * Find the interface for a given node 65133391Sharti */ 66133391Shartistruct atmif * 67133391Shartiatm_node2if(u_int node) 68133391Sharti{ 69133391Sharti struct atmif_priv *aif; 70133391Sharti 71133391Sharti if (node != 0) 72133391Sharti TAILQ_FOREACH(aif, &atmif_list, link) 73133391Sharti if (aif->sys->atm_node == node) 74133391Sharti return (&aif->pub); 75133391Sharti return (NULL); 76133391Sharti} 77133391Sharti 78133391Shartiu_int 79133391Shartiatm_if2node(struct atmif *pub) 80133391Sharti{ 81133391Sharti struct atmif_priv *aif = (struct atmif_priv *)pub; 82133391Sharti 83133391Sharti return (aif->sys->atm_node); 84133391Sharti} 85133391Sharti 86133391Sharti/* 87133391Sharti * Destroy system dependend stuff. 88133391Sharti */ 89133391Shartivoid 90133391Shartiatmif_sys_destroy(struct atmif_priv *aif) 91133391Sharti{ 92133391Sharti 93133391Sharti ng_unregister_cookie(aif->sys->regc); 94133391Sharti free(aif->sys); 95133391Sharti free(aif->pub.mib); 96133391Sharti} 97133391Sharti 98133391Sharti/* 99133391Sharti * Handle a message from the ATM node 100133391Sharti */ 101133391Shartistatic void 102133391Shartihandle_atm_message(const struct ng_mesg *mesg, const char *path __unused, 103133391Sharti ng_ID_t node, void *uarg) 104133391Sharti{ 105133391Sharti struct atmif_priv *aif = uarg; 106133391Sharti enum atmif_carrier_state ost; 107133391Sharti 108133391Sharti switch (mesg->header.cmd) { 109133391Sharti 110133391Sharti case NGM_ATM_IF_CHANGE: 111133391Sharti { 112133391Sharti const struct ngm_atm_if_change *arg; 113133391Sharti 114133391Sharti ost = aif->pub.carrier; 115133391Sharti if (mesg->header.arglen != sizeof(*arg)) { 116133391Sharti syslog(LOG_ERR, "ATM_IF_CHANGE: wrong size"); 117133391Sharti atmif_check_carrier(aif); 118133391Sharti return; 119133391Sharti } 120133391Sharti arg = (const struct ngm_atm_if_change *) 121133391Sharti (const void *)mesg->data; 122133391Sharti 123133391Sharti if (arg->carrier) 124133391Sharti aif->pub.carrier = ATMIF_CARRIER_ON; 125133391Sharti else 126133391Sharti aif->pub.carrier = ATMIF_CARRIER_OFF; 127133391Sharti 128133391Sharti if (ost != aif->pub.carrier) 129133391Sharti atmif_send_notification(aif, ATMIF_NOTIFY_CARRIER, 130133391Sharti (uintptr_t)ost); 131133391Sharti return; 132133391Sharti } 133133391Sharti 134133391Sharti case NGM_ATM_VCC_CHANGE: 135133391Sharti { 136133391Sharti const struct ngm_atm_vcc_change *arg; 137133391Sharti 138133391Sharti if (mesg->header.arglen != sizeof(*arg)) { 139133391Sharti syslog(LOG_ERR, "ATM_VCC_CHANGE: wrong size"); 140133391Sharti return; 141133391Sharti } 142133391Sharti arg = (const struct ngm_atm_vcc_change *) 143133391Sharti (const void *)mesg->data; 144133391Sharti atmif_send_notification(aif, ATMIF_NOTIFY_VCC, 145133391Sharti (uintptr_t)(((arg->vpi & 0xff) << 24) | 146133391Sharti ((arg->vci & 0xffff) << 8) | (arg->state & 1))); 147133391Sharti return; 148133391Sharti } 149133391Sharti } 150133391Sharti syslog(LOG_WARNING, "spurious message %u from node [%x]", 151133391Sharti mesg->header.cmd, node); 152133391Sharti} 153133391Sharti 154133391Sharti/* 155133391Sharti * Attach to an ATM interface 156133391Sharti */ 157133391Shartiint 158133391Shartiatmif_sys_attach_if(struct atmif_priv *aif) 159133391Sharti{ 160133391Sharti struct ng_mesg *resp, *resp1; 161133391Sharti struct namelist *list; 162133391Sharti u_int i; 163133391Sharti 164133391Sharti if ((aif->sys = malloc(sizeof(*aif->sys))) == NULL) { 165133391Sharti syslog(LOG_CRIT, "out of memory"); 166133391Sharti return (-1); 167133391Sharti } 168133391Sharti memset(aif->sys, 0, sizeof(*aif->sys)); 169133391Sharti 170133391Sharti if ((aif->pub.mib = malloc(sizeof(*aif->pub.mib))) == NULL) { 171133391Sharti free(aif->sys); 172133391Sharti syslog(LOG_CRIT, "out of memory"); 173133391Sharti return (-1); 174133391Sharti } 175133391Sharti 176133391Sharti atmif_sys_fill_mib(aif); 177133391Sharti 178133391Sharti /* 179133391Sharti * Get ATM node Id. Must do it the hard way by scanning all nodes 180133391Sharti * because the name may be wrong. 181133391Sharti */ 182133391Sharti if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, NGM_LISTNODES, 183133391Sharti NULL, 0)) == NULL) { 184133391Sharti syslog(LOG_ERR, "cannot fetch node list: %m"); 185133391Sharti free(aif->sys); 186133391Sharti return (-1); 187133391Sharti } 188133391Sharti list = (struct namelist *)(void *)resp->data; 189133391Sharti 190133391Sharti for (i = 0; i < list->numnames; i++) { 191133391Sharti if (strcmp(list->nodeinfo[i].type, NG_ATM_NODE_TYPE) != 0) 192133391Sharti continue; 193133391Sharti if ((resp1 = ng_dialog_id(list->nodeinfo[i].id, 194133391Sharti NGM_ATM_COOKIE, NGM_ATM_GET_IFNAME, NULL, 0)) == NULL) 195133391Sharti continue; 196133391Sharti if (strcmp(resp1->data, aif->pub.ifp->name) == 0) { 197133391Sharti free(resp1); 198133391Sharti break; 199133391Sharti } 200133391Sharti free(resp1); 201133391Sharti } 202133391Sharti if (i == list->numnames) 203133391Sharti aif->sys->atm_node = 0; 204133391Sharti else 205133391Sharti aif->sys->atm_node = list->nodeinfo[i].id; 206133391Sharti 207133391Sharti free(resp); 208133391Sharti 209133391Sharti if ((aif->sys->regc = ng_register_cookie(module, NGM_ATM_COOKIE, 210133391Sharti aif->sys->atm_node, handle_atm_message, aif)) == NULL) { 211133391Sharti syslog(LOG_ERR, "cannot register cookie: %m"); 212133391Sharti free(aif->sys); 213133391Sharti return (-1); 214133391Sharti } 215133391Sharti return (0); 216133391Sharti} 217133391Sharti 218133391Sharti/* 219133391Sharti * Table of all ATM interfaces - Ng part 220133391Sharti */ 221133391Shartiint 222133391Shartiop_atmif_ng(struct snmp_context *ctx __unused, struct snmp_value *value, 223133391Sharti u_int sub, u_int vindex __unused, enum snmp_op op) 224133391Sharti{ 225133391Sharti struct atmif_priv *aif; 226133391Sharti int err; 227133391Sharti 228133391Sharti if ((err = atmif_get_aif(value, sub, op, &aif)) != SNMP_ERR_NOERROR) 229133391Sharti return (err); 230133391Sharti 231133391Sharti if (op == SNMP_OP_SET) { 232133391Sharti switch (value->var.subs[sub - 1]) { 233133391Sharti 234133391Sharti default: 235133391Sharti return (SNMP_ERR_NOT_WRITEABLE); 236133391Sharti } 237133391Sharti } 238133391Sharti 239133391Sharti switch (value->var.subs[sub - 1]) { 240133391Sharti 241133391Sharti case LEAF_begemotAtmIfNodeId: 242133391Sharti value->v.uint32 = aif->sys->atm_node; 243133391Sharti return (SNMP_ERR_NOERROR); 244133391Sharti } 245133391Sharti abort(); 246133391Sharti} 247133391Sharti 248133391Sharti/* 249133391Sharti * Get vendor string 250133391Sharti */ 251133391Shartiint 252133391Shartiatm_sys_get_hw_vendor(struct atmif_priv *aif, struct snmp_value *value) 253133391Sharti{ 254133391Sharti 255133391Sharti if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0])) 256133391Sharti return (string_get(value, "unknown", -1)); 257133391Sharti return (string_get(value, hwinfo[aif->pub.mib->device].vendor, -1)); 258133391Sharti} 259133391Sharti 260133391Sharti/* 261133391Sharti * Get device string 262133391Sharti */ 263133391Shartiint 264133391Shartiatm_sys_get_hw_device(struct atmif_priv *aif, struct snmp_value *value) 265133391Sharti{ 266133391Sharti 267133391Sharti if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0])) 268133391Sharti return (string_get(value, "unknown", -1)); 269133391Sharti return (string_get(value, hwinfo[aif->pub.mib->device].device, -1)); 270133391Sharti} 271133391Sharti 272133391Sharti/* 273133391Sharti * Extract the ATM MIB from the interface's private MIB 274133391Sharti */ 275133391Shartivoid 276133391Shartiatmif_sys_fill_mib(struct atmif_priv *aif) 277133391Sharti{ 278133391Sharti struct ifatm_mib *mib; 279133391Sharti 280133391Sharti if (aif->pub.ifp->specmiblen != sizeof(struct ifatm_mib)) { 281133391Sharti syslog(LOG_ERR, "atmif MIB has wrong size %zu", 282133391Sharti aif->pub.ifp->specmiblen); 283133391Sharti memset(aif->pub.mib, 0, sizeof(*aif->pub.mib)); 284133391Sharti aif->pub.mib->version = 0; 285133391Sharti return; 286133391Sharti } 287133391Sharti mib = (struct ifatm_mib *)aif->pub.ifp->specmib; 288133391Sharti 289133391Sharti aif->pub.mib->device = mib->device; 290133391Sharti aif->pub.mib->serial = mib->serial; 291133391Sharti aif->pub.mib->hw_version = mib->hw_version; 292133391Sharti aif->pub.mib->sw_version = mib->sw_version; 293133391Sharti aif->pub.mib->media = mib->media; 294133391Sharti 295133391Sharti memcpy(aif->pub.mib->esi, mib->esi, 6); 296133391Sharti aif->pub.mib->pcr = mib->pcr; 297133391Sharti aif->pub.mib->vpi_bits = mib->vpi_bits; 298133391Sharti aif->pub.mib->vci_bits = mib->vci_bits; 299133391Sharti aif->pub.mib->max_vpcs = mib->max_vpcs; 300133391Sharti aif->pub.mib->max_vccs = mib->max_vccs; 301133391Sharti} 302