From c37a24b653b5a3834eecd8e6f95a88a95379c005 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Thu, 25 Feb 2010 17:05:46 +0100 Subject: [PATCH] 10_set-client-ccid.diff This adds a commandline option to either * select the CCID in use for the sender-receiver half-connection or * advertise the (para_)client's priorities for the CCID; * the feature is optional and can be used to fine-tune a connection. The arguments are both range-checked by gengetopt, and against the CCIDs available on the host. Currently known CCIDs are 2-4, 248-254. Trying a CCID which is not supported by the host exits via the following route: dccp_recv_ccid_support_check: 'CCID-253' not supported on this host. main: parse failed main: recv syntax error The CCID negotiation can be watched in wireshark, between the 'Request' packet sent by the para_client and the corresponding 'Response' packet of the para_server. Here are some example negotiations: +-------------+---------------+----------------+ | client-list | server-list | resulting CCID | +-------------+---------------+----------------+ | 3, 2 | 2, 3, 4 | 2 | | 4, 3, 2, 4 | 3, 2, 4 | 3 | | 2, 4 | 2, 3, 4 | 2 | | 4, 3, 2, 4 | 2, 3, 4 | 2 | | 2 | 2, 3, 4 | 2 | | 3 | 2, 3, 4 | 3 | | 4 | 2, 3, 4 | 4 | +-------------+---------------+----------------+ The server list of (2, 3, 4) is the unaltered default, it can be changed on the server using the same mechanism. As shown, the easiest way is to use just a single '--ccid ' argument; when passing multiple values, the outcome is determined by the algorithm described in RFC 4340, 6.3.1: * 'server-priority' means that the server overrids the result; * the server traverses its list of preferences in order of priority and * uses the first entry which also appears in the client-list; * resets connection with negotiation failure when there is no common value. Applying this algorithm on the above lists can be used to verify the table. This also illustrates that repetition of CCID values has no effect on the outcome: if the repeated value is first in the server list, it will be chosen; otherwise all instances of that value are ignored. --- dccp_recv.c | 54 +++++++++++++++++++++++++++++++++++++++++------ ggo/dccp_recv.ggo | 28 ++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 7 deletions(-) diff --git a/dccp_recv.c b/dccp_recv.c index 0a7b3c06..a0f8371e 100644 --- a/dccp_recv.c +++ b/dccp_recv.c @@ -57,11 +57,25 @@ static int dccp_recv_open(struct receiver_node *rn) { struct private_dccp_recv_data *pdd; struct dccp_recv_args_info *conf = rn->conf; - int fd, ret = para_connect_simple(IPPROTO_DCCP, conf->host_arg, - conf->port_arg); - if (ret < 0) - return ret; - fd = ret; + struct flowopts *fo = NULL; + uint8_t *ccids = NULL; + int fd, ret, i; + + /* Copy CCID preference list (u8 array required) */ + if (conf->ccid_given) { + ccids = para_malloc(conf->ccid_given); + fo = flowopt_new(); + + for (i = 0; i < conf->ccid_given; i++) + ccids[i] = conf->ccid_arg[i]; + + OPT_ADD(fo, SOL_DCCP, DCCP_SOCKOPT_CCID, ccids, i); + } + + fd = makesock(IPPROTO_DCCP, 0, conf->host_arg, conf->port_arg, fo); + free(ccids); + if (fd < 0) + return fd; /* * Disable unused CCIDs: the receiver does not send any application * data to the server. By shutting down this unused path we reduce @@ -84,11 +98,37 @@ err: return ret; } +/** + * Check whether the host supports the requested 'ccid' arguments. + * \param conf DCCP receiver arguments. + * \return True if all CCIDs requested in \a conf are supported. + */ +static bool dccp_recv_ccid_support_check(struct dccp_recv_args_info *conf) +{ + uint8_t ccids[DCCP_MAX_HOST_CCIDS]; + uint8_t nccids = sizeof(ccids), i, j; + + if (dccp_available_ccids(ccids, &nccids) == NULL) + return false; + + for (i = 0; i < conf->ccid_given; i++) { + for (j = 0; j < nccids && ccids[j] != conf->ccid_arg[i]; j++) + ; + if (j == nccids) { + PARA_ERROR_LOG("'CCID-%d' not supported on this host.\n", + conf->ccid_arg[i]); + return false; + } + } + return true; +} + static void *dccp_recv_parse_config(int argc, char **argv) { - struct dccp_recv_args_info *tmp = para_calloc(sizeof(struct dccp_recv_args_info)); + struct dccp_recv_args_info *tmp = para_calloc(sizeof(*tmp)); - if (!dccp_recv_cmdline_parser(argc, argv, tmp)) + if (!dccp_recv_cmdline_parser(argc, argv, tmp) && + dccp_recv_ccid_support_check(tmp)) return tmp; free(tmp); return NULL; diff --git a/ggo/dccp_recv.ggo b/ggo/dccp_recv.ggo index 9717329d..2c7f364c 100644 --- a/ggo/dccp_recv.ggo +++ b/ggo/dccp_recv.ggo @@ -11,3 +11,31 @@ option "port" p int default="8000" optional + +option "ccid" c +"CCID preference(s) for this connection" +int +# restrict the maximum number of times this option can be passed +optional multiple(-10) +# currently known CCIDs: +# - CCID-2 (RFC 4341), +# - CCID-3 (RFC 4342), +# - CCID-4 (RFC 5622), +# - CCID-248 ... CCID-254 are experimental (RFC 4340, 19.5) +values="2", "3", "4", "248", "249", "250", "251", "252", "253", "254" +details=" + Depends on the CCIDs available on the server; this information + can be seen in the display of 'para_client si'. + + When present exactly once, this option mandates the CCID + to use for the sender-receiver connection. + + If it is passed more than once, it sets a preference list + of CCIDs for this connection. The order of appearance here + signifies descending priority. For example, + --ccid 4 --c 2 --ccid 3 + generates the preference list (CCID-4, CCID-2, CCID-3). + + The request is reconciled with the CCIDs on the server via + the 'server-priority' mechanism of RFC 4340 6.3.1/10. +" -- 2.39.5