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 December 19, 2010 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 oid_usmUnknownEngineIDs , 64.Nm oid_usmNotInTimeWindows , 65.Nm reqid_allocate , 66.Nm reqid_next , 67.Nm reqid_base , 68.Nm reqid_istype , 69.Nm reqid_type , 70.Nm timer_start , 71.Nm timer_start_repeat , 72.Nm timer_stop , 73.Nm fd_select , 74.Nm fd_deselect , 75.Nm fd_suspend , 76.Nm fd_resume , 77.Nm or_register , 78.Nm or_unregister , 79.Nm buf_alloc , 80.Nm buf_size , 81.Nm snmp_input_start , 82.Nm snmp_input_finish , 83.Nm snmp_output , 84.Nm snmp_send_port , 85.Nm snmp_send_trap , 86.Nm snmp_pdu_auth_access 87.Nm string_save , 88.Nm string_commit , 89.Nm string_rollback , 90.Nm string_get , 91.Nm string_get_max , 92.Nm string_free , 93.Nm ip_save , 94.Nm ip_rollback , 95.Nm ip_commit , 96.Nm ip_get , 97.Nm oid_save , 98.Nm oid_rollback , 99.Nm oid_commit , 100.Nm oid_get , 101.Nm index_decode , 102.Nm index_compare , 103.Nm index_compare_off , 104.Nm index_append , 105.Nm index_append_off , 106.Nm snmpd_usmstats , 107.Nm bsnmpd_get_usm_stats , 108.Nm bsnmpd_reset_usm_stats , 109.Nm usm_first_user , 110.Nm usm_next_user , 111.Nm usm_find_user , 112.Nm usm_new_user , 113.Nm usm_delete_user , 114.Nm usm_flush_users , 115.Nm usm_user , 116.Nm snmpd_target_stat , 117.Nm bsnmpd_get_target_stats , 118.Nm target_first_address , 119.Nm target_next_address , 120.Nm target_new_address , 121.Nm target_activate_address , 122.Nm target_delete_address , 123.Nm target_first_param , 124.Nm target_next_param , 125.Nm target_new_param , 126.Nm target_delete_param , 127.Nm target_first_notify , 128.Nm target_next_notify , 129.Nm target_new_notify , 130.Nm target_delete_notify , 131.Nm target_flush_all , 132.Nm target_address , 133.Nm target_param , 134.Nm target_notify 135.Nd "SNMP daemon loadable module interface" 136.Sh LIBRARY 137Begemot SNMP library 138.Pq libbsnmp, -lbsnmp 139.Sh SYNOPSIS 140.In bsnmp/snmpmod.h 141.Fn INSERT_OBJECT_OID_LINK_INDEX "PTR" "LIST" "LINK" "INDEX" 142.Fn INSERT_OBJECT_INT_LINK_INDEX "PTR" "LIST" "LINK" "INDEX" 143.Fn FIND_OBJECT_OID_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX" 144.Fn FIND_OBJECT_INT_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX" 145.Fn NEXT_OBJECT_OID_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX" 146.Fn NEXT_OBJECT_INT_LINK_INDEX "LIST" "OID" "SUB" "LINK" "INDEX" 147.Fn INSERT_OBJECT_OID_LINK "PTR" "LIST" "LINK" 148.Fn INSERT_OBJECT_INT_LINK "PTR" "LIST" "LINK" 149.Fn FIND_OBJECT_OID_LINK "LIST" "OID" "SUB" "LINK" 150.Fn FIND_OBJECT_INT_LINK "LIST" "OID" "SUB" "LINK" 151.Fn NEXT_OBJECT_OID_LINK "LIST" "OID" "SUB" "LINK" 152.Fn NEXT_OBJECT_INT_LINK "LIST" "OID" "SUB" "LINK" 153.Fn INSERT_OBJECT_OID "PTR" "LIST" 154.Fn INSERT_OBJECT_INT "PTR" "LIST" 155.Fn FIND_OBJECT_OID "LIST" "OID" "SUB" 156.Fn FIND_OBJECT_INT "LIST" "OID" "SUB" 157.Fn NEXT_OBJECT_OID "LIST" "OID" "SUB" 158.Fn NEXT_OBJECT_INT "LIST" "OID" "SUB" 159.Vt extern uint64_t this_tick ; 160.Vt extern uint64_t start_tick ; 161.Ft uint64_t 162.Fn get_ticks "void" 163.Vt extern struct systemg systemg ; 164.Ft u_int 165.Fn comm_define "u_int priv" "const char *descr" "struct lmodule *mod" "const char *str" 166.Ft const char * 167.Fn comm_string "u_int comm" 168.Vt extern u_int community ; 169.Vt extern const struct asn_oid oid_zeroDotZero ; 170.Ft u_int 171.Fn reqid_allocate "int size" "struct lmodule *mod" 172.Ft int32_t 173.Fn reqid_next "u_int type" 174.Ft int32_t 175.Fn reqid_base "u_int type" 176.Ft int 177.Fn reqid_istype "int32_t reqid" "u_int type" 178.Ft u_int 179.Fn reqid_type "int32_t reqid" 180.Ft void * 181.Fn timer_start "u_int ticks" "void (*func)(void *)" "void *uarg" "struct lmodule *mod" 182.Ft void * 183.Fn timer_start_repeat "u_int ticks" "u_int repeat_ticks" "void (*func)(void *)" "void *uarg" "struct lmodule *mod" 184.Ft void 185.Fn timer_stop "void *timer_id" 186.Ft void * 187.Fn fd_select "int fd" "void (*func)(int, void *)" "void *uarg" "struct lmodule *mod" 188.Ft void 189.Fn fd_deselect "void *fd_id" 190.Ft void 191.Fn fd_suspend "void *fd_id" 192.Ft int 193.Fn fd_resume "void *fd_id" 194.Ft u_int 195.Fn or_register "const struct asn_oid *oid" "const char *descr" "struct lmodule *mod" 196.Ft void 197.Fn or_unregister "u_int or_id" 198.Ft void * 199.Fn buf_alloc "int tx" 200.Ft size_t 201.Fn buf_size "int tx" 202.Ft enum snmpd_input_err 203.Fo snmp_input_start 204.Fa "const u_char *buf" "size_t len" "const char *source" 205.Fa "struct snmp_pdu *pdu" "int32_t *ip" "size_t *pdulen" 206.Fc 207.Ft enum snmpd_input_err 208.Fo snmp_input_finish 209.Fa "struct snmp_pdu *pdu" "const u_char *rcvbuf" 210.Fa "size_t rcvlen" "u_char *sndbuf" "size_t *sndlen" "const char *source" 211.Fa "enum snmpd_input_err ierr" "int32_t ip" "void *data" 212.Fc 213.Ft void 214.Fo snmp_output 215.Fa "struct snmp_pdu *pdu" "u_char *sndbuf" "size_t *sndlen" 216.Fa "const char *dest" 217.Fc 218.Ft void 219.Fo snmp_send_port 220.Fa "void *trans" "const struct asn_oid *port" 221.Fa "struct snmp_pdu *pdu" "const struct sockaddr *addr" "socklen_t addrlen" 222.Fc 223.Ft void 224.Fn snmp_send_trap "const struct asn_oid *oid" "..." 225.Ft enum snmp_code 226.Fn snmp_pdu_auth_access "struct snmp_pdu *pdu" "int32_t *ip" 227.Ft int 228.Fn string_save "struct snmp_value *val" "struct snmp_context *ctx" "ssize_t req_size" "u_char **strp" 229.Ft void 230.Fn string_commit "struct snmp_context *ctx" 231.Ft void 232.Fn string_rollback "struct snmp_context *ctx" "u_char **strp" 233.Ft int 234.Fn string_get "struct snmp_value *val" "const u_char *str" "ssize_t len" 235.Ft int 236.Fn string_get_max "struct snmp_value *val" "const u_char *str" "ssize_t len" "size_t maxlen" 237.Ft void 238.Fn string_free "struct snmp_context *ctx" 239.Ft int 240.Fn ip_save "struct snmp_value *val" "struct snmp_context *ctx" "u_char *ipa" 241.Ft void 242.Fn ip_rollback "struct snmp_context *ctx" "u_char *ipa" 243.Ft void 244.Fn ip_commit "struct snmp_context *ctx" 245.Ft int 246.Fn ip_get "struct snmp_value *val" "u_char *ipa" 247.Ft int 248.Fn oid_save "struct snmp_value *val" "struct snmp_context *ctx" "struct asn_oid *oid" 249.Ft void 250.Fn oid_rollback "struct snmp_context *ctx" "struct asn_oid *oid" 251.Ft void 252.Fn oid_commit "struct snmp_context *ctx" 253.Ft int 254.Fn oid_get "struct snmp_value *val" "const struct asn_oid *oid" 255.Ft int 256.Fn index_decode "const struct asn_oid *oid" "u_int sub" "u_int code" "..." 257.Ft int 258.Fn index_compare "const struct asn_oid *oid1" "u_int sub" "const struct asn_oid *oid2" 259.Ft int 260.Fn index_compare_off "const struct asn_oid *oid1" "u_int sub" "const struct asn_oid *oid2" "u_int off" 261.Ft void 262.Fn index_append "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src" 263.Ft void 264.Fn index_append_off "struct asn_oid *dst" "u_int sub" "const struct asn_oid *src" "u_int off" 265.Vt extern struct snmpd_usmstat snmpd_usmstats ; 266.Ft struct snmpd_usmstat * 267.Fn bsnmpd_get_usm_stats "void" 268.Ft void 269.Fn bsnmpd_reset_usm_stats "void" 270.Ft struct usm_user * 271.Fn usm_first_user "void" 272.Ft struct usm_user * 273.Fn usm_next_user "struct usm_user *uuser" 274.Ft struct usm_user * 275.Fn usm_find_user "uint8_t *engine" "uint32_t elen" "char *uname" 276.Ft struct usm_user * 277.Fn usm_new_user "uint8_t *engine" "uint32_t elen" "char *uname" 278.Ft void 279.Fn usm_delete_user "struct usm_user *" 280.Ft void 281.Fn usm_flush_users "void" 282.Vt extern struct usm_user *usm_user; 283.Ft struct snmpd_target_stats * 284.Fn bsnmpd_get_target_stats "void" 285.Ft struct target_address * 286.Fn target_first_address "void" 287.Ft struct target_address * 288.Fn target_next_address "struct target_address *" 289.Ft struct target_address * 290.Fn target_new_address "char *" 291.Ft int 292.Fn target_activate_address "struct target_address *" 293.Ft int 294.Fn target_delete_address "struct target_address *" 295.Ft struct target_param * 296.Fn target_first_param "void" 297.Ft struct target_param * 298.Fn target_next_param "struct target_param *" 299.Ft struct target_param * 300.Fn target_new_param "char *" 301.Ft int 302.Fn target_delete_param "struct target_param *" 303.Ft struct target_notify * 304.Fn target_first_notify "void" 305.Ft struct target_notify * 306.Fn target_next_notify "struct target_notify *" 307.Ft struct target_notify * 308.Fn target_new_notify "char *" 309.Ft int 310.Fn target_delete_notify "struct target_notify *" 311.Ft void 312.Fn target_flush_all "void" 313.Vt extern const struct asn_oid oid_usmUnknownEngineIDs; 314.Vt extern const struct asn_oid oid_usmNotInTimeWindows; 315.Sh DESCRIPTION 316The 317.Xr bsnmpd 1 318SNMP daemon implements a minimal MIB which consists of the system group, part 319of the SNMP MIB, a private configuration MIB, a trap destination table, a 320UDP port table, a community table, a module table, a statistics group and 321a debugging group. 322All other MIBs are support through loadable modules. 323This allows 324.Xr bsnmpd 1 325to use for task, that are not the classical SNMP task. 326.Ss MODULE LOADING AND UNLOADING 327Modules are loaded by writing to the module table. 328This table is indexed by a string, that identifies the module to the daemon. 329This identifier is used 330to select the correct configuration section from the configuration files and 331to identify resources allocated to this module. 332A row in the module table is 333created by writing a string of non-zero length to the 334.Va begemotSnmpdModulePath 335column. 336This string must be the complete path to the file containing the module. 337A module can be unloaded by writing a zero length string to the path column 338of an existing row. 339.Pp 340Modules may depend on each other an hence must be loaded in the correct order. 341The dependencies are listed in the corresponding manual pages. 342.Pp 343Upon loading a module the SNMP daemon expects the module file to a export 344a global symbol 345.Va config . 346This symbol should be a variable of type 347.Vt struct snmp_module : 348.Bd -literal -offset indent 349typedef enum snmpd_proxy_err (*proxy_err_f)(struct snmp_pdu *, void *, 350 const struct asn_oid *, const struct sockaddr *, socklen_t, 351 enum snmpd_input_err, int32_t); 352 353 354struct snmp_module { 355 const char *comment; 356 int (*init)(struct lmodule *, int argc, char *argv[]); 357 int (*fini)(void); 358 void (*idle)(void); 359 void (*dump)(void); 360 void (*config)(void); 361 void (*start)(void); 362 proxy_err_f proxy; 363 const struct snmp_node *tree; 364 u_int tree_size; 365 void (*loading)(const struct lmodule *, int); 366}; 367.Ed 368.Pp 369This structure must be statically initialized and its fields have the 370following functions: 371.Bl -tag -width ".It Va tree_size" 372.It Va comment 373This is a string that will be visible in the module table. 374It should give some hint about the function of this module. 375.It Va init 376This function is called upon loading the module. 377The module pointer should 378be stored by the module because it is needed in other calls and the 379argument vector will contain the arguments to this module from the daemons 380command line. 381This function should return 0 if everything is ok or an UNIX error code (see 382.Xr errno 3 ) . 383Once the function returns 0, the 384.Va fini 385function is called when the module is unloaded. 386.It Va fini 387The module is unloaded. 388This gives the module a chance to free resources that 389are not automatically freed. 390Be sure to free all memory, because daemons tend to run very long. 391This function pointer may be 392.Li NULL 393if it is not needed. 394.It Va idle 395If this function pointer is not 396.Li NULL , 397the function pointed to by it is called whenever the daemon is going 398to wait for an event. 399Try to avoid using this feature. 400.It Va dump 401Whenever the daemon receives a 402.Li SIGUSR1 403it dumps it internal state via 404.Xr syslog 3 . 405If the 406.Va dump 407field is not 408.Li NULL 409it is called by the daemon to dump the state of the module. 410.It Va config 411Whenever the daemon receives a 412.Li SIGHUP 413signal it re-reads its configuration file. 414If the 415.Va config 416field is not 417.Li NULL 418it is called after reading the configuration file to give the module a chance 419to adapt to the new configuration. 420.It Va start 421If not 422.Li NULL 423this function is called after successful loading and initializing the module 424to start its actual operation. 425.It Va proxy 426If the daemon receives a PDU and that PDU has a community string whose 427community was registered by this module and 428.Va proxy 429is not 430.Li NULL 431than this function is called to handle the PDU. 432.It Va tree 433This is a pointer to the node array for the MIB tree implemented by this module. 434.It Va tree_size 435This is the number of nodes in 436.Va tree . 437.It Va loading 438If this pointer is not 439.Li NULL 440it is called whenever another module was loaded or unloaded. 441It gets a 442pointer to that module and a flag that is 0 for unloading and 1 for loading. 443.El 444.Pp 445When everything is ok, the daemon merges the module's MIB tree into its current 446global tree, calls the modules 447.Fn init 448function. 449If this function returns an error, the modules MIB tree is removed from 450the global one and the module is unloaded. 451If initialization is successful, the modules 452.Fn start 453function is called. 454After it returns the 455.Fn loaded 456functions of all modules (including the loaded one) are called. 457.Pp 458When the module is unloaded, its MIB tree is removed from the global one, 459the communities, request id ranges, running timers and selected file 460descriptors are released, the 461.Fn fini 462function is called, the module file is unloaded and the 463.Fn loaded 464functions of all other modules are called. 465.Ss IMPLEMENTING TABLES 466There are a number of macros designed to help implementing SNMP tables. 467A problem while implementing a table is the support for the GETNEXT operator. 468The GETNEXT operation has to find out whether, given an arbitrary OID, the 469lessest table row, that has an OID higher than the given OID. 470The easiest way 471to do this is to keep the table as an ordered list of structures each one 472of which contains an OID that is the index of the table row. 473This allows easy removal, insertion and search. 474.Pp 475The helper macros assume, that the table is organized as a TAILQ (see 476.Xr queue 3 477and each structure contains a 478.Vt struct asn_oid 479that is used as index. 480For simple tables with only a integer or unsigned index, an alternate form 481of the macros is available, that presume the existence of an integer or 482unsigned field as index field. 483.Pp 484The macros have name of the form 485.Bd -literal -offset indent 486{INSERT,FIND,NEXT}_OBJECT_{OID,INT}[_LINK[_INDEX]] 487.Ed 488.Pp 489The 490.Fn INSERT_* 491macros are used in the SET operation to insert a new table row into the table. 492The 493.Fn FIND_* 494macros are used in the GET operation to find a specific row in the table. 495The 496.Fn NEXT_* 497macros are used in the GETNEXT operation to find the next row in the table. 498The last two macros return a pointer to the row structure if a row is found, 499.Li NULL 500otherwise. 501The macros 502.Fn *_OBJECT_OID_* 503assume the existence of a 504.Vt struct asn_oid 505that is used as index, the macros 506.Fn *_OBJECT_INT_* 507assume the existence of an unsigned integer field that is used as index. 508.Pp 509The macros 510.Fn *_INDEX 511allow the explicit naming of the index field in the parameter 512.Fa INDEX , 513whereas the other macros assume that this field is named 514.Va index . 515The macros 516.Fn *_LINK_* 517allow the explicit naming of the link field of the tail queues, the others 518assume that the link field is named 519.Va link . 520Explicitly naming the link field may be necessary if the same structures 521are held in two or more different tables. 522.Pp 523The arguments to the macros are as follows: 524.Bl -tag -width "INDEX" 525.It Fa PTR 526A pointer to the new structure to be inserted into the table. 527.It Fa LIST 528A pointer to the tail queue head. 529.It Fa LINK 530The name of the link field in the row structure. 531.It Fa INDEX 532The name of the index field in the row structure. 533.It Fa OID 534Must point to the 535.Va var 536field of the 537.Fa value 538argument to the node operation callback. 539This is the OID to search for. 540.It Fa SUB 541This is the index of the start of the table index in the OID pointed to 542by 543.Fa OID . 544This is usually the same as the 545.Fa sub 546argument to the node operation callback. 547.El 548.Ss DAEMON TIMESTAMPS 549The variable 550.Va this_tick 551contains the tick (there are 100 SNMP ticks in a second) when 552the current PDU processing was started. 553The variable 554.Va start_tick 555contains the tick when the daemon was started. 556The function 557.Fn get_ticks 558returns the current tick. 559The number of ticks since the daemon was started 560is 561.Bd -literal -offset indent 562get_ticks() - start_tick 563.Ed 564.Ss THE SYSTEM GROUP 565The scalar fields of the system group are held in the global variable 566.Va systemg : 567.Bd -literal -offset indent 568struct systemg { 569 u_char *descr; 570 struct asn_oid object_id; 571 u_char *contact; 572 u_char *name; 573 u_char *location; 574 uint32_t services; 575 uint32_t or_last_change; 576}; 577.Ed 578.Ss COMMUNITIES 579The SNMP daemon implements a community table. 580On recipte of a request message 581the community string in that message is compared to each of the community 582strings in that table, if a match is found, the global variable 583.Va community 584is set to the community identifier for that community. 585Community identifiers are unsigned integers. 586For the three standard communities there are three constants defined: 587.Bd -literal -offset indent 588#define COMM_INITIALIZE 0 589#define COMM_READ 1 590#define COMM_WRITE 2 591.Ed 592.Pp 593.Va community 594is set to 595.Li COMM_INITIALIZE 596while the assignments in the configuration file are processed. 597To 598.Li COMM_READ 599or 600.Li COMM_WRITE 601when the community strings for the read-write or read-only community are found 602in the incoming PDU. 603.Pp 604Modules can define additional communities. 605This may be necessary to provide 606transport proxying (a PDU received on one communication link is proxied to 607another link) or to implement non-UDP access points to SNMP. 608A new community is defined with the function 609.Fn comm_define . 610It takes the following parameters: 611.Bl -tag -width ".It Fa descr" 612.It Fa priv 613This is an integer identifying the community to the module. 614Each module has its own namespace with regard to this parameter. 615The community table is indexed with the module name and this identifier. 616.It Fa descr 617This is a string providing a human readable description of the community. 618It is visible in the community table. 619.It Fa mod 620This is the module defining the community. 621.It Fa str 622This is the initial community string. 623.El 624.Pp 625The function returns a globally unique community identifier. 626If a SNMPv1 or SNMPv2 PDU is 627received who's community string matches, this identifier is set into the global 628.Va community . 629.Pp 630The function 631.Fn comm_string 632returns the current community string for the given community. 633.Pp 634All communities defined by a module are automatically released when the module 635is unloaded. 636.Ss THE USER-BASED SECURITY GROUP 637The scalar statistics of the USM group are held in the global variable 638.Va snmpd_usmstats : 639.Bd -literal -offset indent 640struct snmpd_usmstat { 641 uint32_t unsupported_seclevels; 642 uint32_t not_in_time_windows; 643 uint32_t unknown_users; 644 uint32_t unknown_engine_ids; 645 uint32_t wrong_digests; 646 uint32_t decrypt_errors; 647}; 648.Ed 649.Fn bsnmpd_get_usm_stats 650returns a pointer to the global structure containing the statistics. 651.Fn bsnmpd_reset_usm_stats 652clears the statistics of the USM group. 653.Pp 654A global list of configured USM users is maintained by the daemon. 655.Bd -literal -offset indent 656struct usm_user { 657 struct snmp_user suser; 658 uint8_t user_engine_id[SNMP_ENGINE_ID_SIZ]; 659 uint32_t user_engine_len; 660 char user_public[SNMP_ADM_STR32_SIZ]; 661 uint32_t user_public_len; 662 int32_t status; 663 int32_t type; 664 SLIST_ENTRY(usm_user) up; 665}; 666.Ed 667This structure represents an USM user. The daemon only responds to SNMPv3 PDUs 668with user credentials matching an USM user entry in its global list. 669If a SNMPv3 PDU is received, whose security model is USM, the global 670.Va usm_user 671is set to point at the user entry that matches the credentials contained in 672the PDU. 673However, the daemon does not create or remove USM users, it gives an interface 674to external loadable module(s) to manage the list. 675.Fn usm_new_user 676adds an user entry in the list, and 677.Fn usm_delete_user 678deletes an existing entry from the list. 679.Fn usm_flush_users 680is used to remove all configured USM users. 681.Fn usm_first_user 682will return the first user in the list, or 683.Li NULL 684if the list is empty. 685.Fn usm_next_user 686will return the next user of a given entry if one exists, or 687.Li NULL . 688The list is sorted according to the USM user name and Engine ID. 689.Fn usm_find_user 690returns the USM user entry matching the given 691.Fa engine 692and 693.Fa uname 694or 695.Li NULL 696if an user with the specified name and engine id is not present in the list. 697.Ss THE MANAGEMENT TARGET GROUP 698The Management Target group holds target address information used when sending 699SNMPv3 notifications. 700.Pp 701The scalar statistics of the Management Target group are held in the global 702variable 703.Va snmpd_target_stats : 704.Bd -literal -offset indent 705struct snmpd_target_stats { 706 uint32_t unavail_contexts; 707 uint32_t unknown_contexts; 708}; 709.Ed 710.Fn bsnmpd_get_target_stats 711returns a pointer to the global structure containing the statistics. 712.Pp 713Three global lists of configured management target addresses, parameters and 714notifications respectively are maintained by the daemon. 715.Bd -literal -offset indent 716struct target_address { 717 char name[SNMP_ADM_STR32_SIZ]; 718 uint8_t address[SNMP_UDP_ADDR_SIZ]; 719 int32_t timeout; 720 int32_t retry; 721 char taglist[SNMP_TAG_SIZ]; 722 char paramname[SNMP_ADM_STR32_SIZ]; 723 int32_t type; 724 int32_t socket; 725 int32_t status; 726 SLIST_ENTRY(target_address) ta; 727}; 728.Ed 729This structure represents a SNMPv3 Management Target address. Each time a SNMP 730TRAP is send the daemon will send the Trap to all active Management Target 731addresses in its global list. 732.Bd -literal -offset indent 733struct target_param { 734 char name[SNMP_ADM_STR32_SIZ]; 735 int32_t mpmodel; 736 int32_t sec_model; 737 char secname[SNMP_ADM_STR32_SIZ]; 738 enum snmp_usm_level sec_level; 739 int32_t type; 740 int32_t status; 741 SLIST_ENTRY(target_param) tp; 742}; 743.Ed 744This structure represents the information used to generate SNMP messages to the 745associated SNMPv3 Management Target addresses. 746.Bd -literal -offset indent 747struct target_notify { 748 char name[SNMP_ADM_STR32_SIZ]; 749 char taglist[SNMP_TAG_SIZ]; 750 int32_t notify_type; 751 int32_t type; 752 int32_t status; 753 SLIST_ENTRY(target_notify) tn; 754}; 755.Ed 756This structure represents Notification Tag entries - SNMP notifications are sent 757to the Target address for each entry in the Management Target Address list that 758has a tag matching the specified tag in this structure. 759.Pp 760The daemon does not create or remove entries in the Management Target group 761lists, it gives an interface to external loadable module(s) to manage the lists. 762.Fn target_new_address 763adds a target address entry, and 764.Fn target_delete_address 765deletes an existing entry from the target address list. 766.Fn target_activate_address 767creates a socket associated with the target address entry so that SNMP 768notifications may actually be send to that target address. 769.Fn target_first_address 770will return a pointer to the first target address entry in the list, while 771.Fn target_next_address 772will return a pointer to the next target address of a given entry if one exists. 773.Fn target_new_param 774adds a target parameters' entry, and 775.Fn target_delete_param 776deletes an existing entry from the target parameters list. 777.Fn target_first_param 778will return a pointer to the first target parameters' entry in the list, while 779.Fn target_next_param 780will return a pointer to the next target parameters of a given entry if one 781exists. 782.Fn target_new_notify 783adds a notification target entry, and 784.Fn target_delete_notify 785deletes an existing entry from the notification target list. 786.Fn target_first_notify 787will return a pointer to the first notification target entry in the list, while 788.Fn target_next_notify 789will return a pointer to the next notification target of a given entry if one 790exists. 791.Fn target_flush_all 792is used to remove all configured data from the three global Management Target 793Group lists. 794.Ss WELL KNOWN OIDS 795The global variable 796.Va oid_zeroDotZero 797contains the OID 0.0. 798The global variables 799.Va oid_usmUnknownEngineIDs 800.Va oid_usmNotInTimeWindows 801contains the OIDs 1.3.6.1.6.3.15.1.1.4.0 and 1.3.6.1.6.3.15.1.1.2.0 used 802in the SNMPv3 USM Engine Discovery. 803.Ss REQUEST ID RANGES 804For modules that implement SNMP client functions besides SNMP agent functions 805it may be necessary to identify SNMP requests by their identifier to allow 806easier routing of responses to the correct sub-system. 807Request id ranges 808provide a way to acquire globally non-overlapping sub-ranges of the entire 80931-bit id range. 810.Pp 811A request id range is allocated with 812.Fn reqid_allocate . 813The arguments are: the size of the range and the module allocating the range. 814For example, the call 815.Bd -literal -offset indent 816id = reqid_allocate(1000, module); 817.Ed 818.Pp 819allocates a range of 1000 request ids. 820The function returns the request 821id range identifier or 0 if there is not enough identifier space. 822The function 823.Fn reqid_base 824returns the lowest request id in the given range. 825.Pp 826Request id are allocated starting at the lowest one linear throughout the range. 827If the client application may have a lot of outstanding request the range 828must be large enough so that an id is not reused until it is really expired. 829.Fn reqid_next 830returns the sequentially next id in the range. 831.Pp 832The function 833.Fn reqid_istype 834checks whether the request id 835.Fa reqid 836is within the range identified by 837.Fa type . 838The function 839.Fn reqid_type 840returns the range identifier for the given 841.Fa reqid 842or 0 if the request id is in none of the ranges. 843.Ss TIMERS 844The SNMP daemon supports an arbitrary number of timers with SNMP tick granularity. 845The function 846.Fn timer_start 847arranges for the callback 848.Fa func 849to be called with the argument 850.Fa uarg 851after 852.Fa ticks 853SNMP ticks have expired. 854.Fa mod 855is the module that starts the timer. 856These timers are one-shot, they are not restarted. 857Repeatable timers are started with 858.Fn timer_start_repeat 859which takes an additional argument 860.Fa repeat_ticks . 861The argument 862.Fa ticks 863gives the number of ticks until the first execution of the callback, while 864.Fa repeat_ticks 865is the number of ticks between invocations of the callback. 866Note, that currently the number of initial ticks silently may be set identical 867to the number of ticks between callback invocations. 868The function returns a timer identifier that can be used to stop the timer via 869.Fn timer_stop . 870If a module is unloaded all timers started by the module that have not expired 871yet are stopped. 872.Ss FILE DESCRIPTOR SUPPORT 873A module may need to get input from socket file descriptors without blocking 874the daemon (for example to implement alternative SNMP transports). 875.Pp 876The function 877.Fn fd_select 878causes the callback function 879.Fa func 880to be called with the file descriptor 881.Fa fd 882and the user argument 883.Fa uarg 884whenever the file descriptor 885.Fa fd 886can be read or has a close condition. 887If the file descriptor is not in 888non-blocking mode, it is set to non-blocking mode. 889If the callback is not needed anymore, 890.Fn fd_deselect 891may be called with the value returned from 892.Fn fd_select . 893All file descriptors selected by a module are automatically deselected when 894the module is unloaded. 895.Pp 896To temporarily suspend the file descriptor registration 897.Fn fd_suspend 898can be called. 899This also causes the file descriptor to be switched back to 900blocking mode if it was blocking prior the call to 901.Fn fd_select . 902This is necessary to do synchronous input on a selected socket. 903The effect of 904.Fn fd_suspend 905can be undone with 906.Fn fd_resume . 907.Ss OBJECT RESOURCES 908The system group contains an object resource table. 909A module may create an entry in this table by calling 910.Fn or_register 911with the 912.Fa oid 913to be registered, a textual description in 914.Fa str 915and a pointer to the module 916.Fa mod . 917The registration can be removed with 918.Fn or_unregister . 919All registrations of a module are automatically removed if the module is 920unloaded. 921.Ss TRANSMIT AND RECEIVE BUFFERS 922A buffer is allocated via 923.Fn buf_alloc . 924The argument must be 1 for transmit and 0 for receive buffers. 925The function may return 926.Li NULL 927if there is no memory available. 928The current buffersize can be obtained with 929.Fn buf_size . 930.Sh PROCESSING PDUS 931For modules that need to do their own PDU processing (for example for proxying) 932the following functions are available: 933.Pp 934Function 935.Fn snmp_input_start 936decodes the PDU, searches the community, and sets the global 937.Va this_tick . 938It returns one of the following error codes: 939.Bl -tag -width ".It Er SNMPD_INPUT_VALBADLEN" 940.It Er SNMPD_INPUT_OK 941Everything ok, continue with processing. 942.It Er SNMPD_INPUT_FAILED 943The PDU could not be decoded, has a wrong version or an unknown 944community string. 945.It Er SNMPD_INPUT_VALBADLEN 946A SET PDU had a value field in a binding with a wrong length field in an 947ASN.1 header. 948.It Er SNMPD_INPUT_VALRANGE 949A SET PDU had a value field in a binding with a value that is out of range 950for the given ASN.1 type. 951.It Er SNMPD_INPUT_VALBADENC 952A SET PDU had a value field in a binding with wrong ASN.1 encoding. 953.It Er SNMPD_INPUT_TRUNC 954The buffer appears to contain a valid begin of a PDU, but is too short. 955For streaming transports this means that the caller must save what he 956already has and trying to obtain more input and reissue this input to 957the function. 958For datagram transports this means that part of the 959datagram was lost and the input should be ignored. 960.El 961.Pp 962The function 963.Fn snmp_input_finish 964does the other half of processing: if 965.Fn snmp_input_start 966did not return OK, tries to construct an error response. 967If the start was OK, it calls the correct function from 968.Xr bsnmpagent 3 969to execute the request and depending on the outcome constructs a response or 970error response PDU or ignores the request PDU. 971It returns either 972.Er SNMPD_INPUT_OK 973or 974.Er SNMPD_INPUT_FAILED . 975In the first case a response PDU was constructed and should be sent. 976.Pp 977The function 978.Fn snmp_output 979takes a PDU and encodes it. 980.Pp 981The function 982.Fn snmp_send_port 983takes a PDU, encodes it and sends it through the given port (identified by 984the transport and the index in the port table) to the given address. 985.Pp 986The function 987.Fn snmp_send_trap 988sends a trap to all trap destinations. 989The arguments are the 990.Fa oid 991identifying the trap and a NULL-terminated list of 992.Vt struct snmp_value 993pointers that are to be inserted into the trap binding list. 994.Fn snmp_pdu_auth_access 995verifies whether access to the object IDs contained in the 996.Fa pdu 997 should be granted or denied, according to the configured View-Based Access 998rules. 999.Fa ip 1000contains the index of the first varbinding to which access was denied, or 0 if 1001access to all varbindings in the PDU is granted. 1002.Ss SIMPLE ACTION SUPPORT 1003For simple scalar variables that need no dependencies a number of support 1004functions is available to handle the set, commit, rollback and get. 1005.Pp 1006The following functions are used for OCTET STRING scalars, either NUL terminated 1007or not: 1008.Bl -tag -width "XXXXXXXXX" 1009.It Fn string_save 1010should be called for SNMP_OP_SET. 1011.Fa value 1012and 1013.Fa ctx 1014are the resp\&.\& arguments to the node callback. 1015.Fa valp 1016is a pointer to the pointer that holds the current value and 1017.Fa req_size 1018should be -1 if any size of the string is acceptable or a number larger or 1019equal zero if the string must have a specific size. 1020The function saves 1021the old value in the scratch area (note, that any initial value must have 1022been allocated by 1023.Xr malloc 3 ) , 1024allocates a new string, copies over the new value, NUL-terminates it and 1025sets the new current value. 1026.It Fn string_commit 1027simply frees the saved old value in the scratch area. 1028.It Fn string_rollback 1029frees the new value, and puts back the old one. 1030.It Fn string_get 1031is used for GET or GETNEXT. 1032The function 1033.It Fn string_get_max 1034can be used instead of 1035.Fn string_get 1036to ensure that the returned string has a certain maximum length. 1037If 1038.Fa len 1039is -1, the length is computed via 1040.Xr strlen 3 1041from the current string value. 1042If the current value is NULL, 1043a OCTET STRING of zero length is returned. 1044.It Fn string_free 1045must be called if either rollback or commit fails to free the saved old value. 1046.El 1047.Pp 1048The following functions are used to process scalars of type IP-address: 1049.Bl -tag -width "XXXXXXXXX" 1050.It Fn ip_save 1051Saves the current value in the scratch area and sets the new value from 1052.Fa valp . 1053.It Fn ip_commit 1054Does nothing. 1055.It Fn ip_rollback 1056Restores the old IP address from the scratch area. 1057.It Fn ip_get 1058Retrieves the IP current address. 1059.El 1060.Pp 1061The following functions handle OID-typed variables: 1062.Bl -tag -width "XXXXXXXXX" 1063.It Fn oid_save 1064Saves the current value in the scratch area by allocating a 1065.Vt struct asn_oid 1066with 1067.Xr malloc 3 1068and sets the new value from 1069.Fa oid . 1070.It Fn oid_commit 1071Frees the old value in the scratch area. 1072.It Fn oid_rollback 1073Restores the old OID from the scratch area and frees the old OID. 1074.It Fn oid_get 1075Retrieves the OID 1076.El 1077.Ss TABLE INDEX HANDLING 1078The following functions help in handling table indexes: 1079.Bl -tag -width "XXXXXXXXX" 1080.It Fn index_decode 1081Decodes the index part of the OID. 1082The parameter 1083.Fa oid 1084must be a pointer to the 1085.Va var 1086field of the 1087.Fa value 1088argument of the node callback. 1089The 1090.Fa sub 1091argument must be the index of the start of the index in the OID (this is 1092the 1093.Fa sub 1094argument to the node callback). 1095.Fa code 1096is the index expression (parameter 1097.Fa idx 1098to the node callback). 1099These parameters are followed by parameters depending on the syntax of the index 1100elements as follows: 1101.Bl -tag -width ".It Li OCTET STRING" 1102.It Li INTEGER 1103.Vt int32_t * 1104expected as argument. 1105.It Li COUNTER64 1106.Vt uint64_t * 1107expected as argument. 1108Note, that this syntax is illegal for indexes. 1109.It Li OCTET STRING 1110A 1111.Vt u_char ** 1112and a 1113.Vt size_t * 1114expected as arguments. 1115A buffer is allocated to hold the decoded string. 1116.It Li OID 1117A 1118.Vt struct asn_oid * 1119is expected as argument. 1120.It Li IP ADDRESS 1121A 1122.Vt u_int8_t * 1123expected as argument that points to a buffer of at least four byte. 1124.It Li COUNTER, GAUGE, TIMETICKS 1125A 1126.Vt u_int32_t 1127expected. 1128.It Li NULL 1129No argument expected. 1130.El 1131.It Fn index_compare 1132compares the current variable with an OID. 1133.Fa oid1 1134and 1135.Fa sub 1136come from the node callback arguments 1137.Fa value->var 1138and 1139.Fa sub 1140resp. 1141.Fa oid2 1142is the OID to compare to. 1143The function returns -1, 0, +1 when the 1144variable is lesser, equal, higher to the given OID. 1145.Fa oid2 1146must contain only the index part of the table column. 1147.It Fn index_compare_off 1148is equivalent to 1149.Fn index_compare 1150except that it takes an additional parameter 1151.Fa off 1152that causes it to ignore the first 1153.Fa off 1154components of both indexes. 1155.It Fn index_append 1156appends OID 1157.Fa src 1158beginning at position 1159.Fa sub 1160to 1161.Fa dst . 1162.It Fn index_append_off 1163appends OID 1164.Fa src 1165beginning at position 1166.Fa off 1167to 1168.Fa dst 1169beginning at position 1170.Fa sub 1171+ 1172.Fa off . 1173.El 1174.Sh SEE ALSO 1175.Xr gensnmptree 1 , 1176.Xr bsnmpd 1 , 1177.Xr bsnmpagent 3 , 1178.Xr bsnmpclient 3 , 1179.Xr bsnmplib 3 1180.Sh STANDARDS 1181This implementation conforms to the applicable IETF RFCs and ITU-T 1182recommendations. 1183.Sh AUTHORS 1184.An Hartmut Brandt Aq harti@FreeBSD.org 1185