xref: /openbsd/usr.sbin/snmpd/trap.c (revision 73471bf0)
1 /*	$OpenBSD: trap.c,v 1.37 2021/09/02 05:41:02 martijn Exp $	*/
2 
3 /*
4  * Copyright (c) 2008 Reyk Floeter <reyk@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/types.h>
21 #include <sys/stat.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <sys/tree.h>
25 
26 #include <net/if.h>
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <errno.h>
33 #include <event.h>
34 #include <fcntl.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <pwd.h>
38 
39 #include "snmpd.h"
40 #include "mib.h"
41 
42 void
43 trap_init(void)
44 {
45 	struct ber_oid	 trapoid = OID(MIB_coldStart);
46 
47 	/*
48 	 * Send a coldStart to notify that the daemon has been
49 	 * started and re-initialized.
50 	 */
51 	trap_send(&trapoid, NULL);
52 }
53 
54 int
55 trap_send(struct ber_oid *oid, struct ber_element *elm)
56 {
57 	struct trap_address	*tr;
58 	struct ber_element	*vblist, *trap;
59 	struct			 ber_oid uptime = OID(MIB_sysUpTime);
60 	struct			 ber_oid trapoid = OID(MIB_snmpTrapOID);
61 	char			 ostr[SNMP_MAX_OID_STRLEN];
62 	struct oid		 oa, ob;
63 	struct snmp_message	*msg;
64 
65 	if (TAILQ_EMPTY(&snmpd_env->sc_trapreceivers))
66 		return (0);
67 
68 	smi_scalar_oidlen(&uptime);
69 	smi_scalar_oidlen(&trapoid);
70 	smi_scalar_oidlen(oid);
71 
72 	smi_oid2string(oid, ostr, sizeof(ostr), 0);
73 	log_debug("trap_send: oid %s", ostr);
74 
75 	/* Setup OIDs to compare against the trap receiver MIB */
76 	bzero(&oa, sizeof(oa));
77 	bcopy(oid->bo_id, &oa.o_oid, sizeof(oa.o_oid));
78 	oa.o_oidlen = oid->bo_n;
79 	bzero(&ob, sizeof(ob));
80 	ob.o_flags = OID_TABLE;
81 
82 	/* Add mandatory varbind elements */
83 	trap = ober_add_sequence(NULL);
84 	vblist = ober_printf_elements(trap, "{Odt}{OO}",
85 	    &uptime, smi_getticks(),
86 	    BER_CLASS_APPLICATION, SNMP_T_TIMETICKS,
87 	    &trapoid, oid);
88 	if (elm != NULL)
89 		ober_link_elements(vblist, elm);
90 
91 	TAILQ_FOREACH(tr, &snmpd_env->sc_trapreceivers, entry) {
92 		if (tr->ta_oid != NULL && tr->ta_oid->bo_n) {
93 			/* The trap receiver may want only a specified MIB */
94 			bcopy(&tr->ta_oid->bo_id, &ob.o_oid,
95 			    sizeof(ob.o_oid));
96 			ob.o_oidlen = tr->ta_oid->bo_n;
97 			if (smi_oid_cmp(&oa, &ob) != 0)
98 				continue;
99 		}
100 
101 		if ((msg = calloc(1, sizeof(*msg))) == NULL)
102 			fatal("malloc");
103 		msg->sm_sock = snmpd_socket_af(&tr->ta_ss, SOCK_DGRAM);
104 		if (msg->sm_sock == -1) {
105 			log_warn("socket");
106 			free(msg);
107 			continue;
108 		}
109 		memcpy(&(msg->sm_ss), &(tr->ta_ss), sizeof(msg->sm_ss));
110 		msg->sm_slen = tr->ta_ss.ss_len;
111 		if (tr->ta_sslocal.ss_family != 0) {
112 			memcpy(&(msg->sm_local_ss), &(tr->ta_sslocal),
113 			    sizeof(msg->sm_local_ss));
114 			msg->sm_local_slen = tr->ta_sslocal.ss_len;
115 		}
116 		msg->sm_version = tr->ta_version;
117 		msg->sm_pdutype = SNMP_C_TRAPV2;
118 		ober_set_application(&msg->sm_ber, smi_application);
119 		msg->sm_request = arc4random();
120 		if ((msg->sm_varbindresp = ober_dup(trap->be_sub)) == NULL)
121 			fatal("malloc");
122 
123 		switch (msg->sm_version) {
124 		case SNMP_V2:
125 			(void)strlcpy(msg->sm_community, tr->ta_community,
126 			    sizeof(msg->sm_community));
127 			break;
128 		case SNMP_V3:
129 			msg->sm_msgid = msg->sm_request & INT32_MAX;
130 			msg->sm_max_msg_size = READ_BUF_SIZE;
131 			msg->sm_flags = tr->ta_seclevel != -1 ?
132 			    tr->ta_seclevel : snmpd_env->sc_min_seclevel;
133 			msg->sm_secmodel = SNMP_SEC_USM;
134 			msg->sm_engine_time = snmpd_engine_time();
135 			msg->sm_engine_boots = snmpd_env->sc_engine_boots;
136 			memcpy(msg->sm_ctxengineid, snmpd_env->sc_engineid,
137 			    snmpd_env->sc_engineid_len);
138 			msg->sm_ctxengineid_len =
139 			    snmpd_env->sc_engineid_len;
140 			(void)strlcpy(msg->sm_username, tr->ta_usmusername,
141 			    sizeof(msg->sm_username));
142 			msg->sm_user = tr->ta_usmuser;
143 			arc4random_buf(msg->sm_salt, sizeof(msg->sm_salt));
144 			break;
145 		}
146 
147 		snmpe_response(msg);
148 	}
149 	ober_free_elements(trap);
150 
151 	return 0;
152 }
153