Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/bsnmpd/tools/libbsnmptools/bsnmptc.c
106842 views
1
/*-
2
* Copyright (c) 2006 The FreeBSD Project
3
* All rights reserved.
4
*
5
* Author: Shteryana Shopova <[email protected]>
6
*
7
* Redistribution of this software and documentation and use in source and
8
* binary forms, with or without modification, are permitted provided that
9
* the following conditions are met:
10
*
11
* 1. Redistributions of source code or documentation must retain the above
12
* copyright notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*
29
* Textual conventions for OctetStrings
30
*/
31
32
#include <sys/param.h>
33
#include <sys/queue.h>
34
#include <sys/socket.h>
35
#include <sys/uio.h>
36
37
#include <ctype.h>
38
#include <err.h>
39
#include <errno.h>
40
#include <fcntl.h>
41
#include <stdio.h>
42
#include <stdlib.h>
43
#include <string.h>
44
#include <syslog.h>
45
#include <unistd.h>
46
47
#include <arpa/inet.h>
48
#include <netinet/in.h>
49
50
#include <bsnmp/asn1.h>
51
#include <bsnmp/snmp.h>
52
#include "bsnmptc.h"
53
#include "bsnmptools.h"
54
55
/* OctetString, DisplayString */
56
static char *snmp_oct2str(uint32_t, char *, char *);
57
static char *snmp_str2asn_oid(char *, struct asn_oid *);
58
static int parse_octetstring(struct snmp_value *, char *);
59
60
/* DateAndTime */
61
static char *snmp_octstr2date(uint32_t, char *, char *);
62
static char *snmp_date2asn_oid(char * , struct asn_oid *);
63
static int parse_dateandtime(struct snmp_value *, char *);
64
65
/* PhysAddress */
66
static char *snmp_oct2physAddr(uint32_t, char *, char *);
67
static char *snmp_addr2asn_oid(char *, struct asn_oid *);
68
static int parse_physaddress(struct snmp_value *, char *);
69
70
/* NTPTimeStamp */
71
static char *snmp_oct2ntp_ts(uint32_t, char *, char *);
72
static char *snmp_ntp_ts2asn_oid(char *, struct asn_oid *);
73
static int parse_ntp_ts(struct snmp_value *, char *);
74
75
/* BridgeId */
76
static char *snmp_oct2bridgeid(uint32_t, char *, char *);
77
static char *snmp_bridgeid2oct(char *, struct asn_oid *);
78
static int parse_bridge_id(struct snmp_value *, char *);
79
80
/* BridgePortId */
81
static char *snmp_oct2bport_id(uint32_t, char *, char *);
82
static char *snmp_bport_id2oct(char *, struct asn_oid *);
83
static int parse_bport_id(struct snmp_value *, char *);
84
85
/* InetAddress */
86
static char *snmp_oct2inetaddr(uint32_t len, char *octets, char *buf);
87
static char *snmp_inetaddr2oct(char *str, struct asn_oid *oid);
88
static int32_t parse_inetaddr(struct snmp_value *value, char *string);
89
90
static char *snmp_oct2bits(uint32_t len, char *octets, char *buf);
91
static char *snmp_bits2oct(char *str, struct asn_oid *oid);
92
static int32_t parse_bits(struct snmp_value *value, char *string);
93
94
static struct snmp_text_conv {
95
enum snmp_tc tc;
96
const char *tc_str;
97
int32_t len;
98
snmp_oct2tc_f oct2tc;
99
snmp_tc2oid_f tc2oid;
100
snmp_tc2oct_f tc2oct;
101
} text_convs[] = {
102
{ SNMP_STRING, "OctetString", SNMP_VAR_STRSZ,
103
snmp_oct2str, snmp_str2asn_oid, parse_octetstring },
104
105
{ SNMP_DISPLAYSTRING, "DisplayString" , SNMP_VAR_STRSZ,
106
snmp_oct2str, snmp_str2asn_oid, parse_octetstring },
107
108
{ SNMP_DATEANDTIME, "DateAndTime", SNMP_DATETIME_STRSZ,
109
snmp_octstr2date, snmp_date2asn_oid, parse_dateandtime },
110
111
{ SNMP_PHYSADDR, "PhysAddress", SNMP_PHYSADDR_STRSZ,
112
snmp_oct2physAddr, snmp_addr2asn_oid, parse_physaddress },
113
114
{ SNMP_ATMESI, "AtmESI", SNMP_PHYSADDR_STRSZ,
115
snmp_oct2physAddr, snmp_addr2asn_oid, parse_physaddress },
116
117
{ SNMP_NTP_TIMESTAMP, "NTPTimeStamp", SNMP_NTP_TS_STRSZ,
118
snmp_oct2ntp_ts, snmp_ntp_ts2asn_oid, parse_ntp_ts },
119
120
{ SNMP_MACADDRESS, "MacAddress", SNMP_PHYSADDR_STRSZ,
121
snmp_oct2physAddr, snmp_addr2asn_oid, parse_physaddress },
122
123
{ SNMP_BRIDGE_ID, "BridgeId", SNMP_BRIDGEID_STRSZ,
124
snmp_oct2bridgeid, snmp_bridgeid2oct, parse_bridge_id },
125
126
{ SNMP_BPORT_ID, "BridgePortId", SNMP_BPORT_STRSZ,
127
snmp_oct2bport_id, snmp_bport_id2oct, parse_bport_id },
128
129
{ SNMP_INETADDRESS, "InetAddress", SNMP_INADDRS_STRSZ,
130
snmp_oct2inetaddr, snmp_inetaddr2oct, parse_inetaddr },
131
132
{ SNMP_TC_OWN, "BITS", SNMP_VAR_STRSZ,
133
snmp_oct2bits, snmp_bits2oct, parse_bits },
134
135
{ SNMP_UNKNOWN, "Unknown", SNMP_VAR_STRSZ, snmp_oct2str,
136
snmp_str2asn_oid, parse_octetstring } /* keep last */
137
};
138
139
/* Common API */
140
enum snmp_tc
141
snmp_get_tc(char *str)
142
{
143
int i;
144
for (i = 0; i < SNMP_UNKNOWN; i++) {
145
if (!strncmp(text_convs[i].tc_str, str,
146
strlen(text_convs[i].tc_str)))
147
return (text_convs[i].tc);
148
}
149
150
return (SNMP_STRING);
151
}
152
153
char *
154
snmp_oct2tc(enum snmp_tc tc, uint32_t len, char *octets)
155
{
156
uint32_t tc_len;
157
char * buf;
158
159
if (tc > SNMP_UNKNOWN)
160
tc = SNMP_UNKNOWN;
161
162
if (text_convs[tc].len > 0)
163
tc_len = text_convs[tc].len;
164
else
165
tc_len = 2 * len + 3;
166
167
if ((buf = malloc(tc_len)) == NULL ) {
168
syslog(LOG_ERR, "malloc failed - %s", strerror(errno));
169
return (NULL);
170
}
171
172
memset(buf, 0, tc_len);
173
if (text_convs[tc].oct2tc(len, octets, buf) == NULL) {
174
free(buf);
175
return (NULL);
176
}
177
178
return (buf);
179
}
180
181
char *
182
snmp_tc2oid(enum snmp_tc tc, char *str, struct asn_oid *oid)
183
{
184
if (tc > SNMP_UNKNOWN)
185
tc = SNMP_UNKNOWN;
186
187
return (text_convs[tc].tc2oid(str, oid));
188
}
189
190
int32_t
191
snmp_tc2oct(enum snmp_tc tc, struct snmp_value *value, char *string)
192
{
193
if (tc > SNMP_UNKNOWN)
194
tc = SNMP_UNKNOWN;
195
196
return (text_convs[tc].tc2oct(value, string));
197
}
198
199
/*****************************************************
200
* Basic OctetString type.
201
*/
202
static char *
203
snmp_oct2str(uint32_t len, char *octets, char *buf)
204
{
205
uint8_t binary = 0;
206
uint32_t i;
207
char *ptr;
208
209
if (len > MAX_OCTSTRING_LEN || octets == NULL || buf == NULL)
210
return (NULL);
211
212
for (ptr = buf, i = 0; i < len; i++)
213
if (!isprint(octets[i])) {
214
binary = 1;
215
buf += sprintf(buf, "0x");
216
break;
217
}
218
219
for (ptr = buf, i = 0; i < len; i++)
220
if (!binary)
221
ptr += sprintf(ptr, "%c", octets[i]);
222
else
223
ptr += sprintf(ptr, "%2.2x", (u_char)octets[i]);
224
225
return (buf);
226
}
227
228
static char *
229
snmp_str2asn_oid(char *str, struct asn_oid *oid)
230
{
231
uint32_t i, len = 0;
232
233
/*
234
* OctetStrings are allowed max length of ASN_MAXOCTETSTRING,
235
* but trying to index an entry with such a long OctetString
236
* will fail anyway.
237
*/
238
for (len = 0; len < ASN_MAXOIDLEN; len++) {
239
if (strchr(",]", *(str + len)) != NULL)
240
break;
241
}
242
243
if (len >= ASN_MAXOIDLEN)
244
return (NULL);
245
246
if (snmp_suboid_append(oid, (asn_subid_t) len) < 0)
247
return (NULL);
248
249
for (i = 0; i < len; i++)
250
if (snmp_suboid_append(oid, (asn_subid_t) *(str + i)) < 0)
251
return (NULL);
252
253
return (str + len);
254
}
255
256
static int32_t
257
parse_octetstring(struct snmp_value *value, char *val)
258
{
259
size_t len;
260
261
if ((len = strlen(val)) >= MAX_OCTSTRING_LEN) {
262
warnx("Octetstring too long - %d is max allowed",
263
MAX_OCTSTRING_LEN - 1);
264
return (-1);
265
}
266
267
if ((value->v.octetstring.octets = malloc(len)) == NULL) {
268
value->v.octetstring.len = 0;
269
syslog(LOG_ERR, "malloc failed: %s", strerror(errno));
270
return (-1);
271
}
272
273
value->v.octetstring.len = len;
274
memcpy(value->v.octetstring.octets, val, len);
275
value->syntax = SNMP_SYNTAX_OCTETSTRING;
276
277
return (0);
278
}
279
280
/*************************************************************
281
* DateAndTime
282
*************************************************************
283
* rfc 2579 specification:
284
* DateAndTime ::= TEXTUAL-CONVENTION
285
* DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d"
286
* STATUS current
287
* DESCRIPTION
288
* "A date-time specification.
289
*
290
* field octets contents range
291
* ----- ------ -------- -----
292
* 1 1-2 year* 0..65536
293
* 2 3 month 1..12
294
* 3 4 day 1..31
295
* 4 5 hour 0..23
296
* 5 6 minutes 0..59
297
* 6 7 seconds 0..60
298
* (use 60 for leap-second)
299
* 7 8 deci-seconds 0..9
300
* 8 9 direction from UTC '+' / '-'
301
* 9 10 hours from UTC* 0..13
302
* 10 11 minutes from UTC 0..59
303
*
304
* * Notes:
305
* - the value of year is in network-byte order
306
* - daylight saving time in New Zealand is +13
307
*
308
* For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be
309
* displayed as:
310
*
311
* 1992-5-26,13:30:15.0,-4:0
312
*/
313
static char *
314
snmp_octstr2date(uint32_t len, char *octets, char *buf)
315
{
316
int year;
317
char *ptr;
318
319
if (len != SNMP_DATETIME_OCTETS || octets == NULL || buf == NULL)
320
return (NULL);
321
322
buf[0]= '\0';
323
year = (octets[0] << 8);
324
year += (octets[1]);
325
326
ptr = buf;
327
ptr += sprintf(ptr, "%4.4d-%.2d-%.2d, ", year, octets[2],octets[3]);
328
ptr += sprintf(ptr, "%2.2d:%2.2d:%2.2d.%.2d, ", octets[4],octets[5],
329
octets[6],octets[7]);
330
ptr += sprintf(ptr, "%c%.2d:%.2d", octets[8],octets[9],octets[10]);
331
332
return (buf);
333
}
334
335
static char *
336
snmp_date2asn_oid(char *str, struct asn_oid *oid)
337
{
338
char *endptr, *ptr;
339
static const char UTC[3] __nonstring = "UTC";
340
int32_t saved_errno;
341
uint32_t v;
342
343
if (snmp_suboid_append(oid, (asn_subid_t) SNMP_DATETIME_OCTETS) < 0)
344
return (NULL);
345
346
/* Read 'YYYY-' and write it in two subs. */
347
ptr = str;
348
saved_errno = errno;
349
errno = 0;
350
v = strtoul(ptr, &endptr, 10);
351
if (v > 0xffff)
352
goto error;
353
else
354
errno = saved_errno;
355
if (*endptr != '-')
356
goto error1;
357
if (snmp_suboid_append(oid, (asn_subid_t) ((v & 0xff00) >> 8)) < 0)
358
return (NULL);
359
if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xff)) < 0)
360
return (NULL);
361
362
/* 'MM-' */
363
ptr = endptr + 1;
364
saved_errno = errno;
365
errno = 0;
366
v = strtoul(ptr, &endptr, 10);
367
if (errno != 0)
368
goto error;
369
else
370
errno = saved_errno;
371
if (*endptr != '-')
372
goto error1;
373
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
374
return (NULL);
375
376
/* 'DD,' */
377
ptr = endptr + 1;
378
saved_errno = errno;
379
errno = 0;
380
v = strtoul(ptr, &endptr, 10);
381
if (errno != 0)
382
goto error;
383
else
384
errno = saved_errno;
385
if (*endptr != '-')
386
goto error1;
387
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
388
return (NULL);
389
390
/* 'HH:' */
391
ptr = endptr + 1;
392
saved_errno = errno;
393
errno = 0;
394
v = strtoul(ptr, &endptr, 10);
395
if (errno != 0)
396
goto error;
397
else
398
errno = saved_errno;
399
if (*endptr != ':')
400
goto error1;
401
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
402
return (NULL);
403
404
/* 'MM:' */
405
ptr = endptr + 1;
406
saved_errno = errno;
407
errno = 0;
408
v = strtoul(ptr, &endptr, 10);
409
if (errno != 0)
410
goto error;
411
else
412
errno = saved_errno;
413
if (*endptr != ':')
414
goto error1;
415
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
416
return (NULL);
417
418
/* 'SS.' */
419
ptr = endptr + 1;
420
saved_errno = errno;
421
errno = 0;
422
v = strtoul(ptr, &endptr, 10);
423
if (errno != 0)
424
goto error;
425
else
426
errno = saved_errno;
427
if (*endptr != '.')
428
goto error1;
429
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
430
return (NULL);
431
432
/* 'M(mseconds),' */
433
ptr = endptr + 1;
434
saved_errno = errno;
435
errno = 0;
436
v = strtoul(ptr, &endptr, 10);
437
if (errno != 0)
438
goto error;
439
else
440
errno = saved_errno;
441
if (*endptr != ',')
442
goto error1;
443
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
444
return (NULL);
445
446
/* 'UTC' - optional */
447
ptr = endptr + 1;
448
if (strncmp(ptr, UTC, sizeof(UTC)) == 0)
449
ptr += sizeof(UTC);
450
451
/* '+/-' */
452
if (*ptr == '-' || *ptr == '+') {
453
if (snmp_suboid_append(oid, (asn_subid_t) (*ptr)) < 0)
454
return (NULL);
455
} else
456
goto error1;
457
458
/* 'HH:' */
459
ptr = endptr + 1;
460
saved_errno = errno;
461
errno = 0;
462
v = strtoul(ptr, &endptr, 10);
463
if (errno != 0)
464
goto error;
465
else
466
errno = saved_errno;
467
if (*endptr != ':')
468
goto error1;
469
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
470
return (NULL);
471
472
/* 'MM' - last one - ignore endptr here. */
473
ptr = endptr + 1;
474
saved_errno = errno;
475
errno = 0;
476
v = strtoul(ptr, &endptr, 10);
477
if (errno != 0)
478
goto error;
479
else
480
errno = saved_errno;
481
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
482
return (NULL);
483
484
return (endptr);
485
486
error:
487
errno = saved_errno;
488
error1:
489
warnx("Date value %s not supported", str);
490
return (NULL);
491
}
492
493
/* Read a DateAndTime string eg. 1992-5-26,13:30:15.0,-4:0. */
494
static int32_t
495
parse_dateandtime(struct snmp_value *sv, char *val)
496
{
497
char *endptr;
498
uint32_t v;
499
uint8_t date[SNMP_DATETIME_OCTETS];
500
501
/* 'YYYY-' */
502
v = strtoul(val, &endptr, 10);
503
if (v > 0xffff || *endptr != '-')
504
goto error;
505
date[0] = ((v & 0xff00) >> 8);
506
date[1] = (v & 0xff);
507
val = endptr + 1;
508
509
/* 'MM-' */
510
v = strtoul(val, &endptr, 10);
511
if (v == 0 || v > 12 || *endptr != '-')
512
goto error;
513
date[2] = v;
514
val = endptr + 1;
515
516
/* 'DD,' */
517
v = strtoul(val, &endptr, 10);
518
if (v == 0 || v > 31 || *endptr != ',')
519
goto error;
520
date[3] = v;
521
val = endptr + 1;
522
523
/* 'HH:' */
524
v = strtoul(val, &endptr, 10);
525
if (v > 23 || *endptr != ':')
526
goto error;
527
date[4] = v;
528
val = endptr + 1;
529
530
/* 'MM:' */
531
v = strtoul(val, &endptr, 10);
532
if (v > 59 || *endptr != ':')
533
goto error;
534
date[5] = v;
535
val = endptr + 1;
536
537
/* 'SS.' */
538
v = strtoul(val, &endptr, 10);
539
if (v > 60 || *endptr != '.')
540
goto error;
541
date[6] = v;
542
val = endptr + 1;
543
544
/* '(deci-)s,' */
545
v = strtoul(val, &endptr, 10);
546
if (v > 9 || *endptr != ',')
547
goto error;
548
date[7] = v;
549
val = endptr + 1;
550
551
/* offset - '+/-' */
552
if (*val != '-' && *val != '+')
553
goto error;
554
date[8] = (uint8_t) *val;
555
val = endptr + 1;
556
557
/* 'HH:' - offset from UTC */
558
v = strtoul(val, &endptr, 10);
559
if (v > 13 || *endptr != ':')
560
goto error;
561
date[9] = v;
562
val = endptr + 1;
563
564
/* 'MM'\0'' offset from UTC */
565
v = strtoul(val, &endptr, 10);
566
if (v > 59 || *endptr != '\0')
567
goto error;
568
date[10] = v;
569
570
if ((sv->v.octetstring.octets = malloc(SNMP_DATETIME_OCTETS)) == NULL) {
571
warn("malloc() failed");
572
return (-1);
573
}
574
575
sv->v.octetstring.len = SNMP_DATETIME_OCTETS;
576
memcpy(sv->v.octetstring.octets, date, SNMP_DATETIME_OCTETS);
577
sv->syntax = SNMP_SYNTAX_OCTETSTRING;
578
return (1);
579
580
error:
581
warnx("Date value %s not supported", val);
582
return (-1);
583
}
584
585
/**************************************************************
586
* PhysAddress
587
*/
588
static char *
589
snmp_oct2physAddr(uint32_t len, char *octets, char *buf)
590
{
591
char *ptr;
592
uint32_t i;
593
594
if (len != SNMP_PHYSADDR_OCTETS || octets == NULL || buf == NULL)
595
return (NULL);
596
597
buf[0]= '\0';
598
599
ptr = buf;
600
ptr += sprintf(ptr, "%2.2x", octets[0]);
601
for (i = 1; i < 6; i++)
602
ptr += sprintf(ptr, ":%2.2x", octets[i]);
603
604
return (buf);
605
}
606
607
static char *
608
snmp_addr2asn_oid(char *str, struct asn_oid *oid)
609
{
610
char *endptr, *ptr;
611
uint32_t v, i;
612
int saved_errno;
613
614
if (snmp_suboid_append(oid, (asn_subid_t) SNMP_PHYSADDR_OCTETS) < 0)
615
return (NULL);
616
617
ptr = str;
618
for (i = 0; i < 5; i++) {
619
saved_errno = errno;
620
v = strtoul(ptr, &endptr, 16);
621
errno = saved_errno;
622
if (v > 0xff) {
623
warnx("Integer value %s not supported", str);
624
return (NULL);
625
}
626
if (*endptr != ':') {
627
warnx("Failed adding oid - %s", str);
628
return (NULL);
629
}
630
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
631
return (NULL);
632
ptr = endptr + 1;
633
}
634
635
/* The last one - don't check the ending char here. */
636
saved_errno = errno;
637
v = strtoul(ptr, &endptr, 16);
638
errno = saved_errno;
639
if (v > 0xff) {
640
warnx("Integer value %s not supported", str);
641
return (NULL);
642
}
643
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
644
return (NULL);
645
646
return (endptr);
647
}
648
649
static int32_t
650
parse_physaddress(struct snmp_value *sv, char *val)
651
{
652
char *endptr;
653
int32_t i;
654
uint32_t v;
655
uint8_t phys_addr[SNMP_PHYSADDR_OCTETS];
656
657
for (i = 0; i < 5; i++) {
658
v = strtoul(val, &endptr, 16);
659
if (v > 0xff) {
660
warnx("Integer value %s not supported", val);
661
return (-1);
662
}
663
if(*endptr != ':') {
664
warnx("Failed reading octet - %s", val);
665
return (-1);
666
}
667
phys_addr[i] = v;
668
val = endptr + 1;
669
}
670
671
/* The last one - don't check the ending char here. */
672
v = strtoul(val, &endptr, 16);
673
if (v > 0xff) {
674
warnx("Integer value %s not supported", val);
675
return (-1);
676
}
677
phys_addr[5] = v;
678
679
if ((sv->v.octetstring.octets = malloc(SNMP_PHYSADDR_OCTETS)) == NULL) {
680
syslog(LOG_ERR, "malloc failed: %s", strerror(errno));
681
return (-1);
682
}
683
684
sv->v.octetstring.len = SNMP_PHYSADDR_OCTETS;
685
memcpy(sv->v.octetstring.octets, phys_addr, SNMP_PHYSADDR_OCTETS);
686
sv->syntax = SNMP_SYNTAX_OCTETSTRING;
687
return (1);
688
}
689
690
/**************************************************************
691
* NTPTimeStamp
692
**************************************************************
693
* NTP MIB, Revision 0.2, 7/25/97:
694
* NTPTimeStamp ::= TEXTUAL-CONVENTION
695
* DISPLAY-HINT "4x.4x"
696
* STATUS current
697
* DESCRIPTION
698
* ""
699
* SYNTAX OCTET STRING (SIZE(8))
700
*/
701
static char *
702
snmp_oct2ntp_ts(uint32_t len, char *octets, char *buf)
703
{
704
char *ptr;
705
uint32_t i;
706
707
if (len != SNMP_NTP_TS_OCTETS || octets == NULL || buf == NULL)
708
return (NULL);
709
710
buf[0]= '\0';
711
712
ptr = buf;
713
i = octets[0] * 1000 + octets[1] * 100 + octets[2] * 10 + octets[3];
714
ptr += sprintf(ptr, "%4.4d", i);
715
i = octets[4] * 1000 + octets[5] * 100 + octets[6] * 10 + octets[7];
716
ptr += sprintf(ptr, ".%4.4d", i);
717
718
return (buf);
719
}
720
721
static char *
722
snmp_ntp_ts2asn_oid(char *str, struct asn_oid *oid)
723
{
724
char *endptr, *ptr;
725
uint32_t v, i, d;
726
struct asn_oid suboid;
727
int saved_errno;
728
729
if (snmp_suboid_append(oid, (asn_subid_t) SNMP_NTP_TS_OCTETS) < 0)
730
return (NULL);
731
732
ptr = str;
733
saved_errno = errno;
734
errno = 0;
735
v = strtoul(ptr, &endptr, 10);
736
if (errno != 0 || (v / 1000) > 9) {
737
warnx("Integer value %s not supported", str);
738
errno = saved_errno;
739
return (NULL);
740
} else
741
errno = saved_errno;
742
743
if (*endptr != '.') {
744
warnx("Failed adding oid - %s", str);
745
return (NULL);
746
}
747
748
memset(&suboid, 0, sizeof(struct asn_oid));
749
suboid.len = SNMP_NTP_TS_OCTETS;
750
751
for (i = 0, d = 1000; i < 4; i++) {
752
suboid.subs[i] = v / d;
753
v = v % d;
754
d = d / 10;
755
}
756
757
ptr = endptr + 1;
758
saved_errno = errno;
759
errno = 0;
760
v = strtoul(ptr, &endptr, 10);
761
if (errno != 0 || (v / 1000) > 9) {
762
warnx("Integer value %s not supported", str);
763
errno = saved_errno;
764
return (NULL);
765
} else
766
errno = saved_errno;
767
768
for (i = 0, d = 1000; i < 4; i++) {
769
suboid.subs[i + 4] = v / d;
770
v = v % d;
771
d = d / 10;
772
}
773
774
asn_append_oid(oid, &suboid);
775
return (endptr);
776
}
777
778
static int32_t
779
parse_ntp_ts(struct snmp_value *sv, char *val)
780
{
781
char *endptr;
782
int32_t i, d, saved_errno;
783
uint32_t v;
784
uint8_t ntp_ts[SNMP_NTP_TS_OCTETS];
785
786
saved_errno = errno;
787
errno = 0;
788
v = strtoul(val, &endptr, 10);
789
if (errno != 0 || (v / 1000) > 9) {
790
errno = saved_errno;
791
warnx("Integer value %s not supported", val);
792
return (-1);
793
} else
794
errno = saved_errno;
795
796
if (*endptr != '.') {
797
warnx("Failed reading octet - %s", val);
798
return (-1);
799
}
800
801
for (i = 0, d = 1000; i < 4; i++) {
802
ntp_ts[i] = v / d;
803
v = v % d;
804
d = d / 10;
805
}
806
val = endptr + 1;
807
808
saved_errno = errno;
809
errno = 0;
810
v = strtoul(val, &endptr, 10);
811
if (errno != 0 || (v / 1000) > 9) {
812
errno = saved_errno;
813
warnx("Integer value %s not supported", val);
814
return (-1);
815
} else
816
errno = saved_errno;
817
818
for (i = 0, d = 1000; i < 4; i++) {
819
ntp_ts[i + 4] = v / d;
820
v = v % d;
821
d = d / 10;
822
}
823
824
if ((sv->v.octetstring.octets = malloc(SNMP_NTP_TS_OCTETS)) == NULL) {
825
syslog(LOG_ERR, "malloc failed: %s", strerror(errno));
826
return (-1);
827
}
828
829
sv->v.octetstring.len = SNMP_NTP_TS_OCTETS;
830
memcpy(sv->v.octetstring.octets, ntp_ts, SNMP_NTP_TS_OCTETS);
831
sv->syntax = SNMP_SYNTAX_OCTETSTRING;
832
return (1);
833
}
834
835
/**************************************************************
836
* BridgeId
837
**************************************************************
838
* BRIDGE-MIB, REVISION "200509190000Z"
839
* BridgeId ::= TEXTUAL-CONVENTION
840
* STATUS current
841
* DESCRIPTION
842
* "The Bridge-Identifier, as used in the Spanning Tree
843
* Protocol, to uniquely identify a bridge. Its first two
844
* octets (in network byte order) contain a priority value,
845
* and its last 6 octets contain the MAC address used to
846
* refer to a bridge in a unique fashion (typically, the
847
* numerically smallest MAC address of all ports on the
848
* bridge)."
849
* SYNTAX OCTET STRING (SIZE (8))
850
*/
851
static char *
852
snmp_oct2bridgeid(uint32_t len, char *octets, char *buf)
853
{
854
char *ptr;
855
uint32_t i, priority;
856
857
if (len != SNMP_BRIDGEID_OCTETS || octets == NULL || buf == NULL)
858
return (NULL);
859
860
buf[0]= '\0';
861
ptr = buf;
862
863
priority = octets[0] << 8;
864
priority += octets[1];
865
if (priority > SNMP_MAX_BRIDGE_PRIORITY) {
866
warnx("Invalid bridge priority %d", priority);
867
return (NULL);
868
} else
869
ptr += sprintf(ptr, "%d.", octets[0]);
870
871
ptr += sprintf(ptr, "%2.2x", octets[2]);
872
873
for (i = 1; i < 6; i++)
874
ptr += sprintf(ptr, ":%2.2x", octets[i + 2]);
875
876
return (buf);
877
}
878
879
static char *
880
snmp_bridgeid2oct(char *str, struct asn_oid *oid)
881
{
882
char *endptr, *ptr;
883
uint32_t v, i;
884
int32_t saved_errno;
885
886
if (snmp_suboid_append(oid, (asn_subid_t) SNMP_BRIDGEID_OCTETS) < 0)
887
return (NULL);
888
889
ptr = str;
890
/* Read the priority. */
891
saved_errno = errno;
892
errno = 0;
893
v = strtoul(ptr, &endptr, 10);
894
895
if (v > SNMP_MAX_BRIDGE_PRIORITY || errno != 0 || *endptr != '.') {
896
errno = saved_errno;
897
warnx("Bad bridge priority value %d", v);
898
return (NULL);
899
}
900
901
if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xff00)) < 0)
902
return (NULL);
903
904
if (snmp_suboid_append(oid, (asn_subid_t) (v & 0xff)) < 0)
905
return (NULL);
906
907
ptr = endptr + 1;
908
for (i = 0; i < 5; i++) {
909
saved_errno = errno;
910
errno = 0;
911
v = strtoul(ptr, &endptr, 16);
912
errno = saved_errno;
913
if (v > 0xff) {
914
warnx("Integer value %s not supported", str);
915
return (NULL);
916
}
917
if (*endptr != ':') {
918
warnx("Failed adding oid - %s",str);
919
return (NULL);
920
}
921
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
922
return (NULL);
923
ptr = endptr + 1;
924
}
925
926
/* The last one - don't check the ending char here. */
927
saved_errno = errno;
928
errno = 0;
929
v = strtoul(ptr, &endptr, 16);
930
errno = saved_errno;
931
if (v > 0xff) {
932
warnx("Integer value %s not supported", str);
933
return (NULL);
934
}
935
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
936
return (NULL);
937
938
return (endptr);
939
}
940
941
static int32_t
942
parse_bridge_id(struct snmp_value *sv, char *string)
943
{
944
char *endptr;
945
int32_t i, saved_errno;
946
uint32_t v;
947
uint8_t bridge_id[SNMP_BRIDGEID_OCTETS];
948
949
/* Read the priority. */
950
saved_errno = errno;
951
errno = 0;
952
v = strtoul(string, &endptr, 10);
953
954
if (v > SNMP_MAX_BRIDGE_PRIORITY || errno != 0 || *endptr != '.') {
955
errno = saved_errno;
956
warnx("Bad bridge priority value %d", v);
957
return (-1);
958
}
959
960
bridge_id[0] = (v & 0xff00);
961
bridge_id[1] = (v & 0xff);
962
963
string = endptr + 1;
964
965
for (i = 0; i < 5; i++) {
966
v = strtoul(string, &endptr, 16);
967
if (v > 0xff) {
968
warnx("Integer value %s not supported", string);
969
return (-1);
970
}
971
if(*endptr != ':') {
972
warnx("Failed reading octet - %s", string);
973
return (-1);
974
}
975
bridge_id[i + 2] = v;
976
string = endptr + 1;
977
}
978
979
/* The last one - don't check the ending char here. */
980
v = strtoul(string, &endptr, 16);
981
if (v > 0xff) {
982
warnx("Integer value %s not supported", string);
983
return (-1);
984
}
985
bridge_id[7] = v;
986
987
if ((sv->v.octetstring.octets = malloc(SNMP_BRIDGEID_OCTETS)) == NULL) {
988
syslog(LOG_ERR, "malloc failed: %s", strerror(errno));
989
return (-1);
990
}
991
992
sv->v.octetstring.len = SNMP_BRIDGEID_OCTETS;
993
memcpy(sv->v.octetstring.octets, bridge_id, SNMP_BRIDGEID_OCTETS);
994
sv->syntax = SNMP_SYNTAX_OCTETSTRING;
995
return (1);
996
}
997
998
/**************************************************************
999
* BridgePortId
1000
**************************************************************
1001
* BEGEMOT-BRIDGE-MIB, LAST-UPDATED "200608100000Z"
1002
* BridgePortId ::= TEXTUAL-CONVENTION
1003
* DISPLAY-HINT "1x.1x"
1004
* STATUS current
1005
* DESCRIPTION
1006
* "A port identifier that contains a bridge port's STP priority
1007
* in the first octet and the port number in the second octet."
1008
* SYNTAX OCTET STRING (SIZE(2))
1009
*/
1010
static char *
1011
snmp_oct2bport_id(uint32_t len, char *octets, char *buf)
1012
{
1013
char *ptr;
1014
1015
if (len != SNMP_BPORT_OCTETS || octets == NULL || buf == NULL)
1016
return (NULL);
1017
1018
buf[0]= '\0';
1019
ptr = buf;
1020
1021
ptr += sprintf(ptr, "%d.", octets[0]);
1022
ptr += sprintf(ptr, "%d", octets[1]);
1023
1024
return (buf);
1025
}
1026
1027
static char *
1028
snmp_bport_id2oct(char *str, struct asn_oid *oid)
1029
{
1030
char *endptr, *ptr;
1031
uint32_t v;
1032
int saved_errno;
1033
1034
if (snmp_suboid_append(oid, (asn_subid_t) SNMP_BPORT_OCTETS) < 0)
1035
return (NULL);
1036
1037
ptr = str;
1038
/* Read the priority. */
1039
saved_errno = errno;
1040
errno = 0;
1041
v = strtoul(ptr, &endptr, 10);
1042
1043
if (v > SNMP_MAX_BPORT_PRIORITY || errno != 0 || *endptr != '.') {
1044
errno = saved_errno;
1045
warnx("Bad bridge port priority value %d", v);
1046
return (NULL);
1047
}
1048
1049
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
1050
return (NULL);
1051
1052
saved_errno = errno;
1053
errno = 0;
1054
v = strtoul(ptr, &endptr, 16);
1055
errno = saved_errno;
1056
1057
if (v > 0xff) {
1058
warnx("Bad port number - %d", v);
1059
return (NULL);
1060
}
1061
1062
if (snmp_suboid_append(oid, (asn_subid_t) v) < 0)
1063
return (NULL);
1064
1065
return (endptr);
1066
}
1067
1068
static int32_t
1069
parse_bport_id(struct snmp_value *value, char *string)
1070
{
1071
char *endptr;
1072
int saved_errno;
1073
uint32_t v;
1074
uint8_t bport_id[SNMP_BPORT_OCTETS];
1075
1076
/* Read the priority. */
1077
saved_errno = errno;
1078
errno = 0;
1079
v = strtoul(string, &endptr, 10);
1080
1081
if (v > SNMP_MAX_BPORT_PRIORITY || errno != 0 || *endptr != '.') {
1082
errno = saved_errno;
1083
warnx("Bad bridge port priority value %d", v);
1084
return (-1);
1085
}
1086
1087
bport_id[0] = v;
1088
1089
string = endptr + 1;
1090
v = strtoul(string, &endptr, 16);
1091
if (v > 0xff) {
1092
warnx("Bad port number - %d", v);
1093
return (-1);
1094
}
1095
1096
bport_id[1] = v;
1097
1098
if ((value->v.octetstring.octets = malloc(SNMP_BPORT_OCTETS)) == NULL) {
1099
syslog(LOG_ERR, "malloc failed: %s", strerror(errno));
1100
return (-1);
1101
}
1102
1103
value->v.octetstring.len = SNMP_BPORT_OCTETS;
1104
memcpy(value->v.octetstring.octets, bport_id, SNMP_BPORT_OCTETS);
1105
value->syntax = SNMP_SYNTAX_OCTETSTRING;
1106
return (1);
1107
}
1108
/**************************************************************
1109
* InetAddress
1110
**************************************************************
1111
* INET-ADDRESS-MIB, REVISION "200502040000Z"
1112
* InetAddress ::= TEXTUAL-CONVENTION
1113
* STATUS current
1114
* DESCRIPTION
1115
* "Denotes a generic Internet address.
1116
*
1117
* An InetAddress value is always interpreted within the context
1118
* of an InetAddressType value. Every usage of the InetAddress
1119
* textual convention is required to specify the InetAddressType
1120
* object that provides the context. It is suggested that the
1121
* InetAddressType object be logically registered before the
1122
* object(s) that use the InetAddress textual convention, if
1123
* they appear in the same logical row.
1124
*
1125
* The value of an InetAddress object must always be
1126
* consistent with the value of the associated InetAddressType
1127
* object. Attempts to set an InetAddress object to a value
1128
* inconsistent with the associated InetAddressType
1129
* must fail with an inconsistentValue error.
1130
*
1131
* When this textual convention is used as the syntax of an
1132
* index object, there may be issues with the limit of 128
1133
* sub-identifiers specified in SMIv2, STD 58. In this case,
1134
* the object definition MUST include a 'SIZE' clause to
1135
* limit the number of potential instance sub-identifiers;
1136
* otherwise the applicable constraints MUST be stated in
1137
* the appropriate conceptual row DESCRIPTION clauses, or
1138
* in the surrounding documentation if there is no single
1139
* DESCRIPTION clause that is appropriate."
1140
* SYNTAX OCTET STRING (SIZE (0..255))
1141
**************************************************************
1142
* TODO: FIXME!!! syrinx: Since we do not support checking the
1143
* consistency of a varbinding based on the value of a previous
1144
* one, try to guess the type of address based on the
1145
* OctetString SIZE - 4 for IPv4, 16 for IPv6, others currently
1146
* not supported.
1147
*/
1148
static char *
1149
snmp_oct2inetaddr(uint32_t len, char *octets, char *buf)
1150
{
1151
int af;
1152
void *ip;
1153
struct in_addr ipv4;
1154
struct in6_addr ipv6;
1155
1156
if (len > MAX_OCTSTRING_LEN || octets == NULL || buf == NULL)
1157
return (NULL);
1158
1159
switch (len) {
1160
/* XXX: FIXME - IPv4*/
1161
case 4:
1162
memcpy(&ipv4.s_addr, octets, sizeof(ipv4.s_addr));
1163
af = AF_INET;
1164
ip = &ipv4;
1165
break;
1166
1167
/* XXX: FIXME - IPv4*/
1168
case 16:
1169
memcpy(ipv6.s6_addr, octets, sizeof(ipv6.s6_addr));
1170
af = AF_INET6;
1171
ip = &ipv6;
1172
break;
1173
1174
default:
1175
return (NULL);
1176
}
1177
1178
if (inet_ntop(af, ip, buf, SNMP_INADDRS_STRSZ) == NULL) {
1179
warn("inet_ntop failed");
1180
return (NULL);
1181
}
1182
1183
return (buf);
1184
}
1185
1186
static char *
1187
snmp_inetaddr2oct(char *str __unused, struct asn_oid *oid __unused)
1188
{
1189
return (NULL);
1190
}
1191
1192
static int32_t
1193
parse_inetaddr(struct snmp_value *value __unused, char *string __unused)
1194
{
1195
return (-1);
1196
}
1197
1198
/**************************************************************
1199
* SNMP BITS type - XXX: FIXME
1200
**************************************************************/
1201
static char *
1202
snmp_oct2bits(uint32_t len, char *octets, char *buf)
1203
{
1204
int i, bits;
1205
uint64_t value;
1206
1207
if (len > sizeof(value) || octets == NULL || buf == NULL)
1208
return (NULL);
1209
1210
for (i = len, value = 0, bits = 0; i > 0; i--, bits += 8)
1211
value += octets[i] << bits;
1212
1213
buf[0]= '\0';
1214
sprintf(buf, "0x%llx.",(long long unsigned) value);
1215
1216
return (buf);
1217
}
1218
1219
static char *
1220
snmp_bits2oct(char *str, struct asn_oid *oid)
1221
{
1222
char *endptr;
1223
int i, size, bits, saved_errno;
1224
uint64_t v, mask = 0xFF00000000000000;
1225
1226
saved_errno = errno;
1227
errno = 0;
1228
1229
v = strtoull(str, &endptr, 16);
1230
if (errno != 0) {
1231
warn("Bad BITS value %s", str);
1232
errno = saved_errno;
1233
return (NULL);
1234
}
1235
1236
bits = 8;
1237
/* Determine length - up to 8 octets supported so far. */
1238
for (size = sizeof(v); size > 0; size--) {
1239
if ((v & mask) != 0)
1240
break;
1241
mask = mask >> bits;
1242
}
1243
1244
if (size == 0)
1245
size = 1;
1246
1247
if (snmp_suboid_append(oid, (asn_subid_t) size) < 0)
1248
return (NULL);
1249
1250
for (i = 0, bits = 0; i < size; i++, bits += 8)
1251
if (snmp_suboid_append(oid,
1252
(asn_subid_t)((v & mask) >> bits)) < 0)
1253
return (NULL);
1254
1255
return (endptr);
1256
}
1257
1258
static int32_t
1259
parse_bits(struct snmp_value *value, char *string)
1260
{
1261
char *endptr;
1262
int i, size, bits, saved_errno;
1263
uint64_t v, mask = 0xFF00000000000000;
1264
1265
saved_errno = errno;
1266
errno = 0;
1267
1268
v = strtoull(string, &endptr, 16);
1269
1270
if (errno != 0) {
1271
warn("Bad BITS value %s", string);
1272
errno = saved_errno;
1273
return (-1);
1274
}
1275
1276
bits = 8;
1277
/* Determine length - up to 8 octets supported so far. */
1278
for (size = sizeof(v); size > 0; size--) {
1279
if ((v & mask) != 0)
1280
break;
1281
mask = mask >> bits;
1282
}
1283
1284
if (size == 0)
1285
size = 1;
1286
1287
if ((value->v.octetstring.octets = malloc(size)) == NULL) {
1288
syslog(LOG_ERR, "malloc failed: %s", strerror(errno));
1289
return (-1);
1290
}
1291
1292
value->v.octetstring.len = size;
1293
for (i = 0, bits = 0; i < size; i++, bits += 8)
1294
value->v.octetstring.octets[i] = (v & mask) >> bits;
1295
value->syntax = SNMP_SYNTAX_OCTETSTRING;
1296
return (1);
1297
}
1298
1299