Move tcpdump-3.9/ to tcpdump/. No need for a versioned dir.
[dragonfly.git] / contrib / 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.1.2.6 2006/02/19 05:08:44 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 *dccp_reset_codes[] = {
36         "unspecified",
37         "closed",
38         "aborted",
39         "no_connection",
40         "packet_error",
41         "option_error",
42         "mandatory_error",
43         "connection_refused",
44         "bad_service_code",
45         "too_busy",
46         "bad_init_cookie",
47         "aggression_penalty",
48 };
49
50 static const char *dccp_feature_nums[] = {
51         "reserved", 
52         "ccid",
53         "allow_short_seqno",
54         "sequence_window",
55         "ecn_incapable", 
56         "ack_ratio",     
57         "send_ack_vector",
58         "send_ndp_count", 
59         "minimum checksum coverage", 
60         "check data checksum",
61 };
62
63 static int dccp_cksum(const struct ip *ip,
64         const struct dccp_hdr *dh, u_int len)
65 {
66         union phu {
67                 struct phdr {
68                         u_int32_t src;
69                         u_int32_t dst;
70                         u_char mbz;
71                         u_char proto;
72                         u_int16_t len;
73                 } ph;
74                 u_int16_t pa[6];
75         } phu;
76         const u_int16_t *sp;
77
78         /* pseudo-header.. */
79         phu.ph.mbz = 0;
80         phu.ph.len = htons(len);
81         phu.ph.proto = IPPROTO_DCCP;
82         memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
83         if (IP_HL(ip) == 5)
84                 memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
85         else
86                 phu.ph.dst = ip_finddst(ip);
87
88         sp = &phu.pa[0];
89         return in_cksum((u_short *)dh, len, sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
90 }
91
92 #ifdef INET6
93 static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len)
94 {
95         size_t i;
96         const u_int16_t *sp;
97         u_int32_t sum;
98         union {
99                 struct {
100                         struct in6_addr ph_src;
101                         struct in6_addr ph_dst;
102                         u_int32_t   ph_len;
103                         u_int8_t    ph_zero[3];
104                         u_int8_t    ph_nxt;
105                 } ph;
106                 u_int16_t pa[20];
107         } phu;
108
109         /* pseudo-header */
110         memset(&phu, 0, sizeof(phu));
111         phu.ph.ph_src = ip6->ip6_src;
112         phu.ph.ph_dst = ip6->ip6_dst;
113         phu.ph.ph_len = htonl(len);
114         phu.ph.ph_nxt = IPPROTO_DCCP;
115
116         sum = 0;
117         for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
118                 sum += phu.pa[i];
119
120         sp = (const u_int16_t *)dh;
121
122         for (i = 0; i < (len & ~1); i += 2)
123                 sum += *sp++;
124
125         if (len & 1)
126                 sum += htons((*(const u_int8_t *)sp) << 8);
127
128         while (sum > 0xffff)
129                 sum = (sum & 0xffff) + (sum >> 16);
130         sum = ~sum & 0xffff;
131
132         return (sum);
133 }
134 #endif
135
136 static const char *dccp_reset_code(u_int8_t code)
137 {
138         if (code >= __DCCP_RESET_CODE_LAST)
139                 return "invalid";
140         return dccp_reset_codes[code];
141 }
142
143 static u_int64_t dccp_seqno(const struct dccp_hdr *dh)
144 {
145         u_int32_t seq_high = DCCPH_SEQ(dh);
146         u_int64_t seqno = EXTRACT_24BITS(&seq_high) & 0xFFFFFF;
147
148         if (DCCPH_X(dh) != 0) {
149                 const struct dccp_hdr_ext *dhx = (void *)(dh + 1);
150                 u_int32_t seq_low = dhx->dccph_seq_low;
151                 seqno &= 0x00FFFF;  /* clear reserved field */
152                 seqno = (seqno << 32) + EXTRACT_32BITS(&seq_low);
153         }
154
155         return seqno;
156 }
157
158 static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh)
159 {
160         return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0);
161 }
162
163 static void dccp_print_ack_no(const u_char *bp)
164 {
165         const struct dccp_hdr *dh = (const struct dccp_hdr *)bp;
166         const struct dccp_hdr_ack_bits *dh_ack =
167                 (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh));
168         u_int32_t ack_high;
169         u_int64_t ackno;
170
171         TCHECK2(*dh_ack,4);
172         ack_high = DCCPH_ACK(dh_ack);
173         ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF;
174
175         if (DCCPH_X(dh) != 0) {
176                 u_int32_t ack_low;
177
178                 TCHECK2(*dh_ack,8);
179                 ack_low = dh_ack->dccph_ack_nr_low;
180
181                 ackno &= 0x00FFFF;  /* clear reserved field */
182                 ackno = (ackno << 32) + EXTRACT_32BITS(&ack_low);
183         }
184
185         (void)printf("(ack=%" PRIu64 ") ", ackno);
186 trunc:
187         return;
188 }
189
190 static inline unsigned int dccp_packet_hdr_len(const u_int8_t type)
191 {
192         if (type == DCCP_PKT_DATA)
193                 return 0;
194         if (type == DCCP_PKT_DATAACK    ||
195             type == DCCP_PKT_ACK        ||
196             type == DCCP_PKT_SYNC       ||
197             type == DCCP_PKT_SYNCACK    ||
198             type == DCCP_PKT_CLOSE      ||
199             type == DCCP_PKT_CLOSEREQ)
200                 return sizeof(struct dccp_hdr_ack_bits);
201         if (type == DCCP_PKT_REQUEST)
202                 return sizeof(struct dccp_hdr_request);
203         if (type == DCCP_PKT_RESPONSE)
204                 return sizeof(struct dccp_hdr_response);
205         return sizeof(struct dccp_hdr_reset);
206 }
207
208 static int dccp_print_option(const u_char *option);
209
210 /**
211  * dccp_print - show dccp packet
212  * @bp - beginning of dccp packet
213  * @data2 - beginning of enclosing 
214  * @len - lenght of ip packet
215  */
216 void dccp_print(const u_char *bp, const u_char *data2, u_int len)
217 {
218         const struct dccp_hdr *dh;
219         const struct ip *ip;
220 #ifdef INET6
221         const struct ip6_hdr *ip6;
222 #endif
223         const u_char *cp;
224         u_short sport, dport;
225         u_int hlen;
226         u_int extlen = 0;
227
228         dh = (const struct dccp_hdr *)bp;
229
230         ip = (struct ip *)data2;
231 #ifdef INET6
232         if (IP_V(ip) == 6)
233                 ip6 = (const struct ip6_hdr *)data2;
234         else
235                 ip6 = NULL;
236 #endif /*INET6*/
237         cp = (const u_char *)(dh + 1);
238         if (cp > snapend) {
239                 printf("[Invalid packet|dccp]");
240                 return;
241         }
242
243         if (len < sizeof(struct dccp_hdr)) {
244                 printf("truncated-dccp - %ld bytes missing!",
245                              (long)len - sizeof(struct dccp_hdr));
246                 return;
247         }
248
249         sport = EXTRACT_16BITS(&dh->dccph_sport);
250         dport = EXTRACT_16BITS(&dh->dccph_dport);
251         hlen = dh->dccph_doff * 4;
252
253 #ifdef INET6
254         if (ip6) {
255                 (void)printf("%s.%d > %s.%d: ",
256                              ip6addr_string(&ip6->ip6_src), sport,
257                              ip6addr_string(&ip6->ip6_dst), dport);
258         } else
259 #endif /*INET6*/
260         {
261                 (void)printf("%s.%d > %s.%d: ",
262                              ipaddr_string(&ip->ip_src), sport,
263                              ipaddr_string(&ip->ip_dst), dport);
264         }
265         fflush(stdout);
266
267         if (qflag) {
268                 (void)printf(" %d", len - hlen);
269                 if (hlen > len) {
270                         (void)printf("dccp [bad hdr length %u - too long, > %u]",
271                             hlen, len);
272                 }
273                 return;
274         }
275
276         /* other variables in generic header */
277         if (vflag) {
278                 (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh));
279         }
280
281         /* checksum calculation */
282 #ifdef INET6
283         if (ip6) {
284                 if (ip6->ip6_plen && vflag) {
285                         u_int16_t sum, dccp_sum;
286
287                         sum = dccp6_cksum(ip6, dh, len);
288                         dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);         
289                         printf("cksum 0x%04x", dccp_sum);               
290                         if (sum != 0) {
291                                 (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
292                         } else
293                                 (void)printf(" (correct), ");
294                 }                                       
295         } else 
296 #endif /* INET6 */
297         if (vflag)
298         {
299                 u_int16_t sum, dccp_sum;
300
301                 sum = dccp_cksum(ip, dh, len);
302                 dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);         
303                 printf("cksum 0x%04x", dccp_sum);               
304                 if (sum != 0) {
305                         (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
306                 } else
307                         (void)printf(" (correct), ");
308         }
309
310         switch (DCCPH_TYPE(dh)) {
311         case DCCP_PKT_REQUEST: {
312                 struct dccp_hdr_request *dhr =
313                         (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh));
314                 TCHECK(*dhr);
315                 (void)printf("request (service=%d) ",
316                              EXTRACT_32BITS(&dhr->dccph_req_service));
317                 extlen += 4;
318                 break;
319         }
320         case DCCP_PKT_RESPONSE: {
321                 struct dccp_hdr_response *dhr =
322                         (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh));
323                 TCHECK(*dhr);
324                 (void)printf("response (service=%d) ",
325                              EXTRACT_32BITS(&dhr->dccph_resp_service));
326                 extlen += 12;
327                 break;
328         }
329         case DCCP_PKT_DATA:
330                 (void)printf("data ");
331                 break;
332         case DCCP_PKT_ACK: {
333                 (void)printf("ack ");
334                 extlen += 8;
335                 break;
336         }
337         case DCCP_PKT_DATAACK: {
338                 (void)printf("dataack ");
339                 extlen += 8;
340                 break;
341         }
342         case DCCP_PKT_CLOSEREQ:
343                 (void)printf("closereq ");
344                 extlen += 8;
345                 break;
346         case DCCP_PKT_CLOSE:
347                 (void)printf("close ");
348                 extlen += 8;
349                 break;
350         case DCCP_PKT_RESET: {
351                 struct dccp_hdr_reset *dhr =
352                         (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh));
353                 TCHECK(*dhr);
354                 (void)printf("reset (code=%s) ",
355                              dccp_reset_code(dhr->dccph_reset_code));
356                 extlen += 12;
357                 break;
358         }
359         case DCCP_PKT_SYNC:
360                 (void)printf("sync ");
361                 extlen += 8;
362                 break;
363         case DCCP_PKT_SYNCACK:
364                 (void)printf("syncack ");
365                 extlen += 8;
366                 break;
367         default:
368                 (void)printf("invalid ");
369                 break;
370         }
371
372         if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && 
373                         (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST))
374                 dccp_print_ack_no(bp);
375
376         if (vflag < 2)
377                 return;
378
379         (void)printf("seq %" PRIu64, dccp_seqno(dh));
380
381         /* process options */
382         if (hlen > dccp_basic_hdr_len(dh) + extlen){
383                 const u_char *cp;
384                 u_int optlen;
385                 cp = bp + dccp_basic_hdr_len(dh) + extlen;
386                 printf(" <");   
387
388                 hlen -= dccp_basic_hdr_len(dh) + extlen;
389                 while(1){
390                         TCHECK(*cp);
391                         optlen = dccp_print_option(cp);
392                         if (!optlen) goto trunc2;
393                         if (hlen <= optlen) break; 
394                         hlen -= optlen;
395                         cp += optlen;
396                         printf(", ");
397                 }
398                 printf(">");    
399         }
400         return;
401 trunc:
402         printf("[|dccp]");
403 trunc2:
404         return;
405 }
406
407 static int dccp_print_option(const u_char *option)
408 {       
409         u_int8_t optlen, i;
410         u_int32_t *ts;
411         u_int16_t *var16;
412         u_int32_t *var32;
413
414         TCHECK(*option);
415
416         if (*option >= 32) {
417                 TCHECK(*(option+1));
418                 optlen = *(option +1);
419                 if (optlen < 2) {
420                         printf("Option %d optlen too short",*option);
421                         return 1;
422                 }
423         } else optlen = 1;
424
425         TCHECK2(*option,optlen);
426
427         switch (*option){
428         case 0:
429                 printf("nop");
430                 break;  
431         case 1:
432                 printf("mandatory");
433                 break;  
434         case 2:
435                 printf("slowreceiver");
436                 break;  
437         case 32:
438                 printf("change_l");
439                 if (*(option +2) < 10){
440                         printf(" %s", dccp_feature_nums[*(option +2)]);
441                         for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));       
442                 }
443                 break;  
444         case 33:
445                 printf("confirm_l");
446                 if (*(option +2) < 10){
447                         printf(" %s", dccp_feature_nums[*(option +2)]);
448                         for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));       
449                 }
450                 break;
451         case 34:
452                 printf("change_r");
453                 if (*(option +2) < 10){
454                         printf(" %s", dccp_feature_nums[*(option +2)]);
455                         for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));       
456                 }
457                 break;
458         case 35:
459                 printf("confirm_r");
460                 if (*(option +2) < 10){
461                         printf(" %s", dccp_feature_nums[*(option +2)]);
462                         for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));       
463                 }
464                 break;
465         case 36:
466                 printf("initcookie 0x");
467                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
468                 break;
469         case 37:
470                 printf("ndp_count");
471                 for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i));       
472                 break;
473         case 38:
474                 printf("ack_vector0 0x");
475                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
476                 break;
477         case 39:
478                 printf("ack_vector1 0x");
479                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
480                 break;
481         case 40:
482                 printf("data_dropped 0x");
483                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
484                 break;
485         case 41:
486                 ts = (u_int32_t *)(option + 2);
487                 printf("timestamp %u", (u_int32_t)ntohl(*ts));
488                 break;
489         case 42:
490                 ts = (u_int32_t *)(option + 2);
491                 printf("timestamp_echo %u", (u_int32_t)ntohl(*ts));
492                 break;
493         case 43:
494                 printf("elapsed_time ");
495                 if (optlen == 6){
496                         ts = (u_int32_t *)(option + 2);
497                         printf("%u", (u_int32_t)ntohl(*ts));
498                 } else {
499                         var16 = (u_int16_t *)(option + 2);
500                         printf("%u", ntohs(*var16));
501                 }       
502                 break;
503         case 44:
504                 printf("data_checksum ");
505                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
506                 break;
507         default :
508                 if (*option >= 128) {
509                         printf("CCID option %d",*option);
510                         switch (optlen) {
511                                 case 4:
512                                         var16 = (u_int16_t *)(option + 2);
513                                         printf(" %u",ntohs(*var16));
514                                         break;
515                                 case 6:
516                                         var32 = (u_int32_t *)(option + 2);
517                                         printf(" %u",(u_int32_t)ntohl(*var32));
518                                         break;
519                                 default:
520                                         break;
521                         }
522                         break;
523                 }
524                         
525                 printf("unknown_opt %d", *option);
526                 break;
527         }
528
529         return optlen;
530 trunc:
531         printf("[|dccp]");
532         return 0;
533 }