aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:30:19 -0400
committerGerrit Renker <gerrit@erg.abdn.ac.uk>2008-09-04 01:45:31 -0400
commit5d3dac267a7fd0811ec777e76a81f97f5cdcb395 (patch)
treeef57f539a5be1c7776c73a4bcffe2d840e6883f5
parentb235dc4abbc1356284bd0dc730efa711f394e0e2 (diff)
dccp: Initialisation framework for feature negotiation
This initialises feature negotiation from two tables, which are initialised from sysctls. As a novel feature, specifics of the implementation (e.g. currently short seqnos and ECN are not supported) are advertised for robustness. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
-rw-r--r--include/linux/dccp.h19
-rw-r--r--net/dccp/feat.c66
-rw-r--r--net/dccp/feat.h2
3 files changed, 57 insertions, 30 deletions
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 61734e27abb7..990e97fa1f07 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -369,28 +369,9 @@ static inline unsigned int dccp_hdr_len(const struct sk_buff *skb)
369 * Will be used to pass the state from dccp_request_sock to dccp_sock. 369 * Will be used to pass the state from dccp_request_sock to dccp_sock.
370 * 370 *
371 * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2) 371 * @dccpms_sequence_window - Sequence Window Feature (section 7.5.2)
372 * @dccpms_pending - List of features being negotiated
373 * @dccpms_conf -
374 */ 372 */
375struct dccp_minisock { 373struct dccp_minisock {
376 __u64 dccpms_sequence_window; 374 __u64 dccpms_sequence_window;
377 struct list_head dccpms_pending;
378 struct list_head dccpms_conf;
379};
380
381struct dccp_opt_conf {
382 __u8 *dccpoc_val;
383 __u8 dccpoc_len;
384};
385
386struct dccp_opt_pend {
387 struct list_head dccpop_node;
388 __u8 dccpop_type;
389 __u8 dccpop_feat;
390 __u8 *dccpop_val;
391 __u8 dccpop_len;
392 int dccpop_conf;
393 struct dccp_opt_conf *dccpop_sc;
394}; 375};
395 376
396extern void dccp_minisock_init(struct dccp_minisock *dmsk); 377extern void dccp_minisock_init(struct dccp_minisock *dmsk);
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 35a57ab3bb1e..a687740e4420 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -1110,24 +1110,70 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq,
1110 return 0; /* ignore FN options in all other states */ 1110 return 0; /* ignore FN options in all other states */
1111} 1111}
1112 1112
1113/**
1114 * dccp_feat_init - Seed feature negotiation with host-specific defaults
1115 * This initialises global defaults, depending on the value of the sysctls.
1116 * These can later be overridden by registering changes via setsockopt calls.
1117 * The last link in the chain is finalise_settings, to make sure that between
1118 * here and the start of actual feature negotiation no inconsistencies enter.
1119 *
1120 * All features not appearing below use either defaults or are otherwise
1121 * later adjusted through dccp_feat_finalise_settings().
1122 */
1113int dccp_feat_init(struct sock *sk) 1123int dccp_feat_init(struct sock *sk)
1114{ 1124{
1115 struct dccp_sock *dp = dccp_sk(sk); 1125 struct list_head *fn = &dccp_sk(sk)->dccps_featneg;
1116 struct dccp_minisock *dmsk = dccp_msk(sk); 1126 u8 on = 1, off = 0;
1117 int rc; 1127 int rc;
1128 struct {
1129 u8 *val;
1130 u8 len;
1131 } tx, rx;
1132
1133 /* Non-negotiable (NN) features */
1134 rc = __feat_register_nn(fn, DCCPF_SEQUENCE_WINDOW, 0,
1135 sysctl_dccp_feat_sequence_window);
1136 if (rc)
1137 return rc;
1138
1139 /* Server-priority (SP) features */
1140
1141 /* Advertise that short seqnos are not supported (7.6.1) */
1142 rc = __feat_register_sp(fn, DCCPF_SHORT_SEQNOS, true, true, &off, 1);
1143 if (rc)
1144 return rc;
1118 1145
1119 INIT_LIST_HEAD(&dmsk->dccpms_pending); /* XXX no longer used */ 1146 /* RFC 4340 12.1: "If a DCCP is not ECN capable, ..." */
1120 INIT_LIST_HEAD(&dmsk->dccpms_conf); /* XXX no longer used */ 1147 rc = __feat_register_sp(fn, DCCPF_ECN_INCAPABLE, true, true, &on, 1);
1148 if (rc)
1149 return rc;
1150
1151 /*
1152 * We advertise the available list of CCIDs and reorder according to
1153 * preferences, to avoid failure resulting from negotiating different
1154 * singleton values (which always leads to failure).
1155 * These settings can still (later) be overridden via sockopts.
1156 */
1157 if (ccid_get_builtin_ccids(&tx.val, &tx.len) ||
1158 ccid_get_builtin_ccids(&rx.val, &rx.len))
1159 return -ENOBUFS;
1121 1160
1122 /* Ack ratio */ 1161 if (!dccp_feat_prefer(sysctl_dccp_feat_tx_ccid, tx.val, tx.len) ||
1123 rc = __feat_register_nn(&dp->dccps_featneg, DCCPF_ACK_RATIO, 0, 1162 !dccp_feat_prefer(sysctl_dccp_feat_rx_ccid, rx.val, rx.len))
1124 dp->dccps_l_ack_ratio); 1163 goto free_ccid_lists;
1125out: 1164
1165 rc = __feat_register_sp(fn, DCCPF_CCID, true, false, tx.val, tx.len);
1166 if (rc)
1167 goto free_ccid_lists;
1168
1169 rc = __feat_register_sp(fn, DCCPF_CCID, false, false, rx.val, rx.len);
1170
1171free_ccid_lists:
1172 kfree(tx.val);
1173 kfree(rx.val);
1126 return rc; 1174 return rc;
1127} 1175}
1128 1176
1129EXPORT_SYMBOL_GPL(dccp_feat_init);
1130
1131int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list) 1177int dccp_feat_activate_values(struct sock *sk, struct list_head *fn_list)
1132{ 1178{
1133 struct dccp_sock *dp = dccp_sk(sk); 1179 struct dccp_sock *dp = dccp_sk(sk);
diff --git a/net/dccp/feat.h b/net/dccp/feat.h
index 177e9c39ea9f..f73b47abca93 100644
--- a/net/dccp/feat.h
+++ b/net/dccp/feat.h
@@ -112,13 +112,13 @@ static inline void dccp_feat_debug(const u8 type, const u8 feat, const u8 val)
112#define dccp_feat_debug(type, feat, val) 112#define dccp_feat_debug(type, feat, val)
113#endif /* CONFIG_IP_DCCP_DEBUG */ 113#endif /* CONFIG_IP_DCCP_DEBUG */
114 114
115extern int dccp_feat_init(struct sock *sk);
115extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local, 116extern int dccp_feat_register_sp(struct sock *sk, u8 feat, u8 is_local,
116 u8 const *list, u8 len); 117 u8 const *list, u8 len);
117extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val); 118extern int dccp_feat_register_nn(struct sock *sk, u8 feat, u64 val);
118extern int dccp_feat_parse_options(struct sock *, struct dccp_request_sock *, 119extern int dccp_feat_parse_options(struct sock *, struct dccp_request_sock *,
119 u8 mand, u8 opt, u8 feat, u8 *val, u8 len); 120 u8 mand, u8 opt, u8 feat, u8 *val, u8 len);
120extern int dccp_feat_clone_list(struct list_head const *, struct list_head *); 121extern int dccp_feat_clone_list(struct list_head const *, struct list_head *);
121extern int dccp_feat_init(struct sock *sk);
122 122
123/* 123/*
124 * Encoding variable-length options and their maximum length. 124 * Encoding variable-length options and their maximum length.