Bug Summary

File:src/usr.sbin/snmpd/traphandler.c
Warning:line 259, column 7
Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name traphandler.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/snmpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/snmpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/snmpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/snmpd/traphandler.c
1/* $OpenBSD: traphandler.c,v 1.22 2021/10/21 08:17:34 martijn Exp $ */
2
3/*
4 * Copyright (c) 2014 Bret Stephen Lambert <blambert@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/queue.h>
20#include <sys/socket.h>
21#include <sys/stat.h>
22#include <sys/types.h>
23#include <sys/uio.h>
24#include <sys/wait.h>
25
26#include <net/if.h>
27#include <netinet/in.h>
28#include <arpa/inet.h>
29
30#include <ber.h>
31#include <errno(*__errno()).h>
32#include <event.h>
33#include <fcntl.h>
34#include <imsg.h>
35#include <netdb.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <syslog.h>
40#include <unistd.h>
41#include <pwd.h>
42
43#include "snmpd.h"
44#include "mib.h"
45
46int traphandler_priv_recvmsg(struct privsep_proc *, struct imsg *);
47int traphandler_fork_handler(struct privsep_proc *, struct imsg *);
48struct ber_element *
49 traphandler_v1translate(struct snmp_message *, int);
50int trapcmd_cmp(struct trapcmd *, struct trapcmd *);
51void trapcmd_exec(struct trapcmd *, struct sockaddr *,
52 struct ber_element *);
53
54char *traphandler_hostname(struct sockaddr *, int);
55
56RB_PROTOTYPE(trapcmd_tree, trapcmd, cmd_entry, trapcmd_cmp)void trapcmd_tree_RB_INSERT_COLOR(struct trapcmd_tree *, struct
trapcmd *); void trapcmd_tree_RB_REMOVE_COLOR(struct trapcmd_tree
*, struct trapcmd *, struct trapcmd *); struct trapcmd *trapcmd_tree_RB_REMOVE
(struct trapcmd_tree *, struct trapcmd *); struct trapcmd *trapcmd_tree_RB_INSERT
(struct trapcmd_tree *, struct trapcmd *); struct trapcmd *trapcmd_tree_RB_FIND
(struct trapcmd_tree *, struct trapcmd *); struct trapcmd *trapcmd_tree_RB_NFIND
(struct trapcmd_tree *, struct trapcmd *); struct trapcmd *trapcmd_tree_RB_NEXT
(struct trapcmd *); struct trapcmd *trapcmd_tree_RB_PREV(struct
trapcmd *); struct trapcmd *trapcmd_tree_RB_MINMAX(struct trapcmd_tree
*, int);
57RB_GENERATE(trapcmd_tree, trapcmd, cmd_entry, trapcmd_cmp)void trapcmd_tree_RB_INSERT_COLOR(struct trapcmd_tree *head, struct
trapcmd *elm) { struct trapcmd *parent, *gparent, *tmp; while
((parent = (elm)->cmd_entry.rbe_parent) && (parent
)->cmd_entry.rbe_color == 1) { gparent = (parent)->cmd_entry
.rbe_parent; if (parent == (gparent)->cmd_entry.rbe_left) {
tmp = (gparent)->cmd_entry.rbe_right; if (tmp && (
tmp)->cmd_entry.rbe_color == 1) { (tmp)->cmd_entry.rbe_color
= 0; do { (parent)->cmd_entry.rbe_color = 0; (gparent)->
cmd_entry.rbe_color = 1; } while (0); elm = gparent; continue
; } if ((parent)->cmd_entry.rbe_right == elm) { do { (tmp)
= (parent)->cmd_entry.rbe_right; if (((parent)->cmd_entry
.rbe_right = (tmp)->cmd_entry.rbe_left)) { ((tmp)->cmd_entry
.rbe_left)->cmd_entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->cmd_entry.rbe_parent = (parent)->cmd_entry
.rbe_parent)) { if ((parent) == ((parent)->cmd_entry.rbe_parent
)->cmd_entry.rbe_left) ((parent)->cmd_entry.rbe_parent)
->cmd_entry.rbe_left = (tmp); else ((parent)->cmd_entry
.rbe_parent)->cmd_entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->cmd_entry.rbe_left = (parent); (parent
)->cmd_entry.rbe_parent = (tmp); do {} while (0); if (((tmp
)->cmd_entry.rbe_parent)) do {} while (0); } while (0); tmp
= parent; parent = elm; elm = tmp; } do { (parent)->cmd_entry
.rbe_color = 0; (gparent)->cmd_entry.rbe_color = 1; } while
(0); do { (tmp) = (gparent)->cmd_entry.rbe_left; if (((gparent
)->cmd_entry.rbe_left = (tmp)->cmd_entry.rbe_right)) { (
(tmp)->cmd_entry.rbe_right)->cmd_entry.rbe_parent = (gparent
); } do {} while (0); if (((tmp)->cmd_entry.rbe_parent = (
gparent)->cmd_entry.rbe_parent)) { if ((gparent) == ((gparent
)->cmd_entry.rbe_parent)->cmd_entry.rbe_left) ((gparent
)->cmd_entry.rbe_parent)->cmd_entry.rbe_left = (tmp); else
((gparent)->cmd_entry.rbe_parent)->cmd_entry.rbe_right
= (tmp); } else (head)->rbh_root = (tmp); (tmp)->cmd_entry
.rbe_right = (gparent); (gparent)->cmd_entry.rbe_parent = (
tmp); do {} while (0); if (((tmp)->cmd_entry.rbe_parent)) do
{} while (0); } while (0); } else { tmp = (gparent)->cmd_entry
.rbe_left; if (tmp && (tmp)->cmd_entry.rbe_color ==
1) { (tmp)->cmd_entry.rbe_color = 0; do { (parent)->cmd_entry
.rbe_color = 0; (gparent)->cmd_entry.rbe_color = 1; } while
(0); elm = gparent; continue; } if ((parent)->cmd_entry.rbe_left
== elm) { do { (tmp) = (parent)->cmd_entry.rbe_left; if (
((parent)->cmd_entry.rbe_left = (tmp)->cmd_entry.rbe_right
)) { ((tmp)->cmd_entry.rbe_right)->cmd_entry.rbe_parent
= (parent); } do {} while (0); if (((tmp)->cmd_entry.rbe_parent
= (parent)->cmd_entry.rbe_parent)) { if ((parent) == ((parent
)->cmd_entry.rbe_parent)->cmd_entry.rbe_left) ((parent)
->cmd_entry.rbe_parent)->cmd_entry.rbe_left = (tmp); else
((parent)->cmd_entry.rbe_parent)->cmd_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->cmd_entry
.rbe_right = (parent); (parent)->cmd_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->cmd_entry.rbe_parent)) do {
} while (0); } while (0); tmp = parent; parent = elm; elm = tmp
; } do { (parent)->cmd_entry.rbe_color = 0; (gparent)->
cmd_entry.rbe_color = 1; } while (0); do { (tmp) = (gparent)->
cmd_entry.rbe_right; if (((gparent)->cmd_entry.rbe_right =
(tmp)->cmd_entry.rbe_left)) { ((tmp)->cmd_entry.rbe_left
)->cmd_entry.rbe_parent = (gparent); } do {} while (0); if
(((tmp)->cmd_entry.rbe_parent = (gparent)->cmd_entry.rbe_parent
)) { if ((gparent) == ((gparent)->cmd_entry.rbe_parent)->
cmd_entry.rbe_left) ((gparent)->cmd_entry.rbe_parent)->
cmd_entry.rbe_left = (tmp); else ((gparent)->cmd_entry.rbe_parent
)->cmd_entry.rbe_right = (tmp); } else (head)->rbh_root
= (tmp); (tmp)->cmd_entry.rbe_left = (gparent); (gparent)
->cmd_entry.rbe_parent = (tmp); do {} while (0); if (((tmp
)->cmd_entry.rbe_parent)) do {} while (0); } while (0); } }
(head->rbh_root)->cmd_entry.rbe_color = 0; } void trapcmd_tree_RB_REMOVE_COLOR
(struct trapcmd_tree *head, struct trapcmd *parent, struct trapcmd
*elm) { struct trapcmd *tmp; while ((elm == ((void *)0) || (
elm)->cmd_entry.rbe_color == 0) && elm != (head)->
rbh_root) { if ((parent)->cmd_entry.rbe_left == elm) { tmp
= (parent)->cmd_entry.rbe_right; if ((tmp)->cmd_entry.
rbe_color == 1) { do { (tmp)->cmd_entry.rbe_color = 0; (parent
)->cmd_entry.rbe_color = 1; } while (0); do { (tmp) = (parent
)->cmd_entry.rbe_right; if (((parent)->cmd_entry.rbe_right
= (tmp)->cmd_entry.rbe_left)) { ((tmp)->cmd_entry.rbe_left
)->cmd_entry.rbe_parent = (parent); } do {} while (0); if (
((tmp)->cmd_entry.rbe_parent = (parent)->cmd_entry.rbe_parent
)) { if ((parent) == ((parent)->cmd_entry.rbe_parent)->
cmd_entry.rbe_left) ((parent)->cmd_entry.rbe_parent)->cmd_entry
.rbe_left = (tmp); else ((parent)->cmd_entry.rbe_parent)->
cmd_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->cmd_entry.rbe_left = (parent); (parent)->cmd_entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->cmd_entry
.rbe_parent)) do {} while (0); } while (0); tmp = (parent)->
cmd_entry.rbe_right; } if (((tmp)->cmd_entry.rbe_left == (
(void *)0) || ((tmp)->cmd_entry.rbe_left)->cmd_entry.rbe_color
== 0) && ((tmp)->cmd_entry.rbe_right == ((void *)
0) || ((tmp)->cmd_entry.rbe_right)->cmd_entry.rbe_color
== 0)) { (tmp)->cmd_entry.rbe_color = 1; elm = parent; parent
= (elm)->cmd_entry.rbe_parent; } else { if ((tmp)->cmd_entry
.rbe_right == ((void *)0) || ((tmp)->cmd_entry.rbe_right)->
cmd_entry.rbe_color == 0) { struct trapcmd *oleft; if ((oleft
= (tmp)->cmd_entry.rbe_left)) (oleft)->cmd_entry.rbe_color
= 0; (tmp)->cmd_entry.rbe_color = 1; do { (oleft) = (tmp)
->cmd_entry.rbe_left; if (((tmp)->cmd_entry.rbe_left = (
oleft)->cmd_entry.rbe_right)) { ((oleft)->cmd_entry.rbe_right
)->cmd_entry.rbe_parent = (tmp); } do {} while (0); if (((
oleft)->cmd_entry.rbe_parent = (tmp)->cmd_entry.rbe_parent
)) { if ((tmp) == ((tmp)->cmd_entry.rbe_parent)->cmd_entry
.rbe_left) ((tmp)->cmd_entry.rbe_parent)->cmd_entry.rbe_left
= (oleft); else ((tmp)->cmd_entry.rbe_parent)->cmd_entry
.rbe_right = (oleft); } else (head)->rbh_root = (oleft); (
oleft)->cmd_entry.rbe_right = (tmp); (tmp)->cmd_entry.rbe_parent
= (oleft); do {} while (0); if (((oleft)->cmd_entry.rbe_parent
)) do {} while (0); } while (0); tmp = (parent)->cmd_entry
.rbe_right; } (tmp)->cmd_entry.rbe_color = (parent)->cmd_entry
.rbe_color; (parent)->cmd_entry.rbe_color = 0; if ((tmp)->
cmd_entry.rbe_right) ((tmp)->cmd_entry.rbe_right)->cmd_entry
.rbe_color = 0; do { (tmp) = (parent)->cmd_entry.rbe_right
; if (((parent)->cmd_entry.rbe_right = (tmp)->cmd_entry
.rbe_left)) { ((tmp)->cmd_entry.rbe_left)->cmd_entry.rbe_parent
= (parent); } do {} while (0); if (((tmp)->cmd_entry.rbe_parent
= (parent)->cmd_entry.rbe_parent)) { if ((parent) == ((parent
)->cmd_entry.rbe_parent)->cmd_entry.rbe_left) ((parent)
->cmd_entry.rbe_parent)->cmd_entry.rbe_left = (tmp); else
((parent)->cmd_entry.rbe_parent)->cmd_entry.rbe_right =
(tmp); } else (head)->rbh_root = (tmp); (tmp)->cmd_entry
.rbe_left = (parent); (parent)->cmd_entry.rbe_parent = (tmp
); do {} while (0); if (((tmp)->cmd_entry.rbe_parent)) do {
} while (0); } while (0); elm = (head)->rbh_root; break; }
} else { tmp = (parent)->cmd_entry.rbe_left; if ((tmp)->
cmd_entry.rbe_color == 1) { do { (tmp)->cmd_entry.rbe_color
= 0; (parent)->cmd_entry.rbe_color = 1; } while (0); do {
(tmp) = (parent)->cmd_entry.rbe_left; if (((parent)->cmd_entry
.rbe_left = (tmp)->cmd_entry.rbe_right)) { ((tmp)->cmd_entry
.rbe_right)->cmd_entry.rbe_parent = (parent); } do {} while
(0); if (((tmp)->cmd_entry.rbe_parent = (parent)->cmd_entry
.rbe_parent)) { if ((parent) == ((parent)->cmd_entry.rbe_parent
)->cmd_entry.rbe_left) ((parent)->cmd_entry.rbe_parent)
->cmd_entry.rbe_left = (tmp); else ((parent)->cmd_entry
.rbe_parent)->cmd_entry.rbe_right = (tmp); } else (head)->
rbh_root = (tmp); (tmp)->cmd_entry.rbe_right = (parent); (
parent)->cmd_entry.rbe_parent = (tmp); do {} while (0); if
(((tmp)->cmd_entry.rbe_parent)) do {} while (0); } while (
0); tmp = (parent)->cmd_entry.rbe_left; } if (((tmp)->cmd_entry
.rbe_left == ((void *)0) || ((tmp)->cmd_entry.rbe_left)->
cmd_entry.rbe_color == 0) && ((tmp)->cmd_entry.rbe_right
== ((void *)0) || ((tmp)->cmd_entry.rbe_right)->cmd_entry
.rbe_color == 0)) { (tmp)->cmd_entry.rbe_color = 1; elm = parent
; parent = (elm)->cmd_entry.rbe_parent; } else { if ((tmp)
->cmd_entry.rbe_left == ((void *)0) || ((tmp)->cmd_entry
.rbe_left)->cmd_entry.rbe_color == 0) { struct trapcmd *oright
; if ((oright = (tmp)->cmd_entry.rbe_right)) (oright)->
cmd_entry.rbe_color = 0; (tmp)->cmd_entry.rbe_color = 1; do
{ (oright) = (tmp)->cmd_entry.rbe_right; if (((tmp)->cmd_entry
.rbe_right = (oright)->cmd_entry.rbe_left)) { ((oright)->
cmd_entry.rbe_left)->cmd_entry.rbe_parent = (tmp); } do {}
while (0); if (((oright)->cmd_entry.rbe_parent = (tmp)->
cmd_entry.rbe_parent)) { if ((tmp) == ((tmp)->cmd_entry.rbe_parent
)->cmd_entry.rbe_left) ((tmp)->cmd_entry.rbe_parent)->
cmd_entry.rbe_left = (oright); else ((tmp)->cmd_entry.rbe_parent
)->cmd_entry.rbe_right = (oright); } else (head)->rbh_root
= (oright); (oright)->cmd_entry.rbe_left = (tmp); (tmp)->
cmd_entry.rbe_parent = (oright); do {} while (0); if (((oright
)->cmd_entry.rbe_parent)) do {} while (0); } while (0); tmp
= (parent)->cmd_entry.rbe_left; } (tmp)->cmd_entry.rbe_color
= (parent)->cmd_entry.rbe_color; (parent)->cmd_entry.rbe_color
= 0; if ((tmp)->cmd_entry.rbe_left) ((tmp)->cmd_entry.
rbe_left)->cmd_entry.rbe_color = 0; do { (tmp) = (parent)->
cmd_entry.rbe_left; if (((parent)->cmd_entry.rbe_left = (tmp
)->cmd_entry.rbe_right)) { ((tmp)->cmd_entry.rbe_right)
->cmd_entry.rbe_parent = (parent); } do {} while (0); if (
((tmp)->cmd_entry.rbe_parent = (parent)->cmd_entry.rbe_parent
)) { if ((parent) == ((parent)->cmd_entry.rbe_parent)->
cmd_entry.rbe_left) ((parent)->cmd_entry.rbe_parent)->cmd_entry
.rbe_left = (tmp); else ((parent)->cmd_entry.rbe_parent)->
cmd_entry.rbe_right = (tmp); } else (head)->rbh_root = (tmp
); (tmp)->cmd_entry.rbe_right = (parent); (parent)->cmd_entry
.rbe_parent = (tmp); do {} while (0); if (((tmp)->cmd_entry
.rbe_parent)) do {} while (0); } while (0); elm = (head)->
rbh_root; break; } } } if (elm) (elm)->cmd_entry.rbe_color
= 0; } struct trapcmd * trapcmd_tree_RB_REMOVE(struct trapcmd_tree
*head, struct trapcmd *elm) { struct trapcmd *child, *parent
, *old = elm; int color; if ((elm)->cmd_entry.rbe_left == (
(void *)0)) child = (elm)->cmd_entry.rbe_right; else if ((
elm)->cmd_entry.rbe_right == ((void *)0)) child = (elm)->
cmd_entry.rbe_left; else { struct trapcmd *left; elm = (elm)->
cmd_entry.rbe_right; while ((left = (elm)->cmd_entry.rbe_left
)) elm = left; child = (elm)->cmd_entry.rbe_right; parent =
(elm)->cmd_entry.rbe_parent; color = (elm)->cmd_entry.
rbe_color; if (child) (child)->cmd_entry.rbe_parent = parent
; if (parent) { if ((parent)->cmd_entry.rbe_left == elm) (
parent)->cmd_entry.rbe_left = child; else (parent)->cmd_entry
.rbe_right = child; do {} while (0); } else (head)->rbh_root
= child; if ((elm)->cmd_entry.rbe_parent == old) parent =
elm; (elm)->cmd_entry = (old)->cmd_entry; if ((old)->
cmd_entry.rbe_parent) { if (((old)->cmd_entry.rbe_parent)->
cmd_entry.rbe_left == old) ((old)->cmd_entry.rbe_parent)->
cmd_entry.rbe_left = elm; else ((old)->cmd_entry.rbe_parent
)->cmd_entry.rbe_right = elm; do {} while (0); } else (head
)->rbh_root = elm; ((old)->cmd_entry.rbe_left)->cmd_entry
.rbe_parent = elm; if ((old)->cmd_entry.rbe_right) ((old)->
cmd_entry.rbe_right)->cmd_entry.rbe_parent = elm; if (parent
) { left = parent; do { do {} while (0); } while ((left = (left
)->cmd_entry.rbe_parent)); } goto color; } parent = (elm)->
cmd_entry.rbe_parent; color = (elm)->cmd_entry.rbe_color; if
(child) (child)->cmd_entry.rbe_parent = parent; if (parent
) { if ((parent)->cmd_entry.rbe_left == elm) (parent)->
cmd_entry.rbe_left = child; else (parent)->cmd_entry.rbe_right
= child; do {} while (0); } else (head)->rbh_root = child
; color: if (color == 0) trapcmd_tree_RB_REMOVE_COLOR(head, parent
, child); return (old); } struct trapcmd * trapcmd_tree_RB_INSERT
(struct trapcmd_tree *head, struct trapcmd *elm) { struct trapcmd
*tmp; struct trapcmd *parent = ((void *)0); int comp = 0; tmp
= (head)->rbh_root; while (tmp) { parent = tmp; comp = (trapcmd_cmp
)(elm, parent); if (comp < 0) tmp = (tmp)->cmd_entry.rbe_left
; else if (comp > 0) tmp = (tmp)->cmd_entry.rbe_right; else
return (tmp); } do { (elm)->cmd_entry.rbe_parent = parent
; (elm)->cmd_entry.rbe_left = (elm)->cmd_entry.rbe_right
= ((void *)0); (elm)->cmd_entry.rbe_color = 1; } while (0
); if (parent != ((void *)0)) { if (comp < 0) (parent)->
cmd_entry.rbe_left = elm; else (parent)->cmd_entry.rbe_right
= elm; do {} while (0); } else (head)->rbh_root = elm; trapcmd_tree_RB_INSERT_COLOR
(head, elm); return (((void *)0)); } struct trapcmd * trapcmd_tree_RB_FIND
(struct trapcmd_tree *head, struct trapcmd *elm) { struct trapcmd
*tmp = (head)->rbh_root; int comp; while (tmp) { comp = trapcmd_cmp
(elm, tmp); if (comp < 0) tmp = (tmp)->cmd_entry.rbe_left
; else if (comp > 0) tmp = (tmp)->cmd_entry.rbe_right; else
return (tmp); } return (((void *)0)); } struct trapcmd * trapcmd_tree_RB_NFIND
(struct trapcmd_tree *head, struct trapcmd *elm) { struct trapcmd
*tmp = (head)->rbh_root; struct trapcmd *res = ((void *)0
); int comp; while (tmp) { comp = trapcmd_cmp(elm, tmp); if (
comp < 0) { res = tmp; tmp = (tmp)->cmd_entry.rbe_left;
} else if (comp > 0) tmp = (tmp)->cmd_entry.rbe_right;
else return (tmp); } return (res); } struct trapcmd * trapcmd_tree_RB_NEXT
(struct trapcmd *elm) { if ((elm)->cmd_entry.rbe_right) { elm
= (elm)->cmd_entry.rbe_right; while ((elm)->cmd_entry.
rbe_left) elm = (elm)->cmd_entry.rbe_left; } else { if ((elm
)->cmd_entry.rbe_parent && (elm == ((elm)->cmd_entry
.rbe_parent)->cmd_entry.rbe_left)) elm = (elm)->cmd_entry
.rbe_parent; else { while ((elm)->cmd_entry.rbe_parent &&
(elm == ((elm)->cmd_entry.rbe_parent)->cmd_entry.rbe_right
)) elm = (elm)->cmd_entry.rbe_parent; elm = (elm)->cmd_entry
.rbe_parent; } } return (elm); } struct trapcmd * trapcmd_tree_RB_PREV
(struct trapcmd *elm) { if ((elm)->cmd_entry.rbe_left) { elm
= (elm)->cmd_entry.rbe_left; while ((elm)->cmd_entry.rbe_right
) elm = (elm)->cmd_entry.rbe_right; } else { if ((elm)->
cmd_entry.rbe_parent && (elm == ((elm)->cmd_entry.
rbe_parent)->cmd_entry.rbe_right)) elm = (elm)->cmd_entry
.rbe_parent; else { while ((elm)->cmd_entry.rbe_parent &&
(elm == ((elm)->cmd_entry.rbe_parent)->cmd_entry.rbe_left
)) elm = (elm)->cmd_entry.rbe_parent; elm = (elm)->cmd_entry
.rbe_parent; } } return (elm); } struct trapcmd * trapcmd_tree_RB_MINMAX
(struct trapcmd_tree *head, int val) { struct trapcmd *tmp = (
head)->rbh_root; struct trapcmd *parent = ((void *)0); while
(tmp) { parent = tmp; if (val < 0) tmp = (tmp)->cmd_entry
.rbe_left; else tmp = (tmp)->cmd_entry.rbe_right; } return
(parent); }
58
59struct trapcmd_tree trapcmd_tree = RB_INITIALIZER(&trapcmd_tree){ ((void *)0) };
60
61/*
62 * Validate received message
63 */
64int
65traphandler_parse(struct snmp_message *msg)
66{
67 struct privsep *ps = &snmpd_env->sc_ps;
68 struct snmp_stats *stats = &snmpd_env->sc_stats;
69 struct ber ber = {0};
70 struct ber_element *vblist = NULL((void *)0), *elm;
71 struct ber_oid o1, o2, snmpTrapOIDOID;
72 struct ber_oid snmpTrapOID, sysUpTimeOID;
73 int sysUpTime;
74 struct iovec iov[2];
75 void *buf;
76 ssize_t buflen;
77 int ret = -1;
78
79 switch (msg->sm_pdu->be_type) {
80 case SNMP_C_TRAP:
81 if ((vblist = traphandler_v1translate(msg, 0)) == NULL((void *)0))
82 goto done;
83 break;
84 case SNMP_C_TRAPV2:
85 if (ober_scanf_elements(msg->sm_pdu, "{SSe}$", &elm) == -1) {
86 stats->snmp_inasnparseerrs++;
87 goto done;
88 }
89 if (elm->be_type != BER_TYPE_INTEGER2) {
90 stats->snmp_inasnparseerrs++;
91 goto done;
92 }
93 vblist = ober_unlink_elements(elm);
94 break;
95 default:
96 fatalx("%s called without proper context", __func__);
97 }
98
99 (void)ober_string2oid("1.3.6.1.2.1.1.3.0", &sysUpTimeOID);
100 (void)ober_string2oid("1.3.6.1.6.3.1.1.4.1.0", &snmpTrapOIDOID);
101 if (ober_scanf_elements(vblist, "{{od$}{oo$}", &o1, &sysUpTime, &o2,
102 &snmpTrapOID) == -1 ||
103 ober_oid_cmp(&o1, &sysUpTimeOID) != 0 ||
104 ober_oid_cmp(&o2, &snmpTrapOIDOID) != 0) {
105 stats->snmp_inasnparseerrs++;
106 goto done;
107 }
108 (void)ober_scanf_elements(vblist, "{Se", &elm);
109 for (elm = elm->be_next; elm != NULL((void *)0); elm = elm->be_next) {
110 if (ober_scanf_elements(elm, "{oS$}", &o1) == -1) {
111 stats->snmp_inasnparseerrs++;
112 goto done;
113 }
114 }
115
116 ober_set_application(&ber, smi_application);
117
118 if ((buflen = ober_write_elements(&ber, vblist)) == -1 ||
119 ober_get_writebuf(&ber, &buf) == -1) {
120 msg->sm_errstr = "failed to handle trap";
121 goto done;
122 }
123
124 iov[0].iov_base = &(msg->sm_ss);
125 iov[0].iov_len = msg->sm_slen;
126 iov[1].iov_base = buf;
127 iov[1].iov_len = buflen;
128
129 /* Forward it to the parent process */
130 if (proc_composev(ps, PROC_PARENT, IMSG_TRAP_EXEC, iov, 2) == -1) {
131 msg->sm_errstr = "failed to handle trap";
132 goto done;
133 }
134
135 ret = 0;
136done:
137 ober_free(&ber);
138 if (vblist != NULL((void *)0))
139 ober_free_elements(vblist);
140 return ret;
141}
142
143struct ber_element *
144traphandler_v1translate(struct snmp_message *msg, int proxy)
145{
146 struct snmp_stats *stats = &snmpd_env->sc_stats;
147 struct ber_oid trapoid, enterprise, oid, snmpTrapAddressOid;
148 struct ber_oid snmpTrapCommunityOid, snmpTrapEnterpriseOid;
149 struct ber_element *elm, *last, *vblist, *vb0 = NULL((void *)0);
150 void *agent_addr;
151 size_t agent_addrlen;
152 int generic_trap, specific_trap, time_stamp;
153 int hasaddress = 0, hascommunity = 0, hasenterprise = 0;
154
155 if (ober_scanf_elements(msg->sm_pdu, "{oxdddeS$}$", &enterprise,
156 &agent_addr, &agent_addrlen, &generic_trap, &specific_trap,
157 &time_stamp, &vblist) == -1 ||
158 agent_addrlen != 4 ||
159 vblist->be_type != BER_TYPE_SEQUENCE16) {
160 stats->snmp_inasnparseerrs++;
161 return NULL((void *)0);
162 }
163 switch (generic_trap) {
164 case 0:
165 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.1", &trapoid);
166 break;
167 case 1:
168 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.2", &trapoid);
169 break;
170 case 2:
171 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.3", &trapoid);
172 break;
173 case 3:
174 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.4", &trapoid);
175 break;
176 case 4:
177 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.5", &trapoid);
178 break;
179 case 5:
180 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.6", &trapoid);
181 break;
182 case 6:
183 trapoid = enterprise;
184 /* Officially this should be 128, but BER_MAX_OID_LEN is 64 */
185 if (trapoid.bo_n + 2 > BER_MAX_OID_LEN128) {
186 stats->snmp_inasnparseerrs++;
187 return NULL((void *)0);
188 }
189 trapoid.bo_id[trapoid.bo_n++] = 0;
190 trapoid.bo_id[trapoid.bo_n++] = specific_trap;
191 break;
192 default:
193 stats->snmp_inasnparseerrs++;
194 return NULL((void *)0);
195 }
196
197 /* work aronud net-snmp's snmptrap: It adds an EOC element in vblist */
198 if (vblist->be_len != 0)
199 vb0 = ober_unlink_elements(vblist);
200
201 if ((vblist = ober_add_sequence(NULL((void *)0))) == NULL((void *)0)) {
202 msg->sm_errstr = strerror(errno(*__errno()));
203 if (vb0 != NULL((void *)0))
204 ober_free_elements(vb0);
205 return NULL((void *)0);
206 }
207 if (ober_printf_elements(vblist, "{od}{oO}e", "1.3.6.1.2.1.1.3.0",
208 time_stamp, "1.3.6.1.6.3.1.1.4.1.0", &trapoid, vb0) == NULL((void *)0)) {
209 msg->sm_errstr = strerror(errno(*__errno()));
210 if (vb0 != 0)
211 ober_free_elements(vb0);
212 ober_free_elements(vblist);
213 return NULL((void *)0);
214 }
215
216 if (proxy) {
217 (void)ober_string2oid("1.3.6.1.6.3.18.1.3.0",
218 &snmpTrapAddressOid);
219 (void)ober_string2oid("1.3.6.1.6.3.18.1.4.0",
220 &snmpTrapCommunityOid);
221 (void)ober_string2oid("1.3.6.1.6.3.1.1.4.3.0",
222 &snmpTrapEnterpriseOid);
223 for (elm = vblist->be_subbe_union.bv_sub; elm != NULL((void *)0); elm = elm->be_next) {
224 if (ober_get_oid(elm->be_subbe_union.bv_sub, &oid) == -1) {
225 msg->sm_errstr = "failed to read oid";
226 ober_free_elements(vblist);
227 return NULL((void *)0);
228 }
229 if (ober_oid_cmp(&oid, &snmpTrapAddressOid) == 0)
230 hasaddress = 1;
231 else if (ober_oid_cmp(&oid, &snmpTrapCommunityOid) == 0)
232 hascommunity = 1;
233 else if (ober_oid_cmp(&oid,
234 &snmpTrapEnterpriseOid) == 0)
235 hasenterprise = 1;
236 last = elm;
237 }
238 if (!hasaddress || !hascommunity || !hasenterprise) {
239 if (ober_printf_elements(last, "{Oxt}{Os}{OO}",
240 &snmpTrapAddressOid, agent_addr, 4,
241 BER_CLASS_APPLICATION0x1, SNMP_T_IPADDR,
242 &snmpTrapCommunityOid, msg->sm_community,
243 &snmpTrapEnterpriseOid, &enterprise) == NULL((void *)0)) {
244 msg->sm_errstr = strerror(errno(*__errno()));
245 ober_free_elements(vblist);
246 return NULL((void *)0);
247 }
248 }
249 }
250 return vblist;
251}
252
253int
254traphandler_priv_recvmsg(struct privsep_proc *p, struct imsg *imsg)
255{
256 ssize_t n;
257 pid_t pid;
258
259 if ((n = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr))) <= 0)
Although the value stored to 'n' is used in the enclosing expression, the value is never actually read from 'n'
260 return (-1); /* XXX */
261
262 switch ((pid = fork())) {
263 case 0:
264 traphandler_fork_handler(p, imsg);
265 /* NOTREACHED */
266 case -1:
267 log_warn("%s: couldn't fork traphandler", __func__);
268 return (0);
269 default:
270 log_debug("forked process %i to handle trap", pid);
271 return (0);
272 }
273 /* NOTREACHED */
274}
275
276int
277traphandler_fork_handler(struct privsep_proc *p, struct imsg *imsg)
278{
279 struct privsep *ps = p->p_ps;
280 struct snmpd *env = ps->ps_env;
281 struct ber ber = {0};
282 struct sockaddr *sa;
283 char *buf;
284 ssize_t n;
285 struct ber_element *vblist;
286 struct ber_oid trapoid;
287 struct trapcmd *cmd;
288 struct passwd *pw;
289 int verbose;
290
291 pw = ps->ps_pw;
292 verbose = log_getverbose();
293
294 if (setgroups(1, &pw->pw_gid) ||
295 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
296 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
297 fatal("traphandler_fork_handler: cannot drop privileges");
298
299 closefrom(STDERR_FILENO2 + 1);
300
301 log_init((env->sc_flags & SNMPD_F_DEBUG0x02) ? 1 : 0, LOG_DAEMON(3<<3));
302 log_setverbose(verbose);
303 log_procinit(p->p_title);
304
305 n = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr));
306
307 sa = imsg->data;
308 n -= sa->sa_len;
309 buf = (char *)imsg->data + sa->sa_len;
310
311 ober_set_application(&ber, smi_application);
312 ober_set_readbuf(&ber, buf, n);
313
314 if ((vblist = ober_read_elements(&ber, NULL((void *)0))) == NULL((void *)0))
315 fatalx("couldn't parse SNMP trap message");
316 ober_free(&ber);
317
318 (void)ober_scanf_elements(vblist, "{S{So", &trapoid);
319 if ((cmd = trapcmd_lookup(&trapoid)) != NULL((void *)0))
320 trapcmd_exec(cmd, sa, vblist->be_subbe_union.bv_sub);
321
322 ober_free_elements(vblist);
323
324 exit(0);
325}
326
327void
328trapcmd_exec(struct trapcmd *cmd, struct sockaddr *sa,
329 struct ber_element *vb)
330{
331 char oidbuf[SNMP_MAX_OID_STRLEN128];
332 struct ber_oid oid;
333 struct ber_element *elm;
334 int n, s[2], status = 0;
335 char *value, *host;
336 pid_t child = -1;
337
338 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, s) == -1) {
339 log_warn("could not create pipe for OID '%s'",
340 smi_oid2string(cmd->cmd_oid, oidbuf, sizeof(oidbuf), 0));
341 return;
342 }
343
344 switch (child = fork()) {
345 case 0:
346 dup2(s[1], STDIN_FILENO0);
347
348 close(s[0]);
349 close(s[1]);
350
351 closefrom(STDERR_FILENO2 + 1);
352
353 /* path to command is in argv[0], args follow */
354 execve(cmd->cmd_argv[0], cmd->cmd_argv, NULL((void *)0));
355
356 /* this shouldn't happen */
357 log_warn("could not exec trap command for OID '%s'",
358 smi_oid2string(cmd->cmd_oid, oidbuf, sizeof(oidbuf), 0));
359 _exit(1);
360 /* NOTREACHED */
361
362 case -1:
363 log_warn("could not fork trap command for OID '%s'",
364 smi_oid2string(cmd->cmd_oid, oidbuf, sizeof(oidbuf), 0));
365 close(s[0]);
366 close(s[1]);
367 return;
368 }
369
370 close(s[1]);
371
372 host = traphandler_hostname(sa, 0);
373 if (dprintf(s[0], "%s\n", host) == -1)
374 goto out;
375
376 host = traphandler_hostname(sa, 1);
377 if (dprintf(s[0], "%s\n", host) == -1)
378 goto out;
379
380 for (; vb != NULL((void *)0); vb = vb->be_next) {
381 if (ober_scanf_elements(vb, "{oeS$}", &oid, &elm) == -1)
382 goto out;
383 if ((value = smi_print_element(elm)) == NULL((void *)0))
384 goto out;
385 smi_oid2string(&oid, oidbuf, sizeof(oidbuf), 0);
386 n = dprintf(s[0], "%s %s\n", oidbuf, value);
387 free(value);
388 if (n == -1)
389 goto out;
390 }
391 out:
392 close(s[0]);
393 waitpid(child, &status, 0);
394
395 if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
) {
396 log_warnx("child %i exited due to receipt of signal %i",
397 child, WTERMSIG(status)(((status) & 0177)));
398 } else if (WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff) != 0) {
399 log_warnx("child %i exited with status %i",
400 child, WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff));
401 } else {
402 log_debug("child %i finished", child);
403 }
404 close(s[1]);
405
406 return;
407}
408
409char *
410traphandler_hostname(struct sockaddr *sa, int numeric)
411{
412 static char buf[NI_MAXHOST256];
413 int flag = 0;
414
415 if (numeric)
416 flag = NI_NUMERICHOST1;
417
418 bzero(buf, sizeof(buf));
419 if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL((void *)0), 0, flag) != 0)
420 return ("Unknown");
421
422 return (buf);
423}
424
425struct trapcmd *
426trapcmd_lookup(struct ber_oid *oid)
427{
428 struct trapcmd key, *res;
429
430 bzero(&key, sizeof(key));
431 key.cmd_oid = oid;
432
433 if ((res = RB_FIND(trapcmd_tree, &trapcmd_tree, &key)trapcmd_tree_RB_FIND(&trapcmd_tree, &key)) == NULL((void *)0))
434 res = key.cmd_maybe;
435 return (res);
436}
437
438int
439trapcmd_cmp(struct trapcmd *cmd1, struct trapcmd *cmd2)
440{
441 int ret;
442
443 ret = ober_oid_cmp(cmd1->cmd_oid, cmd2->cmd_oid);
444 switch (ret) {
445 case 2:
446 /* cmd1 is a child of cmd2 */
447 cmd1->cmd_maybe = cmd2;
448 return (1);
449 default:
450 return (ret);
451 }
452 /* NOTREACHED */
453}
454
455int
456trapcmd_add(struct trapcmd *cmd)
457{
458 return (RB_INSERT(trapcmd_tree, &trapcmd_tree, cmd)trapcmd_tree_RB_INSERT(&trapcmd_tree, cmd) != NULL((void *)0));
459}
460
461void
462trapcmd_free(struct trapcmd *cmd)
463{
464 RB_REMOVE(trapcmd_tree, &trapcmd_tree, cmd)trapcmd_tree_RB_REMOVE(&trapcmd_tree, cmd);
465 free(cmd->cmd_argv);
466 free(cmd->cmd_oid);
467 free(cmd);
468}