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.27 2004/08/06 08:47:14 brandt 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 /* ticks when program and current packet was started */ 163 extern u_int32_t this_tick; 164 extern u_int32_t start_tick; 165 166 u_int32_t get_ticks(void); 167 168 /* 169 * Return code for proxy function 170 */ 171 enum snmpd_proxy_err { 172 /* proxy code will process the PDU */ 173 SNMPD_PROXY_OK, 174 /* proxy code does not process PDU */ 175 SNMPD_PROXY_REJ, 176 /* drop this PDU */ 177 SNMPD_PROXY_DROP, 178 /* drop because of bad community */ 179 SNMPD_PROXY_BADCOMM, 180 /* drop because of bad community use */ 181 SNMPD_PROXY_BADCOMMUSE 182 }; 183 184 /* 185 * Input handling 186 */ 187 enum snmpd_input_err { 188 /* proceed with packet */ 189 SNMPD_INPUT_OK, 190 /* fatal error in packet, ignore it */ 191 SNMPD_INPUT_FAILED, 192 /* value encoding has wrong length in a SET operation */ 193 SNMPD_INPUT_VALBADLEN, 194 /* value encoding is out of range */ 195 SNMPD_INPUT_VALRANGE, 196 /* value has bad encoding */ 197 SNMPD_INPUT_VALBADENC, 198 /* need more data (truncated packet) */ 199 SNMPD_INPUT_TRUNC, 200 /* unknown community */ 201 SNMPD_INPUT_BAD_COMM, 202 }; 203 204 /* 205 * Every loadable module must have one of this structures with 206 * the external name 'config'. 207 */ 208 struct snmp_module { 209 /* a comment describing what this module implements */ 210 const char *comment; 211 212 /* the initialisation function */ 213 int (*init)(struct lmodule *, int argc, char *argv[]); 214 215 /* the finalisation function */ 216 int (*fini)(void); 217 218 /* the idle function */ 219 void (*idle)(void); 220 221 /* the dump function */ 222 void (*dump)(void); 223 224 /* re-configuration function */ 225 void (*config)(void); 226 227 /* start operation */ 228 void (*start)(void); 229 230 /* proxy a PDU */ 231 enum snmpd_proxy_err (*proxy)(struct snmp_pdu *, void *, 232 const struct asn_oid *, const struct sockaddr *, socklen_t, 233 enum snmpd_input_err, int32_t, int); 234 235 /* the tree this module is going to server */ 236 const struct snmp_node *tree; 237 u_int tree_size; 238 239 /* function called, when another module was unloaded/loaded */ 240 void (*loading)(const struct lmodule *, int); 241 }; 242 243 /* 244 * Stuff exported to modules 245 */ 246 247 /* 248 * The system group. 249 */ 250 struct systemg { 251 u_char *descr; 252 struct asn_oid object_id; 253 u_char *contact; 254 u_char *name; 255 u_char *location; 256 u_int32_t services; 257 u_int32_t or_last_change; 258 }; 259 extern struct systemg systemg; 260 261 /* 262 * Community support. 263 * 264 * We have 2 fixed communities for SNMP read and write access. Modules 265 * can create their communities dynamically. They are deleted automatically 266 * if the module is unloaded. 267 */ 268 #define COMM_INITIALIZE 0 269 #define COMM_READ 1 270 #define COMM_WRITE 2 271 272 u_int comm_define(u_int, const char *descr, struct lmodule *, const char *str); 273 const char * comm_string(u_int); 274 275 /* community for current packet */ 276 extern u_int community; 277 278 /* 279 * Well known OIDs 280 */ 281 extern const struct asn_oid oid_zeroDotZero; 282 283 /* 284 * Request ID ranges. 285 * 286 * A module can request a range of request ids and associate them with a 287 * type field. All ranges are deleted if a module is unloaded. 288 */ 289 u_int reqid_allocate(int size, struct lmodule *); 290 int32_t reqid_next(u_int type); 291 int32_t reqid_base(u_int type); 292 int reqid_istype(int32_t reqid, u_int type); 293 u_int reqid_type(int32_t reqid); 294 295 /* 296 * Timers. 297 */ 298 void *timer_start(u_int, void (*)(void *), void *, struct lmodule *); 299 void timer_stop(void *); 300 301 /* 302 * File descriptors 303 */ 304 void *fd_select(int, void (*)(int, void *), void *, struct lmodule *); 305 void fd_deselect(void *); 306 void fd_suspend(void *); 307 int fd_resume(void *); 308 309 /* 310 * Object resources 311 */ 312 u_int or_register(const struct asn_oid *, const char *, struct lmodule *); 313 void or_unregister(u_int); 314 315 /* 316 * Buffers 317 */ 318 void *buf_alloc(int tx); 319 size_t buf_size(int tx); 320 321 /* decode PDU and find community */ 322 enum snmpd_input_err snmp_input_start(const u_char *, size_t, const char *, 323 struct snmp_pdu *, int32_t *, size_t *); 324 325 /* process the pdu. returns either _OK or _FAILED */ 326 enum snmpd_input_err snmp_input_finish(struct snmp_pdu *, const u_char *, 327 size_t, u_char *, size_t *, const char *, enum snmpd_input_err, int32_t, 328 void *); 329 330 void snmp_output(struct snmp_pdu *, u_char *, size_t *, const char *); 331 void snmp_send_port(void *, const struct asn_oid *, struct snmp_pdu *, 332 const struct sockaddr *, socklen_t); 333 334 /* sending traps */ 335 void snmp_send_trap(const struct asn_oid *, ...); 336 337 /* 338 * Action support 339 */ 340 int string_save(struct snmp_value *, struct snmp_context *, ssize_t, u_char **); 341 void string_commit(struct snmp_context *); 342 void string_rollback(struct snmp_context *, u_char **); 343 int string_get(struct snmp_value *, const u_char *, ssize_t); 344 void string_free(struct snmp_context *); 345 346 int ip_save(struct snmp_value *, struct snmp_context *, u_char *); 347 void ip_rollback(struct snmp_context *, u_char *); 348 void ip_commit(struct snmp_context *); 349 int ip_get(struct snmp_value *, u_char *); 350 351 int oid_save(struct snmp_value *, struct snmp_context *, struct asn_oid *); 352 void oid_rollback(struct snmp_context *, struct asn_oid *); 353 void oid_commit(struct snmp_context *); 354 int oid_get(struct snmp_value *, const struct asn_oid *); 355 356 int index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...); 357 int index_compare(const struct asn_oid *, u_int, const struct asn_oid *); 358 int index_compare_off(const struct asn_oid *, u_int, const struct asn_oid *, 359 u_int); 360 void index_append(struct asn_oid *, u_int, const struct asn_oid *); 361 void index_append_off(struct asn_oid *, u_int, const struct asn_oid *, u_int); 362 363 #endif 364