]> The Tcpdump Group git mirrors - tcpdump/blob - print-dccp.c
make consistent use of the "tstr" idiom
[tcpdump] / print-dccp.c
1 /*
2 * Copyright (C) Arnaldo Carvalho de Melo 2004
3 * Copyright (C) Ian McDonald 2005
4 * Copyright (C) Yoshifumi Nishida 2005
5 *
6 * This software may be distributed either under the terms of the
7 * BSD-style license that accompanies tcpdump or the GNU GPL version 2
8 */
9
10 #ifndef lint
11 static const char rcsid[] _U_ =
12 "@(#) $Header: /tcpdump/master/tcpdump/print-dccp.c,v 1.8 2007-11-09 00:44:09 guy Exp $ (LBL)";
13 #endif
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18
19 #include <tcpdump-stdinc.h>
20
21 #include "dccp.h"
22
23 #include <stdio.h>
24 #include <string.h>
25
26 #include "interface.h"
27 #include "addrtoname.h"
28 #include "extract.h" /* must come after interface.h */
29 #include "ip.h"
30 #ifdef INET6
31 #include "ip6.h"
32 #endif
33 #include "ipproto.h"
34
35 static const char tstr[] = "[|dccp]";
36
37 static const char *dccp_reset_codes[] = {
38 "unspecified",
39 "closed",
40 "aborted",
41 "no_connection",
42 "packet_error",
43 "option_error",
44 "mandatory_error",
45 "connection_refused",
46 "bad_service_code",
47 "too_busy",
48 "bad_init_cookie",
49 "aggression_penalty",
50 };
51
52 static const char *dccp_feature_nums[] = {
53 "reserved",
54 "ccid",
55 "allow_short_seqno",
56 "sequence_window",
57 "ecn_incapable",
58 "ack_ratio",
59 "send_ack_vector",
60 "send_ndp_count",
61 "minimum checksum coverage",
62 "check data checksum",
63 };
64
65 static inline u_int dccp_csum_coverage(const struct dccp_hdr* dh, u_int len)
66 {
67 u_int cov;
68
69 if (DCCPH_CSCOV(dh) == 0)
70 return len;
71 cov = (dh->dccph_doff + DCCPH_CSCOV(dh) - 1) * sizeof(u_int32_t);
72 return (cov > len)? len : cov;
73 }
74
75 static int dccp_cksum(const struct ip *ip,
76 const struct dccp_hdr *dh, u_int len)
77 {
78 return nextproto4_cksum(ip, (const u_int8_t *)(void *)dh,
79 dccp_csum_coverage(dh, len), IPPROTO_DCCP);
80 }
81
82 #ifdef INET6
83 static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len)
84 {
85 return nextproto6_cksum(ip6, (const u_int8_t *)(void *)dh,
86 dccp_csum_coverage(dh, len), IPPROTO_DCCP);
87 }
88 #endif
89
90 static const char *dccp_reset_code(u_int8_t code)
91 {
92 if (code >= __DCCP_RESET_CODE_LAST)
93 return "invalid";
94 return dccp_reset_codes[code];
95 }
96
97 static u_int64_t dccp_seqno(const struct dccp_hdr *dh)
98 {
99 u_int32_t seq_high = DCCPH_SEQ(dh);
100 u_int64_t seqno = EXTRACT_24BITS(&seq_high) & 0xFFFFFF;
101
102 if (DCCPH_X(dh) != 0) {
103 const struct dccp_hdr_ext *dhx = (void *)(dh + 1);
104 u_int32_t seq_low = dhx->dccph_seq_low;
105 seqno &= 0x00FFFF; /* clear reserved field */
106 seqno = (seqno << 32) + EXTRACT_32BITS(&seq_low);
107 }
108
109 return seqno;
110 }
111
112 static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh)
113 {
114 return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0);
115 }
116
117 static void dccp_print_ack_no(const u_char *bp)
118 {
119 const struct dccp_hdr *dh = (const struct dccp_hdr *)bp;
120 const struct dccp_hdr_ack_bits *dh_ack =
121 (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh));
122 u_int32_t ack_high;
123 u_int64_t ackno;
124
125 TCHECK2(*dh_ack,4);
126 ack_high = DCCPH_ACK(dh_ack);
127 ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF;
128
129 if (DCCPH_X(dh) != 0) {
130 u_int32_t ack_low;
131
132 TCHECK2(*dh_ack,8);
133 ack_low = dh_ack->dccph_ack_nr_low;
134
135 ackno &= 0x00FFFF; /* clear reserved field */
136 ackno = (ackno << 32) + EXTRACT_32BITS(&ack_low);
137 }
138
139 (void)printf("(ack=%" PRIu64 ") ", ackno);
140 trunc:
141 return;
142 }
143
144 static inline unsigned int dccp_packet_hdr_len(const u_int8_t type)
145 {
146 if (type == DCCP_PKT_DATA)
147 return 0;
148 if (type == DCCP_PKT_DATAACK ||
149 type == DCCP_PKT_ACK ||
150 type == DCCP_PKT_SYNC ||
151 type == DCCP_PKT_SYNCACK ||
152 type == DCCP_PKT_CLOSE ||
153 type == DCCP_PKT_CLOSEREQ)
154 return sizeof(struct dccp_hdr_ack_bits);
155 if (type == DCCP_PKT_REQUEST)
156 return sizeof(struct dccp_hdr_request);
157 if (type == DCCP_PKT_RESPONSE)
158 return sizeof(struct dccp_hdr_response);
159 return sizeof(struct dccp_hdr_reset);
160 }
161
162 static int dccp_print_option(const u_char *option);
163
164 /**
165 * dccp_print - show dccp packet
166 * @bp - beginning of dccp packet
167 * @data2 - beginning of enclosing
168 * @len - lenght of ip packet
169 */
170 void dccp_print(const u_char *bp, const u_char *data2, u_int len)
171 {
172 const struct dccp_hdr *dh;
173 const struct ip *ip;
174 #ifdef INET6
175 const struct ip6_hdr *ip6;
176 #endif
177 const u_char *cp;
178 u_short sport, dport;
179 u_int hlen;
180 u_int extlen = 0;
181
182 dh = (const struct dccp_hdr *)bp;
183
184 ip = (struct ip *)data2;
185 #ifdef INET6
186 if (IP_V(ip) == 6)
187 ip6 = (const struct ip6_hdr *)data2;
188 else
189 ip6 = NULL;
190 #endif /*INET6*/
191 cp = (const u_char *)(dh + 1);
192 if (cp > snapend) {
193 printf("[Invalid packet|dccp]");
194 return;
195 }
196
197 if (len < sizeof(struct dccp_hdr)) {
198 printf("truncated-dccp - %ld bytes missing!",
199 (long)len - sizeof(struct dccp_hdr));
200 return;
201 }
202
203 sport = EXTRACT_16BITS(&dh->dccph_sport);
204 dport = EXTRACT_16BITS(&dh->dccph_dport);
205 hlen = dh->dccph_doff * 4;
206
207 #ifdef INET6
208 if (ip6) {
209 (void)printf("%s.%d > %s.%d: ",
210 ip6addr_string(&ip6->ip6_src), sport,
211 ip6addr_string(&ip6->ip6_dst), dport);
212 } else
213 #endif /*INET6*/
214 {
215 (void)printf("%s.%d > %s.%d: ",
216 ipaddr_string(&ip->ip_src), sport,
217 ipaddr_string(&ip->ip_dst), dport);
218 }
219 fflush(stdout);
220
221 if (qflag) {
222 (void)printf(" %d", len - hlen);
223 if (hlen > len) {
224 (void)printf("dccp [bad hdr length %u - too long, > %u]",
225 hlen, len);
226 }
227 return;
228 }
229
230 /* other variables in generic header */
231 if (vflag) {
232 (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh));
233 }
234
235 /* checksum calculation */
236 if (vflag && TTEST2(bp[0], len)) {
237 u_int16_t sum = 0, dccp_sum;
238
239 dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);
240 (void)printf("cksum 0x%04x ", dccp_sum);
241 if (IP_V(ip) == 4)
242 sum = dccp_cksum(ip, dh, len);
243 #ifdef INET6
244 else if (IP_V(ip) == 6)
245 sum = dccp6_cksum(ip6, dh, len);
246 #endif
247 if (sum != 0)
248 (void)printf("(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
249 else
250 (void)printf("(correct), ");
251 }
252
253 switch (DCCPH_TYPE(dh)) {
254 case DCCP_PKT_REQUEST: {
255 struct dccp_hdr_request *dhr =
256 (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh));
257 TCHECK(*dhr);
258 (void)printf("request (service=%d) ",
259 EXTRACT_32BITS(&dhr->dccph_req_service));
260 extlen += 4;
261 break;
262 }
263 case DCCP_PKT_RESPONSE: {
264 struct dccp_hdr_response *dhr =
265 (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh));
266 TCHECK(*dhr);
267 (void)printf("response (service=%d) ",
268 EXTRACT_32BITS(&dhr->dccph_resp_service));
269 extlen += 12;
270 break;
271 }
272 case DCCP_PKT_DATA:
273 (void)printf("data ");
274 break;
275 case DCCP_PKT_ACK: {
276 (void)printf("ack ");
277 extlen += 8;
278 break;
279 }
280 case DCCP_PKT_DATAACK: {
281 (void)printf("dataack ");
282 extlen += 8;
283 break;
284 }
285 case DCCP_PKT_CLOSEREQ:
286 (void)printf("closereq ");
287 extlen += 8;
288 break;
289 case DCCP_PKT_CLOSE:
290 (void)printf("close ");
291 extlen += 8;
292 break;
293 case DCCP_PKT_RESET: {
294 struct dccp_hdr_reset *dhr =
295 (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh));
296 TCHECK(*dhr);
297 (void)printf("reset (code=%s) ",
298 dccp_reset_code(dhr->dccph_reset_code));
299 extlen += 12;
300 break;
301 }
302 case DCCP_PKT_SYNC:
303 (void)printf("sync ");
304 extlen += 8;
305 break;
306 case DCCP_PKT_SYNCACK:
307 (void)printf("syncack ");
308 extlen += 8;
309 break;
310 default:
311 (void)printf("invalid ");
312 break;
313 }
314
315 if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) &&
316 (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST))
317 dccp_print_ack_no(bp);
318
319 if (vflag < 2)
320 return;
321
322 (void)printf("seq %" PRIu64, dccp_seqno(dh));
323
324 /* process options */
325 if (hlen > dccp_basic_hdr_len(dh) + extlen){
326 const u_char *cp;
327 u_int optlen;
328 cp = bp + dccp_basic_hdr_len(dh) + extlen;
329 printf(" <");
330
331 hlen -= dccp_basic_hdr_len(dh) + extlen;
332 while(1){
333 TCHECK(*cp);
334 optlen = dccp_print_option(cp);
335 if (!optlen) goto trunc2;
336 if (hlen <= optlen) break;
337 hlen -= optlen;
338 cp += optlen;
339 printf(", ");
340 }
341 printf(">");
342 }
343 return;
344 trunc:
345 printf("%s", tstr);
346 trunc2:
347 return;
348 }
349
350 static int dccp_print_option(const u_char *option)
351 {
352 u_int8_t optlen, i;
353
354 TCHECK(*option);
355
356 if (*option >= 32) {
357 TCHECK(*(option+1));
358 optlen = *(option +1);
359 if (optlen < 2) {
360 printf("Option %d optlen too short",*option);
361 return 1;
362 }
363 } else optlen = 1;
364
365 TCHECK2(*option,optlen);
366
367 switch (*option){
368 case 0:
369 printf("nop");
370 break;
371 case 1:
372 printf("mandatory");
373 break;
374 case 2:
375 printf("slowreceiver");
376 break;
377 case 32:
378 printf("change_l");
379 if (*(option +2) < 10){
380 printf(" %s", dccp_feature_nums[*(option +2)]);
381 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));
382 }
383 break;
384 case 33:
385 printf("confirm_l");
386 if (*(option +2) < 10){
387 printf(" %s", dccp_feature_nums[*(option +2)]);
388 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));
389 }
390 break;
391 case 34:
392 printf("change_r");
393 if (*(option +2) < 10){
394 printf(" %s", dccp_feature_nums[*(option +2)]);
395 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));
396 }
397 break;
398 case 35:
399 printf("confirm_r");
400 if (*(option +2) < 10){
401 printf(" %s", dccp_feature_nums[*(option +2)]);
402 for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));
403 }
404 break;
405 case 36:
406 printf("initcookie 0x");
407 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));
408 break;
409 case 37:
410 printf("ndp_count");
411 for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i));
412 break;
413 case 38:
414 printf("ack_vector0 0x");
415 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));
416 break;
417 case 39:
418 printf("ack_vector1 0x");
419 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));
420 break;
421 case 40:
422 printf("data_dropped 0x");
423 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));
424 break;
425 case 41:
426 printf("timestamp %u", EXTRACT_32BITS(option + 2));
427 break;
428 case 42:
429 printf("timestamp_echo %u", EXTRACT_32BITS(option + 2));
430 break;
431 case 43:
432 printf("elapsed_time ");
433 if (optlen == 6)
434 printf("%u", EXTRACT_32BITS(option + 2));
435 else
436 printf("%u", EXTRACT_16BITS(option + 2));
437 break;
438 case 44:
439 printf("data_checksum ");
440 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));
441 break;
442 default :
443 if (*option >= 128) {
444 printf("CCID option %d",*option);
445 switch (optlen) {
446 case 4:
447 printf(" %u", EXTRACT_16BITS(option + 2));
448 break;
449 case 6:
450 printf(" %u", EXTRACT_32BITS(option + 2));
451 break;
452 default:
453 break;
454 }
455 break;
456 }
457
458 printf("unknown_opt %d", *option);
459 break;
460 }
461
462 return optlen;
463 trunc:
464 printf("%s", tstr);
465 return 0;
466 }