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