/* $OpenBSD: snmpd.h,v 1.106 2022/10/06 14:41:08 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 #include "log.h" #include "smi.h" #include "snmp.h" #ifndef nitems #define nitems(_a) (sizeof((_a)) / sizeof((_a)[0])) #endif /* * common definitions for snmpd */ #define CONF_FILE "/etc/snmpd.conf" #define SNMPD_BACKEND "/usr/libexec/snmpd" #define SNMPD_USER "_snmpd" #define SNMP_PORT "161" #define SNMPTRAP_PORT "162" #define AGENTX_MASTER_PATH "/var/agentx/master" #define AGENTX_GROUP "_agentx" #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 enum imsg_type { IMSG_NONE, IMSG_CTL_VERBOSE, IMSG_CTL_PROCFD, IMSG_TRAP_EXEC, IMSG_AX_FD }; struct imsgev { struct imsgbuf ibuf; void (*handler)(int, short, void *); struct event ev; struct privsep_proc *proc; void *data; short events; const char *name; }; #define IMSG_SIZE_CHECK(imsg, p) do { \ if (IMSG_DATA_SIZE(imsg) < sizeof(*p)) \ fatalx("bad length imsg received"); \ } while (0) #define IMSG_DATA_SIZE(imsg) ((imsg)->hdr.len - IMSG_HEADER_SIZE) enum privsep_procid { PROC_PARENT, /* Parent process and application interface */ PROC_SNMPE, /* SNMP engine */ PROC_MAX }; extern enum privsep_procid privsep_process; struct privsep_pipes { int *pp_pipes[PROC_MAX]; }; struct privsep { struct privsep_pipes *ps_pipes[PROC_MAX]; struct privsep_pipes *ps_pp; struct imsgev *ps_ievs[PROC_MAX]; const char *ps_title[PROC_MAX]; pid_t ps_pid[PROC_MAX]; struct passwd *ps_pw; u_int ps_instances[PROC_MAX]; u_int ps_instance; int ps_noaction; /* Event and signal handlers */ struct event ps_evsigint; struct event ps_evsigterm; struct event ps_evsigchld; struct event ps_evsighup; struct event ps_evsigpipe; struct event ps_evsigusr1; void *ps_env; }; struct privsep_proc { const char *p_title; enum privsep_procid p_id; int (*p_cb)(int, struct privsep_proc *, struct imsg *); void (*p_init)(struct privsep *, struct privsep_proc *); void (*p_shutdown)(void); const char *p_chroot; struct privsep *p_ps; struct passwd *p_pw; }; struct privsep_fd { enum privsep_procid pf_procid; unsigned int pf_instance; }; #define PROC_PARENT_SOCK_FILENO 3 #define PROC_MAX_INSTANCES 32 #if DEBUG #define DPRINTF log_debug #else #define DPRINTF(x...) do {} while(0) #endif /* * Message Processing Subsystem (mps) */ struct oid { struct ber_oid o_id; #define o_oid o_id.bo_id #define o_oidlen o_id.bo_n char *o_name; u_int o_flags; int (*o_get)(struct oid *, struct ber_oid *, struct ber_element **); struct ber_oid *(*o_table)(struct oid *, struct ber_oid *, struct ber_oid *); long long o_val; void *o_data; RB_ENTRY(oid) o_element; RB_ENTRY(oid) o_keyword; }; #define OID_RD 0x01 #define OID_WR 0x02 #define OID_IFSET 0x04 /* only if user-specified value */ #define OID_DYNAMIC 0x08 /* free allocated data */ #define OID_TABLE 0x10 /* dynamic sub-elements */ #define OID_MIB 0x20 /* root-OID of a supported MIB */ #define OID_KEY 0x40 /* lookup tables */ #define OID_RS (OID_RD|OID_IFSET) #define OID_TRD (OID_RD|OID_TABLE) #define OID_NOTSET(_oid) \ (((_oid)->o_flags & OID_IFSET) && \ ((_oid)->o_data == NULL) && ((_oid)->o_val == 0)) #define OID(...) { { __VA_ARGS__ } } #define MIBDECL(...) { { MIB_##__VA_ARGS__ } }, #__VA_ARGS__ #define MIB(...) { { MIB_##__VA_ARGS__ } }, NULL #define MIBEND { { 0 } }, NULL /* * daemon structures */ #define MSG_HAS_AUTH(m) (((m)->sm_flags & SNMP_MSGFLAG_AUTH) != 0) #define MSG_HAS_PRIV(m) (((m)->sm_flags & SNMP_MSGFLAG_PRIV) != 0) #define MSG_SECLEVEL(m) ((m)->sm_flags & SNMP_MSGFLAG_SECMASK) #define MSG_REPORT(m) (((m)->sm_flags & SNMP_MSGFLAG_REPORT) != 0) struct snmp_message { int sm_sock; struct sockaddr_storage sm_ss; socklen_t sm_slen; int sm_sock_tcp; int sm_aflags; enum snmp_pdutype sm_pdutype; struct event sm_sockev; char sm_host[HOST_NAME_MAX+1]; in_port_t sm_port; struct sockaddr_storage sm_local_ss; socklen_t sm_local_slen; struct ber sm_ber; struct ber_element *sm_req; struct ber_element *sm_resp; u_int8_t sm_data[READ_BUF_SIZE]; size_t sm_datalen; uint32_t sm_transactionid; u_int sm_version; /* V1, V2c */ char sm_community[SNMPD_MAXCOMMUNITYLEN]; /* V3 */ long long sm_msgid; long long sm_max_msg_size; u_int8_t sm_flags; long long sm_secmodel; u_int32_t sm_engine_boots; u_int32_t sm_engine_time; uint8_t sm_ctxengineid[SNMPD_MAXENGINEIDLEN]; size_t sm_ctxengineid_len; char sm_ctxname[SNMPD_MAXCONTEXNAMELEN+1]; /* USM */ char sm_username[SNMPD_MAXUSERNAMELEN+1]; struct usmuser *sm_user; size_t sm_digest_offs; char sm_salt[SNMP_USM_SALTLEN]; int sm_usmerr; long long sm_request; const char *sm_errstr; long long sm_error; #define sm_nonrepeaters sm_error long long sm_errorindex; #define sm_maxrepetitions sm_errorindex struct ber_element *sm_pdu; struct ber_element *sm_pduend; struct ber_element *sm_varbind; struct ber_element *sm_varbindresp; RB_ENTRY(snmp_message) sm_entry; }; RB_HEAD(snmp_messages, snmp_message); extern struct snmp_messages snmp_messages; /* Defined in SNMPv2-MIB.txt (RFC 3418) */ struct snmp_stats { u_int32_t snmp_inpkts; u_int32_t snmp_outpkts; u_int32_t snmp_inbadversions; u_int32_t snmp_inbadcommunitynames; u_int32_t snmp_inbadcommunityuses; u_int32_t snmp_inasnparseerrs; u_int32_t snmp_intoobigs; u_int32_t snmp_innosuchnames; u_int32_t snmp_inbadvalues; u_int32_t snmp_inreadonlys; u_int32_t snmp_ingenerrs; u_int32_t snmp_intotalreqvars; u_int32_t snmp_intotalsetvars; u_int32_t snmp_ingetrequests; u_int32_t snmp_ingetnexts; u_int32_t snmp_insetrequests; u_int32_t snmp_ingetresponses; u_int32_t snmp_intraps; u_int32_t snmp_outtoobigs; u_int32_t snmp_outnosuchnames; u_int32_t snmp_outbadvalues; u_int32_t snmp_outgenerrs; u_int32_t snmp_outgetrequests; u_int32_t snmp_outgetnexts; u_int32_t snmp_outsetrequests; u_int32_t snmp_outgetresponses; u_int32_t snmp_outtraps; int snmp_enableauthentraps; u_int32_t snmp_silentdrops; u_int32_t snmp_proxydrops; /* USM stats (RFC 3414) */ u_int32_t snmp_usmbadseclevel; u_int32_t snmp_usmtimewindow; u_int32_t snmp_usmnosuchuser; u_int32_t snmp_usmnosuchengine; u_int32_t snmp_usmwrongdigest; u_int32_t snmp_usmdecrypterr; }; struct address { struct sockaddr_storage ss; in_port_t port; int type; int flags; int fd; struct event ev; struct event evt; TAILQ_ENTRY(address) entry; }; TAILQ_HEAD(addresslist, address); struct agentx_master { int axm_fd; struct sockaddr_un axm_sun; uid_t axm_owner; gid_t axm_group; mode_t axm_mode; struct event axm_ev; TAILQ_ENTRY(agentx_master) axm_entry; }; TAILQ_HEAD(axmasterlist, agentx_master); #define ADDRESS_FLAG_READ 0x01 #define ADDRESS_FLAG_WRITE 0x02 #define ADDRESS_FLAG_NOTIFY 0x04 #define ADDRESS_FLAG_PERM \ (ADDRESS_FLAG_READ | ADDRESS_FLAG_WRITE | ADDRESS_FLAG_NOTIFY) #define ADDRESS_FLAG_SNMPV1 0x10 #define ADDRESS_FLAG_SNMPV2 0x20 #define ADDRESS_FLAG_SNMPV3 0x40 #define ADDRESS_FLAG_MPS \ (ADDRESS_FLAG_SNMPV1 | ADDRESS_FLAG_SNMPV2 | ADDRESS_FLAG_SNMPV3) struct trap_address { struct sockaddr_storage ta_ss; struct sockaddr_storage ta_sslocal; int ta_version; union { char ta_community[SNMPD_MAXCOMMUNITYLEN]; struct { char *ta_usmusername; struct usmuser *ta_usmuser; int ta_seclevel; }; }; struct ber_oid *ta_oid; TAILQ_ENTRY(trap_address) entry; }; TAILQ_HEAD(trap_addresslist, trap_address); enum usmauth { AUTH_NONE = 0, AUTH_MD5, /* HMAC-MD5-96, RFC3414 */ AUTH_SHA1, /* HMAC-SHA-96, RFC3414 */ AUTH_SHA224, /* usmHMAC128SHA224AuthProtocol. RFC7860 */ AUTH_SHA256, /* usmHMAC192SHA256AuthProtocol. RFC7860 */ AUTH_SHA384, /* usmHMAC256SHA384AuthProtocol. RFC7860 */ AUTH_SHA512 /* usmHMAC384SHA512AuthProtocol. RFC7860 */ }; #define AUTH_DEFAULT AUTH_SHA1 /* Default digest */ enum usmpriv { PRIV_NONE = 0, PRIV_DES, /* CBC-DES, RFC3414 */ PRIV_AES /* CFB128-AES-128, RFC3826 */ }; #define PRIV_DEFAULT PRIV_AES /* Default cipher */ struct usmuser { char *uu_name; int uu_seclevel; enum usmauth uu_auth; char *uu_authkey; unsigned uu_authkeylen; enum usmpriv uu_priv; char *uu_privkey; unsigned long long uu_salt; SLIST_ENTRY(usmuser) uu_next; }; struct snmpd { u_int8_t sc_flags; #define SNMPD_F_VERBOSE 0x01 #define SNMPD_F_DEBUG 0x02 #define SNMPD_F_NONAMES 0x04 const char *sc_confpath; struct addresslist sc_addresses; struct axmasterlist sc_agentx_masters; struct timeval sc_starttime; u_int32_t sc_engine_boots; char sc_rdcommunity[SNMPD_MAXCOMMUNITYLEN]; char sc_rwcommunity[SNMPD_MAXCOMMUNITYLEN]; char sc_trcommunity[SNMPD_MAXCOMMUNITYLEN]; uint8_t sc_engineid[SNMPD_MAXENGINEIDLEN]; size_t sc_engineid_len; struct snmp_stats sc_stats; struct trap_addresslist sc_trapreceivers; struct ber_oid *sc_blocklist; size_t sc_nblocklist; int sc_rtfilter; int sc_min_seclevel; int sc_traphandler; struct privsep sc_ps; }; struct trapcmd { struct ber_oid *cmd_oid; /* sideways return for intermediate lookups */ struct trapcmd *cmd_maybe; int cmd_argc; char **cmd_argv; RB_ENTRY(trapcmd) cmd_entry; }; RB_HEAD(trapcmd_tree, trapcmd); extern struct trapcmd_tree trapcmd_tree; extern struct snmpd *snmpd_env; /* parse.y */ struct snmpd *parse_config(const char *, u_int); int cmdline_symset(char *); /* snmpe.c */ void snmpe(struct privsep *, struct privsep_proc *); void snmpe_shutdown(void); void snmpe_dispatchmsg(struct snmp_message *); void snmpe_response(struct snmp_message *); int snmp_messagecmp(struct snmp_message *, struct snmp_message *); RB_PROTOTYPE(snmp_messages, snmp_message, sm_entry, snmp_messagecmp) /* trap.c */ void trap_init(void); int trap_imsg(struct imsgev *, pid_t); int trap_send(struct ber_oid *, struct ber_element *); /* mps.c */ int mps_getreq(struct snmp_message *, struct ber_element *, struct ber_oid *, u_int); int mps_getnextreq(struct snmp_message *, struct ber_element *, struct ber_oid *); int mps_getbulkreq(struct snmp_message *, struct ber_element **, struct ber_element **, struct ber_oid *, int); int mps_set(struct ber_oid *, void *, long long); int mps_getstr(struct oid *, struct ber_oid *, struct ber_element **); int mps_getint(struct oid *, struct ber_oid *, struct ber_element **); int mps_getts(struct oid *, struct ber_oid *, struct ber_element **); /* smi.c */ int smi_init(void); void smi_mibtree(struct oid *); struct oid *smi_find(struct oid *); struct oid *smi_nfind(struct oid *); struct oid *smi_findkey(char *); struct oid *smi_next(struct oid *); struct oid *smi_foreach(struct oid *, u_int); void smi_oidlen(struct ber_oid *); void smi_scalar_oidlen(struct ber_oid *); int smi_string2oid(const char *, struct ber_oid *); void smi_delete(struct oid *); int smi_insert(struct oid *); int smi_oid_cmp(struct oid *, struct oid *); int smi_key_cmp(struct oid *, struct oid *); unsigned int smi_application(struct ber_element *); void smi_debug_elements(struct ber_element *); /* snmpd.c */ int snmpd_socket_af(struct sockaddr_storage *, int); u_long snmpd_engine_time(void); /* usm.c */ void usm_generate_keys(void); struct usmuser *usm_newuser(char *name, const char **); struct usmuser *usm_finduser(char *name); int usm_checkuser(struct usmuser *, const char **); struct ber_element *usm_decode(struct snmp_message *, struct ber_element *, const char **); struct ber_element *usm_encode(struct snmp_message *, struct ber_element *); struct ber_element *usm_encrypt(struct snmp_message *, struct ber_element *); void usm_finalize_digest(struct snmp_message *, char *, ssize_t); void usm_make_report(struct snmp_message *); const struct usmuser *usm_check_mincred(int, const char **); /* proc.c */ enum privsep_procid proc_getid(struct privsep_proc *, unsigned int, const char *); void proc_init(struct privsep *, struct privsep_proc *, unsigned int, int, int, char **, enum privsep_procid); void proc_kill(struct privsep *); void proc_connect(struct privsep *); void proc_dispatch(int, short event, void *); void proc_run(struct privsep *, struct privsep_proc *, struct privsep_proc *, u_int, void (*)(struct privsep *, struct privsep_proc *, void *), void *); void imsg_event_add(struct imsgev *); int imsg_compose_event(struct imsgev *, u_int16_t, u_int32_t, pid_t, int, void *, u_int16_t); int imsg_composev_event(struct imsgev *, u_int16_t, u_int32_t, pid_t, int, const struct iovec *, int); void proc_range(struct privsep *, enum privsep_procid, int *, int *); int proc_compose_imsg(struct privsep *, enum privsep_procid, int, u_int16_t, u_int32_t, int, void *, u_int16_t); int proc_compose(struct privsep *, enum privsep_procid, uint16_t, void *, uint16_t); int proc_composev_imsg(struct privsep *, enum privsep_procid, int, u_int16_t, u_int32_t, int, const struct iovec *, int); int proc_composev(struct privsep *, enum privsep_procid, uint16_t, const struct iovec *, int); int proc_forward_imsg(struct privsep *, struct imsg *, enum privsep_procid, int); struct imsgbuf * proc_ibuf(struct privsep *, enum privsep_procid, int); struct imsgev * proc_iev(struct privsep *, enum privsep_procid, int); int proc_flush_imsg(struct privsep *, enum privsep_procid, int); /* traphandler.c */ int traphandler_parse(struct snmp_message *); int traphandler_priv_recvmsg(struct privsep_proc *, struct imsg *); void trapcmd_free(struct trapcmd *); int trapcmd_add(struct trapcmd *); struct trapcmd * trapcmd_lookup(struct ber_oid *); /* 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 *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 */