From: martijn Date: Thu, 1 Sep 2022 14:20:32 +0000 (+0000) Subject: Import snmpd_metrics. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=5e39b8099378bf76b55ebe1b7ea3a033c86608c7;p=openbsd Import snmpd_metrics. This contains snmpd's mib.c (and friends) adjusted for libagentx. This standalone binary is to be used by snmpd to achieve privilege separation. If people need net-snmpd, but want some of the base snmpd metrics they can start this binary as a normal daemon and connect to net-snmpd's agentx socket. Tested, Feedback, and OK sthen@ Release build test, and OK tb@ --- diff --git a/libexec/snmpd/Makefile b/libexec/snmpd/Makefile new file mode 100644 index 00000000000..06d5c442cc6 --- /dev/null +++ b/libexec/snmpd/Makefile @@ -0,0 +1,8 @@ +# from: @(#)Makefile 5.7 (Berkeley) 4/1/91 +# $OpenBSD: Makefile,v 1.1.1.1 2022/09/01 14:20:32 martijn Exp $ + +.include + +SUBDIR= snmpd_metrics + +.include diff --git a/libexec/snmpd/snmpd_metrics/Makefile b/libexec/snmpd/snmpd_metrics/Makefile new file mode 100644 index 00000000000..1b768f72e62 --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/Makefile @@ -0,0 +1,17 @@ +# $OpenBSD: Makefile,v 1.1.1.1 2022/09/01 14:20:34 martijn Exp $ + +PROG= snmpd_metrics +SRCS= mib.c log.c kroute.c pf.c timer.c util.c +MAN= snmpd_metrics.8 + +CFLAGS+= -Wall -I${.CURDIR} +CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes +CFLAGS+= -Wmissing-declarations +CFLAGS+= -Wshadow -Wpointer-arith -Wcast-qual +CFLAGS+= -Wsign-compare + +LDADD= -lagentx -levent -lkvm +DPADD= ${LIBAGENTX} ${LIBEVENT} ${LIBKVM} +BINDIR= /usr/libexec/snmpd/ + +.include diff --git a/libexec/snmpd/snmpd_metrics/kroute.c b/libexec/snmpd/snmpd_metrics/kroute.c new file mode 100644 index 00000000000..91de8d431f7 --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/kroute.c @@ -0,0 +1,1699 @@ +/* $OpenBSD: kroute.c,v 1.1.1.1 2022/09/01 14:20:33 martijn Exp $ */ + +/* + * Copyright (c) 2007, 2008 Reyk Floeter + * Copyright (c) 2004 Esben Norby + * Copyright (c) 2003, 2004 Henning Brauer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snmpd.h" + +struct ktable **krt; +u_int krt_size; + +struct { + struct event ks_ev; + u_long ks_iflastchange; + u_long ks_nroutes; /* 4 billions enough? */ + int ks_fd; + int ks_ifd; + u_short ks_nkif; +} kr_state; + +struct kroute_node { + RB_ENTRY(kroute_node) entry; + struct kroute r; + struct kroute_node *next; +}; + +struct kroute6_node { + RB_ENTRY(kroute6_node) entry; + struct kroute6 r; + struct kroute6_node *next; +}; + +struct kif_node { + RB_ENTRY(kif_node) entry; + TAILQ_HEAD(, kif_addr) addrs; + TAILQ_HEAD(, kif_arp) arps; + struct kif k; +}; + +int kroute_compare(struct kroute_node *, struct kroute_node *); +int kroute6_compare(struct kroute6_node *, struct kroute6_node *); +int kif_compare(struct kif_node *, struct kif_node *); + +void ktable_init(void); +int ktable_new(u_int, u_int); +void ktable_free(u_int); +int ktable_exists(u_int, u_int *); +struct ktable *ktable_get(u_int); +int ktable_update(u_int); + +struct kroute_node *kroute_find(struct ktable *, in_addr_t, u_int8_t, + u_int8_t); +struct kroute_node *kroute_matchgw(struct kroute_node *, + struct sockaddr_in *); +int kroute_insert(struct ktable *, struct kroute_node *); +int kroute_remove(struct ktable *, struct kroute_node *); +void kroute_clear(struct ktable *); + +struct kroute6_node *kroute6_find(struct ktable *, const struct in6_addr *, + u_int8_t, u_int8_t); +struct kroute6_node *kroute6_matchgw(struct kroute6_node *, + struct sockaddr_in6 *); +int kroute6_insert(struct ktable *, struct kroute6_node *); +int kroute6_remove(struct ktable *, struct kroute6_node *); +void kroute6_clear(struct ktable *); + +struct kif_arp *karp_find(struct sockaddr *, u_short); +int karp_insert(struct kif_node *, struct kif_arp *); +int karp_remove(struct kif_node *, struct kif_arp *); + +struct kif_node *kif_find(u_short); +struct kif_node *kif_insert(u_short); +int kif_remove(struct kif_node *); +void kif_clear(void); +struct kif *kif_update(u_short, int, struct if_data *, + struct sockaddr_dl *); + +int ka_compare(struct kif_addr *, struct kif_addr *); +void ka_insert(u_short, struct kif_addr *); +struct kif_addr *ka_find(struct sockaddr *); +int ka_remove(struct kif_addr *); + +u_int8_t prefixlen_classful(in_addr_t); +u_int8_t mask2prefixlen(in_addr_t); +in_addr_t prefixlen2mask(u_int8_t); +u_int8_t mask2prefixlen6(struct sockaddr_in6 *); +struct in6_addr *prefixlen2mask6(u_int8_t); +void get_rtaddrs(int, struct sockaddr *, struct sockaddr **); +void if_change(u_short, int, struct if_data *, struct sockaddr_dl *); +void if_newaddr(u_short, struct sockaddr *, struct sockaddr *, + struct sockaddr *); +void if_deladdr(u_short, struct sockaddr *, struct sockaddr *, + struct sockaddr *); +void if_announce(void *); + +int fetchtable(struct ktable *); +int fetchifs(u_short); +int fetcharp(struct ktable *); +void dispatch_rtmsg(int, short, void *); +int rtmsg_process(char *, int); +int dispatch_rtmsg_addr(struct ktable *, struct rt_msghdr *, + struct sockaddr *[RTAX_MAX]); + +RB_PROTOTYPE(kroute_tree, kroute_node, entry, kroute_compare) +RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare) + +RB_PROTOTYPE(kroute6_tree, kroute6_node, entry, kroute6_compare) +RB_GENERATE(kroute6_tree, kroute6_node, entry, kroute6_compare) + +RB_HEAD(kif_tree, kif_node) kit; +RB_PROTOTYPE(kif_tree, kif_node, entry, kif_compare) +RB_GENERATE(kif_tree, kif_node, entry, kif_compare) + +RB_HEAD(ka_tree, kif_addr) kat; +RB_PROTOTYPE(ka_tree, kif_addr, node, ka_compare) +RB_GENERATE(ka_tree, kif_addr, node, ka_compare) + +void +kr_init(void) +{ + int opt = 0, rcvbuf, default_rcvbuf; + unsigned int tid = RTABLE_ANY; + socklen_t optlen; + + if ((kr_state.ks_ifd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + fatal("kr_init: ioctl socket"); + + if ((kr_state.ks_fd = socket(AF_ROUTE, SOCK_RAW, 0)) == -1) + fatal("kr_init: route socket"); + + /* not interested in my own messages */ + if (setsockopt(kr_state.ks_fd, SOL_SOCKET, SO_USELOOPBACK, + &opt, sizeof(opt)) == -1) + log_warn("%s: SO_USELOOPBACK", __func__); /* not fatal */ + + if (snmpd_env->sc_rtfilter && setsockopt(kr_state.ks_fd, AF_ROUTE, + ROUTE_MSGFILTER, &snmpd_env->sc_rtfilter, + sizeof(snmpd_env->sc_rtfilter)) == -1) + log_warn("%s: ROUTE_MSGFILTER", __func__); + + /* grow receive buffer, don't wanna miss messages */ + optlen = sizeof(default_rcvbuf); + if (getsockopt(kr_state.ks_fd, SOL_SOCKET, SO_RCVBUF, + &default_rcvbuf, &optlen) == -1) + log_warn("%s: SO_RCVBUF", __func__); + else + for (rcvbuf = MAX_RTSOCK_BUF; + rcvbuf > default_rcvbuf && + setsockopt(kr_state.ks_fd, SOL_SOCKET, SO_RCVBUF, + &rcvbuf, sizeof(rcvbuf)) == -1 && errno == ENOBUFS; + rcvbuf /= 2) + ; /* nothing */ + + if (setsockopt(kr_state.ks_fd, AF_ROUTE, ROUTE_TABLEFILTER, &tid, + sizeof(tid)) == -1) + log_warn("%s: ROUTE_TABLEFILTER", __func__); + + RB_INIT(&kit); + RB_INIT(&kat); + + if (fetchifs(0) == -1) + fatalx("kr_init: fetchifs"); + + ktable_init(); + + event_set(&kr_state.ks_ev, kr_state.ks_fd, EV_READ | EV_PERSIST, + dispatch_rtmsg, NULL); + event_add(&kr_state.ks_ev, NULL); +} + +void +ktable_init(void) +{ + u_int i; + + for (i = 0; i <= RT_TABLEID_MAX; i++) + if (ktable_exists(i, NULL)) + ktable_update(i); +} + +int +ktable_new(u_int rtableid, u_int rdomid) +{ + struct ktable **xkrt; + struct ktable *kt; + size_t newsize, oldsize; + + /* resize index table if needed */ + if (rtableid >= krt_size) { + if ((xkrt = reallocarray(krt, rtableid + 1, + sizeof(struct ktable *))) == NULL) { + log_warn("%s: realloc", __func__); + return (-1); + } + krt = xkrt; + oldsize = krt_size * sizeof(struct ktable *); + krt_size = rtableid + 1; + newsize = krt_size * sizeof(struct ktable *); + bzero((char *)krt + oldsize, newsize - oldsize); + } + + if (krt[rtableid]) + fatalx("ktable_new: table already exists"); + + /* allocate new element */ + kt = krt[rtableid] = calloc(1, sizeof(struct ktable)); + if (kt == NULL) { + log_warn("%s: calloc", __func__); + return (-1); + } + + /* initialize structure ... */ + RB_INIT(&kt->krt); + RB_INIT(&kt->krt6); + kt->rtableid = rtableid; + kt->rdomain = rdomid; + + /* ... and load it */ + if (fetchtable(kt) == -1) + return (-1); + /* load arp information */ + if (fetcharp(kt) == -1) + return (-1); + + log_debug("%s: new ktable for rtableid %d", __func__, rtableid); + return (0); +} + +void +ktable_free(u_int rtableid) +{ + struct ktable *kt; + + if ((kt = ktable_get(rtableid)) == NULL) + return; + + log_debug("%s: freeing ktable rtableid %u", __func__, kt->rtableid); + kroute_clear(kt); + kroute6_clear(kt); + + krt[kt->rtableid] = NULL; + free(kt); +} + +struct ktable * +ktable_get(u_int rtableid) +{ + if (rtableid >= krt_size) + return (NULL); + return (krt[rtableid]); +} + +int +ktable_update(u_int rtableid) +{ + struct ktable *kt; + u_int rdomid; + + if (!ktable_exists(rtableid, &rdomid)) + fatalx("ktable_update: table doesn't exist"); + + if (rdomid != rtableid) { + if (ktable_get(rdomid) == NULL && + ktable_new(rdomid, rdomid) != 0) + return (-1); + } + + kt = ktable_get(rtableid); + if (kt == NULL) { + if (ktable_new(rtableid, rdomid)) + return (-1); + } + return (0); +} + +int +ktable_exists(u_int rtableid, u_int *rdomid) +{ + size_t len; + struct rt_tableinfo info; + int mib[6]; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; + mib[4] = NET_RT_TABLE; + mib[5] = rtableid; + + len = sizeof(info); + if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) { + if (errno == ENOENT) + /* table nonexistent */ + return (0); + log_warn("%s: sysctl", __func__); + /* must return 0 so that the table is considered non-existent */ + return (0); + } + if (rdomid) + *rdomid = info.rti_domainid; + return (1); +} + +void +kr_shutdown(void) +{ + u_int i; + + for (i = krt_size; i > 0; i--) + ktable_free(i - 1); + kif_clear(); +} + +u_int +kr_ifnumber(void) +{ + return (kr_state.ks_nkif); +} + +u_long +kr_iflastchange(void) +{ + return (kr_state.ks_iflastchange); +} + +int +kr_updateif(u_int if_index) +{ + return (fetchifs(if_index)); +} + +u_long +kr_routenumber(void) +{ + return (kr_state.ks_nroutes); +} + +/* rb-tree compare */ +int +kroute_compare(struct kroute_node *a, struct kroute_node *b) +{ + if (ntohl(a->r.prefix.s_addr) < ntohl(b->r.prefix.s_addr)) + return (-1); + if (ntohl(a->r.prefix.s_addr) > ntohl(b->r.prefix.s_addr)) + return (1); + if (a->r.prefixlen < b->r.prefixlen) + return (-1); + if (a->r.prefixlen > b->r.prefixlen) + return (1); + + /* if the priority is RTP_ANY finish on the first address hit */ + if (a->r.priority == RTP_ANY || b->r.priority == RTP_ANY) + return (0); + if (a->r.priority < b->r.priority) + return (-1); + if (a->r.priority > b->r.priority) + return (1); + return (0); +} + +int +kroute6_compare(struct kroute6_node *a, struct kroute6_node *b) +{ + int i; + + for (i = 0; i < 16; i++) { + if (a->r.prefix.s6_addr[i] < b->r.prefix.s6_addr[i]) + return (-1); + if (a->r.prefix.s6_addr[i] > b->r.prefix.s6_addr[i]) + return (1); + } + + if (a->r.prefixlen < b->r.prefixlen) + return (-1); + if (a->r.prefixlen > b->r.prefixlen) + return (1); + + /* if the priority is RTP_ANY finish on the first address hit */ + if (a->r.priority == RTP_ANY || b->r.priority == RTP_ANY) + return (0); + if (a->r.priority < b->r.priority) + return (-1); + if (a->r.priority > b->r.priority) + return (1); + return (0); +} + +int +kif_compare(struct kif_node *a, struct kif_node *b) +{ + return (a->k.if_index - b->k.if_index); +} + +int +ka_compare(struct kif_addr *a, struct kif_addr *b) +{ + if (a->addr.sa.sa_family < b->addr.sa.sa_family) + return (-1); + if (a->addr.sa.sa_family > b->addr.sa.sa_family) + return (1); + return (memcmp(&a->addr.sa, &b->addr.sa, a->addr.sa.sa_len)); +} + +/* tree management */ +struct kroute_node * +kroute_find(struct ktable *kt, in_addr_t prefix, u_int8_t prefixlen, + u_int8_t prio) +{ + struct kroute_node s; + struct kroute_node *kn, *tmp; + + s.r.prefix.s_addr = prefix; + s.r.prefixlen = prefixlen; + s.r.priority = prio; + + kn = RB_FIND(kroute_tree, &kt->krt, &s); + if (kn && prio == RTP_ANY) { + tmp = RB_PREV(kroute_tree, &kt->krt, kn); + while (tmp) { + if (kroute_compare(&s, tmp) == 0) + kn = tmp; + else + break; + tmp = RB_PREV(kroute_tree, &kt->krt, kn); + } + } + return (kn); +} + +struct kroute_node * +kroute_matchgw(struct kroute_node *kr, struct sockaddr_in *sa_in) +{ + in_addr_t nexthop; + + if (sa_in == NULL) { + log_warnx("%s: no nexthop defined", __func__); + return (NULL); + } + nexthop = sa_in->sin_addr.s_addr; + + while (kr) { + if (kr->r.nexthop.s_addr == nexthop) + return (kr); + kr = kr->next; + } + + return (NULL); +} + +int +kroute_insert(struct ktable *kt, struct kroute_node *kr) +{ + struct kroute_node *krm; + + if ((krm = RB_INSERT(kroute_tree, &kt->krt, kr)) != NULL) { + /* multipath route, add at end of list */ + while (krm->next != NULL) + krm = krm->next; + krm->next = kr; + kr->next = NULL; /* to be sure */ + } + + kr_state.ks_nroutes++; + return (0); +} + +int +kroute_remove(struct ktable *kt, struct kroute_node *kr) +{ + struct kroute_node *krm; + + if ((krm = RB_FIND(kroute_tree, &kt->krt, kr)) == NULL) { + log_warnx("%s: failed to find %s/%u", __func__, + inet_ntoa(kr->r.prefix), kr->r.prefixlen); + return (-1); + } + + if (krm == kr) { + /* head element */ + if (RB_REMOVE(kroute_tree, &kt->krt, kr) == NULL) { + log_warnx("%s: failed for %s/%u", __func__, + inet_ntoa(kr->r.prefix), kr->r.prefixlen); + return (-1); + } + if (kr->next != NULL) { + if (RB_INSERT(kroute_tree, &kt->krt, kr->next) + != NULL) { + log_warnx("%s: failed to add %s/%u", __func__, + inet_ntoa(kr->r.prefix), kr->r.prefixlen); + return (-1); + } + } + } else { + /* somewhere in the list */ + while (krm->next != kr && krm->next != NULL) + krm = krm->next; + if (krm->next == NULL) { + log_warnx("%s: multipath list corrupted for %s/%u", + __func__, inet_ntoa(kr->r.prefix), kr->r.prefixlen); + return (-1); + } + krm->next = kr->next; + } + + kr_state.ks_nroutes--; + free(kr); + return (0); +} + +void +kroute_clear(struct ktable *kt) +{ + struct kroute_node *kr; + + while ((kr = RB_MIN(kroute_tree, &kt->krt)) != NULL) + kroute_remove(kt, kr); +} + +struct kroute6_node * +kroute6_find(struct ktable *kt, const struct in6_addr *prefix, + u_int8_t prefixlen, u_int8_t prio) +{ + struct kroute6_node s; + struct kroute6_node *kn6, *tmp; + + memcpy(&s.r.prefix, prefix, sizeof(struct in6_addr)); + s.r.prefixlen = prefixlen; + s.r.priority = prio; + + kn6 = RB_FIND(kroute6_tree, &kt->krt6, &s); + if (kn6 && prio == RTP_ANY) { + tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); + while (tmp) { + if (kroute6_compare(&s, tmp) == 0) + kn6 = tmp; + else + break; + tmp = RB_PREV(kroute6_tree, &kt->krt6, kn6); + } + } + return (kn6); +} + +struct kroute6_node * +kroute6_matchgw(struct kroute6_node *kr, struct sockaddr_in6 *sa_in6) +{ + struct in6_addr nexthop; + + if (sa_in6 == NULL) { + log_warnx("%s: no nexthop defined", __func__); + return (NULL); + } + memcpy(&nexthop, &sa_in6->sin6_addr, sizeof(nexthop)); + + while (kr) { + if (memcmp(&kr->r.nexthop, &nexthop, sizeof(nexthop)) == 0) + return (kr); + kr = kr->next; + } + + return (NULL); +} + +int +kroute6_insert(struct ktable *kt, struct kroute6_node *kr) +{ + struct kroute6_node *krm; + + if ((krm = RB_INSERT(kroute6_tree, &kt->krt6, kr)) != NULL) { + /* multipath route, add at end of list */ + while (krm->next != NULL) + krm = krm->next; + krm->next = kr; + kr->next = NULL; /* to be sure */ + } + + kr_state.ks_nroutes++; + return (0); +} + +int +kroute6_remove(struct ktable *kt, struct kroute6_node *kr) +{ + struct kroute6_node *krm; + + if ((krm = RB_FIND(kroute6_tree, &kt->krt6, kr)) == NULL) { + log_warnx("%s: failed for %s/%u", __func__, + log_in6addr(&kr->r.prefix), kr->r.prefixlen); + return (-1); + } + + if (krm == kr) { + /* head element */ + if (RB_REMOVE(kroute6_tree, &kt->krt6, kr) == NULL) { + log_warnx("%s: failed for %s/%u", __func__, + log_in6addr(&kr->r.prefix), kr->r.prefixlen); + return (-1); + } + if (kr->next != NULL) { + if (RB_INSERT(kroute6_tree, &kt->krt6, kr->next) != + NULL) { + log_warnx("%s: failed to add %s/%u", __func__, + log_in6addr(&kr->r.prefix), + kr->r.prefixlen); + return (-1); + } + } + } else { + /* somewhere in the list */ + while (krm->next != kr && krm->next != NULL) + krm = krm->next; + if (krm->next == NULL) { + log_warnx("%s: multipath list corrupted for %s/%u", + __func__, log_in6addr(&kr->r.prefix), + kr->r.prefixlen); + return (-1); + } + krm->next = kr->next; + } + + kr_state.ks_nroutes--; + free(kr); + return (0); +} + +void +kroute6_clear(struct ktable *kt) +{ + struct kroute6_node *kr; + + while ((kr = RB_MIN(kroute6_tree, &kt->krt6)) != NULL) + kroute6_remove(kt, kr); +} + +static inline int +karp_compare(struct kif_arp *a, struct kif_arp *b) +{ + /* Interface indices are assumed equal */ + if (ntohl(a->addr.sin.sin_addr.s_addr) > + ntohl(b->addr.sin.sin_addr.s_addr)) + return (1); + if (ntohl(a->addr.sin.sin_addr.s_addr) < + ntohl(b->addr.sin.sin_addr.s_addr)) + return (-1); + return (0); +} + +static inline struct kif_arp * +karp_search(struct kif_node *kn, struct kif_arp *ka) +{ + struct kif_arp *pivot; + + TAILQ_FOREACH(pivot, &kn->arps, entry) { + switch (karp_compare(ka, pivot)) { + case 0: /* found */ + return (pivot); + case -1: /* ka < pivot, end the search */ + return (NULL); + } + } + /* looped through the whole list and didn't find */ + return (NULL); +} + +struct kif_arp * +karp_find(struct sockaddr *sa, u_short ifindex) +{ + struct kif_node *kn; + struct kif_arp *ka = NULL, s; + + memcpy(&s.addr.sa, sa, sa->sa_len); + + if (ifindex == 0) { + /* + * We iterate manually to handle zero ifindex special + * case differently from kif_find, in particular we + * want to look for the address on all available + * interfaces. + */ + RB_FOREACH(kn, kif_tree, &kit) { + if ((ka = karp_search(kn, &s)) != NULL) + break; + } + } else { + if ((kn = kif_find(ifindex)) == NULL) + return (NULL); + ka = karp_search(kn, &s); + } + return (ka); +} + +int +karp_insert(struct kif_node *kn, struct kif_arp *ka) +{ + struct kif_arp *pivot; + + if (ka->if_index == 0) + return (-1); + if (!kn && (kn = kif_find(ka->if_index)) == NULL) + return (-1); + /* Put entry on the list in the ascending lexical order */ + TAILQ_FOREACH(pivot, &kn->arps, entry) { + switch (karp_compare(ka, pivot)) { + case 0: /* collision */ + return (-1); + case -1: /* ka < pivot */ + TAILQ_INSERT_BEFORE(pivot, ka, entry); + return (0); + } + } + /* ka is larger than any other element on the list */ + TAILQ_INSERT_TAIL(&kn->arps, ka, entry); + return (0); +} + +int +karp_remove(struct kif_node *kn, struct kif_arp *ka) +{ + if (ka->if_index == 0) + return (-1); + if (!kn && (kn = kif_find(ka->if_index)) == NULL) + return (-1); + TAILQ_REMOVE(&kn->arps, ka, entry); + free(ka); + return (0); +} + +struct kif_arp * +karp_first(u_short ifindex) +{ + struct kif_node *kn; + + if ((kn = kif_find(ifindex)) == NULL) + return (NULL); + return (TAILQ_FIRST(&kn->arps)); +} + +struct kif_arp * +karp_getaddr(struct sockaddr *sa, u_short ifindex, int next) +{ + struct kif_arp *ka; + + if ((ka = karp_find(sa, ifindex)) == NULL) + return (NULL); + return (next ? TAILQ_NEXT(ka, entry) : ka); +} + +struct kif_node * +kif_find(u_short if_index) +{ + struct kif_node s; + + if (if_index == 0) + return (RB_MIN(kif_tree, &kit)); + + bzero(&s, sizeof(s)); + s.k.if_index = if_index; + + return (RB_FIND(kif_tree, &kit, &s)); +} + +struct kif * +kr_getif(u_short if_index) +{ + struct kif_node *kn; + + kn = kif_find(if_index); + if (kn == NULL) + return (NULL); + + return (&kn->k); +} + +struct kif * +kr_getnextif(u_short if_index) +{ + struct kif_node *kn; + + if ((kn = kif_find(if_index)) == NULL) + return (NULL); + if (if_index) + kn = RB_NEXT(kif_tree, &kit, kn); + if (kn == NULL) + return (NULL); + + return (&kn->k); +} + +struct kif_node * +kif_insert(u_short if_index) +{ + struct kif_node *kif; + + if ((kif = calloc(1, sizeof(struct kif_node))) == NULL) + return (NULL); + + kif->k.if_index = if_index; + TAILQ_INIT(&kif->addrs); + TAILQ_INIT(&kif->arps); + + if (RB_INSERT(kif_tree, &kit, kif) != NULL) + fatalx("kif_insert: RB_INSERT"); + + kr_state.ks_nkif++; + kr_state.ks_iflastchange = smi_getticks(); + + return (kif); +} + +int +kif_remove(struct kif_node *kif) +{ + struct kif_addr *ka; + struct kif_arp *kr; + + if (RB_REMOVE(kif_tree, &kit, kif) == NULL) { + log_warnx("%s: RB_REMOVE failed", __func__); + return (-1); + } + + while ((ka = TAILQ_FIRST(&kif->addrs)) != NULL) { + TAILQ_REMOVE(&kif->addrs, ka, entry); + ka_remove(ka); + } + while ((kr = TAILQ_FIRST(&kif->arps)) != NULL) { + karp_remove(kif, kr); + } + free(kif); + + kr_state.ks_nkif--; + kr_state.ks_iflastchange = smi_getticks(); + + return (0); +} + +void +kif_clear(void) +{ + struct kif_node *kif; + + while ((kif = RB_MIN(kif_tree, &kit)) != NULL) + kif_remove(kif); + kr_state.ks_nkif = 0; + kr_state.ks_iflastchange = smi_getticks(); +} + +struct kif * +kif_update(u_short if_index, int flags, struct if_data *ifd, + struct sockaddr_dl *sdl) +{ + struct kif_node *kif; + struct ether_addr *ea; + struct ifreq ifr; + + if ((kif = kif_find(if_index)) == NULL) + if ((kif = kif_insert(if_index)) == NULL) + return (NULL); + + kif->k.if_flags = flags; + bcopy(ifd, &kif->k.if_data, sizeof(struct if_data)); + kif->k.if_ticks = smi_getticks(); + + if (sdl && sdl->sdl_family == AF_LINK) { + if (sdl->sdl_nlen >= sizeof(kif->k.if_name)) + memcpy(kif->k.if_name, sdl->sdl_data, + sizeof(kif->k.if_name) - 1); + else if (sdl->sdl_nlen > 0) + memcpy(kif->k.if_name, sdl->sdl_data, + sdl->sdl_nlen); + /* string already terminated via calloc() */ + + if ((ea = (struct ether_addr *)LLADDR(sdl)) != NULL) + bcopy(&ea->ether_addr_octet, kif->k.if_lladdr, + ETHER_ADDR_LEN); + } + + bzero(&ifr, sizeof(ifr)); + strlcpy(ifr.ifr_name, kif->k.if_name, sizeof(ifr.ifr_name)); + ifr.ifr_data = (caddr_t)&kif->k.if_descr; + if (ioctl(kr_state.ks_ifd, SIOCGIFDESCR, &ifr) == -1) + bzero(&kif->k.if_descr, sizeof(kif->k.if_descr)); + + return (&kif->k); +} + +void +ka_insert(u_short if_index, struct kif_addr *ka) +{ + if (ka->addr.sa.sa_len == 0) + return; + + ka->if_index = if_index; + RB_INSERT(ka_tree, &kat, ka); +} + +struct kif_addr * +ka_find(struct sockaddr *sa) +{ + struct kif_addr ka; + + if (sa == NULL) + return (RB_MIN(ka_tree, &kat)); + bzero(&ka.addr, sizeof(ka.addr)); + bcopy(sa, &ka.addr.sa, sa->sa_len); + return (RB_FIND(ka_tree, &kat, &ka)); +} + +int +ka_remove(struct kif_addr *ka) +{ + RB_REMOVE(ka_tree, &kat, ka); + free(ka); + return (0); +} + +struct kif_addr * +kr_getaddr(struct sockaddr *sa) +{ + return (ka_find(sa)); +} + +struct kif_addr * +kr_getnextaddr(struct sockaddr *sa) +{ + struct kif_addr ka; + + bzero(&ka.addr, sizeof(ka.addr)); + bcopy(sa, &ka.addr.sa, sa->sa_len); + return RB_NFIND(ka_tree, &kat, &ka); +} + +/* misc */ +u_int8_t +prefixlen_classful(in_addr_t ina) +{ + /* it hurt to write this. */ + + if (ina >= 0xf0000000U) /* class E */ + return (32); + else if (ina >= 0xe0000000U) /* class D */ + return (4); + else if (ina >= 0xc0000000U) /* class C */ + return (24); + else if (ina >= 0x80000000U) /* class B */ + return (16); + else /* class A */ + return (8); +} + +u_int8_t +mask2prefixlen(in_addr_t ina) +{ + if (ina == 0) + return (0); + else + return (33 - ffs(ntohl(ina))); +} + +in_addr_t +prefixlen2mask(u_int8_t prefixlen) +{ + if (prefixlen == 0) + return (0); + + return (htonl(0xffffffff << (32 - prefixlen))); +} + +u_int8_t +mask2prefixlen6(struct sockaddr_in6 *sa_in6) +{ + unsigned int l = 0; + u_int8_t *ap, *ep; + + /* + * sin6_len is the size of the sockaddr so substract the offset of + * the possibly truncated sin6_addr struct. + */ + ap = (u_int8_t *)&sa_in6->sin6_addr; + ep = (u_int8_t *)sa_in6 + sa_in6->sin6_len; + for (; ap < ep; ap++) { + /* this "beauty" is adopted from sbin/route/show.c ... */ + switch (*ap) { + case 0xff: + l += 8; + break; + case 0xfe: + l += 7; + goto done; + case 0xfc: + l += 6; + goto done; + case 0xf8: + l += 5; + goto done; + case 0xf0: + l += 4; + goto done; + case 0xe0: + l += 3; + goto done; + case 0xc0: + l += 2; + goto done; + case 0x80: + l += 1; + goto done; + case 0x00: + goto done; + default: + fatalx("non contiguous inet6 netmask"); + } + } + +done: + if (l > sizeof(struct in6_addr) * 8) + fatalx("inet6 prefixlen out of bound"); + return (l); +} + +struct in6_addr * +prefixlen2mask6(u_int8_t prefixlen) +{ + static struct in6_addr mask; + int i; + + bzero(&mask, sizeof(mask)); + for (i = 0; i < prefixlen / 8; i++) + mask.s6_addr[i] = 0xff; + i = prefixlen % 8; + if (i) + mask.s6_addr[prefixlen / 8] = 0xff00 >> i; + + return (&mask); +} + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) + +void +get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) +{ + int i; + + for (i = 0; i < RTAX_MAX; i++) { + if (addrs & (1 << i)) { + rti_info[i] = sa; + sa = (struct sockaddr *)((char *)(sa) + + ROUNDUP(sa->sa_len)); + } else + rti_info[i] = NULL; + + } +} + +void +if_change(u_short if_index, int flags, struct if_data *ifd, + struct sockaddr_dl *sdl) +{ + if (kif_update(if_index, flags, ifd, sdl) == NULL) + log_warn("%s: interface %u update failed", __func__, if_index); +} + +void +if_newaddr(u_short if_index, struct sockaddr *ifa, struct sockaddr *mask, + struct sockaddr *brd) +{ + struct kif_node *kif; + struct kif_addr *ka; + + if (ifa == NULL) + return; + if ((kif = kif_find(if_index)) == NULL) { + log_warnx("%s: corresponding if %u not found", __func__, + if_index); + return; + } + if ((ka = ka_find(ifa)) == NULL) { + if ((ka = calloc(1, sizeof(struct kif_addr))) == NULL) + fatal("if_newaddr"); + bcopy(ifa, &ka->addr.sa, ifa->sa_len); + TAILQ_INSERT_TAIL(&kif->addrs, ka, entry); + ka_insert(if_index, ka); + } + + if (mask) + bcopy(mask, &ka->mask.sa, mask->sa_len); + else + bzero(&ka->mask, sizeof(ka->mask)); + if (brd) + bcopy(brd, &ka->dstbrd.sa, brd->sa_len); + else + bzero(&ka->dstbrd, sizeof(ka->dstbrd)); +} + +void +if_deladdr(u_short if_index, struct sockaddr *ifa, struct sockaddr *mask, + struct sockaddr *brd) +{ + struct kif_node *kif; + struct kif_addr *ka; + + if (ifa == NULL) + return; + if ((kif = kif_find(if_index)) == NULL) { + log_warnx("%s: corresponding if %u not found", __func__, + if_index); + return; + } + if ((ka = ka_find(ifa)) == NULL) + return; + + TAILQ_REMOVE(&kif->addrs, ka, entry); + ka_remove(ka); +} + +void +if_announce(void *msg) +{ + struct if_announcemsghdr *ifan; + struct kif_node *kif; + + ifan = msg; + + switch (ifan->ifan_what) { + case IFAN_ARRIVAL: + kif = kif_insert(ifan->ifan_index); + strlcpy(kif->k.if_name, ifan->ifan_name, + sizeof(kif->k.if_name)); + break; + case IFAN_DEPARTURE: + kif = kif_find(ifan->ifan_index); + kif_remove(kif); + break; + } +} + +int +fetchtable(struct ktable *kt) +{ + int mib[7]; + size_t len; + char *buf; + int rv; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_INET; + mib[4] = NET_RT_DUMP; + mib[5] = 0; + mib[6] = kt->rtableid; + + if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) { + if (kt->rtableid != 0 && errno == EINVAL) + /* table nonexistent */ + return (0); + log_warn("%s: failed to fetch routing table %u size", __func__, + kt->rtableid); + return (-1); + } + if (len == 0) + return (0); + if ((buf = malloc(len)) == NULL) { + log_warn("%s: malloc", __func__); + return (-1); + } + if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) { + log_warn("%s: failed to fetch routing table %u", __func__, + kt->rtableid); + free(buf); + return (-1); + } + + rv = rtmsg_process(buf, len); + free(buf); + + return (rv); +} + +int +fetchifs(u_short if_index) +{ + size_t len; + int mib[6]; + char *buf; + int rv; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; /* wildcard address family */ + mib[4] = NET_RT_IFLIST; + mib[5] = if_index; + + if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) { + log_warn("%s: failed to fetch address table size for %u", + __func__, if_index); + return (-1); + } + if ((buf = malloc(len)) == NULL) { + log_warn("%s: malloc", __func__); + return (-1); + } + if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) { + log_warn("%s: failed to fetch address table for %u", + __func__, if_index); + free(buf); + return (-1); + } + + rv = rtmsg_process(buf, len); + free(buf); + + return (rv); +} + +int +fetcharp(struct ktable *kt) +{ + size_t len; + int mib[7]; + char *buf; + int rv; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_INET; + mib[4] = NET_RT_FLAGS; + mib[5] = RTF_LLINFO; + mib[6] = kt->rtableid; + + if (sysctl(mib, 7, NULL, &len, NULL, 0) == -1) { + log_warn("%s: failed to fetch arp table %u size", __func__, + kt->rtableid); + return (-1); + } + /* Empty table? */ + if (len == 0) + return (0); + if ((buf = malloc(len)) == NULL) { + log_warn("%s: malloc", __func__); + return (-1); + } + if (sysctl(mib, 7, buf, &len, NULL, 0) == -1) { + log_warn("%s: failed to fetch arp table %u", __func__, + kt->rtableid); + free(buf); + return (-1); + } + + rv = rtmsg_process(buf, len); + free(buf); + + return (rv); +} + +/* ARGSUSED */ +void +dispatch_rtmsg(int fd, short event, void *arg) +{ + char buf[RT_BUF_SIZE]; + ssize_t n; + + if ((n = read(fd, &buf, sizeof(buf))) == -1) { + log_warn("%s: read error", __func__); + return; + } + + if (n == 0) { + log_warnx("%s: routing socket closed", __func__); + return; + } + + rtmsg_process(buf, n); +} + +int +rtmsg_process(char *buf, int len) +{ + struct ktable *kt; + struct rt_msghdr *rtm; + struct if_msghdr ifm; + struct ifa_msghdr *ifam; + struct sockaddr *sa, *rti_info[RTAX_MAX]; + int offset; + char *next; + + for (offset = 0; offset < len; offset += rtm->rtm_msglen) { + next = buf + offset; + rtm = (struct rt_msghdr *)next; + if (rtm->rtm_version != RTM_VERSION) + continue; + + sa = (struct sockaddr *)(next + rtm->rtm_hdrlen); + get_rtaddrs(rtm->rtm_addrs, sa, rti_info); + + switch (rtm->rtm_type) { + case RTM_ADD: + case RTM_GET: + case RTM_CHANGE: + case RTM_DELETE: + case RTM_RESOLVE: + if (rtm->rtm_errno) /* failed attempts */ + continue; + + if ((kt = ktable_get(rtm->rtm_tableid)) == NULL) + continue; + + if (dispatch_rtmsg_addr(kt, rtm, rti_info) == -1) + return (-1); + break; + case RTM_IFINFO: + memcpy(&ifm, next, sizeof(ifm)); + if_change(ifm.ifm_index, ifm.ifm_flags, &ifm.ifm_data, + (struct sockaddr_dl *)rti_info[RTAX_IFP]); + break; + case RTM_DELADDR: + ifam = (struct ifa_msghdr *)rtm; + if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | + RTA_BRD)) == 0) + break; + + if_deladdr(ifam->ifam_index, rti_info[RTAX_IFA], + rti_info[RTAX_NETMASK], rti_info[RTAX_BRD]); + break; + case RTM_NEWADDR: + ifam = (struct ifa_msghdr *)rtm; + if ((ifam->ifam_addrs & (RTA_NETMASK | RTA_IFA | + RTA_BRD)) == 0) + break; + + if_newaddr(ifam->ifam_index, rti_info[RTAX_IFA], + rti_info[RTAX_NETMASK], rti_info[RTAX_BRD]); + break; + case RTM_IFANNOUNCE: + if_announce(next); + break; + case RTM_DESYNC: + kr_shutdown(); + if (fetchifs(0) == -1) + fatalx("rtmsg_process: fetchifs"); + ktable_init(); + break; + default: + /* ignore for now */ + break; + } + } + + return (offset); +} + +int +dispatch_rtmsg_addr(struct ktable *kt, struct rt_msghdr *rtm, + struct sockaddr *rti_info[RTAX_MAX]) +{ + struct sockaddr *sa, *psa; + struct sockaddr_in *sa_in, *psa_in = NULL; + struct sockaddr_in6 *sa_in6, *psa_in6 = NULL; + struct sockaddr_dl *sa_dl; + struct kroute_node *kr; + struct kroute6_node *kr6; + struct kif_arp *ka; + int flags, mpath = 0; + u_int16_t ifindex; + u_int8_t prefixlen; + u_int8_t prio; + + flags = 0; + ifindex = 0; + prefixlen = 0; + + if ((psa = rti_info[RTAX_DST]) == NULL) + return (-1); + + if (rtm->rtm_flags & RTF_STATIC) + flags |= F_STATIC; + if (rtm->rtm_flags & RTF_BLACKHOLE) + flags |= F_BLACKHOLE; + if (rtm->rtm_flags & RTF_REJECT) + flags |= F_REJECT; + if (rtm->rtm_flags & RTF_DYNAMIC) + flags |= F_DYNAMIC; +#ifdef RTF_MPATH + if (rtm->rtm_flags & RTF_MPATH) + mpath = 1; +#endif + + prio = rtm->rtm_priority; + switch (psa->sa_family) { + case AF_INET: + psa_in = (struct sockaddr_in *)psa; + sa_in = (struct sockaddr_in *)rti_info[RTAX_NETMASK]; + if (sa_in != NULL) { + if (sa_in->sin_len != 0) + prefixlen = mask2prefixlen( + sa_in->sin_addr.s_addr); + } else if (rtm->rtm_flags & RTF_HOST) + prefixlen = 32; + else + prefixlen = + prefixlen_classful(psa_in->sin_addr.s_addr); + break; + case AF_INET6: + psa_in6 = (struct sockaddr_in6 *)psa; + sa_in6 = (struct sockaddr_in6 *)rti_info[RTAX_NETMASK]; + if (sa_in6 != NULL) { + if (sa_in6->sin6_len != 0) + prefixlen = mask2prefixlen6(sa_in6); + } else if (rtm->rtm_flags & RTF_HOST) + prefixlen = 128; + else + fatalx("in6 net addr without netmask"); + break; + default: + return (0); + } + + if ((sa = rti_info[RTAX_GATEWAY]) != NULL) + switch (sa->sa_family) { + case AF_INET: + case AF_INET6: + if (rtm->rtm_flags & RTF_CONNECTED) { + flags |= F_CONNECTED; + ifindex = rtm->rtm_index; + } + mpath = 0; /* link local stuff can't be mpath */ + break; + case AF_LINK: + /* + * Traditional BSD connected routes have + * a gateway of type AF_LINK. + */ + flags |= F_CONNECTED; + ifindex = rtm->rtm_index; + mpath = 0; /* link local stuff can't be mpath */ + break; + } + + if (rtm->rtm_type == RTM_DELETE) { + if (sa != NULL && sa->sa_family == AF_LINK && + (rtm->rtm_flags & RTF_HOST) && + psa->sa_family == AF_INET) { + if ((ka = karp_find(psa, ifindex)) == NULL) + return (0); + if (karp_remove(NULL, ka) == -1) + return (-1); + return (0); + } else if (sa == NULL && (rtm->rtm_flags & RTF_HOST) && + psa->sa_family == AF_INET) { + if ((ka = karp_find(psa, ifindex)) != NULL) + karp_remove(NULL, ka); + /* Continue to the route section below */ + } + switch (psa->sa_family) { + case AF_INET: + sa_in = (struct sockaddr_in *)sa; + if ((kr = kroute_find(kt, psa_in->sin_addr.s_addr, + prefixlen, prio)) == NULL) + return (0); + + if (mpath) + /* get the correct route */ + if ((kr = kroute_matchgw(kr, sa_in)) == NULL) { + log_warnx("%s[delete]: " + "mpath route not found", __func__); + return (0); + } + + if (kroute_remove(kt, kr) == -1) + return (-1); + break; + case AF_INET6: + sa_in6 = (struct sockaddr_in6 *)sa; + if ((kr6 = kroute6_find(kt, &psa_in6->sin6_addr, + prefixlen, prio)) == NULL) + return (0); + + if (mpath) + /* get the correct route */ + if ((kr6 = kroute6_matchgw(kr6, sa_in6)) == + NULL) { + log_warnx("%s[delete]: " + "IPv6 mpath route not found", + __func__); + return (0); + } + + if (kroute6_remove(kt, kr6) == -1) + return (-1); + break; + } + return (0); + } + + if (sa == NULL && !(flags & F_CONNECTED)) + return (0); + + /* Add or update an ARP entry */ + if ((rtm->rtm_flags & RTF_LLINFO) && (rtm->rtm_flags & RTF_HOST) && + sa != NULL && sa->sa_family == AF_LINK && + psa->sa_family == AF_INET) { + sa_dl = (struct sockaddr_dl *)sa; + /* ignore incomplete entries */ + if (!sa_dl->sdl_alen) + return (0); + /* ignore entries that do not specify an interface */ + if (ifindex == 0) + return (0); + if ((ka = karp_find(psa, ifindex)) != NULL) { + memcpy(&ka->target.sdl, sa_dl, sa_dl->sdl_len); + if (rtm->rtm_flags & RTF_PERMANENT_ARP) + flags |= F_STATIC; + ka->flags = flags; + } else { + if ((ka = calloc(1, sizeof(struct kif_arp))) == NULL) { + log_warn("%s: calloc", __func__); + return (-1); + } + memcpy(&ka->addr.sa, psa, psa->sa_len); + memcpy(&ka->target.sdl, sa_dl, sa_dl->sdl_len); + if (rtm->rtm_flags & RTF_PERMANENT_ARP) + flags |= F_STATIC; + ka->flags = flags; + ka->if_index = ifindex; + if (karp_insert(NULL, ka)) { + free(ka); + log_warnx("%s: failed to insert", __func__); + return (-1); + } + } + return (0); + } + + switch (psa->sa_family) { + case AF_INET: + sa_in = (struct sockaddr_in *)sa; + if ((kr = kroute_find(kt, psa_in->sin_addr.s_addr, prefixlen, + prio)) != NULL) { + /* get the correct route */ + if (mpath && rtm->rtm_type == RTM_CHANGE && + (kr = kroute_matchgw(kr, sa_in)) == NULL) { + log_warnx("%s[change]: " + "mpath route not found", __func__); + return (-1); + } else if (mpath && rtm->rtm_type == RTM_ADD) + goto add4; + + if (sa_in != NULL) + kr->r.nexthop.s_addr = + sa_in->sin_addr.s_addr; + else + kr->r.nexthop.s_addr = 0; + kr->r.flags = flags; + kr->r.if_index = ifindex; + kr->r.ticks = smi_getticks(); + } else { +add4: + if ((kr = calloc(1, + sizeof(struct kroute_node))) == NULL) { + log_warn("%s: calloc", __func__); + return (-1); + } + kr->r.prefix.s_addr = psa_in->sin_addr.s_addr; + kr->r.prefixlen = prefixlen; + if (sa_in != NULL) + kr->r.nexthop.s_addr = sa_in->sin_addr.s_addr; + else + kr->r.nexthop.s_addr = 0; + kr->r.flags = flags; + kr->r.if_index = ifindex; + kr->r.ticks = smi_getticks(); + kr->r.priority = prio; + + kroute_insert(kt, kr); + } + break; + case AF_INET6: + sa_in6 = (struct sockaddr_in6 *)sa; + if ((kr6 = kroute6_find(kt, &psa_in6->sin6_addr, prefixlen, + prio)) != NULL) { + /* get the correct route */ + if (mpath && rtm->rtm_type == RTM_CHANGE && + (kr6 = kroute6_matchgw(kr6, sa_in6)) == + NULL) { + log_warnx("%s[change]: " + "IPv6 mpath route not found", __func__); + return (-1); + } else if (mpath && rtm->rtm_type == RTM_ADD) + goto add6; + + if (sa_in6 != NULL) + memcpy(&kr6->r.nexthop, + &sa_in6->sin6_addr, + sizeof(struct in6_addr)); + else + memcpy(&kr6->r.nexthop, + &in6addr_any, + sizeof(struct in6_addr)); + + kr6->r.flags = flags; + kr6->r.if_index = ifindex; + kr6->r.ticks = smi_getticks(); + } else { +add6: + if ((kr6 = calloc(1, + sizeof(struct kroute6_node))) == NULL) { + log_warn("%s: calloc", __func__); + return (-1); + } + memcpy(&kr6->r.prefix, &psa_in6->sin6_addr, + sizeof(struct in6_addr)); + kr6->r.prefixlen = prefixlen; + if (sa_in6 != NULL) + memcpy(&kr6->r.nexthop, &sa_in6->sin6_addr, + sizeof(struct in6_addr)); + else + memcpy(&kr6->r.nexthop, &in6addr_any, + sizeof(struct in6_addr)); + kr6->r.flags = flags; + kr6->r.if_index = ifindex; + kr6->r.ticks = smi_getticks(); + kr6->r.priority = prio; + + kroute6_insert(kt, kr6); + } + break; + } + + return (0); +} + +struct kroute * +kroute_first(void) +{ + struct kroute_node *kn; + struct ktable *kt; + + if ((kt = ktable_get(0)) == NULL) + return (NULL); + kn = RB_MIN(kroute_tree, &kt->krt); + return (&kn->r); +} + +struct kroute * +kroute_getaddr(in_addr_t prefix, u_int8_t prefixlen, u_int8_t prio, int next) +{ + struct kroute_node *kn; + struct ktable *kt; + + if ((kt = ktable_get(0)) == NULL) + return (NULL); + kn = kroute_find(kt, prefix, prefixlen, prio); + if (kn != NULL && next) + kn = RB_NEXT(kroute_tree, &kt->krt, kn); + if (kn != NULL) + return (&kn->r); + else + return (NULL); +} diff --git a/libexec/snmpd/snmpd_metrics/log.c b/libexec/snmpd/snmpd_metrics/log.c new file mode 100644 index 00000000000..3a322bf1ec0 --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/log.c @@ -0,0 +1,218 @@ +/* $OpenBSD: log.c,v 1.1.1.1 2022/09/01 14:20:34 martijn Exp $ */ + +/* + * Copyright (c) 2003, 2004 Henning Brauer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +static int debug; +static int verbose; +const char *log_procname; + +void log_init(int, int); +void log_procinit(const char *); +void log_setverbose(int); +int log_getverbose(void); +void log_warn(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_warnx(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_info(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_debug(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void logit(int, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +void vlog(int, const char *, va_list) + __attribute__((__format__ (printf, 2, 0))); +__dead void fatal(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +__dead void fatalx(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); + +void +log_init(int n_debug, int facility) +{ + extern char *__progname; + + debug = n_debug; + verbose = n_debug; + log_procinit(__progname); + + if (!debug) + openlog(__progname, LOG_PID | LOG_NDELAY, facility); + + tzset(); +} + +void +log_procinit(const char *procname) +{ + if (procname != NULL) + log_procname = procname; +} + +void +log_setverbose(int v) +{ + verbose = v; +} + +int +log_getverbose(void) +{ + return (verbose); +} + +void +logit(int pri, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vlog(pri, fmt, ap); + va_end(ap); +} + +void +vlog(int pri, const char *fmt, va_list ap) +{ + char *nfmt; + int saved_errno = errno; + + if (debug) { + /* best effort in out of mem situations */ + if (asprintf(&nfmt, "%s\n", fmt) == -1) { + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + } else { + vfprintf(stderr, nfmt, ap); + free(nfmt); + } + fflush(stderr); + } else + vsyslog(pri, fmt, ap); + + errno = saved_errno; +} + +void +log_warn(const char *emsg, ...) +{ + char *nfmt; + va_list ap; + int saved_errno = errno; + + /* best effort to even work in out of memory situations */ + if (emsg == NULL) + logit(LOG_ERR, "%s", strerror(saved_errno)); + else { + va_start(ap, emsg); + + if (asprintf(&nfmt, "%s: %s", emsg, + strerror(saved_errno)) == -1) { + /* we tried it... */ + vlog(LOG_ERR, emsg, ap); + logit(LOG_ERR, "%s", strerror(saved_errno)); + } else { + vlog(LOG_ERR, nfmt, ap); + free(nfmt); + } + va_end(ap); + } + + errno = saved_errno; +} + +void +log_warnx(const char *emsg, ...) +{ + va_list ap; + + va_start(ap, emsg); + vlog(LOG_ERR, emsg, ap); + va_end(ap); +} + +void +log_info(const char *emsg, ...) +{ + va_list ap; + + va_start(ap, emsg); + vlog(LOG_INFO, emsg, ap); + va_end(ap); +} + +void +log_debug(const char *emsg, ...) +{ + va_list ap; + + if (verbose > 1) { + va_start(ap, emsg); + vlog(LOG_DEBUG, emsg, ap); + va_end(ap); + } +} + +static void +vfatalc(int code, const char *emsg, va_list ap) +{ + static char s[BUFSIZ]; + const char *sep; + + if (emsg != NULL) { + (void)vsnprintf(s, sizeof(s), emsg, ap); + sep = ": "; + } else { + s[0] = '\0'; + sep = ""; + } + if (code) + logit(LOG_CRIT, "%s: %s%s%s", + log_procname, s, sep, strerror(code)); + else + logit(LOG_CRIT, "%s%s%s", log_procname, sep, s); +} + +void +fatal(const char *emsg, ...) +{ + va_list ap; + + va_start(ap, emsg); + vfatalc(errno, emsg, ap); + va_end(ap); + exit(1); +} + +void +fatalx(const char *emsg, ...) +{ + va_list ap; + + va_start(ap, emsg); + vfatalc(0, emsg, ap); + va_end(ap); + exit(1); +} diff --git a/libexec/snmpd/snmpd_metrics/log.h b/libexec/snmpd/snmpd_metrics/log.h new file mode 100644 index 00000000000..a02fe82c1f1 --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/log.h @@ -0,0 +1,40 @@ +/* $OpenBSD: log.h,v 1.1.1.1 2022/09/01 14:20:34 martijn Exp $ */ + +/* + * Copyright (c) 2003, 2004 Henning Brauer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +void log_init(int, int); +void log_procinit(const char *); +void log_setverbose(int); +int log_getverbose(void); +void log_warn(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_warnx(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_info(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void log_debug(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +void logit(int, const char *, ...) + __attribute__((__format__ (printf, 2, 3))); +void vlog(int, const char *, va_list) + __attribute__((__format__ (printf, 2, 0))); +__dead void fatal(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); +__dead void fatalx(const char *, ...) + __attribute__((__format__ (printf, 1, 2))); diff --git a/libexec/snmpd/snmpd_metrics/mib.c b/libexec/snmpd/snmpd_metrics/mib.c new file mode 100644 index 00000000000..eeedb1e0714 --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/mib.c @@ -0,0 +1,4367 @@ +/* $OpenBSD: mib.c,v 1.1.1.1 2022/09/01 14:20:34 martijn Exp $ */ + +/* + * Copyright (c) 2022 Martijn van Duren + * Copyright (c) 2012 Joel Knight + * Copyright (c) 2007, 2008, 2012 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" +#include "snmpd.h" +#include "mib.h" + +struct event connev; +const char *agentxsocket = NULL; +int agentxfd = -1; + +void snmp_connect(struct agentx *, void *, int); +void snmp_tryconnect(int, short, void *); +void snmp_read(int, short, void *); + +struct agentx_context *sac; +struct snmpd *snmpd_env; + +/* HOST-RESOURCES-MIB */ +struct agentx_object *hrSystemProcesses, *hrSystemMaxProcesses; +struct agentx_index *hrStorageIdx; +struct agentx_object *hrStorageIndex, *hrStorageType, *hrStorageDescr; +struct agentx_object *hrStorageAllocationUnits, *hrStorageSize, *hrStorageUsed; +struct agentx_object *hrStorageAllocationFailures; +struct agentx_index *hrDeviceIdx; +struct agentx_object *hrDeviceIndex, *hrDeviceType, *hrDeviceDescr, *hrDeviceID; +struct agentx_object *hrDeviceStatus, *hrDeviceErrors, *hrProcessorFrwID; +struct agentx_object *hrProcessorLoad; +struct agentx_index *hrSWRunIdx; +struct agentx_object *hrSWRunIndex, *hrSWRunName, *hrSWRunID, *hrSWRunPath; +struct agentx_object *hrSWRunParameters, *hrSWRunType, *hrSWRunStatus; + +void mib_hrsystemuptime(struct agentx_varbind *); +void mib_hrsystemdate(struct agentx_varbind *); +void mib_hrsystemprocs(struct agentx_varbind *); +void mib_hrmemory(struct agentx_varbind *); +void mib_hrstorage(struct agentx_varbind *); +void mib_hrdevice(struct agentx_varbind *); +void mib_hrprocessor(struct agentx_varbind *); +void mib_hrswrun(struct agentx_varbind *); + +int kinfo_proc_comp(const void *, const void *); +int kinfo_proc(u_int32_t, struct kinfo_proc **); +void kinfo_timer_cb(int, short, void *); +void kinfo_proc_free(void); +int kinfo_args(struct kinfo_proc *, char **); + +/* IF-MIB */ +struct agentx_index *ifIdx; +struct agentx_object *ifName, *ifInMulticastPkts, *ifInBroadcastPkts; +struct agentx_object *ifOutMulticastPkts, *ifOutBroadcastPkts; +struct agentx_object *ifOutBroadcastPkts, *ifHCInOctets, *ifHCInUcastPkts; +struct agentx_object *ifHCInMulticastPkts, *ifHCInBroadcastPkts, *ifHCOutOctets; +struct agentx_object *ifHCOutUcastPkts, *ifHCOutMulticastPkts; +struct agentx_object *ifHCOutBroadcastPkts, *ifLinkUpDownTrapEnable; +struct agentx_object *ifHighSpeed, *ifPromiscuousMode, *ifConnectorPresent; +struct agentx_object *ifAlias, *ifCounterDiscontinuityTime; +struct agentx_index *ifRcvAddressAddress; +struct agentx_object *ifRcvAddressStatus, *ifRcvAddressType; +struct agentx_object *ifStackLastChange, *ifNumber, *ifIndex, *ifDescr, *ifType; +struct agentx_object *ifMtu, *ifSpeed, *ifPhysAddress, *ifAdminStatus; +struct agentx_object *ifOperStatus, *ifLastChange, *ifInOctets, *ifInUcastPkts; +struct agentx_object *ifInNUcastPkts, *ifInDiscards, *ifInErrors; +struct agentx_object *ifInUnknownProtos, *ifOutOctets, *ifOutUcastPkts; +struct agentx_object *ifOutNUcastPkts, *ifOutDiscards, *ifOutErrors, *ifOutQLen; +struct agentx_object *ifSpecific; + +/* OPENBSD-PF-MIB */ +struct agentx_object *pfRunning, *pfRuntime, *pfDebug, *pfHostid; +struct agentx_object *pfCntMatch, *pfCntBadOffset, *pfCntFragment, *pfCntShort; +struct agentx_object *pfCntNormalize, *pfCntMemory, *pfCntTimestamp; +struct agentx_object *pfCntCongestion, *pfCntIpOption, *pfCntProtoCksum; +struct agentx_object *pfCntStateMismatch, *pfCntStateInsert, *pfCntStateLimit; +struct agentx_object *pfCntSrcLimit, *pfCntSynproxy, *pfCntTranslate; +struct agentx_object *pfCntNoRoute; +struct agentx_object *pfStateCount, *pfStateSearches, *pfStateInserts; +struct agentx_object *pfStateRemovals; +struct agentx_object *pfLogIfName, *pfLogIfIpBytesIn, *pfLogIfIpBytesOut; +struct agentx_object *pfLogIfIpPktsInPass, *pfLogIfIpPktsInDrop; +struct agentx_object *pfLogIfIpPktsOutPass, *pfLogIfIpPktsOutDrop; +struct agentx_object *pfLogIfIp6BytesIn, *pfLogIfIp6BytesOut; +struct agentx_object *pfLogIfIp6PktsInPass, *pfLogIfIp6PktsInDrop; +struct agentx_object *pfLogIfIp6PktsOutPass, *pfLogIfIp6PktsOutDrop; +struct agentx_object *pfSrcTrackCount, *pfSrcTrackSearches, *pfSrcTrackInserts; +struct agentx_object *pfSrcTrackRemovals; +struct agentx_object *pfLimitStates, *pfLimitSourceNodes, *pfLimitFragments; +struct agentx_object *pfLimitMaxTables, *pfLimitMaxTableEntries; +struct agentx_object *pfTimeoutTcpFirst, *pfTimeoutTcpOpening; +struct agentx_object *pfTimeoutTcpEstablished, *pfTimeoutTcpClosing; +struct agentx_object *pfTimeoutTcpFinWait, *pfTimeoutTcpClosed; +struct agentx_object *pfTimeoutUdpFirst, *pfTimeoutUdpSingle; +struct agentx_object *pfTimeoutUdpMultiple, *pfTimeoutIcmpFirst; +struct agentx_object *pfTimeoutIcmpError, *pfTimeoutOtherFirst; +struct agentx_object *pfTimeoutOtherSingle, *pfTimeoutOtherMultiple; +struct agentx_object *pfTimeoutFragment, *pfTimeoutInterval, *pfTimeoutInterval; +struct agentx_object *pfTimeoutAdaptiveStart, *pfTimeoutAdaptiveEnd; +struct agentx_object *pfTimeoutSrcTrack; +struct agentx_index *pfIfIdx; +struct agentx_object *pfIfNumber, *pfIfIndex, *pfIfDescr, *pfIfType, *pfIfRefs; +struct agentx_object *pfIfRules, *pfIfIn4PassPkts, *pfIfIn4PassBytes; +struct agentx_object *pfIfIn4BlockPkts, *pfIfIn4BlockBytes, *pfIfOut4PassPkts; +struct agentx_object *pfIfOut4PassBytes, *pfIfOut4BlockPkts; +struct agentx_object *pfIfOut4BlockBytes, *pfIfIn6PassPkts, *pfIfIn6PassBytes; +struct agentx_object *pfIfIn6BlockPkts, *pfIfIn6BlockBytes, *pfIfOut6PassPkts; +struct agentx_object *pfIfOut6PassBytes, *pfIfOut6BlockPkts; +struct agentx_object *pfIfOut6BlockBytes; +struct agentx_index *pfTblIdx; +struct agentx_object *pfTblNumber, *pfTblIndex, *pfTblName, *pfTblAddresses; +struct agentx_object *pfTblAnchorRefs, *pfTblRuleRefs, *pfTblEvalsMatch; +struct agentx_object *pfTblEvalsNoMatch, *pfTblInPassPkts, *pfTblInPassBytes; +struct agentx_object *pfTblInBlockPkts, *pfTblInBlockBytes, *pfTblInXPassPkts; +struct agentx_object *pfTblInXPassBytes, *pfTblOutPassPkts, *pfTblOutPassBytes; +struct agentx_object *pfTblOutBlockPkts, *pfTblOutBlockBytes; +struct agentx_object *pfTblOutXPassPkts, *pfTblOutXPassBytes; +struct agentx_object *pfTblStatsCleared, *pfTblInMatchPkts, *pfTblInMatchBytes; +struct agentx_object *pfTblOutMatchPkts, *pfTblOutMatchBytes; +struct agentx_index *pfTblAddrTblIdx, *pfTblAddrNetIdx, *pfTblAddrMaskIdx; +struct agentx_object *pfTblAddrTblIndex, *pfTblAddrNet, *pfTblAddrMask; +struct agentx_object *pfTblAddrCleared, *pfTblAddrInBlockPkts; +struct agentx_object *pfTblAddrInBlockBytes, *pfTblAddrInPassPkts; +struct agentx_object *pfTblAddrInPassBytes, *pfTblAddrOutBlockPkts; +struct agentx_object *pfTblAddrOutBlockBytes, *pfTblAddrOutPassPkts; +struct agentx_object *pfTblAddrOutPassBytes, *pfTblAddrInMatchPkts; +struct agentx_object *pfTblAddrInMatchBytes, *pfTblAddrOutMatchPkts; +struct agentx_object *pfTblAddrOutMatchBytes; +struct agentx_index *pfLabelIdx; +struct agentx_object *pfLabelNumber, *pfLabelIndex, *pfLabelName, *pfLabelEvals; +struct agentx_object *pfLabelPkts, *pfLabelBytes, *pfLabelInPkts; +struct agentx_object *pfLabelInBytes, *pfLabelOutPkts, *pfLabelOutBytes; +struct agentx_object *pfLabelTotalStates; +struct agentx_object *pfsyncIpPktsRecv, *pfsyncIp6PktsRecv; +struct agentx_object *pfsyncPktDiscardsForBadInterface; +struct agentx_object *pfsyncPktDiscardsForBadTtl, *pfsyncPktShorterThanHeader; +struct agentx_object *pfsyncPktDiscardsForBadVersion; +struct agentx_object *pfsyncPktDiscardsForBadAction; +struct agentx_object *pfsyncPktDiscardsForBadLength; +struct agentx_object *pfsyncPktDiscardsForBadAuth; +struct agentx_object *pfsyncPktDiscardsForStaleState; +struct agentx_object *pfsyncPktDiscardsForBadValues; +struct agentx_object *pfsyncPktDiscardsForBadState; +struct agentx_object *pfsyncIpPktsSent, *pfsyncIp6PktsSent, *pfsyncNoMemory; +struct agentx_object *pfsyncOutputErrors; + +/* OPENBSD-SENSORS-MIB */ +struct agentx_index *sensorIdx; +struct agentx_object *sensorNumber, *sensorIndex, *sensorDescr, *sensorType; +struct agentx_object *sensorDevice, *sensorValue, *sensorUnits, *sensorStatus; + +/* OPENBSD-CARP-MIB */ +struct agentx_object *carpAllow, *carpPreempt, *carpLog; +struct agentx_index *carpIfIdx; +struct agentx_object *carpIfNumber, *carpIfIndex, *carpIfDescr, *carpIfVhid; +struct agentx_object *carpIfDev, *carpIfAdvbase, *carpIfAdvskew, *carpIfState; +struct agentx_index *carpGroupIdx; +struct agentx_object *carpGroupIndex, *carpGroupName, *carpGroupDemote; +struct agentx_object *carpIpPktsRecv, *carpIp6PktsRecv; +struct agentx_object *carpPktDiscardsForBadInterface; +struct agentx_object *carpPktDiscardsForWrongTtl, *carpPktShorterThanHeader; +struct agentx_object *carpPktDiscardsForBadChecksum; +struct agentx_object *carpPktDiscardsForBadVersion, *carpPktDiscardsForTooShort; +struct agentx_object *carpPktDiscardsForBadAuth, *carpPktDiscardsForBadVhid; +struct agentx_object *carpPktDiscardsForBadAddressList, *carpIpPktsSent; +struct agentx_object *carpIp6PktsSent, *carpNoMemory, *carpTransitionsToMaster; + +/* OPENBSD-MEM-MIB */ +struct agentx_object *memMIBVersion, *memIfName, *memIfLiveLocks; + +/* IP-MIB */ +struct agentx_object *ipForwarding, *ipDefaultTTL, *ipInReceives; +struct agentx_object *ipInHdrErrors, *ipInAddrErrors, *ipForwDatagrams; +struct agentx_object *ipInUnknownProtos, *ipInDelivers, *ipOutRequests; +struct agentx_object *ipOutDiscards, *ipOutNoRoutes, *ipReasmTimeout; +struct agentx_object *ipReasmReqds, *ipReasmOKs, *ipReasmFails, *ipFragOKs; +struct agentx_object *ipFragFails, *ipFragCreates, *ipAdEntAddr; +struct agentx_index *ipAdEntAddrIdx; +struct agentx_object *ipAdEntAddr, *ipAdEntIfIndex, *ipAdEntNetMask; +struct agentx_object *ipAdEntBcastAddr, *ipAdEntReasmMaxSize; +struct agentx_index *ipNetToMediaIfIdx, *ipNetToMediaNetAddressIdx; +struct agentx_object *ipNetToMediaIfIndex, *ipNetToMediaPhysAddress; +struct agentx_object *ipNetToMediaNetAddress, *ipNetToMediaType; + +/* IP-FORWARD-MIB */ +struct agentx_object *inetCidrRouteNumber; +struct agentx_index *inetCidrRouteDestTypeIdx, *inetCidrRouteDestIdx; +struct agentx_index *inetCidrRoutePfxLenIdx, *inetCidrRoutePolicyIdx; +struct agentx_index *inetCidrRouteNextHopTypeIdx, *inetCidrRouteNextHopIdx; +struct agentx_object *inetCidrRouteIfIndex, *inetCidrRouteType; +struct agentx_object *inetCidrRouteProto, *inetCidrRouteAge; +struct agentx_object *inetCidrRouteNextHopAS, *inetCidrRouteMetric1; +struct agentx_object *inetCidrRouteMetric2, *inetCidrRouteMetric3; +struct agentx_object *inetCidrRouteMetric4, *inetCidrRouteMetric5; +struct agentx_object *inetCidrRouteStatus; + +/* UCD-DISKIO-MIB */ +struct agentx_index *diskIOIdx; +struct agentx_object *diskIOIndex, *diskIODevice, *diskIONRead, *diskIONWritten; +struct agentx_object *diskIOReads, *diskIOWrites, *diskIONReadX; +struct agentx_object *diskIONWrittenX; + +/* BRIDGE-MIB */ +struct agentx_object *dot1dBaseNumPorts, *dot1dBaseType; +struct agentx_index *dot1dBasePortIdx; +struct agentx_object *dot1dBasePort, *dot1dBasePortIfIndex; +struct agentx_object *dot1dBasePortCircuit, *dot1dBasePortDelayExceededDiscards; +struct agentx_object *dot1dBasePortMtuExceededDiscards; + +/* HOST-RESOURCES-MIB */ +void +mib_hrsystemuptime(struct agentx_varbind *vb) +{ + struct timespec uptime; + long long ticks; + + if (clock_gettime(CLOCK_BOOTTIME, &uptime) == -1) { + log_warn("clock_gettime"); + agentx_varbind_error(vb); + return; + } + ticks = uptime.tv_sec * 100 + uptime.tv_nsec / 10000000; + agentx_varbind_timeticks(vb, ticks); +} + +void +mib_hrsystemdate(struct agentx_varbind *vb) +{ + struct tm *ptm; + u_char s[11]; + time_t now; + int tzoffset; + unsigned short year; + + (void)time(&now); + ptm = localtime(&now); + + year = htons(ptm->tm_year + 1900); + memcpy(s, &year, 2); + s[2] = ptm->tm_mon + 1; + s[3] = ptm->tm_mday; + s[4] = ptm->tm_hour; + s[5] = ptm->tm_min; + s[6] = ptm->tm_sec; + s[7] = 0; + + tzoffset = ptm->tm_gmtoff; + if (tzoffset < 0) + s[8] = '-'; + else + s[8] = '+'; + + s[9] = abs(tzoffset) / 3600; + s[10] = (abs(tzoffset) - (s[9] * 3600)) / 60; + + agentx_varbind_nstring(vb, s, sizeof(s)); +} + +void +mib_hrsystemprocs(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + char errbuf[_POSIX2_LINE_MAX]; + int val; + int mib[] = { CTL_KERN, KERN_MAXPROC }; + kvm_t *kd; + size_t len; + + obj = agentx_varbind_get_object(vb); + if (obj == hrSystemProcesses) { + if ((kd = kvm_openfiles(NULL, NULL, NULL, + KVM_NO_FILES, errbuf)) == NULL) { + log_warn("kvm_openfiles"); + agentx_varbind_error(vb); + return; + } + + if (kvm_getprocs(kd, KERN_PROC_ALL, 0, + sizeof(struct kinfo_proc), &val) == NULL) { + log_warn("kvm_getprocs"); + kvm_close(kd); + agentx_varbind_error(vb); + return; + } + + agentx_varbind_gauge32(vb, val); + + kvm_close(kd); + } else if (obj == hrSystemMaxProcesses) { + len = sizeof(val); + if (sysctl(mib, 2, &val, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + agentx_varbind_integer(vb, val); + } else + fatal("%s: Unexpected object", __func__); +} + +void +mib_hrmemory(struct agentx_varbind *vb) +{ + int mib[] = { CTL_HW, HW_PHYSMEM64 }; + u_int64_t physmem; + size_t len = sizeof(physmem); + + if (sysctl(mib, nitems(mib), &physmem, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + agentx_varbind_integer(vb, physmem / 1024); +} + +void +mib_hrstorage(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + int32_t idx; + struct statfs *mntbuf, *mnt; + int mntsize, maxsize; + uint64_t units, size, used, fail = 0; + const char *descr = NULL; + int mib[] = { CTL_HW, 0 }; + u_int64_t physmem, realmem; + struct uvmexp uvm; + size_t len; + uint32_t sop[] = { HRSTORAGEOTHER }; + + /* Physical memory, real memory, swap */ + mib[1] = HW_PHYSMEM64; + len = sizeof(physmem); + if (sysctl(mib, nitems(mib), &physmem, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + mib[1] = HW_USERMEM64; + len = sizeof(realmem); + if (sysctl(mib, nitems(mib), &realmem, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + mib[0] = CTL_VM; + mib[1] = VM_UVMEXP; + len = sizeof(uvm); + if (sysctl(mib, nitems(mib), &uvm, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + maxsize = 10; + + /* Disks */ + if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { + log_warn("getmntinfo"); + agentx_varbind_error(vb); + return; + } + maxsize = 30 + mntsize; + + /* + * Get and verify the current row index. + * + * We use a special mapping here that is inspired by other SNMP + * agents: index 1 + 2 for RAM, index 10 for swap, index 31 and + * higher for disk storage. + */ + obj = agentx_varbind_get_object(vb); + req = agentx_varbind_request(vb); + idx = agentx_varbind_get_index_integer(vb, hrStorageIdx); + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + if (idx > maxsize) { + agentx_varbind_notfound(vb); + return; + } + if (req == AGENTX_REQUEST_TYPE_GET) { + if (idx < 1 || (idx > 2 && idx < 10) || + (idx > 10 && idx < 31)) { + agentx_varbind_notfound(vb); + return; + } + } else { + if (idx < 1) + idx = 1; + else if (idx > 2 && idx < 10) + idx = 10; + else if (idx > 10 && idx < 31) + idx = 31; + } + + switch (idx) { + case 1: + descr = "Physical memory"; + units = uvm.pagesize; + size = physmem / uvm.pagesize; + used = size - uvm.free; + memcpy(sop, (uint32_t[]){ HRSTORAGERAM }, sizeof(sop)); + break; + case 2: + descr = "Real memory"; + units = uvm.pagesize; + size = realmem / uvm.pagesize; + used = size - uvm.free; + memcpy(sop, (uint32_t[]){ HRSTORAGERAM }, sizeof(sop)); + break; + case 10: + descr = "Swap space"; + units = uvm.pagesize; + size = uvm.swpages; + used = uvm.swpginuse; + memcpy(sop, (uint32_t[]){ HRSTORAGEVIRTUALMEMORY }, + sizeof(sop)); + break; + default: + mnt = &mntbuf[idx - 31]; + descr = mnt->f_mntonname; + units = mnt->f_bsize; + size = mnt->f_blocks; + used = mnt->f_blocks - mnt->f_bfree; + memcpy(sop, (uint32_t[]){ HRSTORAGEFIXEDDISK }, sizeof(sop)); + break; + } + + while (size > INT32_MAX) { + units *= 2; + size /= 2; + used /= 2; + } + + agentx_varbind_set_index_integer(vb, hrStorageIdx, idx); + + if (obj == hrStorageIndex) + agentx_varbind_integer(vb, idx); + else if (obj == hrStorageType) + agentx_varbind_oid(vb, sop, nitems(sop)); + else if (obj == hrStorageDescr) + agentx_varbind_string(vb, descr); + else if (obj == hrStorageAllocationUnits) + agentx_varbind_integer(vb, units); + else if (obj == hrStorageSize) + agentx_varbind_integer(vb, size); + else if (obj == hrStorageUsed) + agentx_varbind_integer(vb, used); + else if (obj == hrStorageAllocationFailures) + agentx_varbind_counter32(vb, fail); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_hrdevice(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + int32_t idx; + uint32_t fail = 0; + int status; + int mib[] = { CTL_HW, HW_MODEL }; + size_t len; + char descr[BUFSIZ]; + uint32_t sop[] = { HRDEVICEPROCESSOR }; + + /* Get and verify the current row index */ + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, hrDeviceIdx); + req = agentx_varbind_request(vb); + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + if (idx < 1) + idx = 1; + } else if (req == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) { + if (idx < 1) + idx = 1; + } + if (idx < 1 || idx > snmpd_env->sc_ncpu) { + agentx_varbind_notfound(vb); + return; + } + + agentx_varbind_set_index_integer(vb, hrDeviceIdx, idx); + + len = sizeof(descr); + if (sysctl(mib, nitems(mib), &descr, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + /* unknown(1), running(2), warning(3), testing(4), down(5) */ + status = 2; + + if (obj == hrDeviceIndex) + agentx_varbind_integer(vb, idx); + else if (obj == hrDeviceType) + agentx_varbind_oid(vb, sop, nitems(sop)); + else if (obj == hrDeviceDescr) + agentx_varbind_string(vb, descr); + else if (obj == hrDeviceID) + agentx_varbind_oid(vb, AGENTX_OID(0, 0)); + else if (obj == hrDeviceStatus) + agentx_varbind_integer(vb, status); + else if (obj == hrDeviceErrors) + agentx_varbind_counter32(vb, fail); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_hrprocessor(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + int32_t idx; + int64_t *cptime2, val; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, hrDeviceIdx); + req = agentx_varbind_request(vb); + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + if (idx < 1) + idx = 1; + } + else if (req == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) { + if (idx < 1) + idx = 1; + } + if (idx < 1 || idx > snmpd_env->sc_ncpu) { + agentx_varbind_notfound(vb); + return; + } + + agentx_varbind_set_index_integer(vb, hrDeviceIdx, idx); + + if (obj == hrProcessorFrwID) + agentx_varbind_oid(vb, AGENTX_OID(0, 0)); + else if (obj == hrProcessorLoad) { + /* + * The percentage of time that the system was not + * idle during the last minute. + */ + if (snmpd_env->sc_cpustates == NULL) { + log_warnx("cpustates not initialized"); + agentx_varbind_error(vb); + return; + } + cptime2 = snmpd_env->sc_cpustates + (CPUSTATES * (idx - 1)); + val = 100 - + (cptime2[CP_IDLE] > 1000 ? 1000 : (cptime2[CP_IDLE] / 10)); + agentx_varbind_integer(vb, val); + } else + fatal("%s: Unexpected object", __func__); +} + +void +mib_hrswrun(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + int32_t idx; + struct kinfo_proc *kinfo; + char *s; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, hrSWRunIdx); + req = agentx_varbind_request(vb); + + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + /* Get and verify the current row index */ + if (kinfo_proc(idx, &kinfo) == -1) { + log_warn("kinfo_proc"); + agentx_varbind_error(vb); + return; + } + + if (kinfo == NULL) { + agentx_varbind_notfound(vb); + return; + } + if (req == AGENTX_REQUEST_TYPE_GET) { + if (kinfo->p_pid != idx) { + agentx_varbind_notfound(vb); + return; + } + } + agentx_varbind_set_index_integer(vb, hrSWRunIdx, kinfo->p_pid); + + if (obj == hrSWRunIndex) + agentx_varbind_integer(vb, kinfo->p_pid); + else if (obj == hrSWRunName || obj == hrSWRunPath) + agentx_varbind_string(vb, kinfo->p_comm); + else if (obj == hrSWRunID) + agentx_varbind_oid(vb, AGENTX_OID(0, 0)); + else if (obj == hrSWRunParameters) { + if (kinfo_args(kinfo, &s) == -1) { + log_warn("kinfo_args"); + agentx_varbind_error(vb); + return; + } + + agentx_varbind_string(vb, s); + } else if (obj == hrSWRunType) { + if (kinfo->p_flag & P_SYSTEM) { + /* operatingSystem(2) */ + agentx_varbind_integer(vb, 2); + } else { + /* application(4) */ + agentx_varbind_integer(vb, 4); + } + } else if (obj == hrSWRunStatus) { + switch (kinfo->p_stat) { + case SONPROC: + /* running(1) */ + agentx_varbind_integer(vb, 1); + break; + case SIDL: + case SRUN: + case SSLEEP: + /* runnable(2) */ + agentx_varbind_integer(vb, 2); + break; + case SSTOP: + /* notRunnable(3) */ + agentx_varbind_integer(vb, 3); + break; + case SDEAD: + default: + /* invalid(4) */ + agentx_varbind_integer(vb, 4); + break; + } + } else + fatal("%s: Unexpected object", __func__); +} + +int +kinfo_proc_comp(const void *a, const void *b) +{ + struct kinfo_proc * const *k1 = a; + struct kinfo_proc * const *k2 = b; + + return (((*k1)->p_pid > (*k2)->p_pid) ? 1 : -1); +} + +static struct event kinfo_timer; +static struct kinfo_proc *kp = NULL; +static struct kinfo_proc **klist = NULL; +static size_t nkp = 0, nklist = 0; + +int +kinfo_proc(u_int32_t idx, struct kinfo_proc **kinfo) +{ + int mib[] = { CTL_KERN, KERN_PROC, + KERN_PROC_ALL, 0, sizeof(*kp), 0 }; + size_t size, count, i; + struct timeval timer; + + if (kp != NULL && klist != NULL) + goto cached; + + kinfo_proc_free(); + for (;;) { + size = nkp * sizeof(*kp); + mib[5] = nkp; + if (sysctl(mib, nitems(mib), kp, &size, NULL, 0) == -1) { + if (errno == ENOMEM) { + kinfo_proc_free(); + continue; + } + + return (-1); + } + + count = size / sizeof(*kp); + if (count <= nkp) + break; + + kp = malloc(size); + if (kp == NULL) { + kinfo_proc_free(); + return (-1); + } + nkp = count; + } + + klist = calloc(count, sizeof(*klist)); + if (klist == NULL) { + kinfo_proc_free(); + return (-1); + } + nklist = count; + + for (i = 0; i < nklist; i++) + klist[i] = &kp[i]; + qsort(klist, nklist, sizeof(*klist), kinfo_proc_comp); + + evtimer_set(&kinfo_timer, kinfo_timer_cb, NULL); + timer.tv_sec = 5; + timer.tv_usec = 0; + evtimer_add(&kinfo_timer, &timer); + +cached: + *kinfo = NULL; + for (i = 0; i < nklist; i++) { + if (klist[i]->p_pid >= (int32_t)idx) { + *kinfo = klist[i]; + break; + } + } + + return (0); +} + +void +kinfo_timer_cb(int fd, short event, void *arg) +{ + kinfo_proc_free(); +} + +void +kinfo_proc_free(void) +{ + free(kp); + kp = NULL; + nkp = 0; + free(klist); + klist = NULL; + nklist = 0; +} + +int +kinfo_args(struct kinfo_proc *kinfo, char **s) +{ + static char str[128]; + static char *buf = NULL; + static size_t buflen = 128; + + int mib[] = { CTL_KERN, KERN_PROC_ARGS, + kinfo->p_pid, KERN_PROC_ARGV }; + char *nbuf, **argv; + + if (buf == NULL) { + buf = malloc(buflen); + if (buf == NULL) + return (-1); + } + + str[0] = '\0'; + *s = str; + + while (sysctl(mib, nitems(mib), buf, &buflen, NULL, 0) == -1) { + if (errno != ENOMEM) { + /* some errors are expected, dont get too upset */ + return (0); + } + + nbuf = realloc(buf, buflen + 128); + if (nbuf == NULL) + return (-1); + + buf = nbuf; + buflen += 128; + } + + argv = (char **)buf; + if (argv[0] == NULL) + return (0); + + argv++; + while (*argv != NULL) { + strlcat(str, *argv, sizeof(str)); + argv++; + if (*argv != NULL) + strlcat(str, " ", sizeof(str)); + } + + return (0); +} + +/* + * Defined in IF-MIB.txt (RFCs 1229, 1573, 2233, 2863) + */ + +void mib_ifnumber(struct agentx_varbind *); +struct kif + *mib_ifget(u_int); +void mib_iftable(struct agentx_varbind *); +void mib_ifxtable(struct agentx_varbind *); +void mib_ifstacklast(struct agentx_varbind *); +void mib_ifrcvtable(struct agentx_varbind *); + +static uint8_t ether_zeroaddr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +void +mib_ifnumber(struct agentx_varbind *vb) +{ + agentx_varbind_integer(vb, kr_ifnumber()); +} + +struct kif * +mib_ifget(u_int idx) +{ + struct kif *kif; + + if ((kif = kr_getif(idx)) == NULL) { + /* + * It may happen that an interface with a specific index + * does not exist or has been removed. Jump to the next + * available interface index. + */ + for (kif = kr_getif(0); kif != NULL; + kif = kr_getnextif(kif->if_index)) + if (kif->if_index > idx) + break; + if (kif == NULL) + return (NULL); + } + idx = kif->if_index; + + /* Update interface information */ + kr_updateif(idx); + if ((kif = kr_getif(idx)) == NULL) { + log_debug("mib_ifxtable: interface %d disappeared?", idx); + return (NULL); + } + + return (kif); +} + +void +mib_iftable(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + int32_t idx = 0; + struct kif *kif; + long long i; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, ifIdx); + req = agentx_varbind_request(vb); + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + if ((kif = mib_ifget(idx)) == NULL) { + agentx_varbind_notfound(vb); + return; + } + if (req == AGENTX_REQUEST_TYPE_GET) { + if (idx != kif->if_index) { + agentx_varbind_notfound(vb); + return; + } + } + agentx_varbind_set_index_integer(vb, ifIdx, kif->if_index); + + if (obj == ifIndex) + agentx_varbind_integer(vb, kif->if_index); + else if (obj == ifDescr) { + /* + * The ifDescr should contain a vendor, product, etc. + * but we just use the interface name (like ifName). + * The interface name includes the driver name on OpenBSD. + */ + agentx_varbind_string(vb, kif->if_name); + } else if (obj == ifType) { + if (kif->if_type >= 0xf0) { + /* + * It does not make sense to announce the private + * interface types for CARP, ENC, PFSYNC, etc. + */ + agentx_varbind_integer(vb, IFT_OTHER); + } else + agentx_varbind_integer(vb, kif->if_type); + } else if (obj == ifMtu) + agentx_varbind_integer(vb, kif->if_mtu); + else if (obj == ifSpeed) { + if (kif->if_baudrate > UINT32_MAX) { + /* speed should be obtained from ifHighSpeed instead */ + agentx_varbind_gauge32(vb, UINT32_MAX); + } else + agentx_varbind_gauge32(vb, kif->if_baudrate); + } else if (obj == ifPhysAddress) { + if (bcmp(kif->if_lladdr, ether_zeroaddr, + sizeof(kif->if_lladdr)) == 0) { + agentx_varbind_string(vb, ""); + } else { + agentx_varbind_nstring(vb, kif->if_lladdr, + sizeof(kif->if_lladdr)); + } + } else if (obj == ifAdminStatus) { + /* ifAdminStatus up(1), down(2), testing(3) */ + i = (kif->if_flags & IFF_UP) ? 1 : 2; + agentx_varbind_integer(vb, i); + } else if (obj == ifOperStatus) { + if ((kif->if_flags & IFF_UP) == 0) + i = 2; /* down(2) */ + else if (kif->if_link_state == LINK_STATE_UNKNOWN) + i = 4; /* unknown(4) */ + else if (LINK_STATE_IS_UP(kif->if_link_state)) + i = 1; /* up(1) */ + else + i = 7; /* lowerLayerDown(7) or dormant(5)? */ + agentx_varbind_integer(vb, i); + } else if (obj == ifLastChange) + agentx_varbind_timeticks(vb, kif->if_ticks); + else if (obj == ifInOctets) + agentx_varbind_counter32(vb, (uint32_t)kif->if_ibytes); + else if (obj == ifInUcastPkts) + agentx_varbind_counter32(vb, (uint32_t)kif->if_ipackets); + else if (obj == ifInNUcastPkts) + agentx_varbind_counter32(vb, (uint32_t)kif->if_imcasts); + else if (obj == ifInDiscards) + agentx_varbind_counter32(vb, (uint32_t)kif->if_iqdrops); + else if (obj == ifInErrors) + agentx_varbind_counter32(vb, (uint32_t)kif->if_ierrors); + else if (obj == ifInUnknownProtos) + agentx_varbind_counter32(vb, (uint32_t)kif->if_noproto); + else if (obj == ifOutOctets) + agentx_varbind_counter32(vb, (uint32_t)kif->if_obytes); + else if (obj == ifOutUcastPkts) + agentx_varbind_counter32(vb, (uint32_t)kif->if_opackets); + else if (obj == ifOutNUcastPkts) + agentx_varbind_counter32(vb, (uint32_t)kif->if_omcasts); + else if (obj == ifOutDiscards) + agentx_varbind_counter32(vb, (uint32_t)kif->if_oqdrops); + else if (obj == ifOutErrors) + agentx_varbind_counter32(vb, (uint32_t)kif->if_oerrors); + else if (obj == ifOutQLen) + agentx_varbind_gauge32(vb, 0); + else if (obj == ifSpecific) + agentx_varbind_oid(vb, AGENTX_OID(0, 0)); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_ifxtable(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + int32_t idx = 0; + struct kif *kif; + int i = 0; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, ifIdx); + req = agentx_varbind_request(vb); + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + if ((kif = mib_ifget(idx)) == NULL) { + agentx_varbind_notfound(vb); + return; + } + if (req == AGENTX_REQUEST_TYPE_GET) { + if (idx != kif->if_index) { + agentx_varbind_notfound(vb); + return; + } + } + agentx_varbind_set_index_integer(vb, ifIdx, kif->if_index); + + if (obj == ifName) + agentx_varbind_string(vb, kif->if_name); + else if (obj == ifInMulticastPkts) + agentx_varbind_counter32(vb, (uint32_t)kif->if_imcasts); + else if (obj == ifInBroadcastPkts) + agentx_varbind_counter32(vb, 0); + else if (obj == ifOutMulticastPkts) + agentx_varbind_counter32(vb, (uint32_t)kif->if_omcasts); + else if (obj == ifOutBroadcastPkts) + agentx_varbind_counter32(vb, 0); + else if (obj == ifHCInOctets) + agentx_varbind_counter64(vb, (uint64_t)kif->if_ibytes); + else if (obj == ifHCInUcastPkts) + agentx_varbind_counter64(vb, (uint64_t)kif->if_ipackets); + else if (obj == ifHCInMulticastPkts) + agentx_varbind_counter64(vb, (uint64_t)kif->if_imcasts); + else if (obj == ifHCInBroadcastPkts) + agentx_varbind_counter64(vb, 0); + else if (obj == ifHCOutOctets) + agentx_varbind_counter64(vb, (uint64_t)kif->if_obytes); + else if (obj == ifHCOutUcastPkts) + agentx_varbind_counter64(vb, (uint64_t)kif->if_opackets); + else if (obj == ifHCOutMulticastPkts) + agentx_varbind_counter64(vb, (uint64_t)kif->if_omcasts); + else if (obj == ifHCOutBroadcastPkts) + agentx_varbind_counter64(vb, 0); + else if (obj == ifLinkUpDownTrapEnable) + agentx_varbind_integer(vb, 0); /* enabled(1), disabled(2) */ + else if (obj == ifHighSpeed) { + i = kif->if_baudrate >= 1000000 ? + kif->if_baudrate / 1000000 : 0; + agentx_varbind_gauge32(vb, i); + } else if (obj == ifPromiscuousMode) { + /* ifPromiscuousMode: true(1), false(2) */ + i = kif->if_flags & IFF_PROMISC ? 1 : 2; + agentx_varbind_integer(vb, i); + } else if (obj == ifConnectorPresent) { + /* ifConnectorPresent: false(2), true(1) */ + i = kif->if_type == IFT_ETHER ? 1 : 2; + agentx_varbind_integer(vb, i); + } else if (obj == ifAlias) + agentx_varbind_string(vb, kif->if_descr); + else if (obj == ifCounterDiscontinuityTime) + agentx_varbind_timeticks(vb, 0); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_ifstacklast(struct agentx_varbind *vb) +{ + agentx_varbind_timeticks(vb, kr_iflastchange()); +} + +void +mib_ifrcvtable(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + int32_t idx = 0; + const uint8_t *lladdr; + struct kif *kif; + int i = 0, llcmp, impl; + size_t slen; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, ifIdx); + lladdr = (const uint8_t *)agentx_varbind_get_index_string(vb, + ifRcvAddressAddress, &slen, &impl); + if (lladdr == NULL) + lladdr = ether_zeroaddr; + req = agentx_varbind_request(vb); + + if ((kif = mib_ifget(idx)) == NULL) { + agentx_varbind_notfound(vb); + return; + } + /* + * The lladdr of the interface will be encoded in the returned OID + * ifRcvAddressX.ifindex.6.x.x.x.x.x.x = val + * Thanks to the virtual cloner interfaces, it is an easy 1:1 + * mapping in OpenBSD; only one lladdr (MAC) address per interface. + */ + if (slen == 6) + llcmp = bcmp(lladdr, kif->if_lladdr, sizeof(kif->if_lladdr)); + if (req == AGENTX_REQUEST_TYPE_GET) { + if (idx != kif->if_index || slen != 6 || llcmp != 0) { + agentx_varbind_notfound(vb); + return; + } + } else if (idx == kif->if_index) { + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (slen > 6 || llcmp >= 0) + kif = kr_getnextif(kif->if_index); + } else { + if (slen > 6 || llcmp > 0) + kif = kr_getnextif(kif->if_index); + } + if (kif == NULL) { + agentx_varbind_notfound(vb); + return; + } + } + agentx_varbind_set_index_integer(vb, ifIdx, kif->if_index); + agentx_varbind_set_index_nstring(vb, ifRcvAddressAddress, + kif->if_lladdr, sizeof(kif->if_lladdr)); + + if (obj == ifRcvAddressStatus) { + /* ifRcvAddressStatus: RowStatus active(1), notInService(2) */ + i = kif->if_flags & IFF_UP ? 1 : 2; + agentx_varbind_integer(vb, i); + } else if (obj == ifRcvAddressType) { + /* ifRcvAddressType: other(1), volatile(2), nonVolatile(3) */ + agentx_varbind_integer(vb, 1); + } else + fatal("%s: Unexpected object", __func__); +} + +/* + * Defined in + * - OPENBSD-PF-MIB.txt + * - OPENBSD-SENSORS-MIB.txt + * - OPENBSD-CARP-MIB.txt + * (http://www.packetmischief.ca/openbsd-snmp-mibs/) + */ +#define OIDVER_OPENBSD_MEM 1 + +struct carpif { + struct carpreq carpr; + struct kif kif; +}; + +void mib_pfinfo(struct agentx_varbind *); +void mib_pfcounters(struct agentx_varbind *); +void mib_pfscounters(struct agentx_varbind *); +void mib_pflogif(struct agentx_varbind *); +void mib_pfsrctrack(struct agentx_varbind *); +void mib_pflimits(struct agentx_varbind *); +void mib_pftimeouts(struct agentx_varbind *); +void mib_pfifnum(struct agentx_varbind *); +void mib_pfiftable(struct agentx_varbind *); +void mib_pftablenum(struct agentx_varbind *); +void mib_pftables(struct agentx_varbind *); +void mib_pftableaddrs(struct agentx_varbind *); +void mib_pflabelnum(struct agentx_varbind *); +void mib_pflabels(struct agentx_varbind *); +void mib_pfsyncstats(struct agentx_varbind *); + +void mib_sensornum(struct agentx_varbind *); +void mib_sensors(struct agentx_varbind *); +const char *mib_sensorunit(struct sensor *); +char *mib_sensorvalue(struct sensor *); + +void mib_carpsysctl(struct agentx_varbind *); +void mib_carpstats(struct agentx_varbind *); +void mib_carpiftable(struct agentx_varbind *); +void mib_carpgrouptable(struct agentx_varbind *); +void mib_carpifnum(struct agentx_varbind *); +struct carpif + *mib_carpifget(u_int); +void mib_memversion(struct agentx_varbind *); +void mib_memiftable(struct agentx_varbind *); + +void +mib_pfinfo(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + struct pf_status s; + time_t runtime = 0; + struct timespec uptime; + + if (pf_get_stats(&s)) { + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + if (obj == pfRunning) + agentx_varbind_integer(vb, s.running); + else if (obj == pfRuntime) { + if (!clock_gettime(CLOCK_BOOTTIME, &uptime)) + runtime = uptime.tv_sec - s.since; + runtime *= 100; + agentx_varbind_timeticks(vb, runtime); + } else if (obj == pfDebug) + agentx_varbind_integer(vb, s.debug); + else if (obj == pfHostid) + agentx_varbind_printf(vb, "0x%08x", ntohl(s.hostid)); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_pfcounters(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + struct pf_status s; + + if (pf_get_stats(&s)) { + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + if (obj == pfCntMatch) + agentx_varbind_counter64(vb, s.counters[PFRES_MATCH]); + else if (obj == pfCntBadOffset) + agentx_varbind_counter64(vb, s.counters[PFRES_BADOFF]); + else if (obj == pfCntFragment) + agentx_varbind_counter64(vb, s.counters[PFRES_FRAG]); + else if (obj == pfCntShort) + agentx_varbind_counter64(vb, s.counters[PFRES_SHORT]); + else if (obj == pfCntNormalize) + agentx_varbind_counter64(vb, s.counters[PFRES_NORM]); + else if (obj == pfCntMemory) + agentx_varbind_counter64(vb, s.counters[PFRES_MEMORY]); + else if (obj == pfCntTimestamp) + agentx_varbind_counter64(vb, s.counters[PFRES_TS]); + else if (obj == pfCntCongestion) + agentx_varbind_counter64(vb, s.counters[PFRES_CONGEST]); + else if (obj == pfCntIpOption) + agentx_varbind_counter64(vb, s.counters[PFRES_IPOPTIONS]); + else if (obj == pfCntProtoCksum) + agentx_varbind_counter64(vb, s.counters[PFRES_PROTCKSUM]); + else if (obj == pfCntStateMismatch) + agentx_varbind_counter64(vb, s.counters[PFRES_BADSTATE]); + else if (obj == pfCntStateInsert) + agentx_varbind_counter64(vb, s.counters[PFRES_STATEINS]); + else if (obj == pfCntStateLimit) + agentx_varbind_counter64(vb, s.counters[PFRES_MAXSTATES]); + else if (obj == pfCntSrcLimit) + agentx_varbind_counter64(vb, s.counters[PFRES_SRCLIMIT]); + else if (obj == pfCntSynproxy) + agentx_varbind_counter64(vb, s.counters[PFRES_SYNPROXY]); + else if (obj == pfCntTranslate) + agentx_varbind_counter64(vb, s.counters[PFRES_TRANSLATE]); + else if (obj == pfCntNoRoute) + agentx_varbind_counter64(vb, s.counters[PFRES_NOROUTE]); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_pfscounters(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + struct pf_status s; + + if (pf_get_stats(&s)) { + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + if (obj == pfStateCount) + agentx_varbind_unsigned32(vb, s.states); + else if (obj == pfStateSearches) + agentx_varbind_counter64(vb, s.fcounters[FCNT_STATE_SEARCH]); + else if (obj == pfStateInserts) + agentx_varbind_counter64(vb, s.fcounters[FCNT_STATE_INSERT]); + else if (obj == pfStateRemovals) + agentx_varbind_counter64(vb, s.fcounters[FCNT_STATE_REMOVALS]); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_pflogif(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + struct pf_status s; + + if (pf_get_stats(&s)) { + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + if (obj == pfLogIfName) + agentx_varbind_string(vb, s.ifname); + else if (obj == pfLogIfIpBytesIn) + agentx_varbind_counter64(vb, s.bcounters[IPV4][IN]); + else if (obj == pfLogIfIpBytesOut) + agentx_varbind_counter64(vb, s.bcounters[IPV4][OUT]); + else if (obj == pfLogIfIpPktsInPass) + agentx_varbind_counter64(vb, s.pcounters[IPV4][IN][PF_PASS]); + else if (obj == pfLogIfIpPktsInDrop) + agentx_varbind_counter64(vb, s.pcounters[IPV4][IN][PF_DROP]); + else if (obj == pfLogIfIpPktsOutPass) + agentx_varbind_counter64(vb, s.pcounters[IPV4][OUT][PF_PASS]); + else if (obj == pfLogIfIpPktsOutDrop) + agentx_varbind_counter64(vb, s.pcounters[IPV4][OUT][PF_DROP]); + else if (obj == pfLogIfIp6BytesIn) + agentx_varbind_counter64(vb, s.bcounters[IPV6][IN]); + else if (obj == pfLogIfIp6BytesOut) + agentx_varbind_counter64(vb, s.bcounters[IPV6][OUT]); + else if (obj == pfLogIfIp6PktsInPass) + agentx_varbind_counter64(vb, s.pcounters[IPV6][IN][PF_PASS]); + else if (obj == pfLogIfIp6PktsInDrop) + agentx_varbind_counter64(vb, s.pcounters[IPV6][IN][PF_DROP]); + else if (obj == pfLogIfIp6PktsOutPass) + agentx_varbind_counter64(vb, s.pcounters[IPV6][OUT][PF_PASS]); + else if (obj == pfLogIfIp6PktsOutDrop) + agentx_varbind_counter64(vb, s.pcounters[IPV6][OUT][PF_DROP]); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_pfsrctrack(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + struct pf_status s; + + if (pf_get_stats(&s)) { + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + if (obj == pfSrcTrackCount) + agentx_varbind_unsigned32(vb, s.src_nodes); + else if (obj == pfSrcTrackSearches) + agentx_varbind_counter64(vb, s.scounters[SCNT_SRC_NODE_SEARCH]); + else if (obj == pfSrcTrackInserts) + agentx_varbind_counter64(vb, s.scounters[SCNT_SRC_NODE_INSERT]); + else if (obj == pfSrcTrackRemovals) + agentx_varbind_counter64(vb, + s.scounters[SCNT_SRC_NODE_REMOVALS]); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_pflimits(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + struct pfioc_limit pl; + extern int devpf; + + obj = agentx_varbind_get_object(vb); + memset(&pl, 0, sizeof(pl)); + if (obj == pfLimitStates) + pl.index = PF_LIMIT_STATES; + else if (obj == pfLimitSourceNodes) + pl.index = PF_LIMIT_SRC_NODES; + else if (obj == pfLimitFragments) + pl.index = PF_LIMIT_FRAGS; + else if (obj == pfLimitMaxTables) + pl.index = PF_LIMIT_TABLES; + else if (obj == pfLimitMaxTableEntries) + pl.index = PF_LIMIT_TABLE_ENTRIES; + else + fatal("%s: Unexpected object", __func__); + + if (ioctl(devpf, DIOCGETLIMIT, &pl) == -1) { + log_warn("DIOCGETLIMIT"); + agentx_varbind_error(vb); + return; + } + + agentx_varbind_unsigned32(vb, pl.limit); +} + +void +mib_pftimeouts(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + struct pfioc_tm pt; + extern int devpf; + + obj = agentx_varbind_get_object(vb); + memset(&pt, 0, sizeof(pt)); + if (obj == pfTimeoutTcpFirst) + pt.timeout = PFTM_TCP_FIRST_PACKET; + else if (obj == pfTimeoutTcpOpening) + pt.timeout = PFTM_TCP_OPENING; + else if (obj == pfTimeoutTcpEstablished) + pt.timeout = PFTM_TCP_ESTABLISHED; + else if (obj == pfTimeoutTcpClosing) + pt.timeout = PFTM_TCP_CLOSING; + else if (obj == pfTimeoutTcpFinWait) + pt.timeout = PFTM_TCP_FIN_WAIT; + else if (obj == pfTimeoutTcpClosed) + pt.timeout = PFTM_TCP_CLOSED; + else if (obj == pfTimeoutUdpFirst) + pt.timeout = PFTM_UDP_FIRST_PACKET; + else if (obj == pfTimeoutUdpSingle) + pt.timeout = PFTM_UDP_SINGLE; + else if (obj == pfTimeoutUdpMultiple) + pt.timeout = PFTM_UDP_MULTIPLE; + else if (obj == pfTimeoutIcmpFirst) + pt.timeout = PFTM_ICMP_FIRST_PACKET; + else if (obj == pfTimeoutIcmpError) + pt.timeout = PFTM_ICMP_ERROR_REPLY; + else if (obj == pfTimeoutOtherFirst) + pt.timeout = PFTM_OTHER_FIRST_PACKET; + else if (obj == pfTimeoutOtherSingle) + pt.timeout = PFTM_OTHER_SINGLE; + else if (obj == pfTimeoutOtherMultiple) + pt.timeout = PFTM_OTHER_MULTIPLE; + else if (obj == pfTimeoutFragment) + pt.timeout = PFTM_FRAG; + else if (obj == pfTimeoutInterval) + pt.timeout = PFTM_INTERVAL; + else if (obj == pfTimeoutAdaptiveStart) + pt.timeout = PFTM_ADAPTIVE_START; + else if (obj == pfTimeoutAdaptiveEnd) + pt.timeout = PFTM_ADAPTIVE_END; + else if (obj == pfTimeoutSrcTrack) + pt.timeout = PFTM_SRC_NODE; + else + fatal("%s: Unexpected object", __func__); + + if (ioctl(devpf, DIOCGETTIMEOUT, &pt) == -1) { + log_warn("DIOCGETTIMEOUT"); + agentx_varbind_error(vb); + return; + } + + agentx_varbind_integer(vb, pt.seconds); +} + +void +mib_pfifnum(struct agentx_varbind *vb) +{ + int c; + + if ((c = pfi_count()) == -1) + agentx_varbind_error(vb); + else + agentx_varbind_integer(vb, c); +} + +void +mib_pfiftable(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + struct pfi_kif pif; + int idx, iftype; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, pfIfIdx); + req = agentx_varbind_request(vb); + + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx < 1) + idx = 1; + else if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } else + idx++; + } else if (req == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) { + if (idx < 1) + idx = 1; + } + if (pfi_get_if(&pif, idx)) { + agentx_varbind_notfound(vb); + return; + } + agentx_varbind_set_index_integer(vb, pfIfIdx, idx); + + if (obj == pfIfIndex) + agentx_varbind_integer(vb, idx); + else if (obj == pfIfDescr) + agentx_varbind_string(vb, pif.pfik_name); + else if (obj == pfIfType) { + iftype = (pif.pfik_ifp == NULL ? PFI_IFTYPE_GROUP + : PFI_IFTYPE_INSTANCE); + agentx_varbind_integer(vb, iftype); + } else if (obj == pfIfRefs) + agentx_varbind_unsigned32(vb, pif.pfik_states); + else if (obj == pfIfRules) + agentx_varbind_unsigned32(vb, pif.pfik_rules); + else if (obj == pfIfIn4PassPkts) + agentx_varbind_counter64(vb, pif.pfik_packets[IPV4][IN][PASS]); + else if (obj == pfIfIn4PassBytes) + agentx_varbind_counter64(vb, pif.pfik_bytes[IPV4][IN][PASS]); + else if (obj == pfIfIn4BlockPkts) + agentx_varbind_counter64(vb, pif.pfik_packets[IPV4][IN][BLOCK]); + else if (obj == pfIfIn4BlockBytes) + agentx_varbind_counter64(vb, pif.pfik_bytes[IPV4][IN][BLOCK]); + else if (obj == pfIfOut4PassPkts) + agentx_varbind_counter64(vb, pif.pfik_packets[IPV4][OUT][PASS]); + else if (obj == pfIfOut4PassBytes) + agentx_varbind_counter64(vb, pif.pfik_bytes[IPV4][OUT][PASS]); + else if (obj == pfIfOut4BlockPkts) + agentx_varbind_counter64(vb, pif.pfik_packets[IPV4][OUT][BLOCK]); + else if (obj == pfIfOut4BlockBytes) + agentx_varbind_counter64(vb, pif.pfik_bytes[IPV4][OUT][BLOCK]); + else if (obj == pfIfIn6PassPkts) + agentx_varbind_counter64(vb, pif.pfik_packets[IPV6][IN][PASS]); + else if (obj == pfIfIn6PassBytes) + agentx_varbind_counter64(vb, pif.pfik_bytes[IPV6][IN][PASS]); + else if (obj == pfIfIn6BlockPkts) + agentx_varbind_counter64(vb, pif.pfik_packets[IPV6][IN][BLOCK]); + else if (obj == pfIfIn6BlockBytes) + agentx_varbind_counter64(vb, pif.pfik_bytes[IPV6][IN][BLOCK]); + else if (obj == pfIfOut6PassPkts) + agentx_varbind_counter64(vb, pif.pfik_packets[IPV6][OUT][PASS]); + else if (obj == pfIfOut6PassBytes) + agentx_varbind_counter64(vb, pif.pfik_bytes[IPV6][OUT][PASS]); + else if (obj == pfIfOut6BlockPkts) + agentx_varbind_counter64(vb, pif.pfik_packets[IPV6][OUT][BLOCK]); + else if (obj == pfIfOut6BlockBytes) + agentx_varbind_counter64(vb, pif.pfik_bytes[IPV6][OUT][BLOCK]); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_pftablenum(struct agentx_varbind *vb) +{ + int c; + + if ((c = pft_count()) == -1) + agentx_varbind_error(vb); + else + agentx_varbind_integer(vb, c); +} + +void +mib_pftables(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + struct pfr_tstats ts; + time_t tzero; + int idx; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, pfTblIdx); + req = agentx_varbind_request(vb); + + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx < 1) + idx = 1; + else if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } else + idx++; + } else if (req == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) { + if (idx < 1) + idx = 1; + } + if (pft_get_table(&ts, idx)) { + agentx_varbind_notfound(vb); + return; + } + agentx_varbind_set_index_integer(vb, pfTblIdx, idx); + + if (obj == pfTblIndex) + agentx_varbind_integer(vb, idx); + else if (obj == pfTblName) + agentx_varbind_string(vb, ts.pfrts_name); + else if (obj == pfTblAddresses) + agentx_varbind_integer(vb, ts.pfrts_cnt); + else if (obj == pfTblAnchorRefs) + agentx_varbind_integer(vb, ts.pfrts_refcnt[PFR_REFCNT_ANCHOR]); + else if (obj == pfTblRuleRefs) + agentx_varbind_integer(vb, ts.pfrts_refcnt[PFR_REFCNT_RULE]); + else if (obj == pfTblEvalsMatch) + agentx_varbind_counter64(vb, ts.pfrts_match); + else if (obj == pfTblEvalsNoMatch) + agentx_varbind_counter64(vb, ts.pfrts_nomatch); + else if (obj == pfTblInPassPkts) + agentx_varbind_counter64(vb, ts.pfrts_packets[IN][PFR_OP_PASS]); + else if (obj == pfTblInPassBytes) + agentx_varbind_counter64(vb, ts.pfrts_bytes[IN][PFR_OP_PASS]); + else if (obj == pfTblInBlockPkts) + agentx_varbind_counter64(vb, ts.pfrts_packets[IN][PFR_OP_BLOCK]); + else if (obj == pfTblInBlockBytes) + agentx_varbind_counter64(vb, ts.pfrts_bytes[IN][PFR_OP_BLOCK]); + else if (obj == pfTblInXPassPkts) + agentx_varbind_counter64(vb, ts.pfrts_packets[IN][PFR_OP_XPASS]); + else if (obj == pfTblInXPassBytes) + agentx_varbind_counter64(vb, ts.pfrts_bytes[IN][PFR_OP_XPASS]); + else if (obj == pfTblOutPassPkts) + agentx_varbind_counter64(vb, ts.pfrts_packets[OUT][PFR_OP_PASS]); + else if (obj == pfTblOutPassBytes) + agentx_varbind_counter64(vb, ts.pfrts_bytes[OUT][PFR_OP_PASS]); + else if (obj == pfTblOutBlockPkts) + agentx_varbind_counter64(vb, ts.pfrts_packets[OUT][PFR_OP_BLOCK]); + else if (obj == pfTblOutBlockBytes) + agentx_varbind_counter64(vb, ts.pfrts_bytes[OUT][PFR_OP_BLOCK]); + else if (obj == pfTblOutXPassPkts) + agentx_varbind_counter64(vb, ts.pfrts_packets[OUT][PFR_OP_XPASS]); + else if (obj == pfTblOutXPassBytes) + agentx_varbind_counter64(vb, ts.pfrts_bytes[OUT][PFR_OP_XPASS]); + else if (obj == pfTblStatsCleared) { + tzero = (time(NULL) - ts.pfrts_tzero) * 100; + agentx_varbind_timeticks(vb, tzero); + } else if (obj == pfTblInMatchPkts) + agentx_varbind_counter64(vb, ts.pfrts_packets[IN][PFR_OP_MATCH]); + else if (obj == pfTblInMatchBytes) + agentx_varbind_counter64(vb, ts.pfrts_bytes[IN][PFR_OP_MATCH]); + else if (obj == pfTblOutMatchPkts) + agentx_varbind_counter64(vb, ts.pfrts_packets[OUT][PFR_OP_MATCH]); + else if (obj == pfTblOutMatchBytes) + agentx_varbind_counter64(vb, ts.pfrts_bytes[OUT][PFR_OP_MATCH]); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_pftableaddrs(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + struct pfr_astats as; + int tblidx; + + obj = agentx_varbind_get_object(vb); + tblidx = agentx_varbind_get_index_integer(vb, pfTblAddrTblIdx); + req = agentx_varbind_request(vb); + + /* + * XXX No consistent way to differentiate between not found and error + * Treat everything as not found. + */ + if (req == AGENTX_REQUEST_TYPE_GET || + req == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) { + as.pfras_a.pfra_ip4addr = *agentx_varbind_get_index_ipaddress( + vb, pfTblAddrNetIdx); + as.pfras_a.pfra_net = agentx_varbind_get_index_integer(vb, + pfTblAddrMaskIdx); + + if (pfta_get_addr(&as, tblidx)) { + if (req == AGENTX_REQUEST_TYPE_GET) { + agentx_varbind_notfound(vb); + return; + } + req = AGENTX_REQUEST_TYPE_GETNEXT; + } + } + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (tblidx < 1) + tblidx = 1; + as.pfras_a.pfra_ip4addr = *agentx_varbind_get_index_ipaddress( + vb, pfTblAddrNetIdx); + as.pfras_a.pfra_net = agentx_varbind_get_index_integer(vb, + pfTblAddrMaskIdx); + + if (pfta_get_nextaddr(&as, &tblidx)){ + agentx_varbind_notfound(vb); + return; + } + } + agentx_varbind_set_index_integer(vb, pfTblAddrTblIdx, tblidx); + agentx_varbind_set_index_ipaddress(vb, pfTblAddrNetIdx, + &as.pfras_a.pfra_ip4addr); + agentx_varbind_set_index_integer(vb, pfTblAddrMaskIdx, + as.pfras_a.pfra_net); + + if (obj == pfTblAddrTblIndex) + agentx_varbind_integer(vb, tblidx); + else if (obj == pfTblAddrNet) + agentx_varbind_ipaddress(vb, &as.pfras_a.pfra_ip4addr); + else if (obj == pfTblAddrMask) + agentx_varbind_integer(vb, as.pfras_a.pfra_net); + else if (obj == pfTblAddrCleared) + agentx_varbind_timeticks(vb, (time(NULL) - as.pfras_tzero) * 100); + else if (obj == pfTblAddrInBlockPkts) + agentx_varbind_counter64(vb, as.pfras_packets[IN][PFR_OP_BLOCK]); + else if (obj == pfTblAddrInBlockBytes) + agentx_varbind_counter64(vb, as.pfras_bytes[IN][PFR_OP_BLOCK]); + else if (obj == pfTblAddrInPassPkts) + agentx_varbind_counter64(vb, as.pfras_packets[IN][PFR_OP_PASS]); + else if (obj == pfTblAddrInPassBytes) + agentx_varbind_counter64(vb, as.pfras_bytes[IN][PFR_OP_PASS]); + else if (obj == pfTblAddrOutBlockPkts) + agentx_varbind_counter64(vb, as.pfras_packets[OUT][PFR_OP_BLOCK]); + else if (obj == pfTblAddrOutBlockBytes) + agentx_varbind_counter64(vb, as.pfras_bytes[OUT][PFR_OP_BLOCK]); + else if (obj == pfTblAddrOutPassPkts) + agentx_varbind_counter64(vb, as.pfras_packets[OUT][PFR_OP_PASS]); + else if (obj == pfTblAddrOutPassBytes) + agentx_varbind_counter64(vb, as.pfras_bytes[OUT][PFR_OP_PASS]); + else if (obj == pfTblAddrInMatchPkts) + agentx_varbind_counter64(vb, as.pfras_packets[IN][PFR_OP_MATCH]); + else if (obj == pfTblAddrInMatchBytes) + agentx_varbind_counter64(vb, as.pfras_bytes[IN][PFR_OP_MATCH]); + else if (obj == pfTblAddrOutMatchPkts) + agentx_varbind_counter64(vb, as.pfras_packets[OUT][PFR_OP_MATCH]); + else if (obj == pfTblAddrOutMatchBytes) + agentx_varbind_counter64(vb, as.pfras_bytes[OUT][PFR_OP_MATCH]); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_pflabelnum(struct agentx_varbind *vb) +{ + struct pfioc_rule pr; + u_int32_t nr, mnr, lnr; + extern int devpf; + + memset(&pr, 0, sizeof(pr)); + if (ioctl(devpf, DIOCGETRULES, &pr) == -1) { + log_warn("DIOCGETRULES"); + agentx_varbind_error(vb); + return; + } + + mnr = pr.nr; + lnr = 0; + for (nr = 0; nr < mnr; ++nr) { + pr.nr = nr; + if (ioctl(devpf, DIOCGETRULE, &pr) == -1) { + log_warn("DIOCGETRULE"); + agentx_varbind_error(vb); + return; + } + + if (pr.rule.label[0]) + lnr++; + } + + agentx_varbind_integer(vb, lnr); +} + +void +mib_pflabels(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + struct pfioc_rule pr; + struct pf_rule *r = NULL; + u_int32_t nr, mnr, lnr; + u_int32_t idx; + extern int devpf; + + memset(&pr, 0, sizeof(pr)); + if (ioctl(devpf, DIOCGETRULES, &pr) == -1) { + log_warn("DIOCGETRULES"); + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, pfLabelIdx); + req = agentx_varbind_request(vb); + + if (idx < 1) { + if (req == AGENTX_REQUEST_TYPE_GET) { + agentx_varbind_notfound(vb); + return; + } + idx = 1; + } else if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + + mnr = pr.nr; + lnr = 0; + for (nr = 0; nr < mnr; ++nr) { + pr.nr = nr; + if (ioctl(devpf, DIOCGETRULE, &pr) == -1) { + log_warn("DIOCGETRULE"); + agentx_varbind_error(vb); + return; + } + + if (pr.rule.label[0] && ++lnr == idx) { + r = &pr.rule; + break; + } + } + + if (r == NULL) { + agentx_varbind_notfound(vb); + return; + } + agentx_varbind_set_index_integer(vb, pfLabelIdx, idx); + + if (obj == pfLabelIndex) + agentx_varbind_integer(vb, lnr); + else if (obj == pfLabelName) + agentx_varbind_string(vb, r->label); + else if (obj == pfLabelEvals) + agentx_varbind_counter64(vb, r->evaluations); + else if (obj == pfLabelPkts) + agentx_varbind_counter64(vb, r->packets[IN] + r->packets[OUT]); + else if (obj == pfLabelBytes) + agentx_varbind_counter64(vb, r->bytes[IN] + r->bytes[OUT]); + else if (obj == pfLabelInPkts) + agentx_varbind_counter64(vb, r->packets[IN]); + else if (obj == pfLabelInBytes) + agentx_varbind_counter64(vb, r->bytes[IN]); + else if (obj == pfLabelOutPkts) + agentx_varbind_counter64(vb, r->packets[OUT]); + else if (obj == pfLabelOutBytes) + agentx_varbind_counter64(vb, r->bytes[OUT]); + else if (obj == pfLabelTotalStates) + agentx_varbind_counter32(vb, r->states_tot); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_pfsyncstats(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + int mib[] = { CTL_NET, PF_INET, IPPROTO_PFSYNC, + PFSYNCCTL_STATS }; + size_t len = sizeof(struct pfsyncstats); + struct pfsyncstats s; + + if (sysctl(mib, 4, &s, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + if (obj == pfsyncIpPktsRecv) + agentx_varbind_counter64(vb, s.pfsyncs_ipackets); + else if (obj == pfsyncIp6PktsRecv) + agentx_varbind_counter64(vb, s.pfsyncs_ipackets6); + else if (obj == pfsyncPktDiscardsForBadInterface) + agentx_varbind_counter64(vb, s.pfsyncs_badif); + else if (obj == pfsyncPktDiscardsForBadTtl) + agentx_varbind_counter64(vb, s.pfsyncs_badttl); + else if (obj == pfsyncPktShorterThanHeader) + agentx_varbind_counter64(vb, s.pfsyncs_hdrops); + else if (obj == pfsyncPktDiscardsForBadVersion) + agentx_varbind_counter64(vb, s.pfsyncs_badver); + else if (obj == pfsyncPktDiscardsForBadAction) + agentx_varbind_counter64(vb, s.pfsyncs_badact); + else if (obj == pfsyncPktDiscardsForBadLength) + agentx_varbind_counter64(vb, s.pfsyncs_badlen); + else if (obj == pfsyncPktDiscardsForBadAuth) + agentx_varbind_counter64(vb, s.pfsyncs_badauth); + else if (obj == pfsyncPktDiscardsForStaleState) + agentx_varbind_counter64(vb, s.pfsyncs_stale); + else if (obj == pfsyncPktDiscardsForBadValues) + agentx_varbind_counter64(vb, s.pfsyncs_badval); + else if (obj == pfsyncPktDiscardsForBadState) + agentx_varbind_counter64(vb, s.pfsyncs_badstate); + else if (obj == pfsyncIpPktsSent) + agentx_varbind_counter64(vb, s.pfsyncs_opackets); + else if (obj == pfsyncIp6PktsSent) + agentx_varbind_counter64(vb, s.pfsyncs_opackets6); + else if (obj == pfsyncNoMemory) + agentx_varbind_counter64(vb, s.pfsyncs_onomem); + else if (obj == pfsyncOutputErrors) + agentx_varbind_counter64(vb, s.pfsyncs_oerrors); + else + fatal("%s: Unexpected object", __func__); +} + +/* OPENBSD-SENSORS-MIB */ +void +mib_sensornum(struct agentx_varbind *vb) +{ + struct sensordev sensordev; + size_t len = sizeof(sensordev); + int mib[] = { CTL_HW, HW_SENSORS, 0 }; + int i, c; + + for (i = c = 0; ; i++) { + mib[2] = i; + if (sysctl(mib, nitems(mib), + &sensordev, &len, NULL, 0) == -1) { + if (errno == ENXIO) + continue; + if (errno == ENOENT) + break; + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + c += sensordev.sensors_count; + } + + agentx_varbind_integer(vb, c); +} + +void +mib_sensors(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + struct sensordev sensordev; + size_t len = sizeof(sensordev); + struct sensor sensor; + size_t slen = sizeof(sensor); + char desc[32]; + int mib[] = + { CTL_HW, HW_SENSORS, 0, 0, 0 }; + int i, j, k; + u_int32_t idx = 0, n; + char *s; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, sensorIdx); + req = agentx_varbind_request(vb); + + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + if (idx < 1 && + (req == AGENTX_REQUEST_TYPE_GETNEXT || + req == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE)) + idx = 1; + + for (i = 0, n = 1; ; i++) { + mib[2] = i; + if (sysctl(mib, 3, &sensordev, &len, NULL, 0) == -1) { + if (errno == ENXIO) + continue; + if (errno == ENOENT) + break; + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + for (j = 0; j < SENSOR_MAX_TYPES; j++) { + mib[3] = j; + for (k = 0; k < sensordev.maxnumt[j]; k++) { + mib[4] = k; + if (sysctl(mib, 5, + &sensor, &slen, NULL, 0) == -1) { + if (errno == ENXIO) + continue; + if (errno == ENOENT) + break; + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + if (sensor.flags & SENSOR_FINVALID) + continue; + if (n == idx) + goto found; + n++; + } + } + } + agentx_varbind_notfound(vb); + return; + + found: + agentx_varbind_set_index_integer(vb, sensorIdx, idx); + if (obj == sensorIndex) + agentx_varbind_integer(vb, (int32_t)n); + else if (obj == sensorDescr) { + if (sensor.desc[0] == '\0') { + snprintf(desc, sizeof(desc), "%s%d", + sensor_type_s[sensor.type], + sensor.numt); + agentx_varbind_string(vb, desc); + } else + agentx_varbind_string(vb, sensor.desc); + } else if (obj == sensorType) + agentx_varbind_integer(vb, sensor.type); + else if (obj == sensorDevice) + agentx_varbind_string(vb, sensordev.xname); + else if (obj == sensorValue) { + if ((s = mib_sensorvalue(&sensor)) == NULL) { + log_warn("asprintf"); + agentx_varbind_error(vb); + return; + } + agentx_varbind_string(vb, s); + free(s); + } else if (obj == sensorUnits) + agentx_varbind_string(vb, mib_sensorunit(&sensor)); + else if (obj == sensorStatus) + agentx_varbind_integer(vb, sensor.status); + else + fatal("%s: Unexpected object", __func__); +} + +#define SENSOR_DRIVE_STATES (SENSOR_DRIVE_PFAIL + 1) +static const char * const sensor_drive_s[SENSOR_DRIVE_STATES] = { + NULL, "empty", "ready", "powerup", "online", "idle", "active", + "rebuild", "powerdown", "fail", "pfail" +}; + +static const char * const sensor_unit_s[SENSOR_MAX_TYPES + 1] = { + "degC", "RPM", "V DC", "V AC", "Ohm", "W", "A", "Wh", "Ah", + "", "", "%", "lx", "", "sec", "%RH", "Hz", "degree", + "m", "Pa", "m/s^2", "m/s", "" +}; + +const char * +mib_sensorunit(struct sensor *s) +{ + u_int idx; + idx = s->type > SENSOR_MAX_TYPES ? + SENSOR_MAX_TYPES : s->type; + return (sensor_unit_s[idx]); +} + +char * +mib_sensorvalue(struct sensor *s) +{ + char *v; + int ret = -1; + + switch (s->type) { + case SENSOR_TEMP: + ret = asprintf(&v, "%.2f", + (s->value - 273150000) / 1000000.0); + break; + case SENSOR_VOLTS_DC: + case SENSOR_VOLTS_AC: + case SENSOR_WATTS: + case SENSOR_AMPS: + case SENSOR_WATTHOUR: + case SENSOR_AMPHOUR: + case SENSOR_LUX: + case SENSOR_FREQ: + case SENSOR_ACCEL: + case SENSOR_VELOCITY: + case SENSOR_DISTANCE: + ret = asprintf(&v, "%.2f", s->value / 1000000.0); + break; + case SENSOR_INDICATOR: + ret = asprintf(&v, "%s", s->value ? "on" : "off"); + break; + case SENSOR_PERCENT: + case SENSOR_HUMIDITY: + ret = asprintf(&v, "%.2f", s->value / 1000.0); + break; + case SENSOR_PRESSURE: + ret = asprintf(&v, "%.2f", s->value / 1000.0); + break; + case SENSOR_TIMEDELTA: + ret = asprintf(&v, "%.6f", s->value / 1000000000.0); + break; + case SENSOR_DRIVE: + if (s->value > 0 && s->value < SENSOR_DRIVE_STATES) { + ret = asprintf(&v, "%s", sensor_drive_s[s->value]); + break; + } + /* FALLTHROUGH */ + case SENSOR_FANRPM: + case SENSOR_OHMS: + case SENSOR_INTEGER: + default: + ret = asprintf(&v, "%lld", s->value); + break; + } + + if (ret == -1) + return (NULL); + return (v); +} + +void +mib_carpsysctl(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + size_t len; + int mib[] = { CTL_NET, PF_INET, IPPROTO_CARP, 0 }; + int v; + + obj = agentx_varbind_get_object(vb); + if (obj == carpAllow) + mib[3] = CARPCTL_ALLOW; + else if (obj == carpPreempt) + mib[3] = CARPCTL_PREEMPT; + else if (obj == carpLog) + mib[3] = CARPCTL_LOG; + else + fatal("%s: Unexpected object", __func__); + len = sizeof(v); + + if (sysctl(mib, 4, &v, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + agentx_varbind_integer(vb, v); +} + +void +mib_carpstats(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + int mib[] = { CTL_NET, PF_INET, IPPROTO_CARP, + CARPCTL_STATS }; + size_t len; + struct carpstats stats; + + len = sizeof(stats); + + if (sysctl(mib, 4, &stats, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + if (obj == carpIpPktsRecv) + agentx_varbind_counter64(vb, stats.carps_ipackets); + else if (obj == carpIp6PktsRecv) + agentx_varbind_counter64(vb, stats.carps_ipackets6); + else if (obj == carpPktDiscardsForBadInterface) + agentx_varbind_counter64(vb, stats.carps_badif); + else if (obj == carpPktDiscardsForWrongTtl) + agentx_varbind_counter64(vb, stats.carps_badttl); + else if (obj == carpPktShorterThanHeader) + agentx_varbind_counter64(vb, stats.carps_hdrops); + else if (obj == carpPktDiscardsForBadChecksum) + agentx_varbind_counter64(vb, stats.carps_badsum); + else if (obj == carpPktDiscardsForBadVersion) + agentx_varbind_counter64(vb, stats.carps_badver); + else if (obj == carpPktDiscardsForTooShort) + agentx_varbind_counter64(vb, stats.carps_badlen); + else if (obj == carpPktDiscardsForBadAuth) + agentx_varbind_counter64(vb, stats.carps_badauth); + else if (obj == carpPktDiscardsForBadVhid) + agentx_varbind_counter64(vb, stats.carps_badvhid); + else if (obj == carpPktDiscardsForBadAddressList) + agentx_varbind_counter64(vb, stats.carps_badaddrs); + else if (obj == carpIpPktsSent) + agentx_varbind_counter64(vb, stats.carps_opackets); + else if (obj == carpIp6PktsSent) + agentx_varbind_counter64(vb, stats.carps_opackets6); + else if (obj == carpNoMemory) + agentx_varbind_counter64(vb, stats.carps_onomem); + else if (obj == carpTransitionsToMaster) + agentx_varbind_counter64(vb, stats.carps_preempt); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_carpifnum(struct agentx_varbind *vb) +{ + struct kif *kif; + int c = 0; + + for (kif = kr_getif(0); kif != NULL; + kif = kr_getnextif(kif->if_index)) + if (kif->if_type == IFT_CARP) + c++; + + agentx_varbind_integer(vb, c); +} + +struct carpif * +mib_carpifget(u_int idx) +{ + struct kif *kif; + struct carpif *cif; + int s; + struct ifreq ifr; + struct carpreq carpr; + + if ((kif = kr_getif(idx)) == NULL || kif->if_type != IFT_CARP) { + /* + * It may happen that an interface with a specific index + * does not exist, has been removed, or is not a carp(4) + * interface. Jump to the next available carp(4) interface + * index. + */ + for (kif = kr_getif(0); kif != NULL; + kif = kr_getnextif(kif->if_index)) { + if (kif->if_type != IFT_CARP) + continue; + if (kif->if_index > idx) + break; + + } + if (kif == NULL) + return (NULL); + } + idx = kif->if_index; + + /* Update interface information */ + kr_updateif(idx); + if ((kif = kr_getif(idx)) == NULL) { + log_debug("mib_carpifget: interface %d disappeared?", idx); + return (NULL); + } + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + return (NULL); + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, kif->if_name, sizeof(ifr.ifr_name)); + memset((char *)&carpr, 0, sizeof(carpr)); + ifr.ifr_data = (caddr_t)&carpr; + + if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1) { + close(s); + return (NULL); + } + + cif = calloc(1, sizeof(struct carpif)); + if (cif != NULL) { + memcpy(&cif->carpr, &carpr, sizeof(struct carpreq)); + memcpy(&cif->kif, kif, sizeof(struct kif)); + } + + close(s); + + return (cif); +} + +void +mib_carpiftable(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + u_int32_t idx; + struct carpif *cif; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, carpIfIdx); + req = agentx_varbind_request(vb); + + if (idx < 1) { + if (req == AGENTX_REQUEST_TYPE_GET) { + agentx_varbind_notfound(vb); + return; + } + idx = 1; + } else if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + + /* + * XXX No consistent way to differentiate between not found and error + * Treat everything as not found. + */ + if ((cif = mib_carpifget(idx)) == NULL) { + agentx_varbind_notfound(vb); + return; + } + + if (req == AGENTX_REQUEST_TYPE_GET && cif->kif.if_index != idx) { + agentx_varbind_notfound(vb); + return; + } + agentx_varbind_set_index_integer(vb, carpIfIdx, cif->kif.if_index); + + if (obj == carpIfIndex) + agentx_varbind_integer(vb, cif->kif.if_index); + else if (obj == carpIfDescr) + agentx_varbind_string(vb, cif->kif.if_name); + else if (obj == carpIfVhid) + agentx_varbind_integer(vb, cif->carpr.carpr_vhids[0]); + else if (obj == carpIfDev) + agentx_varbind_string(vb, cif->carpr.carpr_carpdev); + else if (obj == carpIfAdvbase) + agentx_varbind_integer(vb, cif->carpr.carpr_advbase); + else if (obj == carpIfAdvskew) + agentx_varbind_integer(vb, cif->carpr.carpr_advskews[0]); + else if (obj == carpIfState) + agentx_varbind_integer(vb, cif->carpr.carpr_states[0]); + else + fatal("%s: Unexpected object", __func__); + free(cif); +} + +static struct ifg_req * +mib_carpgroupget(u_int idx) +{ + struct ifgroupreq ifgr; + struct ifg_req *ifg = NULL; + u_int len; + int s = -1; + + bzero(&ifgr, sizeof(ifgr)); + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + log_warn("socket"); + return (NULL); + } + + if (ioctl(s, SIOCGIFGLIST, (caddr_t)&ifgr) == -1) { + log_warn("SIOCGIFGLIST"); + goto err; + } + len = ifgr.ifgr_len; + + if (len / sizeof(*ifgr.ifgr_groups) <= idx-1) + goto err; + + if ((ifgr.ifgr_groups = calloc(1, len)) == NULL) { + log_warn("alloc"); + goto err; + } + if (ioctl(s, SIOCGIFGLIST, (caddr_t)&ifgr) == -1) { + log_warn("SIOCGIFGLIST"); + goto err; + } + close(s); + + if ((ifg = calloc(1, sizeof *ifg)) == NULL) { + log_warn("alloc"); + goto err; + } + + memcpy(ifg, &ifgr.ifgr_groups[idx-1], sizeof *ifg); + free(ifgr.ifgr_groups); + return ifg; + err: + free(ifgr.ifgr_groups); + close(s); + return (NULL); +} + +void +mib_carpgrouptable(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + struct ifgroupreq ifgr; + struct ifg_req *ifg; + uint32_t idx; + int s; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, carpGroupIdx); + req = agentx_varbind_request(vb); + + if (idx < 1) { + if (req == AGENTX_REQUEST_TYPE_GET) { + agentx_varbind_notfound(vb); + return; + } + idx = 1; + } else if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + + /* + * XXX No consistent way to differentiate between not found and error + * Treat everything as not found. + */ + if ((ifg = mib_carpgroupget(idx)) == NULL) { + agentx_varbind_notfound(vb); + return; + } + agentx_varbind_set_index_integer(vb, carpGroupIdx, idx); + + if (obj == carpGroupName) + agentx_varbind_string(vb, ifg->ifgrq_group); + else if (obj == carpGroupDemote) { + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + log_warn("socket"); + free(ifg); + agentx_varbind_error(vb); + return; + } + + bzero(&ifgr, sizeof(ifgr)); + strlcpy(ifgr.ifgr_name, ifg->ifgrq_group, sizeof(ifgr.ifgr_name)); + if (ioctl(s, SIOCGIFGATTR, (caddr_t)&ifgr) == -1) { + log_warn("SIOCGIFGATTR"); + close(s); + free(ifg); + agentx_varbind_error(vb); + return; + } + + close(s); + agentx_varbind_integer(vb, ifgr.ifgr_attrib.ifg_carp_demoted); + } else + fatal("%s: Unexpected object", __func__); + + free(ifg); +} + +void +mib_memversion(struct agentx_varbind *vb) +{ + agentx_varbind_integer(vb, 1); +} + +void +mib_memiftable(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + u_int32_t idx = 0; + struct kif *kif; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, ifIdx); + req = agentx_varbind_request(vb); + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + if ((kif = mib_ifget(idx)) == NULL) { + agentx_varbind_notfound(vb); + return; + } + if (req == AGENTX_REQUEST_TYPE_GET) { + if (idx != kif->if_index) { + agentx_varbind_notfound(vb); + return; + } + } + agentx_varbind_set_index_integer(vb, ifIdx, kif->if_index); + + if (obj == memIfName) + agentx_varbind_string(vb, kif->if_name); + else if (obj == memIfLiveLocks) + agentx_varbind_counter64(vb, 0); + else + fatal("%s: Unexpected object", __func__); +} + +/* + * Defined in IP-MIB.txt + */ +int mib_getipstat(struct ipstat *); +void mib_ipstat(struct agentx_varbind *); +void mib_ipforwarding(struct agentx_varbind *); +void mib_ipdefaultttl(struct agentx_varbind *); +void mib_ipinhdrerrs(struct agentx_varbind *); +void mib_ipinaddrerrs(struct agentx_varbind *); +void mib_ipforwdgrams(struct agentx_varbind *); +void mib_ipreasmtimeout(struct agentx_varbind *); +void mib_ipreasmfails(struct agentx_varbind *); +void mib_ipfragfails(struct agentx_varbind *); +void mib_ipaddr(struct agentx_varbind *); +void mib_physaddr(struct agentx_varbind *); + +void +mib_ipforwarding(struct agentx_varbind *vb) +{ + int mib[] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_FORWARDING }; + int v; + size_t len = sizeof(v); + + if (sysctl(mib, nitems(mib), &v, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + /* ipForwarding: forwarding(1), notForwarding(2) */ + agentx_varbind_integer(vb, (v == 0) ? 2 : 1); +} + +void +mib_ipdefaultttl(struct agentx_varbind *vb) +{ + int mib[] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_DEFTTL }; + int v; + size_t len = sizeof(v); + + if (sysctl(mib, nitems(mib), &v, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + agentx_varbind_integer(vb, v); +} + +int +mib_getipstat(struct ipstat *ipstat) +{ + int mib[] = { CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS }; + size_t len = sizeof(*ipstat); + + return (sysctl(mib, nitems(mib), ipstat, &len, NULL, 0)); +} + +void +mib_ipstat(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + struct ipstat ipstat; + + if (mib_getipstat(&ipstat) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + if (obj == ipInReceives) + agentx_varbind_counter32(vb, ipstat.ips_total); + else if (obj == ipInUnknownProtos) + agentx_varbind_counter32(vb, ipstat.ips_noproto); + else if (obj == ipInDelivers) + agentx_varbind_counter32(vb, ipstat.ips_delivered); + else if (obj == ipOutRequests) + agentx_varbind_counter32(vb, ipstat.ips_localout); + else if (obj == ipOutDiscards) + agentx_varbind_counter32(vb, ipstat.ips_odropped); + else if (obj == ipOutNoRoutes) + agentx_varbind_counter32(vb, ipstat.ips_noroute); + else if (obj == ipReasmReqds) + agentx_varbind_counter32(vb, ipstat.ips_fragments); + else if (obj == ipReasmOKs) + agentx_varbind_counter32(vb, ipstat.ips_reassembled); + else if (obj == ipFragOKs) + agentx_varbind_counter32(vb, ipstat.ips_fragmented); + else if (obj == ipFragCreates) + agentx_varbind_counter32(vb, ipstat.ips_ofragments); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_ipinhdrerrs(struct agentx_varbind *vb) +{ + u_int32_t errors; + struct ipstat ipstat; + + if (mib_getipstat(&ipstat) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + errors = ipstat.ips_badsum + ipstat.ips_badvers + + ipstat.ips_tooshort + ipstat.ips_toosmall + + ipstat.ips_badhlen + ipstat.ips_badlen + + ipstat.ips_badoptions + ipstat.ips_toolong + + ipstat.ips_badaddr; + + agentx_varbind_counter32(vb, errors); +} + +void +mib_ipinaddrerrs(struct agentx_varbind *vb) +{ + u_int32_t errors; + struct ipstat ipstat; + + if (mib_getipstat(&ipstat) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + errors = ipstat.ips_cantforward + ipstat.ips_badaddr; + + agentx_varbind_counter32(vb, errors); +} + +void +mib_ipforwdgrams(struct agentx_varbind *vb) +{ + u_int32_t counter; + struct ipstat ipstat; + + if (mib_getipstat(&ipstat) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + counter = ipstat.ips_forward + ipstat.ips_redirectsent; + + agentx_varbind_counter32(vb, counter); +} + +void +mib_ipreasmtimeout(struct agentx_varbind *vb) +{ + agentx_varbind_integer(vb, IPFRAGTTL); +} + +void +mib_ipreasmfails(struct agentx_varbind *vb) +{ + u_int32_t counter; + struct ipstat ipstat; + + if (mib_getipstat(&ipstat) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + counter = ipstat.ips_fragdropped + ipstat.ips_fragtimeout; + + agentx_varbind_counter32(vb, counter); +} + +void +mib_ipfragfails(struct agentx_varbind *vb) +{ + u_int32_t counter; + struct ipstat ipstat; + + if (mib_getipstat(&ipstat) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + counter = ipstat.ips_badfrags + ipstat.ips_cantfrag; + agentx_varbind_counter32(vb, counter); +} + +void +mib_ipaddr(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + struct sockaddr_in addr; + struct kif_addr *ka; + + obj = agentx_varbind_get_object(vb); + req = agentx_varbind_request(vb); + bzero(&addr, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_len = sizeof(addr); + addr.sin_addr = *agentx_varbind_get_index_ipaddress(vb, ipAdEntAddrIdx); + + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (addr.sin_addr.s_addr == UINT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + addr.sin_addr.s_addr = htonl(ntohl(addr.sin_addr.s_addr) + 1); + } + /* + * XXX No consistent way to differentiate between not found and error + * Treat everything as not found. + */ + ka = kr_getnextaddr((struct sockaddr *)&addr); + if (ka == NULL || ka->addr.sa.sa_family != AF_INET) { + agentx_varbind_notfound(vb); + return; + } + if (req == AGENTX_REQUEST_TYPE_GET) { + if (addr.sin_addr.s_addr != + ((struct sockaddr_in *)&ka->addr.sa)->sin_addr.s_addr) { + agentx_varbind_notfound(vb); + return; + } + } + agentx_varbind_set_index_ipaddress(vb, ipAdEntAddrIdx, + &((struct sockaddr_in *)&ka->addr.sa)->sin_addr); + + if (obj == ipAdEntAddr) + agentx_varbind_ipaddress(vb, + &((struct sockaddr_in *)&ka->addr.sa)->sin_addr); + else if (obj == ipAdEntIfIndex) + agentx_varbind_integer(vb, ka->if_index); + else if (obj == ipAdEntNetMask) + agentx_varbind_ipaddress(vb, &ka->mask.sin.sin_addr); + else if (obj == ipAdEntBcastAddr) + agentx_varbind_integer(vb, ka->dstbrd.sa.sa_len ? 1 : 0); + else if (obj == ipAdEntReasmMaxSize) + agentx_varbind_integer(vb, IP_MAXPACKET); + else + fatal("%s: Unexpected object", __func__); +} + +void +mib_physaddr(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + struct sockaddr_in addr; + struct kif *kif; + struct kif_arp *ka; + u_int32_t idx = 0; + + obj = agentx_varbind_get_object(vb); + idx = agentx_varbind_get_index_integer(vb, ipNetToMediaIfIdx); + req = agentx_varbind_request(vb); + + /* Get the IP address */ + bzero(&addr, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_len = sizeof(addr); + addr.sin_addr = *agentx_varbind_get_index_ipaddress(vb, + ipNetToMediaNetAddressIdx); + + if (req == AGENTX_REQUEST_TYPE_GET || + req == AGENTX_REQUEST_TYPE_GETNEXTINCLUSIVE) { + if ((ka = karp_getaddr((struct sockaddr *)&addr, idx, 0)) == NULL) { + if (req == AGENTX_REQUEST_TYPE_GET) { + agentx_varbind_notfound(vb); + return; + } + req = AGENTX_REQUEST_TYPE_GETNEXT; + } else { + if (req == AGENTX_REQUEST_TYPE_GET && + (idx != ka->if_index || + addr.sin_addr.s_addr != + ka->addr.sin.sin_addr.s_addr)) { + agentx_varbind_notfound(vb); + return; + } + } + } + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if ((kif = kr_getif(idx)) == NULL) { + /* No configured interfaces */ + if (idx == 0) { + agentx_varbind_notfound(vb); + return; + } + /* + * It may happen that an interface with a specific index + * does not exist or has been removed. Jump to the next + * available interface. + */ + kif = kr_getif(0); + nextif: + for (; kif != NULL; kif = kr_getnextif(kif->if_index)) + if (kif->if_index > idx && + (ka = karp_first(kif->if_index)) != NULL) + break; + if (kif == NULL) { + /* No more interfaces with addresses on them */ + agentx_varbind_notfound(vb); + return; + } + } else { + if (idx == 0 || addr.sin_addr.s_addr == 0) + ka = karp_first(kif->if_index); + else { + /* XXX This only works on a walk. */ + ka = karp_getaddr((struct sockaddr *)&addr, idx, 1); + } + if (ka == NULL) { + /* Try next interface */ + goto nextif; + } + } + } + agentx_varbind_set_index_integer(vb, ipNetToMediaIfIdx, ka->if_index); + agentx_varbind_set_index_ipaddress(vb, ipNetToMediaNetAddressIdx, + &ka->addr.sin.sin_addr); + + if (obj == ipNetToMediaIfIndex) + agentx_varbind_integer(vb, ka->if_index); + else if (obj == ipNetToMediaPhysAddress) { + if (bcmp(LLADDR(&ka->target.sdl), ether_zeroaddr, + sizeof(ether_zeroaddr)) == 0) + agentx_varbind_nstring(vb, ether_zeroaddr, + sizeof(ether_zeroaddr)); + else + agentx_varbind_nstring(vb, LLADDR(&ka->target.sdl), + ka->target.sdl.sdl_alen); + } else if (obj == ipNetToMediaNetAddress) + agentx_varbind_ipaddress(vb, &ka->addr.sin.sin_addr); + else if (obj == ipNetToMediaType) { + if (ka->flags & F_STATIC) + agentx_varbind_integer(vb, 4); /* static */ + else + agentx_varbind_integer(vb, 3); /* dynamic */ + } else + fatal("%s: Unexpected object", __func__); +} + +/* + * Defined in IP-FORWARD-MIB.txt (rfc4292) + */ + +void mib_ipfnroutes(struct agentx_varbind *); +//struct ber_oid * +//mib_ipfroutetable(struct oid *oid, struct ber_oid *o, struct ber_oid *no); +void mib_ipfroute(struct agentx_varbind *); + +void +mib_ipfnroutes(struct agentx_varbind *vb) +{ + agentx_varbind_gauge32(vb, kr_routenumber()); +} + +#define INETADDRESSTYPE_IPV4 1 +void +mib_ipfroute(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + struct kroute *kr; + const in_addr_t *addr, *nhaddr; + const uint32_t *policy; + size_t alen, plen, nlen; + int af; + int implied; + u_int8_t prefixlen, prio, type, proto; + + + obj = agentx_varbind_get_object(vb); + req = agentx_varbind_request(vb); + af = agentx_varbind_get_index_integer(vb, inetCidrRouteDestTypeIdx); + addr = (const in_addr_t *)agentx_varbind_get_index_string(vb, + inetCidrRouteDestIdx, &alen, &implied); + prefixlen = agentx_varbind_get_index_integer(vb, + inetCidrRoutePfxLenIdx); + policy = agentx_varbind_get_index_oid(vb, inetCidrRoutePolicyIdx, + &plen, &implied); + nhaddr = ((const in_addr_t *)agentx_varbind_get_index_string(vb, + inetCidrRouteNextHopIdx, &nlen, &implied)); + + if (plen >= 2) + prio = policy[1]; + /* Initial 2 sub-identifiers should always be the same for us */ + if (af < INETADDRESSTYPE_IPV4 || + (af == INETADDRESSTYPE_IPV4 && alen < 4)) { + if (req == AGENTX_REQUEST_TYPE_GET) { + agentx_varbind_notfound(vb); + return; + } + kr = kroute_first(); + } else if (af > INETADDRESSTYPE_IPV4 || + (af == INETADDRESSTYPE_IPV4 && alen > 4)) { + agentx_varbind_notfound(vb); + return; + } else { + /* XXX This only works when requesting known values. */ + kr = kroute_getaddr(*addr, prefixlen, prio, + req == AGENTX_REQUEST_TYPE_GETNEXT); + if (kr == NULL) { + agentx_varbind_notfound(vb); + return; + } + if (req == AGENTX_REQUEST_TYPE_GETNEXT) + goto done; + if (nlen < 4) { + if (req == AGENTX_REQUEST_TYPE_GET) { + agentx_varbind_notfound(vb); + return; + } + } else if (nlen > 4) { + kr = kroute_getaddr(*addr, prefixlen, prio, 1); + if (req == AGENTX_REQUEST_TYPE_GET || kr == NULL) { + agentx_varbind_notfound(vb); + return; + } + } else { + if (ntohl(kr->nexthop.s_addr) < ntohl(*nhaddr)) { + if (req == AGENTX_REQUEST_TYPE_GET) { + agentx_varbind_notfound(vb); + return; + } + } else if (ntohl(kr->nexthop.s_addr) > ntohl(*nhaddr)) { + kr = kroute_getaddr(*addr, prefixlen, prio, 1); + if (req == AGENTX_REQUEST_TYPE_GET || + kr == NULL) { + agentx_varbind_notfound(vb); + return; + } + } + + } + } + done: + agentx_varbind_set_index_integer(vb, inetCidrRouteDestTypeIdx, + INETADDRESSTYPE_IPV4); + agentx_varbind_set_index_nstring(vb, inetCidrRouteDestIdx, + (unsigned char *)&kr->prefix.s_addr, 4); + agentx_varbind_set_index_integer(vb, inetCidrRoutePfxLenIdx, + kr->prefixlen); + agentx_varbind_set_index_oid(vb, inetCidrRoutePolicyIdx, + AGENTX_OID(0, kr->priority)); + agentx_varbind_set_index_integer(vb, inetCidrRouteNextHopTypeIdx, + INETADDRESSTYPE_IPV4); + agentx_varbind_set_index_nstring(vb, inetCidrRouteNextHopIdx, + (unsigned char *)&kr->nexthop.s_addr, 4); + + if (obj == inetCidrRouteIfIndex) + agentx_varbind_integer(vb, kr->if_index); + else if (obj == inetCidrRouteType) { + if (kr->flags & F_REJECT) + type = 2; + else if (kr->flags & F_BLACKHOLE) + type = 5; + else if (kr->flags & F_CONNECTED) + type = 3; + else + type = 4; + agentx_varbind_integer(vb, type); + } else if (obj == inetCidrRouteProto) { + switch (kr->priority) { + case RTP_CONNECTED: + proto = 2; + break; + case RTP_STATIC: + proto = 3; + break; + case RTP_OSPF: + proto = 13; + break; + case RTP_ISIS: + proto = 9; + break; + case RTP_RIP: + proto = 8; + break; + case RTP_BGP: + proto = 14; + break; + default: + if (kr->flags & F_DYNAMIC) + proto = 4; + else + proto = 1; /* not specified */ + break; + } + agentx_varbind_integer(vb, proto); + } else if (obj == inetCidrRouteAge) + agentx_varbind_gauge32(vb, 0); + else if (obj == inetCidrRouteNextHopAS) + agentx_varbind_unsigned32(vb, 0); /* unknown */ + else if (obj == inetCidrRouteMetric1) + agentx_varbind_integer(vb, -1); + else if (obj == inetCidrRouteMetric2) + agentx_varbind_integer(vb, -1); + else if (obj == inetCidrRouteMetric3) + agentx_varbind_integer(vb, -1); + else if (obj == inetCidrRouteMetric4) + agentx_varbind_integer(vb, -1); + else if (obj == inetCidrRouteMetric5) + agentx_varbind_integer(vb, -1); + else if (obj == inetCidrRouteStatus) + agentx_varbind_integer(vb, 1); /* XXX */ + else + fatal("%s: Unexpected object", __func__); +} + +/* + * Defined in UCD-DISKIO-MIB.txt. + */ + +void mib_diskio(struct agentx_varbind *vb); + +void +mib_diskio(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + u_int32_t idx; + int mib[] = { CTL_HW, 0 }; + unsigned int diskcount; + struct diskstats *stats; + size_t len; + + len = sizeof(diskcount); + mib[1] = HW_DISKCOUNT; + if (sysctl(mib, nitems(mib), &diskcount, &len, NULL, 0) == -1) { + log_warn("sysctl"); + agentx_varbind_error(vb); + return; + } + + obj = agentx_varbind_get_object(vb); + req = agentx_varbind_request(vb); + idx = agentx_varbind_get_index_integer(vb, diskIOIdx); + + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + if(idx < 1) { + if (req == AGENTX_REQUEST_TYPE_GET) { + agentx_varbind_notfound(vb); + return; + } + idx = 1; + } else if (idx > diskcount) { + agentx_varbind_notfound(vb); + return; + } + agentx_varbind_set_index_integer(vb, diskIOIdx, idx); + + stats = calloc(diskcount, sizeof(*stats)); + if (stats == NULL) { + log_warn("malloc"); + agentx_varbind_error(vb); + return; + } + /* We know len won't overflow, otherwise calloc() would have failed. */ + len = diskcount * sizeof(*stats); + mib[1] = HW_DISKSTATS; + if (sysctl(mib, nitems(mib), stats, &len, NULL, 0) == -1) { + log_warn("sysctl"); + free(stats); + agentx_varbind_error(vb); + return; + } + + if (obj == diskIOIndex) + agentx_varbind_integer(vb, idx); + else if (obj == diskIODevice) + agentx_varbind_string(vb, stats[idx - 1].ds_name); + else if (obj == diskIONRead) + agentx_varbind_counter32(vb, + (u_int32_t)stats[idx - 1].ds_rbytes); + else if (obj == diskIONWritten) + agentx_varbind_counter32(vb, + (u_int32_t)stats[idx - 1].ds_wbytes); + else if (obj == diskIOReads) + agentx_varbind_counter32(vb, + (u_int32_t)stats[idx - 1].ds_rxfer); + else if (obj == diskIOWrites) + agentx_varbind_counter32(vb, + (u_int32_t)stats[idx - 1].ds_wxfer); + else if (obj == diskIONReadX) + agentx_varbind_counter64(vb, stats[idx - 1].ds_rbytes); + else if (obj == diskIONWrittenX) + agentx_varbind_counter64(vb, stats[idx - 1].ds_wbytes); + else + fatal("%s: Unexpected object", __func__); + free(stats); +} + +/* + * Defined in BRIDGE-MIB.txt (rfc1493) + * + * This MIB is required by some NMS to accept the device because + * the RFC says that mostly any network device has to provide this MIB... :( + */ + +void mib_dot1basetype(struct agentx_varbind *); +void mib_dot1dtable(struct agentx_varbind *); + +void +mib_dot1basetype(struct agentx_varbind *vb) +{ + /* srt (sourceroute + transparent) */ + agentx_varbind_integer(vb, 4); +} + +void +mib_dot1dtable(struct agentx_varbind *vb) +{ + struct agentx_object *obj; + enum agentx_request_type req; + u_int32_t idx = 0; + struct kif *kif; + + obj = agentx_varbind_get_object(vb); + req = agentx_varbind_request(vb); + idx = agentx_varbind_get_index_integer(vb, dot1dBasePortIdx); + + if (req == AGENTX_REQUEST_TYPE_GETNEXT) { + if (idx == INT32_MAX) { + agentx_varbind_notfound(vb); + return; + } + idx++; + } + if ((kif = mib_ifget(idx)) == NULL) { + agentx_varbind_notfound(vb); + return; + } + if (req == AGENTX_REQUEST_TYPE_GET) { + if (idx != kif->if_index) { + agentx_varbind_notfound(vb); + return; + } + } + agentx_varbind_set_index_integer(vb, dot1dBasePortIdx, kif->if_index); + + if (obj == dot1dBasePort) + agentx_varbind_integer(vb, kif->if_index); + else if (obj == dot1dBasePortIfIndex) + agentx_varbind_integer(vb, kif->if_index); + else if (obj == dot1dBasePortCircuit) + agentx_varbind_oid(vb, AGENTX_OID(0, 0)); + else if (obj == dot1dBasePortDelayExceededDiscards) + agentx_varbind_counter32(vb, 0); + else if (obj == dot1dBasePortMtuExceededDiscards) + agentx_varbind_counter32(vb, 0); + else + fatal("%s: Unexpected object", __func__); +} + +/* + * Import all MIBs + */ + +int +main(int argc, char *argv[]) +{ + static struct snmpd conf; + struct agentx *sa; + struct agentx_session *sas; + struct agentx_index *indices[6]; + struct passwd *pw; + struct group *gr; + char agentxsocketdir[PATH_MAX]; + int ch; + int verbose = 0, daemonize = 1, debug = 0; + char *context = NULL; + const char *errstr; + /* HOST-RESOURCES-MIB */ + struct agentx_region *host; + struct agentx_object *hrSystemUptime, *hrSystemDate, *hrMemorySize; + /* IF-MIB */ + struct agentx_region *ifMIB, *interfaces; + /* OPENBSD-PF-MIB */ + struct agentx_region *pfMIBObjects; + /* OPENBSD-SENSOR-MIB */ + struct agentx_region *sensorsMIBObjects; + /* OPENBSD-CARP-MIB */ + struct agentx_region *carpMIBObjects; + /* OPENBSD-MEM-MIB */ + struct agentx_region *memMIBObjects; + /* IP-MIB */ + struct agentx_region *ip; + /* IP-FORWARD-MIB */ + struct agentx_region *ipForward; + /* UCD-DISKIO-MIB */ + struct agentx_region *ucdDiskIOMIB; + /* BRIDGE-MIB */ + struct agentx_region *dot1dBridge; + + snmpd_env = &conf; + log_init(2, LOG_DAEMON); + + agentx_log_fatal = fatalx; + agentx_log_warn = log_warnx; + agentx_log_info = log_info; + agentx_log_debug = log_debug; + + while ((ch = getopt(argc, argv, "C:c:ds:vx:")) != -1) { + switch (ch) { + case 'C': + if (strcmp(optarg, "filter-routes") == 0) { + conf.sc_rtfilter = 1; + } + break; + case 'c': + context = optarg; + break; + case 'd': + daemonize = 0; + debug = 1; + break; + case 's': + if (optarg[0] != '/') + fatalx("agentx socket path must be absolute"); + agentxsocket = optarg; + break; + case 'v': + verbose++; + break; + case 'x': + /* Undocumented flag for snmpd(8) spawning */ + agentxfd = strtonum(optarg, 0, INT_MAX, &errstr); + if (errstr != NULL) + fatalx("invalid agentx fd: %s", errstr); + daemonize = 0; + break; + default: + fatalx("usage: snmpd_metrics [-dv] [-C option] " + "[-c context] [-s master]\n"); + } + } + + if (agentxfd != -1 && !debug) + /* Initialize syslog logging asap for snmpd */ + log_init(0, LOG_DAEMON); + + if ((pw = getpwnam("_snmpd")) == NULL) + fatal("can't find _snmpd user"); + if ((gr = getgrnam("_agentx")) == NULL) + fatal("can't find _agentx group"); + + if (agentxfd != -1 && agentxsocket != NULL) + fatalx("-s and -x are mutually exclusive"); + if (agentxfd == -1 && agentxsocket == NULL) + agentxsocket = AGENTX_MASTER_PATH; + + event_init(); + + if ((sa = agentx(snmp_connect, NULL)) == NULL) + fatal("agentx"); + if ((sas = agentx_session(sa, NULL, 0, "OpenSNMPd metrics", 0)) == NULL) + fatal("agentx_session"); + if ((sac = agentx_context(sas, context)) == NULL) + fatal("agentx_context"); + + /* kr_init requires sac */ + kr_init(); + pf_init(); + timer_init(); + + if (agentxsocket != NULL) { + if (strlcpy(agentxsocketdir, agentxsocket, + sizeof(agentxsocketdir)) >= sizeof(agentxsocketdir)) { + errno = ENAMETOOLONG; + fatal("-s"); + } + if (unveil(dirname(agentxsocketdir), "r") == -1) + fatal("unveil"); + } + + /* Can't pledge: kvm_getfiles */ + if (unveil(NULL, NULL) == -1) + fatal("unveil"); + + if (setgid(gr->gr_gid) == -1) + fatal("setgid"); + if (setuid(pw->pw_uid) == -1) + fatal("setuid"); + + /* HOST-RESOURCES-MIB */ + if ((host = agentx_region(sac, AGENTX_OID(HOST), 0)) == NULL) + fatal("agentx_region"); + + if ((hrSystemUptime = agentx_object(host, AGENTX_OID(HRSYSTEMUPTIME), + NULL, 0, 0, mib_hrsystemuptime)) == NULL || + (hrSystemDate = agentx_object(host, AGENTX_OID(HRSYSTEMDATE), + NULL, 0, 0, mib_hrsystemdate)) == NULL || + (hrSystemProcesses = agentx_object(host, + AGENTX_OID(HRSYSTEMPROCESSES), NULL, 0, 0, + mib_hrsystemprocs)) == NULL || + (hrSystemMaxProcesses = agentx_object(host, + AGENTX_OID(HRSYSTEMMAXPROCESSES), NULL, 0, 0, + mib_hrsystemprocs)) == NULL || + (hrMemorySize = agentx_object(host, AGENTX_OID(HRMEMORYSIZE), + NULL, 0, 0, mib_hrmemory)) == NULL) + fatal("agentx_object"); + + if ((hrStorageIdx = agentx_index_integer_dynamic(host, + AGENTX_OID(HRSTORAGEINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((hrStorageIndex = agentx_object(host, AGENTX_OID(HRSTORAGEINDEX), + &hrStorageIdx, 1, 0, mib_hrstorage)) == NULL || + (hrStorageType = agentx_object(host, AGENTX_OID(HRSTORAGETYPE), + &hrStorageIdx, 1, 0, mib_hrstorage)) == NULL || + (hrStorageDescr = agentx_object(host, AGENTX_OID(HRSTORAGEDESCR), + &hrStorageIdx, 1, 0, mib_hrstorage)) == NULL || + (hrStorageAllocationUnits = agentx_object(host, + AGENTX_OID(HRSTORAGEALLOCATIONUNITS), &hrStorageIdx, 1, 0, + mib_hrstorage)) == NULL || + (hrStorageSize = agentx_object(host, AGENTX_OID(HRSTORAGESIZE), + &hrStorageIdx, 1, 0, mib_hrstorage)) == NULL || + (hrStorageUsed = agentx_object(host, AGENTX_OID(HRSTORAGEUSED), + &hrStorageIdx, 1, 0, mib_hrstorage)) == NULL || + (hrStorageAllocationFailures = agentx_object(host, + AGENTX_OID(HRSTORAGEALLOCATIONFAILURES), &hrStorageIdx, 1, 0, + mib_hrstorage)) == NULL) + fatal("agentx_object"); + + if ((hrDeviceIdx = agentx_index_integer_dynamic(host, + AGENTX_OID(HRDEVICEINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((hrDeviceIndex = agentx_object(host, AGENTX_OID(HRDEVICEINDEX), + &hrDeviceIdx, 1, 0, mib_hrdevice)) == NULL || + (hrDeviceType = agentx_object(host, AGENTX_OID(HRDEVICETYPE), + &hrDeviceIdx, 1, 0, mib_hrdevice)) == NULL | + (hrDeviceDescr = agentx_object(host, AGENTX_OID(HRDEVICEDESCR), + &hrDeviceIdx, 1, 0, mib_hrdevice)) == NULL || + (hrDeviceID = agentx_object(host, AGENTX_OID(HRDEVICEID), + &hrDeviceIdx, 1, 0, mib_hrdevice)) == NULL || + (hrDeviceStatus = agentx_object(host, AGENTX_OID(HRDEVICESTATUS), + &hrDeviceIdx, 1, 0, mib_hrdevice)) == NULL || + (hrDeviceErrors = agentx_object(host, AGENTX_OID(HRDEVICEERRORS), + &hrDeviceIdx, 1, 0, mib_hrdevice)) == NULL) + fatal("agentx_object"); + if ((hrProcessorFrwID = agentx_object(host, AGENTX_OID(HRPROCESSORFRWID), + &hrDeviceIdx, 1, 0, mib_hrprocessor)) == NULL || + (hrProcessorLoad = agentx_object(host, AGENTX_OID(HRPROCESSORLOAD), + &hrDeviceIdx, 1, 0, mib_hrprocessor)) == NULL) + fatal("agentx_object"); + if ((hrSWRunIdx = agentx_index_integer_dynamic(host, + AGENTX_OID(HRSWRUNINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((hrSWRunIndex = agentx_object(host, AGENTX_OID(HRSWRUNINDEX), + &hrSWRunIdx, 1, 0, mib_hrswrun)) == NULL || + (hrSWRunName = agentx_object(host, AGENTX_OID(HRSWRUNNAME), + &hrSWRunIdx, 1, 0, mib_hrswrun)) == NULL || + (hrSWRunID = agentx_object(host, AGENTX_OID(HRSWRUNID), + &hrSWRunIdx, 1, 0, mib_hrswrun)) == NULL || + (hrSWRunPath = agentx_object(host, AGENTX_OID(HRSWRUNPATH), + &hrSWRunIdx, 1, 0, mib_hrswrun)) == NULL || + (hrSWRunParameters = agentx_object(host, + AGENTX_OID(HRSWRUNPARAMETERS), &hrSWRunIdx, 1, 0, + mib_hrswrun)) == NULL || + (hrSWRunType = agentx_object(host, AGENTX_OID(HRSWRUNTYPE), + &hrSWRunIdx, 1, 0, mib_hrswrun)) == NULL || + (hrSWRunStatus = agentx_object(host, AGENTX_OID(HRSWRUNSTATUS), + &hrSWRunIdx, 1, 0, mib_hrswrun)) == NULL) + fatal("agentx_object"); + + /* IF-MIB */ + if ((ifMIB = agentx_region(sac, AGENTX_OID(IFMIB), 0)) == NULL || + (interfaces = agentx_region(sac, + AGENTX_OID(INTERFACES), 0)) == NULL) + fatal("agentx_region"); + + if ((ifIdx = agentx_index_integer_dynamic(interfaces, + AGENTX_OID(IFINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((ifName = agentx_object(ifMIB, AGENTX_OID(IFNAME), + &ifIdx, 1, 0, mib_ifxtable)) == NULL || + (ifInMulticastPkts = agentx_object(ifMIB, + AGENTX_OID(IFINMULTICASTPKTS), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifInBroadcastPkts = agentx_object(ifMIB, + AGENTX_OID(IFINBROADCASTPKTS), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifOutMulticastPkts = agentx_object(ifMIB, + AGENTX_OID(IFOUTMULTICASTPKTS), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifOutBroadcastPkts = agentx_object(ifMIB, + AGENTX_OID(IFOUTBROADCASTPKTS), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifHCInOctets = agentx_object(ifMIB, AGENTX_OID(IFHCINOCTETS), + &ifIdx, 1, 0, mib_ifxtable)) == NULL || + (ifHCInUcastPkts = agentx_object(ifMIB, AGENTX_OID(IFHCINUCASTPKTS), + &ifIdx, 1, 0, mib_ifxtable)) == NULL || + (ifHCInMulticastPkts = agentx_object(ifMIB, + AGENTX_OID(IFHCINMULTICASTPKTS), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifHCInBroadcastPkts = agentx_object(ifMIB, + AGENTX_OID(IFHCINBROADCASTPKTS), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifHCOutOctets = agentx_object(ifMIB, AGENTX_OID(IFHCOUTOCTETS), + &ifIdx, 1, 0, mib_ifxtable)) == NULL || + (ifHCOutUcastPkts = agentx_object(ifMIB, + AGENTX_OID(IFHCOUTUCASTPKTS), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifHCOutMulticastPkts = agentx_object(ifMIB, + AGENTX_OID(IFHCOUTMULTICASTPKTS), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifHCOutBroadcastPkts = agentx_object(ifMIB, + AGENTX_OID(IFHCOUTBROADCASTPKTS), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifLinkUpDownTrapEnable = agentx_object(ifMIB, + AGENTX_OID(IFLINKUPDOWNTRAPENABLE), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifHighSpeed = agentx_object(ifMIB, AGENTX_OID(IFHIGHSPEED), + &ifIdx, 1, 0, mib_ifxtable)) == NULL || + (ifPromiscuousMode = agentx_object(ifMIB, + AGENTX_OID(IFPROMISCUOUSMODE), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifConnectorPresent = agentx_object(ifMIB, + AGENTX_OID(IFCONNECTORPRESENT), &ifIdx, 1, 0, + mib_ifxtable)) == NULL || + (ifAlias = agentx_object(ifMIB, AGENTX_OID(IFALIAS), + &ifIdx, 1, 0, mib_ifxtable)) == NULL || + (ifCounterDiscontinuityTime = agentx_object(ifMIB, + AGENTX_OID(IFCOUNTERDISCONTINUITYTIME), &ifIdx, 1, 0, + mib_ifxtable)) == NULL) + fatal("agentx_object"); + + if ((ifRcvAddressAddress = agentx_index_string_dynamic(ifMIB, + AGENTX_OID(IFRCVADDRESSADDRESS))) == NULL) + fatal("agentx_index_string_dynamic"); + indices[0] = ifIdx; + indices[1] = ifRcvAddressAddress; + if ((ifRcvAddressStatus = agentx_object(ifMIB, + AGENTX_OID(IFRCVADDRESSSTATUS), indices, 2, 0, + mib_ifrcvtable)) == NULL || + (ifRcvAddressType = agentx_object(ifMIB, + AGENTX_OID(IFRCVADDRESSTYPE), indices, 2, 0, + mib_ifrcvtable)) == NULL) + fatal("agentx_object"); + + if ((ifStackLastChange = agentx_object(ifMIB, + AGENTX_OID(IFSTACKLASTCHANGE), NULL, 0, 0, + mib_ifstacklast)) == NULL) + fatal("agentx_object"); + + if ((ifNumber = agentx_object(interfaces, AGENTX_OID(IFNUMBER), + NULL, 0, 0, mib_ifnumber)) == NULL) + fatal("agentx_object"); + + if ((ifIndex = agentx_object(interfaces, AGENTX_OID(IFINDEX), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifDescr = agentx_object(interfaces, AGENTX_OID(IFDESCR), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifType = agentx_object(interfaces, AGENTX_OID(IFTYPE), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifMtu = agentx_object(interfaces, AGENTX_OID(IFMTU), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifSpeed = agentx_object(interfaces, AGENTX_OID(IFSPEED), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifPhysAddress = agentx_object(interfaces, + AGENTX_OID(IFPHYSADDRESS), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifAdminStatus = agentx_object(interfaces, + AGENTX_OID(IFADMINSTATUS), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifOperStatus = agentx_object(interfaces, + AGENTX_OID(IFOPERSTATUS), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifLastChange = agentx_object(interfaces, + AGENTX_OID(IFLASTCHANGE), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifInOctets = agentx_object(interfaces, AGENTX_OID(IFINOCTETS), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifInUcastPkts = agentx_object(interfaces, + AGENTX_OID(IFINUCASTPKTS), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifInNUcastPkts = agentx_object(interfaces, + AGENTX_OID(IFINNUCASTPKTS), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifInDiscards = agentx_object(interfaces, + AGENTX_OID(IFINDISCARDS), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifInErrors = agentx_object(interfaces, AGENTX_OID(IFINERRORS), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifInUnknownProtos = agentx_object(interfaces, + AGENTX_OID(IFINUNKNOWNPROTOS), &ifIdx, 1, 0, + mib_iftable)) == NULL || + (ifOutOctets = agentx_object(interfaces, AGENTX_OID(IFOUTOCTETS), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifOutUcastPkts = agentx_object(interfaces, + AGENTX_OID(IFOUTUCASTPKTS), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifOutNUcastPkts = agentx_object(interfaces, + AGENTX_OID(IFOUTNUCASTPKTS), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifOutDiscards = agentx_object(interfaces, + AGENTX_OID(IFOUTDISCARDS), &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifOutErrors = agentx_object(interfaces, AGENTX_OID(IFOUTERRORS), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifOutQLen = agentx_object(interfaces, AGENTX_OID(IFOUTQLEN), + &ifIdx, 1, 0, mib_iftable)) == NULL || + (ifSpecific = agentx_object(interfaces, AGENTX_OID(IFSPECIFIC), + &ifIdx, 1, 0, mib_iftable)) == NULL) + fatal("agentx_object"); + + /* OPENBSD-PF-MIB */ + if ((pfMIBObjects = agentx_region(sac, + AGENTX_OID(PFMIBOBJECTS), 0)) == NULL) + fatal("agentx_region"); + if ((pfRunning = agentx_object(pfMIBObjects, AGENTX_OID(PFRUNNING), + NULL, 0, 0, mib_pfinfo)) == NULL || + (pfRuntime = agentx_object(pfMIBObjects, AGENTX_OID(PFRUNTIME), + NULL, 0, 0, mib_pfinfo)) == NULL || + (pfDebug = agentx_object(pfMIBObjects, AGENTX_OID(PFDEBUG), + NULL, 0, 0, mib_pfinfo)) == NULL || + (pfHostid = agentx_object(pfMIBObjects, AGENTX_OID(PFHOSTID), + NULL, 0, 0, mib_pfinfo)) == NULL) + fatal("agentx_object"); + + if ((pfCntMatch = agentx_object(pfMIBObjects, AGENTX_OID(PFCNTMATCH), + NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntBadOffset = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTBADOFFSET), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntFragment = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTFRAGMENT), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntShort = agentx_object(pfMIBObjects, AGENTX_OID(PFCNTSHORT), + NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntNormalize = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTNORMALIZE), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntMemory = agentx_object(pfMIBObjects, AGENTX_OID(PFCNTMEMORY), + NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntTimestamp = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTTIMESTAMP), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntCongestion = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTCONGESTION), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntIpOption = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTIPOPTION), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntProtoCksum = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTPROTOCKSUM), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntStateMismatch = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTSTATEMISMATCH), NULL, 0, 0, + mib_pfcounters)) == NULL || + (pfCntStateInsert = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTSTATEINSERT), NULL, 0, 0, + mib_pfcounters)) == NULL || + (pfCntStateLimit = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTSTATELIMIT), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntSrcLimit = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTSRCLIMIT), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntSynproxy = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTSYNPROXY), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntTranslate = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTTRANSLATE), NULL, 0, 0, mib_pfcounters)) == NULL || + (pfCntNoRoute = agentx_object(pfMIBObjects, + AGENTX_OID(PFCNTNOROUTE), NULL, 0, 0, mib_pfcounters)) == NULL) + fatal("agentx_object"); + + if ((pfStateCount = agentx_object(pfMIBObjects, + AGENTX_OID(PFSTATECOUNT), NULL, 0, 0, mib_pfscounters)) == NULL || + (pfStateSearches = agentx_object(pfMIBObjects, + AGENTX_OID(PFSTATESEARCHES), NULL, 0, 0, + mib_pfscounters)) == NULL || + (pfStateInserts = agentx_object(pfMIBObjects, + AGENTX_OID(PFSTATEINSERTS), NULL, 0, 0, mib_pfscounters)) == NULL || + (pfStateRemovals = agentx_object(pfMIBObjects, + AGENTX_OID(PFSTATEREMOVALS), NULL, 0, 0, mib_pfscounters)) == NULL) + fatal("agentx_object"); + + if ((pfLogIfName = agentx_object(pfMIBObjects, AGENTX_OID(PFLOGIFNAME), + NULL, 0, 0, mib_pflogif)) == NULL || + (pfLogIfIpBytesIn = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIPBYTESIN), NULL, 0, 0, mib_pflogif)) == NULL || + (pfLogIfIpBytesOut = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIPBYTESOUT), NULL, 0, 0, mib_pflogif)) == NULL || + (pfLogIfIpPktsInPass = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIPPKTSINPASS), NULL, 0, 0, + mib_pflogif)) == NULL || + (pfLogIfIpPktsInDrop = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIPPKTSINDROP), NULL, 0, 0, + mib_pflogif)) == NULL || + (pfLogIfIpPktsOutPass = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIPPKTSOUTPASS), NULL, 0, 0, + mib_pflogif)) == NULL || + (pfLogIfIpPktsOutDrop = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIPPKTSOUTDROP), NULL, 0, 0, + mib_pflogif)) == NULL || + (pfLogIfIp6BytesIn = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIP6BYTESIN), NULL, 0, 0, mib_pflogif)) == NULL || + (pfLogIfIp6BytesOut = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIP6BYTESOUT), NULL, 0, 0, mib_pflogif)) == NULL || + (pfLogIfIp6PktsInPass = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIP6PKTSINPASS), NULL, 0, 0, + mib_pflogif)) == NULL || + (pfLogIfIp6PktsInDrop = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIP6PKTSINDROP), NULL, 0, 0, + mib_pflogif)) == NULL || + (pfLogIfIp6PktsOutPass = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIP6PKTSOUTPASS), NULL, 0, 0, + mib_pflogif)) == NULL || + (pfLogIfIp6PktsOutDrop = agentx_object(pfMIBObjects, + AGENTX_OID(PFLOGIFIP6PKTSOUTDROP), NULL, 0, 0, + mib_pflogif)) == NULL) + fatal("agentx_object"); + + if ((pfSrcTrackCount = agentx_object(pfMIBObjects, + AGENTX_OID(PFSRCTRACKCOUNT), NULL, 0, 0, mib_pfsrctrack)) == NULL || + (pfSrcTrackSearches = agentx_object(pfMIBObjects, + AGENTX_OID(PFSRCTRACKSEARCHES), NULL, 0, 0, + mib_pfsrctrack)) == NULL || + (pfSrcTrackInserts = agentx_object(pfMIBObjects, + AGENTX_OID(PFSRCTRACKINSERTS), NULL, 0, 0, + mib_pfsrctrack)) == NULL || + (pfSrcTrackRemovals = agentx_object(pfMIBObjects, + AGENTX_OID(PFSRCTRACKREMOVALS), NULL, 0, 0, + mib_pfsrctrack)) == NULL) + fatal("agentx_object"); + + if ((pfLimitStates = agentx_object(pfMIBObjects, + AGENTX_OID(PFLIMITSTATES), NULL, 0, 0, mib_pflimits)) == NULL || + (pfLimitSourceNodes = agentx_object(pfMIBObjects, + AGENTX_OID(PFLIMITSOURCENODES), NULL, 0, 0, + mib_pflimits)) == NULL || + (pfLimitFragments = agentx_object(pfMIBObjects, + AGENTX_OID(PFLIMITFRAGMENTS), NULL, 0, 0, mib_pflimits)) == NULL || + (pfLimitMaxTables = agentx_object(pfMIBObjects, + AGENTX_OID(PFLIMITMAXTABLES), NULL, 0, 0, mib_pflimits)) == NULL || + (pfLimitMaxTableEntries = agentx_object(pfMIBObjects, + AGENTX_OID(PFLIMITMAXTABLEENTRIES), NULL, 0, 0, + mib_pflimits)) == NULL) + fatal("agentx_object"); + + if ((pfTimeoutTcpFirst = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTTCPFIRST), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutTcpOpening = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTTCPOPENING), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutTcpEstablished = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTTCPESTABLISHED), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutTcpClosing = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTTCPCLOSING), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutTcpFinWait = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTTCPFINWAIT), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutTcpClosed = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTTCPCLOSED), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutUdpFirst = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTUDPFIRST), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutUdpSingle = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTUDPSINGLE), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutUdpMultiple = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTUDPMULTIPLE), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutIcmpFirst = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTICMPFIRST), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutIcmpError = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTICMPERROR), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutOtherFirst = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTOTHERFIRST), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutOtherSingle = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTOTHERSINGLE), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutOtherMultiple = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTOTHERMULTIPLE), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutFragment = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTFRAGMENT), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutInterval = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTINTERVAL), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutAdaptiveStart = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTADAPTIVESTART), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutAdaptiveEnd = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTADAPTIVEEND), NULL, 0, 0, + mib_pftimeouts)) == NULL || + (pfTimeoutSrcTrack = agentx_object(pfMIBObjects, + AGENTX_OID(PFTIMEOUTSRCTRACK), NULL, 0, 0, + mib_pftimeouts)) == NULL) + fatal("agentx_object"); + + if ((pfIfNumber = agentx_object(pfMIBObjects, AGENTX_OID(PFIFNUMBER), + NULL, 0, 0, mib_pfifnum)) == NULL) + fatal("agentx_object"); + if ((pfIfIdx = agentx_index_integer_dynamic(pfMIBObjects, + AGENTX_OID(PFIFINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((pfIfIndex = agentx_object(pfMIBObjects, AGENTX_OID(PFIFINDEX), + &pfIfIdx, 1, 0, mib_pfiftable)) == NULL || + (pfIfDescr = agentx_object(pfMIBObjects, AGENTX_OID(PFIFDESCR), + &pfIfIdx, 1, 0, mib_pfiftable)) == NULL || + (pfIfType = agentx_object(pfMIBObjects, AGENTX_OID(PFIFTYPE), + &pfIfIdx, 1, 0, mib_pfiftable)) == NULL || + (pfIfRefs = agentx_object(pfMIBObjects, AGENTX_OID(PFIFREFS), + &pfIfIdx, 1, 0, mib_pfiftable)) == NULL || + (pfIfRules = agentx_object(pfMIBObjects, AGENTX_OID(PFIFRULES), + &pfIfIdx, 1, 0, mib_pfiftable)) == NULL || + (pfIfIn4PassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFIN4PASSPKTS), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfIn4PassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFIN4PASSBYTES), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfIn4BlockPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFIN4BLOCKPKTS), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfIn4BlockBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFIN4BLOCKBYTES), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfOut4PassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFOUT4PASSPKTS), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfOut4PassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFOUT4PASSBYTES), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfOut4BlockPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFOUT4BLOCKPKTS), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfOut4BlockBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFOUT4BLOCKBYTES), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfIn6PassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFIN6PASSPKTS), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfIn6PassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFIN6PASSBYTES), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfIn6BlockPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFIN6BLOCKPKTS), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfIn6BlockBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFIN6BLOCKBYTES), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfOut6PassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFOUT6PASSPKTS), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfOut6PassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFOUT6PASSBYTES), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfOut6BlockPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFOUT6BLOCKPKTS), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL || + (pfIfOut6BlockBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFIFOUT6BLOCKBYTES), &pfIfIdx, 1, 0, + mib_pfiftable)) == NULL) + fatal("agentx_object"); + + if ((pfTblNumber = agentx_object(pfMIBObjects, AGENTX_OID(PFTBLNUMBER), + NULL, 0, 0, mib_pftablenum)) == NULL) + fatal("agentx_object"); + if ((pfTblIdx = agentx_index_integer_dynamic(pfMIBObjects, + AGENTX_OID(PFTBLINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((pfTblIndex = agentx_object(pfMIBObjects, AGENTX_OID(PFTBLINDEX), + &pfTblIdx, 1, 0, mib_pftables)) == NULL || + (pfTblName = agentx_object(pfMIBObjects, AGENTX_OID(PFTBLNAME), + &pfTblIdx, 1, 0, mib_pftables)) == NULL || + (pfTblAddresses = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRESSES), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblAnchorRefs = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLANCHORREFS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblRuleRefs = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLRULEREFS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblEvalsMatch = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLEVALSMATCH), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblEvalsNoMatch = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLEVALSNOMATCH), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblInPassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLINPASSPKTS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblInPassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLINPASSBYTES), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblInBlockPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLINBLOCKPKTS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblInBlockBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLINBLOCKBYTES), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblInXPassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLINXPASSPKTS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblInXPassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLINXPASSBYTES), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblOutPassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLOUTPASSPKTS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblOutPassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLOUTPASSBYTES), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblOutBlockPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLOUTBLOCKPKTS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblOutBlockBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLOUTBLOCKBYTES), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblOutXPassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLOUTXPASSPKTS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblOutXPassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLOUTXPASSBYTES), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblStatsCleared = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLSTATSCLEARED), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblInMatchPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLINMATCHPKTS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblInMatchBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLINMATCHBYTES), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblOutMatchPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLOUTMATCHPKTS), &pfTblIdx, 1, 0, + mib_pftables)) == NULL || + (pfTblOutMatchBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLOUTMATCHBYTES), &pfTblIdx, 1, 0, + mib_pftables)) == NULL) + fatal("agentx_object"); + + if ((pfTblAddrTblIdx = agentx_index_integer_dynamic(pfMIBObjects, + AGENTX_OID(PFTBLADDRTBLINDEX))) == NULL || + (pfTblAddrNetIdx = agentx_index_ipaddress_dynamic(pfMIBObjects, + AGENTX_OID(PFTBLADDRNET))) == NULL || + (pfTblAddrMaskIdx = agentx_index_integer_dynamic(pfMIBObjects, + AGENTX_OID(PFTBLADDRMASK))) == NULL) + fatal("agentx_index_integer_dynamic"); + indices[0] = pfTblAddrTblIdx; + indices[1] = pfTblAddrNetIdx; + indices[2] = pfTblAddrMaskIdx; + if ((pfTblAddrTblIndex = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRTBLINDEX), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrNet = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRNET), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrMask = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRMASK), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrCleared = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRCLEARED), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrInBlockPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRINBLOCKPKTS), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrInBlockBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRINBLOCKBYTES), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrInPassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRINPASSPKTS), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrInPassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRINPASSBYTES), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrOutBlockPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDROUTBLOCKPKTS), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrOutBlockBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDROUTBLOCKBYTES), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrOutPassPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDROUTPASSPKTS), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrOutPassBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDROUTPASSBYTES), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrInMatchPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRINMATCHPKTS), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrInMatchBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDRINMATCHBYTES), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrOutMatchPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDROUTMATCHPKTS), indices, 3, 0, + mib_pftableaddrs)) == NULL || + (pfTblAddrOutMatchBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFTBLADDROUTMATCHBYTES), indices, 3, 0, + mib_pftableaddrs)) == NULL) + fatal("agentx_object"); + + if ((pfLabelNumber = agentx_object(pfMIBObjects, + AGENTX_OID(PFLABELNUMBER), NULL, 0, 0, mib_pflabelnum)) == NULL) + fatal("agentx_object"); + if ((pfLabelIdx = agentx_index_integer_dynamic(pfMIBObjects, + AGENTX_OID(PFLABELINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((pfLabelIndex = agentx_object(pfMIBObjects, + AGENTX_OID(PFLABELINDEX), &pfLabelIdx, 1, 0, + mib_pflabels)) == NULL || + (pfLabelName = agentx_object(pfMIBObjects, AGENTX_OID(PFLABELNAME), + &pfLabelIdx, 1, 0, mib_pflabels)) == NULL || + (pfLabelEvals = agentx_object(pfMIBObjects, + AGENTX_OID(PFLABELEVALS), &pfLabelIdx, 1, 0, + mib_pflabels)) == NULL || + (pfLabelPkts = agentx_object(pfMIBObjects, AGENTX_OID(PFLABELPKTS), + &pfLabelIdx, 1, 0, mib_pflabels)) == NULL || + (pfLabelBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFLABELBYTES), &pfLabelIdx, 1, 0, + mib_pflabels)) == NULL || + (pfLabelInPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFLABELINPKTS), &pfLabelIdx, 1, 0, + mib_pflabels)) == NULL || + (pfLabelInBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFLABELINBYTES), &pfLabelIdx, 1, 0, + mib_pflabels)) == NULL || + (pfLabelOutPkts = agentx_object(pfMIBObjects, + AGENTX_OID(PFLABELOUTPKTS), &pfLabelIdx, 1, 0, + mib_pflabels)) == NULL || + (pfLabelOutBytes = agentx_object(pfMIBObjects, + AGENTX_OID(PFLABELOUTBYTES), &pfLabelIdx, 1, 0, + mib_pflabels)) == NULL || + (pfLabelTotalStates = agentx_object(pfMIBObjects, + AGENTX_OID(PFLABELTOTALSTATES), &pfLabelIdx, 1, 0, + mib_pflabels)) == NULL) + fatal("agentx_object"); + + if ((pfsyncIpPktsRecv = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCIPPKTSRECV), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncIp6PktsRecv = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCIP6PKTSRECV), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktDiscardsForBadInterface = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTDISCARDSFORBADINTERFACE), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktDiscardsForBadTtl = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTDISCARDSFORBADTTL), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktShorterThanHeader = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTSHORTERTHANHEADER), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktDiscardsForBadVersion = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTDISCARDSFORBADVERSION), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktDiscardsForBadAction = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTDISCARDSFORBADACTION), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktDiscardsForBadLength = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTDISCARDSFORBADLENGTH), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktDiscardsForBadAuth = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTDISCARDSFORBADAUTH), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktDiscardsForStaleState = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTDISCARDSFORSTALESTATE), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktDiscardsForBadValues = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTDISCARDSFORBADVALUES), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncPktDiscardsForBadState = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCPKTDISCARDSFORBADSTATE), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncIpPktsSent = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCIPPKTSSENT), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncIp6PktsSent = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCIP6PKTSSENT), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncNoMemory = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCNOMEMORY), NULL, 0, 0, + mib_pfsyncstats)) == NULL || + (pfsyncOutputErrors = agentx_object(pfMIBObjects, + AGENTX_OID(PFSYNCOUTPUTERRORS), NULL, 0, 0, + mib_pfsyncstats)) == NULL) + fatal("agentx_object"); + + if ((sensorsMIBObjects = agentx_region(sac, + AGENTX_OID(SENSORSMIBOBJECTS), 0)) == NULL) + fatal("agentx_region"); + if ((sensorNumber = agentx_object(sensorsMIBObjects, + AGENTX_OID(SENSORNUMBER), NULL, 0, 0, mib_sensornum)) == NULL) + fatal("agentx_object"); + if ((sensorIdx = agentx_index_integer_dynamic(sensorsMIBObjects, + AGENTX_OID(SENSORINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((sensorIndex = agentx_object(sensorsMIBObjects, + AGENTX_OID(SENSORINDEX), &sensorIdx, 1, 0, mib_sensors)) == NULL || + (sensorDescr = agentx_object(sensorsMIBObjects, + AGENTX_OID(SENSORDESCR), &sensorIdx, 1, 0, mib_sensors)) == NULL || + (sensorType = agentx_object(sensorsMIBObjects, + AGENTX_OID(SENSORTYPE), &sensorIdx, 1, 0, mib_sensors)) == NULL || + (sensorDevice = agentx_object(sensorsMIBObjects, + AGENTX_OID(SENSORDEVICE), &sensorIdx, 1, 0, mib_sensors)) == NULL || + (sensorValue = agentx_object(sensorsMIBObjects, + AGENTX_OID(SENSORVALUE), &sensorIdx, 1, 0, mib_sensors)) == NULL || + (sensorUnits = agentx_object(sensorsMIBObjects, + AGENTX_OID(SENSORUNITS), &sensorIdx, 1, 0, mib_sensors)) == NULL || + (sensorStatus = agentx_object(sensorsMIBObjects, + AGENTX_OID(SENSORSTATUS), &sensorIdx, 1, 0, mib_sensors)) == NULL) + fatal("agentx_object"); + + if ((carpMIBObjects = agentx_region(sac, + AGENTX_OID(CARPMIBOBJECTS), 0)) == NULL) + fatal("agentx_region"); + if ((carpAllow = agentx_object(carpMIBObjects, AGENTX_OID(CARPALLOW), + NULL, 0, 0, mib_carpsysctl)) == NULL || + (carpPreempt = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPREEMPT), NULL, 0, 0, mib_carpsysctl)) == NULL || + (carpLog = agentx_object(carpMIBObjects, AGENTX_OID(CARPLOG), + NULL, 0, 0, mib_carpsysctl)) == NULL) + fatal("agentx_object"); + + if ((carpIfNumber = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIFNUMBER), NULL, 0, 0, mib_carpifnum)) == NULL) + fatal("agentx_object"); + if ((carpIfIdx = agentx_index_integer_dynamic(carpMIBObjects, + AGENTX_OID(CARPIFINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((carpIfIndex = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIFINDEX), &carpIfIdx, 1, 0, + mib_carpiftable)) == NULL || + (carpIfDescr = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIFDESCR), &carpIfIdx, 1, 0, + mib_carpiftable)) == NULL || + (carpIfVhid = agentx_object(carpMIBObjects, AGENTX_OID(CARPIFVHID), + &carpIfIdx, 1, 0, mib_carpiftable)) == NULL || + (carpIfDev = agentx_object(carpMIBObjects, AGENTX_OID(CARPIFDEV), + &carpIfIdx, 1, 0, mib_carpiftable)) == NULL || + (carpIfAdvbase = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIFADVBASE), &carpIfIdx, 1, 0, + mib_carpiftable)) == NULL || + (carpIfAdvskew = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIFADVSKEW), &carpIfIdx, 1, 0, + mib_carpiftable)) == NULL || + (carpIfState = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIFSTATE), &carpIfIdx, 1, 0, + mib_carpiftable)) == NULL) + fatal("agentx_object"); + + if ((carpGroupIdx = agentx_index_integer_dynamic(carpMIBObjects, + AGENTX_OID(CARPGROUPINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((carpGroupName = agentx_object(carpMIBObjects, + AGENTX_OID(CARPGROUPNAME), &carpGroupIdx, 1, 0, + mib_carpgrouptable)) == NULL || + (carpGroupDemote = agentx_object(carpMIBObjects, + AGENTX_OID(CARPGROUPDEMOTE), &carpGroupIdx, 1, 0, + mib_carpgrouptable)) == NULL) + fatal("agentx_object"); + + if ((carpIpPktsRecv = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIPPKTSRECV), NULL, 0, 0, mib_carpstats)) == NULL || + (carpIp6PktsRecv = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIP6PKTSRECV), NULL, 0, 0, mib_carpstats)) == NULL || + (carpPktDiscardsForBadInterface = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPKTDISCARDSFORBADINTERFACE), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpPktDiscardsForWrongTtl = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPKTDISCARDSFORWRONGTTL), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpPktShorterThanHeader = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPKTSHORTERTHANHEADER), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpPktDiscardsForBadChecksum = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPKTDISCARDSFORBADCHECKSUM), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpPktDiscardsForBadVersion = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPKTDISCARDSFORBADVERSION), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpPktDiscardsForTooShort = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPKTDISCARDSFORTOOSHORT), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpPktDiscardsForBadAuth = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPKTDISCARDSFORBADAUTH), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpPktDiscardsForBadVhid = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPKTDISCARDSFORBADVHID), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpPktDiscardsForBadAddressList = agentx_object(carpMIBObjects, + AGENTX_OID(CARPPKTDISCARDSFORBADADDRESSLIST), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpIpPktsSent = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIPPKTSSENT), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpIp6PktsSent = agentx_object(carpMIBObjects, + AGENTX_OID(CARPIP6PKTSSENT), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpNoMemory = agentx_object(carpMIBObjects, + AGENTX_OID(CARPNOMEMORY), NULL, 0, 0, + mib_carpstats)) == NULL || + (carpTransitionsToMaster = agentx_object(carpMIBObjects, + AGENTX_OID(CARPTRANSITIONSTOMASTER), NULL, 0, 0, + mib_carpstats)) == NULL) + fatal("agentx_object"); + + /* OPENBSD-MEM-MIB */ + if ((memMIBObjects = agentx_region(sac, + AGENTX_OID(MEMMIBOBJECTS), 0)) == NULL) + fatal("agentx_region"); + if ((memMIBVersion = agentx_object(memMIBObjects, + AGENTX_OID(MEMMIBVERSION), NULL, 0, 0, mib_memversion)) == NULL) + fatal("agentx_object"); + if ((memIfName = agentx_object(memMIBObjects, AGENTX_OID(MEMIFNAME), + &ifIdx, 1, 0, mib_memiftable)) == NULL || + (memIfLiveLocks = agentx_object(memMIBObjects, + AGENTX_OID(MEMIFLIVELOCKS), &ifIdx, 1, 0, + mib_memiftable)) == NULL) + fatal("agentx_object"); + + /* IP-MIB */ + if ((ip = agentx_region(sac, AGENTX_OID(IP), 0)) == NULL) + fatal("agentx_region"); + if ((ipForwarding = agentx_object(ip, AGENTX_OID(IPFORWARDING), + NULL, 0, 0, mib_ipforwarding)) == NULL || + (ipDefaultTTL = agentx_object(ip, AGENTX_OID(IPDEFAULTTTL), + NULL, 0, 0, mib_ipdefaultttl)) == NULL || + (ipInReceives = agentx_object(ip, AGENTX_OID(IPINRECEIVES), + NULL, 0, 0, mib_ipstat)) == NULL || + (ipInHdrErrors = agentx_object(ip, AGENTX_OID(IPINHDRERRORS), + NULL, 0, 0, mib_ipinhdrerrs)) == NULL || + (ipInAddrErrors = agentx_object(ip, AGENTX_OID(IPINADDRERRORS), + NULL, 0, 0, mib_ipinaddrerrs)) == NULL || + (ipForwDatagrams = agentx_object(ip, AGENTX_OID(IPFORWDATAGRAMS), + NULL, 0, 0, mib_ipforwdgrams)) == NULL || + (ipInUnknownProtos = agentx_object(ip, + AGENTX_OID(IPINUNKNOWNPROTOS), NULL, 0, 0, mib_ipstat)) == NULL || + (ipInDelivers = agentx_object(ip, AGENTX_OID(IPINDELIVERS), + NULL, 0, 0, mib_ipstat)) == NULL || + (ipOutRequests = agentx_object(ip, AGENTX_OID(IPOUTREQUESTS), + NULL, 0, 0, mib_ipstat)) == NULL || + (ipOutDiscards = agentx_object(ip, AGENTX_OID(IPOUTDISCARDS), + NULL, 0, 0, mib_ipstat)) == NULL || + (ipOutNoRoutes = agentx_object(ip, AGENTX_OID(IPOUTNOROUTES), + NULL, 0, 0, mib_ipstat)) == NULL || + (ipReasmTimeout = agentx_object(ip, AGENTX_OID(IPREASMTIMEOUT), + NULL, 0, 0, mib_ipreasmtimeout)) == NULL || + (ipReasmReqds = agentx_object(ip, AGENTX_OID(IPREASMREQDS), + NULL, 0, 0, mib_ipstat)) == NULL || + (ipReasmOKs = agentx_object(ip, AGENTX_OID(IPREASMOKS), + NULL, 0, 0, mib_ipstat)) == NULL || + (ipReasmFails = agentx_object(ip, AGENTX_OID(IPREASMFAILS), + NULL, 0, 0, mib_ipreasmfails)) == NULL || + (ipFragOKs = agentx_object(ip, AGENTX_OID(IPFRAGOKS), + NULL, 0, 0, mib_ipstat)) == NULL || + (ipFragFails = agentx_object(ip, AGENTX_OID(IPFRAGFAILS), + NULL, 0, 0, mib_ipfragfails)) == NULL || + (ipFragCreates = agentx_object(ip, AGENTX_OID(IPFRAGCREATES), + NULL, 0, 0, mib_ipstat)) == NULL) + fatal("agentx_object"); + + if ((ipAdEntAddrIdx = agentx_index_ipaddress_dynamic(ip, + AGENTX_OID(IPADENTADDR))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((ipAdEntAddr = agentx_object(ip, AGENTX_OID(IPADENTADDR), + &ipAdEntAddrIdx, 1, 0, mib_ipaddr)) == NULL || + (ipAdEntIfIndex = agentx_object(ip, AGENTX_OID(IPADENTIFINDEX), + &ipAdEntAddrIdx, 1, 0, mib_ipaddr)) == NULL || + (ipAdEntNetMask = agentx_object(ip, AGENTX_OID(IPADENTNETMASK), + &ipAdEntAddrIdx, 1, 0, mib_ipaddr)) == NULL || + (ipAdEntBcastAddr = agentx_object(ip, AGENTX_OID(IPADENTBCASTADDR), + &ipAdEntAddrIdx, 1, 0, mib_ipaddr)) == NULL || + (ipAdEntReasmMaxSize = agentx_object(ip, + AGENTX_OID(IPADENTREASMMAXSIZE), &ipAdEntAddrIdx, 1, 0, + mib_ipaddr)) == NULL) + fatal("agentx_object"); + + if ((ipNetToMediaIfIdx = agentx_index_integer_dynamic(ip, + AGENTX_OID(IPNETTOMEDIAIFINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((ipNetToMediaNetAddressIdx = agentx_index_ipaddress_dynamic(ip, + AGENTX_OID(IPNETTOMEDIANETADDRESS))) == NULL) + fatal("agentx_index_string_dynamic"); + indices[0] = ipNetToMediaIfIdx; + indices[1] = ipNetToMediaNetAddressIdx; + if ((ipNetToMediaIfIndex = agentx_object(ip, + AGENTX_OID(IPNETTOMEDIAIFINDEX), indices, 2, 0, + mib_physaddr)) == NULL || + (ipNetToMediaPhysAddress = agentx_object(ip, + AGENTX_OID(IPNETTOMEDIAPHYSADDRESS), indices, 2, 0, + mib_physaddr)) == NULL || + (ipNetToMediaNetAddress = agentx_object(ip, + AGENTX_OID(IPNETTOMEDIANETADDRESS), indices, 2, 0, + mib_physaddr)) == NULL || + (ipNetToMediaType = agentx_object(ip, AGENTX_OID(IPNETTOMEDIATYPE), + indices, 2, 0, mib_physaddr)) == NULL) + fatal("agentx_object"); + + if ((ipForward = agentx_region(sac, AGENTX_OID(IPFORWARD), 0)) == NULL) + fatal("agentx_region"); + if ((inetCidrRouteNumber = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTENUMBER), NULL, 0, 0, + mib_ipfnroutes)) == NULL) + fatal("agentx_object"); + if ((inetCidrRouteDestTypeIdx = agentx_index_integer_dynamic(ipForward, + AGENTX_OID(INETCIDRROUTEDESTTYPE))) == NULL || + (inetCidrRouteDestIdx = agentx_index_string_dynamic(ipForward, + AGENTX_OID(INETCIDRROUTEDEST))) == NULL || + (inetCidrRoutePfxLenIdx = agentx_index_integer_dynamic(ipForward, + AGENTX_OID(INETCIDRROUTEPFXLEN))) == NULL || + (inetCidrRoutePolicyIdx = agentx_index_oid_dynamic(ipForward, + AGENTX_OID(INETCIDRROUTEPOLICY))) == NULL || + (inetCidrRouteNextHopTypeIdx = agentx_index_integer_dynamic( + ipForward, AGENTX_OID(INETCIDRROUTENEXTHOPTYPE))) == NULL || + (inetCidrRouteNextHopIdx = agentx_index_string_dynamic(ipForward, + AGENTX_OID(INETCIDRROUTENEXTHOP))) == NULL) + fatal("agentx_index_*_dynamic"); + indices[0] = inetCidrRouteDestTypeIdx; + indices[1] = inetCidrRouteDestIdx; + indices[2] = inetCidrRoutePfxLenIdx; + indices[3] = inetCidrRoutePolicyIdx; + indices[4] = inetCidrRouteNextHopTypeIdx; + indices[5] = inetCidrRouteNextHopIdx; + if ((inetCidrRouteIfIndex = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTEIFINDEX), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteType = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTETYPE), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteProto = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTEPROTO), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteAge = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTEAGE), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteNextHopAS = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTENEXTHOPAS), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteMetric1 = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTEMETRIC1), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteMetric2 = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTEMETRIC2), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteMetric3 = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTEMETRIC3), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteMetric4 = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTEMETRIC4), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteMetric5 = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTEMETRIC5), indices, 6, 0, + mib_ipfroute)) == NULL || + (inetCidrRouteStatus = agentx_object(ipForward, + AGENTX_OID(INETCIDRROUTESTATUS), indices, 6, 0, + mib_ipfroute)) == NULL) + fatal("agentx_object"); + + /* UCD-DISKIO-MIB */ + if ((ucdDiskIOMIB = agentx_region(sac, AGENTX_OID(UCDDISKIOMIB), + 0)) == NULL) + fatal("agentx_region"); + if ((diskIOIdx = agentx_index_integer_dynamic(ucdDiskIOMIB, + AGENTX_OID(DISKIOINDEX))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((diskIOIndex = agentx_object(ucdDiskIOMIB, AGENTX_OID(DISKIOINDEX), + &diskIOIdx, 1, 0, mib_diskio)) == NULL || + (diskIODevice = agentx_object(ucdDiskIOMIB, + AGENTX_OID(DISKIODEVICE), &diskIOIdx, 1, 0, mib_diskio)) == NULL || + (diskIONRead = agentx_object(ucdDiskIOMIB, AGENTX_OID(DISKIONREAD), + &diskIOIdx, 1, 0, mib_diskio)) == NULL || + (diskIONWritten = agentx_object(ucdDiskIOMIB, + AGENTX_OID(DISKIONWRITTEN), &diskIOIdx, 1, 0, + mib_diskio)) == NULL || + (diskIOReads = agentx_object(ucdDiskIOMIB, + AGENTX_OID(DISKIOREADS), &diskIOIdx, 1, 0, mib_diskio)) == NULL || + (diskIOWrites = agentx_object(ucdDiskIOMIB, + AGENTX_OID(DISKIOWRITES), &diskIOIdx, 1, 0, mib_diskio)) == NULL || + (diskIONReadX = agentx_object(ucdDiskIOMIB, + AGENTX_OID(DISKIONREADX), &diskIOIdx, 1, 0, mib_diskio)) == NULL || + (diskIONWrittenX = agentx_object(ucdDiskIOMIB, + AGENTX_OID(DISKIONWRITTENX), &diskIOIdx, 1, 0, + mib_diskio)) == NULL) + fatal("agentx_object"); + + if ((dot1dBridge = agentx_region(sac, AGENTX_OID(DOT1DBRIDGE), + 0)) == NULL) + fatal("agentx_region"); + if ((dot1dBaseNumPorts = agentx_object(dot1dBridge, + AGENTX_OID(DOT1DBASENUMPORTS), NULL, 0, 0, mib_ifnumber)) == NULL || + (dot1dBaseType = agentx_object(dot1dBridge, + AGENTX_OID(DOT1DBASETYPE), NULL, 0, 0, mib_dot1basetype)) == NULL) + fatal("agentx_object"); + + if ((dot1dBasePortIdx = agentx_index_integer_dynamic(dot1dBridge, + AGENTX_OID(DOT1DBASEPORT))) == NULL) + fatal("agentx_index_integer_dynamic"); + if ((dot1dBasePort = agentx_object(dot1dBridge, + AGENTX_OID(DOT1DBASEPORT), &dot1dBasePortIdx, 1, 0, + mib_dot1dtable)) == NULL || + (dot1dBasePortIfIndex = agentx_object(dot1dBridge, + AGENTX_OID(DOT1DBASEPORTIFINDEX), &dot1dBasePortIdx, 1, 0, + mib_dot1dtable)) == NULL || + (dot1dBasePortCircuit = agentx_object(dot1dBridge, + AGENTX_OID(DOT1DBASEPORTCIRCUIT), &dot1dBasePortIdx, 1, 0, + mib_dot1dtable)) == NULL || + (dot1dBasePortDelayExceededDiscards = agentx_object(dot1dBridge, + AGENTX_OID(DOT1DBASEPORTDELAYEXCEEDEDDISCARDS), &dot1dBasePortIdx, + 1, 0, mib_dot1dtable)) == NULL || + (dot1dBasePortMtuExceededDiscards = agentx_object(dot1dBridge, + AGENTX_OID(DOT1DBASEPORTMTUEXCEEDEDDISCARDS), &dot1dBasePortIdx, + 1, 0, mib_dot1dtable)) == NULL) + fatal("agentx_object"); + + if (daemonize) { + log_init(0, LOG_DAEMON); + daemon(0, 0); + } + log_setverbose(verbose); + + event_dispatch(); +} + +void +snmp_connect(struct agentx *sa, void *cookie, int close) +{ + static int init = 0; + + if (close) { + event_del(&connev); + return; + } + + if (agentxfd != -1) { + /* Exit if snmpd(8) leaves */ + if (init) + exit(0); + agentx_connect(sa, agentxfd); + event_set(&connev, agentxfd, EV_READ | EV_PERSIST, + snmp_read, sa); + event_add(&connev, NULL); + init = 1; + } else + snmp_tryconnect(-1, 0, sa); +} + +void +snmp_tryconnect(int fd, short event, void *cookie) +{ + struct timeval timeout = {3, 0}; + struct agentx *sa = cookie; + struct sockaddr_un sun; + + sun.sun_len = sizeof(sun); + sun.sun_family = AF_UNIX; + strlcpy(sun.sun_path, AGENTX_MASTER_PATH, sizeof(sun.sun_path)); + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1 || + connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { + if (fd != -1) + close(fd); + log_warn("Failed to connect to snmpd"); + evtimer_set(&connev, snmp_tryconnect, sa); + evtimer_add(&connev, &timeout); + return; + } + + event_set(&connev, fd, EV_READ | EV_PERSIST, snmp_read, sa); + event_add(&connev, NULL); + + agentx_connect(sa, fd); +} + +void +snmp_read(int fd, short event, void *cookie) +{ + struct agentx *sa = cookie; + + agentx_read(sa); +} + +u_long +smi_getticks(void) +{ + return agentx_context_uptime(sac); +} diff --git a/libexec/snmpd/snmpd_metrics/mib.h b/libexec/snmpd/snmpd_metrics/mib.h new file mode 100644 index 00000000000..97995472164 --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/mib.h @@ -0,0 +1,896 @@ +/* $OpenBSD: mib.h,v 1.1.1.1 2022/09/01 14:20:34 martijn Exp $ */ + +/* + * Copyright (c) 2022 Martijn van Duren + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +/* HOST-RESOURCES-MIB */ +#define HOST AGENTX_MIB2, 25 +#define HRSYSTEM HOST, 1 +#define HRSTORAGE HOST, 2 +#define HRDEVICE HOST, 3 +#define HRSWRUN HOST, 4 +#define HRSWRUNPERF HOST, 5 +#define HRSWINSTALLED HOST, 6 +#define HRMIBADMININFO HOST, 7 +#define HRSYSTEMUPTIME HRSYSTEM, 1 +#define HRSYSTEMDATE HRSYSTEM, 2 +#define HRSYSTEMINITIALLOADDEVICE HRSYSTEM, 3 +#define HRSYSTEMINITIALLOADPARAMETERS HRSYSTEM, 4 +#define HRSYSTEMNUMUSERS HRSYSTEM, 5 +#define HRSYSTEMPROCESSES HRSYSTEM, 6 +#define HRSYSTEMMAXPROCESSES HRSYSTEM, 7 +#define HRSTORAGETYPES HRSTORAGE, 1 +#define HRMEMORYSIZE HRSTORAGE, 2 +#define HRSTORAGETABLE HRSTORAGE, 3 +#define HRSTORAGEENTRY HRSTORAGETABLE, 1 +#define HRSTORAGEINDEX HRSTORAGEENTRY, 1 +#define HRSTORAGETYPE HRSTORAGEENTRY, 2 +#define HRSTORAGEDESCR HRSTORAGEENTRY, 3 +#define HRSTORAGEALLOCATIONUNITS HRSTORAGEENTRY, 4 +#define HRSTORAGESIZE HRSTORAGEENTRY, 5 +#define HRSTORAGEUSED HRSTORAGEENTRY, 6 +#define HRSTORAGEALLOCATIONFAILURES HRSTORAGEENTRY, 7 +#define HRDEVICETYPES HRDEVICE, 1 +#define HRDEVICETABLE HRDEVICE, 2 +#define HRDEVICEENTRY HRDEVICETABLE, 1 +#define HRDEVICEINDEX HRDEVICEENTRY, 1 +#define HRDEVICETYPE HRDEVICEENTRY, 2 +#define HRDEVICEDESCR HRDEVICEENTRY, 3 +#define HRDEVICEID HRDEVICEENTRY, 4 +#define HRDEVICESTATUS HRDEVICEENTRY, 5 +#define HRDEVICEERRORS HRDEVICEENTRY, 6 +#define HRPROCESSORTABLE HRDEVICE, 3 +#define HRPROCESSORENTRY HRPROCESSORTABLE, 1 +#define HRPROCESSORFRWID HRPROCESSORENTRY, 1 +#define HRPROCESSORLOAD HRPROCESSORENTRY, 2 +#define HRNETWORKTABLE HRDEVICE, 4 +#define HRNETWORKENTRY HRNETWORKTABLE, 1 +#define HRNETWORKIFINDEX HRNETWORKENTRY, 1 +#define HRPRINTERTABLE HRDEVICE, 5 +#define HRPRINTERENTRY HRPRINTERTABLE, 1 +#define HRPRINTERSTATUS HRPRINTERENTRY, 1 +#define HRPRINTERDETECTEDERRORSTATE HRPRINTERENTRY, 2 +#define HRDISKSTORAGETABLE HRDEVICE, 6 +#define HRDISKSTORAGEENTRY HRDISKSTORAGETABLE, 1 +#define HRDISKSTORAGEACCESS HRDISKSTORAGEENTRY, 1 +#define HRDISKSTORAGEMEDIA HRDISKSTORAGEENTRY, 2 +#define HRDISKSTORAGEREMOVEBLE HRDISKSTORAGEENTRY, 3 +#define HRDISKSTORAGECAPACITY HRDISKSTORAGEENTRY, 4 +#define HRPARTITIONTABLE HRDEVICE, 7 +#define HRPARTITIONENTRY HRPARTITIONTABLE, 1 +#define HRPARTITIONINDEX HRPARTITIONENTRY, 1 +#define HRPARTITIONLABEL HRPARTITIONENTRY, 2 +#define HRPARTITIONID HRPARTITIONENTRY, 3 +#define HRPARTITIONSIZE HRPARTITIONENTRY, 4 +#define HRPARTITIONFSINDEX HRPARTITIONENTRY, 5 +#define HRFSTYPES HRDEVICE, 9 +#define HRFSTABLE HRDEVICE, 8 +#define HRFSENTRY HRFSTABLE, 1 +#define HRFSINDEX HRFSENTRY, 1 +#define HRFSMOUNTPOINT HRFSENTRY, 2 +#define HRFSREMOTEMOUNTPOINT HRFSENTRY, 3 +#define HRFSTYPE HRFSENTRY, 4 +#define HRFSACCESS HRFSENTRY, 5 +#define HRFSBOOTABLE HRFSENTRY, 6 +#define HRFSSTORAGEINDEX HRFSENTRY, 7 +#define HRFSLASTFULLBACKUPDATE HRFSENTRY, 8 +#define HRFSLASTPARTIALBACKUPDATE HRFSENTRY, 9 +#define HRSWOSINDEX HRSWRUN, 1 +#define HRSWRUNTABLE HRSWRUN, 2 +#define HRSWRUNENTRY HRSWRUNTABLE, 1 +#define HRSWRUNINDEX HRSWRUNENTRY, 1 +#define HRSWRUNNAME HRSWRUNENTRY, 2 +#define HRSWRUNID HRSWRUNENTRY, 3 +#define HRSWRUNPATH HRSWRUNENTRY, 4 +#define HRSWRUNPARAMETERS HRSWRUNENTRY, 5 +#define HRSWRUNTYPE HRSWRUNENTRY, 6 +#define HRSWRUNSTATUS HRSWRUNENTRY, 7 +#define HRSWRUNPERFTABLE HRSWRUNPERF, 1 +#define HRSWRUNPERFENTRY HRSWRUNPERFTABLE, 1 +#define HRSWRUNPERFCPU HRSWRUNPERFENTRY, 1 +#define HRSWRUNPERFMEM HRSWRUNPERFENTRY, 2 +#define HRSWINSTALLEDLASTCHANGE HRSWINSTALLED, 1 +#define HRSWINSTALLEDLASTUPDATETIME HRSWINSTALLED, 2 +#define HRSWINSTALLEDTABLE HRSWINSTALLED, 3 +#define HRSWINSTALLEDENTRY HRSWINSTALLEDTABLE, 1 +#define HRSWINSTALLEDINDEX HRSWINSTALLEDENTRY, 1 +#define HRSWINSTALLEDNAME HRSWINSTALLEDENTRY, 2 +#define HRSWINSTALLEDID HRSWINSTALLEDENTRY, 3 +#define HRSWINSTALLEDTYPE HRSWINSTALLEDENTRY, 4 +#define HRSWINSTALLEDDATE HRSWINSTALLEDENTRY, 5 + +/* HOST-RESOURCES-TYPES */ +#define HRSTORAGEOTHER HRSTORAGETYPES, 1 +#define HRSTORAGERAM HRSTORAGETYPES, 2 +#define HRSTORAGEVIRTUALMEMORY HRSTORAGETYPES, 3 +#define HRSTORAGEFIXEDDISK HRSTORAGETYPES, 4 +#define HRSTORAGEREMOVABLEDISK HRSTORAGETYPES, 5 +#define HRSTORAGEFLOPPYDISK HRSTORAGETYPES, 6 +#define HRSTORAGECOMPACTDISC HRSTORAGETYPES, 7 +#define HRSTORAGERAMDISK HRSTORAGETYPES, 8 +#define HRSTORAGEFLASHMEMORY HRSTORAGETYPES, 9 +#define HRSTORAGENETWORKDISK HRSTORAGETYPES, 10 +#define HRDEVICEOTHER HRDEVICETYPES, 1 +#define HRDEVICEUNKNOWN HRDEVICETYPES, 2 +#define HRDEVICEPROCESSOR HRDEVICETYPES, 3 +#define HRDEVICENETWORK HRDEVICETYPES, 4 +#define HRDEVICEPRINTER HRDEVICETYPES, 5 +#define HRDEVICEDISKSTORAGE HRDEVICETYPES, 6 +#define HRDEVICEVIDEO HRDEVICETYPES, 10 +#define HRDEVICEAUDIO HRDEVICETYPES, 11 +#define HRDEVICECOPROCESSOR HRDEVICETYPES, 12 +#define HRDEVICEKEYBOARD HRDEVICETYPES, 13 +#define HRDEVICEMODEM HRDEVICETYPES, 14 +#define HRDEVICEPARALLELPORT HRDEVICETYPES, 15 +#define HRDEVICEPOINTING HRDEVICETYPES, 16 +#define HRDEVICESERIALPORT HRDEVICETYPES, 17 +#define HRDEVICETAPE HRDEVICETYPES, 18 +#define HRDEVICECLOCK HRDEVICETYPES, 19 +#define HRDEVICEVOLATILEMEMORY HRDEVICETYPES, 20 +#define HRDEVICENONVOLATILEMEMORY HRDEVICETYPES, 21 +#define HRFSOTHER HRFSTYPES, 1 +#define HRFSUNKNOWN HRFSTYPES, 2 +#define HRFSBERKELEYFFS HRFSTYPES, 3 +#define HRFSSYS5FS HRFSTYPES, 4 +#define HRFSFAT HRFSTYPES, 5 +#define HRFSHPFS HRFSTYPES, 6 +#define HRFSHFS HRFSTYPES, 7 +#define HRFSMFS HRFSTYPES, 8 +#define HRFSNTFS HRFSTYPES, 9 +#define HRFSVNODE HRFSTYPES, 10 +#define HRFSJOURNALED HRFSTYPES, 11 +#define HRFSISO9660 HRFSTYPES, 12 +#define HRFSROCKRIDGE HRFSTYPES, 13 +#define HRFSNFS HRFSTYPES, 14 +#define HRFSNETWARE HRFSTYPES, 15 +#define HRFSAFS HRFSTYPES, 16 +#define HRFSDFS HRFSTYPES, 17 +#define HRfSAPPLESHARE HRFSTYPES, 18 +#define HRFSRFS HRFSTYPES, 19 +#define HRFSDGCFS HRFSTYPES, 20 +#define HRFSBFS HRFSTYPES, 21 +#define HRFSFAT32 HRFSTYPES, 22 +#define HRFSLINUXEXT2 HRFSTYPES, 23 + +/* IF-MIB */ +#define IFMIB AGENTX_MIB2, 31 +#define IFMIBOBJECTS IFMIB, 1 +#define INTERFACES AGENTX_MIB2, 2 +#define IFNUMBER INTERFACES, 1 +#define IFTABLELASTCHANGE IFMIBOBJECTS, 5 +#define IFTABLE INTERFACES, 2 +#define IFENTRY IFTABLE, 1 +#define IFINDEX IFENTRY, 1 +#define IFDESCR IFENTRY, 2 +#define IFTYPE IFENTRY, 3 +#define IFMTU IFENTRY, 4 +#define IFSPEED IFENTRY, 5 +#define IFPHYSADDRESS IFENTRY, 6 +#define IFADMINSTATUS IFENTRY, 7 +#define IFOPERSTATUS IFENTRY, 8 +#define IFLASTCHANGE IFENTRY, 9 +#define IFINOCTETS IFENTRY, 10 +#define IFINUCASTPKTS IFENTRY, 11 +#define IFINNUCASTPKTS IFENTRY, 12 +#define IFINDISCARDS IFENTRY, 13 +#define IFINERRORS IFENTRY, 14 +#define IFINUNKNOWNPROTOS IFENTRY, 15 +#define IFOUTOCTETS IFENTRY, 16 +#define IFOUTUCASTPKTS IFENTRY, 17 +#define IFOUTNUCASTPKTS IFENTRY, 18 +#define IFOUTDISCARDS IFENTRY, 19 +#define IFOUTERRORS IFENTRY, 20 +#define IFOUTQLEN IFENTRY, 21 +#define IFSPECIFIC IFENTRY, 22 +#define IFXTABLE IFMIBOBJECTS, 1 +#define IFXENTRY IFXTABLE, 1 +#define IFNAME IFXENTRY, 1 +#define IFINMULTICASTPKTS IFXENTRY, 2 +#define IFINBROADCASTPKTS IFXENTRY, 3 +#define IFOUTMULTICASTPKTS IFXENTRY, 4 +#define IFOUTBROADCASTPKTS IFXENTRY, 5 +#define IFHCINOCTETS IFXENTRY, 6 +#define IFHCINUCASTPKTS IFXENTRY, 7 +#define IFHCINMULTICASTPKTS IFXENTRY, 8 +#define IFHCINBROADCASTPKTS IFXENTRY, 9 +#define IFHCOUTOCTETS IFXENTRY, 10 +#define IFHCOUTUCASTPKTS IFXENTRY, 11 +#define IFHCOUTMULTICASTPKTS IFXENTRY, 12 +#define IFHCOUTBROADCASTPKTS IFXENTRY, 13 +#define IFLINKUPDOWNTRAPENABLE IFXENTRY, 14 +#define IFHIGHSPEED IFXENTRY, 15 +#define IFPROMISCUOUSMODE IFXENTRY, 16 +#define IFCONNECTORPRESENT IFXENTRY, 17 +#define IFALIAS IFXENTRY, 18 +#define IFCOUNTERDISCONTINUITYTIME IFXENTRY, 19 +#define IFSTACKTABLE IFMIBOBJECTS, 2 +#define IFSTACKENTRY IFSTACKTABLE, 1 +#define IFSTACKHIGHERLAYER IFSTACKENTRY, 1 +#define IFSTACKLOWERLAYER IFSTACKENTRY, 2 +#define IFSTACKSTATUS IFSTACKENTRY, 3 +#define IFRCVADDRESSTABLE IFMIBOBJECTS, 4 +#define IFRCVADDRESSENTRY IFRCVADDRESSTABLE, 1 +#define IFRCVADDRESSADDRESS IFRCVADDRESSENTRY, 1 +#define IFRCVADDRESSSTATUS IFRCVADDRESSENTRY, 2 +#define IFRCVADDRESSTYPE IFRCVADDRESSENTRY, 3 +#define IFSTACKLASTCHANGE IFMIBOBJECTS, 6 + +/* OPENBSD-BASE-MIB */ +#define OPENBSD AGENTX_ENTERPRISES, 30155 +#define PFMIBOBJECTS OPENBSD, 1 +#define SENSORSMIBOBJECTS OPENBSD, 2 +#define RELAYDMIBOBJECTS OPENBSD, 3 +#define MEMMIBOBJECTS OPENBSD, 5 +#define CARPMIBOBJECTS OPENBSD, 6 +#define LOCALSYSTEM OPENBSD, 23 +#define OPENBSDDEFAULTOBJECTID LOCALSYSTEM, 1 +#define LOCALTEST OPENBSD, 42 + +/* OPENBSD-PF-MIB */ +#define PFINFO PFMIBOBJECTS, 1 +#define PFCOUNTERS PFMIBOBJECTS, 2 +#define PFSTATETABLE PFMIBOBJECTS, 3 +#define PFLOGINTERFACE PFMIBOBJECTS, 4 +#define PFSRCTRACKING PFMIBOBJECTS, 5 +#define PFLIMITS PFMIBOBJECTS, 6 +#define PFTIMEOUTS PFMIBOBJECTS, 7 +#define PFINTERFACES PFMIBOBJECTS, 8 +#define PFTABLES PFMIBOBJECTS, 9 +#define PFLABELS PFMIBOBJECTS, 10 +#define PFSYNCSTATS PFMIBOBJECTS, 11 +#define PFRUNNING PFINFO, 1 +#define PFRUNTIME PFINFO, 2 +#define PFDEBUG PFINFO, 3 +#define PFHOSTID PFINFO, 4 +#define PFCNTMATCH PFCOUNTERS, 1 +#define PFCNTBADOFFSET PFCOUNTERS, 2 +#define PFCNTFRAGMENT PFCOUNTERS, 3 +#define PFCNTSHORT PFCOUNTERS, 4 +#define PFCNTNORMALIZE PFCOUNTERS, 5 +#define PFCNTMEMORY PFCOUNTERS, 6 +#define PFCNTTIMESTAMP PFCOUNTERS, 7 +#define PFCNTCONGESTION PFCOUNTERS, 8 +#define PFCNTIPOPTION PFCOUNTERS, 9 +#define PFCNTPROTOCKSUM PFCOUNTERS, 10 +#define PFCNTSTATEMISMATCH PFCOUNTERS, 11 +#define PFCNTSTATEINSERT PFCOUNTERS, 12 +#define PFCNTSTATELIMIT PFCOUNTERS, 13 +#define PFCNTSRCLIMIT PFCOUNTERS, 14 +#define PFCNTSYNPROXY PFCOUNTERS, 15 +#define PFCNTTRANSLATE PFCOUNTERS, 16 +#define PFCNTNOROUTE PFCOUNTERS, 17 +#define PFSTATECOUNT PFSTATETABLE, 1 +#define PFSTATESEARCHES PFSTATETABLE, 2 +#define PFSTATEINSERTS PFSTATETABLE, 3 +#define PFSTATEREMOVALS PFSTATETABLE, 4 +#define PFLOGIFNAME PFLOGINTERFACE, 1 +#define PFLOGIFIPBYTESIN PFLOGINTERFACE, 2 +#define PFLOGIFIPBYTESOUT PFLOGINTERFACE, 3 +#define PFLOGIFIPPKTSINPASS PFLOGINTERFACE, 4 +#define PFLOGIFIPPKTSINDROP PFLOGINTERFACE, 5 +#define PFLOGIFIPPKTSOUTPASS PFLOGINTERFACE, 6 +#define PFLOGIFIPPKTSOUTDROP PFLOGINTERFACE, 7 +#define PFLOGIFIP6BYTESIN PFLOGINTERFACE, 8 +#define PFLOGIFIP6BYTESOUT PFLOGINTERFACE, 9 +#define PFLOGIFIP6PKTSINPASS PFLOGINTERFACE, 10 +#define PFLOGIFIP6PKTSINDROP PFLOGINTERFACE, 11 +#define PFLOGIFIP6PKTSOUTPASS PFLOGINTERFACE, 12 +#define PFLOGIFIP6PKTSOUTDROP PFLOGINTERFACE, 13 +#define PFSRCTRACKCOUNT PFSRCTRACKING, 1 +#define PFSRCTRACKSEARCHES PFSRCTRACKING, 2 +#define PFSRCTRACKINSERTS PFSRCTRACKING, 3 +#define PFSRCTRACKREMOVALS PFSRCTRACKING, 4 +#define PFLIMITSTATES PFLIMITS, 1 +#define PFLIMITSOURCENODES PFLIMITS, 2 +#define PFLIMITFRAGMENTS PFLIMITS, 3 +#define PFLIMITMAXTABLES PFLIMITS, 4 +#define PFLIMITMAXTABLEENTRIES PFLIMITS, 5 +#define PFTIMEOUTTCPFIRST PFTIMEOUTS, 1 +#define PFTIMEOUTTCPOPENING PFTIMEOUTS, 2 +#define PFTIMEOUTTCPESTABLISHED PFTIMEOUTS, 3 +#define PFTIMEOUTTCPCLOSING PFTIMEOUTS, 4 +#define PFTIMEOUTTCPFINWAIT PFTIMEOUTS, 5 +#define PFTIMEOUTTCPCLOSED PFTIMEOUTS, 6 +#define PFTIMEOUTUDPFIRST PFTIMEOUTS, 7 +#define PFTIMEOUTUDPSINGLE PFTIMEOUTS, 8 +#define PFTIMEOUTUDPMULTIPLE PFTIMEOUTS, 9 +#define PFTIMEOUTICMPFIRST PFTIMEOUTS, 10 +#define PFTIMEOUTICMPERROR PFTIMEOUTS, 11 +#define PFTIMEOUTOTHERFIRST PFTIMEOUTS, 12 +#define PFTIMEOUTOTHERSINGLE PFTIMEOUTS, 13 +#define PFTIMEOUTOTHERMULTIPLE PFTIMEOUTS, 14 +#define PFTIMEOUTFRAGMENT PFTIMEOUTS, 15 +#define PFTIMEOUTINTERVAL PFTIMEOUTS, 16 +#define PFTIMEOUTADAPTIVESTART PFTIMEOUTS, 17 +#define PFTIMEOUTADAPTIVEEND PFTIMEOUTS, 18 +#define PFTIMEOUTSRCTRACK PFTIMEOUTS, 19 +#define PFIFNUMBER PFINTERFACES, 1 +#define PFIFTABLE PFINTERFACES, 128 +#define PFIFENTRY PFIFTABLE, 1 +#define PFIFINDEX PFIFENTRY, 1 +#define PFIFDESCR PFIFENTRY, 2 +#define PFIFTYPE PFIFENTRY, 3 +#define PFIFREFS PFIFENTRY, 4 +#define PFIFRULES PFIFENTRY, 5 +#define PFIFIN4PASSPKTS PFIFENTRY, 6 +#define PFIFIN4PASSBYTES PFIFENTRY, 7 +#define PFIFIN4BLOCKPKTS PFIFENTRY, 8 +#define PFIFIN4BLOCKBYTES PFIFENTRY, 9 +#define PFIFOUT4PASSPKTS PFIFENTRY, 10 +#define PFIFOUT4PASSBYTES PFIFENTRY, 11 +#define PFIFOUT4BLOCKPKTS PFIFENTRY, 12 +#define PFIFOUT4BLOCKBYTES PFIFENTRY, 13 +#define PFIFIN6PASSPKTS PFIFENTRY, 14 +#define PFIFIN6PASSBYTES PFIFENTRY, 15 +#define PFIFIN6BLOCKPKTS PFIFENTRY, 16 +#define PFIFIN6BLOCKBYTES PFIFENTRY, 17 +#define PFIFOUT6PASSPKTS PFIFENTRY, 18 +#define PFIFOUT6PASSBYTES PFIFENTRY, 19 +#define PFIFOUT6BLOCKPKTS PFIFENTRY, 20 +#define PFIFOUT6BLOCKBYTES PFIFENTRY, 21 +#define PFTBLNUMBER PFTABLES, 1 +#define PFTBLTABLE PFTABLES, 128 +#define PFTBLENTRY PFTBLTABLE, 1 +#define PFTBLINDEX PFTBLENTRY, 1 +#define PFTBLNAME PFTBLENTRY, 2 +#define PFTBLADDRESSES PFTBLENTRY, 3 +#define PFTBLANCHORREFS PFTBLENTRY, 4 +#define PFTBLRULEREFS PFTBLENTRY, 5 +#define PFTBLEVALSMATCH PFTBLENTRY, 6 +#define PFTBLEVALSNOMATCH PFTBLENTRY, 7 +#define PFTBLINPASSPKTS PFTBLENTRY, 8 +#define PFTBLINPASSBYTES PFTBLENTRY, 9 +#define PFTBLINBLOCKPKTS PFTBLENTRY, 10 +#define PFTBLINBLOCKBYTES PFTBLENTRY, 11 +#define PFTBLINXPASSPKTS PFTBLENTRY, 12 +#define PFTBLINXPASSBYTES PFTBLENTRY, 13 +#define PFTBLOUTPASSPKTS PFTBLENTRY, 14 +#define PFTBLOUTPASSBYTES PFTBLENTRY, 15 +#define PFTBLOUTBLOCKPKTS PFTBLENTRY, 16 +#define PFTBLOUTBLOCKBYTES PFTBLENTRY, 17 +#define PFTBLOUTXPASSPKTS PFTBLENTRY, 18 +#define PFTBLOUTXPASSBYTES PFTBLENTRY, 19 +#define PFTBLSTATSCLEARED PFTBLENTRY, 20 +#define PFTBLINMATCHPKTS PFTBLENTRY, 21 +#define PFTBLINMATCHBYTES PFTBLENTRY, 22 +#define PFTBLOUTMATCHPKTS PFTBLENTRY, 23 +#define PFTBLOUTMATCHBYTES PFTBLENTRY, 24 +#define PFTBLADDRTABLE PFTABLES, 129 +#define PFTBLADDRENTRY PFTBLADDRTABLE, 1 +#define PFTBLADDRTBLINDEX PFTBLADDRENTRY, 1 +#define PFTBLADDRNET PFTBLADDRENTRY, 2 +#define PFTBLADDRMASK PFTBLADDRENTRY, 3 +#define PFTBLADDRCLEARED PFTBLADDRENTRY, 4 +#define PFTBLADDRINBLOCKPKTS PFTBLADDRENTRY, 5 +#define PFTBLADDRINBLOCKBYTES PFTBLADDRENTRY, 6 +#define PFTBLADDRINPASSPKTS PFTBLADDRENTRY, 7 +#define PFTBLADDRINPASSBYTES PFTBLADDRENTRY, 8 +#define PFTBLADDROUTBLOCKPKTS PFTBLADDRENTRY, 9 +#define PFTBLADDROUTBLOCKBYTES PFTBLADDRENTRY, 10 +#define PFTBLADDROUTPASSPKTS PFTBLADDRENTRY, 11 +#define PFTBLADDROUTPASSBYTES PFTBLADDRENTRY, 12 +#define PFTBLADDRINMATCHPKTS PFTBLADDRENTRY, 13 +#define PFTBLADDRINMATCHBYTES PFTBLADDRENTRY, 14 +#define PFTBLADDROUTMATCHPKTS PFTBLADDRENTRY, 15 +#define PFTBLADDROUTMATCHBYTES PFTBLADDRENTRY, 16 +#define PFLABELNUMBER PFLABELS, 1 +#define PFLABELTABLE PFLABELS, 128 +#define PFLABELENTRY PFLABELTABLE, 1 +#define PFLABELINDEX PFLABELENTRY, 1 +#define PFLABELNAME PFLABELENTRY, 2 +#define PFLABELEVALS PFLABELENTRY, 3 +#define PFLABELPKTS PFLABELENTRY, 4 +#define PFLABELBYTES PFLABELENTRY, 5 +#define PFLABELINPKTS PFLABELENTRY, 6 +#define PFLABELINBYTES PFLABELENTRY, 7 +#define PFLABELOUTPKTS PFLABELENTRY, 8 +#define PFLABELOUTBYTES PFLABELENTRY, 9 +#define PFLABELTOTALSTATES PFLABELENTRY, 10 +#define PFSYNCIPPKTSRECV PFSYNCSTATS, 1 +#define PFSYNCIP6PKTSRECV PFSYNCSTATS, 2 +#define PFSYNCPKTDISCARDSFORBADINTERFACE PFSYNCSTATS, 3 +#define PFSYNCPKTDISCARDSFORBADTTL PFSYNCSTATS, 4 +#define PFSYNCPKTSHORTERTHANHEADER PFSYNCSTATS, 5 +#define PFSYNCPKTDISCARDSFORBADVERSION PFSYNCSTATS, 6 +#define PFSYNCPKTDISCARDSFORBADACTION PFSYNCSTATS, 7 +#define PFSYNCPKTDISCARDSFORBADLENGTH PFSYNCSTATS, 8 +#define PFSYNCPKTDISCARDSFORBADAUTH PFSYNCSTATS, 9 +#define PFSYNCPKTDISCARDSFORSTALESTATE PFSYNCSTATS, 10 +#define PFSYNCPKTDISCARDSFORBADVALUES PFSYNCSTATS, 11 +#define PFSYNCPKTDISCARDSFORBADSTATE PFSYNCSTATS, 12 +#define PFSYNCIPPKTSSENT PFSYNCSTATS, 13 +#define PFSYNCIP6PKTSSENT PFSYNCSTATS, 14 +#define PFSYNCNOMEMORY PFSYNCSTATS, 15 +#define PFSYNCOUTPUTERRORS PFSYNCSTATS, 16 + +/* OPENBSD-SENSORS-MIB */ +#define SENSORSMIBOBJECTS OPENBSD, 2 +#define SENSORS SENSORSMIBOBJECTS, 1 +#define SENSORNUMBER SENSORS, 1 +#define SENSORTABLE SENSORS, 2 +#define SENSORENTRY SENSORTABLE, 1 +#define SENSORINDEX SENSORENTRY, 1 +#define SENSORDESCR SENSORENTRY, 2 +#define SENSORTYPE SENSORENTRY, 3 +#define SENSORDEVICE SENSORENTRY, 4 +#define SENSORVALUE SENSORENTRY, 5 +#define SENSORUNITS SENSORENTRY, 6 +#define SENSORSTATUS SENSORENTRY, 7 + +/* OPENBSD-CARP-MIB */ +#define CARPSYSCTL CARPMIBOBJECTS, 1 +#define CARPIF CARPMIBOBJECTS, 2 +#define CARPSTATS CARPMIBOBJECTS, 3 +#define CARPALLOW CARPSYSCTL, 1 +#define CARPPREEMPT CARPSYSCTL, 2 +#define CARPLOG CARPSYSCTL, 3 +#define CARPIFNUMBER CARPIF, 1 +#define CARPIFTABLE CARPIF, 2 +#define CARPIFENTRY CARPIFTABLE, 1 +#define CARPIFINDEX CARPIFENTRY, 1 +#define CARPIFDESCR CARPIFENTRY, 2 +#define CARPIFVHID CARPIFENTRY, 3 +#define CARPIFDEV CARPIFENTRY, 4 +#define CARPIFADVBASE CARPIFENTRY, 5 +#define CARPIFADVSKEW CARPIFENTRY, 6 +#define CARPIFSTATE CARPIFENTRY, 7 +#define CARPGROUPTABLE CARPMIBOBJECTS, 4 +#define CARPGROUPENTRY CARPGROUPTABLE, 1 +#define CARPGROUPINDEX CARPGROUPENTRY, 1 +#define CARPGROUPNAME CARPGROUPENTRY, 2 +#define CARPGROUPDEMOTE CARPGROUPENTRY, 3 +#define CARPIPPKTSRECV CARPSTATS, 1 +#define CARPIP6PKTSRECV CARPSTATS, 2 +#define CARPPKTDISCARDSFORBADINTERFACE CARPSTATS, 3 +#define CARPPKTDISCARDSFORWRONGTTL CARPSTATS, 4 +#define CARPPKTSHORTERTHANHEADER CARPSTATS, 5 +#define CARPPKTDISCARDSFORBADCHECKSUM CARPSTATS, 6 +#define CARPPKTDISCARDSFORBADVERSION CARPSTATS, 7 +#define CARPPKTDISCARDSFORTOOSHORT CARPSTATS, 8 +#define CARPPKTDISCARDSFORBADAUTH CARPSTATS, 9 +#define CARPPKTDISCARDSFORBADVHID CARPSTATS, 10 +#define CARPPKTDISCARDSFORBADADDRESSLIST CARPSTATS, 11 +#define CARPIPPKTSSENT CARPSTATS, 12 +#define CARPIP6PKTSSENT CARPSTATS, 13 +#define CARPNOMEMORY CARPSTATS, 14 +#define CARPTRANSITIONSTOMASTER CARPSTATS, 15 + +/* OPENBSD-MEM-MIB */ +#define MEMMIBVERSION MEMMIBOBJECTS, 1 +#define MEMIFTABLE MEMMIBOBJECTS, 2 +#define MEMIFENTRY MEMIFTABLE, 1 +#define MEMIFNAME MEMIFENTRY, 1 +#define MEMIFLIVELOCKS MEMIFENTRY, 2 + +/* IP-MIB */ +#define IPMIB AGENTX_MIB2, 48 +#define IP AGENTX_MIB2, 4 +#define IPFORWARDING IP, 1 +#define IPDEFAULTTTL IP, 2 +#define IPREASMTIMEOUT IP, 13 +#define IPV6IPFORWARDING IP, 25 +#define IPV6IPDEFAULTHOPLIMIT IP, 26 +#define IPV4INTERFACETABLELASTCHANGE IP, 27 +#define IPV4INTERFACETABLE IP, 28 +#define IPV4INTERFACEENTRY IPV4INTERFACETABLE, 1 +#define IPV4INTERFACEIFINDEX IPV4INTERFACEENTRY, 1 +#define IPV4INTERFACEREASMMAXSIZE IPV4INTERFACEENTRY, 2 +#define IPV4INTERFACEENABLESTATUS IPV4INTERFACEENTRY, 3 +#define IPV4INTERFACERETRANSMITTIME IPV4INTERFACEENTRY, 4 +#define IPV6INTERFACETABLELASTCHANGE IP, 29 +#define IPV6INTERFACETABLE IP, 30 +#define IPV6INTERFACEENTRY IPV6INTERFACETABLE, 1 +#define IPV6INTERFACEIFINDEX IPV6INTERFACEENTRY, 1 +#define IPV6INTERFACEREASMMAXSIZE IPV6INTERFACEENTRY, 2 +#define IPV6INTERFACEIDENTIFIER IPV6INTERFACEENTRY, 3 +#define IPV6INTERFACEENABLESTATUS IPV6INTERFACEENTRY, 5 +#define IPV6INTERFACEREACHABLETIME IPV6INTERFACEENTRY, 6 +#define IPV6INTERFACERETRANSMITTIME IPV6INTERFACEENTRY, 7 +#define IPV6INTERFACEFORWARDING IPV6INTERFACEENTRY, 8 +#define IPTRAFFICSTATS IP, 31 +#define IPSYSTEMSTATSTABLE IPTRAFFICSTATS, 1 +#define IPSYSTEMSTATSENTRY IPSYSTEMSTATSTABLE, 1 +#define IPSYSTEMSTATSIPVERSION IPSYSTEMSTATSENTRY, 1 +#define IPSYSTEMSTATSINRECEIVES IPSYSTEMSTATSENTRY, 3 +#define IPSYSTEMSTATSHCINRECEIVES IPSYSTEMSTATSENTRY, 4 +#define IPSYSTEMSTATSINOCTETS IPSYSTEMSTATSENTRY, 5 +#define IPSYSTEMSTATSHCINOCTETS IPSYSTEMSTATSENTRY, 6 +#define IPSYSTEMSTATSINHDRERRORS IPSYSTEMSTATSENTRY, 7 +#define IPSYSTEMSTATSINNOROUTES IPSYSTEMSTATSENTRY, 8 +#define IPSYSTEMSTATSINADDRERRORS IPSYSTEMSTATSENTRY, 9 +#define IPSYSTEMSTATSINUNKNOWNPROTOS IPSYSTEMSTATSENTRY, 10 +#define IPSYSTEMSTATSINTRUNCATEDPKTS IPSYSTEMSTATSENTRY, 11 +#define IPSYSTEMSTATSINFORWDATAGRAMS IPSYSTEMSTATSENTRY, 12 +#define IPSYSTEMSTATSHCINFORWDATAGRAMS IPSYSTEMSTATSENTRY, 13 +#define IPSYSTEMSTATSREASMREQDS IPSYSTEMSTATSENTRY, 14 +#define IPSYSTEMSTATSREASMOKS IPSYSTEMSTATSENTRY, 15 +#define IPSYSTEMSTATSREASMFAILS IPSYSTEMSTATSENTRY, 16 +#define IPSYSTEMSTATSINDISCARDS IPSYSTEMSTATSENTRY, 17 +#define IPSYSTEMSTATSINDELIVERS IPSYSTEMSTATSENTRY, 18 +#define IPSYSTEMSTATSHCINDELIVERS IPSYSTEMSTATSENTRY, 19 +#define IPSYSTEMSTATSOUTREQUESTS IPSYSTEMSTATSENTRY, 20 +#define IPSYSTEMSTATSHCOUTREQUESTS IPSYSTEMSTATSENTRY, 21 +#define IPSYSTEMSTATSOUTNOROUTES IPSYSTEMSTATSENTRY, 22 +#define IPSYSTEMSTATSOUTFORWDATAGRAMS IPSYSTEMSTATSENTRY, 23 +#define IPSYSTEMSTATSHCOUTfORWDATAGRAMS IPSYSTEMSTATSENTRY, 24 +#define IPSYSTEMSTATSOUTDISCARDS IPSYSTEMSTATSENTRY, 25 +#define IPSYSTEMSTATSOUTFRAGREQDS IPSYSTEMSTATSENTRY, 26 +#define IPSYSTEMSTATSOUTFRAGOKS IPSYSTEMSTATSENTRY, 27 +#define IPSYSTEMSTATSOUTFRAGFAILS IPSYSTEMSTATSENTRY, 28 +#define IPSYSTEMSTATSOUTFRAGCREATES IPSYSTEMSTATSENTRY, 29 +#define IPSYSTEMSTATSOUTTRANSMITS IPSYSTEMSTATSENTRY, 30 +#define IPSYSTEMSTATSHCOUTTRANSMITS IPSYSTEMSTATSENTRY, 31 +#define IPSYSTEMSTATSOUTOCTETS IPSYSTEMSTATSENTRY, 32 +#define IPSYSTEMSTATSHCOUTOCTETS IPSYSTEMSTATSENTRY, 33 +#define IPSYSTEMSTATSINMCASTPKTS IPSYSTEMSTATSENTRY, 34 +#define IPSYSTEMSTATSHCINMCASTPKTS IPSYSTEMSTATSENTRY, 35 +#define IPSYSTEMSTATSINMCASTOCTETS IPSYSTEMSTATSENTRY, 36 +#define IPSYSTEMSTATSHCINMCASTOCTETS IPSYSTEMSTATSENTRY, 37 +#define IPSYSTEMSTATSOUTMCASTPKTS IPSYSTEMSTATSENTRY, 38 +#define IPSYSTEMSTATSHCOUTMCASTPKTS IPSYSTEMSTATSENTRY, 39 +#define IPSYSTEMSTATSOUTMCASTOCTETS IPSYSTEMSTATSENTRY, 40 +#define IPSYSTEMSTATSHCOUTMCASTOCTETS IPSYSTEMSTATSENTRY, 41 +#define IPSYSTEMSTATSINBCASTPKTS IPSYSTEMSTATSENTRY, 42 +#define IPSYSTEMSTATSHCINBCASTPKTS IPSYSTEMSTATSENTRY, 43 +#define IPSYSTEMSTATSOUTBCASTPKTS IPSYSTEMSTATSENTRY, 44 +#define IPSYSTEMSTATSHCOUTBCASTPKTS IPSYSTEMSTATSENTRY, 45 +#define IPSYSTEMSTATSDISCONTINUITYTIME IPSYSTEMSTATSENTRY, 46 +#define IPSYSTEMSTATSREFRESHRATE IPSYSTEMSTATSENTRY, 47 +#define IPIFSTATSTABLELASTCHANGE IPTRAFFICSTATS, 2 +#define IPIFSTATSTABLE IPTRAFFICSTATS, 3 +#define IPIFSTATSENTRY IPIFSTATSTABLE, 1 +#define IPIFSTATSIPVERSION IPIFSTATSENTRY, 1 +#define IPIFSTATSIFINDEX IPIFSTATSENTRY, 2 +#define IPIFSTATSINRECEIVES IPIFSTATSENTRY, 3 +#define IPIFSTATSHCINRECEIVES IPIFSTATSENTRY, 4 +#define IPIFSTATSINOCTETS IPIFSTATSENTRY, 5 +#define IPIFSTATSHCINOCTETS IPIFSTATSENTRY, 6 +#define IPIFSTATSINHDRERRORS IPIFSTATSENTRY, 7 +#define IPIFSTATSINNOROUTES IPIFSTATSENTRY, 8 +#define IPIFSTATSINADDRERRORS IPIFSTATSENTRY, 9 +#define IPIFSTATSINUNKNOWNPROTOS IPIFSTATSENTRY, 10 +#define IPIFSTATSINTRUNCATEDPKTS IPIFSTATSENTRY, 11 +#define IPIFSTATSINFORWDATAGRAMS IPIFSTATSENTRY, 12 +#define IPIFSTATSHCINFORWDATAGRAMS IPIFSTATSENTRY, 13 +#define IPIFSTATSREASMREQDS IPIFSTATSENTRY, 14 +#define IPIFSTATSREASMOKS IPIFSTATSENTRY, 15 +#define IPIFSTATSREASMFAILS IPIFSTATSENTRY, 16 +#define IPIFSTATSINDISCARDS IPIFSTATSENTRY, 17 +#define IPIFSTATSINDELIVERS IPIFSTATSENTRY, 18 +#define IPIFSTATSHCINDELIVERS IPIFSTATSENTRY, 19 +#define IPIFSTATSOUTREQUESTS IPIFSTATSENTRY, 20 +#define IPIFSTATSHCOUTREQUESTS IPIFSTATSENTRY, 21 +#define IPIFSTATSOUTFORWDATAGRAMS IPIFSTATSENTRY, 23 +#define IPIFSTATSHCOUTFORWDATAGRAMS IPIFSTATSENTRY, 24 +#define IPIFSTATSOUTDISCARDS IPIFSTATSENTRY, 25 +#define iPIFSTATSOUTFRAGREQDS IPIFSTATSENTRY, 26 +#define IPIFSTATSOUTFRAGOKS IPIFSTATSENTRY, 27 +#define IPIFSTATSOUTFRAGFAILS IPIFSTATSENTRY, 28 +#define IPIFSTATSOUTFRAGCREATES IPIFSTATSENTRY, 29 +#define IPIFSTATSOUTTRANSMITS IPIFSTATSENTRY, 30 +#define IPIFSTATSHCOUTTRANSMITS IPIFSTATSENTRY, 31 +#define IPIFSTATSOUTOCTETS IPIFSTATSENTRY, 32 +#define IPIFSTATSHCOUTOCTETS IPIFSTATSENTRY, 33 +#define IPIFSTATSINMCASTPKTS IPIFSTATSENTRY, 34 +#define IPIFSTATSHCINMCASTPKTS IPIFSTATSENTRY, 35 +#define IPIFSTATSINMCASTOCTETS IPIFSTATSENTRY, 36 +#define IPIFSTATSHCINMCASTOCTETS IPIFSTATSENTRY, 37 +#define IPIFSTATSOUTMCASTPKTS IPIFSTATSENTRY, 38 +#define IPIFSTATSHCOUTMCASTPKTS IPIFSTATSENTRY, 39 +#define IPIFSTATSOUTMCASTOCTETS IPIFSTATSENTRY, 40 +#define IPIFSTATSHCOUTMCASTOCTETS IPIFSTATSENTRY, 41 +#define IPIFSTATSINBCASTPKTS IPIFSTATSENTRY, 42 +#define IPIFSTATSHCINBCASTPKTS IPIFSTATSENTRY, 43 +#define IPIFSTATSOUTBCASTPKTS IPIFSTATSENTRY, 44 +#define IPIFSTATSHCOUTBCASTPKTS IPIFSTATSENTRY, 45 +#define IPIFSTATSDISCONTINUITYTIME IPIFSTATSENTRY, 46 +#define IPIFSTATSREFRESHRATE IPIFSTATSENTRY, 47 +#define IPADDRESSPREFIXTABLE IP, 32 +#define IPADDRESSPREFIXENTRY IPADDRESSPREFIXTABLE, 1 +#define IPADDRESSPREFIXIFINDEX IPADDRESSPREFIXENTRY, 1 +#define IPADDRESSPREFIXTYPE IPADDRESSPREFIXENTRY, 2 +#define IPADDRESSPREFIXPREFIX IPADDRESSPREFIXENTRY, 3 +#define IPADDRESSPREFIXLENGTH IPADDRESSPREFIXENTRY, 4 +#define IPADDRESSPREFIXORIGIN IPADDRESSPREFIXENTRY, 5 +#define IPADDRESSPREFIXONLINKFLAG IPADDRESSPREFIXENTRY, 6 +#define IPADDRESSPREFIXAUTONOMOUSFLAG IPADDRESSPREFIXENTRY, 7 +#define IPADDRESSPREFIXADVPREFERREDLIFETIME IPADDRESSPREFIXENTRY, 8 +#define IPADDRESSPREFIXADVVALIDLIFETIME IPADDRESSPREFIXENTRY, 9 +#define IPADDRESSSPINLOCK IP, 33 +#define IPADDRESSTABLE IP, 34 +#define IPADDRESSENTRY IPADDRESSTABLE, 1 +#define IPADDRESSADDRTYPE IPADDRESSENTRY, 1 +#define IPADDRESSADDR IPADDRESSENTRY, 2 +#define IPADDRESSIFINDEX IPADDRESSENTRY, 3 +#define IPADDRESSTYPE IPADDRESSENTRY, 4 +#define IPADDRESSPREFIX IPADDRESSENTRY, 5 +#define IPADDRESSORIGIN IPADDRESSENTRY, 6 +#define IPADDRESSSTATUS IPADDRESSENTRY, 7 +#define IPADDRESSCREATED IPADDRESSENTRY, 8 +#define IPADDRESSLASTCHANGED IPADDRESSENTRY, 9 +#define IPADDRESSROWSTATUS IPADDRESSENTRY, 10 +#define IPADDRESSSTORAGETYPE IPADDRESSENTRY, 11 +#define IPNETTOPHYSICALTABLE IP, 35 +#define IPNETTOPHYSICALENTRY IPNETTOPHYSICALTABLE, 1 +#define IPNETTOPHYSICALIFINDEX IPNETTOPHYSICALENTRY, 1 +#define IPNETTOPHYSICALNETADDRESSTYPE IPNETTOPHYSICALENTRY, 2 +#define IPNETTOPHYSICALNETADDRESS IPNETTOPHYSICALENTRY, 3 +#define IPNETTOPHYSICALPHYSADDRESS IPNETTOPHYSICALENTRY, 4 +#define IPNETTOPHYSICALLASTUPDATED IPNETTOPHYSICALENTRY, 5 +#define IPNETTOPHYSICALTYPE IPNETTOPHYSICALENTRY, 6 +#define IPNETTOPHYSICALSTATE IPNETTOPHYSICALENTRY, 7 +#define IPNETTOPHYSICALROWSTATUS IPNETTOPHYSICALENTRY, 8 +#define IPV6SCOPEZONEINDEXTABLE IP, 36 +#define IPV6SCOPEZONEINDEXENTRY IPV6SCOPEZONEINDEXTABLE, 1 +#define IPV6SCOPEZONEINDEXIFINDEX IPV6SCOPEZONEINDEXENTRY, 1 +#define IPV6SCOPEZONEINDEXLINKLOCAL IPV6SCOPEZONEINDEXENTRY, 2 +#define IPV6SCOPEZONEINDEX3 IPV6SCOPEZONEINDEXENTRY, 3 +#define IPV6SCOPEZONEINDEXADMINLOCAL IPV6SCOPEZONEINDEXENTRY, 4 +#define IPV6SCOPEZONEINDEXSITELOCAL IPV6SCOPEZONEINDEXENTRY, 5 +#define IPV6SCOPEZONEINDEX6 IPV6SCOPEZONEINDEXENTRY, 6 +#define IPV6SCOPEZONEINDEX7 IPV6SCOPEZONEINDEXENTRY, 7 +#define IPV6SCOPEZONEINDEXORGANIZATIONLOCAL IPV6SCOPEZONEINDEXENTRY, 8 +#define IPV6SCOPEZONEINDEX9 IPV6SCOPEZONEINDEXENTRY, 9 +#define IPV6SCOPEZONEINDEXA IPV6SCOPEZONEINDEXENTRY, 10 +#define IPV6SCOPEZONEINDEXB IPV6SCOPEZONEINDEXENTRY, 11 +#define IPV6SCOPEZONEINDEXC IPV6SCOPEZONEINDEXENTRY, 12 +#define IPV6SCOPEZONEINDEXD IPV6SCOPEZONEINDEXENTRY, 13 +#define IPDEFAULTROUTERTABLE IP, 37 +#define IPDEFAULTROUTERENTRY IPDEFAULTROUTERTABLE, 1 +#define IPDEFAULTROUTERADDRESSTYPE IPDEFAULTROUTERENTRY, 1 +#define IPDEFAULTROUTERADDRESS IPDEFAULTROUTERENTRY, 2 +#define IPDEFAULTROUTERIFINDEX IPDEFAULTROUTERENTRY, 3 +#define IPDEFAULTROUTERLIFETIME IPDEFAULTROUTERENTRY, 4 +#define IPDEFAULTROUTERPREFERENCE IPDEFAULTROUTERENTRY, 5 +#define IPV6ROUTERADVERTSPINLOCK IP, 38 +#define IPV6ROUTERADVERTTABLE IP, 39 +#define IPV6ROUTERADVERTENTRY IPV6ROUTERADVERTTABLE, 1 +#define IPV6ROUTERADVERTIFINDEX IPV6ROUTERADVERTENTRY, 1 +#define IPV6ROUTERADVERTSENDADVERTS IPV6ROUTERADVERTENTRY, 2 +#define IPV6ROUTERADVERTMAXINTERVAL IPV6ROUTERADVERTENTRY, 3 +#define IPV6ROUTERADVERTMININTERVAL IPV6ROUTERADVERTENTRY, 4 +#define IPV6ROUTERADVERTMANAGEDFLAG IPV6ROUTERADVERTENTRY, 5 +#define IPV6ROUTERADVERTOTHERCONFIGFLAG IPV6ROUTERADVERTENTRY, 6 +#define IPV6ROUTERADVERTLINKMTU IPV6ROUTERADVERTENTRY, 7 +#define IPV6ROUTERADVERTREACHABLETIME IPV6ROUTERADVERTENTRY, 8 +#define IPV6ROUTERADVERTRETRANSMITTIME IPV6ROUTERADVERTENTRY, 9 +#define IPV6ROUTERADVERTCURHOPLIMIT IPV6ROUTERADVERTENTRY, 10 +#define IPV6ROUTERADVERTDEFAULTLIFETIME IPV6ROUTERADVERTENTRY, 11 +#define IPV6ROUTERADVERTROWSTATUS IPV6ROUTERADVERTENTRY, 12 +#define ICMP AGENTX_MIB2, 5 +#define ICMPSTATSTABLE ICMP, 29 +#define ICMPSTATSENTRY ICMPSTATSTABLE, 1 +#define ICMPSTATSIPVERSION ICMPSTATSENTRY, 1 +#define ICMPSTATSINMSGS ICMPSTATSENTRY, 2 +#define ICMPSTATSINERRORS ICMPSTATSENTRY, 3 +#define ICMPSTATSOUTMSGS ICMPSTATSENTRY, 4 +#define ICMPSTATSOUTERRORS ICMPSTATSENTRY, 5 +#define ICMPMSGSTATSTABLE ICMP, 30 +#define ICMPMSGSTATSENTRY ICMPMSGSTATSTABLE, 1 +#define ICMPMSGSTATSIPVERSION ICMPMSGSTATSENTRY, 1 +#define ICMPMSGSTATSTYPE ICMPMSGSTATSENTRY, 2 +#define ICMPMSGSTATSINPKTS ICMPMSGSTATSENTRY, 3 +#define ICMPMSGSTATSOUTPKTS ICMPMSGSTATSENTRY, 4 +#define IPINRECEIVES IP, 3 +#define IPINHDRERRORS IP, 4 +#define IPINADDRERRORS IP, 5 +#define IPFORWDATAGRAMS IP, 6 +#define IPINUNKNOWNPROTOS IP, 7 +#define IPINDISCARDS IP, 8 +#define IPINDELIVERS IP, 9 +#define IPOUTREQUESTS IP, 10 +#define IPOUTDISCARDS IP, 11 +#define IPOUTNOROUTES IP, 12 +#define IPREASMREQDS IP, 14 +#define IPREASMOKS IP, 15 +#define IPREASMFAILS IP, 16 +#define IPFRAGOKS IP, 17 +#define IPFRAGFAILS IP, 18 +#define IPFRAGCREATES IP, 19 +#define IPROUTINGDISCARDS IP, 23 +#define IPADDRTABLE IP, 20 +#define IPADDRENTRY IPADDRTABLE, 1 +#define IPADENTADDR IPADDRENTRY, 1 +#define IPADENTIFINDEX IPADDRENTRY, 2 +#define IPADENTNETMASK IPADDRENTRY, 3 +#define IPADENTBCASTADDR IPADDRENTRY, 4 +#define IPADENTREASMMAXSIZE IPADDRENTRY, 5 +#define IPNETTOMEDIATABLE IP, 22 +#define IPNETTOMEDIAENTRY IPNETTOMEDIATABLE, 1 +#define IPNETTOMEDIAIFINDEX IPNETTOMEDIAENTRY, 1 +#define IPNETTOMEDIAPHYSADDRESS IPNETTOMEDIAENTRY, 2 +#define IPNETTOMEDIANETADDRESS IPNETTOMEDIAENTRY, 3 +#define IPNETTOMEDIATYPE IPNETTOMEDIAENTRY, 4 +#define ICMPINMSGS ICMP, 1 +#define ICMPINERRORS ICMP, 2 +#define ICMPINDESTUNREACHS ICMP, 3 +#define ICMPINTIMEEXCDS ICMP, 4 +#define ICMPINPARMPROBS ICMP, 5 +#define ICMPINSRCQUENCHS ICMP, 6 +#define ICMPINREDIRECTS ICMP, 7 +#define ICMPINECHOS ICMP, 8 +#define ICMPINECHOREPS ICMP, 9 +#define ICMPINTIMESTAMPS ICMP, 10 +#define ICMPINTIMESTAMPREPS ICMP, 11 +#define ICMPINADDRMASKS ICMP, 12 +#define ICMPINADDRMASKREPS ICMP, 13 +#define ICMPOUTMSGS ICMP, 14 +#define ICMPOUTERRORS ICMP, 15 +#define ICMPOUTDESTUNREACHS ICMP, 16 +#define ICMPOUTTIMEEXCDS ICMP, 17 +#define ICMPOUTPARMPROBS ICMP, 18 +#define ICMPOUTSRCQUENCHS ICMP, 19 +#define ICMPOUTREDIRECTS ICMP, 20 +#define ICMPOUTECHOS ICMP, 21 +#define ICMPOUTECHOREPS ICMP, 22 +#define ICMPOUTTIMESTAMPS ICMP, 23 +#define ICMPOUTTIMESTAMPREPS ICMP, 24 +#define ICMPOUTADDRMASKS ICMP, 25 +#define ICMPOUTADDRMASKREPS ICMP, 26 + +/* IP-FORWARD-MIB */ +#define IPFORWARD IP, 24 +#define INETCIDRROUTENUMBER IPFORWARD, 6 +#define INETCIDRROUTEDISCARDS IPFORWARD, 8 +#define INETCIDRROUTETABLE IPFORWARD, 7 +#define INETCIDRROUTEENTRY INETCIDRROUTETABLE, 1 +#define INETCIDRROUTEDESTTYPE INETCIDRROUTEENTRY, 1 +#define INETCIDRROUTEDEST INETCIDRROUTEENTRY, 2 +#define INETCIDRROUTEPFXLEN INETCIDRROUTEENTRY, 3 +#define INETCIDRROUTEPOLICY INETCIDRROUTEENTRY, 4 +#define INETCIDRROUTENEXTHOPTYPE INETCIDRROUTEENTRY, 5 +#define INETCIDRROUTENEXTHOP INETCIDRROUTEENTRY, 6 +#define INETCIDRROUTEIFINDEX INETCIDRROUTEENTRY, 7 +#define INETCIDRROUTETYPE INETCIDRROUTEENTRY, 8 +#define INETCIDRROUTEPROTO INETCIDRROUTEENTRY, 9 +#define INETCIDRROUTEAGE INETCIDRROUTEENTRY, 10 +#define INETCIDRROUTENEXTHOPAS INETCIDRROUTEENTRY, 11 +#define INETCIDRROUTEMETRIC1 INETCIDRROUTEENTRY, 12 +#define INETCIDRROUTEMETRIC2 INETCIDRROUTEENTRY, 13 +#define INETCIDRROUTEMETRIC3 INETCIDRROUTEENTRY, 14 +#define INETCIDRROUTEMETRIC4 INETCIDRROUTEENTRY, 15 +#define INETCIDRROUTEMETRIC5 INETCIDRROUTEENTRY, 16 +#define INETCIDRROUTESTATUS INETCIDRROUTEENTRY, 17 +/* Deprecated */ +#define IPCIDRROUTENUMBER IPFORWARD, 3 +#define IPCIDRROUTETABLE IPFORWARD, 4 +#define IPCIDRROUTEENTRY IPCIDRROUTETABLE, 1 +#define IPCIDRROUTEDEST IPCIDRROUTEENTRY, 1 +#define IPCIDRROUTEMASK IPCIDRROUTEENTRY, 2 +#define IPCIDRROUTETOS IPCIDRROUTEENTRY, 3 +#define IPCIDRROUTENEXTHOP IPCIDRROUTEENTRY, 4 +#define IPCIDRROUTEIFINDEX IPCIDRROUTEENTRY, 5 +#define IPCIDRROUTETYPE IPCIDRROUTEENTRY, 6 +#define IPCIDRROUTEPROTO IPCIDRROUTEENTRY, 7 +#define IPCIDRROUTEAGE IPCIDRROUTEENTRY, 8 +#define IPCIDRROUTEINFO IPCIDRROUTEENTRY, 9 +#define IPCIDRROUTENEXTHOPAS IPCIDRROUTEENTRY, 10 +#define IPCIDRROUTEMETRIC1 IPCIDRROUTEENTRY, 11 +#define IPCIDRROUTEMETRIC2 IPCIDRROUTEENTRY, 12 +#define IPCIDRROUTEMETRIC3 IPCIDRROUTEENTRY, 13 +#define IPCIDRROUTEMETRIC4 IPCIDRROUTEENTRY, 14 +#define IPCIDRROUTEMETRIC5 IPCIDRROUTEENTRY, 15 +#define IPCIDRROUTESTATUS IPCIDRROUTEENTRY, 16 +/* Obsolete */ +#define IPFORWARDNUMBER IPFORWARD, 1 +#define IPFORWARDTABLE IPFORWARD, 2 +#define IPFORWARDENTRY IPFORWARDTABLE, 1 +#define IPFORWARDDEST IPFORWARDENTRY, 1 +#define IPFORWARDMASK IPFORWARDENTRY, 2 +#define IPFORWARDPOLICY IPFORWARDENTRY, 3 +#define IPFORWARDNEXTHOP IPFORWARDENTRY, 4 +#define IPFORWARDIFINDEX IPFORWARDENTRY, 5 +#define IPFORWARDTYPE IPFORWARDENTRY, 6 +#define IPFORWARDPROTO IPFORWARDENTRY, 7 +#define IPFORWARDAGE IPFORWARDENTRY, 8 +#define IPFORWARDINFO IPFORWARDENTRY, 9 +#define IPFORWARDNEXTHOPAS IPFORWARDENTRY, 10 +#define IPFORWARDMETRIC1 IPFORWARDENTRY, 11 +#define IPFORWARDMETRIC2 IPFORWARDENTRY, 12 +#define IPFORWARDMETRIC3 IPFORWARDENTRY, 13 +#define IPFORWARDMETRIC4 IPFORWARDENTRY, 13 +#define IPFORWARDMETRIC5 IPFORWARDENTRY, 13 + +/* UCD-SNMP-MIB */ +#define UCDAVIS AGENTX_ENTERPRISES, 2021 +#define UCDEXPERIMENTAL UCDAVIS, 13 + +/* UCD-DISKIO-MIB */ +#define UCDDISKIOMIB UCDEXPERIMENTAL, 15 +#define DISKIOTABLE UCDDISKIOMIB, 1 +#define DISKIOENTRY DISKIOTABLE, 1 +#define DISKIOINDEX DISKIOENTRY, 1 +#define DISKIODEVICE DISKIOENTRY, 2 +#define DISKIONREAD DISKIOENTRY, 3 +#define DISKIONWRITTEN DISKIOENTRY, 4 +#define DISKIOREADS DISKIOENTRY, 5 +#define DISKIOWRITES DISKIOENTRY, 6 +#define DISKIOLA1 DISKIOENTRY, 9 +#define DISKIOLA5 DISKIOENTRY, 10 +#define DISKIOLA15 DISKIOENTRY, 11 +#define DISKIONREADX DISKIOENTRY, 12 +#define DISKIONWRITTENX DISKIOENTRY, 13 +#define DISKIOBUSYTIME DISKIOENTRY, 14 + +/* BRIDGE-MIB */ +#define DOT1DBRIDGE AGENTX_MIB2, 17 +#define DOT1DNOTIFICATIONS DOT1DBRIDGE, 0 +#define DOT1DBASE DOT1DBRIDGE, 1 +#define DOT1DSTP DOT1DBRIDGE, 2 +#define DOT1DSR DOT1DBRIDGE, 3 +#define DOT1DTP DOT1DBRIDGE, 4 +#define DOT1DSTATIC DOT1DBRIDGE, 5 +#define DOT1DBASEBRIDGEADDRESS DOT1DBASE, 1 +#define DOT1DBASENUMPORTS DOT1DBASE, 2 +#define DOT1DBASETYPE DOT1DBASE, 3 +#define DOT1DBASEPORTTABLE DOT1DBASE, 4 +#define DOT1DBASEPORTENTRY DOT1DBASEPORTTABLE, 1 +#define DOT1DBASEPORT DOT1DBASEPORTENTRY, 1 +#define DOT1DBASEPORTIFINDEX DOT1DBASEPORTENTRY, 2 +#define DOT1DBASEPORTCIRCUIT DOT1DBASEPORTENTRY, 3 +#define DOT1DBASEPORTDELAYEXCEEDEDDISCARDS DOT1DBASEPORTENTRY, 4 +#define DOT1DBASEPORTMTUEXCEEDEDDISCARDS DOT1DBASEPORTENTRY, 5 +#define DOT1DSTPPROTOCOLSPECIFICATION DOT1DSTP, 1 +#define DOT1DSTPPRIORITY DOT1DSTP, 2 +#define DOT1DSTPTIMESINCETOPOLOGYCHANGE DOT1DSTP, 3 +#define DOT1DSTPTOPCHANGES DOT1DSTP, 4 +#define DOT1DSTPDESIGNATEDROOT DOT1DSTP, 5 +#define DOT1DSTPROOTCOST DOT1DSTP, 6 +#define DOT1DSTPROOTPORT DOT1DSTP, 7 +#define DOT1DSTPMAXAGE DOT1DSTP, 8 +#define DOT1DSTPHELLOTIME DOT1DSTP, 9 +#define DOT1DSTPHOLDTIME DOT1DSTP, 10 +#define DOT1DSTPFORWARDDELAY DOT1DSTP, 11 +#define DOT1DSTPBRIDGEMAXAGE DOT1DSTP, 12 +#define DOT1DSTPBRIDGEHELLOTIME DOT1DSTP, 13 +#define DOT1DSTPBRIDGEFORWARDDELAY DOT1DSTP, 14 +#define DOT1DSTPPORTTABLE DOT1DSTP, 15 +#define DOT1DSTPPORTENTRY DOT1DSTPPORTTABLE, 1 +#define DOT1DSTPPORT DOT1DSTPPORTENTRY, 1 +#define DOT1DSTPPORTPRIORITY DOT1DSTPPORTENTRY, 2 +#define DOT1DSTPPORTSTATE DOT1DSTPPORTENTRY, 3 +#define DOT1DSTPPORTENABLE DOT1DSTPPORTENTRY, 4 +#define DOT1DSTPPORTPATHCOST DOT1DSTPPORTENTRY, 5 +#define DOT1DSTPPORTDESIGNATEDROOT DOT1DSTPPORTENTRY, 6 +#define DOT1DSTPPORTDESIGNATEDCOST DOT1DSTPPORTENTRY, 7 +#define DOT1DSTPPORTDESIGNATEDBRIDGE DOT1DSTPPORTENTRY, 8 +#define DOT1DSTPPORTDESIGNATEDPORT DOT1DSTPPORTENTRY, 9 +#define DOT1DSTPPORTFORWARDTRANSITIONS DOT1DSTPPORTENTRY, 10 +#define DOT1DSTPPORTPATHCOST32 DOT1DSTPPORTENTRY, 11 +#define DOT1DTPLEARNEDENTRYDISCARDS DOT1DTP, 1 +#define DOT1DTPAGINGTIME DOT1DTP, 2 +#define DOT1DTPFDBTABLE DOT1DTP, 3 +#define DOT1DTPFDBENTRY DOT1DTPFDBTABLE, 1 +#define DOT1DTPFDBADDRESS DOT1DTPFDBENTRY, 1 +#define DOT1DTPFDBPORT DOT1DTPFDBENTRY, 2 +#define DOT1DTPFDBSTATUS DOT1DTPFDBENTRY, 3 +#define DOT1DTPPORTTABLE DOT1DTP, 4 +#define DOT1DTPPORTENTRY DOT1DTPPORTTABLE, 1 +#define DOT1DTPPORT DOT1DTPPORTENTRY, 1 +#define DOT1DTPPORTMAXINFO DOT1DTPPORTENTRY, 2 +#define DOT1DTPPORTINFRAMES DOT1DTPPORTENTRY, 3 +#define DOT1DTPPORTOUTFRAMES DOT1DTPPORTENTRY, 4 +#define DOT1DTPPORTINDISCARDS DOT1DTPPORTENTRY, 5 +#define DOT1DSTATICTABLE DOT1DSTATIC, 1 +#define DOT1DSTATICENTRY DOT1DSTATICTABLE, 1 +#define DOT1DSTATICADDRESS DOT1DSTATICENTRY, 1 +#define DOT1DSTATICRECEIVEPORT DOT1DSTATICENTRY, 2 +#define DOT1DSTATICALLOWEDTOGOTO DOT1DSTATICENTRY, 3 +#define DOT1DSTATICSTATUS DOT1DSTATICENTRY, 4 +#define NEWROOT DOT1DNOTIFICATIONS, 1 +#define TOPOLOGYCHANGE DOT1DNOTIFICATIONS, 2 diff --git a/libexec/snmpd/snmpd_metrics/pf.c b/libexec/snmpd/snmpd_metrics/pf.c new file mode 100644 index 00000000000..a4b60962e32 --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/pf.c @@ -0,0 +1,501 @@ +/* $OpenBSD: pf.c,v 1.1.1.1 2022/09/01 14:20:33 martijn Exp $ */ + +/* + * Copyright (c) 2012 Joel Knight + * Copyright (c) 2002 Cedric Berger + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snmpd.h" + +int devpf = 0; + +size_t buf_esize[PFRB_MAX] = { 0, + sizeof(struct pfr_table), sizeof(struct pfr_tstats), + sizeof(struct pfr_addr), sizeof(struct pfr_astats), + sizeof(struct pfi_kif), sizeof(struct pfioc_trans_e) +}; + +void +pf_init(void) +{ + if ((devpf = open("/dev/pf", O_RDONLY)) == -1) + fatal("pf_init"); +} + +int +pf_get_stats(struct pf_status *s) +{ + extern int devpf; + + memset(s, 0, sizeof(*s)); + if (ioctl(devpf, DIOCGETSTATUS, s) == -1) { + log_warn("DIOCGETSTATUS"); + return (-1); + } + + return (0); +} + +int +pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, + int flags) +{ + struct pfioc_table io; + extern int devpf; + + if (tbl == NULL || size == NULL || *size < 0 || + (*size && addr == NULL)) + return (-1); + + bzero(&io, sizeof io); + io.pfrio_flags = flags; + io.pfrio_table = *tbl; + io.pfrio_buffer = addr; + io.pfrio_esize = sizeof(*addr); + io.pfrio_size = *size; + if (ioctl(devpf, DIOCRGETASTATS, &io) == -1) + return (-1); + *size = io.pfrio_size; + return (0); +} + +int +pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size, + int flags) +{ + struct pfioc_table io; + extern int devpf; + + if (size == NULL || *size < 0 || (*size && tbl == NULL)) + return (-1); + bzero(&io, sizeof io); + io.pfrio_flags = flags; + if (filter != NULL) + io.pfrio_table = *filter; + io.pfrio_buffer = tbl; + io.pfrio_esize = sizeof(*tbl); + io.pfrio_size = *size; + if (ioctl(devpf, DIOCRGETTSTATS, &io) == -1) + return (-1); + *size = io.pfrio_size; + return (0); +} + +int +pfr_buf_grow(struct pfr_buffer *b, int minsize) +{ + caddr_t p; + size_t bs; + + if (minsize != 0 && minsize <= b->pfrb_msize) + return (0); + bs = buf_esize[b->pfrb_type]; + if (!b->pfrb_msize) { + if (minsize < 64) + minsize = 64; + b->pfrb_caddr = calloc(bs, minsize); + if (b->pfrb_caddr == NULL) + return (-1); + b->pfrb_msize = minsize; + } else { + if (minsize == 0) + minsize = b->pfrb_msize * 2; + if (minsize < 0 || (size_t)minsize >= SIZE_MAX / bs) { + /* msize overflow */ + return (-1); + } + p = reallocarray(b->pfrb_caddr, minsize, bs); + if (p == NULL) + return (-1); + bzero(p + b->pfrb_msize * bs, (minsize - b->pfrb_msize) * bs); + b->pfrb_caddr = p; + b->pfrb_msize = minsize; + } + return (0); +} + +const void * +pfr_buf_next(struct pfr_buffer *b, const void *prev) +{ + size_t bs; + + if (b == NULL) + return (NULL); + if (b->pfrb_size == 0) + return (NULL); + if (prev == NULL) + return (b->pfrb_caddr); + bs = buf_esize[b->pfrb_type]; + if ((((const char *)prev)-((char *)b->pfrb_caddr)) / bs >= + (size_t)b->pfrb_size-1) + return (NULL); + + return (((const char *)prev) + bs); +} + +int +pfi_get_ifaces(const char *filter, struct pfi_kif *buf, int *size) +{ + struct pfioc_iface io; + extern int devpf; + + if (size == NULL || *size < 0 || (*size && buf == NULL)) { + errno = EINVAL; + return (-1); + } + bzero(&io, sizeof io); + if (filter != NULL) + if (strlcpy(io.pfiio_name, filter, sizeof(io.pfiio_name)) >= + sizeof(io.pfiio_name)) { + errno = EINVAL; + return (-1); + } + io.pfiio_buffer = buf; + io.pfiio_esize = sizeof(*buf); + io.pfiio_size = *size; + if (ioctl(devpf, DIOCIGETIFACES, &io) == -1) + return (-1); + *size = io.pfiio_size; + return (0); +} + +int +pfi_get(struct pfr_buffer *b, const char *filter) +{ + bzero(b, sizeof(struct pfr_buffer)); + b->pfrb_type = PFRB_IFACES; + for (;;) { + pfr_buf_grow(b, b->pfrb_size); + b->pfrb_size = b->pfrb_msize; + if (pfi_get_ifaces(filter, b->pfrb_caddr, &(b->pfrb_size))) + return (1); + if (b->pfrb_size <= b->pfrb_msize) + break; + } + + return (0); +} + +int +pfi_count(void) +{ + struct pfr_buffer b; + const struct pfi_kif *p; + int c = 0; + + if (pfi_get(&b, NULL)) { + free(b.pfrb_caddr); + return (-1); + } + + PFRB_FOREACH(p, &b) + c++; + + free(b.pfrb_caddr); + return (c); +} + +int +pfi_get_if(struct pfi_kif *rp, int idx) +{ + struct pfr_buffer b; + const struct pfi_kif *p; + int i = 1; + + if (pfi_get(&b, NULL)) { + free(b.pfrb_caddr); + return (-1); + } + + PFRB_FOREACH(p, &b) { + if (i == idx) + break; + i++; + } + + if (p == NULL) { + free(b.pfrb_caddr); + return (-1); + } + + bcopy(p, rp, sizeof(struct pfi_kif)); + free(b.pfrb_caddr); + + return (0); +} + +int +pft_get(struct pfr_buffer *b, struct pfr_table *filter) +{ + bzero(b, sizeof(struct pfr_buffer)); + b->pfrb_type = PFRB_TSTATS; + + for (;;) { + pfr_buf_grow(b, b->pfrb_size); + b->pfrb_size = b->pfrb_msize; + if (pfr_get_tstats(filter, b->pfrb_caddr, &(b->pfrb_size), 0)) + return (1); + if (b->pfrb_size <= b->pfrb_msize) + break; + } + + return (0); +} + +int +pft_get_table(struct pfr_tstats *rts, int idx) +{ + struct pfr_buffer b; + const struct pfr_tstats *ts; + int i = 1; + + if (pft_get(&b, NULL)) { + free(b.pfrb_caddr); + return (-1); + } + + PFRB_FOREACH(ts, &b) { + if (!(ts->pfrts_flags & PFR_TFLAG_ACTIVE)) + continue; + if (i == idx) + break; + i++; + } + + if (ts == NULL) { + free(b.pfrb_caddr); + return (-1); + } + + bcopy(ts, rts, sizeof(struct pfr_tstats)); + free(b.pfrb_caddr); + + return (0); +} + +int +pft_count(void) +{ + struct pfr_buffer b; + const struct pfr_tstats *ts; + int c = 0; + + if (pft_get(&b, NULL)) { + free(b.pfrb_caddr); + return (-1); + } + + PFRB_FOREACH(ts, &b) { + if (!(ts->pfrts_flags & PFR_TFLAG_ACTIVE)) + continue; + c++; + } + + free(b.pfrb_caddr); + return (c); +} + +int +pfta_get(struct pfr_buffer *b, struct pfr_table *filter) +{ + bzero(b, sizeof(struct pfr_buffer)); + b->pfrb_type = PFRB_ASTATS; + + for (;;) { + pfr_buf_grow(b, b->pfrb_size); + b->pfrb_size = b->pfrb_msize; + if (pfr_get_astats(filter, b->pfrb_caddr, &(b->pfrb_size), 0)) { + return (1); + } + if (b->pfrb_size <= b->pfrb_msize) + break; + } + + return (0); +} + +int +pfta_get_addr(struct pfr_astats *ras, int tblidx) +{ + struct pfr_buffer ba; + struct pfr_tstats ts; + struct pfr_table filter; + const struct pfr_astats *as; + + if (pft_get_table(&ts, tblidx)) + return (-1); + + bzero(&filter, sizeof(filter)); + if (strlcpy(filter.pfrt_name, ts.pfrts_name, + sizeof(filter.pfrt_name)) >= sizeof(filter.pfrt_name)) { + return (-1); + } + + if (pfta_get(&ba, &filter) || ba.pfrb_size == 0) { + free(ba.pfrb_caddr); + return (-1); + } + + PFRB_FOREACH(as, &ba) { + if (as->pfras_a.pfra_af != AF_INET) + continue; + if ((memcmp(&as->pfras_a.pfra_ip4addr, &ras->pfras_a.pfra_ip4addr, + sizeof(as->pfras_a.pfra_ip4addr)) == 0) + && (as->pfras_a.pfra_net == ras->pfras_a.pfra_net)) + break; + } + + if (as == NULL) { + free(ba.pfrb_caddr); + return (-1); + } + + bcopy(as, ras, sizeof(struct pfr_astats)); + free(ba.pfrb_caddr); + + return (0); +} + +int +pfta_get_nextaddr(struct pfr_astats *ras, int *tblidx) +{ + struct pfr_buffer ba; + struct pfr_tstats ts; + struct pfr_table filter; + const struct pfr_astats *as; + int i, found = 0, cmp; + + ba.pfrb_caddr = NULL; + + for (i = *tblidx; !pft_get_table(&ts, i); i++) { + bzero(&filter, sizeof(filter)); + if (strlcpy(filter.pfrt_name, ts.pfrts_name, + sizeof(filter.pfrt_name)) >= sizeof(filter.pfrt_name)) + goto fail; + + if (pfta_get(&ba, &filter) || ba.pfrb_size == 0) + goto fail; + + PFRB_FOREACH(as, &ba) { + if (as->pfras_a.pfra_af != AF_INET) + continue; + if (found) + goto found; + cmp = memcmp(&as->pfras_a.pfra_ip4addr, + &ras->pfras_a.pfra_ip4addr, + sizeof(as->pfras_a.pfra_ip4addr)); + if (cmp == 0) { + if (as->pfras_a.pfra_net == + ras->pfras_a.pfra_net) + found = 1; + if (as->pfras_a.pfra_net > + ras->pfras_a.pfra_net) + goto found; + } else if (cmp > 0) + goto found; + } + + free(ba.pfrb_caddr); + ba.pfrb_caddr = NULL; + } + + + fail: + free(ba.pfrb_caddr); + + return (-1); + + found: + bcopy(as, ras, sizeof(struct pfr_astats)); + *tblidx = i; + + free(ba.pfrb_caddr); + + return (0); +} + +int +pfta_get_first(struct pfr_astats *ras) +{ + struct pfr_buffer ba; + struct pfr_tstats ts; + struct pfr_table filter; + const struct pfr_astats *as; + + if (pft_get_table(&ts, 1)) + return (-1); + + bzero(&filter, sizeof(filter)); + if (strlcpy(filter.pfrt_name, ts.pfrts_name, + sizeof(filter.pfrt_name)) >= sizeof(filter.pfrt_name)) { + return (-1); + } + + if (pfta_get(&ba, &filter) || ba.pfrb_size == 0) { + free(ba.pfrb_caddr); + return (-1); + } + + /* take the first AF_INET addr */ + PFRB_FOREACH(as, &ba) { + if (as->pfras_a.pfra_af != AF_INET) + continue; + break; + } + + if (as == NULL) { + free(ba.pfrb_caddr); + return (-1); + } + + bcopy(as, ras, sizeof(struct pfr_astats)); + free(ba.pfrb_caddr); + + return (0); +} + diff --git a/libexec/snmpd/snmpd_metrics/snmpd.h b/libexec/snmpd/snmpd_metrics/snmpd.h new file mode 100644 index 00000000000..b764c778e7b --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/snmpd.h @@ -0,0 +1,284 @@ +/* $OpenBSD: snmpd.h,v 1.1.1.1 2022/09/01 14:20:33 martijn Exp $ */ + +/* + * Copyright (c) 2007, 2008, 2012 Reyk Floeter + * Copyright (c) 2003, 2004 Henning Brauer + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef SNMPD_H +#define SNMPD_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "log.h" + +#ifndef nitems +#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +/* + * common definitions for snmpd + */ + +#define CONF_FILE "/etc/snmpd.conf" +#define SNMPD_SOCKET "/var/run/snmpd.sock" +#define SNMPD_USER "_snmpd" +#define SNMP_PORT "161" +#define SNMPTRAP_PORT "162" + +#define SNMPD_MAXSTRLEN 484 +#define SNMPD_MAXCOMMUNITYLEN SNMPD_MAXSTRLEN +#define SNMPD_MAXVARBIND 0x7fffffff +#define SNMPD_MAXVARBINDLEN 1210 +#define SNMPD_MAXENGINEIDLEN 32 +#define SNMPD_MAXUSERNAMELEN 32 +#define SNMPD_MAXCONTEXNAMELEN 32 + +#define SNMP_USM_MAXDIGESTLEN 48 +#define SNMP_USM_SALTLEN 8 +#define SNMP_USM_KEYLEN 64 +#define SNMP_CIPHER_KEYLEN 16 + +#define SMALL_READ_BUF_SIZE 1024 +#define READ_BUF_SIZE 65535 +#define RT_BUF_SIZE 16384 +#define MAX_RTSOCK_BUF (2 * 1024 * 1024) + +#define SNMP_ENGINEID_OLD 0x00 +#define SNMP_ENGINEID_NEW 0x80 /* RFC3411 */ + +#define SNMP_ENGINEID_FMT_IPv4 1 +#define SNMP_ENGINEID_FMT_IPv6 2 +#define SNMP_ENGINEID_FMT_MAC 3 +#define SNMP_ENGINEID_FMT_TEXT 4 +#define SNMP_ENGINEID_FMT_OCT 5 +#define SNMP_ENGINEID_FMT_HH 129 + +#define PEN_OPENBSD 30155 + +#if DEBUG +#define DPRINTF log_debug +#else +#define DPRINTF(x...) do {} while(0) +#endif + +/* + * kroute + */ + +struct kroute_node; +struct kroute6_node; +RB_HEAD(kroute_tree, kroute_node); +RB_HEAD(kroute6_tree, kroute6_node); + +struct ktable { + struct kroute_tree krt; + struct kroute6_tree krt6; + u_int rtableid; + u_int rdomain; +}; + +union kaddr { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + struct sockaddr_dl sdl; + char pad[32]; +}; + +struct kroute { + struct in_addr prefix; + struct in_addr nexthop; + u_long ticks; + u_int16_t flags; + u_short if_index; + u_int8_t prefixlen; + u_int8_t priority; +}; + +struct kroute6 { + struct in6_addr prefix; + struct in6_addr nexthop; + u_long ticks; + u_int16_t flags; + u_short if_index; + u_int8_t prefixlen; + u_int8_t priority; +}; + +struct kif_addr { + u_short if_index; + union kaddr addr; + union kaddr mask; + union kaddr dstbrd; + + TAILQ_ENTRY(kif_addr) entry; + RB_ENTRY(kif_addr) node; +}; + +struct kif_arp { + u_short flags; + u_short if_index; + union kaddr addr; + union kaddr target; + + TAILQ_ENTRY(kif_arp) entry; +}; + +struct kif { + char if_name[IF_NAMESIZE]; + char if_descr[IFDESCRSIZE]; + u_int8_t if_lladdr[ETHER_ADDR_LEN]; + struct if_data if_data; + u_long if_ticks; + int if_flags; + u_short if_index; +}; +#define if_mtu if_data.ifi_mtu +#define if_type if_data.ifi_type +#define if_addrlen if_data.ifi_addrlen +#define if_hdrlen if_data.ifi_hdrlen +#define if_metric if_data.ifi_metric +#define if_link_state if_data.ifi_link_state +#define if_baudrate if_data.ifi_baudrate +#define if_ipackets if_data.ifi_ipackets +#define if_ierrors if_data.ifi_ierrors +#define if_opackets if_data.ifi_opackets +#define if_oerrors if_data.ifi_oerrors +#define if_collisions if_data.ifi_collisions +#define if_ibytes if_data.ifi_ibytes +#define if_obytes if_data.ifi_obytes +#define if_imcasts if_data.ifi_imcasts +#define if_omcasts if_data.ifi_omcasts +#define if_iqdrops if_data.ifi_iqdrops +#define if_oqdrops if_data.ifi_oqdrops +#define if_noproto if_data.ifi_noproto +#define if_lastchange if_data.ifi_lastchange +#define if_capabilities if_data.ifi_capabilities + +#define F_CONNECTED 0x0001 +#define F_STATIC 0x0002 +#define F_BLACKHOLE 0x0004 +#define F_REJECT 0x0008 +#define F_DYNAMIC 0x0010 + +/* + * pf + */ + +enum { PFRB_TABLES = 1, PFRB_TSTATS, PFRB_ADDRS, PFRB_ASTATS, + PFRB_IFACES, PFRB_TRANS, PFRB_MAX }; + +enum { IN, OUT }; +enum { IPV4, IPV6 }; +enum { PASS, BLOCK }; + +enum { PFI_IFTYPE_GROUP, PFI_IFTYPE_INSTANCE }; + +struct pfr_buffer { + int pfrb_type; /* type of content, see enum above */ + int pfrb_size; /* number of objects in buffer */ + int pfrb_msize; /* maximum number of objects in buffer */ + void *pfrb_caddr; /* malloc'ated memory area */ +}; + +#define PFRB_FOREACH(var, buf) \ + for ((var) = pfr_buf_next((buf), NULL); \ + (var) != NULL; \ + (var) = pfr_buf_next((buf), (var))) + +/* + * daemon structures + */ + +struct snmpd { + int sc_ncpu; + int64_t *sc_cpustates; + int sc_rtfilter; +}; + +extern struct snmpd *snmpd_env; + +/* mib.c */ +u_long smi_getticks(void); + +/* kroute.c */ +void kr_init(void); +void kr_shutdown(void); + +u_int kr_ifnumber(void); +u_long kr_iflastchange(void); +int kr_updateif(u_int); +u_long kr_routenumber(void); + +struct kif *kr_getif(u_short); +struct kif *kr_getnextif(u_short); +struct kif_addr *kr_getaddr(struct sockaddr *); +struct kif_addr *kr_getnextaddr(struct sockaddr *); + +struct kroute *kroute_first(void); +struct kroute *kroute_getaddr(in_addr_t, u_int8_t, u_int8_t, int); + +struct kif_arp *karp_first(u_short); +struct kif_arp *karp_getaddr(struct sockaddr *, u_short, int); + +/* pf.c */ +void pf_init(void); +int pf_get_stats(struct pf_status *); +int pfr_get_astats(struct pfr_table *, struct pfr_astats *, + int *, int); +int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, + int *, int); +int pfr_buf_grow(struct pfr_buffer *, int); +const void *pfr_buf_next(struct pfr_buffer *, const void *); +int pfi_get_ifaces(const char *, struct pfi_kif *, int *); +int pfi_get(struct pfr_buffer *, const char *); +int pfi_count(void); +int pfi_get_if(struct pfi_kif *, int); +int pft_get(struct pfr_buffer *, struct pfr_table *); +int pft_count(void); +int pft_get_table(struct pfr_tstats *, int); +int pfta_get(struct pfr_buffer *, struct pfr_table *); +int pfta_get_addr(struct pfr_astats *, int); +int pfta_get_nextaddr(struct pfr_astats *, int *); +int pfta_get_first(struct pfr_astats *); + +/* timer.c */ +void timer_init(void); + +/* util.c */ +ssize_t sendtofrom(int, void *, size_t, int, struct sockaddr *, + socklen_t, struct sockaddr *, socklen_t); +ssize_t recvfromto(int, void *, size_t, int, struct sockaddr *, + socklen_t *, struct sockaddr *, socklen_t *); +const char *log_in6addr(const struct in6_addr *); +const char *print_host(struct sockaddr_storage *, char *, size_t); +char *tohexstr(u_int8_t *, int); +uint8_t *fromhexstr(uint8_t *, const char *, size_t); + +#endif /* SNMPD_H */ diff --git a/libexec/snmpd/snmpd_metrics/snmpd_metrics.8 b/libexec/snmpd/snmpd_metrics/snmpd_metrics.8 new file mode 100644 index 00000000000..dbfb0af4e7f --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/snmpd_metrics.8 @@ -0,0 +1,110 @@ +.\" $OpenBSD: snmpd_metrics.8,v 1.1.1.1 2022/09/01 14:20:34 martijn Exp $ +.\" +.\" Copyright (c) 2022 Martijn van Duren +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: September 1 2022 $ +.Dt SNMPD_METRICS 8 +.Os +.Sh NAME +.Nm snmpd_metrics +.Nd Export snmpd MIB data. +.Sh SYNOPSIS +.Nm +.Op Fl dv +.Op Fl C Ar option +.Op Fl c Ar context +.Op Fl s Ar path +.Sh DESCRIPTION +.Nm +exports the following +.Pq partial +MIBs via an AgentX compatible +.Pq snmp +daemon: +HOST-RESOURCES-MIB, IF-MIB, OPENBSD-PF-MIB, OPENBSD-SENSORS-MIB, +OPENBSD-CARP-MIB, OPENBSD-MEM-MIB, IP-MIB, IP-FORWARD-MIB, +UCD-DISKIO-MIB, and BRIDGE-MIB. +The options are as follows: +.Bl -tag -width Ds +.It Fl C Ar option +Enable MIB-specific options. Currently only +.Ic filter-routes +is supported. +If set ask the kernel to filter route update messages on the routing socket. +Routing table information will not be available, but CPU use will be +reduced during bulk updates. +.It Fl c Ar context +The SNMPv3 context and can usually be omitted. +.It Fl d +Do not daemonize and log to +.Em stderr . +.It Fl s Ar path +Connect to the AgentX master via +.Ar path . +It defaults to +.Pa /var/agentx/master . +.It Fl v +Produce more verbose output. +.El +.Sh SEE ALSO +.Xr snmpd 8 +.Xr snmp 1 +.Sh STANDARDS +.Rs +.%A P. Grillo +.%A WeSync.com +.%D March 2000 +.%R RFC 2790 +.%T Host Resources MIB +.Re +.Pp +.Rs +.%A K. McCloghrie +.%A Cisco Systems +.%A F. Kastenholz +.%A Argon Networks +.%D June 2000 +.%R RFC 2863 +.%T The Interfaces Group MIB +.Re +.Pp +.Rs +.%A S. Routhier, Ed. +.%D April 2006 +.%R RFC 4293 +.%T Management Information Base for the Internet Protocol (IP) +.Re +.Pp +.Rs +.%A B. Haberman +.%A Johns Hopkins University +.%D April 2006 +.%R RFC 4292 +.%T IP Forwarding Table MIB +.Re +.Pp +.Rs +.%A K. Norseth, Ed. +.%A L-3 Communications +.%A E. Bell, Ed. +.%A 3Com Europe Limited +.%D September 2005 +.%R RFC 4188 +.%T Definitions of Managed Objects for Bridges +.Re +.Sh AUTHORS +.An Martijn van Duren Aq Mt martijn@openbsd.org +.An Joel Knight Aq Mt joel@openbsd.org +.An Reyk Floeter Aq Mt reyk@openbsd.org diff --git a/libexec/snmpd/snmpd_metrics/timer.c b/libexec/snmpd/snmpd_metrics/timer.c new file mode 100644 index 00000000000..e0a70e9f642 --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/timer.c @@ -0,0 +1,169 @@ +/* $OpenBSD: timer.c,v 1.1.1.1 2022/09/01 14:20:33 martijn Exp $ */ + +/* + * Copyright (c) 2008 Reyk Floeter + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snmpd.h" +#include "mib.h" + +void timer_cpu(int, short, void *); +int percentages(int, int64_t *, int64_t *, int64_t *, int64_t *); + +static int64_t **cp_time; +static int64_t **cp_old; +static int64_t **cp_diff; +struct event cpu_ev; + +void +timer_cpu(int fd, short event, void *arg) +{ + struct event *ev = (struct event *)arg; + struct timeval tv = { 60, 0 }; /* every 60 seconds */ + int mib[3] = { CTL_KERN, KERN_CPTIME2, 0 }, n; + size_t len; + int64_t *cptime2; + + len = CPUSTATES * sizeof(int64_t); + for (n = 0; n < snmpd_env->sc_ncpu; n++) { + mib[2] = n; + cptime2 = snmpd_env->sc_cpustates + (CPUSTATES * n); + if (sysctl(mib, 3, cp_time[n], &len, NULL, 0) == -1) + continue; + (void)percentages(CPUSTATES, cptime2, cp_time[n], + cp_old[n], cp_diff[n]); +#ifdef DEBUG + log_debug("timer_cpu: cpu%d %lld%% idle in %llds", n, + (cptime2[CP_IDLE] > 1000 ? + 1000 : (cptime2[CP_IDLE] / 10)), (long long) tv.tv_sec); +#endif + } + + evtimer_add(ev, &tv); +} + +void +timer_init(void) +{ + int mib[] = { CTL_HW, HW_NCPU }, i; + size_t len; + + len = sizeof(snmpd_env->sc_ncpu); + if (sysctl(mib, 2, &snmpd_env->sc_ncpu, &len, NULL, 0) == -1) + fatal("sysctl"); + + snmpd_env->sc_cpustates = calloc(snmpd_env->sc_ncpu, + CPUSTATES * sizeof(int64_t)); + cp_time = calloc(snmpd_env->sc_ncpu, sizeof(int64_t *)); + cp_old = calloc(snmpd_env->sc_ncpu, sizeof(int64_t *)); + cp_diff = calloc(snmpd_env->sc_ncpu, sizeof(int64_t *)); + if (snmpd_env->sc_cpustates == NULL || + cp_time == NULL || cp_old == NULL || cp_diff == NULL) + fatal("calloc"); + for (i = 0; i < snmpd_env->sc_ncpu; i++) { + cp_time[i] = calloc(CPUSTATES, sizeof(int64_t)); + cp_old[i] = calloc(CPUSTATES, sizeof(int64_t)); + cp_diff[i] = calloc(CPUSTATES, sizeof(int64_t)); + if (cp_time[i] == NULL || cp_old[i] == NULL || + cp_diff[i] == NULL) + fatal("calloc"); + } + + evtimer_set(&cpu_ev, timer_cpu, &cpu_ev); + timer_cpu(0, EV_TIMEOUT, &cpu_ev); +} + +/* + * percentages() function to calculate CPU utilization. + * Source code derived from the top(1) utility: + * + * Copyright (c) 1984, 1989, William LeFebvre, Rice University + * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS EMPLOYER BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +int +percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs) +{ + int64_t change, total_change, *dp, half_total; + int i; + + /* initialization */ + total_change = 0; + dp = diffs; + + /* calculate changes for each state and the overall change */ + for (i = 0; i < cnt; i++) { + if ((change = *new - *old) < 0) { + /* this only happens when the counter wraps */ + change = (*new - *old); + } + total_change += (*dp++ = change); + *old++ = *new++; + } + + /* avoid divide by zero potential */ + if (total_change == 0) + total_change = 1; + + /* calculate percentages based on overall change, rounding up */ + half_total = total_change / 2l; + for (i = 0; i < cnt; i++) + *out++ = ((*diffs++ * 1000 + half_total) / total_change); + + /* return the total in case the caller wants to use it */ + return (total_change); +} diff --git a/libexec/snmpd/snmpd_metrics/util.c b/libexec/snmpd/snmpd_metrics/util.c new file mode 100644 index 00000000000..bfb55b45718 --- /dev/null +++ b/libexec/snmpd/snmpd_metrics/util.c @@ -0,0 +1,229 @@ +/* $OpenBSD: util.c,v 1.1.1.1 2022/09/01 14:20:33 martijn Exp $ */ +/* + * Copyright (c) 2014 Bret Stephen Lambert + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "snmpd.h" + +ssize_t +sendtofrom(int s, void *buf, size_t len, int flags, struct sockaddr *to, + socklen_t tolen, struct sockaddr *from, socklen_t fromlen) +{ + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + struct in6_pktinfo *pkt6; + struct sockaddr_in *in; + struct sockaddr_in6 *in6; + union { + struct cmsghdr hdr; + char inbuf[CMSG_SPACE(sizeof(struct in_addr))]; + char in6buf[CMSG_SPACE(sizeof(struct in6_pktinfo))]; + } cmsgbuf; + + bzero(&msg, sizeof(msg)); + bzero(&cmsgbuf, sizeof(cmsgbuf)); + + iov.iov_base = buf; + iov.iov_len = len; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = to; + msg.msg_namelen = tolen; + msg.msg_control = &cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + + cmsg = CMSG_FIRSTHDR(&msg); + switch (to->sa_family) { + case AF_INET: + msg.msg_controllen = sizeof(cmsgbuf.inbuf); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr)); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_SENDSRCADDR; + in = (struct sockaddr_in *)from; + memcpy(CMSG_DATA(cmsg), &in->sin_addr, sizeof(struct in_addr)); + break; + case AF_INET6: + msg.msg_controllen = sizeof(cmsgbuf.in6buf); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); + cmsg->cmsg_level = IPPROTO_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + in6 = (struct sockaddr_in6 *)from; + pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg); + pkt6->ipi6_addr = in6->sin6_addr; + break; + } + + return sendmsg(s, &msg, flags); +} + +ssize_t +recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from, + socklen_t *fromlen, struct sockaddr *to, socklen_t *tolen) +{ + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + struct in6_pktinfo *pkt6; + struct sockaddr_in *in; + struct sockaddr_in6 *in6; + ssize_t ret; + union { + struct cmsghdr hdr; + char buf[CMSG_SPACE(sizeof(struct sockaddr_storage))]; + } cmsgbuf; + + bzero(&msg, sizeof(msg)); + bzero(&cmsgbuf.buf, sizeof(cmsgbuf.buf)); + + iov.iov_base = buf; + iov.iov_len = len; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = from; + msg.msg_namelen = *fromlen; + msg.msg_control = &cmsgbuf.buf; + msg.msg_controllen = sizeof(cmsgbuf.buf); + + if ((ret = recvmsg(s, &msg, flags)) == -1) + return (-1); + + *fromlen = from->sa_len; + *tolen = 0; + + if (getsockname(s, to, tolen) != 0) + *tolen = 0; + + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + switch (from->sa_family) { + case AF_INET: + if (cmsg->cmsg_level == IPPROTO_IP && + cmsg->cmsg_type == IP_RECVDSTADDR) { + in = (struct sockaddr_in *)to; + in->sin_family = AF_INET; + in->sin_len = *tolen = sizeof(*in); + memcpy(&in->sin_addr, CMSG_DATA(cmsg), + sizeof(struct in_addr)); + } + break; + case AF_INET6: + if (cmsg->cmsg_level == IPPROTO_IPV6 && + cmsg->cmsg_type == IPV6_PKTINFO) { + in6 = (struct sockaddr_in6 *)to; + in6->sin6_family = AF_INET6; + in6->sin6_len = *tolen = sizeof(*in6); + pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg); + memcpy(&in6->sin6_addr, &pkt6->ipi6_addr, + sizeof(struct in6_addr)); + if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr)) + in6->sin6_scope_id = + pkt6->ipi6_ifindex; + } + break; + } + } + + return (ret); +} + +const char * +log_in6addr(const struct in6_addr *addr) +{ + static char buf[NI_MAXHOST]; + struct sockaddr_in6 sa_in6; + u_int16_t tmp16; + + bzero(&sa_in6, sizeof(sa_in6)); + sa_in6.sin6_len = sizeof(sa_in6); + sa_in6.sin6_family = AF_INET6; + memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr)); + + /* XXX thanks, KAME, for this ugliness... adopted from route/show.c */ + if (IN6_IS_ADDR_LINKLOCAL(&sa_in6.sin6_addr) || + IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6.sin6_addr)) { + memcpy(&tmp16, &sa_in6.sin6_addr.s6_addr[2], sizeof(tmp16)); + sa_in6.sin6_scope_id = ntohs(tmp16); + sa_in6.sin6_addr.s6_addr[2] = 0; + sa_in6.sin6_addr.s6_addr[3] = 0; + } + + return (print_host((struct sockaddr_storage *)&sa_in6, buf, + NI_MAXHOST)); +} + +const char * +print_host(struct sockaddr_storage *ss, char *buf, size_t len) +{ + if (getnameinfo((struct sockaddr *)ss, ss->ss_len, + buf, len, NULL, 0, NI_NUMERICHOST) != 0) { + buf[0] = '\0'; + return (NULL); + } + return (buf); +} + +char * +tohexstr(uint8_t *bstr, int len) +{ +#define MAXHEXSTRLEN 256 + static char hstr[2 * MAXHEXSTRLEN + 1]; + static const char hex[] = "0123456789abcdef"; + int i; + + if (len > MAXHEXSTRLEN) + len = MAXHEXSTRLEN; /* truncate */ + for (i = 0; i < len; i++) { + hstr[i + i] = hex[bstr[i] >> 4]; + hstr[i + i + 1] = hex[bstr[i] & 0x0f]; + } + hstr[i + i] = '\0'; + return hstr; +} + +uint8_t * +fromhexstr(uint8_t *bstr, const char *hstr, size_t len) +{ + size_t i; + char hex[3]; + + if (len % 2 != 0) + return NULL; + + hex[2] = '\0'; + for (i = 0; i < len; i += 2) { + if (!isxdigit(hstr[i]) || !isxdigit(hstr[i + 1])) + return NULL; + hex[0] = hstr[i]; + hex[1] = hstr[i + 1]; + bstr[i / 2] = strtol(hex, NULL, 16); + } + + return bstr; +}