xref: /freebsd/contrib/tcpdump/print-sl.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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  * $FreeBSD$
22  */
23 
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Header: /tcpdump/master/tcpdump/print-sl.c,v 1.46 1999/11/21 12:38:24 itojun Exp $ (LBL)";
27 #endif
28 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #ifdef HAVE_NET_SLIP_H
34 #include <sys/param.h>
35 #include <sys/time.h>
36 #include <sys/timeb.h>
37 #include <sys/file.h>
38 #include <sys/ioctl.h>
39 #include <sys/mbuf.h>
40 #include <sys/socket.h>
41 
42 #if __STDC__
43 struct rtentry;
44 #endif
45 #include <net/if.h>
46 
47 #include <netinet/in.h>
48 #include <netinet/in_systm.h>
49 #include <netinet/ip.h>
50 #include <net/ethernet.h>
51 #include <netinet/ip_var.h>
52 #include <netinet/udp.h>
53 #include <netinet/tcp.h>
54 
55 #include <net/slcompress.h>
56 #include <net/slip.h>
57 
58 #include <ctype.h>
59 #include <netdb.h>
60 #include <pcap.h>
61 #include <stdio.h>
62 
63 #include "interface.h"
64 #include "addrtoname.h"
65 #include "extract.h"			/* must come after interface.h */
66 
67 static u_int lastlen[2][256];
68 static u_int lastconn = 255;
69 
70 static void sliplink_print(const u_char *, const struct ip *, u_int);
71 static void compressed_sl_print(const u_char *, const struct ip *, u_int, int);
72 
73 /* XXX BSD/OS 2.1 compatibility */
74 #if !defined(SLIP_HDRLEN) && defined(SLC_BPFHDR)
75 #define SLIP_HDRLEN SLC_BPFHDR
76 #define SLX_DIR 0
77 #define SLX_CHDR (SLC_BPFHDRLEN - 1)
78 #define CHDR_LEN (SLC_BPFHDR - SLC_BPFHDRLEN)
79 #endif
80 
81 /* XXX needs more hacking to work right */
82 
83 void
84 sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
85 {
86 	register u_int caplen = h->caplen;
87 	register u_int length = h->len;
88 	register const struct ip *ip;
89 
90 	ts_print(&h->ts);
91 
92 	if (caplen < SLIP_HDRLEN) {
93 		printf("[|slip]");
94 		goto out;
95 	}
96 	/*
97 	 * Some printers want to get back at the link level addresses,
98 	 * and/or check that they're not walking off the end of the packet.
99 	 * Rather than pass them all the way down, we set these globals.
100 	 */
101 	packetp = p;
102 	snapend = p + caplen;
103 
104 	length -= SLIP_HDRLEN;
105 
106 	ip = (struct ip *)(p + SLIP_HDRLEN);
107 
108 	if (eflag)
109 		sliplink_print(p, ip, length);
110 
111 	switch (ip->ip_v) {
112 	case 4:
113 		ip_print((u_char *)ip, length);
114 		break;
115 #ifdef INET6
116 	case 6:
117 		ip6_print((u_char *)ip, length);
118 		break;
119 #endif
120 	default:
121 		printf ("ip v%d", ip->ip_v);
122 	}
123 
124 	if (xflag)
125 		default_print((u_char *)ip, caplen - SLIP_HDRLEN);
126  out:
127 	putchar('\n');
128 }
129 
130 
131 void
132 sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
133 {
134 	register u_int caplen = h->caplen;
135 	register u_int length = h->len;
136 	register const struct ip *ip;
137 
138 	ts_print(&h->ts);
139 
140 	if (caplen < SLIP_HDRLEN) {
141 		printf("[|slip]");
142 		goto out;
143 	}
144 	/*
145 	 * Some printers want to get back at the link level addresses,
146 	 * and/or check that they're not walking off the end of the packet.
147 	 * Rather than pass them all the way down, we set these globals.
148 	 */
149 	packetp = p;
150 	snapend = p + caplen;
151 
152 	length -= SLIP_HDRLEN;
153 
154 	ip = (struct ip *)(p + SLIP_HDRLEN);
155 
156 #ifdef notdef
157 	if (eflag)
158 		sliplink_print(p, ip, length);
159 #endif
160 
161 	ip_print((u_char *)ip, length);
162 
163 	if (xflag)
164 		default_print((u_char *)ip, caplen - SLIP_HDRLEN);
165  out:
166 	putchar('\n');
167 }
168 
169 static void
170 sliplink_print(register const u_char *p, register const struct ip *ip,
171 	       register u_int length)
172 {
173 	int dir;
174 	u_int hlen;
175 
176 	dir = p[SLX_DIR];
177 	putchar(dir == SLIPDIR_IN ? 'I' : 'O');
178 	putchar(' ');
179 
180 	if (nflag) {
181 		/* XXX just dump the header */
182 		register int i;
183 
184 		for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i)
185 			printf("%02x.", p[i]);
186 		printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]);
187 		return;
188 	}
189 	switch (p[SLX_CHDR] & 0xf0) {
190 
191 	case TYPE_IP:
192 		printf("ip %d: ", length + SLIP_HDRLEN);
193 		break;
194 
195 	case TYPE_UNCOMPRESSED_TCP:
196 		/*
197 		 * The connection id is stored in the IP protocol field.
198 		 * Get it from the link layer since sl_uncompress_tcp()
199 		 * has restored the IP header copy to IPPROTO_TCP.
200 		 */
201 		lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p;
202 		hlen = ip->ip_hl;
203 		hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off;
204 		lastlen[dir][lastconn] = length - (hlen << 2);
205 		printf("utcp %d: ", lastconn);
206 		break;
207 
208 	default:
209 		if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
210 			compressed_sl_print(&p[SLX_CHDR], ip,
211 			    length, dir);
212 			printf(": ");
213 		} else
214 			printf("slip-%d!: ", p[SLX_CHDR]);
215 	}
216 }
217 
218 static const u_char *
219 print_sl_change(const char *str, register const u_char *cp)
220 {
221 	register u_int i;
222 
223 	if ((i = *cp++) == 0) {
224 		i = EXTRACT_16BITS(cp);
225 		cp += 2;
226 	}
227 	printf(" %s%d", str, i);
228 	return (cp);
229 }
230 
231 static const u_char *
232 print_sl_winchange(register const u_char *cp)
233 {
234 	register short i;
235 
236 	if ((i = *cp++) == 0) {
237 		i = EXTRACT_16BITS(cp);
238 		cp += 2;
239 	}
240 	if (i >= 0)
241 		printf(" W+%d", i);
242 	else
243 		printf(" W%d", i);
244 	return (cp);
245 }
246 
247 static void
248 compressed_sl_print(const u_char *chdr, const struct ip *ip,
249 		    u_int length, int dir)
250 {
251 	register const u_char *cp = chdr;
252 	register u_int flags, hlen;
253 
254 	flags = *cp++;
255 	if (flags & NEW_C) {
256 		lastconn = *cp++;
257 		printf("ctcp %d", lastconn);
258 	} else
259 		printf("ctcp *");
260 
261 	/* skip tcp checksum */
262 	cp += 2;
263 
264 	switch (flags & SPECIALS_MASK) {
265 	case SPECIAL_I:
266 		printf(" *SA+%d", lastlen[dir][lastconn]);
267 		break;
268 
269 	case SPECIAL_D:
270 		printf(" *S+%d", lastlen[dir][lastconn]);
271 		break;
272 
273 	default:
274 		if (flags & NEW_U)
275 			cp = print_sl_change("U=", cp);
276 		if (flags & NEW_W)
277 			cp = print_sl_winchange(cp);
278 		if (flags & NEW_A)
279 			cp = print_sl_change("A+", cp);
280 		if (flags & NEW_S)
281 			cp = print_sl_change("S+", cp);
282 		break;
283 	}
284 	if (flags & NEW_I)
285 		cp = print_sl_change("I+", cp);
286 
287 	/*
288 	 * 'hlen' is the length of the uncompressed TCP/IP header (in words).
289 	 * 'cp - chdr' is the length of the compressed header.
290 	 * 'length - hlen' is the amount of data in the packet.
291 	 */
292 	hlen = ip->ip_hl;
293 	hlen += ((struct tcphdr *)&((int32_t *)ip)[hlen])->th_off;
294 	lastlen[dir][lastconn] = length - (hlen << 2);
295 	printf(" %d (%d)", lastlen[dir][lastconn], cp - chdr);
296 }
297 #else
298 #include <sys/types.h>
299 #include <sys/time.h>
300 
301 #include <pcap.h>
302 #include <stdio.h>
303 
304 #include "interface.h"
305 
306 void
307 sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
308 {
309 
310 	error("not configured for slip");
311 	/* NOTREACHED */
312 }
313 
314 void
315 sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
316 {
317 
318 	error("not configured for slip");
319 	/* NOTREACHED */
320 }
321 #endif
322