snmpmod.h revision 156066
1255736Sdavidch/* 2255736Sdavidch * Copyright (c) 2001-2003 3255736Sdavidch * Fraunhofer Institute for Open Communication Systems (FhG Fokus). 4255736Sdavidch * All rights reserved. 5255736Sdavidch * 6255736Sdavidch * Author: Harti Brandt <harti@freebsd.org> 7255736Sdavidch * 8255736Sdavidch * Redistribution and use in source and binary forms, with or without 9255736Sdavidch * modification, are permitted provided that the following conditions 10255736Sdavidch * are met: 11255736Sdavidch * 1. Redistributions of source code must retain the above copyright 12255736Sdavidch * notice, this list of conditions and the following disclaimer. 13255736Sdavidch * 2. Redistributions in binary form must reproduce the above copyright 14255736Sdavidch * notice, this list of conditions and the following disclaimer in the 15255736Sdavidch * documentation and/or other materials provided with the distribution. 16255736Sdavidch * 17255736Sdavidch * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18255736Sdavidch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19255736Sdavidch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20255736Sdavidch * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21255736Sdavidch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22255736Sdavidch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23255736Sdavidch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24255736Sdavidch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25255736Sdavidch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26255736Sdavidch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27255736Sdavidch * SUCH DAMAGE. 28255736Sdavidch * 29255736Sdavidch * $Begemot: bsnmp/snmpd/snmpmod.h,v 1.32 2006/02/14 09:04:20 brandt_h Exp $ 30255736Sdavidch * 31255736Sdavidch * SNMP daemon data and functions exported to modules. 32255736Sdavidch */ 33255736Sdavidch#ifndef snmpmod_h_ 34255736Sdavidch#define snmpmod_h_ 35255736Sdavidch 36255736Sdavidch#include <sys/types.h> 37255736Sdavidch#include <sys/socket.h> 38255736Sdavidch#include <net/if.h> 39255736Sdavidch#include <netinet/in.h> 40255736Sdavidch#include "asn1.h" 41255736Sdavidch#include "snmp.h" 42255736Sdavidch#include "snmpagent.h" 43255736Sdavidch 44255736Sdavidch#define MAX_MOD_ARGS 16 45255736Sdavidch 46255736Sdavidch/* 47255736Sdavidch * These macros help to handle object lists for SNMP tables. They use 48255736Sdavidch * tail queues to hold the objects in ascending order in the list. 49255736Sdavidch * ordering can be done either on an integer/unsigned field, an asn_oid 50255736Sdavidch * or an ordering function. 51255736Sdavidch */ 52255736Sdavidch#define INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, INDEX) do { \ 53255736Sdavidch __typeof (PTR) _lelem; \ 54255736Sdavidch \ 55255736Sdavidch TAILQ_FOREACH(_lelem, (LIST), LINK) \ 56255736Sdavidch if (asn_compare_oid(&_lelem->INDEX, &(PTR)->INDEX) > 0) \ 57255736Sdavidch break; \ 58255736Sdavidch if (_lelem == NULL) \ 59255736Sdavidch TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \ 60255736Sdavidch else \ 61255736Sdavidch TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \ 62255736Sdavidch } while (0) 63255736Sdavidch 64255736Sdavidch#define INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, INDEX) do { \ 65255736Sdavidch __typeof (PTR) _lelem; \ 66255736Sdavidch \ 67255736Sdavidch TAILQ_FOREACH(_lelem, (LIST), LINK) \ 68255736Sdavidch if ((asn_subid_t)_lelem->INDEX > (asn_subid_t)(PTR)->INDEX)\ 69255736Sdavidch break; \ 70255736Sdavidch if (_lelem == NULL) \ 71255736Sdavidch TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \ 72255736Sdavidch else \ 73255736Sdavidch TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \ 74255736Sdavidch } while (0) 75255736Sdavidch 76255736Sdavidch#define INSERT_OBJECT_FUNC_LINK(PTR, LIST, LINK, FUNC) do { \ 77255736Sdavidch __typeof (PTR) _lelem; \ 78255736Sdavidch \ 79255736Sdavidch TAILQ_FOREACH(_lelem, (LIST), LINK) \ 80255736Sdavidch if ((FUNC)(_lelem, (PTR)) > 0) \ 81255736Sdavidch break; \ 82255736Sdavidch if (_lelem == NULL) \ 83255736Sdavidch TAILQ_INSERT_TAIL((LIST), (PTR), LINK); \ 84255736Sdavidch else \ 85255736Sdavidch TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK); \ 86255736Sdavidch } while (0) 87255736Sdavidch 88255736Sdavidch#define INSERT_OBJECT_FUNC_LINK_REV(PTR, LIST, HEAD, LINK, FUNC) do { \ 89255736Sdavidch __typeof (PTR) _lelem; \ 90255736Sdavidch \ 91255736Sdavidch TAILQ_FOREACH_REVERSE(_lelem, (LIST), HEAD, LINK) \ 92255736Sdavidch if ((FUNC)(_lelem, (PTR)) < 0) \ 93255736Sdavidch break; \ 94255736Sdavidch if (_lelem == NULL) \ 95255736Sdavidch TAILQ_INSERT_HEAD((LIST), (PTR), LINK); \ 96255736Sdavidch else \ 97255736Sdavidch TAILQ_INSERT_AFTER((LIST), _lelem, (PTR), LINK); \ 98255736Sdavidch } while (0) 99255736Sdavidch 100255736Sdavidch#define FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ 101255736Sdavidch __typeof (TAILQ_FIRST(LIST)) _lelem; \ 102255736Sdavidch \ 103255736Sdavidch TAILQ_FOREACH(_lelem, (LIST), LINK) \ 104255736Sdavidch if (index_compare(OID, SUB, &_lelem->INDEX) == 0) \ 105255736Sdavidch break; \ 106255736Sdavidch (_lelem); \ 107255736Sdavidch }) 108255736Sdavidch 109255736Sdavidch#define NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ 110255736Sdavidch __typeof (TAILQ_FIRST(LIST)) _lelem; \ 111255736Sdavidch \ 112255736Sdavidch TAILQ_FOREACH(_lelem, (LIST), LINK) \ 113255736Sdavidch if (index_compare(OID, SUB, &_lelem->INDEX) < 0) \ 114255736Sdavidch break; \ 115255736Sdavidch (_lelem); \ 116255736Sdavidch }) 117255736Sdavidch 118255736Sdavidch#define FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ 119255736Sdavidch __typeof (TAILQ_FIRST(LIST)) _lelem; \ 120255736Sdavidch \ 121255736Sdavidch if ((OID)->len - SUB != 1) \ 122255736Sdavidch _lelem = NULL; \ 123255736Sdavidch else \ 124255736Sdavidch TAILQ_FOREACH(_lelem, (LIST), LINK) \ 125255736Sdavidch if ((OID)->subs[SUB] == (asn_subid_t)_lelem->INDEX)\ 126255736Sdavidch break; \ 127255736Sdavidch (_lelem); \ 128255736Sdavidch }) 129255736Sdavidch 130255736Sdavidch#define NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({ \ 131255736Sdavidch __typeof (TAILQ_FIRST(LIST)) _lelem; \ 132255736Sdavidch \ 133255736Sdavidch if ((OID)->len - SUB == 0) \ 134255736Sdavidch _lelem = TAILQ_FIRST(LIST); \ 135255736Sdavidch else \ 136255736Sdavidch TAILQ_FOREACH(_lelem, (LIST), LINK) \ 137255736Sdavidch if ((OID)->subs[SUB] < (asn_subid_t)_lelem->INDEX)\ 138255736Sdavidch break; \ 139255736Sdavidch (_lelem); \ 140255736Sdavidch }) 141255736Sdavidch 142255736Sdavidch#define FIND_OBJECT_FUNC_LINK(LIST, OID, SUB, LINK, FUNC) ({ \ 143255736Sdavidch __typeof (TAILQ_FIRST(LIST)) _lelem; \ 144255736Sdavidch \ 145255736Sdavidch TAILQ_FOREACH(_lelem, (LIST), LINK) \ 146255736Sdavidch if ((FUNC)(OID, SUB, _lelem) == 0) \ 147255736Sdavidch break; \ 148255736Sdavidch (_lelem); \ 149255736Sdavidch }) 150255736Sdavidch 151255736Sdavidch#define NEXT_OBJECT_FUNC_LINK(LIST, OID, SUB, LINK, FUNC) ({ \ 152255736Sdavidch __typeof (TAILQ_FIRST(LIST)) _lelem; \ 153255736Sdavidch \ 154255736Sdavidch TAILQ_FOREACH(_lelem, (LIST), LINK) \ 155255736Sdavidch if ((FUNC)(OID, SUB, _lelem) < 0) \ 156255736Sdavidch break; \ 157255736Sdavidch (_lelem); \ 158255736Sdavidch }) 159255736Sdavidch 160255736Sdavidch/* 161255736Sdavidch * Macros for the case where the index field is called 'index' 162255736Sdavidch */ 163255736Sdavidch#define INSERT_OBJECT_OID_LINK(PTR, LIST, LINK) \ 164255736Sdavidch INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, index) 165255736Sdavidch 166255736Sdavidch#define INSERT_OBJECT_INT_LINK(PTR, LIST, LINK) do { \ 167255736Sdavidch INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, index) 168255736Sdavidch 169255736Sdavidch#define FIND_OBJECT_OID_LINK(LIST, OID, SUB, LINK) \ 170255736Sdavidch FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index) 171255736Sdavidch 172255736Sdavidch#define NEXT_OBJECT_OID_LINK(LIST, OID, SUB, LINK) \ 173255736Sdavidch NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index) 174255736Sdavidch 175255736Sdavidch#define FIND_OBJECT_INT_LINK(LIST, OID, SUB, LINK) \ 176255736Sdavidch FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index) 177255736Sdavidch 178255736Sdavidch#define NEXT_OBJECT_INT_LINK(LIST, OID, SUB, LINK) \ 179255736Sdavidch NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index) 180255736Sdavidch 181255736Sdavidch/* 182255736Sdavidch * Macros for the case where the index field is called 'index' and the 183255736Sdavidch * link field 'link'. 184255736Sdavidch */ 185255736Sdavidch#define INSERT_OBJECT_OID(PTR, LIST) \ 186255736Sdavidch INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, link, index) 187255736Sdavidch 188255736Sdavidch#define INSERT_OBJECT_INT(PTR, LIST) \ 189255736Sdavidch INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, link, index) 190255736Sdavidch 191255736Sdavidch#define INSERT_OBJECT_FUNC_REV(PTR, LIST, HEAD, FUNC) \ 192255736Sdavidch INSERT_OBJECT_FUNC_LINK_REV(PTR, LIST, HEAD, link, FUNC) 193255736Sdavidch 194255736Sdavidch#define FIND_OBJECT_OID(LIST, OID, SUB) \ 195255736Sdavidch FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index) 196255736Sdavidch 197255736Sdavidch#define FIND_OBJECT_INT(LIST, OID, SUB) \ 198255736Sdavidch FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index) 199255736Sdavidch 200255736Sdavidch#define FIND_OBJECT_FUNC(LIST, OID, SUB, FUNC) \ 201255736Sdavidch FIND_OBJECT_FUNC_LINK(LIST, OID, SUB, link, FUNC) 202255736Sdavidch 203255736Sdavidch#define NEXT_OBJECT_OID(LIST, OID, SUB) \ 204255736Sdavidch NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index) 205255736Sdavidch 206255736Sdavidch#define NEXT_OBJECT_INT(LIST, OID, SUB) \ 207255736Sdavidch NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index) 208255736Sdavidch 209255736Sdavidch#define NEXT_OBJECT_FUNC(LIST, OID, SUB, FUNC) \ 210255736Sdavidch NEXT_OBJECT_FUNC_LINK(LIST, OID, SUB, link, FUNC) 211255736Sdavidch 212255736Sdavidchstruct lmodule; 213255736Sdavidch 214255736Sdavidch/* The tick when the program was started. This is the absolute time of 215255736Sdavidch * the start in 100th of a second. */ 216255736Sdavidchextern uint64_t start_tick; 217255736Sdavidch 218255736Sdavidch/* The tick when the current packet was received. This is the absolute 219255736Sdavidch * time in 100th of second. */ 220255736Sdavidchextern uint64_t this_tick; 221255736Sdavidch 222255736Sdavidch/* Get the current absolute time in 100th of a second. */ 223255736Sdavidchuint64_t get_ticks(void); 224255736Sdavidch 225255736Sdavidch/* 226255736Sdavidch * Return code for proxy function 227255736Sdavidch */ 228255736Sdavidchenum snmpd_proxy_err { 229255736Sdavidch /* proxy code will process the PDU */ 230255736Sdavidch SNMPD_PROXY_OK, 231255736Sdavidch /* proxy code does not process PDU */ 232255736Sdavidch SNMPD_PROXY_REJ, 233255736Sdavidch /* drop this PDU */ 234255736Sdavidch SNMPD_PROXY_DROP, 235255736Sdavidch /* drop because of bad community */ 236255736Sdavidch SNMPD_PROXY_BADCOMM, 237255736Sdavidch /* drop because of bad community use */ 238255736Sdavidch SNMPD_PROXY_BADCOMMUSE 239255736Sdavidch}; 240255736Sdavidch 241255736Sdavidch/* 242255736Sdavidch * Input handling 243255736Sdavidch */ 244255736Sdavidchenum snmpd_input_err { 245255736Sdavidch /* proceed with packet */ 246255736Sdavidch SNMPD_INPUT_OK, 247255736Sdavidch /* fatal error in packet, ignore it */ 248255736Sdavidch SNMPD_INPUT_FAILED, 249255736Sdavidch /* value encoding has wrong length in a SET operation */ 250255736Sdavidch SNMPD_INPUT_VALBADLEN, 251255736Sdavidch /* value encoding is out of range */ 252255736Sdavidch SNMPD_INPUT_VALRANGE, 253255736Sdavidch /* value has bad encoding */ 254255736Sdavidch SNMPD_INPUT_VALBADENC, 255255736Sdavidch /* need more data (truncated packet) */ 256255736Sdavidch SNMPD_INPUT_TRUNC, 257255736Sdavidch /* unknown community */ 258255736Sdavidch SNMPD_INPUT_BAD_COMM, 259255736Sdavidch}; 260255736Sdavidch 261255736Sdavidch/* 262255736Sdavidch * Every loadable module must have one of this structures with 263255736Sdavidch * the external name 'config'. 264255736Sdavidch */ 265255736Sdavidchstruct snmp_module { 266255736Sdavidch /* a comment describing what this module implements */ 267255736Sdavidch const char *comment; 268255736Sdavidch 269255736Sdavidch /* the initialization function */ 270255736Sdavidch int (*init)(struct lmodule *, int argc, char *argv[]); 271255736Sdavidch 272255736Sdavidch /* the finalisation function */ 273255736Sdavidch int (*fini)(void); 274255736Sdavidch 275255736Sdavidch /* the idle function */ 276255736Sdavidch void (*idle)(void); 277255736Sdavidch 278255736Sdavidch /* the dump function */ 279255736Sdavidch void (*dump)(void); 280255736Sdavidch 281255736Sdavidch /* re-configuration function */ 282255736Sdavidch void (*config)(void); 283255736Sdavidch 284255736Sdavidch /* start operation */ 285255736Sdavidch void (*start)(void); 286255736Sdavidch 287255736Sdavidch /* proxy a PDU */ 288255736Sdavidch enum snmpd_proxy_err (*proxy)(struct snmp_pdu *, void *, 289255736Sdavidch const struct asn_oid *, const struct sockaddr *, socklen_t, 290255736Sdavidch enum snmpd_input_err, int32_t, int); 291255736Sdavidch 292255736Sdavidch /* the tree this module is going to server */ 293255736Sdavidch const struct snmp_node *tree; 294255736Sdavidch u_int tree_size; 295255736Sdavidch 296255736Sdavidch /* function called, when another module was unloaded/loaded */ 297255736Sdavidch void (*loading)(const struct lmodule *, int); 298255736Sdavidch}; 299255736Sdavidch 300255736Sdavidch/* 301255736Sdavidch * Stuff exported to modules 302255736Sdavidch */ 303255736Sdavidch 304255736Sdavidch/* 305255736Sdavidch * The system group. 306255736Sdavidch */ 307255736Sdavidchstruct systemg { 308255736Sdavidch u_char *descr; 309255736Sdavidch struct asn_oid object_id; 310255736Sdavidch u_char *contact; 311255736Sdavidch u_char *name; 312255736Sdavidch u_char *location; 313255736Sdavidch u_int32_t services; 314255736Sdavidch u_int32_t or_last_change; 315255736Sdavidch}; 316255736Sdavidchextern struct systemg systemg; 317255736Sdavidch 318255736Sdavidch/* 319255736Sdavidch * Community support. 320255736Sdavidch * 321255736Sdavidch * We have 2 fixed communities for SNMP read and write access. Modules 322255736Sdavidch * can create their communities dynamically. They are deleted automatically 323255736Sdavidch * if the module is unloaded. 324255736Sdavidch */ 325255736Sdavidch#define COMM_INITIALIZE 0 326255736Sdavidch#define COMM_READ 1 327255736Sdavidch#define COMM_WRITE 2 328255736Sdavidch 329255736Sdavidchu_int comm_define(u_int, const char *descr, struct lmodule *, const char *str); 330255736Sdavidchconst char * comm_string(u_int); 331255736Sdavidch 332255736Sdavidch/* community for current packet */ 333255736Sdavidchextern u_int community; 334255736Sdavidch 335255736Sdavidch/* 336255736Sdavidch * Well known OIDs 337255736Sdavidch */ 338255736Sdavidchextern const struct asn_oid oid_zeroDotZero; 339255736Sdavidch 340255736Sdavidch/* 341255736Sdavidch * Request ID ranges. 342255736Sdavidch * 343255736Sdavidch * A module can request a range of request ids and associate them with a 344255736Sdavidch * type field. All ranges are deleted if a module is unloaded. 345255736Sdavidch */ 346255736Sdavidchu_int reqid_allocate(int size, struct lmodule *); 347255736Sdavidchint32_t reqid_next(u_int type); 348255736Sdavidchint32_t reqid_base(u_int type); 349255736Sdavidchint reqid_istype(int32_t reqid, u_int type); 350255736Sdavidchu_int reqid_type(int32_t reqid); 351255736Sdavidch 352255736Sdavidch/* 353255736Sdavidch * Timers. 354255736Sdavidch */ 355255736Sdavidchvoid *timer_start(u_int, void (*)(void *), void *, struct lmodule *); 356255736Sdavidchvoid *timer_start_repeat(u_int, u_int, void (*)(void *), void *, 357255736Sdavidch struct lmodule *); 358255736Sdavidchvoid timer_stop(void *); 359255736Sdavidch 360255736Sdavidch/* 361255736Sdavidch * File descriptors 362255736Sdavidch */ 363255736Sdavidchvoid *fd_select(int, void (*)(int, void *), void *, struct lmodule *); 364255736Sdavidchvoid fd_deselect(void *); 365255736Sdavidchvoid fd_suspend(void *); 366255736Sdavidchint fd_resume(void *); 367255736Sdavidch 368255736Sdavidch/* 369255736Sdavidch * Object resources 370255736Sdavidch */ 371255736Sdavidchu_int or_register(const struct asn_oid *, const char *, struct lmodule *); 372255736Sdavidchvoid or_unregister(u_int); 373255736Sdavidch 374255736Sdavidch/* 375255736Sdavidch * Buffers 376 */ 377void *buf_alloc(int tx); 378size_t buf_size(int tx); 379 380/* decode PDU and find community */ 381enum snmpd_input_err snmp_input_start(const u_char *, size_t, const char *, 382 struct snmp_pdu *, int32_t *, size_t *); 383 384/* process the pdu. returns either _OK or _FAILED */ 385enum snmpd_input_err snmp_input_finish(struct snmp_pdu *, const u_char *, 386 size_t, u_char *, size_t *, const char *, enum snmpd_input_err, int32_t, 387 void *); 388 389void snmp_output(struct snmp_pdu *, u_char *, size_t *, const char *); 390void snmp_send_port(void *, const struct asn_oid *, struct snmp_pdu *, 391 const struct sockaddr *, socklen_t); 392 393/* sending traps */ 394void snmp_send_trap(const struct asn_oid *, ...); 395 396/* 397 * Action support 398 */ 399int string_save(struct snmp_value *, struct snmp_context *, ssize_t, u_char **); 400void string_commit(struct snmp_context *); 401void string_rollback(struct snmp_context *, u_char **); 402int string_get(struct snmp_value *, const u_char *, ssize_t); 403int string_get_max(struct snmp_value *, const u_char *, ssize_t, size_t); 404void string_free(struct snmp_context *); 405 406int ip_save(struct snmp_value *, struct snmp_context *, u_char *); 407void ip_rollback(struct snmp_context *, u_char *); 408void ip_commit(struct snmp_context *); 409int ip_get(struct snmp_value *, u_char *); 410 411int oid_save(struct snmp_value *, struct snmp_context *, struct asn_oid *); 412void oid_rollback(struct snmp_context *, struct asn_oid *); 413void oid_commit(struct snmp_context *); 414int oid_get(struct snmp_value *, const struct asn_oid *); 415 416int index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...); 417int index_compare(const struct asn_oid *, u_int, const struct asn_oid *); 418int index_compare_off(const struct asn_oid *, u_int, const struct asn_oid *, 419 u_int); 420void index_append(struct asn_oid *, u_int, const struct asn_oid *); 421void index_append_off(struct asn_oid *, u_int, const struct asn_oid *, u_int); 422 423#endif 424