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