Bug Summary

File:src/usr.sbin/snmpd/traphandler.c
Warning:line 254, 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.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name traphandler.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/llvm16/lib/clang/16 -I /usr/src/usr.sbin/snmpd -internal-isystem /usr/local/llvm16/lib/clang/16/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 -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/snmpd/traphandler.c
1/* $OpenBSD: traphandler.c,v 1.25 2023/12/21 12:43:31 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/tree.h>
22#include <sys/wait.h>
23
24#include <ber.h>
25#include <errno(*__errno()).h>
26#include <imsg.h>
27#include <netdb.h>
28#include <pwd.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <strings.h>
33#include <syslog.h>
34#include <unistd.h>
35
36#include "log.h"
37#include "smi.h"
38#include "snmp.h"
39#include "snmpd.h"
40
41int traphandler_priv_recvmsg(struct privsep_proc *, struct imsg *);
42int traphandler_fork_handler(struct privsep_proc *, struct imsg *);
43struct ber_element *
44 traphandler_v1translate(struct snmp_message *, int);
45int trapcmd_cmp(struct trapcmd *, struct trapcmd *);
46void trapcmd_exec(struct trapcmd *, struct sockaddr *,
47 struct ber_element *);
48
49char *traphandler_hostname(struct sockaddr *, int);
50
51RB_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);
52RB_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); }
53
54struct trapcmd_tree trapcmd_tree = RB_INITIALIZER(&trapcmd_tree){ ((void *)0) };
55
56/*
57 * Validate received message
58 */
59int
60traphandler_parse(struct snmp_message *msg)
61{
62 struct privsep *ps = &snmpd_env->sc_ps;
63 struct snmp_stats *stats = &snmpd_env->sc_stats;
64 struct ber ber = {0};
65 struct ber_element *vblist = NULL((void *)0), *elm;
66 struct ber_oid o1, o2, snmpTrapOIDOID;
67 struct ber_oid snmpTrapOID, sysUpTimeOID;
68 int sysUpTime;
69 struct iovec iov[2];
70 void *buf;
71 ssize_t buflen;
72 int ret = -1;
73
74 switch (msg->sm_pdu->be_type) {
75 case SNMP_C_TRAP:
76 if ((vblist = traphandler_v1translate(msg, 0)) == NULL((void *)0))
77 goto done;
78 break;
79 case SNMP_C_TRAPV2:
80 if (ober_scanf_elements(msg->sm_pdu, "{SSe}$", &elm) == -1) {
81 stats->snmp_inasnparseerrs++;
82 goto done;
83 }
84 if (elm->be_type != BER_TYPE_INTEGER2) {
85 stats->snmp_inasnparseerrs++;
86 goto done;
87 }
88 vblist = ober_unlink_elements(elm);
89 break;
90 default:
91 fatalx("%s called without proper context", __func__);
92 }
93
94 (void)ober_string2oid("1.3.6.1.2.1.1.3.0", &sysUpTimeOID);
95 (void)ober_string2oid("1.3.6.1.6.3.1.1.4.1.0", &snmpTrapOIDOID);
96 if (ober_scanf_elements(vblist, "{{od$}{oo$}", &o1, &sysUpTime, &o2,
97 &snmpTrapOID) == -1 ||
98 ober_oid_cmp(&o1, &sysUpTimeOID) != 0 ||
99 ober_oid_cmp(&o2, &snmpTrapOIDOID) != 0) {
100 stats->snmp_inasnparseerrs++;
101 goto done;
102 }
103 (void)ober_scanf_elements(vblist, "{Se", &elm);
104 for (elm = elm->be_next; elm != NULL((void *)0); elm = elm->be_next) {
105 if (ober_scanf_elements(elm, "{oS$}", &o1) == -1) {
106 stats->snmp_inasnparseerrs++;
107 goto done;
108 }
109 }
110
111 ober_set_application(&ber, smi_application);
112
113 if ((buflen = ober_write_elements(&ber, vblist)) == -1 ||
114 ober_get_writebuf(&ber, &buf) == -1) {
115 msg->sm_errstr = "failed to handle trap";
116 goto done;
117 }
118
119 iov[0].iov_base = &(msg->sm_ss);
120 iov[0].iov_len = msg->sm_slen;
121 iov[1].iov_base = buf;
122 iov[1].iov_len = buflen;
123
124 /* Forward it to the parent process */
125 if (proc_composev(ps, PROC_PARENT, IMSG_TRAP_EXEC, iov, 2) == -1) {
126 msg->sm_errstr = "failed to handle trap";
127 goto done;
128 }
129
130 ret = 0;
131done:
132 ober_free(&ber);
133 if (vblist != NULL((void *)0))
134 ober_free_elements(vblist);
135 return ret;
136}
137
138struct ber_element *
139traphandler_v1translate(struct snmp_message *msg, int proxy)
140{
141 struct snmp_stats *stats = &snmpd_env->sc_stats;
142 struct ber_oid trapoid, enterprise, oid, snmpTrapAddressOid;
143 struct ber_oid snmpTrapCommunityOid, snmpTrapEnterpriseOid;
144 struct ber_element *elm, *last, *vblist, *vb0 = NULL((void *)0);
145 void *agent_addr;
146 size_t agent_addrlen;
147 int generic_trap, specific_trap, time_stamp;
148 int hasaddress = 0, hascommunity = 0, hasenterprise = 0;
149
150 if (ober_scanf_elements(msg->sm_pdu, "{oxdddeS$}$", &enterprise,
151 &agent_addr, &agent_addrlen, &generic_trap, &specific_trap,
152 &time_stamp, &vblist) == -1 ||
153 agent_addrlen != 4 ||
154 vblist->be_type != BER_TYPE_SEQUENCE16) {
155 stats->snmp_inasnparseerrs++;
156 return NULL((void *)0);
157 }
158 switch (generic_trap) {
159 case 0:
160 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.1", &trapoid);
161 break;
162 case 1:
163 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.2", &trapoid);
164 break;
165 case 2:
166 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.3", &trapoid);
167 break;
168 case 3:
169 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.4", &trapoid);
170 break;
171 case 4:
172 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.5", &trapoid);
173 break;
174 case 5:
175 (void)ober_string2oid("1.3.6.1.6.3.1.1.5.6", &trapoid);
176 break;
177 case 6:
178 trapoid = enterprise;
179 /* Officially this should be 128, but BER_MAX_OID_LEN is 64 */
180 if (trapoid.bo_n + 2 > BER_MAX_OID_LEN128) {
181 stats->snmp_inasnparseerrs++;
182 return NULL((void *)0);
183 }
184 trapoid.bo_id[trapoid.bo_n++] = 0;
185 trapoid.bo_id[trapoid.bo_n++] = specific_trap;
186 break;
187 default:
188 stats->snmp_inasnparseerrs++;
189 return NULL((void *)0);
190 }
191
192 /* work around net-snmp's snmptrap: It adds an EOC element in vblist */
193 if (vblist->be_len != 0)
194 vb0 = ober_unlink_elements(vblist);
195
196 if ((vblist = ober_add_sequence(NULL((void *)0))) == NULL((void *)0)) {
197 msg->sm_errstr = strerror(errno(*__errno()));
198 if (vb0 != NULL((void *)0))
199 ober_free_elements(vb0);
200 return NULL((void *)0);
201 }
202 if (ober_printf_elements(vblist, "{od}{oO}e", "1.3.6.1.2.1.1.3.0",
203 time_stamp, "1.3.6.1.6.3.1.1.4.1.0", &trapoid, vb0) == NULL((void *)0)) {
204 msg->sm_errstr = strerror(errno(*__errno()));
205 if (vb0 != 0)
206 ober_free_elements(vb0);
207 ober_free_elements(vblist);
208 return NULL((void *)0);
209 }
210
211 if (proxy) {
212 (void)ober_string2oid("1.3.6.1.6.3.18.1.3.0",
213 &snmpTrapAddressOid);
214 (void)ober_string2oid("1.3.6.1.6.3.18.1.4.0",
215 &snmpTrapCommunityOid);
216 (void)ober_string2oid("1.3.6.1.6.3.1.1.4.3.0",
217 &snmpTrapEnterpriseOid);
218 for (elm = vblist->be_subbe_union.bv_sub; elm != NULL((void *)0); elm = elm->be_next) {
219 if (ober_get_oid(elm->be_subbe_union.bv_sub, &oid) == -1) {
220 msg->sm_errstr = "failed to read oid";
221 ober_free_elements(vblist);
222 return NULL((void *)0);
223 }
224 if (ober_oid_cmp(&oid, &snmpTrapAddressOid) == 0)
225 hasaddress = 1;
226 else if (ober_oid_cmp(&oid, &snmpTrapCommunityOid) == 0)
227 hascommunity = 1;
228 else if (ober_oid_cmp(&oid,
229 &snmpTrapEnterpriseOid) == 0)
230 hasenterprise = 1;
231 last = elm;
232 }
233 if (!hasaddress || !hascommunity || !hasenterprise) {
234 if (ober_printf_elements(last, "{Oxt}{Os}{OO}",
235 &snmpTrapAddressOid, agent_addr, 4,
236 BER_CLASS_APPLICATION0x1, SNMP_T_IPADDR,
237 &snmpTrapCommunityOid, msg->sm_community,
238 &snmpTrapEnterpriseOid, &enterprise) == NULL((void *)0)) {
239 msg->sm_errstr = strerror(errno(*__errno()));
240 ober_free_elements(vblist);
241 return NULL((void *)0);
242 }
243 }
244 }
245 return vblist;
246}
247
248int
249traphandler_priv_recvmsg(struct privsep_proc *p, struct imsg *imsg)
250{
251 ssize_t n;
252 pid_t pid;
253
254 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'
255 return (-1); /* XXX */
256
257 switch ((pid = fork())) {
258 case 0:
259 traphandler_fork_handler(p, imsg);
260 /* NOTREACHED */
261 case -1:
262 log_warn("%s: couldn't fork traphandler", __func__);
263 return (0);
264 default:
265 log_debug("forked process %i to handle trap", pid);
266 return (0);
267 }
268 /* NOTREACHED */
269}
270
271int
272traphandler_fork_handler(struct privsep_proc *p, struct imsg *imsg)
273{
274 struct privsep *ps = p->p_ps;
275 struct snmpd *env = ps->ps_env;
276 struct ber ber = {0};
277 struct sockaddr *sa;
278 char *buf;
279 ssize_t n;
280 struct ber_element *vblist;
281 struct ber_oid trapoid;
282 struct trapcmd *cmd;
283 struct passwd *pw;
284 int verbose;
285
286 pw = ps->ps_pw;
287 verbose = log_getverbose();
288
289 if (setgroups(1, &pw->pw_gid) ||
290 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
291 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
292 fatal("traphandler_fork_handler: cannot drop privileges");
293
294 closefrom(STDERR_FILENO2 + 1);
295
296 log_init((env->sc_flags & SNMPD_F_DEBUG0x02) ? 1 : 0, LOG_DAEMON(3<<3));
297 log_setverbose(verbose);
298 log_procinit(p->p_title);
299
300 n = IMSG_DATA_SIZE(imsg)((imsg)->hdr.len - sizeof(struct imsg_hdr));
301
302 sa = imsg->data;
303 n -= sa->sa_len;
304 buf = (char *)imsg->data + sa->sa_len;
305
306 ober_set_application(&ber, smi_application);
307 ober_set_readbuf(&ber, buf, n);
308
309 if ((vblist = ober_read_elements(&ber, NULL((void *)0))) == NULL((void *)0))
310 fatalx("couldn't parse SNMP trap message");
311 ober_free(&ber);
312
313 (void)ober_scanf_elements(vblist, "{S{So", &trapoid);
314 if ((cmd = trapcmd_lookup(&trapoid)) != NULL((void *)0))
315 trapcmd_exec(cmd, sa, vblist->be_subbe_union.bv_sub);
316
317 ober_free_elements(vblist);
318
319 exit(0);
320}
321
322void
323trapcmd_exec(struct trapcmd *cmd, struct sockaddr *sa,
324 struct ber_element *vb)
325{
326 char oidbuf[SNMP_MAX_OID_STRLEN128];
327 struct ber_oid oid;
328 struct ber_element *elm;
329 int n, s[2], status = 0;
330 char *value, *host;
331 pid_t child = -1;
332
333 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, s) == -1) {
334 log_warn("could not create pipe for OID '%s'",
335 smi_oid2string(cmd->cmd_oid, oidbuf, sizeof(oidbuf), 0));
336 return;
337 }
338
339 switch (child = fork()) {
340 case 0:
341 dup2(s[1], STDIN_FILENO0);
342
343 close(s[0]);
344 close(s[1]);
345
346 closefrom(STDERR_FILENO2 + 1);
347
348 /* path to command is in argv[0], args follow */
349 execve(cmd->cmd_argv[0], cmd->cmd_argv, NULL((void *)0));
350
351 /* this shouldn't happen */
352 log_warn("could not exec trap command for OID '%s'",
353 smi_oid2string(cmd->cmd_oid, oidbuf, sizeof(oidbuf), 0));
354 _exit(1);
355 /* NOTREACHED */
356
357 case -1:
358 log_warn("could not fork trap command for OID '%s'",
359 smi_oid2string(cmd->cmd_oid, oidbuf, sizeof(oidbuf), 0));
360 close(s[0]);
361 close(s[1]);
362 return;
363 }
364
365 close(s[1]);
366
367 host = traphandler_hostname(sa, 0);
368 if (dprintf(s[0], "%s\n", host) == -1)
369 goto out;
370
371 host = traphandler_hostname(sa, 1);
372 if (dprintf(s[0], "%s\n", host) == -1)
373 goto out;
374
375 for (; vb != NULL((void *)0); vb = vb->be_next) {
376 if (ober_scanf_elements(vb, "{oeS$}", &oid, &elm) == -1)
377 goto out;
378 if ((value = smi_print_element_legacy(elm)) == NULL((void *)0))
379 goto out;
380 smi_oid2string(&oid, oidbuf, sizeof(oidbuf), 0);
381 n = dprintf(s[0], "%s %s\n", oidbuf, value);
382 free(value);
383 if (n == -1)
384 goto out;
385 }
386 out:
387 close(s[0]);
388 waitpid(child, &status, 0);
389
390 if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
) {
391 log_warnx("child %i exited due to receipt of signal %i",
392 child, WTERMSIG(status)(((status) & 0177)));
393 } else if (WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff) != 0) {
394 log_warnx("child %i exited with status %i",
395 child, WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff));
396 } else {
397 log_debug("child %i finished", child);
398 }
399 close(s[1]);
400
401 return;
402}
403
404char *
405traphandler_hostname(struct sockaddr *sa, int numeric)
406{
407 static char buf[NI_MAXHOST256];
408 int flag = 0;
409
410 if (numeric)
411 flag = NI_NUMERICHOST1;
412
413 bzero(buf, sizeof(buf));
414 if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL((void *)0), 0, flag) != 0)
415 return ("Unknown");
416
417 return (buf);
418}
419
420struct trapcmd *
421trapcmd_lookup(struct ber_oid *oid)
422{
423 struct trapcmd key, *res;
424
425 bzero(&key, sizeof(key));
426 key.cmd_oid = oid;
427
428 if ((res = RB_FIND(trapcmd_tree, &trapcmd_tree, &key)trapcmd_tree_RB_FIND(&trapcmd_tree, &key)) == NULL((void *)0))
429 res = key.cmd_maybe;
430 return (res);
431}
432
433int
434trapcmd_cmp(struct trapcmd *cmd1, struct trapcmd *cmd2)
435{
436 int ret;
437
438 ret = ober_oid_cmp(cmd1->cmd_oid, cmd2->cmd_oid);
439 switch (ret) {
440 case 2:
441 /* cmd1 is a child of cmd2 */
442 cmd1->cmd_maybe = cmd2;
443 return (1);
444 default:
445 return (ret);
446 }
447 /* NOTREACHED */
448}
449
450int
451trapcmd_add(struct trapcmd *cmd)
452{
453 return (RB_INSERT(trapcmd_tree, &trapcmd_tree, cmd)trapcmd_tree_RB_INSERT(&trapcmd_tree, cmd) != NULL((void *)0));
454}
455
456void
457trapcmd_free(struct trapcmd *cmd)
458{
459 RB_REMOVE(trapcmd_tree, &trapcmd_tree, cmd)trapcmd_tree_RB_REMOVE(&trapcmd_tree, cmd);
460 free(cmd->cmd_argv);
461 free(cmd->cmd_oid);
462 free(cmd);
463}