]> The Tcpdump Group git mirrors - tcpdump/blob - print-sl.c
f714b450540b080e62755d4c174799e2ba54931f
[tcpdump] / print-sl.c
1 /*
2 * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-sl.c,v 1.51 2000-09-28 06:43:08 guy Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #ifdef HAVE_NET_SLIP_H
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/timeb.h>
35 #include <sys/file.h>
36 #include <sys/ioctl.h>
37 #include <sys/mbuf.h>
38 #include <sys/socket.h>
39
40 struct mbuf;
41 struct rtentry;
42
43 #include <netinet/in.h>
44 #include <netinet/in_systm.h>
45
46 #include <ctype.h>
47 #include <netdb.h>
48 #include <pcap.h>
49 #include <stdio.h>
50
51 #include "interface.h"
52 #include "addrtoname.h"
53 #include "extract.h" /* must come after interface.h */
54
55 #include "ip.h"
56 #include "tcp.h"
57
58 #include <net/slcompress.h>
59 #include <net/slip.h>
60
61 static u_int lastlen[2][256];
62 static u_int lastconn = 255;
63
64 static void sliplink_print(const u_char *, const struct ip *, u_int);
65 static void compressed_sl_print(const u_char *, const struct ip *, u_int, int);
66
67 /* XXX BSD/OS 2.1 compatibility */
68 #if !defined(SLIP_HDRLEN) && defined(SLC_BPFHDR)
69 #define SLIP_HDRLEN SLC_BPFHDR
70 #define SLX_DIR 0
71 #define SLX_CHDR (SLC_BPFHDRLEN - 1)
72 #define CHDR_LEN (SLC_BPFHDR - SLC_BPFHDRLEN)
73 #endif
74
75 /* XXX needs more hacking to work right */
76
77 void
78 sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
79 {
80 register u_int caplen = h->caplen;
81 register u_int length = h->len;
82 register const struct ip *ip;
83
84 ts_print(&h->ts);
85
86 if (caplen < SLIP_HDRLEN) {
87 printf("[|slip]");
88 goto out;
89 }
90 /*
91 * Some printers want to get back at the link level addresses,
92 * and/or check that they're not walking off the end of the packet.
93 * Rather than pass them all the way down, we set these globals.
94 */
95 packetp = p;
96 snapend = p + caplen;
97
98 length -= SLIP_HDRLEN;
99
100 ip = (struct ip *)(p + SLIP_HDRLEN);
101
102 if (eflag)
103 sliplink_print(p, ip, length);
104
105 switch (ip->ip_v) {
106 case 4:
107 ip_print((u_char *)ip, length);
108 break;
109 #ifdef INET6
110 case 6:
111 ip6_print((u_char *)ip, length);
112 break;
113 #endif
114 default:
115 printf ("ip v%d", ip->ip_v);
116 }
117
118 if (xflag)
119 default_print((u_char *)ip, caplen - SLIP_HDRLEN);
120 out:
121 putchar('\n');
122 }
123
124
125 void
126 sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
127 {
128 register u_int caplen = h->caplen;
129 register u_int length = h->len;
130 register const struct ip *ip;
131
132 ts_print(&h->ts);
133
134 if (caplen < SLIP_HDRLEN) {
135 printf("[|slip]");
136 goto out;
137 }
138 /*
139 * Some printers want to get back at the link level addresses,
140 * and/or check that they're not walking off the end of the packet.
141 * Rather than pass them all the way down, we set these globals.
142 */
143 packetp = p;
144 snapend = p + caplen;
145
146 length -= SLIP_HDRLEN;
147
148 ip = (struct ip *)(p + SLIP_HDRLEN);
149
150 #ifdef notdef
151 if (eflag)
152 sliplink_print(p, ip, length);
153 #endif
154
155 ip_print((u_char *)ip, length);
156
157 if (xflag)
158 default_print((u_char *)ip, caplen - SLIP_HDRLEN);
159 out:
160 putchar('\n');
161 }
162
163 static void
164 sliplink_print(register const u_char *p, register const struct ip *ip,
165 register u_int length)
166 {
167 int dir;
168 u_int hlen;
169
170 dir = p[SLX_DIR];
171 putchar(dir == SLIPDIR_IN ? 'I' : 'O');
172 putchar(' ');
173
174 if (nflag) {
175 /* XXX just dump the header */
176 register int i;
177
178 for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i)
179 printf("%02x.", p[i]);
180 printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]);
181 return;
182 }
183 switch (p[SLX_CHDR] & 0xf0) {
184
185 case TYPE_IP:
186 printf("ip %d: ", length + SLIP_HDRLEN);
187 break;
188
189 case TYPE_UNCOMPRESSED_TCP:
190 /*
191 * The connection id is stored in the IP protocol field.
192 * Get it from the link layer since sl_uncompress_tcp()
193 * has restored the IP header copy to IPPROTO_TCP.
194 */
195 lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p;
196 hlen = ip->ip_hl;
197 hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off;
198 lastlen[dir][lastconn] = length - (hlen << 2);
199 printf("utcp %d: ", lastconn);
200 break;
201
202 default:
203 if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
204 compressed_sl_print(&p[SLX_CHDR], ip,
205 length, dir);
206 printf(": ");
207 } else
208 printf("slip-%d!: ", p[SLX_CHDR]);
209 }
210 }
211
212 static const u_char *
213 print_sl_change(const char *str, register const u_char *cp)
214 {
215 register u_int i;
216
217 if ((i = *cp++) == 0) {
218 i = EXTRACT_16BITS(cp);
219 cp += 2;
220 }
221 printf(" %s%d", str, i);
222 return (cp);
223 }
224
225 static const u_char *
226 print_sl_winchange(register const u_char *cp)
227 {
228 register short i;
229
230 if ((i = *cp++) == 0) {
231 i = EXTRACT_16BITS(cp);
232 cp += 2;
233 }
234 if (i >= 0)
235 printf(" W+%d", i);
236 else
237 printf(" W%d", i);
238 return (cp);
239 }
240
241 static void
242 compressed_sl_print(const u_char *chdr, const struct ip *ip,
243 u_int length, int dir)
244 {
245 register const u_char *cp = chdr;
246 register u_int flags, hlen;
247
248 flags = *cp++;
249 if (flags & NEW_C) {
250 lastconn = *cp++;
251 printf("ctcp %d", lastconn);
252 } else
253 printf("ctcp *");
254
255 /* skip tcp checksum */
256 cp += 2;
257
258 switch (flags & SPECIALS_MASK) {
259 case SPECIAL_I:
260 printf(" *SA+%d", lastlen[dir][lastconn]);
261 break;
262
263 case SPECIAL_D:
264 printf(" *S+%d", lastlen[dir][lastconn]);
265 break;
266
267 default:
268 if (flags & NEW_U)
269 cp = print_sl_change("U=", cp);
270 if (flags & NEW_W)
271 cp = print_sl_winchange(cp);
272 if (flags & NEW_A)
273 cp = print_sl_change("A+", cp);
274 if (flags & NEW_S)
275 cp = print_sl_change("S+", cp);
276 break;
277 }
278 if (flags & NEW_I)
279 cp = print_sl_change("I+", cp);
280
281 /*
282 * 'hlen' is the length of the uncompressed TCP/IP header (in words).
283 * 'cp - chdr' is the length of the compressed header.
284 * 'length - hlen' is the amount of data in the packet.
285 */
286 hlen = ip->ip_hl;
287 hlen += ((struct tcphdr *)&((int32_t *)ip)[hlen])->th_off;
288 lastlen[dir][lastconn] = length - (hlen << 2);
289 printf(" %d (%d)", lastlen[dir][lastconn], cp - chdr);
290 }
291 #else
292 #include <sys/types.h>
293 #include <sys/time.h>
294
295 #include <pcap.h>
296 #include <stdio.h>
297
298 #include "interface.h"
299
300 void
301 sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
302 {
303
304 error("not configured for slip");
305 /* NOTREACHED */
306 }
307
308 void
309 sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
310 {
311
312 error("not configured for slip");
313 /* NOTREACHED */
314 }
315 #endif