diff --git a/contrib/bsnmp/gensnmptree/gensnmptree.c b/contrib/bsnmp/gensnmptree/gensnmptree.c index f2dc4fd68c6..304e31e4bc7 100644 --- a/contrib/bsnmp/gensnmptree/gensnmptree.c +++ b/contrib/bsnmp/gensnmptree/gensnmptree.c @@ -406,6 +406,7 @@ static const struct { { "UNSIGNED32", TOK_TYPE, SNMP_SYNTAX_GAUGE }, { "OCTETSTRING", TOK_TYPE, SNMP_SYNTAX_OCTETSTRING }, { "IPADDRESS", TOK_TYPE, SNMP_SYNTAX_IPADDRESS }, + { "IP6ADDRESS", TOK_TYPE, SNMP_SYNTAX_IP6ADDRESS }, { "OID", TOK_TYPE, SNMP_SYNTAX_OID }, { "TIMETICKS", TOK_TYPE, SNMP_SYNTAX_TIMETICKS }, { "COUNTER", TOK_TYPE, SNMP_SYNTAX_COUNTER }, @@ -963,6 +964,10 @@ gen_node(FILE *fp, struct node *np, struct asn_oid *oid, u_int idx, fprintf(fp, "SNMP_SYNTAX_IPADDRESS, "); break; + case SNMP_SYNTAX_IP6ADDRESS: + fprintf(fp, "SNMP_SYNTAX_IP6ADDRESS, "); + break; + case SNMP_SYNTAX_OID: fprintf(fp, "SNMP_SYNTAX_OID, "); break; diff --git a/contrib/bsnmp/lib/asn1.c b/contrib/bsnmp/lib/asn1.c index 03b5662ed22..5ad690e39cc 100644 --- a/contrib/bsnmp/lib/asn1.c +++ b/contrib/bsnmp/lib/asn1.c @@ -738,8 +738,9 @@ asn_get_sequence(struct asn_buf *b, asn_len_t *len) * * 0x40 4 MSB 2MSB 2LSB LSB */ -enum asn_err -asn_get_ipaddress_raw(struct asn_buf *b, asn_len_t len, u_char *addr) +static enum asn_err +_asn_get_ipaddress_raw(struct asn_buf *b, asn_len_t len, u_char *addr, + asn_len_t addrlen) { u_int i; @@ -747,7 +748,7 @@ asn_get_ipaddress_raw(struct asn_buf *b, asn_len_t len, u_char *addr) asn_error(b, "truncated ip-address"); return (ASN_ERR_EOBUF); } - if (len < 4) { + if (len < addrlen) { asn_error(b, "short length for ip-Address %u", len); for (i = 0; i < len; i++) *addr++ = *b->asn_cptr++; @@ -756,46 +757,94 @@ asn_get_ipaddress_raw(struct asn_buf *b, asn_len_t len, u_char *addr) b->asn_len -= len; return (ASN_ERR_BADLEN); } - for (i = 0; i < 4; i++) + for (i = 0; i < addrlen; i++) *addr++ = *b->asn_cptr++; - b->asn_cptr += len - 4; + b->asn_cptr += len - addrlen; b->asn_len -= len; return (ASN_ERR_OK); } -enum asn_err -asn_get_ipaddress(struct asn_buf *b, u_char *addr) +static enum asn_err +_asn_get_ipaddress(struct asn_buf *b, u_char *addr, asn_len_t addrlen, + u_char apptype) { - u_char type; asn_len_t len; enum asn_err err; + u_char type; if ((err = asn_get_header(b, &type, &len)) != ASN_ERR_OK) return (err); - if (type != (ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS)) { - asn_error(b, "bad type for ip-address %u", type); + if (type != (ASN_CLASS_APPLICATION | apptype)) { + asn_error(b, "bad type for ip-address 0x%02x", type); return (ASN_ERR_TAG); } - return (asn_get_ipaddress_raw(b, len, addr)); + return (_asn_get_ipaddress_raw(b, len, addr, addrlen)); } -enum asn_err -asn_put_ipaddress(struct asn_buf *b, const u_char *addr) +static enum asn_err +_asn_put_ipaddress(struct asn_buf *b, const u_char *addr, asn_len_t addrlen, + u_char apptype) { enum asn_err err; - if ((err = asn_put_header(b, ASN_CLASS_APPLICATION|ASN_APP_IPADDRESS, - 4)) != ASN_ERR_OK) + if ((err = asn_put_header(b, ASN_CLASS_APPLICATION | apptype, + addrlen)) != ASN_ERR_OK) return (err); - if (b->asn_len < 4) + if (b->asn_len < addrlen) return (ASN_ERR_EOBUF); - memcpy(b->asn_ptr, addr, 4); - b->asn_ptr += 4; - b->asn_len -= 4; + memcpy(b->asn_ptr, addr, addrlen); + b->asn_ptr += addrlen; + b->asn_len -= addrlen; return (ASN_ERR_OK); } +#define IP4ADDRLEN 4 +enum asn_err +asn_get_ipaddress_raw(struct asn_buf *b, asn_len_t len, u_char *addr) +{ + + return (_asn_get_ipaddress_raw(b, len, addr, IP4ADDRLEN)); +} + +enum asn_err +asn_get_ipaddress(struct asn_buf *b, u_char *addr) +{ + + return (_asn_get_ipaddress(b, addr, IP4ADDRLEN, ASN_APP_IPADDRESS)); +} + +enum asn_err +asn_put_ipaddress(struct asn_buf *b, const u_char *addr) +{ + + return (_asn_put_ipaddress(b, addr, IP4ADDRLEN, ASN_APP_IPADDRESS)); +} + +#define IP6ADDRLEN 16 +enum asn_err +asn_get_ip6address_raw(struct asn_buf *b, asn_len_t len, u_char *addr) +{ + + return (_asn_get_ipaddress_raw(b, len, addr, IP6ADDRLEN)); +} + +enum asn_err +asn_get_ip6address(struct asn_buf *b, u_char *addr) +{ + + return (_asn_get_ipaddress(b, addr, IP6ADDRLEN, ASN_APP_IP6ADDRESS)); +} + +enum asn_err +asn_put_ip6address(struct asn_buf *b, const u_char *addr) +{ + + return (_asn_put_ipaddress(b, addr, IP6ADDRLEN, ASN_APP_IP6ADDRESS)); +} + +#undef IP4ADDRLEN +#undef IP6ADDRLEN /* * UNSIGNED32 diff --git a/contrib/bsnmp/lib/asn1.h b/contrib/bsnmp/lib/asn1.h index 4aded8acebe..641bb16faff 100644 --- a/contrib/bsnmp/lib/asn1.h +++ b/contrib/bsnmp/lib/asn1.h @@ -119,6 +119,10 @@ enum asn_err asn_get_ipaddress_raw(struct asn_buf *, asn_len_t, u_char *); enum asn_err asn_get_ipaddress(struct asn_buf *, u_char *); enum asn_err asn_put_ipaddress(struct asn_buf *, const u_char *); +enum asn_err asn_get_ip6address_raw(struct asn_buf *, asn_len_t, u_char *); +enum asn_err asn_get_ip6address(struct asn_buf *, u_char *); +enum asn_err asn_put_ip6address(struct asn_buf *, const u_char *); + enum asn_err asn_get_uint32_raw(struct asn_buf *, asn_len_t, uint32_t *); enum asn_err asn_put_uint32(struct asn_buf *, u_char, uint32_t); @@ -174,6 +178,7 @@ enum { ASN_APP_TIMETICKS = 0x03, ASN_APP_OPAQUE = 0x04, /* not implemented */ ASN_APP_COUNTER64 = 0x06, + ASN_APP_IP6ADDRESS = 0x07, ASN_EXCEPT_NOSUCHOBJECT = 0x00, ASN_EXCEPT_NOSUCHINSTANCE = 0x01, diff --git a/contrib/bsnmp/lib/snmp.c b/contrib/bsnmp/lib/snmp.c index d1dabc8884a..ddc3ce4b796 100644 --- a/contrib/bsnmp/lib/snmp.c +++ b/contrib/bsnmp/lib/snmp.c @@ -134,6 +134,12 @@ get_var_binding(struct asn_buf *b, struct snmp_value *binding) err = asn_get_ipaddress_raw(b, len, binding->v.ipaddress); break; + case ASN_CLASS_APPLICATION|ASN_APP_IP6ADDRESS: + binding->syntax = SNMP_SYNTAX_IP6ADDRESS; + err = asn_get_ip6address_raw(b, len, + binding->v.ip6address.addr8); + break; + case ASN_CLASS_APPLICATION|ASN_APP_TIMETICKS: binding->syntax = SNMP_SYNTAX_TIMETICKS; err = asn_get_uint32_raw(b, len, &binding->v.uint32); @@ -946,6 +952,10 @@ snmp_binding_encode(struct asn_buf *b, const struct snmp_value *binding) err = asn_put_ipaddress(b, binding->v.ipaddress); break; + case SNMP_SYNTAX_IP6ADDRESS: + err = asn_put_ip6address(b, binding->v.ip6address.addr8); + break; + case SNMP_SYNTAX_TIMETICKS: err = asn_put_uint32(b, ASN_APP_TIMETICKS, binding->v.uint32); break; @@ -1040,6 +1050,21 @@ dump_binding(const struct snmp_value *b) b->v.ipaddress[1], b->v.ipaddress[2], b->v.ipaddress[3]); break; + case SNMP_SYNTAX_IP6ADDRESS: { + struct sockaddr_in6 sin6; + + sin6.sin6_family = AF_INET6; + sin6.sin6_len = sizeof(sin6); + sin6.sin6_scope_id = b->v.ip6address.zoneid; + memcpy(&sin6.sin6_addr, b->v.ip6address.addr8, + sizeof(sin6.sin6_addr)); + if (getnameinfo((const struct sockaddr *)&sin6, + sizeof(sin6), buf, sizeof(buf), NULL, 0, + NI_NUMERICHOST) == 0) + snmp_printf("IP6ADDRESS %s", buf); + } + break; + case SNMP_SYNTAX_COUNTER: snmp_printf("COUNTER %u", b->v.uint32); break; @@ -1421,6 +1446,27 @@ snmp_value_parse(const char *str, enum snmp_syntax syntax, union snmp_values *v) if (*end != '\0') return (-1); return (0); + + case SNMP_SYNTAX_IP6ADDRESS: + { + struct sockaddr_in6 sin6; + struct addrinfo hints, *res; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_CANONNAME | AI_NUMERICHOST; + if (getaddrinfo(str, NULL, &hints, &res) != 0) + return (-1); + memcpy(&sin6, res->ai_addr, sizeof(sin6)); + memcpy(v->ip6address.addr8, &sin6.sin6_addr, + sizeof(v->ip6address.addr8)); + v->ip6address.zoneid = sin6.sin6_scope_id; + freeaddrinfo(res); + return (0); + } + } abort(); } diff --git a/contrib/bsnmp/lib/snmp.h b/contrib/bsnmp/lib/snmp.h index 61e783e76bb..15b76e386a7 100644 --- a/contrib/bsnmp/lib/snmp.h +++ b/contrib/bsnmp/lib/snmp.h @@ -63,6 +63,8 @@ enum snmp_syntax { SNMP_SYNTAX_NOSUCHOBJECT, /* exception */ SNMP_SYNTAX_NOSUCHINSTANCE, /* exception */ SNMP_SYNTAX_ENDOFMIBVIEW, /* exception */ + + SNMP_SYNTAX_IP6ADDRESS, }; struct snmp_value { @@ -76,6 +78,10 @@ struct snmp_value { } octetstring; struct asn_oid oid; u_char ipaddress[4]; + struct { + u_char addr8[16]; + uint32_t zoneid; + } ip6address; uint32_t uint32; /* also gauge32, counter32, unsigned32, timeticks */ uint64_t counter64; diff --git a/contrib/bsnmp/lib/snmpclient.c b/contrib/bsnmp/lib/snmpclient.c index bb711ee0c73..7c616f4e24e 100644 --- a/contrib/bsnmp/lib/snmpclient.c +++ b/contrib/bsnmp/lib/snmpclient.c @@ -287,6 +287,39 @@ table_find(struct tabwork *work, const struct asn_oid *var) "bad index: ipaddress too large"); goto err; } + /* XXX */ + (uint32_t *)((u_char *)e + + work->descr->entries[i].offset)[j] = + var->subs[p++]; + } + break; + + case SNMP_SYNTAX_IP6ADDRESS: + if (var->len < p + 16) { + seterr(&snmp_client, + "bad index: need ip6-address"); + goto err; + } + for (j = 0; j < 16; j++) { + if (var->subs[p] > 0xff) { + seterr(&snmp_client, + "bad index: ip6address too large"); + goto err; + } + ((u_char *)e + + work->descr->entries[i].offset)[j] = + var->subs[p++]; + } + /* Check for IPv6 link-local address */ + if (var->subs[p - 16] == 0xfe && + (var->subs[p - 15] & 0xc0) == 0x80) { + if (var->len < p + 1) { + /* scope zone id */ + seterr(&snmp_client, + "bad index: ambiguous ip6-address"); + goto err; + } + /* XXX: is pointer calculation correct here? */ ((u_char *)e + work->descr->entries[i].offset)[j] = var->subs[p++]; @@ -410,6 +443,14 @@ table_value(const struct snmp_table *descr, struct entry *e, b->v.ipaddress, 4); break; + case SNMP_SYNTAX_IP6ADDRESS: + memcpy((u_char *)e + descr->entries[i].offset, + b->v.ip6address.addr8, sizeof(b->v.ip6address.addr8)); + /* XXX */ + (uint32_t *)((u_char *)e + descr->entries[i].offset)[16] = + b->v.ip6address.zoneid; + break; + case SNMP_SYNTAX_COUNTER: case SNMP_SYNTAX_GAUGE: case SNMP_SYNTAX_TIMETICKS: @@ -742,13 +783,13 @@ snmp_table_fetch_async(const struct snmp_table *descr, void *list, int snmp_oid_append(struct asn_oid *oid, const char *fmt, ...) { - va_list va; - int size; - char *nextptr; + struct sockaddr_in6 *sin6; const u_char *str; - size_t len; + char *nextptr; + va_list va; + size_t len; struct in_addr ina; - int ret; + int i, ret, size; va_start(va, fmt); @@ -781,6 +822,28 @@ snmp_oid_append(struct asn_oid *oid, const char *fmt, ...) oid->subs[oid->len++] = (ina.s_addr >> 8) & 0xff; oid->subs[oid->len++] = (ina.s_addr >> 0) & 0xff; break; + case 'A': + /* append an IP6 address */ + if (oid->len + 16 > ASN_MAXOIDLEN) { + warnx("%s: OID too long for ip6-addr", + __func__); + ret = -1; + break; + } + sin6 = va_arg(va, struct sockaddr_in6 *); + for (i = 0; i < 16; i++) + oid->subs[oid->len++] = + sin6->sin6_addr->s6_addr[i]; + if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) { + if (oid->len + 1 > ASN_MAXOIDLEN) { + warnx("%s: OID too long for ip6-addr", + __func__); + ret = -1; + } else + oid->subs[oid->len++] = + sin6->sin6_scope_id; + } + break; case 's': /* append a null-terminated string, @@ -879,7 +942,7 @@ snmp_client_init(struct snmp_client *c) * Open UDP client socket */ static int -open_client_udp(const char *host, const char *port) +open_client_udp(int family, const char *host, const char *port) { int error; char *ptr; @@ -923,10 +986,10 @@ open_client_udp(const char *host, const char *port) /* open connection */ memset(&hints, 0, sizeof(hints)); - hints.ai_flags = AI_CANONNAME; - hints.ai_family = AF_INET; + hints.ai_flags = AI_CANONNAME | AI_NUMERICHOST; + hints.ai_family = family; hints.ai_socktype = SOCK_DGRAM; - hints.ai_protocol = 0; + hints.ai_protocol = IPPROTO_UDP; error = getaddrinfo(snmp_client.chost, snmp_client.cport, &hints, &res0); if (error != 0) { seterr(&snmp_client, "%s: %s", snmp_client.chost, @@ -1068,7 +1131,12 @@ snmp_open(const char *host, const char *port, const char *readcomm, switch (snmp_client.trans) { case SNMP_TRANS_UDP: - if (open_client_udp(host, port) != 0) + if (open_client_udp(AF_INET, host, port) != 0) + return (-1); + break; + + case SNMP_TRANS_UDP6: + if (open_client_udp(AF_INET6, host, port) != 0) return (-1); break; @@ -1870,12 +1938,24 @@ snmp_client_set_port(struct snmp_client *cl, const char *p) * parse a server specification * * [trans::][community@][server][:port] + * + * For IPv6 server can be specified like: + * community@[2001::1]:port + * udp6::community@server:port */ int snmp_parse_server(struct snmp_client *sc, const char *str) { const char *p, *s = str; + /* look for square brackets */ + for (p = s; *p != '\0'; p++) { + if (*p == '[') { + sc->trans = SNMP_TRANS_UDP6; + break; + } + } + /* look for a double colon */ for (p = s; *p != '\0'; p++) { if (*p == '\\' && p[1] != '\0') { @@ -1889,6 +1969,8 @@ snmp_parse_server(struct snmp_client *sc, const char *str) if (p > s) { if (p - s == 3 && strncmp(s, "udp", 3) == 0) sc->trans = SNMP_TRANS_UDP; + else if (p - s == 4 && strncmp(s, "udp6", 4) == 0) + sc->trans = SNMP_TRANS_UDP6; else if (p - s == 6 && strncmp(s, "stream", 6) == 0) sc->trans = SNMP_TRANS_LOC_STREAM; else if (p - s == 5 && strncmp(s, "dgram", 5) == 0) diff --git a/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt b/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt index 0a68ed9e9ec..b6968481a5a 100644 --- a/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt +++ b/contrib/bsnmp/snmpd/BEGEMOT-SNMPD.txt @@ -457,6 +457,58 @@ begemotSnmpdDebugSyslogPri OBJECT-TYPE DEFVAL { 7 } -- don't log debug messages ::= { begemotSnmpdDebug 3 } +-- +-- SNMP INET6 port table +-- +begemotSnmpdPort6Table OBJECT-TYPE + SYNTAX SEQUENCE OF BegemotSnmpdPort6Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A table with descriptions of UDP ports to listen on + for SNMP messages." + ::= { begemotSnmpdObjects 4 } + +begemotSnmpdPort6Entry OBJECT-TYPE + SYNTAX BegemotSnmpdPort6Entry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry in the table with descriptions of UDP ports to + listen on for SNMP messages." + INDEX { begemotSnmpdPort6Address, begemotSnmpdPort6Port } + ::= { begemotSnmpdPort6Table 1 } + +BegemotSnmpdPort6Entry ::= SEQUENCE { + begemotSnmpdPort6Address Ip6Address, + begemotSnmpdPort6Port INTEGER, + begemotSnmpdPort6Status INTEGER +} + +begemotSnmpdPort6Address OBJECT-TYPE + SYNTAX Ip6Address + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The IP6 address to bind to." + ::= { begemotSnmpdPort6Entry 1 } + +begemotSnmpdPort6Port OBJECT-TYPE + SYNTAX INTEGER (1..65535) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "The UDP port to listen on for SNMP messages." + ::= { begemotSnmpdPort6Entry 2 } + +begemotSnmpdPort6Status OBJECT-TYPE + SYNTAX INTEGER { valid(1), invalid(2) } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Set status to 1 to create entry, set it to 2 to delete it." + ::= { begemotSnmpdPort6Entry 3 } + -- -- Local port table -- diff --git a/contrib/bsnmp/snmpd/config.c b/contrib/bsnmp/snmpd/config.c index fd07bab481e..dcdbf24558e 100644 --- a/contrib/bsnmp/snmpd/config.c +++ b/contrib/bsnmp/snmpd/config.c @@ -775,31 +775,30 @@ parse_section(const struct lmodule *mod) * Convert a hostname to four u_chars */ static void -gethost(const char *host, u_char *ip) +gethost(const char *host, int family, struct sockaddr *sa) { struct addrinfo hints, *res; int error; - struct sockaddr_in *sain; memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; + hints.ai_family = family; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; - hints.ai_flags = AI_PASSIVE; + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_CANONNAME; error = getaddrinfo(host, NULL, &hints, &res); if (error != 0) report("%s: %s", host, gai_strerror(error)); if (res == NULL) report("%s: unknown hostname", host); - sain = (struct sockaddr_in *)(void *)res->ai_addr; - sain->sin_addr.s_addr = ntohl(sain->sin_addr.s_addr); - ip[0] = sain->sin_addr.s_addr >> 24; - ip[1] = sain->sin_addr.s_addr >> 16; - ip[2] = sain->sin_addr.s_addr >> 8; - ip[3] = sain->sin_addr.s_addr >> 0; - - freeaddrinfo(res); + if (res->ai_family != AF_INET && res->ai_family != AF_INET6) { + error = res->ai_family; + freeaddrinfo(res); + report("%s: unsupported address family %d", host, error); + } else { + memcpy(sa, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + } } /* @@ -808,10 +807,13 @@ gethost(const char *host, u_char *ip) static const struct snmp_node * parse_oid(const char *varname, struct asn_oid *oid) { + struct asn_oid str_oid; + union { + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } sun; struct snmp_node *node; u_int i; - u_char ip[4]; - struct asn_oid str_oid; for (node = tree; node < &tree[tree_size]; node++) if (strcmp(varname, node->name) == 0) @@ -850,12 +852,27 @@ parse_oid(const char *varname, struct asn_oid *oid) gettoken(); } else if (token == TOK_HOST) { - gethost(strval, ip); - if (oid->len + 4 > ASN_MAXOIDLEN) - report("index too long"); - for (i = 0; i < 4; i++) - oid->subs[oid->len++] = ip[i]; + gethost(strval, AF_UNSPEC, (struct sockaddr *)&sun); gettoken(); + if (sun.sin.sin_family == AF_INET) { + if (oid->len + 4 > ASN_MAXOIDLEN) + report("index too long"); + sun.sin.sin_addr.s_addr = + ntohl(sun.sin.sin_addr.s_addr); + for (i = 0; i < 4; i++) + oid->subs[oid->len++] = (uint8_t) + (sun.sin.sin_addr.s_addr >> ( + (3 - i) * 8)); + continue; + } + /* AF_INET6: 16 subs for addr8 and one for zoneid */ + if (oid->len + 17 > ASN_MAXOIDLEN) + report("index too long"); + for (i = 0; i < 16; i++) + oid->subs[oid->len++] = + sun.sin6.sin6_addr.s6_addr[i]; + if (IN6_IS_ADDR_LINKLOCAL(&sun.sin6.sin6_addr)) + oid->subs[oid->len++] = sun.sin6.sin6_scope_id; } else report("bad token in index"); } @@ -969,8 +986,8 @@ parse_syntax_oid(struct snmp_value *value) static void parse_syntax_ipaddress(struct snmp_value *value) { + struct sockaddr_in sin; int i; - u_char ip[4]; if (token == TOK_NUM) { /* numerical address */ @@ -988,15 +1005,28 @@ parse_syntax_ipaddress(struct snmp_value *value) } else if (token == TOK_HOST) { /* host name */ - gethost(strval, ip); - for (i = 0; i < 4; i++) - value->v.ipaddress[i] = ip[i]; + gethost(strval, AF_INET, (struct sockaddr *)&sin); + memcpy(value->v.ipaddress, &sin.sin_addr, + sizeof(sin.sin_addr)); gettoken(); - } else report("bad ip address syntax"); } +static void +parse_syntax_ip6address(struct snmp_value *value) +{ + struct sockaddr_in6 sin6; + + if (token != TOK_HOST) + report("bad ip6 address syntax"); + gethost(strval, AF_INET6, (struct sockaddr *)&sin6); + memcpy(value->v.ip6address.addr8, &sin6.sin6_addr, + sizeof(sin6.sin6_addr)); + value->v.ip6address.zoneid = sin6.sin6_scope_id; + gettoken(); +} + static void parse_syntax_uint32(struct snmp_value *value) { @@ -1059,6 +1089,10 @@ parse_assign(const char *varname) parse_syntax_ipaddress(&value); break; + case SNMP_SYNTAX_IP6ADDRESS: + parse_syntax_ip6address(&value); + break; + case SNMP_SYNTAX_COUNTER: case SNMP_SYNTAX_GAUGE: case SNMP_SYNTAX_TIMETICKS: diff --git a/contrib/bsnmp/snmpd/export.c b/contrib/bsnmp/snmpd/export.c index 3135606587e..19e8b892c4e 100644 --- a/contrib/bsnmp/snmpd/export.c +++ b/contrib/bsnmp/snmpd/export.c @@ -331,6 +331,29 @@ index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...) } break; } + case SNMP_SYNTAX_IP6ADDRESS: + { + struct sockaddr_in6 *pval; + u_int i; + + if (sub + 16 > oid->len) + goto err; + pval = va_arg(ap, struct sockaddr_in6 *); + memset(pval, 0, sizeof(*pval)); + pval->sin6_family = AF_INET6; + pval->sin6_len = sizeof(*pval); + for (i = 0; i < 16; i++) { + if (oid->subs[sub] > 0xff) + goto err; + pval->sin6_addr.s6_addr[i] = oid->subs[sub++]; + } + if (IN6_IS_ADDR_LINKLOCAL(&pval->sin6_addr)) { + if (sub + 1 > oid->len) + goto err; + pval->sin6_scope_id = oid->subs[sub++]; + } + break; + } case SNMP_SYNTAX_COUNTER: case SNMP_SYNTAX_GAUGE: diff --git a/contrib/bsnmp/snmpd/snmpd.config b/contrib/bsnmp/snmpd/snmpd.config index f9f88410837..1ef13c4f54b 100644 --- a/contrib/bsnmp/snmpd/snmpd.config +++ b/contrib/bsnmp/snmpd/snmpd.config @@ -75,6 +75,10 @@ begemotSnmpdCommunityDisable = 1 begemotSnmpdPortStatus.[$(host)].161 = 1 begemotSnmpdPortStatus.127.0.0.1.161 = 1 +begemotSnmpdInet6PortStatus.[$(host)].161 = 1 +begemotSnmpdInet6PortStatus.[::1].161 = 1 +begemotSnmpdInet6PortStatus.[fe80::1%igb0].161 = 1 + # open a unix domain socket begemotSnmpdLocalPortStatus."/var/run/snmpd.sock" = 1 begemotSnmpdLocalPortType."/var/run/snmpd.sock" = 4 diff --git a/contrib/bsnmp/snmpd/snmpmod.3 b/contrib/bsnmp/snmpd/snmpmod.3 index ca92bea84d0..5041f606bb5 100644 --- a/contrib/bsnmp/snmpd/snmpmod.3 +++ b/contrib/bsnmp/snmpd/snmpmod.3 @@ -1121,6 +1121,10 @@ is expected as argument. A .Vt u_int8_t * expected as argument that points to a buffer of at least four byte. +.It Li IP6 ADDRESS +A +.Vt struct sockaddr_in6 * +expected as argument. .It Li COUNTER, GAUGE, TIMETICKS A .Vt u_int32_t diff --git a/contrib/bsnmp/snmpd/trans_udp.c b/contrib/bsnmp/snmpd/trans_udp.c index 5c9a7fd470a..5d8651947c5 100644 --- a/contrib/bsnmp/snmpd/trans_udp.c +++ b/contrib/bsnmp/snmpd/trans_udp.c @@ -436,3 +436,11 @@ op_snmp_port(struct snmp_context *ctx, struct snmp_value *value, return (SNMP_ERR_NOERROR); } + +int +op_snmp_port6(struct snmp_context *ctx __unused, struct snmp_value *value __unused, + u_int sub __unused, u_int iidx __unused, enum snmp_op op __unused) +{ + + return (SNMP_ERR_NOERROR); +} diff --git a/contrib/bsnmp/snmpd/tree.def b/contrib/bsnmp/snmpd/tree.def index 2b6a9b98d9a..164a5b3fd44 100644 --- a/contrib/bsnmp/snmpd/tree.def +++ b/contrib/bsnmp/snmpd/tree.def @@ -182,6 +182,15 @@ typedef RowStatus ENUM ( (2 begemotSnmpdTransUdp OID op_transport_dummy) (3 begemotSnmpdTransLsock OID op_transport_dummy) ) +# +# Port6 table +# + (11 begemotSnmpdPort6Table + (1 begemotSnmpdPort6Entry : IP6ADDRESS INTEGER op_snmp_port6 + (1 begemotSnmpdPort6Address IP6ADDRESS) + (2 begemotSnmpdPort6Port UNSIGNED32) + (3 begemotSnmpdPort6Status INTEGER GET SET) + )) ) (2 begemotSnmpdDefs (1 begemotSnmpdAgent