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