Skip to content
Snippets Groups Projects
Commit 0be22a17 authored by Quanah Gibson-Mount's avatar Quanah Gibson-Mount
Browse files

significant update

parent 7d7f0e1d
No related branches found
No related tags found
No related merge requests found
......@@ -29,15 +29,142 @@ The actual type is determined based on the value of the
argument.
Global options are set/retrieved by passing a NULL LDAP handle.
.TP
.B LDAP_OPT_API_FEATURE_INFO
Fills-in a
.BR "LDAPAPIFeatureInfo" ;
.BR outvalue
must be a
.BR "LDAPAPIFeatureInfo *" ,
pointing to an already allocated struct.
This is a read-only option.
.TP
.B LDAP_OPT_API_INFO
Fills-in a
.BR "struct ldapapiinfo" ;
.BR "LDAPAPIInfo" ;
.BR outvalue
must be a
.BR "struct ldapapiinfo *" ,
.BR "LDAPAPIInfo *" ,
pointing to an already allocated struct.
This is a read-only option.
.TP
.B LDAP_OPT_CLIENT_CONTROLS
Sets/gets the client-side controls to be used for all operations.
This is now deprecated as modern LDAP C API provides replacements
for all main operations which accepts client-side controls as
explicit arguments; see for example
.BR ldap_search_ext (3),
.BR ldap_add_ext (3),
.BR ldap_modify_ext (3)
and so on.
.BR outvalue
must be
.BR "LDAPControl ***" ,
and the caller is responsible of freeing the returned controls, if any,
by calling
.BR ldap_controls_free (3),
while
.BR invalue
must be
.BR "LDAPControl *const *" ;
the library duplicates the controls passed via
.BR invalue .
.TP
.B LDAP_OPT_CONNECT_ASYNC
Sets/gets the status of the asynchronous connect flag.
.BR invalue
should either be
.BR LDAP_OPT_OFF
or
.BR LDAP_OPT_ON ;
.BR outvalue
must be
.BR "int *" .
When set, the library will call
.BR connect (2)
and return, without waiting for response.
This leaves the handle in a connecting state.
Subsequent calls to library routines will poll for completion
of the connect before performing further operations.
As a consequence, library calls that need to establish a connection
with a DSA do not block even for the network timeout
(option
.BR LDAP_OPT_NETWORK_TIMEOUT ).
This option is OpenLDAP specific.
.TP
.B LDAP_OPT_CONNECT_CB
This option allows to set a connect callback.
.B invalue
must be a
.BR "const struct ldap_conncb *" .
Callbacks are executed in last in-first served order.
Handle-specific callbacks are executed first, followed by global ones.
Right before freeing the callback structure, the
.B lc_del
callback handler is passed a
.B NULL
.BR Sockbuf .
Calling
.BR ldap_get_option (3)
for this option removes the callback whose pointer matches
.BR outvalue .
This option is OpenLDAP specific.
.TP
.B LDAP_OPT_DEBUG_LEVEL
Sets/gets the debug level of the client library.
.BR invalue
must be a
.BR "const int *" ;
.BR outvalue
must be a
.BR "int *" .
Valid debug levels are
.BR LDAP_DEBUG_ANY ,
.BR LDAP_DEBUG_ARGS ,
.BR LDAP_DEBUG_BER ,
.BR LDAP_DEBUG_CONNS ,
.BR LDAP_DEBUG_NONE ,
.BR LDAP_DEBUG_PACKETS ,
.BR LDAP_DEBUG_PARSE ,
and
.BR LDAP_DEBUG_TRACE .
This option is OpenLDAP specific.
.TP
.B LDAP_OPT_DEFBASE
Sets/gets a string containing the DN to be used as default base
for search operations.
.BR outvalue
must be a
.BR "char **" ,
and the caller is responsible of freeing the returned string by calling
.BR ldap_memfree (3),
while
.BR invalue
must be a
.BR "const char *" ;
the library duplicates the corresponding string.
This option is OpenLDAP specific.
.TP
.B LDAP_OPT_DEREF
Sets/gets the value that defines when alias dereferencing must occur.
.BR invalue
must be
.BR "const int *" ;
.BR outvalue
must be
.BR "int *" .
They cannot be NULL.
The value of
.BR *invalue
should be one of
.BR LDAP_DEREF_NEVER
(the default),
.BR LDAP_DEREF_SEARCHING ,
.BR LDAP_DEREF_FINDING ,
or
.BR LDAP_DEREF_ALWAYS .
Note that this has ever been the only means to determine alias dereferencing
within search operations.
.TP
.B LDAP_OPT_DESC
Returns the file descriptor associated to the socket buffer
of the LDAP handle passed in as
......@@ -45,29 +172,51 @@ of the LDAP handle passed in as
.BR outvalue
must be a
.BR "int *" .
This is a read-only, handler-specific option.
This is a read-only, handle-specific option.
.TP
.B LDAP_OPT_SOCKBUF
Returns a pointer to the socket buffer of the LDAP handle passed in as
.BR ld ;
.B LDAP_OPT_DIAGNOSTIC_MESSAGE
Sets/gets a string containing the error string associated to the LDAP handle.
This option was formerly known as
.BR LDAP_OPT_ERROR_STRING .
.BR outvalue
must be a
.BR "char **" ,
and the caller is responsible of freeing the returned string by calling
.BR ldap_memfree (3),
while
.BR invalue
must be a
.BR "Sockbuf **" .
This is a read-only, handler-specific option.
.BR "char *" ;
the library duplicates the corresponding string.
.TP
.B LDAP_OPT_TIMEOUT
Sets/gets a timeout value for the synchronous API calls.
.B outvalue
.B LDAP_OPT_HOST_NAME
Sets/gets a space-separated list of hosts to be contacted by the library
when trying to establish a connection.
This is now deprecated in favor of
.BR LDAP_OPT_URI .
.BR outvalue
must be a
.BR "struct timeval **"
(the caller has to free
.BR *outvalue ) ,
and
.B invalue
.BR "char **" ,
and the caller is responsible of freeing the resulting string by calling
.BR ldap_memfree (3),
while
.BR invalue
must be a
.BR "struct timeval *" ,
and they cannot be NULL. Using a struct with seconds set to \-1 results
in an infinite timeout, which is the default.
.BR "const char *" ;
the library duplicates the corresponding string.
.TP
.B LDAP_OPT_MATCHED_DN
Sets/gets a string containing the matched DN associated to the LDAP handle.
.BR outvalue
must be a
.BR "char **" ,
and the caller is responsible of freeing the returned string by calling
.BR ldap_memfree (3),
while
.BR invalue
must be a
.BR "const char *" ;
the library duplicates the corresponding string.
.TP
.B LDAP_OPT_NETWORK_TIMEOUT
Sets/gets the network timeout value after which
......@@ -83,69 +232,72 @@ must be a
and
.B invalue
must be a
.BR "struct timeval *" ,
and they cannot be NULL. Using a struct with seconds set to \-1 results
.BR "const struct timeval *" .
They cannot be NULL. Using a struct with seconds set to \-1 results
in an infinite timeout, which is the default.
This option is OpenLDAP specific.
.TP
.B LDAP_OPT_DEREF
Sets/gets the value that defines when alias dereferencing must occur.
.BR outvalue
and
.BR invalue
must be
.BR "int *" ,
and they cannot be NULL.
.TP
.B LDAP_OPT_SIZELIMIT
Sets/gets the value that defines the maximum number of entries
to be returned by a search operation.
.BR outvalue
and
.B LDAP_OPT_PROTOCOL_VERSION
Sets/gets the protocol version.
.BR outvalue
and
.BR invalue
must be
.BR "int *" ,
and they cannot be NULL.
must be
.BR "int *" .
.TP
.B LDAP_OPT_TIMELIMIT
Sets/gets the value that defines the time limit after which
a search operation should be terminated by the server.
.BR outvalue
and
.B LDAP_OPT_REFERRAL_URLS
Sets/gets an array containing the referral URIs associated to the LDAP handle.
.BR outvalue
must be a
.BR "char ***" ,
and the caller is responsible of freeing the returned string by calling
.BR ldap_memvfree (3),
while
.BR invalue
must be
.BR "int *" ,
and they cannot be NULL.
must be a NULL-terminated
.BR "char *const *" ;
the library duplicates the corresponding string.
This option is OpenLDAP specific.
.TP
.B LDAP_OPT_REFERRALS
Determines whether the library should implicitly chase referrals or not.
.BR outvalue
and
.BR invalue
must be
.BR "int *" ;
their value should either be
.BR "const int *" ;
its value should either be
.BR LDAP_OPT_OFF
or
.BR LDAP_OPT_ON .
.BR outvalue
must be
.BR "int *" .
.\".TP
.\".B LDAP_OPT_REFHOPLIMIT
.\"This option is OpenLDAP specific.
.\"It is not currently implemented.
.TP
.B LDAP_OPT_RESTART
Determines whether the library should implicitly restart connections (FIXME).
.BR outvalue
and
.BR invalue
must be
.BR "int *" ;
their value should either be
.BR "const int *" ;
its value should either be
.BR LDAP_OPT_OFF
or
.BR LDAP_OPT_ON .
.TP
.B LDAP_OPT_PROTOCOL_VERSION
Sets/gets the protocol version.
.BR outvalue
and
must be
.BR "int *" .
.TP
.B LDAP_OPT_RESULT_CODE
Sets/gets the LDAP result code associated to the handle.
This option was formerly known as
.BR LDAP_OPT_ERROR_NUMBER .
.BR invalue
must be
must be a
.BR "const int *" .
.BR outvalue
must be a
.BR "int *" .
.TP
.B LDAP_OPT_SERVER_CONTROLS
......@@ -166,50 +318,60 @@ by calling
while
.BR invalue
must be
.BR "LDAPControl **" ;
.BR "LDAPControl *const *" ;
the library duplicates the controls passed via
.BR invalue .
.TP
.B LDAP_OPT_CLIENT_CONTROLS
Sets/gets the client-side controls to be used for all operations.
This is now deprecated as modern LDAP C API provides replacements
for all main operations which accepts client-side controls as
explicit arguments; see for example
.BR ldap_search_ext (3),
.BR ldap_add_ext (3),
.BR ldap_modify_ext (3)
and so on.
.BR outvalue
must be
.BR "LDAPControl ***" ,
and the caller is responsible of freeing the returned controls, if any,
by calling
.BR ldap_controls_free (3),
while
.B LDAP_OPT_SIZELIMIT
Sets/gets the value that defines the maximum number of entries
to be returned by a search operation.
.BR invalue
must be
.BR "LDAPControl **" ;
the library duplicates the controls passed via
.BR invalue .
must be
.BR "const int *" ,
while
.BR outvalue
must be
.BR "int *" ;
They cannot be NULL.
.TP
.B LDAP_OPT_HOST_NAME
Sets/gets a space-separated list of hosts to be contacted by the library
when trying to establish a connection.
This is now deprecated in favor of
.BR LDAP_OPT_URI .
.B LDAP_OPT_SOCKBUF
Returns a pointer to the socket buffer of the LDAP handle passed in as
.BR ld ;
.BR outvalue
must be a
.BR "char **" ,
and the caller is responsible of freeing the resulting string by calling
.BR ldap_memfree (3),
while
.BR "Sockbuf **" .
This is a read-only, handle-specific option.
This option is OpenLDAP specific.
.TP
.B LDAP_OPT_TIMELIMIT
Sets/gets the value that defines the time limit after which
a search operation should be terminated by the server.
.BR invalue
must be
.BR "const int *" ,
while
.BR outvalue
must be
.BR "int *" ,
and they cannot be NULL.
.TP
.B LDAP_OPT_TIMEOUT
Sets/gets a timeout value for the synchronous API calls.
.B outvalue
must be a
.BR "char *" ;
the library duplicates the corresponding string.
.BR "struct timeval **"
(the caller has to free
.BR *outvalue ) ,
and
.B invalue
must be a
.BR "struct timeval *" ,
and they cannot be NULL. Using a struct with seconds set to \-1 results
in an infinite timeout, which is the default.
This option is OpenLDAP specific.
.TP
.B LDAP_OPT_URI
Sets/gets a space-separated list of URIs to be contacted by the library
Sets/gets a comma- or space-separated list of URIs to be contacted by the library
when trying to establish a connection.
.BR outvalue
must be a
......@@ -219,96 +381,366 @@ and the caller is responsible of freeing the resulting string by calling
while
.BR invalue
must be a
.BR "char *" ;
.BR "const char *" ;
the library parses the string into a list of
.BR LDAPURLDesc
structures, so the invocation of
.BR ldap_set_option (3)
may fail if URL parsing fails.
URIs may only contain the
.BR schema ,
the
.BR host ,
and the
.BR port
fields.
This option is OpenLDAP specific.
.SH SASL OPTIONS
The SASL options are OpenLDAP specific.
.TP
.B LDAP_OPT_DEFBASE
Sets/gets a string containing the DN to be used as default base
for search operations.
.B LDAP_OPT_X_SASL_AUTHCID
Gets the SASL authentication identity;
.BR outvalue
must be a
.BR "char **" ,
and the caller is responsible of freeing the returned string by calling
.BR ldap_memfree (3),
while
its content needs to be freed by the caller using
.BR ldap_memfree (3).
.TP
.B LDAP_OPT_X_SASL_AUTHZID
Gets the SASL authorization identity;
.BR outvalue
must be a
.BR "char **" ,
its content needs to be freed by the caller using
.BR ldap_memfree (3).
.TP
.B LDAP_OPT_X_SASL_MAXBUFSIZE
Gets/sets SASL maximum buffer size;
.BR invalue
must be a
.BR "char *" ;
the library duplicates the corresponding string.
must be
.BR "const ber_len_t *" ,
while
.BR outvalue
must be
.BR "ber_len_t *" .
See also
.BR LDAP_OPT_X_SASL_SECPROPS .
.TP
.B LDAP_OPT_RESULT_CODE
Sets/gets the LDAP result code associated to the handle.
This option was formerly known as
.BR LDAP_OPT_ERROR_NUMBER .
Both
.B LDAP_OPT_X_SASL_MECH
Gets the SASL mechanism;
.BR outvalue
and
must be a
.BR "char **" ,
its content needs to be freed by the caller using
.BR ldap_memfree (3).
.TP
.B LDAP_OPT_X_SASL_MECHLIST
Gets the list of the available mechanisms,
in form of a NULL-terminated array of strings;
.BR outvalue
must be
.BR "char ***" .
The caller must not free or otherwise muck with it.
.TP
.B LDAP_OPT_X_SASL_NOCANON
Sets/gets the NOCANON flag.
When unset, the hostname is canonicalized.
.BR invalue
must be a
must be
.BR "const int *" ;
its value should either be
.BR LDAP_OPT_OFF
or
.BR LDAP_OPT_ON .
.BR outvalue
must be
.BR "int *" .
.TP
.B LDAP_OPT_DIAGNOSTIC_MESSAGE
Sets/gets a string containing the error string associated to the LDAP handle.
This option was formerly known as
.BR LDAP_OPT_ERROR_STRING .
.B LDAP_OPT_X_SASL_REALM
Gets the SASL realm;
.BR outvalue
must be a
.BR "char **" ,
and the caller is responsible of freeing the returned string by calling
.BR ldap_memfree (3),
while
its content needs to be freed by the caller using
.BR ldap_memfree (3).
.TP
.B LDAP_OPT_X_SASL_SECPROPS
Sets the SASL secprops;
.BR invalue
must be a
.BR "char *" ;
the library duplicates the corresponding string.
must be a
.BR "char *" ,
containing a comma-separated list of properties.
Legal values are:
.BR none ,
.BR nodict ,
.BR noplain ,
.BR noactive ,
.BR passcred ,
.BR forwardsec ,
.BR noanonymous ,
.BR minssf=<minssf> ,
.BR maxssf=<maxssf> ,
.BR maxbufsize=<maxbufsize> .
.TP
.B LDAP_OPT_MATCHED_DN
Sets/gets a string containing the matched DN associated to the LDAP handle.
.B LDAP_OPT_X_SASL_SSF
Gets the SASL SSF;
.BR outvalue
must be a
.BR "char **" ,
and the caller is responsible of freeing the returned string by calling
.BR ldap_memfree (3),
.BR "ber_len_t *" .
.TP
.B LDAP_OPT_X_SASL_SSF_EXTERNAL
Sets the SASL SSF value related to an authentication
performed using an EXTERNAL mechanism;
.BR invalue
must be a
.BR "const ber_len_t *" .
.TP
.B LDAP_OPT_X_SASL_SSF_MAX
Gets/sets SASL maximum SSF;
.BR invalue
must be
.BR "const ber_len_t *" ,
while
.BR outvalue
must be
.BR "ber_len_t *" .
See also
.BR LDAP_OPT_X_SASL_SECPROPS .
.TP
.B LDAP_OPT_X_SASL_SSF_MIN
Gets/sets SASL minimum SSF;
.BR invalue
must be a
.BR "char *" ;
the library duplicates the corresponding string.
must be
.BR "const ber_len_t *" ,
while
.BR outvalue
must be
.BR "ber_len_t *" .
See also
.BR LDAP_OPT_X_SASL_SECPROPS .
.TP
.B LDAP_OPT_REFERRAL_URLS
Sets/gets an array containing the referral URIs associated to the LDAP handle.
.B LDAP_OPT_X_SASL_USERNAME
Gets the SASL username;
.BR outvalue
must be a
.BR "char ***" ,
and the caller is responsible of freeing the returned string by calling
.BR ber_memvfree (3),
while
.BR "char **" .
Its content needs to be freed by the caller using
.BR ldap_memfree (3).
.SH TCP OPTIONS
The TCP options are OpenLDAP specific.
Mainly intended for use with Linux, they may not be portable.
.TP
.B LDAP_OPT_X_KEEPALIVE_IDLE
Sets/gets the number of seconds a connection needs to remain idle
before TCP starts sending keepalive probes.
.BR invalue
must be a NULL-terminated
.BR "char **" ;
the library duplicates the corresponding string.
must be
.BR "const int *" ;
.BR outvalue
must be
.BR "int *" .
.TP
.B LDAP_OPT_API_FEATURE_INFO
Fills-in a
.BR "LDAPAPIFeatureInfo" ;
.BR outvalue
must be a
.BR "LDAPAPIFeatureInfo *" ,
pointing to an already allocated struct.
This is a read-only option.
.B LDAP_OPT_X_KEEPALIVE_PROBES
Sets/gets the maximum number of keepalive probes TCP should send
before dropping the connection.
.BR invalue
must be
.BR "const int *" ;
.BR outvalue
must be
.BR "int *" .
.TP
.B LDAP_OPT_DEBUG_LEVEL
Sets/gets the debug level of the client library.
Both
.B LDAP_OPT_X_KEEPALIVE_INTERVAL
Sets/gets the interval in seconds between individual keepalive probes.
.BR invalue
must be
.BR "const int *" ;
.BR outvalue
and
must be
.BR "int *" .
.SH TLS OPTIONS
The TLS options are OpenLDAP specific.
.\".TP
.\".B LDAP_OPT_X_TLS
.\"Sets/gets the TLS mode.
.TP
.B LDAP_OPT_X_TLS_CACERTDIR
Sets/gets the path of the directory containing CA certificates.
.BR invalue
must be a
must be
.BR "const char *" ;
.BR outvalue
must be
.BR "char **" ,
and its contents need to be freed by the caller using
.BR ldap_memfree (3).
.TP
.B LDAP_OPT_X_TLS_CACERTFILE
Sets/gets the full-path of the CA certificate file.
.BR invalue
must be
.BR "const char *" ;
.BR outvalue
must be
.BR "char **" ,
and its contents need to be freed by the caller using
.BR ldap_memfree (3).
.TP
.B LDAP_OPT_X_TLS_CERTFILE
Sets/gets the full-path of the certificate file.
.BR invalue
must be
.BR "const char *" ;
.BR outvalue
must be
.BR "char **" ,
and its contents need to be freed by the caller using
.BR ldap_memfree (3).
.TP
.B LDAP_OPT_X_TLS_CIPHER_SUITE
Sets/gets the allowed cipher suite.
.BR invalue
must be
.BR "const char *" ;
.BR outvalue
must be
.BR "char **" ,
and its contents need to be freed by the caller using
.BR ldap_memfree (3).
.TP
.B LDAP_OPT_X_TLS_CONNECT_ARG
Sets/gets the connection callback argument.
.BR invalue
must be
.BR "const void *" ;
.BR outvalue
must be
.BR "void **" .
.TP
.B LDAP_OPT_X_TLS_CONNECT_CB
Sets/gets the connection callback handle.
.BR invalue
must be
.BR "const LDAP_TLS_CONNECT_CB *" ;
.BR outvalue
must be
.BR "LDAP_TLS_CONNECT_CB **" .
.TP
.B LDAP_OPT_X_TLS_CRLCHECK
Sets/gets the CRL evaluation strategy, one of
.BR LDAP_OPT_X_TLS_CRL_NONE ,
.BR LDAP_OPT_X_TLS_CRL_PEER ,
or
.BR LDAP_OPT_X_TLS_CRL_ALL .
.BR invalue
must be
.BR "const int *" ;
.BR outvalue
must be
.BR "int *" .
Requires OpenSSL.
.TP
.B LDAP_OPT_X_TLS_CRLFILE
Sets/gets the full-path of the CRL file.
.BR invalue
must be
.BR "const char *" ;
.BR outvalue
must be
.BR "char **" ,
and its contents need to be freed by the caller using
.BR ldap_memfree (3).
This option is only valid for GnuTLS.
.TP
.B LDAP_OPT_X_TLS_CTX
Sets/gets the TLS library context. New TLS sessions will inherit their
default settings from this library context.
.BR invalue
must be
.BR "const void *" ;
.BR outvalue
must be
.BR "void **" .
When using the OpenSSL library this is an SSL_CTX*. When using other
crypto libraries this is a pointer to an OpenLDAP private structure.
Applications generally should not use this option or attempt to
manipulate this structure.
.TP
.B LDAP_OPT_X_TLS_DHFILE
Gets/sets the full-path of the file containing the parameters
for Diffie-Hellman ephemeral key exchange.
.BR invalue
must be
.BR "const char *" ;
.BR outvalue
must be
.BR "char **" ,
and its contents need to be freed by the caller using
.BR ldap_memfree (3).
Ignored by GnuTLS.
.TP
.B LDAP_OPT_X_TLS_KEYFILE
Sets/gets the full-path of the certificate key file.
.BR invalue
must be
.BR "const char *" ;
.BR outvalue
must be
.BR "char **" ,
and its contents need to be freed by the caller using
.BR ldap_memfree (3).
.TP
.B LDAP_OPT_X_TLS_NEWCTX
Instructs the library to create a new TLS library context.
.BR invalue
must be
.BR "const int *" .
A non-zero value pointed to by
.BR invalue
tells the library to create a context for a server.
.TP
.B LDAP_OPT_X_TLS_PROTOCOL_MIN
Sets/gets the minimum protocol version.
.BR invalue
must be
.BR "const int *" ;
.BR outvalue
must be
.BR "int *" .
.TP
.B LDAP_OPT_X_TLS_RANDOM_FILE
Sets/gets the random file when
.B /dev/random
and
.B /dev/urandom
are not available.
.BR invalue
must be
.BR "const char *" ;
.BR outvalue
must be
.BR "char **" ,
and its contents need to be freed by the caller using
.BR ldap_memfree (3).
Ignored by GnuTLS older than version 2.2.
.TP
.B LDAP_OPT_X_TLS_REQUIRE_CERT
Sets/gets the peer certificate checking strategy,
one of
.BR LDAP_OPT_X_TLS_NEVER ,
.BR LDAP_OPT_X_TLS_HARD ,
.BR LDAP_OPT_X_TLS_DEMAND ,
.BR LDAP_OPT_X_TLS_ALLOW ,
.BR LDAP_OPT_X_TLS_TRY .
.TP
.B LDAP_OPT_X_TLS_SSL_CTX
Gets the TLS session context associated with this handle.
.BR outvalue
must be
.BR "void **" .
When using the OpenSSL library this is an SSL*. When using other
crypto libraries this is a pointer to an OpenLDAP private structure.
Applications generally should not use this option.
.SH ERRORS
On success, the functions return
.BR LDAP_OPT_SUCCESS ,
......@@ -328,6 +760,16 @@ Application developers are encouraged to either implement consistent
referral chasing features, or explicitly disable referral chasing
by setting that option to
.BR LDAP_OPT_OFF .
.P
The protocol version used by the library defaults to LDAPv2 (now historic),
which corresponds to the
.B LDAP_VERSION2
macro.
Application developers are encouraged to explicitly set
.B LDAP_OPT_PROTOCOL_VERSION
to LDAPv3, using the
.B LDAP_VERSION3
macro, or to allow users to select the protocol version.
.SH SEE ALSO
.BR ldap (3),
.BR ldap_error (3),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment