PageRenderTime 51ms CodeModel.GetById 23ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/bsnmp/lib/bsnmpclient.3

https://bitbucket.org/freebsd/freebsd-head/
Unknown | 703 lines | 687 code | 16 blank | 0 comment | 0 complexity | 2e0c31166da22cb7035f1ea7baff2cc4 MD5 | raw file
  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/lib/bsnmpclient.3,v 1.12 2005/10/04 08:46:50 brandt_h Exp $
 33.\"
 34.Dd September 9, 2010
 35.Dt BSNMPCLIENT 3
 36.Os
 37.Sh NAME
 38.Nm snmp_client ,
 39.Nm snmp_send_cb_f ,
 40.Nm snmp_timeout_cb_f ,
 41.Nm snmp_timeout_start_f ,
 42.Nm snmp_timeout_stop_f ,
 43.Nm snmp_open ,
 44.Nm snmp_close ,
 45.Nm snmp_pdu_create ,
 46.Nm snmp_add_binding ,
 47.Nm snmp_pdu_check ,
 48.Nm snmp_pdu_send ,
 49.Nm snmp_oid_append ,
 50.Nm snmp_parse_server ,
 51.Nm snmp_receive ,
 52.Nm snmp_table_cb_f ,
 53.Nm snmp_table_fetch ,
 54.Nm snmp_table_fetch_async ,
 55.Nm snmp_dialog ,
 56.Nm snmp_discover_engine
 57.Nd "SNMP client library"
 58.Sh LIBRARY
 59Begemot SNMP library
 60.Pq libbsnmp, -lbsnmp
 61.Sh SYNOPSIS
 62.In asn1.h
 63.In snmp.h
 64.In snmpclient.h
 65.Ft typedef void
 66.Fn (*snmp_send_cb_f) "struct snmp_pdu *req" "struct snmp_pdu *resp" "void *uarg"
 67.Ft typedef void
 68.Fn (*snmp_timeout_cb_f) "void *uarg"
 69.Ft typedef void *
 70.Fn (*snmp_timeout_start_f) "struct timeval *timeout" "snmp_timeout_cb_f callback" "void *uarg"
 71.Ft typedef void
 72.Fn (*snmp_timeout_stop_f) "void *timeout_id"
 73.Vt extern struct snmp_client snmp_client ;
 74.Ft void
 75.Fn snmp_client_init "struct snmp_client *client"
 76.Ft int
 77.Fn snmp_client_set_host "struct snmp_client *client" "const char *host"
 78.Ft int
 79.Fn snmp_client_set_port "struct snmp_client *client" "const char *port"
 80.Ft int
 81.Fn snmp_open "const char *host" "const char *port" "const char *read_community" "const char *write_community"
 82.Ft void
 83.Fn snmp_close "void"
 84.Ft void
 85.Fn snmp_pdu_create "struct snmp_pdu *pdu" "u_int op"
 86.Ft int
 87.Fn snmp_add_binding "struct snmp_pdu *pdu" "..."
 88.Ft int
 89.Fn snmp_pdu_check "const struct snmp_pdu *req" "const struct snmp_pdu *resp"
 90.Ft int32_t
 91.Fn snmp_pdu_send "struct snmp_pdu *pdu" "snmp_send_cb_f func" "void *uarg"
 92.Ft int
 93.Fn snmp_oid_append "struct asn_oid *oid" "const char *fmt" "..."
 94.Ft int
 95.Fn snmp_parse_server "struct snmp_client *sc" "const char *str"
 96.Ft int
 97.Fn snmp_receive "int blocking"
 98.Ft typedef void
 99.Fn (*snmp_table_cb_f) "void *list" "void *arg" "int res"
100.Ft int
101.Fn snmp_table_fetch "const struct snmp_table *descr" "void *list"
102.Ft int
103.Fn snmp_table_fetch_async "const struct snmp_table *descr" "void *list" "snmp_table_cb_f callback" "void *uarg"
104.Ft int
105.Fn snmp_dialog "struct snmp_pdu *req" "struct snmp_pdu *resp"
106.Ft int
107.Fn snmp_discover_engine "void"
108.Sh DESCRIPTION
109The SNMP library contains routines to easily build SNMP client applications
110that use SNMP versions 1, 2 or 3.
111Most of the routines use a
112.Vt struct snmp_client :
113.Bd -literal -offset indent
114struct snmp_client {
115	enum snmp_version	version;
116	int			trans;	/* which transport to use */
117
118	/* these two are read-only for the application */
119	char			*cport;	/* port number as string */
120	char			*chost;	/* host name or IP address as string */
121
122	char			read_community[SNMP_COMMUNITY_MAXLEN + 1];
123	char			write_community[SNMP_COMMUNITY_MAXLEN + 1];
124
125	/* SNMPv3 specific fields */
126	int32_t			identifier;
127	int32_t			security_model;
128	struct snmp_engine	engine;
129	struct snmp_user	user;
130
131	/* SNMPv3 Access control - VACM*/
132	uint32_t		clen;
133	uint8_t			cengine[SNMP_ENGINE_ID_SIZ];
134	char			cname[SNMP_CONTEXT_NAME_SIZ];
135
136	struct timeval		timeout;
137	u_int			retries;
138
139	int			dump_pdus;
140
141	size_t			txbuflen;
142	size_t			rxbuflen;
143
144	int			fd;
145
146	int32_t			next_reqid;
147	int32_t			max_reqid;
148	int32_t			min_reqid;
149
150	char			error[SNMP_STRERROR_LEN];
151
152	snmp_timeout_start_f	timeout_start;
153	snmp_timeout_stop_f	timeout_stop;
154
155	char			local_path[sizeof(SNMP_LOCAL_PATH)];
156};
157.Ed
158.Pp
159The fields of this structure are described below.
160.Bl -tag -width "timeout_start"
161.It Va version
162This is the version of SNMP to use.
163See
164.Xr bsnmplib 3
165for applicable values.
166The default version is
167.Li SNMP_V2c .
168.It Va trans
169If this is
170.Dv SNMP_TRANS_LOC_DGRAM
171a local datagram socket is used.
172If it is
173.Dv SNMP_TRANS_LOC_STREAM
174a local stream socket is used.
175For
176.Dv SNMP_TRANS_UDP
177a UDP socket is created.
178It uses the
179.Va chost
180field as the path to the server's socket for local sockets.
181.It Va cport
182The SNMP agent's UDP port number.
183This may be a symbolic port number (from
184.Pa /etc/services )
185or a numeric port number.
186If this field is
187.Li NULL
188(the default) the standard SNMP port is used.
189This field should not be changed directly but rather by calling
190.Fn snmp_client_set_port .
191.It Va chost
192The SNMP agent's host name, IP address or
193.Ux
194domain socket path name.
195If this is
196.Li NULL
197(the default)
198.Li localhost
199is assumed.
200This field should not be changed directly but rather through calling
201.Fn snmp_client_set_host .
202.It Va read_community
203This is the community name to be used for all requests except SET requests.
204The default is
205.Sq public .
206.It Va write_community
207The community name to be used for SET requests.
208The default is
209.Sq private .
210.It Va identifier
211The message indentifier value to be used with SNMPv3 PDUs. Incremented with
212each transmitted PDU.
213.It Va security_model
214The security model to be used with SNMPv3 PDUs. Currently only User-Based
215Security model specified by RFC 3414 (value 3) is supported.
216.It Va engine
217The authorative SNMP engine parameters to be used with SNMPv3 PDUs.
218.It Va user
219The USM SNMP user credentials to be used with SNMPv3 PDUs.
220.It Va clen
221The length of the context engine id to be used with SNMPv3 PDUs.
222.It Va cengine
223The context engine id to be used with SNMPv3 PDUs. Default is empty.
224.It Va cname
225The context name to be used with SNMPv3 PDUs. Default is
226.Sq "" .
227.It Va timeout
228The maximum time to wait for responses to requests.
229If the time elapses, the request is resent up to
230.Va retries
231times.
232The default is 3 seconds.
233.It Va retries
234Number of times a request PDU is to be resent.
235If set to 0, the request is sent only once.
236The default is 3 retransmissions.
237.It Va dump_pdus
238If set to a non-zero value all received and sent PDUs are dumped via
239.Xr snmp_pdu_dump 3 .
240The default is not to dump PDUs.
241.It Va txbuflen
242The encoding buffer size to be allocated for transmitted PDUs.
243The default is 10000 octets.
244.It Va rxbuflen
245The decoding buffer size to be allocated for received PDUs.
246This is the size of the maximum PDU that can be received.
247The default is 10000 octets.
248.It Va fd
249After calling
250.Fn snmp_open
251this is the file socket file descriptor used for sending and receiving PDUs.
252.It Va next_reqid
253The request id of the next PDU to send.
254Used internal by the library.
255.It Va max_reqid
256The maximum request id to use for outgoing PDUs.
257The default is
258.Li INT32_MAX .
259.It Va min_reqid
260The minimum request id to use for outgoing PDUs.
261Request ids are allocated linearily starting at
262.Va min_reqid
263up to
264.Va max_reqid .
265.It Va error
266If an error happens, this field is set to a printable string describing the
267error.
268.It Va timeout_start
269This field must point to a function setting up a one shot timeout.
270After the timeout has elapsed, the given callback function must be called
271with the user argument.
272The
273.Fn timeout_start
274function must return a
275.Vt void *
276identifying the timeout.
277.It Va timeout_stop
278This field must be set to a function that stops a running timeout.
279The function will be called with the return value of the corresponding
280.Fn timeout_start
281function.
282.It Va local_path
283If in local socket mode, the name of the clients socket.
284Not needed by the application.
285.El
286.Pp
287In the current implementation there is a global variable
288.Pp
289.D1 Vt extern struct snmp_client snmp_client ;
290.Pp
291that is used by all the library functions.
292The first call into the library must be a call to
293.Fn snmp_client_init
294to initialize this global variable to the default values.
295After this call and before calling
296.Fn snmp_open
297the fields of the variable may be modified by the user.
298The modification of the
299.Va chost
300and
301.Va cport
302fields should be done only via the functions
303.Fn snmp_client_set_host
304and
305.Fn snmp_client_set_port .
306.Pp
307The function
308.Fn snmp_open
309creates a UDP or
310.Ux
311domain socket and connects it to the agent's IP address and port.
312If any of the arguments of the call is not
313.Li NULL
314the corresponding field in the global
315.Va snmp_client
316is set from the argument.
317Otherwise the values that are already in that variable are used.
318The function
319.Fn snmp_close
320closes the socket, stops all timeouts and frees all dynamically allocated
321resources.
322.Pp
323The next three functions are used to create request PDUs.
324The function
325.Fn snmp_pdu_create
326initializes a PDU of type
327.Va op .
328It does not allocate space for the PDU itself.
329This is the responsibility of the caller.
330.Fn snmp_add_binding
331adds bindings to the PDU and returns the (zero based) index of the first new
332binding.
333The arguments are pairs of pointer to the OIDs and syntax constants,
334terminated by a NULL.
335The call
336.Bd -literal -offset indent
337snmp_add_binding(&pdu,
338    &oid1, SNMP_SYNTAX_INTEGER,
339    &oid2, SNMP_SYNTAX_OCTETSTRING,
340    NULL);
341.Ed
342.Pp
343adds two new bindings to the PDU and returns the index of the first one.
344It is the responsibility of the caller to set the value part of the binding
345if necessary.
346The functions returns -1 if the maximum number of bindings is exhausted.
347The function
348.Fn snmp_oid_append
349can be used to construct variable OIDs for requests.
350It takes a pointer to an
351.Vt struct asn_oid
352that is to be constructed, a format string, and a number of arguments
353the type of which depends on the format string.
354The format string is interpreted
355character by character in the following way:
356.Bl -tag -width ".It Li ( Va N Ns Li )"
357.It Li i
358This format expects an argument of type
359.Vt asn_subid_t
360and appends this as a single integer to the OID.
361.It Li a
362This format expects an argument of type
363.Vt struct in_addr
364and appends to four parts of the IP address to the OID.
365.It Li s
366This format expects an argument of type
367.Vt const char *
368and appends the length of the string (as computed by
369.Xr strlen 3 )
370and each of the characters in the string to the OID.
371.It ( Va N Ns )
372This format expects no argument.
373.Va N
374must be a decimal number and is stored into an internal variable
375.Va size .
376.It Li b
377This format expects an argument of type
378.Vt const char *
379and appends
380.Va size
381characters from the string to the OID.
382The string may contain
383.Li NUL
384characters.
385.It Li c
386This format expects two arguments: one of type
387.Vt size_t
388and one of type
389.Vt const u_char * .
390The first argument gives the number of bytes to append to the OID from the string
391pointed to by the second argument.
392.El
393.Pp
394The function
395.Fn snmp_pdu_check
396may be used to check a response PDU.
397A number of checks are performed
398(error code, equal number of bindings, syntaxes and values for SET PDUs).
399The function returns +1 if everything is ok, 0 if a NOSUCHNAME or similar
400error was detected, -1 if the response PDU had fatal errors
401and -2 if
402.Fa resp
403is
404.Li NULL
405(a timeout occurred).
406.Pp
407The function
408.Fn snmp_pdu_send
409encodes and sends the given PDU.
410It records the PDU together with the callback
411and user pointers in an internal list and arranges for retransmission if no
412response is received.
413When a response is received or the retransmission count
414is exceeded the callback
415.Fa func
416is called with the orignal request PDU, the response PDU and the user argument
417.Fa uarg .
418If the retransmit count is exceeded,
419.Fa func
420is called with the original request PDU, the response pointer set to
421.Li NULL
422and the user argument
423.Fa uarg .
424The caller should not free the request PDU until the callback function is
425called.
426The callback function must free the request PDU and the response PDU (if not
427.Li NULL ).
428.Pp
429The function
430.Fn snmp_receive
431tries to receive a PDU.
432If the argument is zero, the function polls to see
433whether a packet is available, if the argument is non-zero, the function blocks
434until the next packet is received.
435The packet is delivered via the usual callback
436mechanism (non-response packets are silently dropped).
437The function returns 0, if a packet was received and successfully dispatched,
438-1 if an error occurred or no packet was available (in polling mode).
439.Pp
440The next two functions are used to retrieve tables from SNMP agents.
441They use
442the following input structure, that describes the table:
443.Bd -literal -offset indent
444struct snmp_table {
445	struct asn_oid		table;
446	struct asn_oid		last_change;
447	u_int			max_iter;
448	size_t			entry_size;
449	u_int			index_size;
450	uint64_t		req_mask;
451
452	struct snmp_table_entry {
453	    asn_subid_t		subid;
454	    enum snmp_syntax	syntax;
455	    off_t		offset;
456	}			entries[];
457};
458.Ed
459.Pp
460The fields of this structure have the following meaning:
461.Bl -tag -width "last_change"
462.It Va table
463This is the base OID of the table.
464.It Va last_change
465Some tables have a scalar variable of type TIMETICKS attached to them,
466that holds the time when the table was last changed.
467This OID should be the OID of this variable (without the \&.0 index).
468When the table is retrieved
469with multiple GET requests, and the variable changes between two request,
470the table fetch is restarted.
471.It Va max_iter
472Maximum number of tries to fetch the table.
473.It Va entry_size
474The table fetching routines return a list of structures one for each table
475row.
476This variable is the size of one structure and used to
477.Xr malloc 3
478the structure.
479.It Va index_size
480This is the number of index columns in the table.
481.It Va req_mask
482This is a bit mask with a 1 for each table column that is required.
483Bit 0 corresponds to the first element (index 0) in the array
484.Va entries ,
485bit 1 to the second (index 1) and so on.
486SNMP tables may be sparse.
487For sparse columns the bit should not be set.
488If the bit for a given column is set and
489the column value cannot be retrieved for a given row, the table fetch is
490restarted assuming that the table is currently being modified by the agent.
491The bits for the index columns are ignored.
492.It Va entries
493This is a variable sized array of column descriptors.
494This array is terminated by an element with syntax
495.Li SNMP_SYNTAX_NULL .
496The first
497.Va index_size
498elements describe all the index columns of the table, the rest are normal
499columns.
500If for the column at
501.Ql entries[N]
502the expression
503.Ql req_mask & (1 << N)
504yields true, the column is considered a required column.
505The fields of this the array elements have the following meaning:
506.Bl -tag -width "syntax"
507.It Va subid
508This is the OID subid of the column.
509This is ignored for index entries.
510Index entries are decoded according to the
511.Va syntax
512field.
513.It Va syntax
514This is the syntax of the column or index.
515A syntax of
516.Li SNMP_SYNTAX_NULL
517terminates the array.
518.It Va offset
519This is the starting offset of the value of the column in the return structures.
520This field can be set with the ISO-C
521.Fn offsetof
522macro.
523.El
524.El
525.Pp
526Both table fetching functions return TAILQ (see
527.Xr queue 3 )
528of structures--one for each table row.
529These structures must start with a
530.Fn TAILQ_ENTRY
531and a
532.Vt uint64_t
533and are allocated via
534.Xr malloc 3 .
535The
536.Fa list
537argument of the table functions must point to a
538.Fn TAILQ_HEAD .
539The
540.Vt uint64_t
541fields, usually called
542.Va found
543is used to indicate which of the columns have been found for the given
544row.
545It is encoded like the
546.Fa req_mask
547field.
548.Pp
549The function
550.Fn snmp_table_fetch
551synchronously fetches the given table.
552If everything is ok 0 is returned.
553Otherwise the function returns -1 and sets an appropriate error string.
554The function
555.Fn snmp_table_fetch_async
556fetches the tables asynchronously.
557If either the entire table is fetch, or
558an error occurs the callback function
559.Fa callback
560is called with the callers arguments
561.Fa list
562and
563.Fa uarg
564and a parameter that is either 0 if the table was fetched, or
565-1 if there was an error.
566The function itself returns -1 if it could not
567initialize fetching of the table.
568.Pp
569The following table description is used to fetch the ATM interface table:
570.Bd -literal -offset indent
571/*
572 * ATM interface table
573 */
574struct atmif {
575	TAILQ_ENTRY(atmif) link;
576	uint64_t	found;
577	int32_t		index;
578	u_char		*ifname;
579	size_t		ifnamelen;
580	uint32_t	node_id;
581	uint32_t	pcr;
582	int32_t		media;
583	uint32_t	vpi_bits;
584	uint32_t	vci_bits;
585	uint32_t	max_vpcs;
586	uint32_t	max_vccs;
587	u_char		*esi;
588	size_t		esilen;
589	int32_t		carrier;
590};
591TAILQ_HEAD(atmif_list, atmif);
592
593/* list of all ATM interfaces */
594struct atmif_list atmif_list;
595
596static const struct snmp_table atmif_table = {
597	OIDX_begemotAtmIfTable,
598	OIDX_begemotAtmIfTableLastChange, 2,
599	sizeof(struct atmif),
600	1, 0x7ffULL,
601	{
602	  { 0, SNMP_SYNTAX_INTEGER,
603		offsetof(struct atmif, index) },
604	  { 1, SNMP_SYNTAX_OCTETSTRING,
605		offsetof(struct atmif, ifname) },
606	  { 2, SNMP_SYNTAX_GAUGE,
607		offsetof(struct atmif, node_id) },
608	  { 3, SNMP_SYNTAX_GAUGE,
609		offsetof(struct atmif, pcr) },
610	  { 4, SNMP_SYNTAX_INTEGER,
611		offsetof(struct atmif, media) },
612	  { 5, SNMP_SYNTAX_GAUGE,
613		offsetof(struct atmif, vpi_bits) },
614	  { 6, SNMP_SYNTAX_GAUGE,
615		offsetof(struct atmif, vci_bits) },
616	  { 7, SNMP_SYNTAX_GAUGE,
617		offsetof(struct atmif, max_vpcs) },
618	  { 8, SNMP_SYNTAX_GAUGE,
619		offsetof(struct atmif, max_vccs) },
620	  { 9, SNMP_SYNTAX_OCTETSTRING,
621		offsetof(struct atmif, esi) },
622	  { 10, SNMP_SYNTAX_INTEGER,
623		offsetof(struct atmif, carrier) },
624          { 0, SNMP_SYNTAX_NULL, 0 }
625	}
626};
627
628\&...
629	if (snmp_table_fetch(&atmif_table, &atmif_list) != 0)
630		errx(1, "AtmIf table: %s", snmp_client.error);
631\&...
632.Ed
633.Pp
634The function
635.Fn snmp_dialog
636is used to execute a synchonuous dialog with the agent.
637The request PDU
638.Fa req
639is sent and the function blocks until the response PDU is received.
640Note,
641that asynchonuous receives are handled (i.e. callback functions of other send
642calls or table fetches may be called while in the function).
643The response PDU is returned in
644.Fa resp .
645If no response could be received after all timeouts and retries, the function
646returns -1.
647If a response was received 0 is returned.
648.Pp
649The function
650.Fn snmp_discover_engine
651is used to discover the authorative snmpEngineId of a remote SNMPv3 agent.
652A request PDU with empty USM user name is sent and the client's engine
653parameters are set according to the snmpEngine parameters received in the
654response PDU.
655If the client is configured to use authentication and/or privacy and the
656snmpEngineBoots and/or snmpEngineTime in the response had zero values, an
657additional request (possibly encrypted) with the appropriate user credentials
658is sent to fetch the missing values.
659Note, that the function blocks until the discovery proccess is completed.
660If no response could be received after all timeouts and retries, or the
661response contained errors the function returns -1.
662If the discovery proccess was completed 0 is returned.
663.Pp
664The function
665.Fn snmp_parse_server
666is used to parse an SNMP server specification string and fill in the
667fields of a
668.Vt struct snmp_client .
669The syntax of a server specification is
670.Pp
671.D1 [trans::][community@][server][:port]
672.Pp
673where
674.Va trans
675is the transport name (one of udp, stream or dgram),
676.Va community
677is the string to be used for both the read and the write community,
678.Va server
679is the server's host name in case of UDP and the path name in case
680of a local socket, and
681.Va port
682is the port in case of UDP transport.
683The function returns 0 in the case of success and return -1 and sets
684the error string in case of an error.
685.Sh DIAGNOSTICS
686If an error occurs in any of the function an error indication as described
687above is returned.
688Additionally the function sets a printable error string
689in the
690.Va error
691filed of
692.Va snmp_client .
693.Sh SEE ALSO
694.Xr gensnmptree 1 ,
695.Xr bsnmpd 1 ,
696.Xr bsnmpagent 3 ,
697.Xr bsnmplib 3
698.Sh STANDARDS
699This implementation conforms to the applicable IETF RFCs and ITU-T
700recommendations.
701.Sh AUTHORS
702.An Hartmut Brandt Aq harti@FreeBSD.org
703.An Kendy Kutzner Aq kutzner@fokus.gmd.de