diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2008-11-05 02:55:49 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-11-05 02:55:49 -0500 |
commit | ac75773c2742d82cbcb078708df406e9017224b7 (patch) | |
tree | 7e7b1aa5131c4a61aabd9d86d7332eca98d66a89 /net/dccp/feat.c | |
parent | 61e6473efbd6087e1db3aaa93a5266c5bfd8aa99 (diff) |
dccp: Per-socket initialisation of feature negotiation
This provides feature-negotiation initialisation for both DCCP sockets
and DCCP request_sockets, to support feature negotiation during
connection setup.
It also resolves a FIXME regarding the congestion control
initialisation.
Thanks to Wei Yongjun for help with the IPv6 side of this patch.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/feat.c')
-rw-r--r-- | net/dccp/feat.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/net/dccp/feat.c b/net/dccp/feat.c index 9a37b6ce3aca..069d8ffe4c6f 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c | |||
@@ -90,6 +90,20 @@ static u8 dccp_feat_type(u8 feat_num) | |||
90 | return dccp_feat_table[idx].reconciliation; | 90 | return dccp_feat_table[idx].reconciliation; |
91 | } | 91 | } |
92 | 92 | ||
93 | /* copy constructor, fval must not already contain allocated memory */ | ||
94 | static int dccp_feat_clone_sp_val(dccp_feat_val *fval, u8 const *val, u8 len) | ||
95 | { | ||
96 | fval->sp.len = len; | ||
97 | if (fval->sp.len > 0) { | ||
98 | fval->sp.vec = kmemdup(val, len, gfp_any()); | ||
99 | if (fval->sp.vec == NULL) { | ||
100 | fval->sp.len = 0; | ||
101 | return -ENOBUFS; | ||
102 | } | ||
103 | } | ||
104 | return 0; | ||
105 | } | ||
106 | |||
93 | static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val) | 107 | static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val) |
94 | { | 108 | { |
95 | if (unlikely(val == NULL)) | 109 | if (unlikely(val == NULL)) |
@@ -99,6 +113,28 @@ static void dccp_feat_val_destructor(u8 feat_num, dccp_feat_val *val) | |||
99 | memset(val, 0, sizeof(*val)); | 113 | memset(val, 0, sizeof(*val)); |
100 | } | 114 | } |
101 | 115 | ||
116 | static struct dccp_feat_entry * | ||
117 | dccp_feat_clone_entry(struct dccp_feat_entry const *original) | ||
118 | { | ||
119 | struct dccp_feat_entry *new; | ||
120 | u8 type = dccp_feat_type(original->feat_num); | ||
121 | |||
122 | if (type == FEAT_UNKNOWN) | ||
123 | return NULL; | ||
124 | |||
125 | new = kmemdup(original, sizeof(struct dccp_feat_entry), gfp_any()); | ||
126 | if (new == NULL) | ||
127 | return NULL; | ||
128 | |||
129 | if (type == FEAT_SP && dccp_feat_clone_sp_val(&new->val, | ||
130 | original->val.sp.vec, | ||
131 | original->val.sp.len)) { | ||
132 | kfree(new); | ||
133 | return NULL; | ||
134 | } | ||
135 | return new; | ||
136 | } | ||
137 | |||
102 | static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry) | 138 | static void dccp_feat_entry_destructor(struct dccp_feat_entry *entry) |
103 | { | 139 | { |
104 | if (entry != NULL) { | 140 | if (entry != NULL) { |
@@ -133,6 +169,25 @@ void dccp_feat_list_purge(struct list_head *fn_list) | |||
133 | } | 169 | } |
134 | EXPORT_SYMBOL_GPL(dccp_feat_list_purge); | 170 | EXPORT_SYMBOL_GPL(dccp_feat_list_purge); |
135 | 171 | ||
172 | /* generate @to as full clone of @from - @to must not contain any nodes */ | ||
173 | int dccp_feat_clone_list(struct list_head const *from, struct list_head *to) | ||
174 | { | ||
175 | struct dccp_feat_entry *entry, *new; | ||
176 | |||
177 | INIT_LIST_HEAD(to); | ||
178 | list_for_each_entry(entry, from, node) { | ||
179 | new = dccp_feat_clone_entry(entry); | ||
180 | if (new == NULL) | ||
181 | goto cloning_failed; | ||
182 | list_add_tail(&new->node, to); | ||
183 | } | ||
184 | return 0; | ||
185 | |||
186 | cloning_failed: | ||
187 | dccp_feat_list_purge(to); | ||
188 | return -ENOMEM; | ||
189 | } | ||
190 | |||
136 | int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, | 191 | int dccp_feat_change(struct dccp_minisock *dmsk, u8 type, u8 feature, |
137 | u8 *val, u8 len, gfp_t gfp) | 192 | u8 *val, u8 len, gfp_t gfp) |
138 | { | 193 | { |