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.23 2003/01/28 13:44:35 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 }; 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_v1_pdu *, 232 const struct asn_oid *, const struct sockaddr *, socklen_t, 233 enum snmpd_input_err, int32_t); 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_v1_pdu *, int32_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_v1_pdu *, u_char *, size_t *, const char *); 331 void snmp_send_port(const struct asn_oid *, struct snmp_v1_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