1 /* $OpenBSD: util.c,v 1.5 2015/11/21 13:06:22 reyk Exp $ */ 2 /* 3 * Copyright (c) 2014 Bret Stephen Lambert <blambert@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/types.h> 19 #include <sys/queue.h> 20 #include <sys/socket.h> 21 22 #include <net/if.h> 23 24 #include <stdio.h> 25 #include <string.h> 26 #include <netdb.h> 27 #include <event.h> 28 29 #include "ber.h" 30 #include "snmp.h" 31 #include "snmpd.h" 32 33 /* log.c */ 34 extern int debug; 35 extern int verbose; 36 37 /* 38 * Convert variable bindings from AgentX to SNMP dialect. 39 */ 40 int 41 varbind_convert(struct agentx_pdu *pdu, struct agentx_varbind_hdr *vbhdr, 42 struct ber_element **varbind, struct ber_element **iter) 43 { 44 struct ber_oid oid; 45 u_int32_t d; 46 u_int64_t l; 47 int slen; 48 char *str; 49 struct ber_element *a; 50 int ret = AGENTX_ERR_NONE; 51 52 if (snmp_agentx_read_oid(pdu, (struct snmp_oid *)&oid) == -1) { 53 ret = AGENTX_ERR_PARSE_ERROR; 54 goto done; 55 } 56 57 *iter = ber_add_sequence(*iter); 58 if (*varbind == NULL) 59 *varbind = *iter; 60 61 a = ber_add_oid(*iter, &oid); 62 63 switch (vbhdr->type) { 64 case AGENTX_NO_SUCH_OBJECT: 65 case AGENTX_NO_SUCH_INSTANCE: 66 case AGENTX_END_OF_MIB_VIEW: 67 case AGENTX_NULL: 68 a = ber_add_null(a); 69 break; 70 71 case AGENTX_IP_ADDRESS: 72 case AGENTX_OPAQUE: 73 case AGENTX_OCTET_STRING: 74 str = snmp_agentx_read_octetstr(pdu, &slen); 75 if (str == NULL) { 76 ret = AGENTX_ERR_PARSE_ERROR; 77 goto done; 78 } 79 a = ber_add_nstring(a, str, slen); 80 break; 81 82 case AGENTX_OBJECT_IDENTIFIER: 83 if (snmp_agentx_read_oid(pdu, 84 (struct snmp_oid *)&oid) == -1) { 85 ret = AGENTX_ERR_PARSE_ERROR; 86 goto done; 87 } 88 a = ber_add_oid(a, &oid); 89 break; 90 91 case AGENTX_INTEGER: 92 case AGENTX_COUNTER32: 93 case AGENTX_GAUGE32: 94 case AGENTX_TIME_TICKS: 95 if (snmp_agentx_read_int(pdu, &d) == -1) { 96 ret = AGENTX_ERR_PARSE_ERROR; 97 goto done; 98 } 99 a = ber_add_integer(a, d); 100 break; 101 102 case AGENTX_COUNTER64: 103 if (snmp_agentx_read_int64(pdu, &l) == -1) { 104 ret = AGENTX_ERR_PARSE_ERROR; 105 goto done; 106 } 107 a = ber_add_integer(a, l); 108 break; 109 110 default: 111 log_debug("unknown data type '%i'", vbhdr->type); 112 ret = AGENTX_ERR_PARSE_ERROR; 113 goto done; 114 } 115 116 /* AgentX types correspond to BER types */ 117 switch (vbhdr->type) { 118 case BER_TYPE_INTEGER: 119 case BER_TYPE_BITSTRING: 120 case BER_TYPE_OCTETSTRING: 121 case BER_TYPE_NULL: 122 case BER_TYPE_OBJECT: 123 /* universal types */ 124 break; 125 126 /* Convert AgentX error types to SNMP error types */ 127 case AGENTX_NO_SUCH_OBJECT: 128 ber_set_header(a, BER_CLASS_CONTEXT, 0); 129 break; 130 case AGENTX_NO_SUCH_INSTANCE: 131 ber_set_header(a, BER_CLASS_CONTEXT, 1); 132 break; 133 134 case AGENTX_COUNTER32: 135 ber_set_header(a, BER_CLASS_APPLICATION, SNMP_COUNTER32); 136 break; 137 138 case AGENTX_GAUGE32: 139 ber_set_header(a, BER_CLASS_APPLICATION, SNMP_GAUGE32); 140 break; 141 142 case AGENTX_COUNTER64: 143 ber_set_header(a, BER_CLASS_APPLICATION, SNMP_COUNTER64); 144 break; 145 146 case AGENTX_IP_ADDRESS: 147 /* application 0 implicit 4-byte octet string per SNMPv2-SMI */ 148 break; 149 150 default: 151 /* application-specific types */ 152 ber_set_header(a, BER_CLASS_APPLICATION, vbhdr->type); 153 break; 154 } 155 done: 156 return (ret); 157 } 158 159 void 160 print_debug(const char *emsg, ...) 161 { 162 va_list ap; 163 164 if (debug && verbose > 2) { 165 va_start(ap, emsg); 166 vfprintf(stderr, emsg, ap); 167 va_end(ap); 168 } 169 } 170 171 void 172 print_verbose(const char *emsg, ...) 173 { 174 va_list ap; 175 176 if (verbose) { 177 va_start(ap, emsg); 178 vfprintf(stderr, emsg, ap); 179 va_end(ap); 180 } 181 } 182 183 const char * 184 log_in6addr(const struct in6_addr *addr) 185 { 186 static char buf[NI_MAXHOST]; 187 struct sockaddr_in6 sa_in6; 188 u_int16_t tmp16; 189 190 bzero(&sa_in6, sizeof(sa_in6)); 191 sa_in6.sin6_len = sizeof(sa_in6); 192 sa_in6.sin6_family = AF_INET6; 193 memcpy(&sa_in6.sin6_addr, addr, sizeof(sa_in6.sin6_addr)); 194 195 /* XXX thanks, KAME, for this ugliness... adopted from route/show.c */ 196 if (IN6_IS_ADDR_LINKLOCAL(&sa_in6.sin6_addr) || 197 IN6_IS_ADDR_MC_LINKLOCAL(&sa_in6.sin6_addr)) { 198 memcpy(&tmp16, &sa_in6.sin6_addr.s6_addr[2], sizeof(tmp16)); 199 sa_in6.sin6_scope_id = ntohs(tmp16); 200 sa_in6.sin6_addr.s6_addr[2] = 0; 201 sa_in6.sin6_addr.s6_addr[3] = 0; 202 } 203 204 return (print_host((struct sockaddr_storage *)&sa_in6, buf, 205 NI_MAXHOST)); 206 } 207 208 const char * 209 print_host(struct sockaddr_storage *ss, char *buf, size_t len) 210 { 211 if (getnameinfo((struct sockaddr *)ss, ss->ss_len, 212 buf, len, NULL, 0, NI_NUMERICHOST) != 0) { 213 buf[0] = '\0'; 214 return (NULL); 215 } 216 return (buf); 217 } 218