]> The Tcpdump Group git mirrors - tcpdump/blob - print-mptcp.c
Multipath TCP (RFC 6824) support
[tcpdump] / print-mptcp.c
1 /**
2 * Copyright (c) 2012
3 *
4 * Gregory Detal <gregory.detal@uclouvain.be>
5 * Christoph Paasch <christoph.paasch@uclouvain.be>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * 3. Neither the name of the University nor of the Laboratory may be used
19 * to endorse or promote products derived from this software without
20 * specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include <tcpdump-stdinc.h>
40
41 #include <stdio.h>
42 #include <string.h>
43
44 #include "interface.h"
45 #include "extract.h"
46 #include "addrtoname.h"
47
48 #include "ipproto.h"
49 #include "mptcp.h"
50
51 static int dummy_print(const u_char *opt, u_int opt_len)
52 {
53 return 1;
54 }
55
56 static int mp_capable_print(const u_char *opt, u_int opt_len)
57 {
58 struct mp_capable *mpc = (struct mp_capable *) opt;
59
60 if (mpc->c)
61 printf(" csum");
62 printf(" {0x%" PRIx64, mpc->sender_key);
63 if (opt_len == 20)
64 printf(",0x%" PRIx64, mpc->receiver_key);
65 printf("}");
66 return 1;
67 }
68
69 static int mp_join_print(const u_char *opt, u_int opt_len)
70 {
71 struct mp_join *mpj = (struct mp_join *) opt;
72
73 if (mpj->b)
74 printf(" backup");
75 printf(" id %" PRIu8, mpj->addr_id);
76
77 if (opt_len == 12)
78 printf(" token 0x%" PRIx32, mpj->u.syn.token);
79
80 return 1;
81 }
82
83 static u_int mp_dss_len(struct mp_dss *m, u_int csum)
84 {
85 return 4 + m->A * (4 + m->a * 4) + m->M * (10 + m->m * 4 + csum * 2);
86 }
87
88 static int mp_dss_print(const u_char *opt, u_int opt_len)
89 {
90 struct mp_dss *mdss = (struct mp_dss *) opt;
91
92 if (mdss->F)
93 printf(" fin");
94
95 opt += 4;
96 if (mdss->A) {
97 printf(" ack ");
98 if (mdss->a)
99 printf("%" PRIu64, EXTRACT_64BITS(opt));
100 else
101 printf("%" PRIu32, EXTRACT_32BITS(opt));
102 opt += mdss->a ? 8 : 4;
103 }
104
105 if (mdss->M) {
106 printf(" seq ");
107 if (mdss->m)
108 printf("%" PRIu64, EXTRACT_64BITS(opt));
109 else
110 printf("%" PRIu32, EXTRACT_32BITS(opt));
111 opt += mdss->m ? 8 : 4;
112 printf(" subseq %" PRIu32, EXTRACT_32BITS(opt));
113 opt += 4;
114 printf(" len %" PRIu16, EXTRACT_16BITS(opt));
115 opt += 2;
116
117 if (opt_len == mp_dss_len(mdss, 1))
118 printf(" csum 0x%" PRIx16, EXTRACT_16BITS(opt));
119 }
120 return 1;
121 }
122
123 static int add_addr_print(const u_char *opt, u_int opt_len)
124 {
125 struct mp_add_addr *add_addr = (struct mp_add_addr *) opt;
126
127 printf(" id %" PRIu8, add_addr->addr_id);
128 switch (add_addr->ipver) {
129 case 4:
130 printf(" %s", ipaddr_string(&add_addr->u.v4.addr));
131 break;
132 #ifdef INET6
133 case 6:
134 printf(" %s", ip6addr_string(&add_addr->u.v6.addr));
135 break;
136 #endif
137 default:
138 return 0;
139 }
140 if (opt_len == 10 || opt_len == 22)
141 printf(":%" PRIu16, ntohs(add_addr->ipver == 4 ?
142 add_addr->u.v4.port :
143 add_addr->u.v6.port));
144 return 1;
145 }
146
147 static int remove_addr_print(const u_char *opt, u_int opt_len)
148 {
149 struct mp_remove_addr *rem_addr = (struct mp_remove_addr *) opt;
150 u_int8_t *addr_id = &rem_addr->addrs_id;
151
152 opt_len -= 3;
153 printf(" id");
154 while (opt_len--)
155 printf(" %" PRIu8, *addr_id++);
156 return 1;
157 }
158
159 static int mp_prio_print(const u_char *opt, u_int opt_len)
160 {
161 struct mp_prio *mpp = (struct mp_prio *) opt;
162
163 if (mpp->b)
164 printf(" backup");
165 else
166 printf(" non-backup");
167 if (opt_len == 4)
168 printf(" id %" PRIu8, mpp->addr_id);
169
170 return 1;
171 }
172
173 static int mp_fail_print(const u_char *opt, u_int opt_len)
174 {
175 opt += 4;
176 printf(" seq %" PRIu64, EXTRACT_64BITS(opt));
177 }
178
179 static int mp_fast_close_print(const u_char *opt, u_int opt_len)
180 {
181 opt += 4;
182 printf(" key 0x%" PRIx64, *((uint64_t *)opt));
183 }
184
185 static struct {
186 const char *name;
187 int (*print)(const u_char *, u_int);
188 } mptcp_options[] = {
189 { "capable", mp_capable_print },
190 { "join", mp_join_print },
191 { "dss", mp_dss_print },
192 { "add-addr", add_addr_print },
193 { "rem-addr", remove_addr_print },
194 { "prio", mp_prio_print },
195 { "fail", mp_fail_print },
196 { "fast-close", mp_fast_close_print },
197 { "unknown", dummy_print },
198 };
199
200 int mptcp_print(const u_char *cp, u_int len)
201 {
202 struct mptcp_option *opt = (struct mptcp_option *) cp;
203 u_int subtype = min(opt->sub, MPTCP_SUB_FCLOSE + 1);
204
205 printf(" %s", mptcp_options[subtype].name);
206 return mptcp_options[subtype].print(cp, len);
207 }