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