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 }