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 }