1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2012 David Hoeppner. All rights reserved.
14 */
15
16 #include <sys/types.h>
17 #include <sys/stream.h>
18 #include <sys/debug.h>
19 #include <sys/cmn_err.h>
20
21 #include "dccp_impl.h"
22 #include "dccp_stack.h"
23
24 /*
25 * This file contains functions to parse and process DCCP options
26 * and features.
27 */
28
29 static void dccp_parse_feature(dccp_t *, uint8_t, uint8_t, uchar_t *,
30 boolean_t);
31
32 /*
33 * Feature handling.
34 */
35 static void
36 dccp_parse_feature(dccp_t *dccp, uint8_t option, uint8_t length, uchar_t *up,
37 boolean_t mandatory)
38 {
39 dccp_feature_t *feature;
40 uint8_t feature_type;
41 uint8_t feature_length = length - 1;
42
43 cmn_err(CE_NOTE, "dccp_features.c: dccp_parse_feature");
44
45 feature_type = *up;
46
47 switch (feature_type) {
48 case DCCP_FEATURE_CCID:
49 cmn_err(CE_NOTE, "DCCP_FEATURE_CCID");
50 break;
51 case DCCP_FEATURE_ALLOW_SHORT_SEQNOS:
52 cmn_err(CE_NOTE, "DCCP_FEATURE_ALLOW_SHORT_SEQNOS");
53 break;
54 case DCCP_FEATURE_SEQUENCE_WINDOW:
55 cmn_err(CE_NOTE, "DCCP_FEATURE_SEQUENCE_WINDOW");
56 break;
57 case DCCP_FEATURE_ECN_INCAPABLE:
58 cmn_err(CE_NOTE, "DCCP_FEATURE_ECN_INCAPABLE");
59 break;
60 case DCCP_FEATURE_ACK_RATIO:
61 cmn_err(CE_NOTE, "DCCP_FEATURE_ACK_RATIO");
62 break;
63 case DCCP_FEATURE_SEND_ACK_VECTOR:
64 cmn_err(CE_NOTE, "DCCP_FEATURE_SEND_ACK_VECTOR");
65 break;
66 case DCCP_FEATURE_SEND_NDP_COUNT:
67 cmn_err(CE_NOTE, "DCCP_FEATURE_SEND_NDP_COUNT");
68 break;
69 case DCCP_FEATURE_MIN_CHECKSUM_COVERAGE:
70 cmn_err(CE_NOTE, "DCCP_FEATURE_MIN_CHECKSUM_COVERAGE");
71 break;
72 case DCCP_FEATURE_CHECK_DATA_CHECKSUM:
73 cmn_err(CE_NOTE, "DCCP_FEATURE_CHECK_DATA_CHECKSUM");
74 break;
75
76 default:
77 cmn_err(CE_NOTE, "ERROR DEFAULT");
78 break;
79 }
80
81 feature = (dccp_feature_t *)kmem_alloc(sizeof (dccp_feature_t),
82 KM_SLEEP);
83 if (feature == NULL) {
84 return;
85 }
86
87 feature->df_option = option;
88 feature->df_type = feature_type;
89 feature->df_mandatory = mandatory;
90
91 list_insert_tail(&dccp->dccp_features, feature);
92 }
93
94 /*
95 * Parse the options in a DCCP header.
96 */
97 void
98 dccp_parse_options(dccp_t *dccp, dccpha_t *dccpha)
99 {
100 uchar_t *end;
101 uchar_t *up;
102 uint8_t dccp_type;
103 uint8_t option_type;
104 uint8_t option_length;
105 int len;
106 int i;
107 uchar_t *value;
108 boolean_t mandatory = B_FALSE;
109
110 cmn_err(CE_NOTE, "dccp_features.c: dccp_parse_options");
111
112 dccp_type = dccpha->dha_type;
113
114 up = (uchar_t *)dccpha;
115 end = up + DCCP_HDR_LENGTH(dccpha);
116 up += 20;
117
118 if (dccp_type != DCCP_PKT_REQUEST) {
119 cmn_err(CE_NOTE, "not request pkt");
120 return;
121 }
122
123 while (up != end) {
124 option_length = 0;
125 option_type = *up++;
126
127 if (option_type > 31) {
128 option_length = *up++;
129 option_length -= 2;
130 value = up;
131
132 up += option_length;
133 }
134
135 switch (option_type) {
136 case DCCP_OPTION_PADDING:
137 cmn_err(CE_NOTE, "PADDING");
138 break;
139 case DCCP_OPTION_MANDATORY:
140 cmn_err(CE_NOTE, "MANDATORY");
141 mandatory = B_TRUE;
142 break;
143 case DCCP_OPTION_SLOW_RECEIVER:
144 cmn_err(CE_NOTE, "SLOW RECEIVER");
145 break;
146 case DCCP_OPTION_CHANGE_L:
147 case DCCP_OPTION_CONFIRM_L:
148 case DCCP_OPTION_CHANGE_R:
149 case DCCP_OPTION_CONFIRM_R:
150 dccp_parse_feature(dccp, option_type, option_length,
151 value, mandatory);
152 break;
153 case DCCP_OPTION_INIT_COOKIE:
154 cmn_err(CE_NOTE, "INIT COOKIE");
155 break;
156 case DCCP_OPTION_NDP_COUNT:
157 cmn_err(CE_NOTE, "NDP COUNT");
158 break;
159 case DCCP_OPTION_ACK_VECTOR_1:
160 cmn_err(CE_NOTE, "ACK VECTOR 1");
161 break;
162 case DCCP_OPTION_ACK_VECTOR_2:
163 cmn_err(CE_NOTE, "ACK VECTOR 2");
164 break;
165 case DCCP_OPTION_DATA_DROPPED:
166 cmn_err(CE_NOTE, "DATA DROPPED");
167 break;
168 case DCCP_OPTION_TIMESTAMP:
169 cmn_err(CE_NOTE, "TIMESTAMP");
170 if (option_length == 4) {
171 cmn_err(CE_NOTE, "timestamp length == 4");
172 } else {
173 cmn_err(CE_NOTE, "timestamp length != 4");
174 }
175 break;
176 case DCCP_OPTION_TIMESTAMP_ECHO:
177 cmn_err(CE_NOTE, "TIMESTAMP ECHO");
178 break;
179 case DCCP_OPTION_ELAPSED_TIME:
180 cmn_err(CE_NOTE, "ELAPSES TIME");
181 break;
182 case DCCP_OPTION_DATA_CHECKSUM:
183 cmn_err(CE_NOTE, "DATA CHECKSUM");
184 break;
185
186 default:
187 cmn_err(CE_NOTE, "DEFAULT");
188 break;
189 }
190
191 if (option_type != DCCP_OPTION_MANDATORY) {
192 mandatory = B_FALSE;
193 }
194 }
195 }
196
197 void
198 dccp_process_options(dccp_t *dccp, dccpha_t *dccpha)
199 {
200 cmn_err(CE_NOTE, "dccp_features.c: dccp_process_features");
201
202 dccp_parse_options(dccp, dccpha);
203 }
204
205 int
206 dccp_generate_options(dccp_t *dccp, void **opt, size_t *opt_len)
207 {
208 dccp_feature_t *feature = NULL;
209 uint8_t buf[1024]; /* XXX */
210 uint8_t option_type;
211 uint_t len = 0;
212 uint_t total_len;
213 void *options;
214 int rest;
215
216 cmn_err(CE_NOTE, "dccp_features.c: dccp_generate_options");
217
218 for (feature = list_head(&dccp->dccp_features); feature;
219 feature = list_next(&dccp->dccp_features, feature)) {
220 if (feature->df_option == DCCP_OPTION_CHANGE_L) {
221 option_type = DCCP_OPTION_CONFIRM_R;
222 } else {
223 option_type = DCCP_OPTION_CONFIRM_L;
224 }
225 /*
226 if (feature->df_mandatory == B_TRUE) {
227 buf[len] = DCCP_OPTION_MANDATORY;
228 len++;
229 }
230 */
231 if (feature->df_type == DCCP_FEATURE_CCID) {
232 cmn_err(CE_NOTE, "FOUND DCCP_FEATURE_CCID");
233
234 buf[len] = option_type;
235 len++;
236 buf[len] = 4;
237 len++;
238 buf[len] = DCCP_FEATURE_CCID;
239 len++;
240 buf[len] = 2;
241 len++;
242 }
243
244 if (feature->df_type == DCCP_FEATURE_ALLOW_SHORT_SEQNOS) {
245 buf[len] = option_type;
246 len++;
247 buf[len] = 4;
248 len++;
249 buf[len] = feature->df_type;
250 len++;
251 buf[len] = 0;
252 len++;
253 }
254
255 if (feature->df_type == DCCP_FEATURE_ECN_INCAPABLE) {
256 buf[len] = option_type;
257 len++;
258 buf[len] = 4;
259 len++;
260 buf[len] = feature->df_type;
261 len++;
262 buf[len] = 1;
263 len++;
264 }
265 }
266
267 total_len = ((len + (4 - 1)) / 4) * 4;
268 options = kmem_zalloc(total_len, KM_SLEEP);
269 if (options == NULL) {
270 cmn_err(CE_NOTE, "kmem_zalloc failed");
271 return (ENOMEM);
272 }
273 memcpy(options, buf, len);
274
275 *opt = options;
276 *opt_len = len;
277
278 return (0);
279 }
280
281 void
282 dccp_features_init(void)
283 {
284 }
285
286 void
287 dccp_features_destroy(void)
288 {
289 }