]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-dccp.c
This commit was generated by cvs2svn to compensate for changes in r168777,
[FreeBSD/FreeBSD.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.2 2005/09/20 06:25:45 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 + sizeof(*dh);
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 u_int64_t dccp_ack_no(const struct dccp_hdr *dh,
159                 const struct dccp_hdr_ack_bits *dh_ack)
160 {
161         u_int32_t ack_high = DCCPH_ACK(dh_ack);
162         u_int64_t ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF;
163
164         if (DCCPH_X(dh) != 0) {
165                 u_int32_t ack_low = dh_ack->dccph_ack_nr_low;
166                 
167                 ackno &= 0x00FFFF;  /* clear reserved field */
168                 ackno = (ackno << 32) + EXTRACT_32BITS(&ack_low);
169         }
170
171         return ackno;
172 }
173
174 static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh)
175 {
176         return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0);
177 }
178
179 static inline unsigned int dccp_packet_hdr_len(const u_int8_t type)
180 {
181         if (type == DCCP_PKT_DATA)
182                 return 0;
183         if (type == DCCP_PKT_DATAACK    ||
184             type == DCCP_PKT_ACK        ||
185             type == DCCP_PKT_SYNC       ||
186             type == DCCP_PKT_SYNCACK    ||
187             type == DCCP_PKT_CLOSE      ||
188             type == DCCP_PKT_CLOSEREQ)
189                 return sizeof(struct dccp_hdr_ack_bits);
190         if (type == DCCP_PKT_REQUEST)
191                 return sizeof(struct dccp_hdr_request);
192         if (type == DCCP_PKT_RESPONSE)
193                 return sizeof(struct dccp_hdr_response);
194         return sizeof(struct dccp_hdr_reset);
195 }
196
197 static int dccp_print_option(const u_char *option);
198
199 /**
200  * dccp_print - show dccp packet
201  * @bp - beginning of dccp packet
202  * @data2 - beginning of enclosing 
203  * @len - lenght of ip packet
204  */
205 void dccp_print(const u_char *bp, const u_char *data2, u_int len)
206 {
207         const struct dccp_hdr *dh;
208         const struct ip *ip;
209 #ifdef INET6
210         const struct ip6_hdr *ip6;
211 #endif
212         const u_char *cp;
213         u_short sport, dport;
214         u_int hlen;
215         u_int extlen = 0;
216
217         dh = (const struct dccp_hdr *)bp;
218
219         ip = (struct ip *)data2;
220 #ifdef INET6
221         if (IP_V(ip) == 6)
222                 ip6 = (const struct ip6_hdr *)data2;
223         else
224                 ip6 = NULL;
225 #endif /*INET6*/
226         cp = (const u_char *)(dh + 1);
227         if (cp > snapend) {
228                 printf("[Invalid packet|dccp]");
229                 return;
230         }
231
232         if (len < sizeof(struct dccp_hdr)) {
233                 printf("truncated-dccp - %ld bytes missing!",
234                              (long)len - sizeof(struct dccp_hdr));
235                 return;
236         }
237
238         sport = EXTRACT_16BITS(&dh->dccph_sport);
239         dport = EXTRACT_16BITS(&dh->dccph_dport);
240         hlen = dh->dccph_doff * 4;
241
242 #ifdef INET6
243         if (ip6) {
244                 (void)printf("%s.%d > %s.%d: ",
245                              ip6addr_string(&ip6->ip6_src), sport,
246                              ip6addr_string(&ip6->ip6_dst), dport);
247         } else
248 #endif /*INET6*/
249         {
250                 (void)printf("%s.%d > %s.%d: ",
251                              ipaddr_string(&ip->ip_src), sport,
252                              ipaddr_string(&ip->ip_dst), dport);
253         }
254         fflush(stdout);
255
256         if (qflag) {
257                 (void)printf(" %d", len - hlen);
258                 if (hlen > len) {
259                         (void)printf("dccp [bad hdr length %u - too long, > %u]",
260                             hlen, len);
261                 }
262                 return;
263         }
264
265         /* other variables in generic header */
266         if (vflag) {
267                 (void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh));
268         }
269
270         /* checksum calculation */
271 #ifdef INET6
272         if (ip6) {
273                 if (ip6->ip6_plen && vflag) {
274                         u_int16_t sum, dccp_sum;
275
276                         sum = dccp6_cksum(ip6, dh, len);
277                         dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);         
278                         printf("cksum 0x%04x", dccp_sum);               
279                         if (sum != 0) {
280                                 (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
281                         } else
282                                 (void)printf(" (correct), ");
283                 }                                       
284         } else 
285 #endif /* INET6 */
286         if (vflag)
287         {
288                 u_int16_t sum, dccp_sum;
289
290                 sum = dccp_cksum(ip, dh, len);
291                 dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);         
292                 printf("cksum 0x%04x", dccp_sum);               
293                 if (sum != 0) {
294                         (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
295                 } else
296                         (void)printf(" (correct), ");
297         }
298
299         switch (DCCPH_TYPE(dh)) {
300         case DCCP_PKT_REQUEST: {
301                 struct dccp_hdr_request *dhr =
302                         (struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh));
303                 TCHECK(*dhr);
304                 (void)printf("request (service=%d) ", dhr->dccph_req_service);
305                 extlen += 4;
306                 break;
307         }
308         case DCCP_PKT_RESPONSE: {
309                 struct dccp_hdr_response *dhr =
310                         (struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh));
311                 TCHECK(*dhr);
312                 (void)printf("response (service=%d, ack=%" PRIu64 ") ",
313                              dhr->dccph_resp_service,
314                              dccp_ack_no(dh,&(dhr->dccph_resp_ack)));
315                 extlen += 12;
316                 break;
317         }
318         case DCCP_PKT_DATA:
319                 (void)printf("data ");
320                 break;
321         case DCCP_PKT_ACK: {
322                 struct dccp_hdr_ack_bits *dha =
323                         (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh));
324                 TCHECK(*dha);
325                 (void)printf("ack (ack=%" PRIu64 ") ",
326                              dccp_ack_no(dh,dha));
327                 extlen += 8;
328                 break;
329         }
330         case DCCP_PKT_DATAACK: {
331                 struct dccp_hdr_ack_bits *dha =
332                         (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh));
333                 TCHECK(*dha);
334                 (void)printf("dataack (ack=%" PRIu64 ") ",
335                              dccp_ack_no(dh,dha));
336                 extlen += 8;
337                 break;
338         }
339         case DCCP_PKT_CLOSEREQ:
340                 (void)printf("closereq ");
341                 extlen += 8;
342                 break;
343         case DCCP_PKT_CLOSE:
344                 (void)printf("close ");
345                 extlen += 8;
346                 break;
347         case DCCP_PKT_RESET: {
348                 struct dccp_hdr_reset *dhr =
349                         (struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh));
350                 TCHECK(*dhr);
351                 (void)printf("reset (code=%s) ",
352                              dccp_reset_code(dhr->dccph_reset_code));
353                 extlen += 12;
354                 break;
355         }
356         case DCCP_PKT_SYNC:
357                 (void)printf("sync ");
358                 extlen += 8;
359                 break;
360         case DCCP_PKT_SYNCACK:
361                 (void)printf("syncack ");
362                 extlen += 8;
363                 break;
364         default:
365                 (void)printf("invalid ");
366                 break;
367         }
368
369         if (vflag < 2)
370                 return;
371
372         (void)printf("seq %" PRIu64, dccp_seqno(dh));
373
374         /* process options */
375         if (hlen > dccp_basic_hdr_len(dh) + extlen){
376                 const u_char *cp;
377                 u_int optlen;
378                 cp = bp + dccp_basic_hdr_len(dh) + extlen;
379                 printf(" <");   
380
381                 hlen -= dccp_basic_hdr_len(dh) + extlen;
382                 while(1){
383                         TCHECK(*cp);
384                         optlen = dccp_print_option(cp);
385                         if (!optlen) goto trunc2;
386                         if (hlen <= optlen) break; 
387                         hlen -= optlen;
388                         cp += optlen;
389                         printf(", ");
390                 }
391                 printf(">");    
392         }
393         return;
394 trunc:
395         printf("[|dccp]");
396 trunc2:
397         return;
398 }
399
400 static int dccp_print_option(const u_char *option)
401 {       
402         u_int8_t optlen, i;
403         u_int32_t *ts;
404         u_int16_t *var16;
405         u_int32_t *var32;
406
407         TCHECK(*option);
408
409         if (*option >= 32) {
410                 TCHECK(*(option+1));
411                 optlen = *(option +1);
412                 if (optlen < 2) {
413                         printf("Option %d optlen too short",*option);
414                         return 1;
415                 }
416         } else optlen = 1;
417
418         TCHECK2(*option,optlen);
419
420         switch (*option){
421         case 0:
422                 printf("nop");
423                 break;  
424         case 1:
425                 printf("mandatory");
426                 break;  
427         case 2:
428                 printf("slowreceiver");
429                 break;  
430         case 32:
431                 printf("change_l");
432                 if (*(option +2) < 10){
433                         printf(" %s", dccp_feature_nums[*(option +2)]);
434                         for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));       
435                 }
436                 break;  
437         case 33:
438                 printf("confirm_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 34:
445                 printf("change_r");
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 35:
452                 printf("confirm_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 36:
459                 printf("initcookie 0x");
460                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
461                 break;
462         case 37:
463                 printf("ndp_count");
464                 for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i));       
465                 break;
466         case 38:
467                 printf("ack_vector0 0x");
468                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
469                 break;
470         case 39:
471                 printf("ack_vector1 0x");
472                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
473                 break;
474         case 40:
475                 printf("data_dropped 0x");
476                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
477                 break;
478         case 41:
479                 ts = (u_int32_t *)(option + 2);
480                 printf("timestamp %u", (u_int32_t)ntohl(*ts));
481                 break;
482         case 42:
483                 ts = (u_int32_t *)(option + 2);
484                 printf("timestamp_echo %u", (u_int32_t)ntohl(*ts));
485                 break;
486         case 43:
487                 printf("elapsed_time ");
488                 if (optlen == 6){
489                         ts = (u_int32_t *)(option + 2);
490                         printf("%u", (u_int32_t)ntohl(*ts));
491                 } else {
492                         var16 = (u_int16_t *)(option + 2);
493                         printf("%u", ntohs(*var16));
494                 }       
495                 break;
496         case 44:
497                 printf("data_checksum ");
498                 for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));      
499                 break;
500         default :
501                 if (*option >= 128) {
502                         printf("CCID option %d",*option);
503                         switch (optlen) {
504                                 case 4:
505                                         var16 = (u_int16_t *)(option + 2);
506                                         printf(" %u",ntohs(*var16));
507                                         break;
508                                 case 6:
509                                         var32 = (u_int32_t *)(option + 2);
510                                         printf(" %u",(u_int32_t)ntohl(*var32));
511                                         break;
512                                 default:
513                                         break;
514                         }
515                         break;
516                 }
517                         
518                 printf("unknown_opt %d", *option);
519                 break;
520         }
521
522         return optlen;
523 trunc:
524         printf("[|dccp]");
525         return 0;
526 }