| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: traphandler.c,v 1.9 2017/08/12 04:29:57 rob 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/socketvar.h>  | 
    ||
22  | 
    #include <sys/stat.h>  | 
    ||
23  | 
    #include <sys/types.h>  | 
    ||
24  | 
    #include <sys/uio.h>  | 
    ||
25  | 
    #include <sys/wait.h>  | 
    ||
26  | 
    |||
27  | 
    #include <net/if.h>  | 
    ||
28  | 
    #include <netinet/in.h>  | 
    ||
29  | 
    #include <arpa/inet.h>  | 
    ||
30  | 
    |||
31  | 
    #include <event.h>  | 
    ||
32  | 
    #include <fcntl.h>  | 
    ||
33  | 
    #include <imsg.h>  | 
    ||
34  | 
    #include <netdb.h>  | 
    ||
35  | 
    #include <stdio.h>  | 
    ||
36  | 
    #include <stdlib.h>  | 
    ||
37  | 
    #include <string.h>  | 
    ||
38  | 
    #include <syslog.h>  | 
    ||
39  | 
    #include <unistd.h>  | 
    ||
40  | 
    #include <pwd.h>  | 
    ||
41  | 
    |||
42  | 
    #include "ber.h"  | 
    ||
43  | 
    #include "snmpd.h"  | 
    ||
44  | 
    #include "mib.h"  | 
    ||
45  | 
    |||
46  | 
    char trap_path[PATH_MAX];  | 
    ||
47  | 
    |||
48  | 
    void traphandler_init(struct privsep *, struct privsep_proc *, void *arg);  | 
    ||
49  | 
    int traphandler_dispatch_parent(int, struct privsep_proc *, struct imsg *);  | 
    ||
50  | 
    int traphandler_bind(struct address *);  | 
    ||
51  | 
    void traphandler_recvmsg(int, short, void *);  | 
    ||
52  | 
    int traphandler_priv_recvmsg(struct privsep_proc *, struct imsg *);  | 
    ||
53  | 
    int traphandler_fork_handler(struct privsep_proc *, struct imsg *);  | 
    ||
54  | 
    int traphandler_parse(char *, size_t, struct ber_element **,  | 
    ||
55  | 
    struct ber_element **, u_int *, struct ber_oid *);  | 
    ||
56  | 
    void traphandler_v1translate(struct ber_oid *, u_int, u_int);  | 
    ||
57  | 
    |||
58  | 
    int trapcmd_cmp(struct trapcmd *, struct trapcmd *);  | 
    ||
59  | 
    void trapcmd_exec(struct trapcmd *, struct sockaddr *,  | 
    ||
60  | 
    struct ber_element *, char *, u_int);  | 
    ||
61  | 
    |||
62  | 
    char *traphandler_hostname(struct sockaddr *, int);  | 
    ||
63  | 
    |||
64  | 
    RB_PROTOTYPE(trapcmd_tree, trapcmd, cmd_entry, trapcmd_cmp)  | 
    ||
65  | 
    ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗  | 
    44  | 
    RB_GENERATE(trapcmd_tree, trapcmd, cmd_entry, trapcmd_cmp)  | 
    
66  | 
    |||
67  | 
    struct trapcmd_tree trapcmd_tree = RB_INITIALIZER(&trapcmd_tree);  | 
    ||
68  | 
    |||
69  | 
    static struct privsep_proc procs[] = { | 
    ||
70  | 
    	{ "parent",	PROC_PARENT,	traphandler_dispatch_parent } | 
    ||
71  | 
    };  | 
    ||
72  | 
    |||
73  | 
    void  | 
    ||
74  | 
    traphandler(struct privsep *ps, struct privsep_proc *p)  | 
    ||
75  | 
    { | 
    ||
76  | 
    struct snmpd *env = ps->ps_env;  | 
    ||
77  | 
    struct address *h;  | 
    ||
78  | 
    struct listen_sock *so;  | 
    ||
79  | 
    |||
80  | 
    	if (env->sc_traphandler) { | 
    ||
81  | 
    		TAILQ_FOREACH(h, &env->sc_addresses, entry) { | 
    ||
82  | 
    if ((so = calloc(1, sizeof(*so))) == NULL)  | 
    ||
83  | 
    				fatal("%s", __func__); | 
    ||
84  | 
    if ((so->s_fd = traphandler_bind(h)) == -1)  | 
    ||
85  | 
    				fatal("could not create trap listener socket"); | 
    ||
86  | 
    TAILQ_INSERT_TAIL(&env->sc_sockets, so, entry);  | 
    ||
87  | 
    }  | 
    ||
88  | 
    }  | 
    ||
89  | 
    |||
90  | 
    proc_run(ps, p, procs, nitems(procs), traphandler_init, NULL);  | 
    ||
91  | 
    }  | 
    ||
92  | 
    |||
93  | 
    void  | 
    ||
94  | 
    traphandler_init(struct privsep *ps, struct privsep_proc *p, void *arg)  | 
    ||
95  | 
    { | 
    ||
96  | 
    struct snmpd *env = ps->ps_env;  | 
    ||
97  | 
    struct listen_sock *so;  | 
    ||
98  | 
    |||
99  | 
    	if (pledge("stdio id proc recvfd exec flock rpath cpath wpath", NULL) == -1) | 
    ||
100  | 
    		fatal("pledge"); | 
    ||
101  | 
    |||
102  | 
    if (!env->sc_traphandler)  | 
    ||
103  | 
    return;  | 
    ||
104  | 
    |||
105  | 
    /* listen for SNMP trap messages */  | 
    ||
106  | 
    	TAILQ_FOREACH(so, &env->sc_sockets, entry) { | 
    ||
107  | 
    event_set(&so->s_ev, so->s_fd, EV_READ|EV_PERSIST,  | 
    ||
108  | 
    traphandler_recvmsg, ps);  | 
    ||
109  | 
    event_add(&so->s_ev, NULL);  | 
    ||
110  | 
    }  | 
    ||
111  | 
    }  | 
    ||
112  | 
    |||
113  | 
    int  | 
    ||
114  | 
    traphandler_bind(struct address *addr)  | 
    ||
115  | 
    { | 
    ||
116  | 
    int s;  | 
    ||
117  | 
    char buf[512];  | 
    ||
118  | 
    |||
119  | 
    if ((s = snmpd_socket_af(&addr->ss, htons(SNMPD_TRAPPORT))) == -1)  | 
    ||
120  | 
    return (-1);  | 
    ||
121  | 
    |||
122  | 
    if (fcntl(s, F_SETFL, O_NONBLOCK) == -1)  | 
    ||
123  | 
    goto bad;  | 
    ||
124  | 
    |||
125  | 
    if (bind(s, (struct sockaddr *)&addr->ss, addr->ss.ss_len) == -1)  | 
    ||
126  | 
    goto bad;  | 
    ||
127  | 
    |||
128  | 
    if (print_host(&addr->ss, buf, sizeof(buf)) == NULL)  | 
    ||
129  | 
    goto bad;  | 
    ||
130  | 
    |||
131  | 
    	log_info("traphandler: listening on %s:%d", buf, SNMPD_TRAPPORT); | 
    ||
132  | 
    |||
133  | 
    return (s);  | 
    ||
134  | 
    bad:  | 
    ||
135  | 
    close (s);  | 
    ||
136  | 
    return (-1);  | 
    ||
137  | 
    }  | 
    ||
138  | 
    |||
139  | 
    void  | 
    ||
140  | 
    traphandler_shutdown(void)  | 
    ||
141  | 
    { | 
    ||
142  | 
    struct listen_sock *so;  | 
    ||
143  | 
    |||
144  | 
    	TAILQ_FOREACH(so, &snmpd_env->sc_sockets, entry) { | 
    ||
145  | 
    event_del(&so->s_ev);  | 
    ||
146  | 
    close(so->s_fd);  | 
    ||
147  | 
    }  | 
    ||
148  | 
    }  | 
    ||
149  | 
    |||
150  | 
    int  | 
    ||
151  | 
    traphandler_dispatch_parent(int fd, struct privsep_proc *p, struct imsg *imsg)  | 
    ||
152  | 
    { | 
    ||
153  | 
    	switch (imsg->hdr.type) { | 
    ||
154  | 
    default:  | 
    ||
155  | 
    break;  | 
    ||
156  | 
    }  | 
    ||
157  | 
    |||
158  | 
    return (-1);  | 
    ||
159  | 
    }  | 
    ||
160  | 
    |||
161  | 
    int  | 
    ||
162  | 
    snmpd_dispatch_traphandler(int fd, struct privsep_proc *p, struct imsg *imsg)  | 
    ||
163  | 
    { | 
    ||
164  | 
    ✓✗ | 8  | 
    	switch (imsg->hdr.type) { | 
    
165  | 
    case IMSG_ALERT:  | 
    ||
166  | 
    4  | 
    return (traphandler_priv_recvmsg(p, imsg));  | 
    |
167  | 
    default:  | 
    ||
168  | 
    break;  | 
    ||
169  | 
    }  | 
    ||
170  | 
    |||
171  | 
    return (-1);  | 
    ||
172  | 
    4  | 
    }  | 
    |
173  | 
    |||
174  | 
    void  | 
    ||
175  | 
    traphandler_recvmsg(int fd, short events, void *arg)  | 
    ||
176  | 
    { | 
    ||
177  | 
    struct privsep *ps = arg;  | 
    ||
178  | 
    char buf[8196];  | 
    ||
179  | 
    struct iovec iov[2];  | 
    ||
180  | 
    struct sockaddr_storage ss;  | 
    ||
181  | 
    socklen_t slen;  | 
    ||
182  | 
    ssize_t n;  | 
    ||
183  | 
    struct ber_element *req, *iter;  | 
    ||
184  | 
    struct ber_oid trapoid;  | 
    ||
185  | 
    u_int uptime;  | 
    ||
186  | 
    |||
187  | 
    slen = sizeof(ss);  | 
    ||
188  | 
    if ((n = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&ss,  | 
    ||
189  | 
    &slen)) == -1)  | 
    ||
190  | 
    return;  | 
    ||
191  | 
    |||
192  | 
    if (traphandler_parse(buf, n, &req, &iter, &uptime, &trapoid) == -1)  | 
    ||
193  | 
    goto done;  | 
    ||
194  | 
    |||
195  | 
    iov[0].iov_base = &ss;  | 
    ||
196  | 
    iov[0].iov_len = ss.ss_len;  | 
    ||
197  | 
    iov[1].iov_base = buf;  | 
    ||
198  | 
    iov[1].iov_len = n;  | 
    ||
199  | 
    |||
200  | 
    /* Forward it to the parent process */  | 
    ||
201  | 
    if (proc_composev(ps, PROC_PARENT, IMSG_ALERT, iov, 2) == -1)  | 
    ||
202  | 
    goto done;  | 
    ||
203  | 
    |||
204  | 
    done:  | 
    ||
205  | 
    if (req != NULL)  | 
    ||
206  | 
    ber_free_elements(req);  | 
    ||
207  | 
    return;  | 
    ||
208  | 
    }  | 
    ||
209  | 
    |||
210  | 
    /*  | 
    ||
211  | 
    * Validate received message  | 
    ||
212  | 
    */  | 
    ||
213  | 
    int  | 
    ||
214  | 
    traphandler_parse(char *buf, size_t n, struct ber_element **req,  | 
    ||
215  | 
    struct ber_element **vbinds, u_int *uptime, struct ber_oid *trapoid)  | 
    ||
216  | 
    { | 
    ||
217  | 
    struct ber ber;  | 
    ||
218  | 
    struct ber_element *elm;  | 
    ||
219  | 
    u_int vers, gtype, etype;  | 
    ||
220  | 
    |||
221  | 
    bzero(&ber, sizeof(ber));  | 
    ||
222  | 
    ber.fd = -1;  | 
    ||
223  | 
    ber_set_application(&ber, smi_application);  | 
    ||
224  | 
    ber_set_readbuf(&ber, buf, n);  | 
    ||
225  | 
    |||
226  | 
    if ((*req = ber_read_elements(&ber, NULL)) == NULL)  | 
    ||
227  | 
    goto done;  | 
    ||
228  | 
    |||
229  | 
    	if (ber_scanf_elements(*req, "{dSe", &vers, &elm) == -1) | 
    ||
230  | 
    goto done;  | 
    ||
231  | 
    |||
232  | 
    	switch (vers) { | 
    ||
233  | 
    case SNMP_V1:  | 
    ||
234  | 
    		if (ber_scanf_elements(elm, "{oSddd", | 
    ||
235  | 
    trapoid, >ype, &etype, uptime) == -1)  | 
    ||
236  | 
    goto done;  | 
    ||
237  | 
    traphandler_v1translate(trapoid, gtype, etype);  | 
    ||
238  | 
    break;  | 
    ||
239  | 
    |||
240  | 
    case SNMP_V2:  | 
    ||
241  | 
    		if (ber_scanf_elements(elm, "{SSSS{e}}", &elm) == -1 || | 
    ||
242  | 
    		    ber_scanf_elements(elm, "{SdS}{So}e", | 
    ||
243  | 
    uptime, trapoid, vbinds) == -1)  | 
    ||
244  | 
    goto done;  | 
    ||
245  | 
    break;  | 
    ||
246  | 
    |||
247  | 
    default:  | 
    ||
248  | 
    		log_warnx("unsupported SNMP trap version '%d'", vers); | 
    ||
249  | 
    goto done;  | 
    ||
250  | 
    }  | 
    ||
251  | 
    |||
252  | 
    ber_free(&ber);  | 
    ||
253  | 
    return (0);  | 
    ||
254  | 
    |||
255  | 
    done:  | 
    ||
256  | 
    ber_free(&ber);  | 
    ||
257  | 
    if (*req)  | 
    ||
258  | 
    ber_free_elements(*req);  | 
    ||
259  | 
    *req = NULL;  | 
    ||
260  | 
    return (-1);  | 
    ||
261  | 
    }  | 
    ||
262  | 
    |||
263  | 
    void  | 
    ||
264  | 
    traphandler_v1translate(struct ber_oid *oid, u_int gtype, u_int etype)  | 
    ||
265  | 
    { | 
    ||
266  | 
    /* append 'specific trap' number to 'enterprise specific' traps */  | 
    ||
267  | 
    	if (gtype >= 6) { | 
    ||
268  | 
    oid->bo_id[oid->bo_n] = 0;  | 
    ||
269  | 
    oid->bo_id[oid->bo_n + 1] = etype;  | 
    ||
270  | 
    oid->bo_n += 2;  | 
    ||
271  | 
    }  | 
    ||
272  | 
    }  | 
    ||
273  | 
    |||
274  | 
    int  | 
    ||
275  | 
    traphandler_priv_recvmsg(struct privsep_proc *p, struct imsg *imsg)  | 
    ||
276  | 
    { | 
    ||
277  | 
    ssize_t n;  | 
    ||
278  | 
    pid_t pid;  | 
    ||
279  | 
    |||
280  | 
    ✗✓ | 8  | 
    if ((n = IMSG_DATA_SIZE(imsg)) <= 0)  | 
    
281  | 
    return (-1); /* XXX */  | 
    ||
282  | 
    |||
283  | 
    ✗✗✓ | 4  | 
    	switch ((pid = fork())) { | 
    
284  | 
    case 0:  | 
    ||
285  | 
    traphandler_fork_handler(p, imsg);  | 
    ||
286  | 
    /* NOTREACHED */  | 
    ||
287  | 
    case -1:  | 
    ||
288  | 
    		log_warn("%s: couldn't fork traphandler", __func__); | 
    ||
289  | 
    return (0);  | 
    ||
290  | 
    default:  | 
    ||
291  | 
    4  | 
    		log_debug("forked process %i to handle trap", pid); | 
    |
292  | 
    4  | 
    return (0);  | 
    |
293  | 
    }  | 
    ||
294  | 
    /* NOTREACHED */  | 
    ||
295  | 
    4  | 
    }  | 
    |
296  | 
    |||
297  | 
    int  | 
    ||
298  | 
    traphandler_fork_handler(struct privsep_proc *p, struct imsg *imsg)  | 
    ||
299  | 
    { | 
    ||
300  | 
    struct privsep *ps = p->p_ps;  | 
    ||
301  | 
    struct snmpd *env = ps->ps_env;  | 
    ||
302  | 
    char oidbuf[SNMP_MAX_OID_STRLEN];  | 
    ||
303  | 
    struct sockaddr *sa;  | 
    ||
304  | 
    char *buf;  | 
    ||
305  | 
    ssize_t n;  | 
    ||
306  | 
    struct ber_element *req, *iter;  | 
    ||
307  | 
    struct trapcmd *cmd;  | 
    ||
308  | 
    struct ber_oid trapoid;  | 
    ||
309  | 
    u_int uptime;  | 
    ||
310  | 
    struct passwd *pw;  | 
    ||
311  | 
    int verbose;  | 
    ||
312  | 
    |||
313  | 
    pw = ps->ps_pw;  | 
    ||
314  | 
    verbose = log_getverbose();  | 
    ||
315  | 
    |||
316  | 
    if (setgroups(1, &pw->pw_gid) ||  | 
    ||
317  | 
    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||  | 
    ||
318  | 
    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))  | 
    ||
319  | 
    		fatal("traphandler_fork_handler: cannot drop privileges"); | 
    ||
320  | 
    |||
321  | 
    closefrom(STDERR_FILENO + 1);  | 
    ||
322  | 
    |||
323  | 
    log_init((env->sc_flags & SNMPD_F_DEBUG) ? 1 : 0, LOG_DAEMON);  | 
    ||
324  | 
    log_setverbose(verbose);  | 
    ||
325  | 
    log_procinit(p->p_title);  | 
    ||
326  | 
    |||
327  | 
    n = IMSG_DATA_SIZE(imsg);  | 
    ||
328  | 
    |||
329  | 
    sa = imsg->data;  | 
    ||
330  | 
    n -= sa->sa_len;  | 
    ||
331  | 
    buf = (char *)imsg->data + sa->sa_len;  | 
    ||
332  | 
    |||
333  | 
    if (traphandler_parse(buf, n, &req, &iter, &uptime, &trapoid) == -1)  | 
    ||
334  | 
    		fatalx("couldn't parse SNMP trap message"); | 
    ||
335  | 
    |||
336  | 
    smi_oid2string(&trapoid, oidbuf, sizeof(oidbuf), 0);  | 
    ||
337  | 
    if ((cmd = trapcmd_lookup(&trapoid)) != NULL)  | 
    ||
338  | 
    trapcmd_exec(cmd, sa, iter, oidbuf, uptime);  | 
    ||
339  | 
    |||
340  | 
    if (req != NULL)  | 
    ||
341  | 
    ber_free_elements(req);  | 
    ||
342  | 
    |||
343  | 
    exit(0);  | 
    ||
344  | 
    }  | 
    ||
345  | 
    |||
346  | 
    void  | 
    ||
347  | 
    trapcmd_exec(struct trapcmd *cmd, struct sockaddr *sa,  | 
    ||
348  | 
    struct ber_element *iter, char *trapoid, u_int uptime)  | 
    ||
349  | 
    { | 
    ||
350  | 
    char oidbuf[SNMP_MAX_OID_STRLEN];  | 
    ||
351  | 
    struct ber_oid oid;  | 
    ||
352  | 
    struct ber_element *elm;  | 
    ||
353  | 
    int n, s[2], status = 0;  | 
    ||
354  | 
    char *value, *host;  | 
    ||
355  | 
    pid_t child = -1;  | 
    ||
356  | 
    |||
357  | 
    	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, s) == -1) { | 
    ||
358  | 
    		log_warn("could not create pipe for OID '%s'", | 
    ||
359  | 
    smi_oid2string(cmd->cmd_oid, oidbuf, sizeof(oidbuf), 0));  | 
    ||
360  | 
    return;  | 
    ||
361  | 
    }  | 
    ||
362  | 
    |||
363  | 
    	switch (child = fork()) { | 
    ||
364  | 
    case 0:  | 
    ||
365  | 
    dup2(s[1], STDIN_FILENO);  | 
    ||
366  | 
    |||
367  | 
    close(s[0]);  | 
    ||
368  | 
    close(s[1]);  | 
    ||
369  | 
    |||
370  | 
    closefrom(STDERR_FILENO + 1);  | 
    ||
371  | 
    |||
372  | 
    /* path to command is in argv[0], args follow */  | 
    ||
373  | 
    execve(cmd->cmd_argv[0], cmd->cmd_argv, NULL);  | 
    ||
374  | 
    |||
375  | 
    /* this shouldn't happen */  | 
    ||
376  | 
    		log_warn("could not exec trap command for OID '%s'", | 
    ||
377  | 
    smi_oid2string(cmd->cmd_oid, oidbuf, sizeof(oidbuf), 0));  | 
    ||
378  | 
    _exit(1);  | 
    ||
379  | 
    /* NOTREACHED */  | 
    ||
380  | 
    |||
381  | 
    case -1:  | 
    ||
382  | 
    		log_warn("could not fork trap command for OID '%s'", | 
    ||
383  | 
    smi_oid2string(cmd->cmd_oid, oidbuf, sizeof(oidbuf), 0));  | 
    ||
384  | 
    close(s[0]);  | 
    ||
385  | 
    close(s[1]);  | 
    ||
386  | 
    return;  | 
    ||
387  | 
    }  | 
    ||
388  | 
    |||
389  | 
    close(s[1]);  | 
    ||
390  | 
    |||
391  | 
    host = traphandler_hostname(sa, 0);  | 
    ||
392  | 
    if (dprintf(s[0], "%s\n", host) == -1)  | 
    ||
393  | 
    goto out;  | 
    ||
394  | 
    |||
395  | 
    host = traphandler_hostname(sa, 1);  | 
    ||
396  | 
    if (dprintf(s[0], "%s\n", host) == -1)  | 
    ||
397  | 
    goto out;  | 
    ||
398  | 
    |||
399  | 
    if (dprintf(s[0],  | 
    ||
400  | 
    "iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.0 %u\n",  | 
    ||
401  | 
    uptime) == -1)  | 
    ||
402  | 
    goto out;  | 
    ||
403  | 
    |||
404  | 
    if (dprintf(s[0],  | 
    ||
405  | 
    "iso.org.dod.internet.snmpV2.snmpModules.snmpMIB.snmpMIBObjects."  | 
    ||
406  | 
    "snmpTrap.snmpTrapOID.0 %s\n", trapoid) == -1)  | 
    ||
407  | 
    goto out;  | 
    ||
408  | 
    |||
409  | 
    	for (; iter != NULL; iter = iter->be_next) { | 
    ||
410  | 
    		if (ber_scanf_elements(iter, "{oe}", &oid, &elm) == -1) | 
    ||
411  | 
    goto out;  | 
    ||
412  | 
    if ((value = smi_print_element(elm)) == NULL)  | 
    ||
413  | 
    goto out;  | 
    ||
414  | 
    smi_oid2string(&oid, oidbuf, sizeof(oidbuf), 0);  | 
    ||
415  | 
    n = dprintf(s[0], "%s %s\n", oidbuf, value);  | 
    ||
416  | 
    free(value);  | 
    ||
417  | 
    if (n == -1)  | 
    ||
418  | 
    goto out;  | 
    ||
419  | 
    }  | 
    ||
420  | 
    out:  | 
    ||
421  | 
    close(s[0]);  | 
    ||
422  | 
    waitpid(child, &status, 0);  | 
    ||
423  | 
    |||
424  | 
    	if (WIFSIGNALED(status)) { | 
    ||
425  | 
    		log_warnx("child %i exited due to receipt of signal %i", | 
    ||
426  | 
    child, WTERMSIG(status));  | 
    ||
427  | 
    	} else if (WEXITSTATUS(status) != 0) { | 
    ||
428  | 
    		log_warnx("child %i exited with status %i", | 
    ||
429  | 
    child, WEXITSTATUS(status));  | 
    ||
430  | 
    	} else { | 
    ||
431  | 
    		log_debug("child %i finished", child); | 
    ||
432  | 
    }  | 
    ||
433  | 
    close(s[1]);  | 
    ||
434  | 
    |||
435  | 
    return;  | 
    ||
436  | 
    }  | 
    ||
437  | 
    |||
438  | 
    char *  | 
    ||
439  | 
    traphandler_hostname(struct sockaddr *sa, int numeric)  | 
    ||
440  | 
    { | 
    ||
441  | 
    static char buf[NI_MAXHOST];  | 
    ||
442  | 
    int flag = 0;  | 
    ||
443  | 
    |||
444  | 
    if (numeric)  | 
    ||
445  | 
    flag = NI_NUMERICHOST;  | 
    ||
446  | 
    |||
447  | 
    bzero(buf, sizeof(buf));  | 
    ||
448  | 
    if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, flag) != 0)  | 
    ||
449  | 
    		return ("Unknown"); | 
    ||
450  | 
    |||
451  | 
    return (buf);  | 
    ||
452  | 
    }  | 
    ||
453  | 
    |||
454  | 
    struct trapcmd *  | 
    ||
455  | 
    trapcmd_lookup(struct ber_oid *oid)  | 
    ||
456  | 
    { | 
    ||
457  | 
    struct trapcmd key, *res;  | 
    ||
458  | 
    |||
459  | 
    bzero(&key, sizeof(key));  | 
    ||
460  | 
    key.cmd_oid = oid;  | 
    ||
461  | 
    |||
462  | 
    if ((res = RB_FIND(trapcmd_tree, &trapcmd_tree, &key)) == NULL)  | 
    ||
463  | 
    res = key.cmd_maybe;  | 
    ||
464  | 
    return (res);  | 
    ||
465  | 
    }  | 
    ||
466  | 
    |||
467  | 
    int  | 
    ||
468  | 
    trapcmd_cmp(struct trapcmd *cmd1, struct trapcmd *cmd2)  | 
    ||
469  | 
    { | 
    ||
470  | 
    int ret;  | 
    ||
471  | 
    |||
472  | 
    ret = ber_oid_cmp(cmd2->cmd_oid, cmd1->cmd_oid);  | 
    ||
473  | 
    	switch (ret) { | 
    ||
474  | 
    case 2:  | 
    ||
475  | 
    /* cmd1 is a child of cmd2 */  | 
    ||
476  | 
    cmd1->cmd_maybe = cmd2;  | 
    ||
477  | 
    return (1);  | 
    ||
478  | 
    default:  | 
    ||
479  | 
    return (ret);  | 
    ||
480  | 
    }  | 
    ||
481  | 
    /* NOTREACHED */  | 
    ||
482  | 
    }  | 
    ||
483  | 
    |||
484  | 
    int  | 
    ||
485  | 
    trapcmd_add(struct trapcmd *cmd)  | 
    ||
486  | 
    { | 
    ||
487  | 
    8  | 
    return (RB_INSERT(trapcmd_tree, &trapcmd_tree, cmd) != NULL);  | 
    |
488  | 
    }  | 
    ||
489  | 
    |||
490  | 
    void  | 
    ||
491  | 
    trapcmd_free(struct trapcmd *cmd)  | 
    ||
492  | 
    { | 
    ||
493  | 
    RB_REMOVE(trapcmd_tree, &trapcmd_tree, cmd);  | 
    ||
494  | 
    free(cmd->cmd_argv);  | 
    ||
495  | 
    free(cmd->cmd_oid);  | 
    ||
496  | 
    free(cmd);  | 
    ||
497  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |