1 /* $OpenBSD: smi.c,v 1.5 2008/01/16 09:51:15 reyk Exp $ */ 2 3 /* 4 * Copyright (c) 2007, 2008 Reyk Floeter <reyk@vantronix.net> 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/param.h> 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 #include <sys/socket.h> 24 #include <sys/un.h> 25 #include <sys/tree.h> 26 #include <sys/sysctl.h> 27 28 #include <net/if.h> 29 #include <net/if_dl.h> 30 #include <net/if_arp.h> 31 #include <net/if_media.h> 32 #include <net/route.h> 33 #include <netinet/in.h> 34 #include <netinet/if_ether.h> 35 #include <arpa/inet.h> 36 37 #include <stdlib.h> 38 #include <stdio.h> 39 #include <errno.h> 40 #include <event.h> 41 #include <fcntl.h> 42 #include <string.h> 43 #include <unistd.h> 44 #include <pwd.h> 45 46 #include "snmpd.h" 47 #include "mib.h" 48 49 extern struct snmpd *env; 50 51 RB_HEAD(oidtree, oid); 52 RB_PROTOTYPE(oidtree, oid, o_element, smi_oid_cmp); 53 struct oidtree smi_oidtree; 54 55 u_long 56 smi_getticks(void) 57 { 58 struct timeval now, run; 59 u_long ticks; 60 61 gettimeofday(&now, NULL); 62 if (timercmp(&now, &env->sc_starttime, <=)) 63 return (0); 64 timersub(&now, &env->sc_starttime, &run); 65 ticks = run.tv_sec * 100; 66 if (run.tv_usec) 67 ticks += run.tv_usec / 10000; 68 69 return (ticks); 70 } 71 72 void 73 smi_oidlen(struct ber_oid *o) 74 { 75 size_t i; 76 for (i = 0; i < BER_MAX_OID_LEN && o->bo_id[i] != 0; i++); 77 o->bo_n = i; 78 } 79 80 char * 81 smi_oidstring(struct ber_oid *o, char *buf, size_t len) 82 { 83 char str[256]; 84 struct oid *value, key; 85 size_t i, lookup = 1; 86 87 bzero(buf, len); 88 bzero(&key, sizeof(key)); 89 bcopy(o, &key.o_id, sizeof(struct ber_oid)); 90 key.o_flags |= OID_KEY; /* do not match wildcards */ 91 92 if (env->sc_flags & SNMPD_F_NONAMES) 93 lookup = 0; 94 95 for (i = 0; i < o->bo_n; i++) { 96 key.o_oidlen = i + 1; 97 if (lookup && 98 (value = RB_FIND(oidtree, &smi_oidtree, &key)) != NULL) 99 snprintf(str, sizeof(str), "%s", value->o_name); 100 else 101 snprintf(str, sizeof(str), "%d", key.o_oid[i]); 102 strlcat(buf, str, len); 103 if (i < (o->bo_n - 1)) 104 strlcat(buf, ".", len); 105 } 106 107 return (buf); 108 } 109 110 void 111 smi_delete(struct oid *oid) 112 { 113 struct oid key, *value; 114 115 bcopy(&oid->o_id, &key.o_id, sizeof(struct ber_oid)); 116 if ((value = RB_FIND(oidtree, &smi_oidtree, &key)) != NULL && 117 value == oid) 118 RB_REMOVE(oidtree, &smi_oidtree, value); 119 120 if (oid->o_data != NULL) 121 free(oid->o_data); 122 if (oid->o_flags & OID_DYNAMIC) { 123 free(oid->o_name); 124 free(oid); 125 } 126 } 127 128 void 129 smi_insert(struct oid *oid) 130 { 131 struct oid key, *value; 132 133 if ((oid->o_flags & OID_TABLE) && oid->o_get == NULL) 134 fatalx("smi_insert: invalid MIB table"); 135 136 bcopy(&oid->o_id, &key.o_id, sizeof(struct ber_oid)); 137 value = RB_FIND(oidtree, &smi_oidtree, &key); 138 if (value != NULL) 139 smi_delete(value); 140 141 RB_INSERT(oidtree, &smi_oidtree, oid); 142 } 143 144 void 145 smi_mibtree(struct oid *oids) 146 { 147 struct oid *oid, *decl; 148 size_t i; 149 150 for (i = 0; oids[i].o_oid[0] != 0; i++) { 151 oid = &oids[i]; 152 smi_oidlen(&oid->o_id); 153 if (oid->o_name != NULL) { 154 if ((oid->o_flags & OID_TABLE) && oid->o_get == NULL) 155 fatalx("smi_mibtree: invalid MIB table"); 156 RB_INSERT(oidtree, &smi_oidtree, oid); 157 continue; 158 } 159 decl = RB_FIND(oidtree, &smi_oidtree, oid); 160 if (decl == NULL) 161 fatalx("smi_mibtree: undeclared MIB"); 162 decl->o_flags = oid->o_flags; 163 decl->o_get = oid->o_get; 164 decl->o_set = oid->o_set; 165 decl->o_table = oid->o_table; 166 decl->o_val = oid->o_val; 167 decl->o_data = oid->o_data; 168 } 169 } 170 171 int 172 smi_init(void) 173 { 174 RB_INIT(&smi_oidtree); 175 mib_init(); 176 return (0); 177 } 178 179 struct oid * 180 smi_find(struct oid *oid) 181 { 182 return (RB_FIND(oidtree, &smi_oidtree, oid)); 183 } 184 185 struct oid * 186 smi_next(struct oid *oid) 187 { 188 return (RB_NEXT(oidtree, &smi_oidtree, oid)); 189 } 190 191 struct oid * 192 smi_foreach(struct oid *oid, u_int flags) 193 { 194 /* 195 * Traverse the tree of MIBs with the option to check 196 * for specific OID flags. 197 */ 198 if (oid == NULL) { 199 oid = RB_MIN(oidtree, &smi_oidtree); 200 if (oid == NULL) 201 return (NULL); 202 if (flags == 0 || (oid->o_flags & flags)) 203 return (oid); 204 } 205 for (;;) { 206 oid = RB_NEXT(oidtree, &smi_oidtree, oid); 207 if (oid == NULL) 208 break; 209 if (flags == 0 || (oid->o_flags & flags)) 210 return (oid); 211 } 212 213 return (oid); 214 } 215 216 int 217 smi_oid_cmp(struct oid *a, struct oid *b) 218 { 219 size_t i; 220 221 for (i = 0; i < MIN(a->o_oidlen, b->o_oidlen); i++) 222 if (a->o_oid[i] != b->o_oid[i]) 223 return (a->o_oid[i] - b->o_oid[i]); 224 225 /* 226 * Return success if the matched object is a table 227 * (it will match any sub-elements) 228 */ 229 if ((b->o_flags & OID_TABLE) && 230 (a->o_flags & OID_KEY) == 0 && 231 (a->o_oidlen > b->o_oidlen)) 232 return (0); 233 234 return (a->o_oidlen - b->o_oidlen); 235 } 236 237 RB_GENERATE(oidtree, oid, o_element, smi_oid_cmp); 238