Line data Source code
1 : /*
2 : * Copyright (c) 2015-2019 Cisco and/or its affiliates.
3 : * Licensed under the Apache License, Version 2.0 (the "License");
4 : * you may not use this file except in compliance with the License.
5 : * You may obtain a copy of the License at:
6 : *
7 : * http://www.apache.org/licenses/LICENSE-2.0
8 : *
9 : * Unless required by applicable law or agreed to in writing, software
10 : * distributed under the License is distributed on an "AS IS" BASIS,
11 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : * See the License for the specific language governing permissions and
13 : * limitations under the License.
14 : */
15 : /*
16 : * tcp/tcp_format.c: tcp formatting
17 : *
18 : * Copyright (c) 2008 Eliot Dresselhaus
19 : *
20 : * Permission is hereby granted, free of charge, to any person obtaining
21 : * a copy of this software and associated documentation files (the
22 : * "Software"), to deal in the Software without restriction, including
23 : * without limitation the rights to use, copy, modify, merge, publish,
24 : * distribute, sublicense, and/or sell copies of the Software, and to
25 : * permit persons to whom the Software is furnished to do so, subject to
26 : * the following conditions:
27 : *
28 : * The above copyright notice and this permission notice shall be
29 : * included in all copies or substantial portions of the Software.
30 : *
31 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
32 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
33 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
34 : * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
35 : * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
36 : * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
37 : * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
38 : */
39 :
40 : #include <vnet/ip/ip.h>
41 : #include <vnet/tcp/tcp.h>
42 :
43 : u8 *
44 17982 : format_tcp_flags (u8 * s, va_list * args)
45 : {
46 17982 : int flags = va_arg (*args, int);
47 :
48 17982 : s = format (s, "0x%02x", flags);
49 : #define _(f) if (flags & TCP_FLAG_##f) s = format (s, " %s", #f);
50 17982 : foreach_tcp_flag
51 : #undef _
52 17982 : return s;
53 : }
54 :
55 : u8 *
56 17982 : format_tcp_options (u8 *s, va_list *args)
57 : {
58 17982 : tcp_options_t *opts = va_arg (*args, tcp_options_t *);
59 17982 : u32 indent, n_opts = 0;
60 : int i;
61 :
62 17982 : if (!opts->flags)
63 15453 : return s;
64 :
65 2529 : indent = format_get_indent (s);
66 2529 : indent += 2;
67 :
68 2529 : s = format (s, "options:\n%U", format_white_space, indent);
69 :
70 2529 : if (tcp_opts_mss (opts))
71 : {
72 2529 : s = format (s, "mss %d", opts->mss);
73 2529 : n_opts++;
74 : }
75 2529 : if (tcp_opts_wscale (opts))
76 : {
77 0 : s = format (s, "%swindow scale %d", n_opts > 0 ? ", " : "",
78 0 : format_white_space, indent, opts->wscale);
79 0 : n_opts++;
80 : }
81 2529 : if (tcp_opts_tstamp (opts))
82 : {
83 0 : s = format (s, "%stimestamp %d, echo/reflected timestamp",
84 : n_opts > 0 ? ", " : "", format_white_space, indent,
85 : opts->tsval, opts->tsecr);
86 0 : n_opts++;
87 : }
88 2529 : if (tcp_opts_sack_permitted (opts))
89 : {
90 0 : s = format (s, "%ssack permitted", n_opts > 0 ? ", " : "",
91 : format_white_space, indent);
92 0 : n_opts++;
93 : }
94 2529 : if (tcp_opts_sack (opts))
95 : {
96 0 : s = format (s, "%ssacks:", n_opts > 0 ? ", " : "", format_white_space,
97 : indent);
98 0 : for (i = 0; i < opts->n_sack_blocks; ++i)
99 : {
100 0 : s = format (s, "\n%Ublock %d: start %d, end %d", format_white_space,
101 0 : indent + 2, i + 1, opts->sacks[i].start,
102 0 : opts->sacks[i].end);
103 : }
104 0 : n_opts++;
105 : }
106 :
107 2529 : return s;
108 : }
109 :
110 : /* Format TCP header. */
111 : u8 *
112 17982 : format_tcp_header (u8 * s, va_list * args)
113 : {
114 17982 : tcp_header_t *tcp = va_arg (*args, tcp_header_t *);
115 17982 : u32 max_header_bytes = va_arg (*args, u32);
116 17982 : tcp_options_t opts = { .flags = 0 };
117 : u32 header_bytes;
118 : u32 indent;
119 :
120 : /* Nothing to do. */
121 17982 : if (max_header_bytes < sizeof (tcp[0]))
122 0 : return format (s, "TCP header truncated");
123 :
124 17982 : indent = format_get_indent (s);
125 17982 : indent += 2;
126 17982 : header_bytes = tcp_header_bytes (tcp);
127 :
128 17982 : s = format (s, "TCP: %d -> %d", clib_net_to_host_u16 (tcp->src),
129 17982 : clib_net_to_host_u16 (tcp->dst));
130 :
131 17982 : s = format (s, "\n%Useq. 0x%08x ack 0x%08x", format_white_space, indent,
132 : clib_net_to_host_u32 (tcp->seq_number),
133 : clib_net_to_host_u32 (tcp->ack_number));
134 :
135 17982 : s = format (s, "\n%Uflags %U, tcp header: %d bytes", format_white_space,
136 17982 : indent, format_tcp_flags, tcp->flags, header_bytes);
137 :
138 17982 : s = format (s, "\n%Uwindow %d, checksum 0x%04x", format_white_space, indent,
139 17982 : clib_net_to_host_u16 (tcp->window),
140 17982 : clib_net_to_host_u16 (tcp->checksum));
141 :
142 17982 : if (tcp_options_parse (tcp, &opts, tcp_is_syn (tcp)) < 0)
143 0 : s = format (s, "\n%Uoptions: parsing failed", format_white_space, indent);
144 : else
145 17982 : s = format (s, "\n%U%U", format_white_space, indent, format_tcp_options,
146 : &opts);
147 :
148 : /* Recurse into next protocol layer. */
149 17982 : if (max_header_bytes != 0 && header_bytes < max_header_bytes)
150 : {
151 17982 : ip_main_t *im = &ip_main;
152 : tcp_udp_port_info_t *pi;
153 :
154 17982 : pi = ip_get_tcp_udp_port_info (im, tcp->dst);
155 :
156 17982 : if (pi && pi->format_header)
157 0 : s = format (s, "\n%U%U", format_white_space, indent - 2,
158 : pi->format_header,
159 : /* next protocol header */ (void *) tcp + header_bytes,
160 : max_header_bytes - header_bytes);
161 : }
162 :
163 17982 : return s;
164 : }
165 :
166 : /*
167 : * fd.io coding-style-patch-verification: ON
168 : *
169 : * Local Variables:
170 : * eval: (c-set-style "gnu")
171 : * End:
172 : */
|