xref: /freebsd/contrib/tcpdump/print-sl.c (revision a88113a83091fa398943e3c86bacb00932e947bf)
14edb46e9SPaul Traina /*
2699fc314SBill Fenner  * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997
34edb46e9SPaul Traina  *	The Regents of the University of California.  All rights reserved.
44edb46e9SPaul Traina  *
54edb46e9SPaul Traina  * Redistribution and use in source and binary forms, with or without
64edb46e9SPaul Traina  * modification, are permitted provided that: (1) source code distributions
74edb46e9SPaul Traina  * retain the above copyright notice and this paragraph in its entirety, (2)
84edb46e9SPaul Traina  * distributions including binary code include the above copyright notice and
94edb46e9SPaul Traina  * this paragraph in its entirety in the documentation or other materials
104edb46e9SPaul Traina  * provided with the distribution, and (3) all advertising materials mentioning
114edb46e9SPaul Traina  * features or use of this software display the following acknowledgement:
124edb46e9SPaul Traina  * ``This product includes software developed by the University of California,
134edb46e9SPaul Traina  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
144edb46e9SPaul Traina  * the University nor the names of its contributors may be used to endorse
154edb46e9SPaul Traina  * or promote products derived from this software without specific prior
164edb46e9SPaul Traina  * written permission.
174edb46e9SPaul Traina  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
184edb46e9SPaul Traina  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
194edb46e9SPaul Traina  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20a88113a8SBill Fenner  *
21a88113a8SBill Fenner  * $FreeBSD$
224edb46e9SPaul Traina  */
234edb46e9SPaul Traina 
244edb46e9SPaul Traina #ifndef lint
252ebf6c05SBill Fenner static const char rcsid[] =
26a88113a8SBill Fenner     "@(#) $Header: /tcpdump/master/tcpdump/print-sl.c,v 1.46 1999/11/21 12:38:24 itojun Exp $ (LBL)";
27a88113a8SBill Fenner #endif
28a88113a8SBill Fenner 
29a88113a8SBill Fenner #ifdef HAVE_CONFIG_H
30a88113a8SBill Fenner #include "config.h"
314edb46e9SPaul Traina #endif
324edb46e9SPaul Traina 
334edb46e9SPaul Traina #ifdef HAVE_NET_SLIP_H
344edb46e9SPaul Traina #include <sys/param.h>
354edb46e9SPaul Traina #include <sys/time.h>
364edb46e9SPaul Traina #include <sys/timeb.h>
374edb46e9SPaul Traina #include <sys/file.h>
384edb46e9SPaul Traina #include <sys/ioctl.h>
394edb46e9SPaul Traina #include <sys/mbuf.h>
404edb46e9SPaul Traina #include <sys/socket.h>
414edb46e9SPaul Traina 
424edb46e9SPaul Traina #if __STDC__
434edb46e9SPaul Traina struct rtentry;
444edb46e9SPaul Traina #endif
454edb46e9SPaul Traina #include <net/if.h>
464edb46e9SPaul Traina 
474edb46e9SPaul Traina #include <netinet/in.h>
484edb46e9SPaul Traina #include <netinet/in_systm.h>
494edb46e9SPaul Traina #include <netinet/ip.h>
50ee3e7633SGarrett Wollman #include <net/ethernet.h>
514edb46e9SPaul Traina #include <netinet/ip_var.h>
524edb46e9SPaul Traina #include <netinet/udp.h>
534edb46e9SPaul Traina #include <netinet/tcp.h>
544edb46e9SPaul Traina 
554edb46e9SPaul Traina #include <net/slcompress.h>
564edb46e9SPaul Traina #include <net/slip.h>
574edb46e9SPaul Traina 
584edb46e9SPaul Traina #include <ctype.h>
594edb46e9SPaul Traina #include <netdb.h>
604edb46e9SPaul Traina #include <pcap.h>
614edb46e9SPaul Traina #include <stdio.h>
624edb46e9SPaul Traina 
634edb46e9SPaul Traina #include "interface.h"
644edb46e9SPaul Traina #include "addrtoname.h"
654edb46e9SPaul Traina #include "extract.h"			/* must come after interface.h */
664edb46e9SPaul Traina 
674edb46e9SPaul Traina static u_int lastlen[2][256];
684edb46e9SPaul Traina static u_int lastconn = 255;
694edb46e9SPaul Traina 
704edb46e9SPaul Traina static void sliplink_print(const u_char *, const struct ip *, u_int);
714edb46e9SPaul Traina static void compressed_sl_print(const u_char *, const struct ip *, u_int, int);
724edb46e9SPaul Traina 
734edb46e9SPaul Traina /* XXX BSD/OS 2.1 compatibility */
744edb46e9SPaul Traina #if !defined(SLIP_HDRLEN) && defined(SLC_BPFHDR)
754edb46e9SPaul Traina #define SLIP_HDRLEN SLC_BPFHDR
764edb46e9SPaul Traina #define SLX_DIR 0
774edb46e9SPaul Traina #define SLX_CHDR (SLC_BPFHDRLEN - 1)
784edb46e9SPaul Traina #define CHDR_LEN (SLC_BPFHDR - SLC_BPFHDRLEN)
794edb46e9SPaul Traina #endif
804edb46e9SPaul Traina 
81699fc314SBill Fenner /* XXX needs more hacking to work right */
82699fc314SBill Fenner 
834edb46e9SPaul Traina void
844edb46e9SPaul Traina sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
854edb46e9SPaul Traina {
864edb46e9SPaul Traina 	register u_int caplen = h->caplen;
874edb46e9SPaul Traina 	register u_int length = h->len;
884edb46e9SPaul Traina 	register const struct ip *ip;
894edb46e9SPaul Traina 
904edb46e9SPaul Traina 	ts_print(&h->ts);
914edb46e9SPaul Traina 
924edb46e9SPaul Traina 	if (caplen < SLIP_HDRLEN) {
934edb46e9SPaul Traina 		printf("[|slip]");
944edb46e9SPaul Traina 		goto out;
954edb46e9SPaul Traina 	}
964edb46e9SPaul Traina 	/*
974edb46e9SPaul Traina 	 * Some printers want to get back at the link level addresses,
984edb46e9SPaul Traina 	 * and/or check that they're not walking off the end of the packet.
994edb46e9SPaul Traina 	 * Rather than pass them all the way down, we set these globals.
1004edb46e9SPaul Traina 	 */
1014edb46e9SPaul Traina 	packetp = p;
1024edb46e9SPaul Traina 	snapend = p + caplen;
1034edb46e9SPaul Traina 
1044edb46e9SPaul Traina 	length -= SLIP_HDRLEN;
1054edb46e9SPaul Traina 
1064edb46e9SPaul Traina 	ip = (struct ip *)(p + SLIP_HDRLEN);
1074edb46e9SPaul Traina 
1084edb46e9SPaul Traina 	if (eflag)
1094edb46e9SPaul Traina 		sliplink_print(p, ip, length);
1104edb46e9SPaul Traina 
111a88113a8SBill Fenner 	switch (ip->ip_v) {
112a88113a8SBill Fenner 	case 4:
1134edb46e9SPaul Traina 		ip_print((u_char *)ip, length);
114a88113a8SBill Fenner 		break;
115a88113a8SBill Fenner #ifdef INET6
116a88113a8SBill Fenner 	case 6:
117a88113a8SBill Fenner 		ip6_print((u_char *)ip, length);
118a88113a8SBill Fenner 		break;
119a88113a8SBill Fenner #endif
120a88113a8SBill Fenner 	default:
121a88113a8SBill Fenner 		printf ("ip v%d", ip->ip_v);
122a88113a8SBill Fenner 	}
1234edb46e9SPaul Traina 
1244edb46e9SPaul Traina 	if (xflag)
1254edb46e9SPaul Traina 		default_print((u_char *)ip, caplen - SLIP_HDRLEN);
1264edb46e9SPaul Traina  out:
1274edb46e9SPaul Traina 	putchar('\n');
1284edb46e9SPaul Traina }
1294edb46e9SPaul Traina 
130699fc314SBill Fenner 
131699fc314SBill Fenner void
132699fc314SBill Fenner sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
133699fc314SBill Fenner {
134699fc314SBill Fenner 	register u_int caplen = h->caplen;
135699fc314SBill Fenner 	register u_int length = h->len;
136699fc314SBill Fenner 	register const struct ip *ip;
137699fc314SBill Fenner 
138699fc314SBill Fenner 	ts_print(&h->ts);
139699fc314SBill Fenner 
140699fc314SBill Fenner 	if (caplen < SLIP_HDRLEN) {
141699fc314SBill Fenner 		printf("[|slip]");
142699fc314SBill Fenner 		goto out;
143699fc314SBill Fenner 	}
144699fc314SBill Fenner 	/*
145699fc314SBill Fenner 	 * Some printers want to get back at the link level addresses,
146699fc314SBill Fenner 	 * and/or check that they're not walking off the end of the packet.
147699fc314SBill Fenner 	 * Rather than pass them all the way down, we set these globals.
148699fc314SBill Fenner 	 */
149699fc314SBill Fenner 	packetp = p;
150699fc314SBill Fenner 	snapend = p + caplen;
151699fc314SBill Fenner 
152699fc314SBill Fenner 	length -= SLIP_HDRLEN;
153699fc314SBill Fenner 
154699fc314SBill Fenner 	ip = (struct ip *)(p + SLIP_HDRLEN);
155699fc314SBill Fenner 
156699fc314SBill Fenner #ifdef notdef
157699fc314SBill Fenner 	if (eflag)
158699fc314SBill Fenner 		sliplink_print(p, ip, length);
159699fc314SBill Fenner #endif
160699fc314SBill Fenner 
161699fc314SBill Fenner 	ip_print((u_char *)ip, length);
162699fc314SBill Fenner 
163699fc314SBill Fenner 	if (xflag)
164699fc314SBill Fenner 		default_print((u_char *)ip, caplen - SLIP_HDRLEN);
165699fc314SBill Fenner  out:
166699fc314SBill Fenner 	putchar('\n');
167699fc314SBill Fenner }
168699fc314SBill Fenner 
1694edb46e9SPaul Traina static void
1704edb46e9SPaul Traina sliplink_print(register const u_char *p, register const struct ip *ip,
1714edb46e9SPaul Traina 	       register u_int length)
1724edb46e9SPaul Traina {
1734edb46e9SPaul Traina 	int dir;
1744edb46e9SPaul Traina 	u_int hlen;
1754edb46e9SPaul Traina 
1764edb46e9SPaul Traina 	dir = p[SLX_DIR];
1774edb46e9SPaul Traina 	putchar(dir == SLIPDIR_IN ? 'I' : 'O');
1784edb46e9SPaul Traina 	putchar(' ');
1794edb46e9SPaul Traina 
1804edb46e9SPaul Traina 	if (nflag) {
1814edb46e9SPaul Traina 		/* XXX just dump the header */
1824edb46e9SPaul Traina 		register int i;
1834edb46e9SPaul Traina 
1844edb46e9SPaul Traina 		for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i)
1854edb46e9SPaul Traina 			printf("%02x.", p[i]);
1864edb46e9SPaul Traina 		printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]);
1874edb46e9SPaul Traina 		return;
1884edb46e9SPaul Traina 	}
1894edb46e9SPaul Traina 	switch (p[SLX_CHDR] & 0xf0) {
1904edb46e9SPaul Traina 
1914edb46e9SPaul Traina 	case TYPE_IP:
1924edb46e9SPaul Traina 		printf("ip %d: ", length + SLIP_HDRLEN);
1934edb46e9SPaul Traina 		break;
1944edb46e9SPaul Traina 
1954edb46e9SPaul Traina 	case TYPE_UNCOMPRESSED_TCP:
1964edb46e9SPaul Traina 		/*
1972ebf6c05SBill Fenner 		 * The connection id is stored in the IP protocol field.
1984edb46e9SPaul Traina 		 * Get it from the link layer since sl_uncompress_tcp()
1994edb46e9SPaul Traina 		 * has restored the IP header copy to IPPROTO_TCP.
2004edb46e9SPaul Traina 		 */
2014edb46e9SPaul Traina 		lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p;
2024edb46e9SPaul Traina 		hlen = ip->ip_hl;
2034edb46e9SPaul Traina 		hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off;
2044edb46e9SPaul Traina 		lastlen[dir][lastconn] = length - (hlen << 2);
2054edb46e9SPaul Traina 		printf("utcp %d: ", lastconn);
2064edb46e9SPaul Traina 		break;
2074edb46e9SPaul Traina 
2084edb46e9SPaul Traina 	default:
2094edb46e9SPaul Traina 		if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
2104edb46e9SPaul Traina 			compressed_sl_print(&p[SLX_CHDR], ip,
2114edb46e9SPaul Traina 			    length, dir);
2124edb46e9SPaul Traina 			printf(": ");
2134edb46e9SPaul Traina 		} else
2144edb46e9SPaul Traina 			printf("slip-%d!: ", p[SLX_CHDR]);
2154edb46e9SPaul Traina 	}
2164edb46e9SPaul Traina }
2174edb46e9SPaul Traina 
2184edb46e9SPaul Traina static const u_char *
2194edb46e9SPaul Traina print_sl_change(const char *str, register const u_char *cp)
2204edb46e9SPaul Traina {
2214edb46e9SPaul Traina 	register u_int i;
2224edb46e9SPaul Traina 
2234edb46e9SPaul Traina 	if ((i = *cp++) == 0) {
2244edb46e9SPaul Traina 		i = EXTRACT_16BITS(cp);
2254edb46e9SPaul Traina 		cp += 2;
2264edb46e9SPaul Traina 	}
2274edb46e9SPaul Traina 	printf(" %s%d", str, i);
2284edb46e9SPaul Traina 	return (cp);
2294edb46e9SPaul Traina }
2304edb46e9SPaul Traina 
2314edb46e9SPaul Traina static const u_char *
2324edb46e9SPaul Traina print_sl_winchange(register const u_char *cp)
2334edb46e9SPaul Traina {
2344edb46e9SPaul Traina 	register short i;
2354edb46e9SPaul Traina 
2364edb46e9SPaul Traina 	if ((i = *cp++) == 0) {
2374edb46e9SPaul Traina 		i = EXTRACT_16BITS(cp);
2384edb46e9SPaul Traina 		cp += 2;
2394edb46e9SPaul Traina 	}
2404edb46e9SPaul Traina 	if (i >= 0)
2414edb46e9SPaul Traina 		printf(" W+%d", i);
2424edb46e9SPaul Traina 	else
2434edb46e9SPaul Traina 		printf(" W%d", i);
2444edb46e9SPaul Traina 	return (cp);
2454edb46e9SPaul Traina }
2464edb46e9SPaul Traina 
2474edb46e9SPaul Traina static void
2484edb46e9SPaul Traina compressed_sl_print(const u_char *chdr, const struct ip *ip,
2494edb46e9SPaul Traina 		    u_int length, int dir)
2504edb46e9SPaul Traina {
2514edb46e9SPaul Traina 	register const u_char *cp = chdr;
2524edb46e9SPaul Traina 	register u_int flags, hlen;
2534edb46e9SPaul Traina 
2544edb46e9SPaul Traina 	flags = *cp++;
2554edb46e9SPaul Traina 	if (flags & NEW_C) {
2564edb46e9SPaul Traina 		lastconn = *cp++;
2574edb46e9SPaul Traina 		printf("ctcp %d", lastconn);
2584edb46e9SPaul Traina 	} else
2594edb46e9SPaul Traina 		printf("ctcp *");
2604edb46e9SPaul Traina 
2614edb46e9SPaul Traina 	/* skip tcp checksum */
2624edb46e9SPaul Traina 	cp += 2;
2634edb46e9SPaul Traina 
2644edb46e9SPaul Traina 	switch (flags & SPECIALS_MASK) {
2654edb46e9SPaul Traina 	case SPECIAL_I:
2664edb46e9SPaul Traina 		printf(" *SA+%d", lastlen[dir][lastconn]);
2674edb46e9SPaul Traina 		break;
2684edb46e9SPaul Traina 
2694edb46e9SPaul Traina 	case SPECIAL_D:
2704edb46e9SPaul Traina 		printf(" *S+%d", lastlen[dir][lastconn]);
2714edb46e9SPaul Traina 		break;
2724edb46e9SPaul Traina 
2734edb46e9SPaul Traina 	default:
2744edb46e9SPaul Traina 		if (flags & NEW_U)
2754edb46e9SPaul Traina 			cp = print_sl_change("U=", cp);
2764edb46e9SPaul Traina 		if (flags & NEW_W)
2774edb46e9SPaul Traina 			cp = print_sl_winchange(cp);
2784edb46e9SPaul Traina 		if (flags & NEW_A)
2794edb46e9SPaul Traina 			cp = print_sl_change("A+", cp);
2804edb46e9SPaul Traina 		if (flags & NEW_S)
2814edb46e9SPaul Traina 			cp = print_sl_change("S+", cp);
2824edb46e9SPaul Traina 		break;
2834edb46e9SPaul Traina 	}
2844edb46e9SPaul Traina 	if (flags & NEW_I)
2854edb46e9SPaul Traina 		cp = print_sl_change("I+", cp);
2864edb46e9SPaul Traina 
2874edb46e9SPaul Traina 	/*
2884edb46e9SPaul Traina 	 * 'hlen' is the length of the uncompressed TCP/IP header (in words).
2894edb46e9SPaul Traina 	 * 'cp - chdr' is the length of the compressed header.
2904edb46e9SPaul Traina 	 * 'length - hlen' is the amount of data in the packet.
2914edb46e9SPaul Traina 	 */
2924edb46e9SPaul Traina 	hlen = ip->ip_hl;
2934edb46e9SPaul Traina 	hlen += ((struct tcphdr *)&((int32_t *)ip)[hlen])->th_off;
2944edb46e9SPaul Traina 	lastlen[dir][lastconn] = length - (hlen << 2);
2954edb46e9SPaul Traina 	printf(" %d (%d)", lastlen[dir][lastconn], cp - chdr);
2964edb46e9SPaul Traina }
2974edb46e9SPaul Traina #else
2984edb46e9SPaul Traina #include <sys/types.h>
2994edb46e9SPaul Traina #include <sys/time.h>
3004edb46e9SPaul Traina 
3012ebf6c05SBill Fenner #include <pcap.h>
3024edb46e9SPaul Traina #include <stdio.h>
3034edb46e9SPaul Traina 
3044edb46e9SPaul Traina #include "interface.h"
305699fc314SBill Fenner 
3064edb46e9SPaul Traina void
3074edb46e9SPaul Traina sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
3084edb46e9SPaul Traina {
3094edb46e9SPaul Traina 
3104edb46e9SPaul Traina 	error("not configured for slip");
3114edb46e9SPaul Traina 	/* NOTREACHED */
3124edb46e9SPaul Traina }
313699fc314SBill Fenner 
314699fc314SBill Fenner void
315699fc314SBill Fenner sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
316699fc314SBill Fenner {
317699fc314SBill Fenner 
318699fc314SBill Fenner 	error("not configured for slip");
319699fc314SBill Fenner 	/* NOTREACHED */
320699fc314SBill Fenner }
3214edb46e9SPaul Traina #endif
322