1181834Sroberto/* 2181834Sroberto * Copyright (c) 2001-2002 3181834Sroberto * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4181834Sroberto * All rights reserved. 5181834Sroberto * Copyright (c) 2003-2004 6181834Sroberto * Hartmut Brandt. 7181834Sroberto * All rights reserved. 8181834Sroberto * 9181834Sroberto * Author: Hartmut Brandt <harti@freebsd.org> 10181834Sroberto * 11181834Sroberto * Redistribution and use in source and binary forms, with or without 12181834Sroberto * modification, are permitted provided that the following conditions 13181834Sroberto * are met: 14181834Sroberto * 1. Redistributions of source code must retain the above copyright 15181834Sroberto * notice, this list of conditions and the following disclaimer. 16181834Sroberto * 2. Redistributions in binary form must reproduce the above copyright 17181834Sroberto * notice, this list of conditions and the following disclaimer in the 18181834Sroberto * documentation and/or other materials provided with the distribution. 19181834Sroberto * 20181834Sroberto * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21181834Sroberto * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22181834Sroberto * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23181834Sroberto * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24181834Sroberto * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25181834Sroberto * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26181834Sroberto * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27181834Sroberto * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28181834Sroberto * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29181834Sroberto * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30181834Sroberto * SUCH DAMAGE. 31181834Sroberto */ 32181834Sroberto 33181834Sroberto#include <sys/cdefs.h> 34181834Sroberto__FBSDID("$FreeBSD$"); 35181834Sroberto 36181834Sroberto#include "atmconfig.h" 37181834Sroberto#include "atmconfig_device.h" 38181834Sroberto#include "private.h" 39181834Sroberto#include "oid.h" 40181834Sroberto 41181834Sroberto#include <bsnmp/asn1.h> 42181834Sroberto#include <bsnmp/snmp.h> 43181834Sroberto#include <bsnmp/snmpclient.h> 44181834Sroberto 45181834Sroberto/* 46181834Sroberto * Description of the begemotAtmIfTable 47181834Sroberto */ 48181834Srobertostatic const struct snmp_table atmif_table = { 49181834Sroberto OIDX_begemotAtmIfTable, 50181834Sroberto OIDX_begemotAtmIfTableLastChange, 2, 51181834Sroberto sizeof(struct atmif), 52181834Sroberto 1, 0x7ffULL, 53181834Sroberto { 54181834Sroberto { 0, 55181834Sroberto SNMP_SYNTAX_INTEGER, offsetof(struct atmif, index) }, 56181834Sroberto { OID_begemotAtmIfName, 57181834Sroberto SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmif, ifname) }, 58181834Sroberto { OID_begemotAtmIfPcr, 59181834Sroberto SNMP_SYNTAX_GAUGE, offsetof(struct atmif, pcr) }, 60181834Sroberto { OID_begemotAtmIfMedia, 61181834Sroberto SNMP_SYNTAX_INTEGER, offsetof(struct atmif, media) }, 62181834Sroberto { OID_begemotAtmIfVpiBits, 63181834Sroberto SNMP_SYNTAX_GAUGE, offsetof(struct atmif, vpi_bits) }, 64181834Sroberto { OID_begemotAtmIfVciBits, 65181834Sroberto SNMP_SYNTAX_GAUGE, offsetof(struct atmif, vci_bits) }, 66181834Sroberto { OID_begemotAtmIfMaxVpcs, 67181834Sroberto SNMP_SYNTAX_GAUGE, offsetof(struct atmif, max_vpcs) }, 68181834Sroberto { OID_begemotAtmIfMaxVccs, 69181834Sroberto SNMP_SYNTAX_GAUGE, offsetof(struct atmif, max_vccs) }, 70181834Sroberto { OID_begemotAtmIfEsi, 71181834Sroberto SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmif, esi) }, 72181834Sroberto { OID_begemotAtmIfCarrierStatus, 73181834Sroberto SNMP_SYNTAX_INTEGER, offsetof(struct atmif, carrier) }, 74181834Sroberto { OID_begemotAtmIfMode, 75181834Sroberto SNMP_SYNTAX_INTEGER, offsetof(struct atmif, mode) }, 76181834Sroberto { 0, SNMP_SYNTAX_NULL, 0 } 77181834Sroberto } 78181834Sroberto}; 79181834Sroberto 80181834Sroberto/* List of all ATM interfaces */ 81181834Srobertostruct atmif_list atmif_list = TAILQ_HEAD_INITIALIZER(atmif_list); 82181834Sroberto 83181834Sroberto/* 84181834Sroberto * ATM hardware table 85181834Sroberto */ 86181834Srobertostruct atmhw { 87181834Sroberto TAILQ_ENTRY(atmhw) link; 88181834Sroberto uint64_t found; 89181834Sroberto int32_t index; 90181834Sroberto u_char *vendor; 91181834Sroberto size_t vendorlen; 92181834Sroberto u_char *device; 93181834Sroberto size_t devicelen; 94181834Sroberto uint32_t serial; 95181834Sroberto uint32_t version; 96181834Sroberto uint32_t soft_version; 97181834Sroberto}; 98181834SrobertoTAILQ_HEAD(atmhw_list, atmhw); 99181834Sroberto 100181834Sroberto/* list of ATM hardware */ 101181834Srobertostatic struct atmhw_list atmhw_list; 102181834Sroberto 103181834Sroberto/* 104181834Sroberto * Read ATM hardware table 105181834Sroberto */ 106181834Srobertostatic const struct snmp_table atmhw_table = { 107181834Sroberto OIDX_begemotAtmHWTable, 108181834Sroberto OIDX_begemotAtmIfTableLastChange, 2, 109181834Sroberto sizeof(struct atmhw), 110181834Sroberto 1, 0x3fULL, 111181834Sroberto { 112181834Sroberto { 0, 113181834Sroberto SNMP_SYNTAX_INTEGER, offsetof(struct atmhw, index) }, 114181834Sroberto { OID_begemotAtmHWVendor, 115181834Sroberto SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmhw, vendor) }, 116181834Sroberto { OID_begemotAtmHWDevice, 117181834Sroberto SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmhw, device) }, 118181834Sroberto { OID_begemotAtmHWSerial, 119181834Sroberto SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, serial) }, 120181834Sroberto { OID_begemotAtmHWVersion, 121181834Sroberto SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, version) }, 122181834Sroberto { OID_begemotAtmHWSoftVersion, 123181834Sroberto SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, soft_version) }, 124181834Sroberto { 0, SNMP_SYNTAX_NULL, 0 } 125181834Sroberto } 126181834Sroberto}; 127181834Sroberto 128181834Srobertostatic void device_status(int, char *[]); 129181834Srobertostatic void device_hardware(int, char *[]); 130181834Srobertostatic void device_modify(int, char *[]); 131181834Sroberto 132181834Srobertostatic const struct cmdtab device_tab[] = { 133181834Sroberto { "hardware", NULL, device_hardware }, 134181834Sroberto { "status", NULL, device_status }, 135181834Sroberto { "modify", NULL, device_modify }, 136181834Sroberto { NULL, NULL, NULL } 137181834Sroberto}; 138181834Sroberto 139181834Srobertostatic const struct cmdtab entry = 140181834Sroberto { "device", device_tab, NULL }; 141181834Sroberto 142181834Srobertostatic DEF_MODULE(&entry); 143181834Sroberto 144181834Sroberto/* 145181834Sroberto * Carrier state to string 146181834Sroberto */ 147181834Srobertostatic const struct penum strcarrier[] = { 148181834Sroberto { 1, "on" }, 149181834Sroberto { 2, "off" }, 150181834Sroberto { 3, "unknown" }, 151181834Sroberto { 4, "none" }, 152181834Sroberto { 0, NULL } 153181834Sroberto}; 154181834Sroberto/* 155181834Sroberto * SUNI mode to string 156181834Sroberto */ 157181834Srobertostatic const struct penum strsunimode[] = { 158181834Sroberto { 1, "sonet" }, 159181834Sroberto { 2, "sdh" }, 160181834Sroberto { 3, "unknown" }, 161181834Sroberto { 0, NULL } 162181834Sroberto}; 163181834Sroberto 164181834Sroberto/* 165181834Sroberto * OIDs 166181834Sroberto */ 167181834Srobertostatic const struct asn_oid 168181834Sroberto oid_begemotAtmIfMode = OIDX_begemotAtmIfMode; 169181834Sroberto 170181834Sroberto/* 171181834Sroberto * Print 1st status line 172181834Sroberto */ 173181834Srobertostatic void 174181834Srobertodev_status1(const struct atmif *aif) 175181834Sroberto{ 176181834Sroberto char buf[100]; 177181834Sroberto 178181834Sroberto printf("%-5u %-8s %-6u %-4u %-5u %-4u %-5u " 179181834Sroberto "%02x:%02x:%02x:%02x:%02x:%02x %s\n", aif->index, 180181834Sroberto aif->ifname, aif->pcr, 181181834Sroberto (1 << aif->vpi_bits) - 1, (1 << aif->vci_bits) - 1, 182181834Sroberto aif->max_vpcs, aif->max_vccs, aif->esi[0], 183181834Sroberto aif->esi[1], aif->esi[2], aif->esi[3], aif->esi[4], aif->esi[5], 184181834Sroberto penum(aif->carrier, strcarrier, buf)); 185181834Sroberto} 186181834Sroberto 187181834Sroberto/* 188181834Sroberto * Print 2nd status line 189181834Sroberto */ 190181834Srobertostatic void 191181834Srobertodev_status2(const struct atmif *aif) 192181834Sroberto{ 193181834Sroberto char buf[100]; 194181834Sroberto 195181834Sroberto printf("%-5u %-8s %s\n", aif->index, aif->ifname, 196181834Sroberto penum(aif->mode, strsunimode, buf)); 197181834Sroberto} 198181834Sroberto 199181834Sroberto/* 200181834Sroberto * Implement the 'device status' command 201181834Sroberto */ 202181834Srobertostatic void 203181834Srobertodevice_status(int argc, char *argv[]) 204181834Sroberto{ 205181834Sroberto int opt, i; 206181834Sroberto struct atmif *aif; 207181834Sroberto static const struct option opts[] = { 208181834Sroberto { NULL, 0, NULL } 209181834Sroberto }; 210181834Sroberto 211181834Sroberto const char dev1[] = 212181834Sroberto "Interface Max Max\n" 213181834Sroberto "Index Name PCR VPI VCI VPCs VCCs ESI Carrier\n"; 214181834Sroberto const char dev2[] = 215181834Sroberto "Interface\n" 216181834Sroberto "Index Name Mode\n"; 217181834Sroberto 218181834Sroberto while ((opt = parse_options(&argc, &argv, opts)) != -1) 219181834Sroberto switch (opt) { 220181834Sroberto } 221181834Sroberto 222181834Sroberto snmp_open(NULL, NULL, NULL, NULL); 223181834Sroberto atexit(snmp_close); 224181834Sroberto 225181834Sroberto atmif_fetchtable(); 226181834Sroberto 227181834Sroberto if (TAILQ_EMPTY(&atmif_list)) 228181834Sroberto errx(1, "no ATM interfaces found"); 229181834Sroberto 230181834Sroberto if (argc > 0) { 231181834Sroberto heading_init(); 232181834Sroberto for (i = 0; i < argc; i++) { 233181834Sroberto if ((aif = atmif_find_name(argv[i])) == NULL) { 234181834Sroberto warnx("%s: no such ATM interface", argv[i]); 235181834Sroberto continue; 236181834Sroberto } 237181834Sroberto heading(dev1); 238181834Sroberto dev_status1(aif); 239181834Sroberto } 240181834Sroberto heading_init(); 241181834Sroberto for (i = 0; i < argc; i++) { 242181834Sroberto if ((aif = atmif_find_name(argv[i])) == NULL) 243181834Sroberto continue; 244181834Sroberto heading(dev2); 245181834Sroberto dev_status2(aif); 246181834Sroberto } 247181834Sroberto } else { 248181834Sroberto heading_init(); 249181834Sroberto TAILQ_FOREACH(aif, &atmif_list, link) { 250181834Sroberto heading(dev1); 251181834Sroberto dev_status1(aif); 252181834Sroberto } 253181834Sroberto heading_init(); 254181834Sroberto TAILQ_FOREACH(aif, &atmif_list, link) { 255181834Sroberto heading(dev2); 256181834Sroberto dev_status2(aif); 257181834Sroberto } 258181834Sroberto } 259181834Sroberto} 260181834Sroberto 261181834Sroberto/* 262181834Sroberto * Print hardware info line 263181834Sroberto */ 264181834Srobertostatic void 265181834Srobertodev_hardware(const struct atmif *aif) 266181834Sroberto{ 267181834Sroberto const struct atmhw *hw; 268181834Sroberto 269181834Sroberto TAILQ_FOREACH(hw, &atmhw_list, link) 270181834Sroberto if (aif->index == hw->index) 271181834Sroberto break; 272181834Sroberto if (hw == NULL) { 273181834Sroberto warnx("hardware info not found for '%s'", aif->ifname); 274181834Sroberto return; 275181834Sroberto } 276181834Sroberto 277181834Sroberto printf("%-5u %-8s %-16s%-10s %-10u %-10u %u\n", aif->index, 278181834Sroberto aif->ifname, hw->vendor, hw->device, hw->serial, 279181834Sroberto hw->version, hw->soft_version); 280181834Sroberto} 281181834Sroberto 282181834Sroberto/* 283181834Sroberto * Show hardware configuration 284181834Sroberto */ 285181834Srobertostatic void 286181834Srobertodevice_hardware(int argc, char *argv[]) 287181834Sroberto{ 288181834Sroberto int opt, i; 289181834Sroberto struct atmif *aif; 290181834Sroberto 291181834Sroberto static const struct option opts[] = { 292181834Sroberto { NULL, 0, NULL } 293181834Sroberto }; 294181834Sroberto 295181834Sroberto static const char headline[] = 296181834Sroberto "Interface \n" 297181834Sroberto "Index Name Vendor Card Serial HW SW\n"; 298181834Sroberto 299181834Sroberto while ((opt = parse_options(&argc, &argv, opts)) != -1) 300181834Sroberto switch (opt) { 301181834Sroberto } 302181834Sroberto 303181834Sroberto snmp_open(NULL, NULL, NULL, NULL); 304181834Sroberto atexit(snmp_close); 305181834Sroberto 306181834Sroberto atmif_fetchtable(); 307181834Sroberto 308181834Sroberto if (snmp_table_fetch(&atmhw_table, &atmhw_list) != 0) 309181834Sroberto errx(1, "AtmHW table: %s", snmp_client.error); 310181834Sroberto 311181834Sroberto if (argc > 0) { 312181834Sroberto heading_init(); 313181834Sroberto for (i = 0; i < argc; i++) { 314181834Sroberto if ((aif = atmif_find_name(argv[i])) == NULL) { 315181834Sroberto warnx("interface not found '%s'", argv[i]); 316181834Sroberto continue; 317181834Sroberto } 318181834Sroberto heading(headline); 319181834Sroberto dev_hardware(aif); 320181834Sroberto } 321181834Sroberto } else { 322181834Sroberto heading_init(); 323181834Sroberto TAILQ_FOREACH(aif, &atmif_list, link) { 324181834Sroberto heading(headline); 325181834Sroberto dev_hardware(aif); 326181834Sroberto } 327181834Sroberto } 328181834Sroberto} 329181834Sroberto 330181834Sroberto/* 331181834Sroberto * Change device parameters 332181834Sroberto */ 333181834Srobertostatic void 334181834Srobertodevice_modify(int argc, char *argv[]) 335181834Sroberto{ 336181834Sroberto int opt; 337181834Sroberto struct atmif *aif; 338181834Sroberto int mode = 0; 339181834Sroberto int n; 340181834Sroberto struct snmp_pdu pdu, resp; 341181834Sroberto 342181834Sroberto static const struct option opts[] = { 343181834Sroberto#define MODIFY_MODE 0 344181834Sroberto { "mode", OPT_STRING, NULL }, 345181834Sroberto { NULL, 0, NULL } 346181834Sroberto }; 347181834Sroberto 348181834Sroberto while ((opt = parse_options(&argc, &argv, opts)) != -1) 349181834Sroberto switch (opt) { 350181834Sroberto 351181834Sroberto case MODIFY_MODE: 352181834Sroberto if (pparse(&mode, strsunimode, optarg) == -1 || 353181834Sroberto mode == 3) 354181834Sroberto errx(1, "illegal mode for -m '%s'", optarg); 355181834Sroberto break; 356181834Sroberto } 357181834Sroberto 358181834Sroberto if (argc != 1) 359181834Sroberto errx(1, "device modify needs one argument"); 360181834Sroberto 361181834Sroberto snmp_open(NULL, NULL, NULL, NULL); 362181834Sroberto 363181834Sroberto atexit(snmp_close); 364181834Sroberto atmif_fetchtable(); 365181834Sroberto 366181834Sroberto if ((aif = atmif_find_name(argv[0])) == NULL) 367181834Sroberto errx(1, "%s: no such ATM interface", argv[0]); 368181834Sroberto 369181834Sroberto snmp_pdu_create(&pdu, SNMP_PDU_SET); 370181834Sroberto if (mode != 0) { 371181834Sroberto n = snmp_add_binding(&pdu, 372181834Sroberto &oid_begemotAtmIfMode, SNMP_SYNTAX_INTEGER, 373181834Sroberto NULL); 374181834Sroberto snmp_oid_append(&pdu.bindings[n + 0].var, "i", 375181834Sroberto (asn_subid_t)aif->index); 376181834Sroberto pdu.bindings[n + 0].v.integer = mode; 377181834Sroberto } 378181834Sroberto 379181834Sroberto if (pdu.nbindings == 0) 380181834Sroberto errx(1, "must specify something to modify"); 381181834Sroberto 382181834Sroberto if (snmp_dialog(&pdu, &resp)) 383181834Sroberto errx(1, "No response from '%s': %s", snmp_client.chost, 384181834Sroberto snmp_client.error); 385181834Sroberto 386181834Sroberto if (snmp_pdu_check(&pdu, &resp) <= 0) 387181834Sroberto errx(1, "Error modifying device"); 388181834Sroberto 389181834Sroberto snmp_pdu_free(&resp); 390181834Sroberto snmp_pdu_free(&pdu); 391181834Sroberto} 392181834Sroberto 393181834Sroberto/* XXX while this is compiled in */ 394181834Srobertovoid 395181834Srobertodevice_register(void) 396181834Sroberto{ 397181834Sroberto register_module(&amodule_1); 398181834Sroberto} 399181834Sroberto 400181834Sroberto/* 401181834Sroberto * Fetch the ATM interface table 402181834Sroberto */ 403181834Srobertovoid 404181834Srobertoatmif_fetchtable(void) 405181834Sroberto{ 406181834Sroberto struct atmif *aif; 407181834Sroberto 408181834Sroberto while ((aif = TAILQ_FIRST(&atmif_list)) != NULL) { 409181834Sroberto free(aif->ifname); 410181834Sroberto free(aif->esi); 411181834Sroberto TAILQ_REMOVE(&atmif_list, aif, link); 412181834Sroberto free(aif); 413181834Sroberto } 414181834Sroberto 415181834Sroberto if (snmp_table_fetch(&atmif_table, &atmif_list) != 0) 416181834Sroberto errx(1, "AtmIf table: %s", snmp_client.error); 417181834Sroberto} 418181834Sroberto 419181834Sroberto/* 420181834Sroberto * Find a named ATM interface 421181834Sroberto */ 422181834Srobertostruct atmif * 423181834Srobertoatmif_find_name(const char *ifname) 424181834Sroberto{ 425181834Sroberto struct atmif *atmif; 426181834Sroberto 427181834Sroberto TAILQ_FOREACH(atmif, &atmif_list, link) 428181834Sroberto if (strcmp(atmif->ifname, ifname) == 0) 429181834Sroberto return (atmif); 430181834Sroberto return (NULL); 431181834Sroberto} 432181834Sroberto/* 433181834Sroberto * find an ATM interface by index 434181834Sroberto */ 435181834Srobertostruct atmif * 436181834Srobertoatmif_find(u_int idx) 437181834Sroberto{ 438181834Sroberto struct atmif *atmif; 439181834Sroberto 440181834Sroberto TAILQ_FOREACH(atmif, &atmif_list, link) 441181834Sroberto if (atmif->index == (int32_t)idx) 442181834Sroberto return (atmif); 443181834Sroberto return (NULL); 444181834Sroberto} 445181834Sroberto