1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Copyright 2012 David Hoeppner. All rights reserved. 25 */ 26 27 #include <stdio.h> 28 #include <ctype.h> 29 #include <string.h> 30 #include <fcntl.h> 31 #include <string.h> 32 #include <sys/types.h> 33 #include <sys/time.h> 34 35 #include <sys/socket.h> 36 #include <sys/sockio.h> 37 #include <net/if.h> 38 #include <netinet/in_systm.h> 39 #include <netinet/in.h> 40 #include <netinet/ip.h> 41 #include <netinet/if_ether.h> 42 #include <netinet/dccp.h> 43 #include "snoop.h" 44 45 /* 46 * Snoop interpreter for DCCP (RFC4340) 47 * 48 */ 49 50 extern char *dlc_header; 51 52 static char *get_type(uint8_t); 53 static void print_dccpoptions_summary(uchar_t *, uchar_t *); 54 static void print_dccpoptions(uchar_t *, uchar_t *); 55 56 static char * 57 get_type(uint8_t type) 58 { 59 switch (type) { 60 case 0: 61 return ("DCCP-Request"); 62 case 1: 63 return ("DCCP-Response"); 64 case 2: 65 return ("DCCP-Data"); 66 case 3: 67 return ("DCCP-Ack"); 68 case 4: 69 return ("DCCP-DataAck"); 70 case 5: 71 return ("DCCP-CloseReq"); 72 case 6: 73 return ("DCCP-Close"); 74 case 7: 75 return ("DCCP-Reset"); 76 case 8: 77 return ("DCCP-Sync"); 78 case 9: 79 return ("DCCP-SyncAck"); 80 case 10 ... 15: 81 return ("Reserved"); 82 83 default: 84 return ("Unknown"); 85 } 86 } 87 88 int 89 interpret_dccp(int flags, struct dccphdr *dccp, int iplen, int fraglen) 90 { 91 char *data; 92 char *line; 93 char *endline; 94 uint64_t seq; 95 uint64_t ack; 96 int hdrlen; 97 int dccplen; 98 int option_offset; 99 int i; 100 101 hdrlen = dccp->dh_offset * 4; 102 data = (char *)dccp + hdrlen; 103 dccplen = iplen - hdrlen; 104 fraglen -= hdrlen; 105 106 if (fraglen < 0) { 107 return (fraglen + hdrlen); /* Incomplete header */ 108 } 109 110 if (fraglen > dccplen) { 111 fraglen = dccplen; 112 } 113 114 if (dccp->dh_x == 1) { 115 switch (dccp->dh_type) { 116 case 0: /* DCCP-Request */ 117 option_offset = 20; 118 break; 119 case 1: /* DCCP-Response */ 120 option_offset = 28; 121 break; 122 case 7: /* DCCP-Reset */ 123 option_offset = 28; 124 break; 125 case 8: /* DCCP-Sync */ 126 case 9: /* DCCP-SyncAck */ 127 option_offset = 24; 128 break; 129 130 default: 131 option_offset = 20; 132 break; 133 } 134 135 /* Sequence number */ 136 seq = ntohs(dccp->dh_seq); 137 seq <<= 32; 138 seq += (uint32_t)dccp + sizeof (struct dccphdr); 139 140 ack = (uint32_t)(dccp + 16) & 0xffff; 141 } else { 142 switch (dccp->dh_type) { 143 case 0: /* DCCP-Request */ 144 case 1: /* DCCP-Response */ 145 case 7: /* DCCP-Reset */ 146 case 8: /* DCCP-Sync */ 147 case 9: /* DCCP-SyncAck */ 148 break; 149 150 default: 151 option_offset = 20; 152 break; 153 } 154 155 /* Sequence number */ 156 seq = dccp->dh_res_seq << 16; 157 seq |= ntohs(dccp->dh_seq); 158 } 159 160 if (flags & F_SUM) { 161 line = get_sum_line(); 162 endline = line + MAXLINE; 163 164 (void) snprintf(line, endline - line, "DCCP D=%d S=%d", 165 ntohs(dccp->dh_dport), ntohs(dccp->dh_sport)); 166 line += strlen(line); 167 168 (void) snprintf(line, endline - line, "CCval=%d CsCov=%d", 169 dccp->dh_ccval, dccp->dh_cscov); 170 171 (void) snprintf(line, endline - line, " Seq=%u Len=%d", 172 seq, dccplen); 173 line += strlen(line); 174 175 /* 176 * All packets except DCCP-Request and DCCP-Data carry 177 * an acknowledgement number. 178 */ 179 if (dccp->dh_type != 0 && dccp->dh_type != 2) { 180 (void) snprintf(line, endline - line, " Ack=%u", 181 seq, dccplen); 182 } 183 line += strlen(line); 184 185 print_dccpoptions_summary((uchar_t *)dccp + option_offset, 186 (uchar_t *)dccp + dccp->dh_offset * 4); 187 } 188 189 190 if (flags & F_DTAIL) { 191 show_header("DCCP: ", "DCCP Header", dccplen); 192 show_space(); 193 194 (void) sprintf(get_line((char *)(uintptr_t)dccp->dh_sport - 195 dlc_header, 2), "Source port = %d", 196 ntohs(dccp->dh_sport)); 197 198 (void) sprintf(get_line((char *)(uintptr_t)dccp->dh_dport - 199 dlc_header, 2), "Destination port = %d", 200 ntohs(dccp->dh_dport)); 201 202 (void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_offset - 203 dlc_header) + 4, 1), "Data offset = %d bytes", 204 dccp->dh_offset * 4); 205 206 (void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_ccval - 207 dlc_header) + 4, 1), "CCVal = %d", 208 dccp->dh_ccval); 209 210 (void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_cscov - 211 dlc_header) + 4, 1), "Checksum coverage (CsCov) = %d", 212 dccp->dh_cscov); 213 214 (void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_sum - 215 dlc_header) + 4, 1), "Checksum = 0x%04x", 216 ntohs(dccp->dh_sum)); 217 218 (void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_type - 219 dlc_header) + 4, 1), "Type = %d (%s)", 220 dccp->dh_type, get_type(dccp->dh_type)); 221 222 (void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_x - 223 dlc_header) + 4, 1), "Extended sequence numbers = %d", 224 dccp->dh_x); 225 226 (void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_seq - 227 dlc_header) + 4, 1), "Sequence number = %d", 228 seq); 229 230 /* 231 * All packets except DCCP-Request and DCCP-Data carry 232 * an acknowledgement number. 233 */ 234 if (dccp->dh_type != 0 && dccp->dh_type != 2) { 235 (void) sprintf(get_line(((char *)(uintptr_t)dccp->dh_seq - 236 dlc_header) + 4, 1), "Acknowledgement number = %d", 237 seq); 238 } 239 240 print_dccpoptions((uchar_t *)dccp + option_offset, 241 (uchar_t *)dccp + dccp->dh_offset * 4); 242 243 show_space(); 244 } 245 246 return (dccplen); 247 } 248 249 static void 250 print_dccpoptions_summary(uchar_t *up, uchar_t *end) 251 { 252 uchar_t *value; 253 uint8_t option_type; 254 uint8_t option_length; 255 int len; 256 boolean_t mandatory = B_FALSE; 257 258 while (up != end) { 259 option_length = 0; 260 option_type = *up++; 261 262 /* 263 * Is this a variable length option? 264 */ 265 if (option_type > 31) { 266 option_length = *up++; 267 option_length -= 2; 268 value = up; 269 270 up += option_length; 271 } 272 switch (option_type) { 273 case 0: /* Padding */ 274 break; 275 case 1: /* Mandatory */ 276 mandatory = B_TRUE; 277 break; 278 case 2: /* Slow receiver */ 279 break; 280 case 3 ... 31: /* Reserved */ 281 break; 282 case 32: /* Change L */ 283 break; 284 case 33: /* Confirm L */ 285 break; 286 case 34: /* Change R */ 287 break; 288 case 35: /* Confirm R */ 289 break; 290 case 36: /* Init cookie */ 291 break; 292 case 37: /* NDP count */ 293 break; 294 case 38: /* Ack Vector 0 */ 295 break; 296 case 39: /* Ack vector 1 */ 297 break; 298 case 40: /* Data dropped */ 299 break; 300 case 41: /* Timestamp */ 301 break; 302 case 42: /* Timestamp echo */ 303 break; 304 case 43: /* Elapsed time */ 305 break; 306 case 44: /* Data checksum */ 307 break; 308 309 default: 310 break; 311 } 312 313 if (option_type != 1) { 314 mandatory = B_FALSE; 315 } 316 } 317 } 318 319 static void 320 print_dccpoptions(uchar_t *up, uchar_t *end) 321 { 322 uchar_t *value; 323 uint8_t option_type; 324 uint8_t option_length; 325 int len; 326 boolean_t mandatory = B_FALSE; 327 328 if (up == end) { 329 (void) sprintf(get_line((char *)&up - dlc_header, 1), 330 "No options"); 331 return; 332 } 333 334 (void) sprintf(get_line((char *)&up - dlc_header, 1), 335 "Options: (%d bytes)", (int)(end - up)); 336 337 while (up != end) { 338 option_length = 0; 339 option_type = *up++; 340 341 /* 342 * Is this a variable length option? 343 */ 344 if (option_type > 31) { 345 option_length = *up++; 346 option_length -= 2; 347 value = up; 348 349 up += option_length; 350 } 351 352 switch (option_type) { 353 case 0: /* Padding */ 354 (void) sprintf(get_line(((char *)(uintptr_t)up - 355 dlc_header) + 4, 1), "Padding"); 356 break; 357 case 1: /* Mandatory */ 358 (void) sprintf(get_line(((char *)(uintptr_t)up - 359 dlc_header) + 4, 1), "Mandatory"); 360 mandatory = B_TRUE; 361 break; 362 case 2: /* Slow receiver */ 363 (void) sprintf(get_line(((char *)(uintptr_t)up - 364 dlc_header) + 4, 1), "Slow receiver"); 365 break; 366 case 3 ... 31: /* Reserved */ 367 (void) sprintf(get_line(((char *)(uintptr_t)up - 368 dlc_header) + 4, 1), "Reserved"); 369 break; 370 case 32: /* Change L */ 371 (void) sprintf(get_line(((char *)(uintptr_t)up - 372 dlc_header) + 4, 1), "Change L"); 373 break; 374 case 33: /* Confirm L */ 375 (void) sprintf(get_line(((char *)(uintptr_t)up - 376 dlc_header) + 4, 1), "Confirm L"); 377 break; 378 case 34: /* Change R */ 379 (void) sprintf(get_line(((char *)(uintptr_t)up - 380 dlc_header) + 4, 1), "Change R"); 381 break; 382 case 35: /* Confirm R */ 383 (void) sprintf(get_line(((char *)(uintptr_t)up - 384 dlc_header) + 4, 1), "Confirm R"); 385 break; 386 case 36: /* Init cookie */ 387 (void) sprintf(get_line(((char *)(uintptr_t)up - 388 dlc_header) + 4, 1), "Init cookie"); 389 break; 390 case 37: /* NDP count */ 391 (void) sprintf(get_line(((char *)(uintptr_t)up - 392 dlc_header) + 4, 1), "NDP count"); 393 break; 394 case 38: /* Ack vector 0 */ 395 (void) sprintf(get_line(((char *)(uintptr_t)up - 396 dlc_header) + 4, 1), "Ack vector 0"); 397 break; 398 case 39: /* Ack vector 1 */ 399 (void) sprintf(get_line(((char *)(uintptr_t)up - 400 dlc_header) + 4, 1), "Ack vector 1"); 401 break; 402 case 40: /* Data dropped */ 403 (void) sprintf(get_line(((char *)(uintptr_t)up - 404 dlc_header) + 4, 1), "Data dropped"); 405 break; 406 case 41: /* Timestamp */ 407 (void) sprintf(get_line(((char *)(uintptr_t)up - 408 dlc_header) + 4, 1), "Timestamp"); 409 break; 410 case 42: /* Timestamp echo */ 411 (void) sprintf(get_line(((char *)(uintptr_t)up - 412 dlc_header) + 4, 1), "TImestamp echo"); 413 break; 414 case 43: /* Elapsed time */ 415 (void) sprintf(get_line(((char *)(uintptr_t)up - 416 dlc_header) + 4, 1), "Elapsed time"); 417 break; 418 case 44: /* Data checksum */ 419 (void) sprintf(get_line(((char *)(uintptr_t)up - 420 dlc_header) + 4, 1), "Data checksum"); 421 break; 422 423 default: 424 (void) sprintf(get_line(((char *)(uintptr_t)up - 425 dlc_header) + 4, 1), "Unknown"); 426 break; 427 } 428 429 if (option_type != 1) { 430 mandatory = B_FALSE; 431 } 432 } 433 }