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