1 /* 2 * Copyright (c) 2001-2003 3 * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4 * All rights reserved. 5 * 6 * Author: Harti Brandt <harti@freebsd.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $Begemot: bsnmp/snmpd/snmpmod.h,v 1.28 2005/05/23 09:03:59 brandt_h Exp $ 30 * 31 * SNMP daemon data and functions exported to modules. 32 */ 33 #ifndef snmpmod_h_ 34 #define snmpmod_h_ 35 36 #include <sys/types.h> 37 #include <sys/socket.h> 38 #include <net/if.h> 39 #include <netinet/in.h> 40 #include "asn1.h" 41 #include "snmp.h" 42 #include "snmpagent.h" 43 44 #define MAX_MOD_ARGS 16 45 46 /* 47 * These macros help to handle object lists for SNMP tables. They use 48 * tail queues to hold the objects in ascending order in the list. 49 * ordering can be done either on an integer/unsigned field or and asn_oid. 50 */ 51 #define INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, INDEX) do { \ 52 __typeof (PTR) _lelem; \ 53 \ 54 TAILQ_FOREACH(_lelem, (LIST), LINK) \ 55 if (asn_compare_oid(&_lelem->INDEX, &(PTR)->INDEX) > 0) \ 56 break; \ 57 if (_lelem == NULL) \ 58 TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \ 59 else \ 60 TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \ 61 } while(0) 62 63 #define INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, INDEX) do { \ 64 __typeof (PTR) _lelem; \ 65 \ 66 TAILQ_FOREACH(_lelem, (LIST), LINK) \ 67 if ((asn_subid_t)_lelem->INDEX > (asn_subid_t)(PTR)->INDEX)\ 68 break; \ 69 if (_lelem == NULL) \ 70 TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \ 71 else \ 72 TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \ 73 } while(0) 74 75 #define FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ 76 __typeof (TAILQ_FIRST(LIST)) _lelem; \ 77 \ 78 TAILQ_FOREACH(_lelem, (LIST), LINK) \ 79 if (index_compare(OID, SUB, &_lelem->INDEX) == 0) \ 80 break; \ 81 (_lelem); \ 82 }) 83 84 #define NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ 85 __typeof (TAILQ_FIRST(LIST)) _lelem; \ 86 \ 87 TAILQ_FOREACH(_lelem, (LIST), LINK) \ 88 if (index_compare(OID, SUB, &_lelem->INDEX) < 0) \ 89 break; \ 90 (_lelem); \ 91 }) 92 93 #define FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ 94 __typeof (TAILQ_FIRST(LIST)) _lelem; \ 95 \ 96 if ((OID)->len - SUB != 1) \ 97 _lelem = NULL; \ 98 else \ 99 TAILQ_FOREACH(_lelem, (LIST), LINK) \ 100 if ((OID)->subs[SUB] == (asn_subid_t)_lelem->INDEX)\ 101 break; \ 102 (_lelem); \ 103 }) 104 105 #define NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ 106 __typeof (TAILQ_FIRST(LIST)) _lelem; \ 107 \ 108 if ((OID)->len - SUB == 0) \ 109 _lelem = TAILQ_FIRST(LIST); \ 110 else \ 111 TAILQ_FOREACH(_lelem, (LIST), LINK) \ 112 if ((OID)->subs[SUB] < (asn_subid_t)_lelem->INDEX)\ 113 break; \ 114 (_lelem); \ 115 }) 116 117 /* 118 * Macros for the case where the index field is called 'index' 119 */ 120 #define INSERT_OBJECT_OID_LINK(PTR, LIST, LINK) \ 121 INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, index) 122 123 #define INSERT_OBJECT_INT_LINK(PTR, LIST, LINK) do { \ 124 INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, index) 125 126 #define FIND_OBJECT_OID_LINK(LIST, OID, SUB, LINK) \ 127 FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index) 128 129 #define NEXT_OBJECT_OID_LINK(LIST, OID, SUB, LINK) \ 130 NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index) 131 132 #define FIND_OBJECT_INT_LINK(LIST, OID, SUB, LINK) \ 133 FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index) 134 135 #define NEXT_OBJECT_INT_LINK(LIST, OID, SUB, LINK) \ 136 NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index) 137 138 /* 139 * Macros for the case where the index field is called 'index' and the 140 * link field 'link'. 141 */ 142 #define INSERT_OBJECT_OID(PTR, LIST) \ 143 INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, link, index) 144 145 #define INSERT_OBJECT_INT(PTR, LIST) \ 146 INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, link, index) 147 148 #define FIND_OBJECT_OID(LIST, OID, SUB) \ 149 FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index) 150 151 #define FIND_OBJECT_INT(LIST, OID, SUB) \ 152 FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index) 153 154 #define NEXT_OBJECT_OID(LIST, OID, SUB) \ 155 NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index) 156 157 #define NEXT_OBJECT_INT(LIST, OID, SUB) \ 158 NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index) 159 160 struct lmodule; 161 162 /* The tick when the program was started. This is the absolute time of 163 * the start in 100th of a second. */ 164 extern uint64_t start_tick; 165 166 /* The tick when the current packet was received. This is the absolute 167 * time in 100th of second. */ 168 extern uint64_t this_tick; 169 170 /* Get the current absolute time in 100th of a second. */ 171 uint64_t get_ticks(void); 172 173 /* 174 * Return code for proxy function 175 */ 176 enum snmpd_proxy_err { 177 /* proxy code will process the PDU */ 178 SNMPD_PROXY_OK, 179 /* proxy code does not process PDU */ 180 SNMPD_PROXY_REJ, 181 /* drop this PDU */ 182 SNMPD_PROXY_DROP, 183 /* drop because of bad community */ 184 SNMPD_PROXY_BADCOMM, 185 /* drop because of bad community use */ 186 SNMPD_PROXY_BADCOMMUSE 187 }; 188 189 /* 190 * Input handling 191 */ 192 enum snmpd_input_err { 193 /* proceed with packet */ 194 SNMPD_INPUT_OK, 195 /* fatal error in packet, ignore it */ 196 SNMPD_INPUT_FAILED, 197 /* value encoding has wrong length in a SET operation */ 198 SNMPD_INPUT_VALBADLEN, 199 /* value encoding is out of range */ 200 SNMPD_INPUT_VALRANGE, 201 /* value has bad encoding */ 202 SNMPD_INPUT_VALBADENC, 203 /* need more data (truncated packet) */ 204 SNMPD_INPUT_TRUNC, 205 /* unknown community */ 206 SNMPD_INPUT_BAD_COMM, 207 }; 208 209 /* 210 * Every loadable module must have one of this structures with 211 * the external name 'config'. 212 */ 213 struct snmp_module { 214 /* a comment describing what this module implements */ 215 const char *comment; 216 217 /* the initialisation function */ 218 int (*init)(struct lmodule *, int argc, char *argv[]); 219 220 /* the finalisation function */ 221 int (*fini)(void); 222 223 /* the idle function */ 224 void (*idle)(void); 225 226 /* the dump function */ 227 void (*dump)(void); 228 229 /* re-configuration function */ 230 void (*config)(void); 231 232 /* start operation */ 233 void (*start)(void); 234 235 /* proxy a PDU */ 236 enum snmpd_proxy_err (*proxy)(struct snmp_pdu *, void *, 237 const struct asn_oid *, const struct sockaddr *, socklen_t, 238 enum snmpd_input_err, int32_t, int); 239 240 /* the tree this module is going to server */ 241 const struct snmp_node *tree; 242 u_int tree_size; 243 244 /* function called, when another module was unloaded/loaded */ 245 void (*loading)(const struct lmodule *, int); 246 }; 247 248 /* 249 * Stuff exported to modules 250 */ 251 252 /* 253 * The system group. 254 */ 255 struct systemg { 256 u_char *descr; 257 struct asn_oid object_id; 258 u_char *contact; 259 u_char *name; 260 u_char *location; 261 u_int32_t services; 262 u_int32_t or_last_change; 263 }; 264 extern struct systemg systemg; 265 266 /* 267 * Community support. 268 * 269 * We have 2 fixed communities for SNMP read and write access. Modules 270 * can create their communities dynamically. They are deleted automatically 271 * if the module is unloaded. 272 */ 273 #define COMM_INITIALIZE 0 274 #define COMM_READ 1 275 #define COMM_WRITE 2 276 277 u_int comm_define(u_int, const char *descr, struct lmodule *, const char *str); 278 const char * comm_string(u_int); 279 280 /* community for current packet */ 281 extern u_int community; 282 283 /* 284 * Well known OIDs 285 */ 286 extern const struct asn_oid oid_zeroDotZero; 287 288 /* 289 * Request ID ranges. 290 * 291 * A module can request a range of request ids and associate them with a 292 * type field. All ranges are deleted if a module is unloaded. 293 */ 294 u_int reqid_allocate(int size, struct lmodule *); 295 int32_t reqid_next(u_int type); 296 int32_t reqid_base(u_int type); 297 int reqid_istype(int32_t reqid, u_int type); 298 u_int reqid_type(int32_t reqid); 299 300 /* 301 * Timers. 302 */ 303 void *timer_start(u_int, void (*)(void *), void *, struct lmodule *); 304 void timer_stop(void *); 305 306 /* 307 * File descriptors 308 */ 309 void *fd_select(int, void (*)(int, void *), void *, struct lmodule *); 310 void fd_deselect(void *); 311 void fd_suspend(void *); 312 int fd_resume(void *); 313 314 /* 315 * Object resources 316 */ 317 u_int or_register(const struct asn_oid *, const char *, struct lmodule *); 318 void or_unregister(u_int); 319 320 /* 321 * Buffers 322 */ 323 void *buf_alloc(int tx); 324 size_t buf_size(int tx); 325 326 /* decode PDU and find community */ 327 enum snmpd_input_err snmp_input_start(const u_char *, size_t, const char *, 328 struct snmp_pdu *, int32_t *, size_t *); 329 330 /* process the pdu. returns either _OK or _FAILED */ 331 enum snmpd_input_err snmp_input_finish(struct snmp_pdu *, const u_char *, 332 size_t, u_char *, size_t *, const char *, enum snmpd_input_err, int32_t, 333 void *); 334 335 void snmp_output(struct snmp_pdu *, u_char *, size_t *, const char *); 336 void snmp_send_port(void *, const struct asn_oid *, struct snmp_pdu *, 337 const struct sockaddr *, socklen_t); 338 339 /* sending traps */ 340 void snmp_send_trap(const struct asn_oid *, ...); 341 342 /* 343 * Action support 344 */ 345 int string_save(struct snmp_value *, struct snmp_context *, ssize_t, u_char **); 346 void string_commit(struct snmp_context *); 347 void string_rollback(struct snmp_context *, u_char **); 348 int string_get(struct snmp_value *, const u_char *, ssize_t); 349 void string_free(struct snmp_context *); 350 351 int ip_save(struct snmp_value *, struct snmp_context *, u_char *); 352 void ip_rollback(struct snmp_context *, u_char *); 353 void ip_commit(struct snmp_context *); 354 int ip_get(struct snmp_value *, u_char *); 355 356 int oid_save(struct snmp_value *, struct snmp_context *, struct asn_oid *); 357 void oid_rollback(struct snmp_context *, struct asn_oid *); 358 void oid_commit(struct snmp_context *); 359 int oid_get(struct snmp_value *, const struct asn_oid *); 360 361 int index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...); 362 int index_compare(const struct asn_oid *, u_int, const struct asn_oid *); 363 int index_compare_off(const struct asn_oid *, u_int, const struct asn_oid *, 364 u_int); 365 void index_append(struct asn_oid *, u_int, const struct asn_oid *); 366 void index_append_off(struct asn_oid *, u_int, const struct asn_oid *, u_int); 367 368 #endif 369