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