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