xref: /freebsd/contrib/bsnmp/snmpd/snmpmod.3 (revision 2be1a816b9ff69588e55be0a84cbe2a31efc0f2f)
1.\"
2.\" Copyright (c) 2004-2005
3.\"	Hartmut Brandt.
4.\"	All rights reserved.
5.\" Copyright (c) 2001-2003
6.\"	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
7.\"	All rights reserved.
8.\"
9.\" Author: Harti Brandt <harti@freebsd.org>
10.\"
11.\" Redistribution and use in source and binary forms, with or without
12.\" modification, are permitted provided that the following conditions
13.\" are met:
14.\" 1. Redistributions of source code must retain the above copyright
15.\"    notice, this list of conditions and the following disclaimer.
16.\" 2. Redistributions in binary form must reproduce the above copyright
17.\"    notice, this list of conditions and the following disclaimer in the
18.\"    documentation and/or other materials provided with the distribution.
19.\"
20.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23.\" ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30.\" SUCH DAMAGE.
31.\"
32.\" $Begemot: bsnmp/snmpd/snmpmod.3,v 1.14 2005/10/04 13:30:35 brandt_h Exp $
33.\"
34.Dd February 27, 2006
35.Dt SNMPMOD 3
36.Os
37.Sh NAME
38.Nm INSERT_OBJECT_OID_LINK_INDEX ,
39.Nm INSERT_OBJECT_INT_LINK_INDEX ,
40.Nm FIND_OBJECT_OID_LINK_INDEX ,
41.Nm NEXT_OBJECT_OID_LINK_INDEX ,
42.Nm FIND_OBJECT_INT_LINK_INDEX ,
43.Nm NEXT_OBJECT_INT_LINK_INDEX ,
44.Nm INSERT_OBJECT_OID_LINK ,
45.Nm INSERT_OBJECT_INT_LINK ,
46.Nm FIND_OBJECT_OID_LINK ,
47.Nm NEXT_OBJECT_OID_LINK ,
48.Nm FIND_OBJECT_INT_LINK ,
49.Nm NEXT_OBJECT_INT_LINK ,
50.Nm INSERT_OBJECT_OID ,
51.Nm INSERT_OBJECT_INT ,
52.Nm FIND_OBJECT_OID ,
53.Nm FIND_OBJECT_INT ,
54.Nm NEXT_OBJECT_OID ,
55.Nm NEXT_OBJECT_INT ,
56.Nm this_tick ,
57.Nm start_tick ,
58.Nm get_ticks ,
59.Nm systemg ,
60.Nm comm_define ,
61.Nm community ,
62.Nm oid_zeroDotZero ,
63.Nm reqid_allocate ,
64.Nm reqid_next ,
65.Nm reqid_base ,
66.Nm reqid_istype ,
67.Nm reqid_type ,
68.Nm timer_start ,
69.Nm timer_start_repeat ,
70.Nm timer_stop ,
71.Nm fd_select ,
72.Nm fd_deselect ,
73.Nm fd_suspend ,
74.Nm fd_resume ,
75.Nm or_register ,
76.Nm or_unregister ,
77.Nm buf_alloc ,
78.Nm buf_size ,
79.Nm snmp_input_start ,
80.Nm snmp_input_finish ,
81.Nm snmp_output ,
82.Nm snmp_send_port ,
83.Nm snmp_send_trap ,
84.Nm string_save ,
85.Nm string_commit ,
86.Nm string_rollback ,
87.Nm string_get ,
88.Nm string_get_max ,
89.Nm string_free ,
90.Nm ip_save ,
91.Nm ip_rollback ,
92.Nm ip_commit ,
93.Nm ip_get ,
94.Nm oid_save ,
95.Nm oid_rollback ,
96.Nm oid_commit ,
97.Nm oid_get ,
98.Nm index_decode ,
99.Nm index_compare ,
100.Nm index_compare_off ,
101.Nm index_append ,
102.Nm index_append_off
103.Nd "SNMP daemon loadable module interface"
104.Sh LIBRARY
105Begemot SNMP library
106.Pq libbsnmp, -lbsnmp
107.Sh SYNOPSIS
108.In bsnmp/snmpmod.h
109.Fn INSERT_OBJECT_OID_LINK_INDEX "PTR" "LIST" "LINK" "INDEX"
110.Fn INSERT_OBJECT_INT_LINK_INDEX "PTR" "LIST" "LINK" "INDEX"
111.Fn FIND_OBJECT_OID_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX"
112.Fn FIND_OBJECT_INT_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX"
113.Fn NEXT_OBJECT_OID_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX"
114.Fn NEXT_OBJECT_INT_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX"
115.Fn INSERT_OBJECT_OID_LINK "PTR" "LIST" "LINK"
116.Fn INSERT_OBJECT_INT_LINK "PTR" "LIST" "LINK"
117.Fn FIND_OBJECT_OID_LINK "LIST" "OID" "SUB" "LINK"
118.Fn FIND_OBJECT_INT_LINK "LIST" "OID" "SUB" "LINK"
119.Fn NEXT_OBJECT_OID_LINK "LIST" "OID" "SUB" "LINK"
120.Fn NEXT_OBJECT_INT_LINK "LIST" "OID" "SUB" "LINK"
121.Fn INSERT_OBJECT_OID "PTR" "LIST"
122.Fn INSERT_OBJECT_INT "PTR" "LIST"
123.Fn FIND_OBJECT_OID "LIST" "OID" "SUB"
124.Fn FIND_OBJECT_INT "LIST" "OID" "SUB"
125.Fn NEXT_OBJECT_OID "LIST" "OID" "SUB"
126.Fn NEXT_OBJECT_INT "LIST" "OID" "SUB"
127.Vt extern uint64_t this_tick ;
128.Vt extern uint64_t start_tick ;
129.Ft uint64_t
130.Fn get_ticks "void"
131.Vt extern struct systemg systemg ;
132.Ft u_int
133.Fn comm_define "u_int priv" "const char *descr" "struct lmodule *mod" "const char *str"
134.Ft const char *
135.Fn comm_string "u_int comm"
136.Vt extern u_int community ;
137.Vt extern const struct asn_oid oid_zeroDotZero ;
138.Ft u_int
139.Fn reqid_allocate "int size" "struct lmodule *mod"
140.Ft int32_t
141.Fn reqid_next "u_int type"
142.Ft int32_t
143.Fn reqid_base "u_int type"
144.Ft int
145.Fn reqid_istype "int32_t reqid" "u_int type"
146.Ft u_int
147.Fn reqid_type "int32_t reqid"
148.Ft void *
149.Fn timer_start "u_int ticks" "void (*func)(void *)" "void *uarg" "struct lmodule *mod"
150.Ft void *
151.Fn timer_start_repeat "u_int ticks" "u_int repeat_ticks" "void (*func)(void *)" "void *uarg" "struct lmodule *mod"
152.Ft void
153.Fn timer_stop "void *timer_id"
154.Ft void *
155.Fn fd_select "int fd" "void (*func)(int, void *)" "void *uarg" "struct lmodule *mod"
156.Ft void
157.Fn fd_deselect "void *fd_id"
158.Ft void
159.Fn fd_suspend "void *fd_id"
160.Ft int
161.Fn fd_resume "void *fd_id"
162.Ft u_int
163.Fn or_register "const struct asn_oid *oid" "const char *descr" "struct lmodule *mod"
164.Ft void
165.Fn or_unregister "u_int or_id"
166.Ft void *
167.Fn buf_alloc "int tx"
168.Ft size_t
169.Fn buf_size "int tx"
170.Ft enum snmpd_input_err
171.Fo snmp_input_start
172.Fa "const u_char *buf" "size_t len" "const char *source"
173.Fa "struct snmp_pdu *pdu" "int32_t *ip" "size_t *pdulen"
174.Fc
175.Ft enum snmpd_input_err
176.Fo snmp_input_finish
177.Fa "struct snmp_pdu *pdu" "const u_char *rcvbuf"
178.Fa "size_t rcvlen" "u_char *sndbuf" "size_t *sndlen" "const char *source"
179.Fa "enum snmpd_input_err ierr" "int32_t ip" "void *data"
180.Fc
181.Ft void
182.Fo snmp_output
183.Fa "struct snmp_pdu *pdu" "u_char *sndbuf" "size_t *sndlen"
184.Fa "const char *dest"
185.Fc
186.Ft void
187.Fo snmp_send_port
188.Fa "void *trans" "const struct asn_oid *port"
189.Fa "struct snmp_pdu *pdu" "const struct sockaddr *addr" "socklen_t addrlen"
190.Fc
191.Ft void
192.Fn snmp_send_trap "const struct asn_oid *oid" "..."
193.Ft int
194.Fn string_save "struct snmp_value *val" "struct snmp_context *ctx" "ssize_t req_size" "u_char **strp"
195.Ft void
196.Fn string_commit "struct snmp_context *ctx"
197.Ft void
198.Fn string_rollback "struct snmp_context *ctx" "u_char **strp"
199.Ft int
200.Fn string_get "struct snmp_value *val" "const u_char *str" "ssize_t len"
201.Ft int
202.Fn string_get_max "struct snmp_value *val" "const u_char *str" "ssize_t len" "size_t maxlen"
203.Ft void
204.Fn string_free "struct snmp_context *ctx"
205.Ft int
206.Fn ip_save "struct snmp_value *val" "struct snmp_context *ctx" "u_char *ipa"
207.Ft void
208.Fn ip_rollback "struct snmp_context *ctx" "u_char *ipa"
209.Ft void
210.Fn ip_commit "struct snmp_context *ctx"
211.Ft int
212.Fn ip_get "struct snmp_value *val" "u_char *ipa"
213.Ft int
214.Fn oid_save "struct snmp_value *val" "struct snmp_context *ctx" "struct asn_oid *oid"
215.Ft void
216.Fn oid_rollback "struct snmp_context *ctx" "struct asn_oid *oid"
217.Ft void
218.Fn oid_commit "struct snmp_context *ctx"
219.Ft int
220.Fn oid_get "struct snmp_value *val" "const struct asn_oid *oid"
221.Ft int
222.Fn index_decode "const struct asn_oid *oid" "u_int sub" "u_int code" "..."
223.Ft int
224.Fn index_compare "const struct asn_oid *oid1" "u_int sub" "const struct asn_oid *oid2"
225.Ft int
226.Fn index_compare_off "const struct asn_oid *oid1" "u_int sub" "const struct asn_oid *oid2" "u_int off"
227.Ft void
228.Fn index_append "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src"
229.Ft void
230.Fn index_append_off "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src" "u_int off"
231.Sh DESCRIPTION
232The
233.Xr bsnmpd 1
234SNMP daemon implements a minimal MIB which consists of the system group, part
235of the SNMP MIB, a private configuration MIB, a trap destination table, a
236UDP port table, a community table, a module table, a statistics group and
237a debugging group.
238All other MIBs are support through loadable modules.
239This allows
240.Xr bsnmpd 1
241to use for task, that are not the classical SNMP task.
242.Ss MODULE LOADING AND UNLOADING
243Modules are loaded by writing to the module table.
244This table is indexed by a string, that identifies the module to the daemon.
245This identifier is used
246to select the correct configuration section from the configuration files and
247to identify resources allocated to this module.
248A row in the module table is
249created by writing a string of non-zero length to the
250.Va begemotSnmpdModulePath
251column.
252This string must be the complete path to the file containing the module.
253A module can be unloaded by writing a zero length string to the path column
254of an existing row.
255.Pp
256Modules may depend on each other an hence must be loaded in the correct order.
257The dependencies are listed in the corresponding manual pages.
258.Pp
259Upon loading a module the SNMP daemon expects the module file to a export
260a global symbol
261.Va config .
262This symbol should be a variable of type
263.Vt struct snmp_module :
264.Bd -literal -offset indent
265typedef enum snmpd_proxy_err (*proxy_err_f)(struct snmp_pdu *, void *,
266    const struct asn_oid *, const struct sockaddr *, socklen_t,
267    enum snmpd_input_err, int32_t);
268
269
270struct snmp_module {
271	const char *comment;
272	int (*init)(struct lmodule *, int argc, char *argv[]);
273	int (*fini)(void);
274	void (*idle)(void);
275	void (*dump)(void);
276	void (*config)(void);
277	void (*start)(void);
278	proxy_err_f proxy;
279	const struct snmp_node *tree;
280	u_int tree_size;
281	void (*loading)(const struct lmodule *, int);
282};
283.Ed
284.Pp
285This structure must be statically initialized and its fields have the
286following functions:
287.Bl -tag -width ".It Va tree_size"
288.It Va comment
289This is a string that will be visible in the module table.
290It should give some hint about the function of this module.
291.It Va init
292This function is called upon loading the module.
293The module pointer should
294be stored by the module because it is needed in other calls and the
295argument vector will contain the arguments to this module from the daemons
296command line.
297This function should return 0 if everything is ok or an UNIX error code (see
298.Xr errno 3 ) .
299Once the function returns 0, the
300.Va fini
301function is called when the module is unloaded.
302.It Va fini
303The module is unloaded.
304This gives the module a chance to free resources that
305are not automatically freed.
306Be sure to free all memory, because daemons tend to run very long.
307This function pointer may be
308.Li NULL
309if it is not needed.
310.It Va idle
311If this function pointer is not
312.Li NULL ,
313the function pointed to by it is called whenever the daemon is going
314to wait for an event.
315Try to avoid using this feature.
316.It Va dump
317Whenever the daemon receives a
318.Li SIGUSR1
319it dumps it internal state via
320.Xr syslog 3 .
321If the
322.Va dump
323field is not
324.Li NULL
325it is called by the daemon to dump the state of the module.
326.It Va config
327Whenever the daemon receives a
328.Li SIGHUP
329signal it re-reads its configuration file.
330If the
331.Va config
332field is not
333.Li NULL
334it is called after reading the configuration file to give the module a chance
335to adapt to the new configuration.
336.It Va start
337If not
338.Li NULL
339this function is called after successful loading and initializing the module
340to start its actual operation.
341.It Va proxy
342If the daemon receives a PDU and that PDU has a community string whose
343community was registered by this module and
344.Va proxy
345is not
346.Li NULL
347than this function is called to handle the PDU.
348.It Va tree
349This is a pointer to the node array for the MIB tree implemented by this module.
350.It Va tree_size
351This is the number of nodes in
352.Va tree .
353.It Va loading
354If this pointer is not
355.Li NULL
356it is called whenever another module was loaded or unloaded.
357It gets a
358pointer to that module and a flag that is 0 for unloading and 1 for loading.
359.El
360.Pp
361When everything is ok, the daemon merges the module's MIB tree into its current
362global tree, calls the modules
363.Fn init
364function.
365If this function returns an error, the modules MIB tree is removed from
366the global one and the module is unloaded.
367If initialization is successful, the modules
368.Fn start
369function is called.
370After it returns the
371.Fn loaded
372functions of all modules (including the loaded one) are called.
373.Pp
374When the module is unloaded, its MIB tree is removed from the global one,
375the communities, request id ranges, running timers and selected file
376descriptors are released, the
377.Fn fini
378function is called, the module file is unloaded and the
379.Fn loaded
380functions of all other modules are called.
381.Ss IMPLEMENTING TABLES
382There are a number of macros designed to help implementing SNMP tables.
383A problem while implementing a table is the support for the GETNEXT operator.
384The GETNEXT operation has to find out whether, given an arbitrary OID, the
385lessest table row, that has an OID higher than the given OID.
386The easiest way
387to do this is to keep the table as an ordered list of structures each one
388of which contains an OID that is the index of the table row.
389This allows easy removal, insertion and search.
390.Pp
391The helper macros assume, that the table is organized as a TAILQ (see
392.Xr queue 3
393and each structure contains a
394.Vt struct asn_oid
395that is used as index.
396For simple tables with only a integer or unsigned index, an alternate form
397of the macros is available, that presume the existence of an integer or
398unsigned field as index field.
399.Pp
400The macros have name of the form
401.Bd -literal -offset indent
402{INSERT,FIND,NEXT}_OBJECT_{OID,INT}[_LINK[_INDEX]]
403.Ed
404.Pp
405The
406.Fn INSERT_*
407macros are used in the SET operation to insert a new table row into the table.
408The
409.Fn FIND_*
410macros are used in the GET operation to find a specific row in the table.
411The
412.Fn NEXT_*
413macros are used in the GETNEXT operation to find the next row in the table.
414The last two macros return a pointer to the row structure if a row is found,
415.Li NULL
416otherwise.
417The macros
418.Fn *_OBJECT_OID_*
419assume the existence of a
420.Vt struct asn_oid
421that is used as index, the macros
422.Fn *_OBJECT_INT_*
423assume the existence of an unsigned integer field that is used as index.
424.Pp
425The macros
426.Fn *_INDEX
427allow the explicit naming of the index field in the parameter
428.Fa INDEX ,
429whereas the other macros assume that this field is named
430.Va index .
431The macros
432.Fn *_LINK_*
433allow the explicit naming of the link field of the tail queues, the others
434assume that the link field is named
435.Va link .
436Explicitly naming the link field may be necessary if the same structures
437are held in two or more different tables.
438.Pp
439The arguments to the macros are as follows:
440.Bl -tag -width "INDEX"
441.It Fa PTR
442A pointer to the new structure to be inserted into the table.
443.It Fa LIST
444A pointer to the tail queue head.
445.It Fa LINK
446The name of the link field in the row structure.
447.It Fa INDEX
448The name of the index field in the row structure.
449.It Fa OID
450Must point to the
451.Va var
452field of the
453.Fa value
454argument to the node operation callback.
455This is the OID to search for.
456.It Fa SUB
457This is the index of the start of the table index in the OID pointed to
458by
459.Fa OID .
460This is usually the same as the
461.Fa sub
462argument to the node operation callback.
463.El
464.Ss DAEMON TIMESTAMPS
465The variable
466.Va this_tick
467contains the tick (there are 100 SNMP ticks in a second) when
468the current PDU processing was started.
469The variable
470.Va start_tick
471contains the tick when the daemon was started.
472The function
473.Fn get_ticks
474returns the current tick.
475The number of ticks since the daemon was started
476is
477.Bd -literal -offset indent
478get_ticks() - start_tick
479.Ed
480.Ss THE SYSTEM GROUP
481The scalar fields of the system group are held in the global variable
482.Va systemg :
483.Bd -literal -offset indent
484struct systemg {
485	u_char		*descr;
486	struct asn_oid	object_id;
487	u_char		*contact;
488	u_char		*name;
489	u_char		*location;
490	uint32_t	services;
491	uint32_t	or_last_change;
492};
493.Ed
494.Ss COMMUNITIES
495The SNMP daemon implements a community table.
496On recipte of a request message
497the community string in that message is compared to each of the community
498strings in that table, if a match is found, the global variable
499.Va community
500is set to the community identifier for that community.
501Community identifiers are unsigned integers.
502For the three standard communities there are three constants defined:
503.Bd -literal -offset indent
504#define COMM_INITIALIZE	0
505#define COMM_READ	1
506#define COMM_WRITE	2
507.Ed
508.Pp
509.Va community
510is set to
511.Li COMM_INITIALIZE
512while the assignments in the configuration file are processed.
513To
514.Li COMM_READ
515or
516.Li COMM_WRITE
517when the community strings for the read-write or read-only community are found
518in the incoming PDU.
519.Pp
520Modules can define additional communities.
521This may be necessary to provide
522transport proxying (a PDU received on one communication link is proxied to
523another link) or to implement non-UDP access points to SNMP.
524A new community is defined with the function
525.Fn comm_define .
526It takes the following parameters:
527.Bl -tag -width ".It Fa descr"
528.It Fa priv
529This is an integer identifying the community to the module.
530Each module has its own namespace with regard to this parameter.
531The community table is indexed with the module name and this identifier.
532.It Fa descr
533This is a string providing a human readable description of the community.
534It is visible in the community table.
535.It Fa mod
536This is the module defining the community.
537.It Fa str
538This is the initial community string.
539.El
540.Pp
541The function returns a globally unique community identifier.
542If a PDU is
543received who's community string matches, this identifier is set into the global
544.Va community .
545.Pp
546The function
547.Fn comm_string
548returns the current community string for the given community.
549.Pp
550All communities defined by a module are automatically released when the module
551is unloaded.
552.Ss WELL KNOWN OIDS
553The global variable
554.Va oid_zeroDotZero
555contains the OID 0.0.
556.Ss REQUEST ID RANGES
557For modules that implement SNMP client functions besides SNMP agent functions
558it may be necessary to identify SNMP requests by their identifier to allow
559easier routing of responses to the correct sub-system.
560Request id ranges
561provide a way to aquire globally non-overlapping sub-ranges of the entire
56231-bit id range.
563.Pp
564A request id range is allocated with
565.Fn reqid_allocate .
566The arguments are: the size of the range and the module allocating the range.
567For example, the call
568.Bd -literal -offset indent
569id = reqid_allocate(1000, module);
570.Ed
571.Pp
572allocates a range of 1000 request ids.
573The function returns the request
574id range identifier or 0 if there is not enough identifier space.
575The function
576.Fn reqid_base
577returns the lowest request id in the given range.
578.Pp
579Request id are allocated starting at the lowest one linear throughout the range.
580If the client application may have a lot of outstanding request the range
581must be large enough so that an id is not reused until it is really expired.
582.Fn reqid_next
583returns the sequentially next id in the range.
584.Pp
585The function
586.Fn reqid_istype
587checks whether the request id
588.Fa reqid
589is withing the range identified by
590.Fa type .
591The function
592.Fn reqid_type
593returns the range identifier for the given
594.Fa reqid
595or 0 if the request id is in none of the ranges.
596.Ss TIMERS
597The SNMP daemon supports an arbitrary number of timers with SNMP tick granularity.
598The function
599.Fn timer_start
600arranges for the callback
601.Fa func
602to be called with the argument
603.Fa uarg
604after
605.Fa ticks
606SNMP ticks have expired.
607.Fa mod
608is the module that starts the timer.
609These timers are one-shot, they are not restarted.
610Repeatable timers are started with
611.Fn timer_start_repeat
612which takes an additional argument
613.Fa repeat_ticks .
614The argument
615.Fa ticks
616gives the number of ticks until the first execution of the callback, while
617.Fa repeat_ticks
618is the number of ticks between invocations of the callback.
619Note, that currently the number of initial ticks silently may be set identical
620to the number of ticks between callback invocations.
621The function returns a timer identifier that can be used to stop the timer via
622.Fn timer_stop .
623If a module is unloaded all timers started by the module that have not expired
624yet are stopped.
625.Ss FILE DESCRIPTOR SUPPORT
626A module may need to get input from socket file descriptors without blocking
627the daemon (for example to implement alternative SNMP transports).
628.Pp
629The function
630.Fn fd_select
631causes the callback function
632.Fa func
633to be called with the file descriptor
634.Fa fd
635and the user argument
636.Fa uarg
637whenever the file descriptor
638.Fa fd
639can be read or has a close condition.
640If the file descriptor is not in
641non-blocking mode, it is set to non-blocking mode.
642If the callback is not needed anymore,
643.Fn fd_deselect
644may be called with the value returned from
645.Fn fd_select .
646All file descriptors selected by a module are automatically deselected when
647the module is unloaded.
648.Pp
649To temporarily suspend the file descriptor registration
650.Fn fd_suspend
651can be called.
652This also causes the file descriptor to be switched back to
653blocking mode if it was blocking prior the call to
654.Fn fd_select .
655This is necessary to do synchronous input on a selected socket.
656The effect of
657.Fn fd_suspend
658can be undone with
659.Fn fd_resume .
660.Ss OBJECT RESOURCES
661The system group contains an object resource table.
662A module may create an entry in this table by calling
663.Fn or_register
664with the
665.Fa oid
666to be registered, a textual description in
667.Fa str
668and a pointer to the module
669.Fa mod .
670The registration can be removed with
671.Fn or_unregister .
672All registrations of a module are automatically removed if the module is
673unloaded.
674.Ss TRANSMIT AND RECEIVE BUFFERS
675A buffer is allocated via
676.Fn buf_alloc .
677The argument must be 1 for transmit and 0 for receive buffers.
678The function may return
679.Li NULL
680if there is no memory available.
681The current buffersize can be obtained with
682.Fn buf_size .
683.Sh PROCESSING PDUS
684For modules that need to do their own PDU processing (for example for proxying)
685the following functions are available:
686.Pp
687Function
688.Fn snmp_input_start
689decodes the PDU, searches the community, and sets the global
690.Va this_tick .
691It returns one of the following error codes:
692.Bl -tag -width ".It Er SNMPD_INPUT_VALBADLEN"
693.It Er SNMPD_INPUT_OK
694Everything ok, continue with processing.
695.It Er SNMPD_INPUT_FAILED
696The PDU could not be decoded, has a wrong version or an unknown
697community string.
698.It Er SNMPD_INPUT_VALBADLEN
699A SET PDU had a value field in a binding with a wrong length field in an
700ASN.1 header.
701.It Er SNMPD_INPUT_VALRANGE
702A SET PDU had a value field in a binding with a value that is out of range
703for the given ASN.1 type.
704.It Er SNMPD_INPUT_VALBADENC
705A SET PDU had a value field in a binding with wrong ASN.1 encoding.
706.It Er SNMPD_INPUT_TRUNC
707The buffer appears to contain a valid begin of a PDU, but is too short.
708For streaming transports this means that the caller must save what he
709already has and trying to obtain more input and reissue this input to
710the function.
711For datagram transports this means that part of the
712datagram was lost and the input should be ignored.
713.El
714.Pp
715The function
716.Fn snmp_input_finish
717does the other half of processing: if
718.Fn snmp_input_start
719did not return OK, tries to construct an error response.
720If the start was OK, it calls the correct function from
721.Xr bsnmpagent 3
722to execute the request and depending on the outcome constructs a response or
723error response PDU or ignores the request PDU.
724It returns either
725.Er SNMPD_INPUT_OK
726or
727.Er SNMPD_INPUT_FAILED .
728In the first case a response PDU was constructed and should be sent.
729.Pp
730The function
731.Fn snmp_output
732takes a PDU and encodes it.
733.Pp
734The function
735.Fn snmp_send_port
736takes a PDU, encodes it and sends it through the given port (identified by
737the transport and the index in the port table) to the given address.
738.Pp
739The function
740.Fn snmp_send_trap
741sends a trap to all trap destinations.
742The arguments are the
743.Fa oid
744identifying the trap and a NULL-terminated list of
745.Vt struct snmp_value
746pointers that are to be inserted into the trap binding list.
747.Ss SIMPLE ACTION SUPPORT
748For simple scalar variables that need no dependencies a number of support
749functions is available to handle the set, commit, rollback and get.
750.Pp
751The following functions are used for OCTET STRING scalars, either NUL terminated
752or not:
753.Bl -tag -width "XXXXXXXXX"
754.It Fn string_save
755should be called for SNMP_OP_SET.
756.Fa value
757and
758.Fa ctx
759are the resp\&.\& arguments to the node callback.
760.Fa valp
761is a pointer to the pointer that holds the current value and
762.Fa req_size
763should be -1 if any size of the string is acceptable or a number larger or
764equal zero if the string must have a specific size.
765The function saves
766the old value in the scratch area (note, that any initial value must have
767been allocated by
768.Xr malloc 3 ) ,
769allocates a new string, copies over the new value, NUL-terminates it and
770sets the new current value.
771.It Fn string_commit
772simply frees the saved old value in the scratch area.
773.It Fn string_rollback
774frees the new value, and puts back the old one.
775.It Fn string_get
776is used for GET or GETNEXT.
777The function
778.It Fn string_get_max
779can be used instead of
780.Nf stringto ensure that the returned string has a certain maximum length.
781If
782.Fa len
783is -1, the length is computed via
784.Xr strlen 3
785from the current string value.
786If the current value is NULL,
787a OCTET STRING of zero length is returned.
788.It Fn string_free
789must be called if either rollback or commit fails to free the saved old value.
790.El
791.Pp
792The following functions are used to process scalars of type IP-address:
793.Bl -tag -width "XXXXXXXXX"
794.It Fn ip_save
795Saves the current value in the scratch area and sets the new value from
796.Fa valp .
797.It Fn ip_commit
798Does nothing.
799.It Fn ip_rollback
800Restores the old IP address from the scratch area.
801.It Fn ip_get
802Retrieves the IP current address.
803.El
804.Pp
805The following functions handle OID-typed variables:
806.Bl -tag -width "XXXXXXXXX"
807.It Fn oid_save
808Saves the current value in the scratch area by allocating a
809.Vt struct asn_oid
810with
811.Xr malloc 3
812and sets the new value from
813.Fa oid .
814.It Fn oid_commit
815Frees the old value in the scratch area.
816.It Fn oid_rollback
817Restores the old OID from the scratch area and frees the old OID.
818.It Fn oid_get
819Retrieves the OID
820.El
821.Ss TABLE INDEX HANDLING
822The following functions help in handling table indexes:
823.Bl -tag -width "XXXXXXXXX"
824.It Fn index_decode
825Decodes the index part of the OID.
826The parameter
827.Fa oid
828must be a pointer to the
829.Va var
830field of the
831.Fa value
832argument of the node callback.
833The
834.Fa sub
835argument must be the index of the start of the index in the OID (this is
836the
837.Fa sub
838argument to the node callback).
839.Fa code
840is the index expression (parameter
841.Fa idx
842to the node callback).
843These parameters are followed by parameters depending on the syntax of the index
844elements as follows:
845.Bl -tag -width ".It Li OCTET STRING"
846.It Li INTEGER
847.Vt int32_t *
848expected as argument.
849.It Li COUNTER64
850.Vt uint64_t *
851expected as argument.
852Note, that this syntax is illegal for indexes.
853.It Li OCTET STRING
854A
855.Vt u_char **
856and a
857.Vt size_t *
858expected as arguments.
859A buffer is allocated to hold the decoded string.
860.It Li OID
861A
862.Vt struct asn_oid *
863is expected as argument.
864.It Li IP ADDRESS
865A
866.Vt u_int8_t *
867expected as argument that points to a buffer of at least four byte.
868.It Li COUNTER, GAUGE, TIMETICKS
869A
870.Vt u_int32_t
871expected.
872.It Li NULL
873No argument expected.
874.El
875.It Fn index_compare
876compares the current variable with an OID.
877.Fa oid1
878and
879.Fa sub
880come from the node callback arguments
881.Fa value->var
882and
883.Fa sub
884resp.
885.Fa oid2
886is the OID to compare to.
887The function returns -1, 0, +1 when the
888variable is lesser, equal, higher to the given OID.
889.Fa oid2
890must contain only the index part of the table column.
891.It Fn index_compare_off
892is equivalent to
893.Fn index_compare
894except that it takes an additional parameter
895.Fa off
896that causes it to ignore the first
897.Fa off
898components of both indexes.
899.It Fn index_append
900appends OID
901.Fa src
902beginning at position
903.Fa sub
904to
905.Fa dst .
906.It Fn index_append_off
907appends OID
908.Fa src
909beginning at position
910.Fa off
911to
912.Fa dst
913beginning at position
914.Fa sub
915+
916.Fa off .
917.El
918.Sh SEE ALSO
919.Xr gensnmptree 1 ,
920.Xr bsnmpd 1 ,
921.Xr bsnmpagent 3 ,
922.Xr bsnmpclient 3 ,
923.Xr bsnmplib 3
924.Sh STANDARDS
925This implementation conforms to the applicable IETF RFCs and ITU-T
926recommendations.
927.Sh AUTHORS
928.An Hartmut Brandt Aq harti@freebsd.org
929