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 THE 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 THE 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 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD$"); 35 36#include "atmconfig.h" 37#include "atmconfig_device.h" 38#include "private.h" 39#include "oid.h" 40 41#include <bsnmp/asn1.h> 42#include <bsnmp/snmp.h> 43#include <bsnmp/snmpclient.h> 44 45/* 46 * Description of the begemotAtmIfTable 47 */ 48static const struct snmp_table atmif_table = { 49 OIDX_begemotAtmIfTable, 50 OIDX_begemotAtmIfTableLastChange, 2, 51 sizeof(struct atmif), 52 1, 0x7ffULL, 53 { 54 { 0, 55 SNMP_SYNTAX_INTEGER, offsetof(struct atmif, index) }, 56 { OID_begemotAtmIfName, 57 SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmif, ifname) }, 58 { OID_begemotAtmIfPcr, 59 SNMP_SYNTAX_GAUGE, offsetof(struct atmif, pcr) }, 60 { OID_begemotAtmIfMedia, 61 SNMP_SYNTAX_INTEGER, offsetof(struct atmif, media) }, 62 { OID_begemotAtmIfVpiBits, 63 SNMP_SYNTAX_GAUGE, offsetof(struct atmif, vpi_bits) }, 64 { OID_begemotAtmIfVciBits, 65 SNMP_SYNTAX_GAUGE, offsetof(struct atmif, vci_bits) }, 66 { OID_begemotAtmIfMaxVpcs, 67 SNMP_SYNTAX_GAUGE, offsetof(struct atmif, max_vpcs) }, 68 { OID_begemotAtmIfMaxVccs, 69 SNMP_SYNTAX_GAUGE, offsetof(struct atmif, max_vccs) }, 70 { OID_begemotAtmIfEsi, 71 SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmif, esi) }, 72 { OID_begemotAtmIfCarrierStatus, 73 SNMP_SYNTAX_INTEGER, offsetof(struct atmif, carrier) }, 74 { OID_begemotAtmIfMode, 75 SNMP_SYNTAX_INTEGER, offsetof(struct atmif, mode) }, 76 { 0, SNMP_SYNTAX_NULL, 0 } 77 } 78}; 79 80/* List of all ATM interfaces */ 81struct atmif_list atmif_list = TAILQ_HEAD_INITIALIZER(atmif_list); 82 83/* 84 * ATM hardware table 85 */ 86struct atmhw { 87 TAILQ_ENTRY(atmhw) link; 88 uint64_t found; 89 int32_t index; 90 u_char *vendor; 91 size_t vendorlen; 92 u_char *device; 93 size_t devicelen; 94 uint32_t serial; 95 uint32_t version; 96 uint32_t soft_version; 97}; 98TAILQ_HEAD(atmhw_list, atmhw); 99 100/* list of ATM hardware */ 101static struct atmhw_list atmhw_list; 102 103/* 104 * Read ATM hardware table 105 */ 106const struct snmp_table atmhw_table = { 107 OIDX_begemotAtmHWTable, 108 OIDX_begemotAtmIfTableLastChange, 2, 109 sizeof(struct atmhw), 110 1, 0x3fULL, 111 { 112 { 0, 113 SNMP_SYNTAX_INTEGER, offsetof(struct atmhw, index) }, 114 { OID_begemotAtmHWVendor, 115 SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmhw, vendor) }, 116 { OID_begemotAtmHWDevice, 117 SNMP_SYNTAX_OCTETSTRING, offsetof(struct atmhw, device) }, 118 { OID_begemotAtmHWSerial, 119 SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, serial) }, 120 { OID_begemotAtmHWVersion, 121 SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, version) }, 122 { OID_begemotAtmHWSoftVersion, 123 SNMP_SYNTAX_GAUGE, offsetof(struct atmhw, soft_version) }, 124 { 0, SNMP_SYNTAX_NULL, 0 } 125 } 126}; 127 128static void device_status(int, char *[]); 129static void device_hardware(int, char *[]); 130static void device_modify(int, char *[]); 131 132static const struct cmdtab device_tab[] = { 133 { "hardware", NULL, device_hardware }, 134 { "status", NULL, device_status }, 135 { "modify", NULL, device_modify }, 136 { NULL, NULL, NULL } 137}; 138 139static const struct cmdtab entry = 140 { "device", device_tab, NULL }; 141 142static DEF_MODULE(&entry); 143 144/* 145 * Carrier state to string 146 */ 147static const struct penum strcarrier[] = { 148 { 1, "on" }, 149 { 2, "off" }, 150 { 3, "unknown" }, 151 { 4, "none" }, 152 { 0, NULL } 153}; 154/* 155 * SUNI mode to string 156 */ 157static const struct penum strsunimode[] = { 158 { 1, "sonet" }, 159 { 2, "sdh" }, 160 { 3, "unknown" }, 161 { 0, NULL } 162}; 163 164/* 165 * OIDs 166 */ 167static const struct asn_oid 168 oid_begemotAtmIfMode = OIDX_begemotAtmIfMode; 169 170/* 171 * Print 1st status line 172 */ 173static void 174dev_status1(const struct atmif *aif) 175{ 176 char buf[100]; 177 178 printf("%-5u %-8s %-6u %-4u %-5u %-4u %-5u " 179 "%02x:%02x:%02x:%02x:%02x:%02x %s\n", aif->index, 180 aif->ifname, aif->pcr, 181 (1 << aif->vpi_bits) - 1, (1 << aif->vci_bits) - 1, 182 aif->max_vpcs, aif->max_vccs, aif->esi[0], 183 aif->esi[1], aif->esi[2], aif->esi[3], aif->esi[4], aif->esi[5], 184 penum(aif->carrier, strcarrier, buf)); 185} 186 187/* 188 * Print 2nd status line 189 */ 190static void 191dev_status2(const struct atmif *aif) 192{ 193 char buf[100]; 194 195 printf("%-5u %-8s %s\n", aif->index, aif->ifname, 196 penum(aif->mode, strsunimode, buf)); 197} 198 199/* 200 * Implement the 'device status' command 201 */ 202static void 203device_status(int argc, char *argv[]) 204{ 205 int opt, i; 206 struct atmif *aif; 207 static const struct option opts[] = { 208 { NULL, 0, NULL } 209 }; 210 211 const char dev1[] = 212 "Interface Max Max\n" 213 "Index Name PCR VPI VCI VPCs VCCs ESI Carrier\n"; 214 const char dev2[] = 215 "Interface\n" 216 "Index Name Mode\n"; 217 218 while ((opt = parse_options(&argc, &argv, opts)) != -1) 219 switch (opt) { 220 } 221 222 snmp_open(NULL, NULL, NULL, NULL); 223 atexit(snmp_close); 224 225 atmif_fetchtable(); 226 227 if (TAILQ_EMPTY(&atmif_list)) 228 errx(1, "no ATM interfaces found"); 229 230 if (argc > 0) { 231 heading_init(); 232 for (i = 0; i < argc; i++) { 233 if ((aif = atmif_find_name(argv[i])) == NULL) { 234 warnx("%s: no such ATM interface", argv[i]); 235 continue; 236 } 237 heading(dev1); 238 dev_status1(aif); 239 } 240 heading_init(); 241 for (i = 0; i < argc; i++) { 242 if ((aif = atmif_find_name(argv[i])) == NULL) 243 continue; 244 heading(dev2); 245 dev_status2(aif); 246 } 247 } else { 248 heading_init(); 249 TAILQ_FOREACH(aif, &atmif_list, link) { 250 heading(dev1); 251 dev_status1(aif); 252 } 253 heading_init(); 254 TAILQ_FOREACH(aif, &atmif_list, link) { 255 heading(dev2); 256 dev_status2(aif); 257 } 258 } 259} 260 261/* 262 * Print hardware info line 263 */ 264static void 265dev_hardware(const struct atmif *aif) 266{ 267 const struct atmhw *hw; 268 269 TAILQ_FOREACH(hw, &atmhw_list, link) 270 if (aif->index == hw->index) 271 break; 272 if (hw == NULL) { 273 warnx("hardware info not found for '%s'", aif->ifname); 274 return; 275 } 276 277 printf("%-5u %-8s %-16s%-10s %-10u %-10u %u\n", aif->index, 278 aif->ifname, hw->vendor, hw->device, hw->serial, 279 hw->version, hw->soft_version); 280} 281 282/* 283 * Show hardware configuration 284 */ 285static void 286device_hardware(int argc, char *argv[]) 287{ 288 int opt, i; 289 struct atmif *aif; 290 291 static const struct option opts[] = { 292 { NULL, 0, NULL } 293 }; 294 295 static const char headline[] = 296 "Interface \n" 297 "Index Name Vendor Card Serial HW SW\n"; 298 299 while ((opt = parse_options(&argc, &argv, opts)) != -1) 300 switch (opt) { 301 } 302 303 snmp_open(NULL, NULL, NULL, NULL); 304 atexit(snmp_close); 305 306 atmif_fetchtable(); 307 308 if (snmp_table_fetch(&atmhw_table, &atmhw_list) != 0) 309 errx(1, "AtmHW table: %s", snmp_client.error); 310 311 if (argc > 0) { 312 heading_init(); 313 for (i = 0; i < argc; i++) { 314 if ((aif = atmif_find_name(argv[i])) == NULL) { 315 warnx("interface not found '%s'", argv[i]); 316 continue; 317 } 318 heading(headline); 319 dev_hardware(aif); 320 } 321 } else { 322 heading_init(); 323 TAILQ_FOREACH(aif, &atmif_list, link) { 324 heading(headline); 325 dev_hardware(aif); 326 } 327 } 328} 329 330/* 331 * Change device parameters 332 */ 333static void 334device_modify(int argc, char *argv[]) 335{ 336 int opt; 337 struct atmif *aif; 338 int mode = 0; 339 int n; 340 struct snmp_pdu pdu, resp; 341 342 static const struct option opts[] = { 343#define MODIFY_MODE 0 344 { "mode", OPT_STRING, NULL }, 345 { NULL, 0, NULL } 346 }; 347 348 while ((opt = parse_options(&argc, &argv, opts)) != -1) 349 switch (opt) { 350 351 case MODIFY_MODE: 352 if (pparse(&mode, strsunimode, optarg) == -1 || 353 mode == 3) 354 errx(1, "illegal mode for -m '%s'", optarg); 355 break; 356 } 357 358 if (argc != 1) 359 errx(1, "device modify needs one argument"); 360 361 snmp_open(NULL, NULL, NULL, NULL); 362 363 atexit(snmp_close); 364 atmif_fetchtable(); 365 366 if ((aif = atmif_find_name(argv[0])) == NULL) 367 errx(1, "%s: no such ATM interface", argv[0]); 368 369 snmp_pdu_create(&pdu, SNMP_PDU_SET); 370 if (mode != 0) { 371 n = snmp_add_binding(&pdu, 372 &oid_begemotAtmIfMode, SNMP_SYNTAX_INTEGER, 373 NULL); 374 snmp_oid_append(&pdu.bindings[n + 0].var, "i", 375 (asn_subid_t)aif->index); 376 pdu.bindings[n + 0].v.integer = mode; 377 } 378 379 if (pdu.nbindings == 0) 380 errx(1, "must specify something to modify"); 381 382 if (snmp_dialog(&pdu, &resp)) 383 errx(1, "No response from '%s': %s", snmp_client.chost, 384 snmp_client.error); 385 386 if (snmp_pdu_check(&pdu, &resp) <= 0) 387 errx(1, "Error modifying device"); 388 389 snmp_pdu_free(&resp); 390 snmp_pdu_free(&pdu); 391} 392 393/* XXX while this is compiled in */ 394void 395device_register(void) 396{ 397 register_module(&amodule_1); 398} 399 400/* 401 * Fetch the ATM interface table 402 */ 403void 404atmif_fetchtable(void) 405{ 406 struct atmif *aif; 407 408 while ((aif = TAILQ_FIRST(&atmif_list)) != NULL) { 409 free(aif->ifname); 410 free(aif->esi); 411 TAILQ_REMOVE(&atmif_list, aif, link); 412 free(aif); 413 } 414 415 if (snmp_table_fetch(&atmif_table, &atmif_list) != 0) 416 errx(1, "AtmIf table: %s", snmp_client.error); 417} 418 419/* 420 * Find a named ATM interface 421 */ 422struct atmif * 423atmif_find_name(const char *ifname) 424{ 425 struct atmif *atmif; 426 427 TAILQ_FOREACH(atmif, &atmif_list, link) 428 if (strcmp(atmif->ifname, ifname) == 0) 429 return (atmif); 430 return (NULL); 431} 432/* 433 * find an ATM interface by index 434 */ 435struct atmif * 436atmif_find(u_int idx) 437{ 438 struct atmif *atmif; 439 440 TAILQ_FOREACH(atmif, &atmif_list, link) 441 if (atmif->index == (int32_t)idx) 442 return (atmif); 443 return (NULL); 444} 445