print-sl.c revision 1.1.1.10 1 1.1 christos /*
2 1.1 christos * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997
3 1.1 christos * The Regents of the University of California. All rights reserved.
4 1.1 christos *
5 1.1 christos * Redistribution and use in source and binary forms, with or without
6 1.1 christos * modification, are permitted provided that: (1) source code distributions
7 1.1 christos * retain the above copyright notice and this paragraph in its entirety, (2)
8 1.1 christos * distributions including binary code include the above copyright notice and
9 1.1 christos * this paragraph in its entirety in the documentation or other materials
10 1.1 christos * provided with the distribution, and (3) all advertising materials mentioning
11 1.1 christos * features or use of this software display the following acknowledgement:
12 1.1 christos * ``This product includes software developed by the University of California,
13 1.1 christos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 1.1 christos * the University nor the names of its contributors may be used to endorse
15 1.1 christos * or promote products derived from this software without specific prior
16 1.1 christos * written permission.
17 1.1 christos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 1.1 christos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 1.1 christos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 1.1 christos */
21 1.1 christos
22 1.1.1.6 spz /* \summary: Compressed Serial Line Internet Protocol printer */
23 1.1.1.6 spz
24 1.1.1.9 christos #include <config.h>
25 1.1 christos
26 1.1.1.9 christos #include "netdissect-stdinc.h"
27 1.1 christos
28 1.1.1.9 christos #define ND_LONGJMP_FROM_TCHECK
29 1.1.1.5 christos #include "netdissect.h"
30 1.1.1.5 christos #include "extract.h"
31 1.1 christos
32 1.1 christos #include "ip.h"
33 1.1 christos #include "tcp.h"
34 1.1 christos #include "slcompress.h"
35 1.1 christos
36 1.1.1.3 christos /*
37 1.1.1.3 christos * definitions of the pseudo- link-level header attached to slip
38 1.1.1.3 christos * packets grabbed by the packet filter (bpf) traffic monitor.
39 1.1.1.3 christos */
40 1.1.1.3 christos #define SLIP_HDRLEN 16
41 1.1.1.3 christos
42 1.1.1.3 christos #define SLX_DIR 0
43 1.1.1.3 christos #define SLX_CHDR 1
44 1.1.1.3 christos
45 1.1.1.3 christos #define SLIPDIR_IN 0
46 1.1.1.3 christos #define SLIPDIR_OUT 1
47 1.1.1.3 christos
48 1.1.1.3 christos
49 1.1 christos static u_int lastlen[2][256];
50 1.1 christos static u_int lastconn = 255;
51 1.1 christos
52 1.1.1.9 christos static void sliplink_print(netdissect_options *, const u_char *, const struct ip *, u_int);
53 1.1.1.9 christos static void compressed_sl_print(netdissect_options *, const u_char *, const struct ip *, u_int, int);
54 1.1 christos
55 1.1.1.9 christos void
56 1.1.1.3 christos sl_if_print(netdissect_options *ndo,
57 1.1.1.3 christos const struct pcap_pkthdr *h, const u_char *p)
58 1.1 christos {
59 1.1.1.9 christos u_int length = h->len;
60 1.1.1.9 christos const struct ip *ip;
61 1.1.1.9 christos
62 1.1.1.9 christos ndo->ndo_protocol = "slip";
63 1.1.1.9 christos ND_TCHECK_LEN(p, SLIP_HDRLEN);
64 1.1.1.9 christos ndo->ndo_ll_hdr_len += SLIP_HDRLEN;
65 1.1 christos
66 1.1 christos length -= SLIP_HDRLEN;
67 1.1 christos
68 1.1.1.5 christos ip = (const struct ip *)(p + SLIP_HDRLEN);
69 1.1 christos
70 1.1.1.3 christos if (ndo->ndo_eflag)
71 1.1.1.9 christos sliplink_print(ndo, p, ip, length);
72 1.1.1.6 spz
73 1.1 christos switch (IP_V(ip)) {
74 1.1 christos case 4:
75 1.1.1.5 christos ip_print(ndo, (const u_char *)ip, length);
76 1.1 christos break;
77 1.1 christos case 6:
78 1.1.1.5 christos ip6_print(ndo, (const u_char *)ip, length);
79 1.1 christos break;
80 1.1 christos default:
81 1.1.1.9 christos ND_PRINT("ip v%u", IP_V(ip));
82 1.1 christos }
83 1.1 christos }
84 1.1 christos
85 1.1.1.9 christos void
86 1.1.1.3 christos sl_bsdos_if_print(netdissect_options *ndo,
87 1.1.1.3 christos const struct pcap_pkthdr *h, const u_char *p)
88 1.1 christos {
89 1.1.1.9 christos u_int length = h->len;
90 1.1.1.9 christos const struct ip *ip;
91 1.1.1.9 christos
92 1.1.1.9 christos ndo->ndo_protocol = "slip_bsdos";
93 1.1.1.9 christos ND_TCHECK_LEN(p, SLIP_HDRLEN);
94 1.1.1.9 christos ndo->ndo_ll_hdr_len += SLIP_HDRLEN;
95 1.1 christos
96 1.1 christos length -= SLIP_HDRLEN;
97 1.1 christos
98 1.1.1.5 christos ip = (const struct ip *)(p + SLIP_HDRLEN);
99 1.1 christos
100 1.1 christos #ifdef notdef
101 1.1.1.3 christos if (ndo->ndo_eflag)
102 1.1.1.3 christos sliplink_print(ndo, p, ip, length);
103 1.1 christos #endif
104 1.1 christos
105 1.1.1.5 christos ip_print(ndo, (const u_char *)ip, length);
106 1.1 christos }
107 1.1 christos
108 1.1.1.9 christos static void
109 1.1.1.3 christos sliplink_print(netdissect_options *ndo,
110 1.1.1.9 christos const u_char *p, const struct ip *ip,
111 1.1.1.9 christos u_int length)
112 1.1 christos {
113 1.1 christos int dir;
114 1.1 christos u_int hlen;
115 1.1 christos
116 1.1.1.9 christos dir = GET_U_1(p + SLX_DIR);
117 1.1.1.7 christos switch (dir) {
118 1.1 christos
119 1.1.1.7 christos case SLIPDIR_IN:
120 1.1.1.9 christos ND_PRINT("I ");
121 1.1.1.7 christos break;
122 1.1.1.7 christos
123 1.1.1.7 christos case SLIPDIR_OUT:
124 1.1.1.9 christos ND_PRINT("O ");
125 1.1.1.7 christos break;
126 1.1.1.7 christos
127 1.1.1.7 christos default:
128 1.1.1.9 christos ND_PRINT("Invalid direction %d ", dir);
129 1.1.1.7 christos dir = -1;
130 1.1.1.7 christos break;
131 1.1.1.7 christos }
132 1.1.1.9 christos switch (GET_U_1(p + SLX_CHDR) & 0xf0) {
133 1.1 christos
134 1.1 christos case TYPE_IP:
135 1.1.1.9 christos ND_PRINT("ip %u: ", length + SLIP_HDRLEN);
136 1.1 christos break;
137 1.1 christos
138 1.1 christos case TYPE_UNCOMPRESSED_TCP:
139 1.1 christos /*
140 1.1 christos * The connection id is stored in the IP protocol field.
141 1.1 christos * Get it from the link layer since sl_uncompress_tcp()
142 1.1 christos * has restored the IP header copy to IPPROTO_TCP.
143 1.1 christos */
144 1.1.1.9 christos lastconn = GET_U_1(((const struct ip *)(p + SLX_CHDR))->ip_p);
145 1.1.1.9 christos ND_PRINT("utcp %u: ", lastconn);
146 1.1.1.7 christos if (dir == -1) {
147 1.1.1.7 christos /* Direction is bogus, don't use it */
148 1.1.1.9 christos return;
149 1.1.1.7 christos }
150 1.1.1.9 christos ND_TCHECK_SIZE(ip);
151 1.1 christos hlen = IP_HL(ip);
152 1.1.1.9 christos ND_TCHECK_SIZE((const struct tcphdr *)&((const int *)ip)[hlen]);
153 1.1.1.5 christos hlen += TH_OFF((const struct tcphdr *)&((const int *)ip)[hlen]);
154 1.1 christos lastlen[dir][lastconn] = length - (hlen << 2);
155 1.1 christos break;
156 1.1 christos
157 1.1 christos default:
158 1.1.1.7 christos if (dir == -1) {
159 1.1.1.7 christos /* Direction is bogus, don't use it */
160 1.1.1.9 christos return;
161 1.1.1.7 christos }
162 1.1.1.9 christos if (GET_U_1(p + SLX_CHDR) & TYPE_COMPRESSED_TCP) {
163 1.1.1.9 christos compressed_sl_print(ndo, p + SLX_CHDR, ip, length, dir);
164 1.1.1.9 christos ND_PRINT(": ");
165 1.1 christos } else
166 1.1.1.9 christos ND_PRINT("slip-%u!: ", GET_U_1(p + SLX_CHDR));
167 1.1 christos }
168 1.1 christos }
169 1.1 christos
170 1.1 christos static const u_char *
171 1.1.1.3 christos print_sl_change(netdissect_options *ndo,
172 1.1.1.9 christos const char *str, const u_char *cp)
173 1.1 christos {
174 1.1.1.9 christos u_int i;
175 1.1 christos
176 1.1.1.9 christos if ((i = GET_U_1(cp)) == 0) {
177 1.1.1.9 christos cp++;
178 1.1.1.9 christos i = GET_BE_U_2(cp);
179 1.1 christos cp += 2;
180 1.1 christos }
181 1.1.1.9 christos ND_PRINT(" %s%u", str, i);
182 1.1 christos return (cp);
183 1.1 christos }
184 1.1 christos
185 1.1 christos static const u_char *
186 1.1.1.3 christos print_sl_winchange(netdissect_options *ndo,
187 1.1.1.9 christos const u_char *cp)
188 1.1 christos {
189 1.1.1.9 christos int16_t i;
190 1.1 christos
191 1.1.1.9 christos if ((i = GET_U_1(cp)) == 0) {
192 1.1.1.9 christos cp++;
193 1.1.1.9 christos i = GET_BE_S_2(cp);
194 1.1 christos cp += 2;
195 1.1 christos }
196 1.1 christos if (i >= 0)
197 1.1.1.9 christos ND_PRINT(" W+%d", i);
198 1.1 christos else
199 1.1.1.9 christos ND_PRINT(" W%d", i);
200 1.1 christos return (cp);
201 1.1 christos }
202 1.1 christos
203 1.1.1.9 christos static void
204 1.1.1.3 christos compressed_sl_print(netdissect_options *ndo,
205 1.1.1.3 christos const u_char *chdr, const struct ip *ip,
206 1.1.1.3 christos u_int length, int dir)
207 1.1 christos {
208 1.1.1.9 christos const u_char *cp = chdr;
209 1.1.1.9 christos u_int flags, hlen;
210 1.1 christos
211 1.1.1.9 christos flags = GET_U_1(cp);
212 1.1.1.9 christos cp++;
213 1.1 christos if (flags & NEW_C) {
214 1.1.1.9 christos lastconn = GET_U_1(cp);
215 1.1.1.9 christos cp++;
216 1.1.1.9 christos ND_PRINT("ctcp %u", lastconn);
217 1.1 christos } else
218 1.1.1.9 christos ND_PRINT("ctcp *");
219 1.1 christos
220 1.1 christos /* skip tcp checksum */
221 1.1 christos cp += 2;
222 1.1 christos
223 1.1 christos switch (flags & SPECIALS_MASK) {
224 1.1 christos case SPECIAL_I:
225 1.1.1.9 christos ND_PRINT(" *SA+%u", lastlen[dir][lastconn]);
226 1.1 christos break;
227 1.1 christos
228 1.1 christos case SPECIAL_D:
229 1.1.1.9 christos ND_PRINT(" *S+%u", lastlen[dir][lastconn]);
230 1.1 christos break;
231 1.1 christos
232 1.1 christos default:
233 1.1 christos if (flags & NEW_U)
234 1.1.1.3 christos cp = print_sl_change(ndo, "U=", cp);
235 1.1 christos if (flags & NEW_W)
236 1.1.1.3 christos cp = print_sl_winchange(ndo, cp);
237 1.1 christos if (flags & NEW_A)
238 1.1.1.3 christos cp = print_sl_change(ndo, "A+", cp);
239 1.1 christos if (flags & NEW_S)
240 1.1.1.3 christos cp = print_sl_change(ndo, "S+", cp);
241 1.1 christos break;
242 1.1 christos }
243 1.1 christos if (flags & NEW_I)
244 1.1.1.3 christos cp = print_sl_change(ndo, "I+", cp);
245 1.1 christos
246 1.1 christos /*
247 1.1 christos * 'hlen' is the length of the uncompressed TCP/IP header (in words).
248 1.1 christos * 'cp - chdr' is the length of the compressed header.
249 1.1 christos * 'length - hlen' is the amount of data in the packet.
250 1.1 christos */
251 1.1.1.9 christos ND_TCHECK_SIZE(ip);
252 1.1 christos hlen = IP_HL(ip);
253 1.1.1.9 christos ND_TCHECK_SIZE((const struct tcphdr *)&((const int32_t *)ip)[hlen]);
254 1.1.1.5 christos hlen += TH_OFF((const struct tcphdr *)&((const int32_t *)ip)[hlen]);
255 1.1 christos lastlen[dir][lastconn] = length - (hlen << 2);
256 1.1.1.9 christos ND_PRINT(" %u (%ld)", lastlen[dir][lastconn], (long)(cp - chdr));
257 1.1 christos }
258