diff --git a/distrib/sets/lists/base/mi b/distrib/sets/lists/base/mi index 2612a790f..f74540b9f 100644 --- a/distrib/sets/lists/base/mi +++ b/distrib/sets/lists/base/mi @@ -6521,6 +6521,7 @@ ./usr/share/zoneinfo/tzdata.zi ./usr/share/zoneinfo/zone.tab ./usr/share/zoneinfo/zone1970.tab +./usr/share/zoneinfo/zonenow.tab ./var ./var/account ./var/agentx diff --git a/regress/lib/libz/infcover.c b/regress/lib/libz/infcover.c index 2be01646c..2109aaebb 100644 --- a/regress/lib/libz/infcover.c +++ b/regress/lib/libz/infcover.c @@ -185,7 +185,7 @@ local void mem_used(z_stream *strm, char *prefix) { struct mem_zone *zone = strm->opaque; - fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); + fprintf(stderr, "%s: %zu allocated\n", prefix, zone->total); } /* show the high water allocation in bytes */ @@ -193,7 +193,7 @@ local void mem_high(z_stream *strm, char *prefix) { struct mem_zone *zone = strm->opaque; - fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); + fprintf(stderr, "%s: %zu high water mark\n", prefix, zone->highwater); } /* release the memory allocation zone -- if there are any surprises, notify */ @@ -218,7 +218,7 @@ local void mem_done(z_stream *strm, char *prefix) /* issue alerts about anything unexpected */ if (count || zone->total) - fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", + fprintf(stderr, "** %s: %zu bytes in %d blocks not freed\n", prefix, zone->total, count); if (zone->notlifo) fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); diff --git a/regress/usr.bin/snmp/Makefile b/regress/usr.bin/snmp/Makefile index a4c0f6776..983efc2dd 100644 --- a/regress/usr.bin/snmp/Makefile +++ b/regress/usr.bin/snmp/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.6 2023/11/06 09:46:04 martijn Exp $ +# $OpenBSD: Makefile,v 1.7 2024/02/08 17:09:51 martijn Exp $ SNMP?= /usr/bin/snmp SNMPD?= /usr/sbin/snmpd -f ${.OBJDIR}/snmpd.conf @@ -31,6 +31,7 @@ snmpd.conf: Makefile printf 'listen on $$listen6_addr snmpv1 snmpv2c snmpv3\n' >> snmpd.conf printf 'listen on tcp $$listen6_addr snmpv1 snmpv2c snmpv3\n' >> snmpd.conf printf 'listen on $$listen_addr notify snmpv1 snmpv2c snmpv3\n\n' >> snmpd.conf + printf 'agentx path "/tmp/agentx"\n\n' >> snmpd.conf printf 'read-only community public\n' >> snmpd.conf printf 'read-write community private\n' >> snmpd.conf printf 'trap community public\n\n' >> snmpd.conf @@ -79,7 +80,19 @@ trap_output: Makefile chmod a+rw trap_output start: stop snmpd.conf traphandle.sh trap_output + rm -f /tmp/agentx 2>/dev/null ${SUDO} ${SNMPD} + @(i=0; \ + while [ ! -S /tmp/agentx ]; do \ + i=$$((i + 1)); \ + [ $$i -eq 100 ] && ( \ + printf "%s\n" '${SUDO} pkill -xf "${SNMPD}"'; \ + printf "Failed to start snmpd\n" >&2; \ + ${SUDO} pkill -xf "${SNMPD}"; \ + exit 1; \ + ); \ + sleep 0.1; \ + done;) stop: -${SUDO} pkill -xf "${SNMPD}" diff --git a/regress/usr.sbin/snmpd/Makefile b/regress/usr.sbin/snmpd/Makefile index 63b0fc017..e77825dc3 100644 --- a/regress/usr.sbin/snmpd/Makefile +++ b/regress/usr.sbin/snmpd/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.12 2023/11/20 10:34:21 martijn Exp $ +# $OpenBSD: Makefile,v 1.14 2024/02/08 17:38:41 martijn Exp $ # Regress tests for snmpd PROG = snmpd_regress @@ -146,6 +146,12 @@ BACKEND_TARGETS+= backend_get_close_overlap BACKEND_TARGETS+= backend_get_disappear BACKEND_TARGETS+= backend_get_disappear_overlap BACKEND_TARGETS+= backend_get_disappear_doublesession +BACKEND_TARGETS+= backend_get_octetstring_max +BACKEND_TARGETS+= backend_get_octetstring_too_long +BACKEND_TARGETS+= backend_get_ipaddress_too_short +BACKEND_TARGETS+= backend_get_ipaddress_too_long +BACKEND_TARGETS+= backend_get_opaque_non_ber +BACKEND_TARGETS+= backend_get_opaque_double_value BACKEND_TARGETS+= backend_getnext_selfbound BACKEND_TARGETS+= backend_getnext_lowerbound BACKEND_TARGETS+= backend_getnext_lowerbound_self @@ -261,8 +267,21 @@ transport: ${TRANSPORT_TARGETS} ${REGRESS_TARGETS}: snmpd_regress # Always start snmpd if it's not running - @pgrep -q snmpd || \ - (printf "%s\n" "${SNMPD_START}"; ${SNMPD_START} sleep 0.5) + @pgrep -q snmpd || ( \ + printf "%s\n" "${SNMPD_START}"; \ + rm -f /tmp/agentx 2>/dev/null; \ + ${SNMPD_START} \ + i=0; \ + while [ ! -S /tmp/agentx ]; do \ + i=$$((i + 1)); \ + [ $$i -eq 100 ] && ( \ + printf "Failed to start snmpd\n"; >&2 \ + ${SUDO} pkill -f ${SNMPD}; \ + exit 1; \ + ); \ + sleep 0.1; \ + done \ + ) ./snmpd_regress ${SNMPD_REGRESS_FLAGS} $@ # Make sure that snmpd hasn't crashed in the meantime. @sleep 0.01 diff --git a/regress/usr.sbin/snmpd/backend.c b/regress/usr.sbin/snmpd/backend.c index 86af8de4b..689cce7f8 100644 --- a/regress/usr.sbin/snmpd/backend.c +++ b/regress/usr.sbin/snmpd/backend.c @@ -1,6 +1,7 @@ #include #include +#include #include #include #include @@ -294,12 +295,13 @@ backend_get_opaque(void) struct varbind varbind = { .type = TYPE_NULL, .name = OID_STRUCT(MIB_BACKEND_GET, 8, 0), - .data.octetstring.string = "\1", - .data.octetstring.len = 1 }; int32_t requestid; char buf[1024]; size_t n; + struct ber ber = {}; + struct ber_element *elm; + ssize_t len; ax_s = agentx_connect(axsocket); sessionid = agentx_open(ax_s, 0, 0, @@ -314,11 +316,20 @@ backend_get_opaque(void) n = agentx_read(ax_s, buf, sizeof(buf), 1000); agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1); + if ((elm = ober_add_integer(NULL, 1)) == NULL) + err(1, "ober_add_integer"); + if (ober_write_elements(&ber, elm) == -1) + err(1, "ober_write_elements"); + varbind.data.octetstring.len = ober_get_writebuf( + &ber, (void **)&varbind.data.octetstring.string); + ober_free_elements(elm); + varbind.type = TYPE_OPAQUE; agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1); snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0, &varbind, 1); + ober_free(&ber); } void @@ -1382,6 +1393,261 @@ backend_get_disappear_doublesession(void) &varbind, 1); } +void +backend_get_octetstring_max(void) +{ + struct sockaddr_storage ss; + struct sockaddr *sa = (struct sockaddr *)&ss; + socklen_t salen; + int snmp_s, ax_s; + uint32_t sessionid; + char vbbuf[65535] = {}; + struct varbind varbind = { + .type = TYPE_NULL, + .name = OID_STRUCT(MIB_BACKEND_GET, 34, 0), + .data.octetstring.string = vbbuf, + .data.octetstring.len = sizeof(vbbuf) + }; + int32_t requestid; + char buf[1024]; + size_t n; + + memset(vbbuf, 'a', sizeof(vbbuf)); + ax_s = agentx_connect(axsocket); + sessionid = agentx_open(ax_s, 0, 0, + OID_ARG(MIB_SUBAGENT_BACKEND_GET, 34), __func__); + agentx_register(ax_s, sessionid, 0, 0, 127, 0, + OID_ARG(MIB_BACKEND_GET, 34), 0); + + /* Too big for SOCK_DGRAM */ + salen = snmp_resolve(SOCK_STREAM, hostname, servname, sa); + snmp_s = snmp_connect(SOCK_STREAM, sa, salen); + requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1); + + n = agentx_read(ax_s, buf, sizeof(buf), 1000); + agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1); + + varbind.type = TYPE_OCTETSTRING; + agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1); + + snmpv2_response_validate(snmp_s, 1000, community, requestid, 0, 0, + &varbind, 1); +} + +void +backend_get_octetstring_too_long(void) +{ + struct sockaddr_storage ss; + struct sockaddr *sa = (struct sockaddr *)&ss; + socklen_t salen; + int snmp_s, ax_s; + uint32_t sessionid; + char vbbuf[65536]; + struct varbind varbind = { + .type = TYPE_NULL, + .name = OID_STRUCT(MIB_BACKEND_GET, 35, 0), + .data.octetstring.string = vbbuf, + .data.octetstring.len = sizeof(vbbuf) + }; + int32_t requestid; + char buf[1024]; + size_t n; + + memset(vbbuf, 'a', sizeof(vbbuf)); + ax_s = agentx_connect(axsocket); + sessionid = agentx_open(ax_s, 0, 0, + OID_ARG(MIB_SUBAGENT_BACKEND_GET, 35), __func__); + agentx_register(ax_s, sessionid, 0, 0, 127, 0, + OID_ARG(MIB_BACKEND_GET, 35), 0); + + salen = snmp_resolve(SOCK_STREAM, hostname, servname, sa); + snmp_s = snmp_connect(SOCK_STREAM, sa, salen); + requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1); + + n = agentx_read(ax_s, buf, sizeof(buf), 1000); + agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1); + + varbind.type = TYPE_OCTETSTRING; + agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1); + + varbind.type = TYPE_NULL; + snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1, + &varbind, 1); +} + +void +backend_get_ipaddress_too_short(void) +{ + struct sockaddr_storage ss; + struct sockaddr *sa = (struct sockaddr *)&ss; + socklen_t salen; + int snmp_s, ax_s; + uint32_t sessionid; + struct varbind varbind = { + .type = TYPE_NULL, + .name = OID_STRUCT(MIB_BACKEND_GET, 36, 0), + .data.octetstring.string = "\0\0\0", + .data.octetstring.len = 3 + }; + int32_t requestid; + char buf[1024]; + size_t n; + + ax_s = agentx_connect(axsocket); + sessionid = agentx_open(ax_s, 0, 0, + OID_ARG(MIB_SUBAGENT_BACKEND_GET, 36), __func__); + agentx_register(ax_s, sessionid, 0, 0, 127, 0, + OID_ARG(MIB_BACKEND_GET, 36), 0); + + salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa); + snmp_s = snmp_connect(SOCK_DGRAM, sa, salen); + requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1); + + n = agentx_read(ax_s, buf, sizeof(buf), 1000); + agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1); + + varbind.type = TYPE_IPADDRESS; + agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1); + + varbind.type = TYPE_NULL; + snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1, + &varbind, 1); +} + +void +backend_get_ipaddress_too_long(void) +{ + struct sockaddr_storage ss; + struct sockaddr *sa = (struct sockaddr *)&ss; + socklen_t salen; + int snmp_s, ax_s; + uint32_t sessionid; + struct varbind varbind = { + .type = TYPE_NULL, + .name = OID_STRUCT(MIB_BACKEND_GET, 37, 0), + .data.octetstring.string = "\0\0\0\0\0", + .data.octetstring.len = 5 + }; + int32_t requestid; + char buf[1024]; + size_t n; + + ax_s = agentx_connect(axsocket); + sessionid = agentx_open(ax_s, 0, 0, + OID_ARG(MIB_SUBAGENT_BACKEND_GET, 37), __func__); + agentx_register(ax_s, sessionid, 0, 0, 127, 0, + OID_ARG(MIB_BACKEND_GET, 37), 0); + + salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa); + snmp_s = snmp_connect(SOCK_DGRAM, sa, salen); + requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1); + + n = agentx_read(ax_s, buf, sizeof(buf), 1000); + agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1); + + varbind.type = TYPE_IPADDRESS; + agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1); + + varbind.type = TYPE_NULL; + snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1, + &varbind, 1); +} + +void +backend_get_opaque_non_ber(void) +{ + struct sockaddr_storage ss; + struct sockaddr *sa = (struct sockaddr *)&ss; + socklen_t salen; + int snmp_s, ax_s; + uint32_t sessionid; + struct varbind varbind = { + .type = TYPE_NULL, + .name = OID_STRUCT(MIB_BACKEND_GET, 38, 0), + .data.octetstring.string = "\1", + .data.octetstring.len = 1 + }; + int32_t requestid; + char buf[1024]; + size_t n; + ssize_t len; + + ax_s = agentx_connect(axsocket); + sessionid = agentx_open(ax_s, 0, 0, + OID_ARG(MIB_SUBAGENT_BACKEND_GET, 38), __func__); + agentx_register(ax_s, sessionid, 0, 0, 127, 0, + OID_ARG(MIB_BACKEND_GET, 38), 0); + + salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa); + snmp_s = snmp_connect(SOCK_DGRAM, sa, salen); + requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1); + + n = agentx_read(ax_s, buf, sizeof(buf), 1000); + agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1); + + varbind.type = TYPE_OPAQUE; + agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1); + + varbind.type = TYPE_NULL; + snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1, + &varbind, 1); +} + +void +backend_get_opaque_double_value(void) +{ + struct sockaddr_storage ss; + struct sockaddr *sa = (struct sockaddr *)&ss; + socklen_t salen; + int snmp_s, ax_s; + uint32_t sessionid; + char vbbuf[1024]; + struct varbind varbind = { + .type = TYPE_NULL, + .name = OID_STRUCT(MIB_BACKEND_GET, 39, 0), + .data.octetstring.string = vbbuf + }; + int32_t requestid; + void *berdata; + char buf[1024]; + size_t n; + struct ber ber = {}; + struct ber_element *elm; + ssize_t len; + + ax_s = agentx_connect(axsocket); + sessionid = agentx_open(ax_s, 0, 0, + OID_ARG(MIB_SUBAGENT_BACKEND_GET, 39), __func__); + agentx_register(ax_s, sessionid, 0, 0, 127, 0, + OID_ARG(MIB_BACKEND_GET, 39), 0); + + salen = snmp_resolve(SOCK_DGRAM, hostname, servname, sa); + snmp_s = snmp_connect(SOCK_DGRAM, sa, salen); + requestid = snmpv2_get(snmp_s, community, 0, &varbind, 1); + + n = agentx_read(ax_s, buf, sizeof(buf), 1000); + agentx_get_handle(__func__, buf, n, 0, sessionid, &varbind, 1); + + if ((elm = ober_add_integer(NULL, 1)) == NULL) + err(1, "ober_add_integer"); + if (ober_write_elements(&ber, elm) == -1) + err(1, "ober_write_elements"); + len = ober_get_writebuf(&ber, &berdata); + ober_free_elements(elm); + + memcpy(vbbuf, berdata, len); + memcpy(vbbuf + len, berdata, len); + varbind.data.octetstring.len = 2 * len; + + varbind.type = TYPE_OPAQUE; + agentx_response(ax_s, buf, NOERROR, 0, &varbind, 1); + + varbind.type = TYPE_NULL; + snmpv2_response_validate(snmp_s, 1000, community, requestid, GENERR, 1, + &varbind, 1); + ober_free(&ber); +} + void backend_getnext_selfbound(void) { diff --git a/regress/usr.sbin/snmpd/regress.h b/regress/usr.sbin/snmpd/regress.h index b63a58723..54f43eefc 100644 --- a/regress/usr.sbin/snmpd/regress.h +++ b/regress/usr.sbin/snmpd/regress.h @@ -289,6 +289,12 @@ void backend_get_close_overlap(void); void backend_get_disappear(void); void backend_get_disappear_overlap(void); void backend_get_disappear_doublesession(void); +void backend_get_octetstring_max(void); +void backend_get_octetstring_too_long(void); +void backend_get_ipaddress_too_short(void); +void backend_get_ipaddress_too_long(void); +void backend_get_opaque_non_ber(void); +void backend_get_opaque_double_value(void); void backend_getnext_selfbound(void); void backend_getnext_lowerbound(void); void backend_getnext_lowerbound_self(void); diff --git a/regress/usr.sbin/snmpd/snmp.c b/regress/usr.sbin/snmpd/snmp.c index d2e105edf..ebdcea972 100644 --- a/regress/usr.sbin/snmpd/snmp.c +++ b/regress/usr.sbin/snmpd/snmp.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -288,7 +289,7 @@ snmpv2_response_validate(int s, int timeout, const char *community, struct varbind *varbindlist, size_t nvarbind) { struct ber_element *message, *pdu; - char buf[1024]; + char buf[100000]; size_t buflen = sizeof(buf); message = snmp_recv(s, timeout, buf, &buflen); @@ -311,22 +312,30 @@ snmp_recv(int s, int timeout, void *buf, size_t *buflen) struct ber ber = {}; struct ber_element *message; ssize_t n; + size_t ntot = 0; int ret; + again: if ((ret = poll(&pfd, 1, timeout)) == -1) err(1, "poll"); - if (ret == 0) - errx(1, "%s: timeout", __func__); - if ((n = read(s, buf, *buflen)) == -1) - err(1, "agentx read"); - - *buflen = n; + if (ret == 0) { + if (ntot == 0) + errx(1, "%s: timeout", __func__); + errc(1, ECANCELED, "%s: unable to decode message", __func__); + } + if ((n = read(s, buf + ntot, *buflen - ntot)) == -1) + err(1, "snmp read"); + ntot += n; ober_set_application(&ber, smi_application); - ober_set_readbuf(&ber, buf, n); + ober_set_readbuf(&ber, buf, ntot); - if ((message = ober_read_elements(&ber, NULL)) == NULL) + if ((message = ober_read_elements(&ber, NULL)) == NULL) { + if (errno == ECANCELED) + goto again; errx(1, "%s: unable to decode message", __func__); + } + *buflen = n; if (verbose) { printf("SNMP received(%d):\n", s); smi_debug_elements(message); diff --git a/regress/usr.sbin/snmpd/snmpd.sh b/regress/usr.sbin/snmpd/snmpd.sh index 29438e33c..137d0f7aa 100644 --- a/regress/usr.sbin/snmpd/snmpd.sh +++ b/regress/usr.sbin/snmpd/snmpd.sh @@ -1,6 +1,6 @@ #!/bin/sh # -# $OpenBSD: snmpd.sh,v 1.19 2023/11/04 09:42:17 martijn Exp $ +# $OpenBSD: snmpd.sh,v 1.20 2024/02/08 17:09:51 martijn Exp $ #/* # * Copyright (c) Rob Pierce # * @@ -26,6 +26,8 @@ SLEEP=1 PF[0]="disabled" PF[1]="enabled" +STARTSOCK="/tmp/agentx" + # This file will be creatred by traphandler.c as user _snmpd TMPFILE=$(mktemp -q /tmp/_snmpd_traptest.XXXXXX) @@ -38,7 +40,30 @@ then exit 0 fi +snmpdstart() { + rm "${STARTSOCK}" >/dev/null 2>&1 + (cd ${OBJDIR} && nohup snmpd -dvf ./snmpd.conf > snmpd.log 2>&1) & + i=0 + # wait max ~10s + while [ ! -S "$STARTSOCK" ]; do + i=$((i + 1)) + if [ $i -eq 100 ]; then + echo "Failed to start snmpd" >&2 + snmpdstop + fail + fi + sleep 0.1 + done +} + +snmpdstop() { + pkill snmpd + wait + rm -f "${STARTSOCK}" >/dev/null 2>&1 +} + cleanup() { + rm ${STARTSOCK} >/dev/null 2>&1 rm ${TMPFILE} >/dev/null 2>&1 rm ${OBJDIR}/nohup.out >/dev/null 2>&1 rm ${OBJDIR}/snmpd.log >/dev/null 2>&1 @@ -69,6 +94,8 @@ listen on 127.0.0.1 snmpv2c notify listen on ::1 snmpv1 snmpv2c snmpv3 listen on ::1 snmpv2c notify +agentx path "${STARTSOCK}" + # Specify communities read-only community public read-write community private @@ -77,11 +104,7 @@ trap community public trap handle 1.2.3.4 "/usr/bin/touch ${TMPFILE}" EOF -(cd ${OBJDIR} && nohup snmpd -dvf ./snmpd.conf > snmpd.log 2>&1) & - -sleep ${SLEEP} - -[ ! -n "$(pgrep snmpd)" ] && echo "Failed to start snmpd." && fail +snmpdstart # pf (also checks "oid all" which obtains privileged kernel data @@ -166,8 +189,7 @@ fi # FAILED=1 #fi -kill $(pgrep snmpd) >/dev/null 2>&1 -wait +snmpdstop # # # # # CONFIG TWO # # # # # echo "\nConfiguration: seclevel auth\n" @@ -178,16 +200,14 @@ cat > ${OBJDIR}/snmpd.conf < snmpd.log 2>&1) & - -sleep ${SLEEP} - -[ ! -n "$(pgrep snmpd)" ] && echo "Failed to start snmpd." && fail +snmpdstart # make sure we can't get an oid with deault community string @@ -213,8 +233,7 @@ then FAILED=1 fi -kill $(pgrep snmpd) >/dev/null 2>&1 -wait +snmpdstop # # # # # CONFIG THREE # # # # # echo "\nConfiguration: seclevel enc\n" @@ -225,16 +244,14 @@ cat > ${OBJDIR}/snmpd.conf < snmpd.log 2>&1) & - -sleep ${SLEEP} - -[ ! -n "$(pgrep snmpd)" ] && echo "Failed to start snmpd." && fail +snmpdstart # get with SHA authentication and AES encryption @@ -249,8 +266,7 @@ then FAILED=1 fi -kill $(pgrep snmpd) >/dev/null 2>&1 -wait +snmpdstop # # # # # CONFIG FOUR # # # # # echo "\nConfiguration: non-default community strings, custom oids\n" @@ -264,6 +280,8 @@ cat > ${OBJDIR}/snmpd.conf < snmpd.log 2>&1) & - -sleep ${SLEEP} - -[ ! -n "$(pgrep snmpd)" ] && echo "Failed to start snmpd." && fail +snmpdstart # carp allow with non-default ro community string @@ -343,7 +357,7 @@ fi # FAILED=1 #fi -kill $(pgrep snmpd) >/dev/null 2>&1 +snmpdstop case $FAILED in 0) echo diff --git a/regress/usr.sbin/snmpd/snmpd_regress.c b/regress/usr.sbin/snmpd/snmpd_regress.c index 044f843e4..2c6ff362b 100644 --- a/regress/usr.sbin/snmpd/snmpd_regress.c +++ b/regress/usr.sbin/snmpd/snmpd_regress.c @@ -118,6 +118,12 @@ const struct { { "backend_get_disappear", backend_get_disappear }, { "backend_get_disappear_overlap", backend_get_disappear_overlap }, { "backend_get_disappear_doublesession", backend_get_disappear_doublesession }, + { "backend_get_octetstring_max", backend_get_octetstring_max }, + { "backend_get_octetstring_too_long", backend_get_octetstring_too_long }, + { "backend_get_ipaddress_too_short", backend_get_ipaddress_too_short }, + { "backend_get_ipaddress_too_long", backend_get_ipaddress_too_long }, + { "backend_get_opaque_non_ber", backend_get_opaque_non_ber }, + { "backend_get_opaque_double_value", backend_get_opaque_double_value }, { "backend_getnext_selfbound", backend_getnext_selfbound }, { "backend_getnext_lowerbound", backend_getnext_lowerbound }, { "backend_getnext_lowerbound_self", backend_getnext_lowerbound_self }, diff --git a/sys/dev/ic/qwx.c b/sys/dev/ic/qwx.c index 784fe71c7..920cad162 100644 --- a/sys/dev/ic/qwx.c +++ b/sys/dev/ic/qwx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: qwx.c,v 1.18 2024/02/06 14:18:15 stsp Exp $ */ +/* $OpenBSD: qwx.c,v 1.28 2024/02/08 14:36:22 stsp Exp $ */ /* * Copyright 2023 Stefan Sperling @@ -8249,7 +8249,7 @@ qwx_qmi_load_file_target_mem(struct qwx_softc *sc, const u_char *data, #ifdef notyet void *bdf_addr = NULL; #endif - int ret; + int ret = EINVAL; /* empty fw image */ uint32_t remaining = len; req = malloc(sizeof(*req), M_DEVBUF, M_NOWAIT | M_ZERO); @@ -8393,7 +8393,7 @@ qwx_qmi_load_bdf_qmi(struct qwx_softc *sc, int regdb) fw_size = MIN(sc->hw_params.fw.board_size, boardfw_len); ret = qwx_qmi_load_file_target_mem(sc, boardfw, fw_size, bdf_type); - if (ret < 0) { + if (ret) { printf("%s: failed to load bdf file\n", __func__); goto out; } @@ -9403,6 +9403,10 @@ qwx_dp_shadow_start_timer(struct qwx_softc *sc, struct hal_srng *srng, if (!sc->hw_params.supports_shadow_regs) return; + update_timer->tx_num++; + if (update_timer->started) + return; + update_timer->started = 1; update_timer->timer_tx_num = update_timer->tx_num; @@ -11422,7 +11426,7 @@ qwx_peer_assoc_conf_event(struct qwx_softc *sc, struct mbuf *m) DNPRINTF(QWX_D_WMI, "%s: event peer assoc conf ev vdev id %d " "macaddr %s\n", __func__, peer_assoc_conf.vdev_id, - ether_sprintf(peer_assoc_conf.macaddr)); + ether_sprintf((u_char *)peer_assoc_conf.macaddr)); sc->peer_assoc_done = 1; wakeup(&sc->peer_assoc_done); @@ -12729,6 +12733,9 @@ qwx_wmi_process_mgmt_tx_comp(struct qwx_softc *sc, if (arvif->txmgmt.queued > 0) arvif->txmgmt.queued--; + if (arvif->txmgmt.queued < nitems(arvif->txmgmt.data) - 1) + sc->qfullmsk &= ~(1U << QWX_MGMT_QUEUE_ID); + if (tx_compl_param->status != 0) ifp->if_oerrors++; } @@ -12752,6 +12759,93 @@ qwx_mgmt_tx_compl_event(struct qwx_softc *sc, struct mbuf *m) tx_compl_param.status, tx_compl_param.ack_rssi); } +int +qwx_pull_roam_ev(struct qwx_softc *sc, struct mbuf *m, + struct wmi_roam_event *roam_ev) +{ + const void **tb; + const struct wmi_roam_event *ev; + int ret; + + tb = qwx_wmi_tlv_parse_alloc(sc, mtod(m, void *), m->m_pkthdr.len); + if (tb == NULL) { + ret = ENOMEM; + printf("%s: failed to parse tlv: %d\n", + sc->sc_dev.dv_xname, ret); + return ret; + } + + ev = tb[WMI_TAG_ROAM_EVENT]; + if (!ev) { + printf("%s: failed to fetch roam ev\n", + sc->sc_dev.dv_xname); + free(tb, M_DEVBUF, WMI_TAG_MAX * sizeof(*tb)); + return EPROTO; + } + + roam_ev->vdev_id = ev->vdev_id; + roam_ev->reason = ev->reason; + roam_ev->rssi = ev->rssi; + + free(tb, M_DEVBUF, WMI_TAG_MAX * sizeof(*tb)); + return 0; +} + +void +qwx_mac_handle_beacon_miss(struct qwx_softc *sc, uint32_t vdev_id) +{ + struct ieee80211com *ic = &sc->sc_ic; + + if ((ic->ic_opmode != IEEE80211_M_STA) || + (ic->ic_state != IEEE80211_S_RUN)) + return; + + if (ic->ic_mgt_timer == 0) { + if (ic->ic_if.if_flags & IFF_DEBUG) + printf("%s: receiving no beacons from %s; checking if " + "this AP is still responding to probe requests\n", + sc->sc_dev.dv_xname, + ether_sprintf(ic->ic_bss->ni_macaddr)); + /* + * Rather than go directly to scan state, try to send a + * directed probe request first. If that fails then the + * state machine will drop us into scanning after timing + * out waiting for a probe response. + */ + IEEE80211_SEND_MGMT(ic, ic->ic_bss, + IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0); + } +} + +void +qwx_roam_event(struct qwx_softc *sc, struct mbuf *m) +{ + struct wmi_roam_event roam_ev = {}; + + if (qwx_pull_roam_ev(sc, m, &roam_ev) != 0) { + printf("%s: failed to extract roam event\n", + sc->sc_dev.dv_xname); + return; + } + + DNPRINTF(QWX_D_WMI, "%s: event roam vdev %u reason 0x%08x rssi %d\n", + __func__, roam_ev.vdev_id, roam_ev.reason, roam_ev.rssi); + + if (roam_ev.reason >= WMI_ROAM_REASON_MAX) + return; + + switch (roam_ev.reason) { + case WMI_ROAM_REASON_BEACON_MISS: + qwx_mac_handle_beacon_miss(sc, roam_ev.vdev_id); + break; + case WMI_ROAM_REASON_BETTER_AP: + case WMI_ROAM_REASON_LOW_RSSI: + case WMI_ROAM_REASON_SUITABLE_AP_FOUND: + case WMI_ROAM_REASON_HO_FAILED: + break; + } +} + void qwx_wmi_tlv_op_rx(struct qwx_softc *sc, struct mbuf *m) { @@ -12813,10 +12907,10 @@ qwx_wmi_tlv_op_rx(struct qwx_softc *sc, struct mbuf *m) case WMI_PEER_STA_KICKOUT_EVENTID: ath11k_peer_sta_kickout_event(ab, skb); break; - case WMI_ROAM_EVENTID: - ath11k_roam_event(ab, skb); - break; #endif + case WMI_ROAM_EVENTID: + qwx_roam_event(sc, m); + break; case WMI_CHAN_INFO_EVENTID: DPRINTF("%s: 0x%x: chan info event\n", __func__, id); qwx_chan_info_event(sc, m); @@ -14692,11 +14786,77 @@ qwx_dp_tx_status_parse(struct qwx_softc *sc, struct hal_wbm_release_ring *desc, ts->rate_stats = 0; } +void +qwx_dp_tx_free_txbuf(struct qwx_softc *sc, int msdu_id, + struct dp_tx_ring *tx_ring) +{ + struct qwx_tx_data *tx_data; + + if (msdu_id >= sc->hw_params.tx_ring_size) + return; + + tx_data = &tx_ring->data[msdu_id]; + + bus_dmamap_unload(sc->sc_dmat, tx_data->map); + m_freem(tx_data->m); + tx_data->m = NULL; + + if (tx_ring->queued > 0) + tx_ring->queued--; +} + +void +qwx_dp_tx_htt_tx_complete_buf(struct qwx_softc *sc, struct dp_tx_ring *tx_ring, + struct qwx_dp_htt_wbm_tx_status *ts) +{ + /* Not using Tx status info for now. Just free the buffer. */ + qwx_dp_tx_free_txbuf(sc, ts->msdu_id, tx_ring); +} + void qwx_dp_tx_process_htt_tx_complete(struct qwx_softc *sc, void *desc, uint8_t mac_id, uint32_t msdu_id, struct dp_tx_ring *tx_ring) { - printf("%s: not implemented\n", __func__); + struct htt_tx_wbm_completion *status_desc; + struct qwx_dp_htt_wbm_tx_status ts = {0}; + enum hal_wbm_htt_tx_comp_status wbm_status; + + status_desc = desc + HTT_TX_WBM_COMP_STATUS_OFFSET; + + wbm_status = FIELD_GET(HTT_TX_WBM_COMP_INFO0_STATUS, + status_desc->info0); + + switch (wbm_status) { + case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_TTL: + ts.acked = (wbm_status == HAL_WBM_REL_HTT_TX_COMP_STATUS_OK); + ts.msdu_id = msdu_id; + ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO1_ACK_RSSI, + status_desc->info1); + + if (FIELD_GET(HTT_TX_WBM_COMP_INFO2_VALID, status_desc->info2)) + ts.peer_id = FIELD_GET(HTT_TX_WBM_COMP_INFO2_SW_PEER_ID, + status_desc->info2); + else + ts.peer_id = HTT_INVALID_PEER_ID; + + qwx_dp_tx_htt_tx_complete_buf(sc, tx_ring, &ts); + break; + case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ: + case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT: + qwx_dp_tx_free_txbuf(sc, msdu_id, tx_ring); + break; + case HAL_WBM_REL_HTT_TX_COMP_STATUS_MEC_NOTIFY: + /* This event is to be handled only when the driver decides to + * use WDS offload functionality. + */ + break; + default: + printf("%s: Unknown htt tx status %d\n", + sc->sc_dev.dv_xname, wbm_status); + break; + } } void @@ -14801,6 +14961,9 @@ qwx_dp_tx_completion_handler(struct qwx_softc *sc, int ring_id) qwx_dp_tx_complete_msdu(sc, tx_ring, msdu_id, &ts); } + if (tx_ring->queued < sc->hw_params.tx_ring_size - 1) + sc->qfullmsk &= ~(1 << ring_id); + return 0; } @@ -15189,6 +15352,7 @@ qwx_dp_rx_process_msdu(struct qwx_softc *sc, struct qwx_rx_msdu *msdu, if (msdu->is_frag) { m_adj(msdu->m, hal_rx_desc_sz); + msdu->m->m_len = msdu->m->m_pkthdr.len = msdu_len; } else if (!msdu->is_continuation) { if ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE) { #if 0 @@ -15207,6 +15371,7 @@ qwx_dp_rx_process_msdu(struct qwx_softc *sc, struct qwx_rx_msdu *msdu, return EINVAL; } m_adj(msdu->m, hal_rx_desc_sz + l3_pad_bytes); + msdu->m->m_len = msdu->m->m_pkthdr.len = msdu_len; } else { ret = qwx_dp_rx_msdu_coalesce(sc, msdu_list, msdu, last_buf, l3_pad_bytes, msdu_len); @@ -15496,9 +15661,9 @@ qwx_dp_rx_reap_mon_status_ring(struct qwx_softc *sc, int mac_id, } bus_dmamap_sync(sc->sc_dmat, rx_data->map, 0, - m->m_pkthdr.len, BUS_DMASYNC_POSTREAD); + rx_data->m->m_pkthdr.len, BUS_DMASYNC_POSTREAD); - tlv = mtod(m, struct hal_tlv_hdr *); + tlv = mtod(rx_data->m, struct hal_tlv_hdr *); if (FIELD_GET(HAL_TLV_HDR_TAG, tlv->tl) != HAL_RX_STATUS_BUFFER_DONE) { printf("%s: mon status DONE not set %lx, " @@ -17414,7 +17579,7 @@ qwx_wmi_vdev_up(struct qwx_softc *sc, uint32_t vdev_id, uint32_t pdev_id, } DNPRINTF(QWX_D_WMI, "%s: cmd vdev up id 0x%x assoc id %d bssid %s\n", - __func__, vdev_id, aid, ether_sprintf(bssid)); + __func__, vdev_id, aid, ether_sprintf((u_char *)bssid)); return 0; } @@ -22061,7 +22226,6 @@ qwx_dp_tx(struct qwx_softc *sc, struct qwx_vif *arvif, uint8_t pdev_id, if (test_bit(ATH11K_FLAG_CRASH_FLUSH, sc->sc_flags)) { m_freem(m); - printf("%s: crash flush\n", __func__); return ESHUTDOWN; } #if 0 @@ -22112,10 +22276,8 @@ qwx_dp_tx(struct qwx_softc *sc, struct qwx_vif *arvif, uint8_t pdev_id, if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { k = ieee80211_get_txkey(ic, wh, ni); - if ((m = ieee80211_encrypt(ic, m, k)) == NULL) { - printf("%s: encrypt failed\n", __func__); + if ((m = ieee80211_encrypt(ic, m, k)) == NULL) return ENOBUFS; - } /* 802.11 header may have moved. */ wh = mtod(m, struct ieee80211_frame *); } @@ -22169,12 +22331,27 @@ qwx_dp_tx(struct qwx_softc *sc, struct qwx_vif *arvif, uint8_t pdev_id, #endif ret = bus_dmamap_load_mbuf(sc->sc_dmat, tx_data->map, m, BUS_DMA_WRITE | BUS_DMA_NOWAIT); - if (ret) { + if (ret && ret != EFBIG) { printf("%s: failed to map Tx buffer: %d\n", sc->sc_dev.dv_xname, ret); m_freem(m); return ret; } + if (ret) { + /* Too many DMA segments, linearize mbuf. */ + if (m_defrag(m, M_DONTWAIT)) { + m_freem(m); + return ENOBUFS; + } + ret = bus_dmamap_load_mbuf(sc->sc_dmat, tx_data->map, m, + BUS_DMA_NOWAIT | BUS_DMA_WRITE); + if (ret) { + printf("%s: failed to map Tx buffer: %d\n", + sc->sc_dev.dv_xname, ret); + m_freem(m); + return ret; + } + } ti.paddr = tx_data->map->dm_segs[0].ds_addr; ti.data_len = m->m_pkthdr.len; @@ -22188,7 +22365,6 @@ qwx_dp_tx(struct qwx_softc *sc, struct qwx_vif *arvif, uint8_t pdev_id, hal_tcl_desc = (void *)qwx_hal_srng_src_get_next_entry(sc, tcl_ring); if (!hal_tcl_desc) { - printf("%s: hal_tcl_desc == NULL\n", __func__); /* NOTE: It is highly unlikely we'll be running out of tcl_ring * desc because the desc is directly enqueued onto hw queue. */ @@ -22217,6 +22393,10 @@ qwx_dp_tx(struct qwx_softc *sc, struct qwx_vif *arvif, uint8_t pdev_id, #endif tx_ring->queued++; tx_ring->cur = (tx_ring->cur + 1) % sc->hw_params.tx_ring_size; + + if (tx_ring->queued >= sc->hw_params.tx_ring_size - 1) + sc->qfullmsk |= (1 << ti.ring_id); + return 0; } @@ -22288,11 +22468,26 @@ qwx_mac_mgmt_tx_wmi(struct qwx_softc *sc, struct qwx_vif *arvif, #endif ret = bus_dmamap_load_mbuf(sc->sc_dmat, tx_data->map, m, BUS_DMA_WRITE | BUS_DMA_NOWAIT); - if (ret) { + if (ret && ret != EFBIG) { printf("%s: failed to map mgmt Tx buffer: %d\n", sc->sc_dev.dv_xname, ret); return ret; } + if (ret) { + /* Too many DMA segments, linearize mbuf. */ + if (m_defrag(m, M_DONTWAIT)) { + m_freem(m); + return ENOBUFS; + } + ret = bus_dmamap_load_mbuf(sc->sc_dmat, tx_data->map, m, + BUS_DMA_NOWAIT | BUS_DMA_WRITE); + if (ret) { + printf("%s: failed to map mgmt Tx buffer: %d\n", + sc->sc_dev.dv_xname, ret); + m_freem(m); + return ret; + } + } ret = qwx_wmi_mgmt_send(sc, arvif, pdev_id, buf_id, m, tx_data); if (ret) { @@ -22303,6 +22498,10 @@ qwx_mac_mgmt_tx_wmi(struct qwx_softc *sc, struct qwx_vif *arvif, txmgmt->cur = (txmgmt->cur + 1) % nitems(txmgmt->data); txmgmt->queued++; + + if (txmgmt->queued >= nitems(txmgmt->data) - 1) + sc->qfullmsk |= (1U << QWX_MGMT_QUEUE_ID); + return 0; err_unmap_buf: @@ -23065,8 +23264,7 @@ qwx_run(struct qwx_softc *sc) #endif DNPRINTF(QWX_D_MAC, "%s: vdev %d up (associated) bssid %s aid %d\n", - __func__, arvif->vdev_id, ether_sprintf(ni->ni_bssid), - vif->cfg.aid); + __func__, arvif->vdev_id, ether_sprintf(ni->ni_bssid), arvif->aid); ret = qwx_wmi_set_peer_param(sc, ni->ni_macaddr, arvif->vdev_id, pdev_id, WMI_PEER_AUTHORIZE, 1); diff --git a/sys/dev/ic/qwxvar.h b/sys/dev/ic/qwxvar.h index bb2c0f33e..7bb50bac8 100644 --- a/sys/dev/ic/qwxvar.h +++ b/sys/dev/ic/qwxvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: qwxvar.h,v 1.12 2024/02/06 14:18:15 stsp Exp $ */ +/* $OpenBSD: qwxvar.h,v 1.14 2024/02/08 14:35:07 stsp Exp $ */ /* * Copyright (c) 2018-2019 The Linux Foundation. @@ -842,6 +842,13 @@ void qwx_dp_htt_htc_t2h_msg_handler(struct qwx_softc *, struct mbuf *); struct qwx_dp; +struct qwx_dp_htt_wbm_tx_status { + uint32_t msdu_id; + int acked; + int ack_rssi; + uint16_t peer_id; +}; + #define DP_NUM_CLIENTS_MAX 64 #define DP_AVG_TIDS_PER_CLIENT 2 #define DP_NUM_TIDS_MAX (DP_NUM_CLIENTS_MAX * DP_AVG_TIDS_PER_CLIENT) @@ -1675,6 +1682,7 @@ struct qwx_softc { int sc_tx_timer; uint32_t qfullmsk; +#define QWX_MGMT_QUEUE_ID 31 bus_addr_t mem; struct ath11k_hw_params hw_params; diff --git a/sys/dev/mii/ytphy.c b/sys/dev/mii/ytphy.c index 85e5e85e6..dcac444cd 100644 --- a/sys/dev/mii/ytphy.c +++ b/sys/dev/mii/ytphy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ytphy.c,v 1.4 2023/09/01 20:35:31 kettenis Exp $ */ +/* $OpenBSD: ytphy.c,v 1.5 2024/02/08 13:00:21 jsg Exp $ */ /* * Copyright (c) 2001 Theo de Raadt * Copyright (c) 2023 Mark Kettenis @@ -58,9 +58,9 @@ #define YT8521_EXT_CHIP_CONFIG 0xa001 #define YT8521_RXC_DLY_EN (1 << 8) #define YT8521_CFG_LDO_MASK (0x3 << 4) -#define YT8521_CFG_LDO_3V3 0x0 -#define YT8521_CFG_LDO_2V5 0x1 -#define YT8521_CFG_LDO_1V8 0x2 /* or 0x3 */ +#define YT8521_CFG_LDO_3V3 (0x0 << 4) +#define YT8521_CFG_LDO_2V5 (0x1 << 4) +#define YT8521_CFG_LDO_1V8 (0x2 << 4) /* or 0x3 */ #define YT8521_EXT_RGMII_CONFIG1 0xa003 #define YT8521_TX_CLK_SEL (1 << 14) #define YT8521_RX_DELAY_SEL_MASK (0xf << 10) diff --git a/usr.sbin/snmpd/application.c b/usr.sbin/snmpd/application.c index a9cf6fe80..5c94fc832 100644 --- a/usr.sbin/snmpd/application.c +++ b/usr.sbin/snmpd/application.c @@ -1,4 +1,4 @@ -/* $OpenBSD: application.c,v 1.42 2024/02/06 12:44:27 martijn Exp $ */ +/* $OpenBSD: application.c,v 1.43 2024/02/08 17:34:09 martijn Exp $ */ /* * Copyright (c) 2021 Martijn van Duren @@ -153,6 +153,7 @@ void appl_request_upstream_reply(struct appl_request_upstream *); int appl_varbind_valid(struct appl_varbind *, struct appl_varbind_internal *, int, int, int, const char **); int appl_error_valid(enum appl_error, enum snmp_pdutype); +unsigned int appl_ber_any(struct ber_element *); int appl_varbind_backend(struct appl_varbind_internal *); void appl_varbind_error(struct appl_varbind_internal *, enum appl_error); void appl_pdu_log(struct appl_backend *, enum snmp_pdutype, int32_t, uint16_t, @@ -1427,6 +1428,11 @@ appl_varbind_valid(struct appl_varbind *varbind, { int cmp; int eomv = 0; + long long intval; + void *buf; + size_t len; + struct ber ber; + struct ber_element *elm; if (null) next = 0; @@ -1438,36 +1444,111 @@ appl_varbind_valid(struct appl_varbind *varbind, } return 1; } + + if (null) { + if (varbind->av_value->be_class != BER_CLASS_UNIVERSAL || + varbind->av_value->be_type != BER_TYPE_NULL) { + *errstr = "expecting null value"; + return 0; + } + } else { + if (varbind->av_value->be_class == BER_CLASS_UNIVERSAL && + varbind->av_value->be_type == BER_TYPE_NULL) { + *errstr = "unexpected null value"; + return 0; + } + } + if (varbind->av_value->be_class == BER_CLASS_UNIVERSAL) { switch (varbind->av_value->be_type) { case BER_TYPE_NULL: - if (null) - break; - *errstr = "not expecting null value"; - return 0; + /* Checked above */ + break; case BER_TYPE_INTEGER: + (void)ober_get_integer(varbind->av_value, &intval); + if (intval < SMI_INTEGER_MIN) { + *errstr = "INTEGER value too small"; + return 0; + } + if (intval > SMI_INTEGER_MAX) { + *errstr = "INTEGER value too large"; + return 0; + } + break; case BER_TYPE_OCTETSTRING: + (void)ober_get_nstring(varbind->av_value, NULL, &len); + if (len > SMI_OCTETSTRING_MAX) { + *errstr = "OCTET STRING too long"; + return 0; + } + break; case BER_TYPE_OBJECT: - if (!null) - break; - /* FALLTHROUGH */ + /* validated by ber.c */ + break; default: - *errstr = "invalid value"; + *errstr = "invalid value encoding"; return 0; } } else if (varbind->av_value->be_class == BER_CLASS_APPLICATION) { switch (varbind->av_value->be_type) { case SNMP_T_IPADDR: + (void)ober_get_nstring(varbind->av_value, NULL, &len); + if (len != SMI_IPADDRESS_MAX) { + *errstr = "invalid IpAddress size"; + return 0; + } + break; case SNMP_T_COUNTER32: + (void)ober_get_integer(varbind->av_value, &intval); + if (intval < SMI_COUNTER32_MIN) { + *errstr = "Counter32 value too small"; + return 0; + } + if (intval > SMI_COUNTER32_MAX) { + *errstr = "Counter32 value too large"; + return 0; + } + break; case SNMP_T_GAUGE32: + (void)ober_get_integer(varbind->av_value, &intval); + if (intval < SMI_GAUGE32_MIN) { + *errstr = "Gauge32 value too small"; + return 0; + } + if (intval > SMI_GAUGE32_MAX) { + *errstr = "Gauge32 value too large"; + return 0; + } + break; case SNMP_T_TIMETICKS: + (void)ober_get_integer(varbind->av_value, &intval); + if (intval < SMI_TIMETICKS_MIN) { + *errstr = "TimeTicks value too small"; + return 0; + } + if (intval > SMI_TIMETICKS_MAX) { + *errstr = "TimeTicks value too large"; + return 0; + } + break; case SNMP_T_OPAQUE: + (void)ober_get_nstring(varbind->av_value, &buf, &len); + memset(&ber, 0, sizeof(ber)); + ober_set_application(&ber, appl_ber_any); + ober_set_readbuf(&ber, buf, len); + elm = ober_read_elements(&ber, NULL); + if (elm == NULL || ober_calc_len(elm) != len) { + ober_free_elements(elm); + *errstr = "Opaque not valid ber encoded value"; + return 0; + } + ober_free_elements(elm); + break; case SNMP_T_COUNTER64: - if (!null) - break; - /* FALLTHROUGH */ + /* Maximum value supported by ber.c */ + break; default: - *errstr = "expecting null value"; + *errstr = "invalid value encoding"; return 0; } } else if (varbind->av_value->be_class == BER_CLASS_CONTEXT) { @@ -1477,22 +1558,14 @@ appl_varbind_valid(struct appl_varbind *varbind, *errstr = "Unexpected noSuchObject"; return 0; } - /* FALLTHROUGH */ + break; case APPL_EXC_NOSUCHINSTANCE: - if (null) { - *errstr = "expecting null value"; - return 0; - } if (next && request != NULL) { *errstr = "Unexpected noSuchInstance"; return 0; } break; case APPL_EXC_ENDOFMIBVIEW: - if (null) { - *errstr = "expecting null value"; - return 0; - } if (!next && request != NULL) { *errstr = "Unexpected endOfMibView"; return 0; @@ -1500,11 +1573,11 @@ appl_varbind_valid(struct appl_varbind *varbind, eomv = 1; break; default: - *errstr = "invalid exception"; + *errstr = "invalid value encoding"; return 0; } } else { - *errstr = "invalid value"; + *errstr = "invalid value encoding"; return 0; } @@ -1546,6 +1619,12 @@ appl_varbind_valid(struct appl_varbind *varbind, return 1; } +unsigned int +appl_ber_any(struct ber_element *elm) +{ + return BER_TYPE_OCTETSTRING; +} + int appl_error_valid(enum appl_error error, enum snmp_pdutype type) { diff --git a/usr.sbin/snmpd/snmp.h b/usr.sbin/snmpd/snmp.h index c0a9a0cf4..c3aad29a6 100644 --- a/usr.sbin/snmpd/snmp.h +++ b/usr.sbin/snmpd/snmp.h @@ -1,4 +1,4 @@ -/* $OpenBSD: snmp.h,v 1.20 2023/12/21 12:43:31 martijn Exp $ */ +/* $OpenBSD: snmp.h,v 1.21 2024/02/08 17:34:09 martijn Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter @@ -157,4 +157,17 @@ enum snmp_security_model { #define SNMP_MAX_TIMEWINDOW 150 /* RFC3414 */ +/* RFC2578 */ +#define SMI_INTEGER_MIN INT32_MIN +#define SMI_INTEGER_MAX INT32_MAX +#define SMI_OCTETSTRING_MAX 65535 +#define SMI_IPADDRESS_MAX 4 +#define SMI_COUNTER32_MIN 0 +#define SMI_COUNTER32_MAX UINT32_MAX +#define SMI_GAUGE32_MIN 0 +#define SMI_GAUGE32_MAX UINT32_MAX +#define SMI_TIMETICKS_MIN 0 +#define SMI_TIMETICKS_MAX UINT32_MAX + + #endif /* SNMPD_SNMP_H */