]> The Tcpdump Group git mirrors - tcpdump/blob - print-mptcp.c
Fix some compiler warnings from the previous checkin.
[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 #include "tcp.h"
51
52 static int dummy_print(const u_char *opt _U_, u_int opt_len _U_, u_char flags _U_)
53 {
54 return 1;
55 }
56
57 static int mp_capable_print(const u_char *opt, u_int opt_len, u_char flags)
58 {
59 struct mp_capable *mpc = (struct mp_capable *) opt;
60
61 if (!(opt_len == 12 && flags & TH_SYN) &&
62 !(opt_len == 20 && (flags & (TH_SYN | TH_ACK)) == TH_ACK))
63 return 0;
64
65 if (mpc->ver != 0) {
66 printf(" Unknown Version (%d)", mpc->ver);
67 return 1;
68 }
69
70 if (mpc->c)
71 printf(" csum");
72 printf(" {0x%" PRIx64, EXTRACT_64BITS(&mpc->sender_key));
73 if (opt_len == 20) /* ACK */
74 printf(",0x%" PRIx64, EXTRACT_64BITS(&mpc->receiver_key));
75 printf("}");
76 return 1;
77 }
78
79 static int mp_join_print(const u_char *opt, u_int opt_len, u_char flags)
80 {
81 struct mp_join *mpj = (struct mp_join *) opt;
82
83 if (!(opt_len == 12 && flags & TH_SYN) &&
84 !(opt_len == 16 && (flags & (TH_SYN | TH_ACK)) == (TH_SYN | TH_ACK)) &&
85 !(opt_len == 24 && flags & TH_ACK))
86 return 0;
87
88 if (opt_len != 24) {
89 if (mpj->b)
90 printf(" backup");
91 printf(" id %u", mpj->addr_id);
92 }
93
94 switch (opt_len) {
95 case 12: /* SYN */
96 printf(" token 0x%" PRIx32 " nonce 0x%" PRIx32,
97 EXTRACT_32BITS(&mpj->u.syn.token),
98 EXTRACT_32BITS(&mpj->u.syn.nonce));
99 break;
100 case 16: /* SYN/ACK */
101 printf(" hmac 0x%" PRIx64 " nonce 0x%" PRIx32,
102 EXTRACT_64BITS(&mpj->u.synack.mac),
103 EXTRACT_32BITS(&mpj->u.synack.nonce));
104 break;
105 case 24: {/* ACK */
106 size_t i;
107 printf(" hmac 0x");
108 for (i = 0; i < sizeof(mpj->u.ack.mac); ++i)
109 printf("%02x", mpj->u.ack.mac[i]);
110 }
111 default:
112 break;
113 }
114 return 1;
115 }
116
117 static u_int mp_dss_len(struct mp_dss *m, int csum)
118 {
119 return 4 + m->A * (4 + m->a * 4) + m->M * (10 + m->m * 4 + csum * 2);
120 }
121
122 static int mp_dss_print(const u_char *opt, u_int opt_len, u_char flags)
123 {
124 struct mp_dss *mdss = (struct mp_dss *) opt;
125
126 if ((opt_len != mp_dss_len(mdss, 1) &&
127 opt_len != mp_dss_len(mdss, 0)) || flags & TH_SYN)
128 return 0;
129
130 if (mdss->F)
131 printf(" fin");
132
133 opt += 4;
134 if (mdss->A) {
135 printf(" ack ");
136 if (mdss->a)
137 printf("%" PRIu64, EXTRACT_64BITS(opt));
138 else
139 printf("%" PRIu32, EXTRACT_32BITS(opt));
140 opt += mdss->a ? 8 : 4;
141 }
142
143 if (mdss->M) {
144 printf(" seq ");
145 if (mdss->m)
146 printf("%" PRIu64, EXTRACT_64BITS(opt));
147 else
148 printf("%" PRIu32, EXTRACT_32BITS(opt));
149 opt += mdss->m ? 8 : 4;
150 printf(" subseq %" PRIu32, EXTRACT_32BITS(opt));
151 opt += 4;
152 printf(" len %" PRIu16, EXTRACT_16BITS(opt));
153 opt += 2;
154
155 if (opt_len == mp_dss_len(mdss, 1))
156 printf(" csum 0x%" PRIx16, EXTRACT_16BITS(opt));
157 }
158 return 1;
159 }
160
161 static int add_addr_print(const u_char *opt, u_int opt_len, u_char flags _U_)
162 {
163 struct mp_add_addr *add_addr = (struct mp_add_addr *) opt;
164
165 if (!((opt_len == 8 || opt_len == 10) && add_addr->ipver == 4) &&
166 !((opt_len == 20 || opt_len == 22) && add_addr->ipver == 6))
167 return 0;
168
169 printf(" id %u", add_addr->addr_id);
170 switch (add_addr->ipver) {
171 case 4:
172 printf(" %s", ipaddr_string(&add_addr->u.v4.addr));
173 break;
174 case 6:
175 #ifdef INET6
176 printf(" %s", ip6addr_string(&add_addr->u.v6.addr));
177 #endif
178 break;
179 default:
180 return 0;
181 }
182
183 if (opt_len == 10 || opt_len == 22)
184 printf(":%" PRIu16, ntohs(add_addr->ipver == 4 ?
185 add_addr->u.v4.port :
186 add_addr->u.v6.port));
187 return 1;
188 }
189
190 static int remove_addr_print(const u_char *opt, u_int opt_len, u_char flags _U_)
191 {
192 struct mp_remove_addr *rem_addr = (struct mp_remove_addr *) opt;
193 u_int8_t *addr_id = &rem_addr->addrs_id;
194
195 if (opt_len < 4)
196 return 0;
197
198 opt_len -= 3;
199 printf(" id");
200 while (opt_len--)
201 printf(" %u", *addr_id++);
202 return 1;
203 }
204
205 static int mp_prio_print(const u_char *opt, u_int opt_len, u_char flags _U_)
206 {
207 struct mp_prio *mpp = (struct mp_prio *) opt;
208
209 if (opt_len != 3 && opt_len != 4)
210 return 0;
211
212 if (mpp->b)
213 printf(" backup");
214 else
215 printf(" non-backup");
216 if (opt_len == 4)
217 printf(" id %u", mpp->addr_id);
218
219 return 1;
220 }
221
222 static int mp_fail_print(const u_char *opt, u_int opt_len, u_char flags _U_)
223 {
224 if (opt_len != 12)
225 return 0;
226
227 printf(" seq %" PRIu64, EXTRACT_64BITS(opt + 4));
228 return 1;
229 }
230
231 static int mp_fast_close_print(const u_char *opt, u_int opt_len, u_char flags _U_)
232 {
233 if (opt_len != 12)
234 return 0;
235
236 printf(" key 0x%" PRIx64, EXTRACT_64BITS(opt + 4));
237 return 1;
238 }
239
240 static struct {
241 const char *name;
242 int (*print)(const u_char *, u_int, u_char);
243 } mptcp_options[] = {
244 { "capable", mp_capable_print},
245 { "join", mp_join_print },
246 { "dss", mp_dss_print },
247 { "add-addr", add_addr_print },
248 { "rem-addr", remove_addr_print },
249 { "prio", mp_prio_print },
250 { "fail", mp_fail_print },
251 { "fast-close", mp_fast_close_print },
252 { "unknown", dummy_print },
253 };
254
255 int mptcp_print(const u_char *cp, u_int len, u_char flags)
256 {
257 struct mptcp_option *opt;
258 u_int subtype;
259
260 if (len < 3)
261 return 0;
262
263 opt = (struct mptcp_option *) cp;
264 subtype = min(opt->sub, MPTCP_SUB_FCLOSE + 1);
265
266 printf(" %s", mptcp_options[subtype].name);
267 return mptcp_options[subtype].print(cp, len, flags);
268 }