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 * Copyright (c) 2010 The FreeBSD Foundation
9 * All rights reserved.
10 *
11 * Portions of this software were developed by Shteryana Sotirova Shopova
12 * under sponsorship from the FreeBSD Foundation.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 * 1. Redistributions of source code must retain the above copyright
18 *    notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 *    notice, this list of conditions and the following disclaimer in the
21 *    documentation and/or other materials provided with the distribution.
22 *
23 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * $Begemot: bsnmp/snmpd/snmpmod.h,v 1.32 2006/02/14 09:04:20 brandt_h Exp $
36 *
37 * SNMP daemon data and functions exported to modules.
38 */
39#ifndef snmpmod_h_
40#define snmpmod_h_
41
42#include <sys/types.h>
43#include <sys/queue.h>
44#include <sys/socket.h>
45#include <net/if.h>
46#include <netinet/in.h>
47#include "asn1.h"
48#include "snmp.h"
49#include "snmpagent.h"
50
51#define MAX_MOD_ARGS	16
52
53/*
54 * These macros help to handle object lists for SNMP tables. They use
55 * tail queues to hold the objects in ascending order in the list.
56 * ordering can be done either on an integer/unsigned field, an asn_oid
57 * or an ordering function.
58 */
59
60/*
61 * First set of macros is used when the link is embedded into sub-struct
62 * and links these sub-structs. The sub-struct must be the first field.
63 *
64 * The list is a list of the subfield types.
65 */
66#define INSERT_OBJECT_OID_LINK_INDEX_TYPE(PTR, LIST, LINK, INDEX, SUBF) do {\
67	typedef __typeof ((PTR)->SUBF) _subf_type;			\
68	_subf_type *_lelem;						\
69									\
70	TAILQ_FOREACH(_lelem, (LIST), LINK)				\
71		if (asn_compare_oid(&_lelem->INDEX, &(PTR)->SUBF.INDEX) > 0)\
72			break;						\
73	if (_lelem == NULL)						\
74		TAILQ_INSERT_TAIL((LIST), &(PTR)->SUBF, LINK);		\
75	else								\
76		TAILQ_INSERT_BEFORE(_lelem, &(PTR)->SUBF, LINK);	\
77    } while (0)
78
79#define NEXT_OBJECT_OID_LINK_INDEX_TYPE(LIST, OID, SUB, LINK, INDEX, TYPE) ({\
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	(TYPE *)(_lelem);						\
86    })
87
88#define FIND_OBJECT_OID_LINK_INDEX_TYPE(LIST, OID, SUB, LINK, INDEX, TYPE) ({\
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	(TYPE *)(_lelem);						\
95    })
96
97/*
98 * This set of macros allows specification of the link and index name.
99 * The index is an OID.
100 */
101#define INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, INDEX) do {	\
102	__typeof (PTR) _lelem;						\
103									\
104	TAILQ_FOREACH(_lelem, (LIST), LINK)				\
105		if (asn_compare_oid(&_lelem->INDEX, &(PTR)->INDEX) > 0)	\
106			break;						\
107	if (_lelem == NULL)						\
108		TAILQ_INSERT_TAIL((LIST), (PTR), LINK);			\
109	else								\
110		TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK);		\
111    } while (0)
112
113#define INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, INDEX) do {	\
114	__typeof (PTR) _lelem;						\
115									\
116	TAILQ_FOREACH(_lelem, (LIST), LINK)				\
117		if ((asn_subid_t)_lelem->INDEX > (asn_subid_t)(PTR)->INDEX)\
118			break;						\
119	if (_lelem == NULL)						\
120		TAILQ_INSERT_TAIL((LIST), (PTR), LINK);			\
121	else								\
122		TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK);		\
123    } while (0)
124
125#define	INSERT_OBJECT_FUNC_LINK(PTR, LIST, LINK, FUNC) do {		\
126	__typeof (PTR) _lelem;						\
127									\
128	TAILQ_FOREACH(_lelem, (LIST), LINK)				\
129		if ((FUNC)(_lelem, (PTR)) > 0)				\
130			break;						\
131	if (_lelem == NULL)						\
132		TAILQ_INSERT_TAIL((LIST), (PTR), LINK);			\
133	else								\
134		TAILQ_INSERT_BEFORE(_lelem, (PTR), LINK);		\
135    } while (0)
136
137#define	INSERT_OBJECT_FUNC_LINK_REV(PTR, LIST, HEAD, LINK, FUNC) do {	\
138	__typeof (PTR) _lelem;						\
139									\
140	TAILQ_FOREACH_REVERSE(_lelem, (LIST), HEAD, LINK)		\
141		if ((FUNC)(_lelem, (PTR)) < 0)				\
142			break;						\
143	if (_lelem == NULL)						\
144		TAILQ_INSERT_HEAD((LIST), (PTR), LINK);			\
145	else								\
146		TAILQ_INSERT_AFTER((LIST), _lelem, (PTR), LINK);	\
147    } while (0)
148
149#define FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({	\
150	__typeof (TAILQ_FIRST(LIST)) _lelem;				\
151									\
152	TAILQ_FOREACH(_lelem, (LIST), LINK)				\
153		if (index_compare(OID, SUB, &_lelem->INDEX) == 0)	\
154			break;						\
155	(_lelem);							\
156    })
157
158#define NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({	\
159	__typeof (TAILQ_FIRST(LIST)) _lelem;				\
160									\
161	TAILQ_FOREACH(_lelem, (LIST), LINK)				\
162		if (index_compare(OID, SUB, &_lelem->INDEX) < 0)	\
163			break;						\
164	(_lelem);							\
165    })
166
167#define FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({	\
168	__typeof (TAILQ_FIRST(LIST)) _lelem;				\
169									\
170	if ((OID)->len - SUB != 1)					\
171		_lelem = NULL;						\
172	else								\
173		TAILQ_FOREACH(_lelem, (LIST), LINK)			\
174			if ((OID)->subs[SUB] == (asn_subid_t)_lelem->INDEX)\
175				break;					\
176	(_lelem);							\
177    })
178
179#define NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, INDEX) ({	\
180	__typeof (TAILQ_FIRST(LIST)) _lelem;				\
181									\
182	if ((OID)->len - SUB == 0)					\
183		_lelem = TAILQ_FIRST(LIST);				\
184	else								\
185		TAILQ_FOREACH(_lelem, (LIST), LINK)			\
186			if ((OID)->subs[SUB] < (asn_subid_t)_lelem->INDEX)\
187				break;					\
188	(_lelem);							\
189    })
190
191#define FIND_OBJECT_FUNC_LINK(LIST, OID, SUB, LINK, FUNC) ({		\
192	__typeof (TAILQ_FIRST(LIST)) _lelem;				\
193									\
194	TAILQ_FOREACH(_lelem, (LIST), LINK)				\
195		if ((FUNC)(OID, SUB, _lelem) == 0)			\
196			break;						\
197	(_lelem);							\
198    })
199
200#define NEXT_OBJECT_FUNC_LINK(LIST, OID, SUB, LINK, FUNC) ({		\
201	__typeof (TAILQ_FIRST(LIST)) _lelem;				\
202									\
203	TAILQ_FOREACH(_lelem, (LIST), LINK)				\
204		if ((FUNC)(OID, SUB, _lelem) < 0)			\
205			break;						\
206	(_lelem);							\
207    })
208
209/*
210 * Macros for the case where the index field is called 'index'
211 */
212#define INSERT_OBJECT_OID_LINK(PTR, LIST, LINK)				\
213    INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, LINK, index)
214
215#define INSERT_OBJECT_INT_LINK(PTR, LIST, LINK) do {			\
216    INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, LINK, index)
217
218#define FIND_OBJECT_OID_LINK(LIST, OID, SUB, LINK)			\
219    FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index)
220
221#define NEXT_OBJECT_OID_LINK(LIST, OID, SUB, LINK)			\
222    NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, LINK, index)
223
224#define FIND_OBJECT_INT_LINK(LIST, OID, SUB, LINK)			\
225    FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index)
226
227#define NEXT_OBJECT_INT_LINK(LIST, OID, SUB, LINK)			\
228    NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, LINK, index)
229
230/*
231 * Macros for the case where the index field is called 'index' and the
232 * link field 'link'.
233 */
234#define INSERT_OBJECT_OID(PTR, LIST)					\
235    INSERT_OBJECT_OID_LINK_INDEX(PTR, LIST, link, index)
236
237#define INSERT_OBJECT_INT(PTR, LIST)					\
238    INSERT_OBJECT_INT_LINK_INDEX(PTR, LIST, link, index)
239
240#define	INSERT_OBJECT_FUNC_REV(PTR, LIST, HEAD, FUNC)			\
241    INSERT_OBJECT_FUNC_LINK_REV(PTR, LIST, HEAD, link, FUNC)
242
243#define FIND_OBJECT_OID(LIST, OID, SUB)					\
244    FIND_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index)
245
246#define FIND_OBJECT_INT(LIST, OID, SUB)					\
247    FIND_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index)
248
249#define	FIND_OBJECT_FUNC(LIST, OID, SUB, FUNC)				\
250    FIND_OBJECT_FUNC_LINK(LIST, OID, SUB, link, FUNC)
251
252#define NEXT_OBJECT_OID(LIST, OID, SUB)					\
253    NEXT_OBJECT_OID_LINK_INDEX(LIST, OID, SUB, link, index)
254
255#define NEXT_OBJECT_INT(LIST, OID, SUB)					\
256    NEXT_OBJECT_INT_LINK_INDEX(LIST, OID, SUB, link, index)
257
258#define	NEXT_OBJECT_FUNC(LIST, OID, SUB, FUNC)				\
259    NEXT_OBJECT_FUNC_LINK(LIST, OID, SUB, link, FUNC)
260
261struct lmodule;
262
263/* The tick when the program was started. This is the absolute time of
264 * the start in 100th of a second. */
265extern uint64_t start_tick;
266
267/* The tick when the current packet was received. This is the absolute
268 * time in 100th of second. */
269extern uint64_t this_tick;
270
271/* Get the current absolute time in 100th of a second. */
272uint64_t get_ticks(void);
273
274/*
275 * Return code for proxy function
276 */
277enum snmpd_proxy_err {
278	/* proxy code will process the PDU */
279	SNMPD_PROXY_OK,
280	/* proxy code does not process PDU */
281	SNMPD_PROXY_REJ,
282	/* drop this PDU */
283	SNMPD_PROXY_DROP,
284	/* drop because of bad community */
285	SNMPD_PROXY_BADCOMM,
286	/* drop because of bad community use */
287	SNMPD_PROXY_BADCOMMUSE
288};
289
290/*
291 * Input handling
292 */
293enum snmpd_input_err {
294	/* proceed with packet */
295	SNMPD_INPUT_OK,
296	/* fatal error in packet, ignore it */
297	SNMPD_INPUT_FAILED,
298	/* value encoding has wrong length in a SET operation */
299	SNMPD_INPUT_VALBADLEN,
300	/* value encoding is out of range */
301	SNMPD_INPUT_VALRANGE,
302	/* value has bad encoding */
303	SNMPD_INPUT_VALBADENC,
304	/* need more data (truncated packet) */
305	SNMPD_INPUT_TRUNC,
306	/* unknown community */
307	SNMPD_INPUT_BAD_COMM,
308};
309
310/*
311 * Every loadable module must have one of this structures with
312 * the external name 'config'.
313 */
314struct snmp_module {
315	/* a comment describing what this module implements */
316	const char *comment;
317
318	/* the initialization function */
319	int (*init)(struct lmodule *, int argc, char *argv[]);
320
321	/* the finalisation function */
322	int (*fini)(void);
323
324	/* the idle function */
325	void (*idle)(void);
326
327	/* the dump function */
328	void (*dump)(void);
329
330	/* re-configuration function */
331	void (*config)(void);
332
333	/* start operation */
334	void (*start)(void);
335
336	/* proxy a PDU */
337	enum snmpd_proxy_err (*proxy)(struct snmp_pdu *, void *,
338	    const struct asn_oid *, const struct sockaddr *, socklen_t,
339	    enum snmpd_input_err, int32_t, int);
340
341	/* the tree this module is going to server */
342	const struct snmp_node *tree;
343	u_int tree_size;
344
345	/* function called, when another module was unloaded/loaded */
346	void (*loading)(const struct lmodule *, int);
347};
348
349/*
350 * Stuff exported to modules
351 */
352
353/*
354 * The system group.
355 */
356struct systemg {
357	u_char		*descr;
358	struct asn_oid	object_id;
359	u_char		*contact;
360	u_char		*name;
361	u_char		*location;
362	uint32_t	services;
363	uint32_t	or_last_change;
364};
365extern struct systemg systemg;
366
367/*
368 * Community support.
369 *
370 * We have 2 fixed communities for SNMP read and write access. Modules
371 * can create their communities dynamically. They are deleted automatically
372 * if the module is unloaded.
373 */
374#define COMM_INITIALIZE	0
375#define COMM_READ	1
376#define COMM_WRITE	2
377
378u_int comm_define(u_int, const char *descr, struct lmodule *, const char *str);
379struct community *comm_define_ordered(u_int priv, const char *descr,
380    struct asn_oid *index, struct lmodule *owner, const char *str);
381const char * comm_string(u_int);
382
383/* community for current packet */
384extern u_int community;
385
386/*
387 * SNMP User-based Security Model data. Modified via the snmp_usm(3) module.
388 */
389struct snmpd_usmstat {
390	uint32_t	unsupported_seclevels;
391	uint32_t	not_in_time_windows;
392	uint32_t	unknown_users;
393	uint32_t	unknown_engine_ids;
394	uint32_t	wrong_digests;
395	uint32_t	decrypt_errors;
396};
397
398extern struct snmpd_usmstat snmpd_usmstats;
399struct snmpd_usmstat *bsnmpd_get_usm_stats(void);
400void bsnmpd_reset_usm_stats(void);
401
402struct usm_user {
403	struct snmp_user		suser;
404	uint8_t				user_engine_id[SNMP_ENGINE_ID_SIZ];
405	uint32_t			user_engine_len;
406	char				user_public[SNMP_ADM_STR32_SIZ];
407	uint32_t			user_public_len;
408	int32_t				status;
409	int32_t				type;
410	SLIST_ENTRY(usm_user)		up;
411};
412
413SLIST_HEAD(usm_userlist, usm_user);
414struct usm_user *usm_first_user(void);
415struct usm_user *usm_next_user(struct usm_user *);
416struct usm_user *usm_find_user(uint8_t *, uint32_t, char *);
417struct usm_user *usm_new_user(uint8_t *, uint32_t, char *);
418void usm_delete_user(struct usm_user *);
419void usm_flush_users(void);
420
421/* USM user for current packet */
422extern struct usm_user *usm_user;
423
424/*
425 * SNMP View-based Access Control Model data. Modified via the snmp_vacm(3) module.
426 */
427struct vacm_group;
428
429struct vacm_user {
430	/* Security user name from USM */
431	char				secname[SNMP_ADM_STR32_SIZ];
432	int32_t				sec_model;
433	/* Back pointer to user assigned group name */
434	struct vacm_group		*group;
435	int32_t				type;
436	int32_t				status;
437	SLIST_ENTRY(vacm_user)		vvu;
438	SLIST_ENTRY(vacm_user)		vvg;
439};
440
441SLIST_HEAD(vacm_userlist, vacm_user);
442
443struct vacm_group {
444	char				groupname[SNMP_ADM_STR32_SIZ];
445	struct vacm_userlist		group_users;
446	SLIST_ENTRY(vacm_group)		vge;
447};
448
449SLIST_HEAD(vacm_grouplist, vacm_group);
450
451struct vacm_access {
452	/* The group name is index, not a column in the table */
453	struct vacm_group		*group;
454	char				ctx_prefix[SNMP_ADM_STR32_SIZ];
455	int32_t				sec_model;
456	int32_t				sec_level;
457	int32_t				ctx_match;
458	struct vacm_view		*read_view;
459	struct vacm_view		*write_view;
460	struct vacm_view		*notify_view;
461	int32_t				type;
462	int32_t				status;
463	TAILQ_ENTRY(vacm_access)	vva;
464};
465
466TAILQ_HEAD(vacm_accesslist, vacm_access);
467
468struct vacm_view {
469	char				viewname[SNMP_ADM_STR32_SIZ]; /* key */
470	struct asn_oid			subtree; /* key */
471	uint8_t				mask[16];
472	uint8_t				exclude;
473	int32_t				type;
474	int32_t				status;
475	SLIST_ENTRY(vacm_view)		vvl;
476};
477
478SLIST_HEAD(vacm_viewlist, vacm_view);
479
480struct vacm_context {
481	/* The ID of the module that registered this context */
482	int32_t				regid;
483	char				ctxname[SNMP_ADM_STR32_SIZ];
484	SLIST_ENTRY(vacm_context)	vcl;
485};
486
487SLIST_HEAD(vacm_contextlist, vacm_context);
488
489void vacm_groups_init(void);
490struct vacm_user *vacm_first_user(void);
491struct vacm_user *vacm_next_user(struct vacm_user *);
492struct vacm_user *vacm_new_user(int32_t, char *);
493int vacm_delete_user(struct vacm_user *);
494int vacm_user_set_group(struct vacm_user *, u_char *, u_int);
495struct vacm_access *vacm_first_access_rule(void);
496struct vacm_access *vacm_next_access_rule(struct vacm_access *);
497struct vacm_access *vacm_new_access_rule(char *, char *, int32_t, int32_t);
498int vacm_delete_access_rule(struct vacm_access *);
499struct vacm_view *vacm_first_view(void);
500struct vacm_view *vacm_next_view(struct vacm_view *);
501struct vacm_view *vacm_new_view(char *, struct asn_oid *);
502int vacm_delete_view(struct vacm_view *);
503struct vacm_context *vacm_first_context(void);
504struct vacm_context *vacm_next_context(struct vacm_context *);
505struct vacm_context *vacm_add_context(char *, int32_t);
506void vacm_flush_contexts(int32_t);
507
508/*
509 * RFC 3413 SNMP Management Target & Notification MIB
510 */
511
512struct snmpd_target_stats {
513	uint32_t			unavail_contexts;
514	uint32_t			unknown_contexts;
515};
516
517#define	SNMP_UDP_ADDR_SIZ		6
518#define	SNMP_TAG_SIZ			(255 + 1)
519
520struct target_address {
521	char				name[SNMP_ADM_STR32_SIZ];
522	uint8_t				address[SNMP_UDP_ADDR_SIZ];
523	int32_t				timeout;
524	int32_t				retry;
525	char				taglist[SNMP_TAG_SIZ];
526	char				paramname[SNMP_ADM_STR32_SIZ];
527	int32_t				type;
528	int32_t				socket;
529	int32_t				status;
530	SLIST_ENTRY(target_address)	ta;
531};
532
533SLIST_HEAD(target_addresslist, target_address);
534
535struct target_param {
536	char				name[SNMP_ADM_STR32_SIZ];
537	int32_t				mpmodel;
538	int32_t				sec_model;
539	char				secname[SNMP_ADM_STR32_SIZ];
540	enum snmp_usm_level		sec_level;
541	int32_t				type;
542	int32_t				status;
543	SLIST_ENTRY(target_param)	tp;
544};
545
546SLIST_HEAD(target_paramlist, target_param);
547
548struct target_notify {
549	char				name[SNMP_ADM_STR32_SIZ];
550	char				taglist[SNMP_TAG_SIZ];
551	int32_t				notify_type;
552	int32_t				type;
553	int32_t				status;
554	SLIST_ENTRY(target_notify)	tn;
555};
556
557SLIST_HEAD(target_notifylist, target_notify);
558
559extern struct snmpd_target_stats snmpd_target_stats;
560struct snmpd_target_stats *bsnmpd_get_target_stats(void);
561struct target_address *target_first_address(void);
562struct target_address *target_next_address(struct target_address *);
563struct target_address *target_new_address(char *);
564int target_activate_address(struct target_address *);
565int target_delete_address(struct target_address *);
566struct target_param *target_first_param(void);
567struct target_param *target_next_param(struct target_param *);
568struct target_param *target_new_param(char *);
569int target_delete_param(struct target_param *);
570struct target_notify *target_first_notify(void);
571struct target_notify *target_next_notify(struct target_notify *);
572struct target_notify *target_new_notify(char *);
573int target_delete_notify (struct target_notify *);
574void target_flush_all(void);
575
576/*
577 * Well known OIDs
578 */
579extern const struct asn_oid oid_zeroDotZero;
580
581/* SNMPv3 Engine Discovery */
582extern const struct asn_oid oid_usmUnknownEngineIDs;
583extern const struct asn_oid oid_usmNotInTimeWindows;
584
585/*
586 * Request ID ranges.
587 *
588 * A module can request a range of request ids and associate them with a
589 * type field. All ranges are deleted if a module is unloaded.
590 */
591u_int reqid_allocate(int size, struct lmodule *);
592int32_t reqid_next(u_int type);
593int32_t reqid_base(u_int type);
594int reqid_istype(int32_t reqid, u_int type);
595u_int reqid_type(int32_t reqid);
596
597/*
598 * Timers.
599 */
600void *timer_start(u_int, void (*)(void *), void *, struct lmodule *);
601void *timer_start_repeat(u_int, u_int, void (*)(void *), void *,
602    struct lmodule *);
603void timer_stop(void *);
604
605/*
606 * File descriptors
607 */
608void *fd_select(int, void (*)(int, void *), void *, struct lmodule *);
609void fd_deselect(void *);
610void fd_suspend(void *);
611int fd_resume(void *);
612
613/*
614 * Object resources
615 */
616u_int or_register(const struct asn_oid *, const char *, struct lmodule *);
617void or_unregister(u_int);
618
619/*
620 * Buffers
621 */
622void *buf_alloc(int tx);
623size_t buf_size(int tx);
624
625/* decode PDU and find community */
626enum snmpd_input_err snmp_input_start(const u_char *, size_t, const char *,
627    struct snmp_pdu *, int32_t *, size_t *);
628
629/* process the pdu. returns either _OK or _FAILED */
630enum snmpd_input_err snmp_input_finish(struct snmp_pdu *, const u_char *,
631    size_t, u_char *, size_t *, const char *, enum snmpd_input_err, int32_t,
632    void *);
633
634void snmp_output(struct snmp_pdu *, u_char *, size_t *, const char *);
635void snmp_send_port(void *, const struct asn_oid *, struct snmp_pdu *,
636	const struct sockaddr *, socklen_t);
637enum snmp_code snmp_pdu_auth_access(struct snmp_pdu *, int32_t *);
638
639/* sending traps */
640void snmp_send_trap(const struct asn_oid *, ...);
641
642/*
643 * Action support
644 */
645int string_save(struct snmp_value *, struct snmp_context *, ssize_t, u_char **);
646void string_commit(struct snmp_context *);
647void string_rollback(struct snmp_context *, u_char **);
648int string_get(struct snmp_value *, const u_char *, ssize_t);
649int string_get_max(struct snmp_value *, const u_char *, ssize_t, size_t);
650void string_free(struct snmp_context *);
651
652int ip_save(struct snmp_value *, struct snmp_context *, u_char *);
653void ip_rollback(struct snmp_context *, u_char *);
654void ip_commit(struct snmp_context *);
655int ip_get(struct snmp_value *, u_char *);
656
657int oid_save(struct snmp_value *, struct snmp_context *, struct asn_oid *);
658void oid_rollback(struct snmp_context *, struct asn_oid *);
659void oid_commit(struct snmp_context *);
660int oid_get(struct snmp_value *, const struct asn_oid *);
661
662int index_decode(const struct asn_oid *oid, u_int sub, u_int code, ...);
663int index_compare(const struct asn_oid *, u_int, const struct asn_oid *);
664int index_compare_off(const struct asn_oid *, u_int, const struct asn_oid *,
665    u_int);
666void index_append(struct asn_oid *, u_int, const struct asn_oid *);
667void index_append_off(struct asn_oid *, u_int, const struct asn_oid *, u_int);
668
669#endif
670