1216295Ssyrinx/*- 2216295Ssyrinx * Copyright (c) 2006 The FreeBSD Project 3216295Ssyrinx * All rights reserved. 4216295Ssyrinx * 5216295Ssyrinx * Author: Shteryana Shopova <syrinx@FreeBSD.org> 6216295Ssyrinx * 7216295Ssyrinx * Redistribution of this software and documentation and use in source and 8216295Ssyrinx * binary forms, with or without modification, are permitted provided that 9216295Ssyrinx * the following conditions are met: 10216295Ssyrinx * 11216295Ssyrinx * 1. Redistributions of source code or documentation must retain the above 12216295Ssyrinx * copyright notice, this list of conditions and the following disclaimer. 13216295Ssyrinx * 2. Redistributions in binary form must reproduce the above copyright 14216295Ssyrinx * notice, this list of conditions and the following disclaimer in the 15216295Ssyrinx * documentation and/or other materials provided with the distribution. 16216295Ssyrinx * 17216295Ssyrinx * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18216295Ssyrinx * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19216295Ssyrinx * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20216295Ssyrinx * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21216295Ssyrinx * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22216295Ssyrinx * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23216295Ssyrinx * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24216295Ssyrinx * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25216295Ssyrinx * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26216295Ssyrinx * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27216295Ssyrinx * SUCH DAMAGE. 28216295Ssyrinx * 29216295Ssyrinx * Textual conventions for OctetStrings 30216295Ssyrinx * 31216295Ssyrinx * $FreeBSD: stable/10/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptc.c 311595 2017-01-07 08:46:16Z ngie $ 32216295Ssyrinx */ 33216295Ssyrinx 34310903Sngie#include <sys/param.h> 35216295Ssyrinx#include <sys/queue.h> 36216295Ssyrinx#include <sys/socket.h> 37216295Ssyrinx#include <sys/uio.h> 38216295Ssyrinx 39216295Ssyrinx#include <ctype.h> 40216295Ssyrinx#include <err.h> 41216295Ssyrinx#include <errno.h> 42216295Ssyrinx#include <fcntl.h> 43216295Ssyrinx#include <stdio.h> 44216295Ssyrinx#include <stdlib.h> 45216295Ssyrinx#include <string.h> 46216295Ssyrinx#include <syslog.h> 47216295Ssyrinx#include <unistd.h> 48216295Ssyrinx 49216295Ssyrinx#include <arpa/inet.h> 50216295Ssyrinx#include <netinet/in.h> 51216295Ssyrinx 52216295Ssyrinx#include <bsnmp/asn1.h> 53216295Ssyrinx#include <bsnmp/snmp.h> 54216295Ssyrinx#include "bsnmptc.h" 55216295Ssyrinx#include "bsnmptools.h" 56216295Ssyrinx 57216295Ssyrinx/* OctetString, DisplayString */ 58216295Ssyrinxstatic char *snmp_oct2str(uint32_t, char *, char *); 59216295Ssyrinxstatic char *snmp_str2asn_oid(char *, struct asn_oid *); 60216295Ssyrinxstatic int parse_octetstring(struct snmp_value *, char *); 61216295Ssyrinx 62216295Ssyrinx/* DateAndTime */ 63216295Ssyrinxstatic char *snmp_octstr2date(uint32_t, char *, char *); 64216295Ssyrinxstatic char *snmp_date2asn_oid(char * , struct asn_oid *); 65216295Ssyrinxstatic int parse_dateandtime(struct snmp_value *, char *); 66216295Ssyrinx 67216295Ssyrinx/* PhysAddress */ 68216295Ssyrinxstatic char *snmp_oct2physAddr(uint32_t, char *, char *); 69216295Ssyrinxstatic char *snmp_addr2asn_oid(char *, struct asn_oid *); 70216295Ssyrinxstatic int parse_physaddress(struct snmp_value *, char *); 71216295Ssyrinx 72216295Ssyrinx/* NTPTimeStamp */ 73216295Ssyrinxstatic char *snmp_oct2ntp_ts(uint32_t, char *, char *); 74216295Ssyrinxstatic char *snmp_ntp_ts2asn_oid(char *, struct asn_oid *); 75216295Ssyrinxstatic int parse_ntp_ts(struct snmp_value *, char *); 76216295Ssyrinx 77216295Ssyrinx/* BridgeId */ 78216295Ssyrinxstatic char *snmp_oct2bridgeid(uint32_t, char *, char *); 79216295Ssyrinxstatic char *snmp_bridgeid2oct(char *, struct asn_oid *); 80216295Ssyrinxstatic int parse_bridge_id(struct snmp_value *, char *); 81216295Ssyrinx 82216295Ssyrinx/* BridgePortId */ 83216295Ssyrinxstatic char *snmp_oct2bport_id(uint32_t, char *, char *); 84216295Ssyrinxstatic char *snmp_bport_id2oct(char *, struct asn_oid *); 85216295Ssyrinxstatic int parse_bport_id(struct snmp_value *, char *); 86216295Ssyrinx 87216295Ssyrinx/* InetAddress */ 88216295Ssyrinxstatic char *snmp_oct2inetaddr(uint32_t len, char *octets, char *buf); 89216295Ssyrinxstatic char *snmp_inetaddr2oct(char *str, struct asn_oid *oid); 90216295Ssyrinxstatic int32_t parse_inetaddr(struct snmp_value *value, char *string); 91216295Ssyrinx 92216295Ssyrinxstatic char *snmp_oct2bits(uint32_t len, char *octets, char *buf); 93216295Ssyrinxstatic char *snmp_bits2oct(char *str, struct asn_oid *oid); 94216295Ssyrinxstatic int32_t parse_bits(struct snmp_value *value, char *string); 95216295Ssyrinx 96300471Sngiestatic struct snmp_text_conv { 97216295Ssyrinx enum snmp_tc tc; 98216295Ssyrinx const char *tc_str; 99216295Ssyrinx int32_t len; 100216295Ssyrinx snmp_oct2tc_f oct2tc; 101216295Ssyrinx snmp_tc2oid_f tc2oid; 102216295Ssyrinx snmp_tc2oct_f tc2oct; 103216295Ssyrinx} text_convs[] = { 104216295Ssyrinx { SNMP_STRING, "OctetString", SNMP_VAR_STRSZ, 105216295Ssyrinx snmp_oct2str, snmp_str2asn_oid, parse_octetstring }, 106216295Ssyrinx 107216295Ssyrinx { SNMP_DISPLAYSTRING, "DisplayString" , SNMP_VAR_STRSZ, 108216295Ssyrinx snmp_oct2str, snmp_str2asn_oid, parse_octetstring }, 109216295Ssyrinx 110216295Ssyrinx { SNMP_DATEANDTIME, "DateAndTime", SNMP_DATETIME_STRSZ, 111216295Ssyrinx snmp_octstr2date, snmp_date2asn_oid, parse_dateandtime }, 112216295Ssyrinx 113216295Ssyrinx { SNMP_PHYSADDR, "PhysAddress", SNMP_PHYSADDR_STRSZ, 114216295Ssyrinx snmp_oct2physAddr, snmp_addr2asn_oid, parse_physaddress }, 115216295Ssyrinx 116216295Ssyrinx { SNMP_ATMESI, "AtmESI", SNMP_PHYSADDR_STRSZ, 117216295Ssyrinx snmp_oct2physAddr, snmp_addr2asn_oid, parse_physaddress }, 118216295Ssyrinx 119216295Ssyrinx { SNMP_NTP_TIMESTAMP, "NTPTimeStamp", SNMP_NTP_TS_STRSZ, 120216295Ssyrinx snmp_oct2ntp_ts, snmp_ntp_ts2asn_oid, parse_ntp_ts }, 121216295Ssyrinx 122216295Ssyrinx { SNMP_MACADDRESS, "MacAddress", SNMP_PHYSADDR_STRSZ, 123216295Ssyrinx snmp_oct2physAddr, snmp_addr2asn_oid, parse_physaddress }, 124216295Ssyrinx 125216295Ssyrinx { SNMP_BRIDGE_ID, "BridgeId", SNMP_BRIDGEID_STRSZ, 126216295Ssyrinx snmp_oct2bridgeid, snmp_bridgeid2oct, parse_bridge_id }, 127216295Ssyrinx 128216295Ssyrinx { SNMP_BPORT_ID, "BridgePortId", SNMP_BPORT_STRSZ, 129216295Ssyrinx snmp_oct2bport_id, snmp_bport_id2oct, parse_bport_id }, 130216295Ssyrinx 131216295Ssyrinx { SNMP_INETADDRESS, "InetAddress", SNMP_INADDRS_STRSZ, 132216295Ssyrinx snmp_oct2inetaddr, snmp_inetaddr2oct, parse_inetaddr }, 133216295Ssyrinx 134216295Ssyrinx { SNMP_TC_OWN, "BITS", SNMP_VAR_STRSZ, 135216295Ssyrinx snmp_oct2bits, snmp_bits2oct, parse_bits }, 136216295Ssyrinx 137216295Ssyrinx { SNMP_UNKNOWN, "Unknown", SNMP_VAR_STRSZ, snmp_oct2str, 138216295Ssyrinx snmp_str2asn_oid, parse_octetstring } /* keep last */ 139216295Ssyrinx}; 140216295Ssyrinx 141216295Ssyrinx/* Common API */ 142216295Ssyrinxenum snmp_tc 143216295Ssyrinxsnmp_get_tc(char *str) 144216295Ssyrinx{ 145216295Ssyrinx int i; 146216295Ssyrinx for (i = 0; i < SNMP_UNKNOWN; i++) { 147216295Ssyrinx if (!strncmp(text_convs[i].tc_str, str, 148216295Ssyrinx strlen(text_convs[i].tc_str))) 149216295Ssyrinx return (text_convs[i].tc); 150216295Ssyrinx } 151216295Ssyrinx 152216295Ssyrinx return (SNMP_STRING); 153216295Ssyrinx} 154216295Ssyrinx 155216295Ssyrinxchar * 156216295Ssyrinxsnmp_oct2tc(enum snmp_tc tc, uint32_t len, char *octets) 157216295Ssyrinx{ 158216295Ssyrinx uint32_t tc_len; 159216295Ssyrinx char * buf; 160216295Ssyrinx 161300471Sngie if (tc > SNMP_UNKNOWN) 162216295Ssyrinx tc = SNMP_UNKNOWN; 163216295Ssyrinx 164216295Ssyrinx if (text_convs[tc].len > 0) 165216295Ssyrinx tc_len = text_convs[tc].len; 166216295Ssyrinx else 167216295Ssyrinx tc_len = 2 * len + 3; 168216295Ssyrinx 169216295Ssyrinx if ((buf = malloc(tc_len)) == NULL ) { 170216295Ssyrinx syslog(LOG_ERR, "malloc failed - %s", strerror(errno)); 171216295Ssyrinx return (NULL); 172216295Ssyrinx } 173216295Ssyrinx 174216295Ssyrinx memset(buf, 0, tc_len); 175216295Ssyrinx if (text_convs[tc].oct2tc(len, octets, buf) == NULL) { 176216295Ssyrinx free(buf); 177216295Ssyrinx return (NULL); 178216295Ssyrinx } 179216295Ssyrinx 180216295Ssyrinx return (buf); 181216295Ssyrinx} 182216295Ssyrinx 183216295Ssyrinxchar * 184216295Ssyrinxsnmp_tc2oid(enum snmp_tc tc, char *str, struct asn_oid *oid) 185216295Ssyrinx{ 186300471Sngie if (tc > SNMP_UNKNOWN) 187216295Ssyrinx tc = SNMP_UNKNOWN; 188216295Ssyrinx 189216295Ssyrinx return (text_convs[tc].tc2oid(str, oid)); 190216295Ssyrinx} 191216295Ssyrinx 192216295Ssyrinxint32_t 193216295Ssyrinxsnmp_tc2oct(enum snmp_tc tc, struct snmp_value *value, char *string) 194216295Ssyrinx{ 195300471Sngie if (tc > SNMP_UNKNOWN) 196216295Ssyrinx tc = SNMP_UNKNOWN; 197216295Ssyrinx 198216295Ssyrinx return (text_convs[tc].tc2oct(value, string)); 199216295Ssyrinx} 200216295Ssyrinx 201216295Ssyrinx/***************************************************** 202216295Ssyrinx* Basic OctetString type. 203216295Ssyrinx*/ 204216295Ssyrinxstatic char * 205216295Ssyrinxsnmp_oct2str(uint32_t len, char *octets, char *buf) 206216295Ssyrinx{ 207216295Ssyrinx uint8_t binary = 0; 208216295Ssyrinx uint32_t i; 209216295Ssyrinx char *ptr; 210216295Ssyrinx 211216295Ssyrinx if (len > MAX_OCTSTRING_LEN || octets == NULL || buf == NULL) 212216295Ssyrinx return (NULL); 213216295Ssyrinx 214216295Ssyrinx for (ptr = buf, i = 0; i < len; i++) 215216295Ssyrinx if (!isprint(octets[i])) { 216216295Ssyrinx binary = 1; 217216295Ssyrinx buf += sprintf(buf, "0x"); 218216295Ssyrinx break; 219216295Ssyrinx } 220216295Ssyrinx 221216295Ssyrinx for (ptr = buf, i = 0; i < len; i++) 222216295Ssyrinx if (!binary) 223216295Ssyrinx ptr += sprintf(ptr, "%c", octets[i]); 224216295Ssyrinx else 225216295Ssyrinx ptr += sprintf(ptr, "%2.2x", (u_char)octets[i]); 226216295Ssyrinx 227216295Ssyrinx return (buf); 228216295Ssyrinx} 229216295Ssyrinx 230216295Ssyrinxstatic char * 231216295Ssyrinxsnmp_str2asn_oid(char *str, struct asn_oid *oid) 232216295Ssyrinx{ 233216295Ssyrinx uint32_t i, len = 0; 234216295Ssyrinx 235216295Ssyrinx /* 236216295Ssyrinx * OctetStrings are allowed max length of ASN_MAXOCTETSTRING, 237216295Ssyrinx * but trying to index an entry with such a long OctetString 238216295Ssyrinx * will fail anyway. 239216295Ssyrinx */ 240216295Ssyrinx for (len = 0; len < ASN_MAXOIDLEN; len++) { 241216295Ssyrinx if (strchr(",]", *(str + len)) != NULL) 242216295Ssyrinx break; 243216295Ssyrinx } 244216295Ssyrinx 245216295Ssyrinx if (len >= ASN_MAXOIDLEN) 246216295Ssyrinx return (NULL); 247216295Ssyrinx 248216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) len) < 0) 249216295Ssyrinx return (NULL); 250216295Ssyrinx 251216295Ssyrinx for (i = 0; i < len; i++) 252216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) *(str + i)) < 0) 253216295Ssyrinx return (NULL); 254216295Ssyrinx 255216295Ssyrinx return (str + len); 256216295Ssyrinx} 257216295Ssyrinx 258216295Ssyrinxstatic int32_t 259216295Ssyrinxparse_octetstring(struct snmp_value *value, char *val) 260216295Ssyrinx{ 261216295Ssyrinx size_t len; 262216295Ssyrinx 263216295Ssyrinx if ((len = strlen(val)) >= MAX_OCTSTRING_LEN) { 264216295Ssyrinx warnx("Octetstring too long - %d is max allowed", 265216295Ssyrinx MAX_OCTSTRING_LEN - 1); 266216295Ssyrinx return (-1); 267216295Ssyrinx } 268216295Ssyrinx 269311590Sngie if ((value->v.octetstring.octets = malloc(len)) == NULL) { 270311590Sngie value->v.octetstring.len = 0; 271311595Sngie syslog(LOG_ERR, "malloc failed: %s", strerror(errno)); 272216295Ssyrinx return (-1); 273216295Ssyrinx } 274216295Ssyrinx 275311590Sngie value->v.octetstring.len = len; 276216295Ssyrinx memcpy(value->v.octetstring.octets, val, len); 277216295Ssyrinx value->syntax = SNMP_SYNTAX_OCTETSTRING; 278216295Ssyrinx 279216295Ssyrinx return (0); 280216295Ssyrinx} 281216295Ssyrinx 282216295Ssyrinx/************************************************************* 283216295Ssyrinx * DateAndTime 284216295Ssyrinx ************************************************************* 285216295Ssyrinx * rfc 2579 specification: 286216295Ssyrinx * DateAndTime ::= TEXTUAL-CONVENTION 287216295Ssyrinx * DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d" 288216295Ssyrinx * STATUS current 289216295Ssyrinx * DESCRIPTION 290216295Ssyrinx * "A date-time specification. 291216295Ssyrinx * 292216295Ssyrinx * field octets contents range 293216295Ssyrinx * ----- ------ -------- ----- 294216295Ssyrinx * 1 1-2 year* 0..65536 295216295Ssyrinx * 2 3 month 1..12 296216295Ssyrinx * 3 4 day 1..31 297216295Ssyrinx * 4 5 hour 0..23 298216295Ssyrinx * 5 6 minutes 0..59 299216295Ssyrinx * 6 7 seconds 0..60 300216295Ssyrinx * (use 60 for leap-second) 301216295Ssyrinx * 7 8 deci-seconds 0..9 302216295Ssyrinx * 8 9 direction from UTC '+' / '-' 303216295Ssyrinx * 9 10 hours from UTC* 0..13 304216295Ssyrinx * 10 11 minutes from UTC 0..59 305216295Ssyrinx * 306216295Ssyrinx * * Notes: 307216295Ssyrinx * - the value of year is in network-byte order 308216295Ssyrinx * - daylight saving time in New Zealand is +13 309216295Ssyrinx * 310216295Ssyrinx * For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be 311216295Ssyrinx * displayed as: 312216295Ssyrinx * 313216295Ssyrinx * 1992-5-26,13:30:15.0,-4:0 314216295Ssyrinx */ 315216295Ssyrinxstatic char * 316216295Ssyrinxsnmp_octstr2date(uint32_t len, char *octets, char *buf) 317216295Ssyrinx{ 318216295Ssyrinx int year; 319216295Ssyrinx char *ptr; 320216295Ssyrinx 321216295Ssyrinx if (len != SNMP_DATETIME_OCTETS || octets == NULL || buf == NULL) 322216295Ssyrinx return (NULL); 323216295Ssyrinx 324216295Ssyrinx buf[0]= '\0'; 325216295Ssyrinx year = (octets[0] << 8); 326216295Ssyrinx year += (octets[1]); 327216295Ssyrinx 328216295Ssyrinx ptr = buf; 329216295Ssyrinx ptr += sprintf(ptr, "%4.4d-%.2d-%.2d, ", year, octets[2],octets[3]); 330216295Ssyrinx ptr += sprintf(ptr, "%2.2d:%2.2d:%2.2d.%.2d, ", octets[4],octets[5], 331216295Ssyrinx octets[6],octets[7]); 332216295Ssyrinx ptr += sprintf(ptr, "%c%.2d:%.2d", octets[8],octets[9],octets[10]); 333216295Ssyrinx 334216295Ssyrinx return (buf); 335216295Ssyrinx} 336216295Ssyrinx 337216295Ssyrinxstatic char * 338216295Ssyrinxsnmp_date2asn_oid(char *str, struct asn_oid *oid) 339216295Ssyrinx{ 340216295Ssyrinx char *endptr, *ptr; 341299016Sngie static const char UTC[3] = "UTC"; 342299016Sngie int32_t saved_errno; 343216295Ssyrinx uint32_t v; 344216295Ssyrinx 345216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) SNMP_DATETIME_OCTETS) < 0) 346216295Ssyrinx return (NULL); 347216295Ssyrinx 348216295Ssyrinx /* Read 'YYYY-' and write it in two subs. */ 349216295Ssyrinx ptr = str; 350216295Ssyrinx saved_errno = errno; 351216295Ssyrinx errno = 0; 352216295Ssyrinx v = strtoul(ptr, &endptr, 10); 353216295Ssyrinx if (v > 0xffff) 354216295Ssyrinx goto error; 355216295Ssyrinx else 356216295Ssyrinx errno = saved_errno; 357216295Ssyrinx if (*endptr != '-') 358216295Ssyrinx goto error1; 359216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) ((v & 0xff00) >> 8)) < 0) 360216295Ssyrinx return (NULL); 361216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xff)) < 0) 362216295Ssyrinx return (NULL); 363216295Ssyrinx 364216295Ssyrinx /* 'MM-' */ 365216295Ssyrinx ptr = endptr + 1; 366216295Ssyrinx saved_errno = errno; 367301656Sngie errno = 0; 368216295Ssyrinx v = strtoul(ptr, &endptr, 10); 369216295Ssyrinx if (errno != 0) 370216295Ssyrinx goto error; 371216295Ssyrinx else 372216295Ssyrinx errno = saved_errno; 373216295Ssyrinx if (*endptr != '-') 374216295Ssyrinx goto error1; 375216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 376216295Ssyrinx return (NULL); 377216295Ssyrinx 378216295Ssyrinx /* 'DD,' */ 379216295Ssyrinx ptr = endptr + 1; 380216295Ssyrinx saved_errno = errno; 381301656Sngie errno = 0; 382216295Ssyrinx v = strtoul(ptr, &endptr, 10); 383216295Ssyrinx if (errno != 0) 384216295Ssyrinx goto error; 385216295Ssyrinx else 386216295Ssyrinx errno = saved_errno; 387216295Ssyrinx if (*endptr != '-') 388216295Ssyrinx goto error1; 389216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 390216295Ssyrinx return (NULL); 391216295Ssyrinx 392216295Ssyrinx /* 'HH:' */ 393216295Ssyrinx ptr = endptr + 1; 394216295Ssyrinx saved_errno = errno; 395301656Sngie errno = 0; 396216295Ssyrinx v = strtoul(ptr, &endptr, 10); 397216295Ssyrinx if (errno != 0) 398216295Ssyrinx goto error; 399216295Ssyrinx else 400216295Ssyrinx errno = saved_errno; 401216295Ssyrinx if (*endptr != ':') 402216295Ssyrinx goto error1; 403216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 404216295Ssyrinx return (NULL); 405216295Ssyrinx 406216295Ssyrinx /* 'MM:' */ 407216295Ssyrinx ptr = endptr + 1; 408216295Ssyrinx saved_errno = errno; 409301656Sngie errno = 0; 410216295Ssyrinx v = strtoul(ptr, &endptr, 10); 411216295Ssyrinx if (errno != 0) 412216295Ssyrinx goto error; 413216295Ssyrinx else 414216295Ssyrinx errno = saved_errno; 415216295Ssyrinx if (*endptr != ':') 416216295Ssyrinx goto error1; 417216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 418216295Ssyrinx return (NULL); 419216295Ssyrinx 420216295Ssyrinx /* 'SS.' */ 421216295Ssyrinx ptr = endptr + 1; 422216295Ssyrinx saved_errno = errno; 423301656Sngie errno = 0; 424216295Ssyrinx v = strtoul(ptr, &endptr, 10); 425216295Ssyrinx if (errno != 0) 426216295Ssyrinx goto error; 427216295Ssyrinx else 428216295Ssyrinx errno = saved_errno; 429216295Ssyrinx if (*endptr != '.') 430216295Ssyrinx goto error1; 431216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 432216295Ssyrinx return (NULL); 433216295Ssyrinx 434216295Ssyrinx /* 'M(mseconds),' */ 435216295Ssyrinx ptr = endptr + 1; 436216295Ssyrinx saved_errno = errno; 437301656Sngie errno = 0; 438216295Ssyrinx v = strtoul(ptr, &endptr, 10); 439216295Ssyrinx if (errno != 0) 440216295Ssyrinx goto error; 441216295Ssyrinx else 442216295Ssyrinx errno = saved_errno; 443216295Ssyrinx if (*endptr != ',') 444216295Ssyrinx goto error1; 445216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 446216295Ssyrinx return (NULL); 447216295Ssyrinx 448216295Ssyrinx /* 'UTC' - optional */ 449216295Ssyrinx ptr = endptr + 1; 450299016Sngie if (strncmp(ptr, UTC, sizeof(UTC)) == 0) 451299016Sngie ptr += sizeof(UTC); 452216295Ssyrinx 453216295Ssyrinx /* '+/-' */ 454216295Ssyrinx if (*ptr == '-' || *ptr == '+') { 455216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) (*ptr)) < 0) 456216295Ssyrinx return (NULL); 457216295Ssyrinx } else 458216295Ssyrinx goto error1; 459216295Ssyrinx 460216295Ssyrinx /* 'HH:' */ 461216295Ssyrinx ptr = endptr + 1; 462216295Ssyrinx saved_errno = errno; 463301656Sngie errno = 0; 464216295Ssyrinx v = strtoul(ptr, &endptr, 10); 465216295Ssyrinx if (errno != 0) 466216295Ssyrinx goto error; 467216295Ssyrinx else 468216295Ssyrinx errno = saved_errno; 469216295Ssyrinx if (*endptr != ':') 470216295Ssyrinx goto error1; 471216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 472216295Ssyrinx return (NULL); 473216295Ssyrinx 474216295Ssyrinx /* 'MM' - last one - ignore endptr here. */ 475216295Ssyrinx ptr = endptr + 1; 476216295Ssyrinx saved_errno = errno; 477301656Sngie errno = 0; 478216295Ssyrinx v = strtoul(ptr, &endptr, 10); 479216295Ssyrinx if (errno != 0) 480216295Ssyrinx goto error; 481216295Ssyrinx else 482216295Ssyrinx errno = saved_errno; 483216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 484216295Ssyrinx return (NULL); 485216295Ssyrinx 486216295Ssyrinx return (endptr); 487216295Ssyrinx 488216295Ssyrinx error: 489216295Ssyrinx errno = saved_errno; 490216295Ssyrinx error1: 491216295Ssyrinx warnx("Date value %s not supported", str); 492216295Ssyrinx return (NULL); 493216295Ssyrinx} 494216295Ssyrinx 495216295Ssyrinx/* Read a DateAndTime string eg. 1992-5-26,13:30:15.0,-4:0. */ 496216295Ssyrinxstatic int32_t 497216295Ssyrinxparse_dateandtime(struct snmp_value *sv, char *val) 498216295Ssyrinx{ 499216295Ssyrinx char *endptr; 500216295Ssyrinx uint32_t v; 501216295Ssyrinx uint8_t date[SNMP_DATETIME_OCTETS]; 502216295Ssyrinx 503216295Ssyrinx /* 'YYYY-' */ 504216295Ssyrinx v = strtoul(val, &endptr, 10); 505216295Ssyrinx if (v > 0xffff || *endptr != '-') 506216295Ssyrinx goto error; 507216295Ssyrinx date[0] = ((v & 0xff00) >> 8); 508216295Ssyrinx date[1] = (v & 0xff); 509216295Ssyrinx val = endptr + 1; 510216295Ssyrinx 511216295Ssyrinx /* 'MM-' */ 512216295Ssyrinx v = strtoul(val, &endptr, 10); 513216295Ssyrinx if (v == 0 || v > 12 || *endptr != '-') 514216295Ssyrinx goto error; 515216295Ssyrinx date[2] = v; 516216295Ssyrinx val = endptr + 1; 517216295Ssyrinx 518216295Ssyrinx /* 'DD,' */ 519216295Ssyrinx v = strtoul(val, &endptr, 10); 520216295Ssyrinx if (v == 0 || v > 31 || *endptr != ',') 521216295Ssyrinx goto error; 522216295Ssyrinx date[3] = v; 523216295Ssyrinx val = endptr + 1; 524216295Ssyrinx 525216295Ssyrinx /* 'HH:' */ 526216295Ssyrinx v = strtoul(val, &endptr, 10); 527216295Ssyrinx if (v > 23 || *endptr != ':') 528216295Ssyrinx goto error; 529216295Ssyrinx date[4] = v; 530216295Ssyrinx val = endptr + 1; 531216295Ssyrinx 532216295Ssyrinx /* 'MM:' */ 533216295Ssyrinx v = strtoul(val, &endptr, 10); 534216295Ssyrinx if (v > 59 || *endptr != ':') 535216295Ssyrinx goto error; 536216295Ssyrinx date[5] = v; 537216295Ssyrinx val = endptr + 1; 538216295Ssyrinx 539216295Ssyrinx /* 'SS.' */ 540216295Ssyrinx v = strtoul(val, &endptr, 10); 541216295Ssyrinx if (v > 60 || *endptr != '.') 542216295Ssyrinx goto error; 543216295Ssyrinx date[6] = v; 544216295Ssyrinx val = endptr + 1; 545216295Ssyrinx 546216295Ssyrinx /* '(deci-)s,' */ 547216295Ssyrinx v = strtoul(val, &endptr, 10); 548216295Ssyrinx if (v > 9 || *endptr != ',') 549216295Ssyrinx goto error; 550216295Ssyrinx date[7] = v; 551216295Ssyrinx val = endptr + 1; 552216295Ssyrinx 553216295Ssyrinx /* offset - '+/-' */ 554216295Ssyrinx if (*val != '-' && *val != '+') 555216295Ssyrinx goto error; 556216295Ssyrinx date[8] = (uint8_t) *val; 557216295Ssyrinx val = endptr + 1; 558216295Ssyrinx 559216295Ssyrinx /* 'HH:' - offset from UTC */ 560216295Ssyrinx v = strtoul(val, &endptr, 10); 561216295Ssyrinx if (v > 13 || *endptr != ':') 562216295Ssyrinx goto error; 563216295Ssyrinx date[9] = v; 564216295Ssyrinx val = endptr + 1; 565216295Ssyrinx 566216295Ssyrinx /* 'MM'\0'' offset from UTC */ 567216295Ssyrinx v = strtoul(val, &endptr, 10); 568216295Ssyrinx if (v > 59 || *endptr != '\0') 569216295Ssyrinx goto error; 570216295Ssyrinx date[10] = v; 571216295Ssyrinx 572216295Ssyrinx if ((sv->v.octetstring.octets = malloc(SNMP_DATETIME_OCTETS)) == NULL) { 573311595Sngie warn("malloc() failed"); 574216295Ssyrinx return (-1); 575216295Ssyrinx } 576216295Ssyrinx 577216295Ssyrinx sv->v.octetstring.len = SNMP_DATETIME_OCTETS; 578216295Ssyrinx memcpy(sv->v.octetstring.octets, date, SNMP_DATETIME_OCTETS); 579216295Ssyrinx sv->syntax = SNMP_SYNTAX_OCTETSTRING; 580216295Ssyrinx return (1); 581216295Ssyrinx 582216295Ssyrinx error: 583216295Ssyrinx warnx("Date value %s not supported", val); 584216295Ssyrinx return (-1); 585216295Ssyrinx} 586216295Ssyrinx 587216295Ssyrinx/************************************************************** 588216295Ssyrinx * PhysAddress 589216295Ssyrinx */ 590216295Ssyrinxstatic char * 591216295Ssyrinxsnmp_oct2physAddr(uint32_t len, char *octets, char *buf) 592216295Ssyrinx{ 593216295Ssyrinx char *ptr; 594216295Ssyrinx uint32_t i; 595216295Ssyrinx 596216295Ssyrinx if (len != SNMP_PHYSADDR_OCTETS || octets == NULL || buf == NULL) 597216295Ssyrinx return (NULL); 598216295Ssyrinx 599216295Ssyrinx buf[0]= '\0'; 600216295Ssyrinx 601216295Ssyrinx ptr = buf; 602216295Ssyrinx ptr += sprintf(ptr, "%2.2x", octets[0]); 603216295Ssyrinx for (i = 1; i < 6; i++) 604216295Ssyrinx ptr += sprintf(ptr, ":%2.2x", octets[i]); 605216295Ssyrinx 606216295Ssyrinx return (buf); 607216295Ssyrinx} 608216295Ssyrinx 609216295Ssyrinxstatic char * 610216295Ssyrinxsnmp_addr2asn_oid(char *str, struct asn_oid *oid) 611216295Ssyrinx{ 612216295Ssyrinx char *endptr, *ptr; 613216295Ssyrinx uint32_t v, i; 614216295Ssyrinx int saved_errno; 615216295Ssyrinx 616216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) SNMP_PHYSADDR_OCTETS) < 0) 617216295Ssyrinx return (NULL); 618216295Ssyrinx 619216295Ssyrinx ptr = str; 620216295Ssyrinx for (i = 0; i < 5; i++) { 621216295Ssyrinx saved_errno = errno; 622216295Ssyrinx v = strtoul(ptr, &endptr, 16); 623216295Ssyrinx errno = saved_errno; 624216295Ssyrinx if (v > 0xff) { 625216295Ssyrinx warnx("Integer value %s not supported", str); 626216295Ssyrinx return (NULL); 627216295Ssyrinx } 628216295Ssyrinx if (*endptr != ':') { 629311595Sngie warnx("Failed adding oid - %s", str); 630216295Ssyrinx return (NULL); 631216295Ssyrinx } 632216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 633216295Ssyrinx return (NULL); 634216295Ssyrinx ptr = endptr + 1; 635216295Ssyrinx } 636216295Ssyrinx 637216295Ssyrinx /* The last one - don't check the ending char here. */ 638216295Ssyrinx saved_errno = errno; 639216295Ssyrinx v = strtoul(ptr, &endptr, 16); 640216295Ssyrinx errno = saved_errno; 641216295Ssyrinx if (v > 0xff) { 642216295Ssyrinx warnx("Integer value %s not supported", str); 643216295Ssyrinx return (NULL); 644216295Ssyrinx } 645216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 646216295Ssyrinx return (NULL); 647216295Ssyrinx 648216295Ssyrinx return (endptr); 649216295Ssyrinx} 650216295Ssyrinx 651216295Ssyrinxstatic int32_t 652216295Ssyrinxparse_physaddress(struct snmp_value *sv, char *val) 653216295Ssyrinx{ 654216295Ssyrinx char *endptr; 655216295Ssyrinx int32_t i; 656216295Ssyrinx uint32_t v; 657216295Ssyrinx uint8_t phys_addr[SNMP_PHYSADDR_OCTETS]; 658216295Ssyrinx 659216295Ssyrinx for (i = 0; i < 5; i++) { 660216295Ssyrinx v = strtoul(val, &endptr, 16); 661216295Ssyrinx if (v > 0xff) { 662216295Ssyrinx warnx("Integer value %s not supported", val); 663216295Ssyrinx return (-1); 664216295Ssyrinx } 665216295Ssyrinx if(*endptr != ':') { 666216295Ssyrinx warnx("Failed reading octet - %s", val); 667216295Ssyrinx return (-1); 668216295Ssyrinx } 669216295Ssyrinx phys_addr[i] = v; 670216295Ssyrinx val = endptr + 1; 671216295Ssyrinx } 672216295Ssyrinx 673216295Ssyrinx /* The last one - don't check the ending char here. */ 674216295Ssyrinx v = strtoul(val, &endptr, 16); 675216295Ssyrinx if (v > 0xff) { 676216295Ssyrinx warnx("Integer value %s not supported", val); 677216295Ssyrinx return (-1); 678216295Ssyrinx } 679216295Ssyrinx phys_addr[5] = v; 680216295Ssyrinx 681216295Ssyrinx if ((sv->v.octetstring.octets = malloc(SNMP_PHYSADDR_OCTETS)) == NULL) { 682311595Sngie syslog(LOG_ERR, "malloc failed: %s", strerror(errno)); 683216295Ssyrinx return (-1); 684216295Ssyrinx } 685216295Ssyrinx 686216295Ssyrinx sv->v.octetstring.len = SNMP_PHYSADDR_OCTETS; 687216295Ssyrinx memcpy(sv->v.octetstring.octets, phys_addr, SNMP_PHYSADDR_OCTETS); 688216295Ssyrinx sv->syntax = SNMP_SYNTAX_OCTETSTRING; 689216295Ssyrinx return (1); 690216295Ssyrinx} 691216295Ssyrinx 692216295Ssyrinx/************************************************************** 693216295Ssyrinx * NTPTimeStamp 694216295Ssyrinx ************************************************************** 695216295Ssyrinx * NTP MIB, Revision 0.2, 7/25/97: 696216295Ssyrinx * NTPTimeStamp ::= TEXTUAL-CONVENTION 697216295Ssyrinx * DISPLAY-HINT "4x.4x" 698216295Ssyrinx * STATUS current 699216295Ssyrinx * DESCRIPTION 700216295Ssyrinx * "" 701216295Ssyrinx * SYNTAX OCTET STRING (SIZE(8)) 702216295Ssyrinx */ 703216295Ssyrinxstatic char * 704216295Ssyrinxsnmp_oct2ntp_ts(uint32_t len, char *octets, char *buf) 705216295Ssyrinx{ 706216295Ssyrinx char *ptr; 707216295Ssyrinx uint32_t i; 708216295Ssyrinx 709216295Ssyrinx if (len != SNMP_NTP_TS_OCTETS || octets == NULL || buf == NULL) 710216295Ssyrinx return (NULL); 711216295Ssyrinx 712216295Ssyrinx buf[0]= '\0'; 713216295Ssyrinx 714216295Ssyrinx ptr = buf; 715216295Ssyrinx i = octets[0] * 1000 + octets[1] * 100 + octets[2] * 10 + octets[3]; 716216295Ssyrinx ptr += sprintf(ptr, "%4.4d", i); 717216295Ssyrinx i = octets[4] * 1000 + octets[5] * 100 + octets[6] * 10 + octets[7]; 718216295Ssyrinx ptr += sprintf(ptr, ".%4.4d", i); 719216295Ssyrinx 720216295Ssyrinx return (buf); 721216295Ssyrinx} 722216295Ssyrinx 723216295Ssyrinxstatic char * 724216295Ssyrinxsnmp_ntp_ts2asn_oid(char *str, struct asn_oid *oid) 725216295Ssyrinx{ 726216295Ssyrinx char *endptr, *ptr; 727216295Ssyrinx uint32_t v, i, d; 728216295Ssyrinx struct asn_oid suboid; 729216295Ssyrinx int saved_errno; 730216295Ssyrinx 731216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) SNMP_NTP_TS_OCTETS) < 0) 732216295Ssyrinx return (NULL); 733216295Ssyrinx 734216295Ssyrinx ptr = str; 735216295Ssyrinx saved_errno = errno; 736301656Sngie errno = 0; 737216295Ssyrinx v = strtoul(ptr, &endptr, 10); 738216295Ssyrinx if (errno != 0 || (v / 1000) > 9) { 739216295Ssyrinx warnx("Integer value %s not supported", str); 740216295Ssyrinx errno = saved_errno; 741216295Ssyrinx return (NULL); 742216295Ssyrinx } else 743216295Ssyrinx errno = saved_errno; 744216295Ssyrinx 745216295Ssyrinx if (*endptr != '.') { 746311595Sngie warnx("Failed adding oid - %s", str); 747216295Ssyrinx return (NULL); 748216295Ssyrinx } 749216295Ssyrinx 750216295Ssyrinx memset(&suboid, 0, sizeof(struct asn_oid)); 751216295Ssyrinx suboid.len = SNMP_NTP_TS_OCTETS; 752216295Ssyrinx 753216295Ssyrinx for (i = 0, d = 1000; i < 4; i++) { 754216295Ssyrinx suboid.subs[i] = v / d; 755216295Ssyrinx v = v % d; 756216295Ssyrinx d = d / 10; 757216295Ssyrinx } 758216295Ssyrinx 759216295Ssyrinx ptr = endptr + 1; 760216295Ssyrinx saved_errno = errno; 761301656Sngie errno = 0; 762216295Ssyrinx v = strtoul(ptr, &endptr, 10); 763216295Ssyrinx if (errno != 0 || (v / 1000) > 9) { 764216295Ssyrinx warnx("Integer value %s not supported", str); 765216295Ssyrinx errno = saved_errno; 766216295Ssyrinx return (NULL); 767216295Ssyrinx } else 768216295Ssyrinx errno = saved_errno; 769216295Ssyrinx 770216295Ssyrinx for (i = 0, d = 1000; i < 4; i++) { 771216295Ssyrinx suboid.subs[i + 4] = v / d; 772216295Ssyrinx v = v % d; 773216295Ssyrinx d = d / 10; 774216295Ssyrinx } 775216295Ssyrinx 776216295Ssyrinx asn_append_oid(oid, &suboid); 777216295Ssyrinx return (endptr); 778216295Ssyrinx} 779216295Ssyrinx 780216295Ssyrinxstatic int32_t 781216295Ssyrinxparse_ntp_ts(struct snmp_value *sv, char *val) 782216295Ssyrinx{ 783216295Ssyrinx char *endptr; 784216295Ssyrinx int32_t i, d, saved_errno; 785216295Ssyrinx uint32_t v; 786216295Ssyrinx uint8_t ntp_ts[SNMP_NTP_TS_OCTETS]; 787216295Ssyrinx 788216295Ssyrinx saved_errno = errno; 789301656Sngie errno = 0; 790216295Ssyrinx v = strtoul(val, &endptr, 10); 791216295Ssyrinx if (errno != 0 || (v / 1000) > 9) { 792300559Sngie errno = saved_errno; 793216295Ssyrinx warnx("Integer value %s not supported", val); 794216295Ssyrinx return (-1); 795216295Ssyrinx } else 796300559Sngie errno = saved_errno; 797216295Ssyrinx 798216295Ssyrinx if (*endptr != '.') { 799216295Ssyrinx warnx("Failed reading octet - %s", val); 800216295Ssyrinx return (-1); 801216295Ssyrinx } 802216295Ssyrinx 803216295Ssyrinx for (i = 0, d = 1000; i < 4; i++) { 804216295Ssyrinx ntp_ts[i] = v / d; 805216295Ssyrinx v = v % d; 806216295Ssyrinx d = d / 10; 807216295Ssyrinx } 808216295Ssyrinx val = endptr + 1; 809216295Ssyrinx 810216295Ssyrinx saved_errno = errno; 811301656Sngie errno = 0; 812216295Ssyrinx v = strtoul(val, &endptr, 10); 813216295Ssyrinx if (errno != 0 || (v / 1000) > 9) { 814300559Sngie errno = saved_errno; 815216295Ssyrinx warnx("Integer value %s not supported", val); 816216295Ssyrinx return (-1); 817216295Ssyrinx } else 818300559Sngie errno = saved_errno; 819216295Ssyrinx 820216295Ssyrinx for (i = 0, d = 1000; i < 4; i++) { 821216295Ssyrinx ntp_ts[i + 4] = v / d; 822216295Ssyrinx v = v % d; 823216295Ssyrinx d = d / 10; 824216295Ssyrinx } 825216295Ssyrinx 826216295Ssyrinx if ((sv->v.octetstring.octets = malloc(SNMP_NTP_TS_OCTETS)) == NULL) { 827311595Sngie syslog(LOG_ERR, "malloc failed: %s", strerror(errno)); 828216295Ssyrinx return (-1); 829216295Ssyrinx } 830216295Ssyrinx 831216295Ssyrinx sv->v.octetstring.len = SNMP_NTP_TS_OCTETS; 832216295Ssyrinx memcpy(sv->v.octetstring.octets, ntp_ts, SNMP_NTP_TS_OCTETS); 833216295Ssyrinx sv->syntax = SNMP_SYNTAX_OCTETSTRING; 834216295Ssyrinx return (1); 835216295Ssyrinx} 836216295Ssyrinx 837216295Ssyrinx/************************************************************** 838216295Ssyrinx * BridgeId 839216295Ssyrinx ************************************************************** 840216295Ssyrinx * BRIDGE-MIB, REVISION "200509190000Z" 841216295Ssyrinx * BridgeId ::= TEXTUAL-CONVENTION 842216295Ssyrinx * STATUS current 843216295Ssyrinx * DESCRIPTION 844216295Ssyrinx * "The Bridge-Identifier, as used in the Spanning Tree 845216295Ssyrinx * Protocol, to uniquely identify a bridge. Its first two 846216295Ssyrinx * octets (in network byte order) contain a priority value, 847216295Ssyrinx * and its last 6 octets contain the MAC address used to 848216295Ssyrinx * refer to a bridge in a unique fashion (typically, the 849216295Ssyrinx * numerically smallest MAC address of all ports on the 850216295Ssyrinx * bridge)." 851216295Ssyrinx * SYNTAX OCTET STRING (SIZE (8)) 852216295Ssyrinx */ 853216295Ssyrinxstatic char * 854216295Ssyrinxsnmp_oct2bridgeid(uint32_t len, char *octets, char *buf) 855216295Ssyrinx{ 856216295Ssyrinx char *ptr; 857216295Ssyrinx uint32_t i, priority; 858216295Ssyrinx 859216295Ssyrinx if (len != SNMP_BRIDGEID_OCTETS || octets == NULL || buf == NULL) 860216295Ssyrinx return (NULL); 861216295Ssyrinx 862216295Ssyrinx buf[0]= '\0'; 863216295Ssyrinx ptr = buf; 864216295Ssyrinx 865216295Ssyrinx priority = octets[0] << 8; 866216295Ssyrinx priority += octets[1]; 867216295Ssyrinx if (priority > SNMP_MAX_BRIDGE_PRIORITY) { 868216295Ssyrinx warnx("Invalid bridge priority %d", priority); 869216295Ssyrinx return (NULL); 870216295Ssyrinx } else 871216295Ssyrinx ptr += sprintf(ptr, "%d.", octets[0]); 872216295Ssyrinx 873216295Ssyrinx ptr += sprintf(ptr, "%2.2x", octets[2]); 874216295Ssyrinx 875216295Ssyrinx for (i = 1; i < 6; i++) 876216295Ssyrinx ptr += sprintf(ptr, ":%2.2x", octets[i + 2]); 877216295Ssyrinx 878216295Ssyrinx return (buf); 879216295Ssyrinx} 880216295Ssyrinx 881216295Ssyrinxstatic char * 882216295Ssyrinxsnmp_bridgeid2oct(char *str, struct asn_oid *oid) 883216295Ssyrinx{ 884216295Ssyrinx char *endptr, *ptr; 885216295Ssyrinx uint32_t v, i; 886216295Ssyrinx int32_t saved_errno; 887216295Ssyrinx 888216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) SNMP_BRIDGEID_OCTETS) < 0) 889216295Ssyrinx return (NULL); 890216295Ssyrinx 891216295Ssyrinx ptr = str; 892216295Ssyrinx /* Read the priority. */ 893216295Ssyrinx saved_errno = errno; 894301656Sngie errno = 0; 895216295Ssyrinx v = strtoul(ptr, &endptr, 10); 896216295Ssyrinx 897216295Ssyrinx if (v > SNMP_MAX_BRIDGE_PRIORITY || errno != 0 || *endptr != '.') { 898216295Ssyrinx errno = saved_errno; 899216295Ssyrinx warnx("Bad bridge priority value %d", v); 900216295Ssyrinx return (NULL); 901216295Ssyrinx } 902216295Ssyrinx 903216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xff00)) < 0) 904216295Ssyrinx return (NULL); 905216295Ssyrinx 906216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xff)) < 0) 907216295Ssyrinx return (NULL); 908216295Ssyrinx 909216295Ssyrinx ptr = endptr + 1; 910216295Ssyrinx for (i = 0; i < 5; i++) { 911216295Ssyrinx saved_errno = errno; 912301656Sngie errno = 0; 913216295Ssyrinx v = strtoul(ptr, &endptr, 16); 914216295Ssyrinx errno = saved_errno; 915216295Ssyrinx if (v > 0xff) { 916216295Ssyrinx warnx("Integer value %s not supported", str); 917216295Ssyrinx return (NULL); 918216295Ssyrinx } 919216295Ssyrinx if (*endptr != ':') { 920216295Ssyrinx warnx("Failed adding oid - %s",str); 921216295Ssyrinx return (NULL); 922216295Ssyrinx } 923216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 924216295Ssyrinx return (NULL); 925216295Ssyrinx ptr = endptr + 1; 926216295Ssyrinx } 927216295Ssyrinx 928216295Ssyrinx /* The last one - don't check the ending char here. */ 929216295Ssyrinx saved_errno = errno; 930301656Sngie errno = 0; 931216295Ssyrinx v = strtoul(ptr, &endptr, 16); 932216295Ssyrinx errno = saved_errno; 933216295Ssyrinx if (v > 0xff) { 934216295Ssyrinx warnx("Integer value %s not supported", str); 935216295Ssyrinx return (NULL); 936216295Ssyrinx } 937216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 938216295Ssyrinx return (NULL); 939216295Ssyrinx 940216295Ssyrinx return (endptr); 941216295Ssyrinx} 942216295Ssyrinx 943216295Ssyrinxstatic int32_t 944216295Ssyrinxparse_bridge_id(struct snmp_value *sv, char *string) 945216295Ssyrinx{ 946300471Sngie char *endptr; 947216295Ssyrinx int32_t i, saved_errno; 948216295Ssyrinx uint32_t v; 949216295Ssyrinx uint8_t bridge_id[SNMP_BRIDGEID_OCTETS]; 950216295Ssyrinx 951216295Ssyrinx /* Read the priority. */ 952216295Ssyrinx saved_errno = errno; 953216295Ssyrinx errno = 0; 954216295Ssyrinx v = strtoul(string, &endptr, 10); 955216295Ssyrinx 956216295Ssyrinx if (v > SNMP_MAX_BRIDGE_PRIORITY || errno != 0 || *endptr != '.') { 957216295Ssyrinx errno = saved_errno; 958216295Ssyrinx warnx("Bad bridge priority value %d", v); 959216295Ssyrinx return (-1); 960216295Ssyrinx } 961216295Ssyrinx 962216295Ssyrinx bridge_id[0] = (v & 0xff00); 963216295Ssyrinx bridge_id[1] = (v & 0xff); 964216295Ssyrinx 965216295Ssyrinx string = endptr + 1; 966216295Ssyrinx 967216295Ssyrinx for (i = 0; i < 5; i++) { 968216295Ssyrinx v = strtoul(string, &endptr, 16); 969216295Ssyrinx if (v > 0xff) { 970216295Ssyrinx warnx("Integer value %s not supported", string); 971216295Ssyrinx return (-1); 972216295Ssyrinx } 973216295Ssyrinx if(*endptr != ':') { 974216295Ssyrinx warnx("Failed reading octet - %s", string); 975216295Ssyrinx return (-1); 976216295Ssyrinx } 977216295Ssyrinx bridge_id[i + 2] = v; 978216295Ssyrinx string = endptr + 1; 979216295Ssyrinx } 980216295Ssyrinx 981216295Ssyrinx /* The last one - don't check the ending char here. */ 982216295Ssyrinx v = strtoul(string, &endptr, 16); 983216295Ssyrinx if (v > 0xff) { 984216295Ssyrinx warnx("Integer value %s not supported", string); 985216295Ssyrinx return (-1); 986216295Ssyrinx } 987216295Ssyrinx bridge_id[7] = v; 988216295Ssyrinx 989216295Ssyrinx if ((sv->v.octetstring.octets = malloc(SNMP_BRIDGEID_OCTETS)) == NULL) { 990311595Sngie syslog(LOG_ERR, "malloc failed: %s", strerror(errno)); 991216295Ssyrinx return (-1); 992216295Ssyrinx } 993216295Ssyrinx 994216295Ssyrinx sv->v.octetstring.len = SNMP_BRIDGEID_OCTETS; 995216295Ssyrinx memcpy(sv->v.octetstring.octets, bridge_id, SNMP_BRIDGEID_OCTETS); 996216295Ssyrinx sv->syntax = SNMP_SYNTAX_OCTETSTRING; 997216295Ssyrinx return (1); 998216295Ssyrinx} 999216295Ssyrinx 1000216295Ssyrinx/************************************************************** 1001216295Ssyrinx * BridgePortId 1002216295Ssyrinx ************************************************************** 1003216295Ssyrinx * BEGEMOT-BRIDGE-MIB, LAST-UPDATED "200608100000Z" 1004216295Ssyrinx * BridgePortId ::= TEXTUAL-CONVENTION 1005216295Ssyrinx * DISPLAY-HINT "1x.1x" 1006216295Ssyrinx * STATUS current 1007216295Ssyrinx * DESCRIPTION 1008216295Ssyrinx * "A port identifier that contains a bridge port's STP priority 1009216295Ssyrinx * in the first octet and the port number in the second octet." 1010216295Ssyrinx * SYNTAX OCTET STRING (SIZE(2)) 1011216295Ssyrinx */ 1012216295Ssyrinxstatic char * 1013216295Ssyrinxsnmp_oct2bport_id(uint32_t len, char *octets, char *buf) 1014216295Ssyrinx{ 1015216295Ssyrinx char *ptr; 1016216295Ssyrinx 1017216295Ssyrinx if (len != SNMP_BPORT_OCTETS || octets == NULL || buf == NULL) 1018216295Ssyrinx return (NULL); 1019216295Ssyrinx 1020216295Ssyrinx buf[0]= '\0'; 1021216295Ssyrinx ptr = buf; 1022216295Ssyrinx 1023216295Ssyrinx ptr += sprintf(ptr, "%d.", octets[0]); 1024216295Ssyrinx ptr += sprintf(ptr, "%d", octets[1]); 1025216295Ssyrinx 1026216295Ssyrinx return (buf); 1027216295Ssyrinx} 1028216295Ssyrinx 1029216295Ssyrinxstatic char * 1030216295Ssyrinxsnmp_bport_id2oct(char *str, struct asn_oid *oid) 1031216295Ssyrinx{ 1032216295Ssyrinx char *endptr, *ptr; 1033216295Ssyrinx uint32_t v; 1034216295Ssyrinx int saved_errno; 1035216295Ssyrinx 1036216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) SNMP_BPORT_OCTETS) < 0) 1037216295Ssyrinx return (NULL); 1038216295Ssyrinx 1039216295Ssyrinx ptr = str; 1040216295Ssyrinx /* Read the priority. */ 1041216295Ssyrinx saved_errno = errno; 1042301656Sngie errno = 0; 1043216295Ssyrinx v = strtoul(ptr, &endptr, 10); 1044216295Ssyrinx 1045216295Ssyrinx if (v > SNMP_MAX_BPORT_PRIORITY || errno != 0 || *endptr != '.') { 1046216295Ssyrinx errno = saved_errno; 1047216295Ssyrinx warnx("Bad bridge port priority value %d", v); 1048216295Ssyrinx return (NULL); 1049216295Ssyrinx } 1050216295Ssyrinx 1051216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1052216295Ssyrinx return (NULL); 1053216295Ssyrinx 1054216295Ssyrinx saved_errno = errno; 1055301656Sngie errno = 0; 1056216295Ssyrinx v = strtoul(ptr, &endptr, 16); 1057216295Ssyrinx errno = saved_errno; 1058216295Ssyrinx 1059216295Ssyrinx if (v > 0xff) { 1060216295Ssyrinx warnx("Bad port number - %d", v); 1061216295Ssyrinx return (NULL); 1062216295Ssyrinx } 1063216295Ssyrinx 1064216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) v) < 0) 1065216295Ssyrinx return (NULL); 1066216295Ssyrinx 1067216295Ssyrinx return (endptr); 1068216295Ssyrinx} 1069216295Ssyrinx 1070216295Ssyrinxstatic int32_t 1071216295Ssyrinxparse_bport_id(struct snmp_value *value, char *string) 1072216295Ssyrinx{ 1073300471Sngie char *endptr; 1074216295Ssyrinx int saved_errno; 1075216295Ssyrinx uint32_t v; 1076216295Ssyrinx uint8_t bport_id[SNMP_BPORT_OCTETS]; 1077216295Ssyrinx 1078216295Ssyrinx /* Read the priority. */ 1079216295Ssyrinx saved_errno = errno; 1080216295Ssyrinx errno = 0; 1081216295Ssyrinx v = strtoul(string, &endptr, 10); 1082216295Ssyrinx 1083216295Ssyrinx if (v > SNMP_MAX_BPORT_PRIORITY || errno != 0 || *endptr != '.') { 1084216295Ssyrinx errno = saved_errno; 1085216295Ssyrinx warnx("Bad bridge port priority value %d", v); 1086216295Ssyrinx return (-1); 1087216295Ssyrinx } 1088216295Ssyrinx 1089216295Ssyrinx bport_id[0] = v; 1090216295Ssyrinx 1091216295Ssyrinx string = endptr + 1; 1092216295Ssyrinx v = strtoul(string, &endptr, 16); 1093216295Ssyrinx if (v > 0xff) { 1094216295Ssyrinx warnx("Bad port number - %d", v); 1095216295Ssyrinx return (-1); 1096216295Ssyrinx } 1097216295Ssyrinx 1098216295Ssyrinx bport_id[1] = v; 1099216295Ssyrinx 1100216295Ssyrinx if ((value->v.octetstring.octets = malloc(SNMP_BPORT_OCTETS)) == NULL) { 1101311595Sngie syslog(LOG_ERR, "malloc failed: %s", strerror(errno)); 1102216295Ssyrinx return (-1); 1103216295Ssyrinx } 1104216295Ssyrinx 1105216295Ssyrinx value->v.octetstring.len = SNMP_BPORT_OCTETS; 1106216295Ssyrinx memcpy(value->v.octetstring.octets, bport_id, SNMP_BPORT_OCTETS); 1107216295Ssyrinx value->syntax = SNMP_SYNTAX_OCTETSTRING; 1108216295Ssyrinx return (1); 1109216295Ssyrinx} 1110216295Ssyrinx/************************************************************** 1111216295Ssyrinx * InetAddress 1112216295Ssyrinx ************************************************************** 1113216295Ssyrinx * INET-ADDRESS-MIB, REVISION "200502040000Z" 1114216295Ssyrinx * InetAddress ::= TEXTUAL-CONVENTION 1115216295Ssyrinx * STATUS current 1116216295Ssyrinx * DESCRIPTION 1117216295Ssyrinx * "Denotes a generic Internet address. 1118216295Ssyrinx * 1119216295Ssyrinx * An InetAddress value is always interpreted within the context 1120216295Ssyrinx * of an InetAddressType value. Every usage of the InetAddress 1121216295Ssyrinx * textual convention is required to specify the InetAddressType 1122216295Ssyrinx * object that provides the context. It is suggested that the 1123216295Ssyrinx * InetAddressType object be logically registered before the 1124216295Ssyrinx * object(s) that use the InetAddress textual convention, if 1125216295Ssyrinx * they appear in the same logical row. 1126216295Ssyrinx * 1127216295Ssyrinx * The value of an InetAddress object must always be 1128216295Ssyrinx * consistent with the value of the associated InetAddressType 1129216295Ssyrinx * object. Attempts to set an InetAddress object to a value 1130216295Ssyrinx * inconsistent with the associated InetAddressType 1131216295Ssyrinx * must fail with an inconsistentValue error. 1132216295Ssyrinx * 1133216295Ssyrinx * When this textual convention is used as the syntax of an 1134216295Ssyrinx * index object, there may be issues with the limit of 128 1135216295Ssyrinx * sub-identifiers specified in SMIv2, STD 58. In this case, 1136216295Ssyrinx * the object definition MUST include a 'SIZE' clause to 1137216295Ssyrinx * limit the number of potential instance sub-identifiers; 1138216295Ssyrinx * otherwise the applicable constraints MUST be stated in 1139216295Ssyrinx * the appropriate conceptual row DESCRIPTION clauses, or 1140216295Ssyrinx * in the surrounding documentation if there is no single 1141216295Ssyrinx * DESCRIPTION clause that is appropriate." 1142216295Ssyrinx * SYNTAX OCTET STRING (SIZE (0..255)) 1143216295Ssyrinx ************************************************************** 1144216295Ssyrinx * TODO: FIXME!!! syrinx: Since we do not support checking the 1145216295Ssyrinx * consistency of a varbinding based on the value of a previous 1146310903Sngie * one, try to guess the type of address based on the 1147216295Ssyrinx * OctetString SIZE - 4 for IPv4, 16 for IPv6, others currently 1148216295Ssyrinx * not supported. 1149216295Ssyrinx */ 1150216295Ssyrinxstatic char * 1151216295Ssyrinxsnmp_oct2inetaddr(uint32_t len, char *octets, char *buf) 1152216295Ssyrinx{ 1153216295Ssyrinx int af; 1154216295Ssyrinx void *ip; 1155216295Ssyrinx struct in_addr ipv4; 1156216295Ssyrinx struct in6_addr ipv6; 1157216295Ssyrinx 1158216295Ssyrinx if (len > MAX_OCTSTRING_LEN || octets == NULL || buf == NULL) 1159216295Ssyrinx return (NULL); 1160216295Ssyrinx 1161216295Ssyrinx switch (len) { 1162216295Ssyrinx /* XXX: FIXME - IPv4*/ 1163216295Ssyrinx case 4: 1164216295Ssyrinx memcpy(&ipv4.s_addr, octets, sizeof(ipv4.s_addr)); 1165216295Ssyrinx af = AF_INET; 1166216295Ssyrinx ip = &ipv4; 1167216295Ssyrinx break; 1168216295Ssyrinx 1169216295Ssyrinx /* XXX: FIXME - IPv4*/ 1170216295Ssyrinx case 16: 1171216295Ssyrinx memcpy(ipv6.s6_addr, octets, sizeof(ipv6.s6_addr)); 1172216295Ssyrinx af = AF_INET6; 1173216295Ssyrinx ip = &ipv6; 1174216295Ssyrinx break; 1175216295Ssyrinx 1176216295Ssyrinx default: 1177216295Ssyrinx return (NULL); 1178216295Ssyrinx } 1179216295Ssyrinx 1180216295Ssyrinx if (inet_ntop(af, ip, buf, SNMP_INADDRS_STRSZ) == NULL) { 1181311595Sngie warn("inet_ntop failed"); 1182216295Ssyrinx return (NULL); 1183216295Ssyrinx } 1184216295Ssyrinx 1185216295Ssyrinx return (buf); 1186216295Ssyrinx} 1187216295Ssyrinx 1188216295Ssyrinxstatic char * 1189300471Sngiesnmp_inetaddr2oct(char *str __unused, struct asn_oid *oid __unused) 1190216295Ssyrinx{ 1191216295Ssyrinx return (NULL); 1192216295Ssyrinx} 1193216295Ssyrinx 1194216295Ssyrinxstatic int32_t 1195300471Sngieparse_inetaddr(struct snmp_value *value __unused, char *string __unused) 1196216295Ssyrinx{ 1197216295Ssyrinx return (-1); 1198216295Ssyrinx} 1199216295Ssyrinx 1200216295Ssyrinx/************************************************************** 1201216295Ssyrinx * SNMP BITS type - XXX: FIXME 1202216295Ssyrinx **************************************************************/ 1203216295Ssyrinxstatic char * 1204216295Ssyrinxsnmp_oct2bits(uint32_t len, char *octets, char *buf) 1205216295Ssyrinx{ 1206216295Ssyrinx int i, bits; 1207216295Ssyrinx uint64_t value; 1208216295Ssyrinx 1209216295Ssyrinx if (len > sizeof(value) || octets == NULL || buf == NULL) 1210216295Ssyrinx return (NULL); 1211216295Ssyrinx 1212216295Ssyrinx for (i = len, value = 0, bits = 0; i > 0; i--, bits += 8) 1213216295Ssyrinx value += octets[i] << bits; 1214216295Ssyrinx 1215216295Ssyrinx buf[0]= '\0'; 1216216295Ssyrinx sprintf(buf, "0x%llx.",(long long unsigned) value); 1217216295Ssyrinx 1218216295Ssyrinx return (buf); 1219216295Ssyrinx} 1220216295Ssyrinx 1221216295Ssyrinxstatic char * 1222216295Ssyrinxsnmp_bits2oct(char *str, struct asn_oid *oid) 1223216295Ssyrinx{ 1224216295Ssyrinx char *endptr; 1225216295Ssyrinx int i, size, bits, saved_errno; 1226216295Ssyrinx uint64_t v, mask = 0xFF00000000000000; 1227216295Ssyrinx 1228216295Ssyrinx saved_errno = errno; 1229216295Ssyrinx errno = 0; 1230216295Ssyrinx 1231216295Ssyrinx v = strtoull(str, &endptr, 16); 1232216295Ssyrinx if (errno != 0) { 1233311595Sngie warn("Bad BITS value %s", str); 1234216295Ssyrinx errno = saved_errno; 1235216295Ssyrinx return (NULL); 1236216295Ssyrinx } 1237216295Ssyrinx 1238216295Ssyrinx bits = 8; 1239216295Ssyrinx /* Determine length - up to 8 octets supported so far. */ 1240216295Ssyrinx for (size = sizeof(v); size > 0; size--) { 1241216295Ssyrinx if ((v & mask) != 0) 1242216295Ssyrinx break; 1243216295Ssyrinx mask = mask >> bits; 1244216295Ssyrinx } 1245216295Ssyrinx 1246216295Ssyrinx if (size == 0) 1247216295Ssyrinx size = 1; 1248216295Ssyrinx 1249216295Ssyrinx if (snmp_suboid_append(oid, (asn_subid_t) size) < 0) 1250216295Ssyrinx return (NULL); 1251216295Ssyrinx 1252216295Ssyrinx for (i = 0, bits = 0; i < size; i++, bits += 8) 1253216295Ssyrinx if (snmp_suboid_append(oid, 1254216295Ssyrinx (asn_subid_t)((v & mask) >> bits)) < 0) 1255216295Ssyrinx return (NULL); 1256216295Ssyrinx 1257216295Ssyrinx return (endptr); 1258216295Ssyrinx} 1259216295Ssyrinx 1260216295Ssyrinxstatic int32_t 1261216295Ssyrinxparse_bits(struct snmp_value *value, char *string) 1262216295Ssyrinx{ 1263216295Ssyrinx char *endptr; 1264216295Ssyrinx int i, size, bits, saved_errno; 1265216295Ssyrinx uint64_t v, mask = 0xFF00000000000000; 1266216295Ssyrinx 1267216295Ssyrinx saved_errno = errno; 1268216295Ssyrinx errno = 0; 1269216295Ssyrinx 1270216295Ssyrinx v = strtoull(string, &endptr, 16); 1271216295Ssyrinx 1272216295Ssyrinx if (errno != 0) { 1273311595Sngie warn("Bad BITS value %s", string); 1274216295Ssyrinx errno = saved_errno; 1275216295Ssyrinx return (-1); 1276216295Ssyrinx } 1277216295Ssyrinx 1278216295Ssyrinx bits = 8; 1279216295Ssyrinx /* Determine length - up to 8 octets supported so far. */ 1280216295Ssyrinx for (size = sizeof(v); size > 0; size--) { 1281216295Ssyrinx if ((v & mask) != 0) 1282216295Ssyrinx break; 1283216295Ssyrinx mask = mask >> bits; 1284216295Ssyrinx } 1285216295Ssyrinx 1286216295Ssyrinx if (size == 0) 1287216295Ssyrinx size = 1; 1288216295Ssyrinx 1289216295Ssyrinx if ((value->v.octetstring.octets = malloc(size)) == NULL) { 1290216295Ssyrinx syslog(LOG_ERR, "malloc failed: %s", strerror(errno)); 1291216295Ssyrinx return (-1); 1292216295Ssyrinx } 1293216295Ssyrinx 1294216295Ssyrinx value->v.octetstring.len = size; 1295216295Ssyrinx for (i = 0, bits = 0; i < size; i++, bits += 8) 1296216295Ssyrinx value->v.octetstring.octets[i] = (v & mask) >> bits; 1297216295Ssyrinx value->syntax = SNMP_SYNTAX_OCTETSTRING; 1298216295Ssyrinx return (1); 1299216295Ssyrinx} 1300