xref: /freebsd/contrib/tcpdump/print-sl.c (revision 699fc31439c6d227def4f2fdf7b4f4c5f3d02828)
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.
204edb46e9SPaul Traina  */
214edb46e9SPaul Traina 
224edb46e9SPaul Traina #ifndef lint
232ebf6c05SBill Fenner static const char rcsid[] =
24699fc314SBill Fenner     "@(#) $Header: print-sl.c,v 1.42 97/06/12 14:21:35 leres Exp $ (LBL)";
254edb46e9SPaul Traina #endif
264edb46e9SPaul Traina 
274edb46e9SPaul Traina #ifdef HAVE_NET_SLIP_H
284edb46e9SPaul Traina #include <sys/param.h>
294edb46e9SPaul Traina #include <sys/time.h>
304edb46e9SPaul Traina #include <sys/timeb.h>
314edb46e9SPaul Traina #include <sys/file.h>
324edb46e9SPaul Traina #include <sys/ioctl.h>
334edb46e9SPaul Traina #include <sys/mbuf.h>
344edb46e9SPaul Traina #include <sys/socket.h>
354edb46e9SPaul Traina 
364edb46e9SPaul Traina #if __STDC__
374edb46e9SPaul Traina struct rtentry;
384edb46e9SPaul Traina #endif
394edb46e9SPaul Traina #include <net/if.h>
404edb46e9SPaul Traina 
414edb46e9SPaul Traina #include <netinet/in.h>
424edb46e9SPaul Traina #include <netinet/in_systm.h>
434edb46e9SPaul Traina #include <netinet/ip.h>
44ee3e7633SGarrett Wollman #include <net/ethernet.h>
454edb46e9SPaul Traina #include <netinet/ip_var.h>
464edb46e9SPaul Traina #include <netinet/udp.h>
474edb46e9SPaul Traina #include <netinet/udp_var.h>
484edb46e9SPaul Traina #include <netinet/tcp.h>
494edb46e9SPaul Traina #include <netinet/tcpip.h>
504edb46e9SPaul Traina 
514edb46e9SPaul Traina #include <net/slcompress.h>
524edb46e9SPaul Traina #include <net/slip.h>
534edb46e9SPaul Traina 
544edb46e9SPaul Traina #include <ctype.h>
554edb46e9SPaul Traina #include <netdb.h>
564edb46e9SPaul Traina #include <pcap.h>
574edb46e9SPaul Traina #include <stdio.h>
584edb46e9SPaul Traina 
594edb46e9SPaul Traina #include "interface.h"
604edb46e9SPaul Traina #include "addrtoname.h"
614edb46e9SPaul Traina #include "extract.h"			/* must come after interface.h */
624edb46e9SPaul Traina 
634edb46e9SPaul Traina static u_int lastlen[2][256];
644edb46e9SPaul Traina static u_int lastconn = 255;
654edb46e9SPaul Traina 
664edb46e9SPaul Traina static void sliplink_print(const u_char *, const struct ip *, u_int);
674edb46e9SPaul Traina static void compressed_sl_print(const u_char *, const struct ip *, u_int, int);
684edb46e9SPaul Traina 
694edb46e9SPaul Traina /* XXX BSD/OS 2.1 compatibility */
704edb46e9SPaul Traina #if !defined(SLIP_HDRLEN) && defined(SLC_BPFHDR)
714edb46e9SPaul Traina #define SLIP_HDRLEN SLC_BPFHDR
724edb46e9SPaul Traina #define SLX_DIR 0
734edb46e9SPaul Traina #define SLX_CHDR (SLC_BPFHDRLEN - 1)
744edb46e9SPaul Traina #define CHDR_LEN (SLC_BPFHDR - SLC_BPFHDRLEN)
754edb46e9SPaul Traina #endif
764edb46e9SPaul Traina 
77699fc314SBill Fenner /* XXX needs more hacking to work right */
78699fc314SBill Fenner 
794edb46e9SPaul Traina void
804edb46e9SPaul Traina sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
814edb46e9SPaul Traina {
824edb46e9SPaul Traina 	register u_int caplen = h->caplen;
834edb46e9SPaul Traina 	register u_int length = h->len;
844edb46e9SPaul Traina 	register const struct ip *ip;
854edb46e9SPaul Traina 
864edb46e9SPaul Traina 	ts_print(&h->ts);
874edb46e9SPaul Traina 
884edb46e9SPaul Traina 	if (caplen < SLIP_HDRLEN) {
894edb46e9SPaul Traina 		printf("[|slip]");
904edb46e9SPaul Traina 		goto out;
914edb46e9SPaul Traina 	}
924edb46e9SPaul Traina 	/*
934edb46e9SPaul Traina 	 * Some printers want to get back at the link level addresses,
944edb46e9SPaul Traina 	 * and/or check that they're not walking off the end of the packet.
954edb46e9SPaul Traina 	 * Rather than pass them all the way down, we set these globals.
964edb46e9SPaul Traina 	 */
974edb46e9SPaul Traina 	packetp = p;
984edb46e9SPaul Traina 	snapend = p + caplen;
994edb46e9SPaul Traina 
1004edb46e9SPaul Traina 	length -= SLIP_HDRLEN;
1014edb46e9SPaul Traina 
1024edb46e9SPaul Traina 	ip = (struct ip *)(p + SLIP_HDRLEN);
1034edb46e9SPaul Traina 
1044edb46e9SPaul Traina 	if (eflag)
1054edb46e9SPaul Traina 		sliplink_print(p, ip, length);
1064edb46e9SPaul Traina 
1074edb46e9SPaul Traina 	ip_print((u_char *)ip, length);
1084edb46e9SPaul Traina 
1094edb46e9SPaul Traina 	if (xflag)
1104edb46e9SPaul Traina 		default_print((u_char *)ip, caplen - SLIP_HDRLEN);
1114edb46e9SPaul Traina  out:
1124edb46e9SPaul Traina 	putchar('\n');
1134edb46e9SPaul Traina }
1144edb46e9SPaul Traina 
115699fc314SBill Fenner 
116699fc314SBill Fenner void
117699fc314SBill Fenner sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
118699fc314SBill Fenner {
119699fc314SBill Fenner 	register u_int caplen = h->caplen;
120699fc314SBill Fenner 	register u_int length = h->len;
121699fc314SBill Fenner 	register const struct ip *ip;
122699fc314SBill Fenner 
123699fc314SBill Fenner 	ts_print(&h->ts);
124699fc314SBill Fenner 
125699fc314SBill Fenner 	if (caplen < SLIP_HDRLEN) {
126699fc314SBill Fenner 		printf("[|slip]");
127699fc314SBill Fenner 		goto out;
128699fc314SBill Fenner 	}
129699fc314SBill Fenner 	/*
130699fc314SBill Fenner 	 * Some printers want to get back at the link level addresses,
131699fc314SBill Fenner 	 * and/or check that they're not walking off the end of the packet.
132699fc314SBill Fenner 	 * Rather than pass them all the way down, we set these globals.
133699fc314SBill Fenner 	 */
134699fc314SBill Fenner 	packetp = p;
135699fc314SBill Fenner 	snapend = p + caplen;
136699fc314SBill Fenner 
137699fc314SBill Fenner 	length -= SLIP_HDRLEN;
138699fc314SBill Fenner 
139699fc314SBill Fenner 	ip = (struct ip *)(p + SLIP_HDRLEN);
140699fc314SBill Fenner 
141699fc314SBill Fenner #ifdef notdef
142699fc314SBill Fenner 	if (eflag)
143699fc314SBill Fenner 		sliplink_print(p, ip, length);
144699fc314SBill Fenner #endif
145699fc314SBill Fenner 
146699fc314SBill Fenner 	ip_print((u_char *)ip, length);
147699fc314SBill Fenner 
148699fc314SBill Fenner 	if (xflag)
149699fc314SBill Fenner 		default_print((u_char *)ip, caplen - SLIP_HDRLEN);
150699fc314SBill Fenner  out:
151699fc314SBill Fenner 	putchar('\n');
152699fc314SBill Fenner }
153699fc314SBill Fenner 
1544edb46e9SPaul Traina static void
1554edb46e9SPaul Traina sliplink_print(register const u_char *p, register const struct ip *ip,
1564edb46e9SPaul Traina 	       register u_int length)
1574edb46e9SPaul Traina {
1584edb46e9SPaul Traina 	int dir;
1594edb46e9SPaul Traina 	u_int hlen;
1604edb46e9SPaul Traina 
1614edb46e9SPaul Traina 	dir = p[SLX_DIR];
1624edb46e9SPaul Traina 	putchar(dir == SLIPDIR_IN ? 'I' : 'O');
1634edb46e9SPaul Traina 	putchar(' ');
1644edb46e9SPaul Traina 
1654edb46e9SPaul Traina 	if (nflag) {
1664edb46e9SPaul Traina 		/* XXX just dump the header */
1674edb46e9SPaul Traina 		register int i;
1684edb46e9SPaul Traina 
1694edb46e9SPaul Traina 		for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i)
1704edb46e9SPaul Traina 			printf("%02x.", p[i]);
1714edb46e9SPaul Traina 		printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]);
1724edb46e9SPaul Traina 		return;
1734edb46e9SPaul Traina 	}
1744edb46e9SPaul Traina 	switch (p[SLX_CHDR] & 0xf0) {
1754edb46e9SPaul Traina 
1764edb46e9SPaul Traina 	case TYPE_IP:
1774edb46e9SPaul Traina 		printf("ip %d: ", length + SLIP_HDRLEN);
1784edb46e9SPaul Traina 		break;
1794edb46e9SPaul Traina 
1804edb46e9SPaul Traina 	case TYPE_UNCOMPRESSED_TCP:
1814edb46e9SPaul Traina 		/*
1822ebf6c05SBill Fenner 		 * The connection id is stored in the IP protocol field.
1834edb46e9SPaul Traina 		 * Get it from the link layer since sl_uncompress_tcp()
1844edb46e9SPaul Traina 		 * has restored the IP header copy to IPPROTO_TCP.
1854edb46e9SPaul Traina 		 */
1864edb46e9SPaul Traina 		lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p;
1874edb46e9SPaul Traina 		hlen = ip->ip_hl;
1884edb46e9SPaul Traina 		hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off;
1894edb46e9SPaul Traina 		lastlen[dir][lastconn] = length - (hlen << 2);
1904edb46e9SPaul Traina 		printf("utcp %d: ", lastconn);
1914edb46e9SPaul Traina 		break;
1924edb46e9SPaul Traina 
1934edb46e9SPaul Traina 	default:
1944edb46e9SPaul Traina 		if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
1954edb46e9SPaul Traina 			compressed_sl_print(&p[SLX_CHDR], ip,
1964edb46e9SPaul Traina 			    length, dir);
1974edb46e9SPaul Traina 			printf(": ");
1984edb46e9SPaul Traina 		} else
1994edb46e9SPaul Traina 			printf("slip-%d!: ", p[SLX_CHDR]);
2004edb46e9SPaul Traina 	}
2014edb46e9SPaul Traina }
2024edb46e9SPaul Traina 
2034edb46e9SPaul Traina static const u_char *
2044edb46e9SPaul Traina print_sl_change(const char *str, register const u_char *cp)
2054edb46e9SPaul Traina {
2064edb46e9SPaul Traina 	register u_int i;
2074edb46e9SPaul Traina 
2084edb46e9SPaul Traina 	if ((i = *cp++) == 0) {
2094edb46e9SPaul Traina 		i = EXTRACT_16BITS(cp);
2104edb46e9SPaul Traina 		cp += 2;
2114edb46e9SPaul Traina 	}
2124edb46e9SPaul Traina 	printf(" %s%d", str, i);
2134edb46e9SPaul Traina 	return (cp);
2144edb46e9SPaul Traina }
2154edb46e9SPaul Traina 
2164edb46e9SPaul Traina static const u_char *
2174edb46e9SPaul Traina print_sl_winchange(register const u_char *cp)
2184edb46e9SPaul Traina {
2194edb46e9SPaul Traina 	register short i;
2204edb46e9SPaul Traina 
2214edb46e9SPaul Traina 	if ((i = *cp++) == 0) {
2224edb46e9SPaul Traina 		i = EXTRACT_16BITS(cp);
2234edb46e9SPaul Traina 		cp += 2;
2244edb46e9SPaul Traina 	}
2254edb46e9SPaul Traina 	if (i >= 0)
2264edb46e9SPaul Traina 		printf(" W+%d", i);
2274edb46e9SPaul Traina 	else
2284edb46e9SPaul Traina 		printf(" W%d", i);
2294edb46e9SPaul Traina 	return (cp);
2304edb46e9SPaul Traina }
2314edb46e9SPaul Traina 
2324edb46e9SPaul Traina static void
2334edb46e9SPaul Traina compressed_sl_print(const u_char *chdr, const struct ip *ip,
2344edb46e9SPaul Traina 		    u_int length, int dir)
2354edb46e9SPaul Traina {
2364edb46e9SPaul Traina 	register const u_char *cp = chdr;
2374edb46e9SPaul Traina 	register u_int flags, hlen;
2384edb46e9SPaul Traina 
2394edb46e9SPaul Traina 	flags = *cp++;
2404edb46e9SPaul Traina 	if (flags & NEW_C) {
2414edb46e9SPaul Traina 		lastconn = *cp++;
2424edb46e9SPaul Traina 		printf("ctcp %d", lastconn);
2434edb46e9SPaul Traina 	} else
2444edb46e9SPaul Traina 		printf("ctcp *");
2454edb46e9SPaul Traina 
2464edb46e9SPaul Traina 	/* skip tcp checksum */
2474edb46e9SPaul Traina 	cp += 2;
2484edb46e9SPaul Traina 
2494edb46e9SPaul Traina 	switch (flags & SPECIALS_MASK) {
2504edb46e9SPaul Traina 	case SPECIAL_I:
2514edb46e9SPaul Traina 		printf(" *SA+%d", lastlen[dir][lastconn]);
2524edb46e9SPaul Traina 		break;
2534edb46e9SPaul Traina 
2544edb46e9SPaul Traina 	case SPECIAL_D:
2554edb46e9SPaul Traina 		printf(" *S+%d", lastlen[dir][lastconn]);
2564edb46e9SPaul Traina 		break;
2574edb46e9SPaul Traina 
2584edb46e9SPaul Traina 	default:
2594edb46e9SPaul Traina 		if (flags & NEW_U)
2604edb46e9SPaul Traina 			cp = print_sl_change("U=", cp);
2614edb46e9SPaul Traina 		if (flags & NEW_W)
2624edb46e9SPaul Traina 			cp = print_sl_winchange(cp);
2634edb46e9SPaul Traina 		if (flags & NEW_A)
2644edb46e9SPaul Traina 			cp = print_sl_change("A+", cp);
2654edb46e9SPaul Traina 		if (flags & NEW_S)
2664edb46e9SPaul Traina 			cp = print_sl_change("S+", cp);
2674edb46e9SPaul Traina 		break;
2684edb46e9SPaul Traina 	}
2694edb46e9SPaul Traina 	if (flags & NEW_I)
2704edb46e9SPaul Traina 		cp = print_sl_change("I+", cp);
2714edb46e9SPaul Traina 
2724edb46e9SPaul Traina 	/*
2734edb46e9SPaul Traina 	 * 'hlen' is the length of the uncompressed TCP/IP header (in words).
2744edb46e9SPaul Traina 	 * 'cp - chdr' is the length of the compressed header.
2754edb46e9SPaul Traina 	 * 'length - hlen' is the amount of data in the packet.
2764edb46e9SPaul Traina 	 */
2774edb46e9SPaul Traina 	hlen = ip->ip_hl;
2784edb46e9SPaul Traina 	hlen += ((struct tcphdr *)&((int32_t *)ip)[hlen])->th_off;
2794edb46e9SPaul Traina 	lastlen[dir][lastconn] = length - (hlen << 2);
2804edb46e9SPaul Traina 	printf(" %d (%d)", lastlen[dir][lastconn], cp - chdr);
2814edb46e9SPaul Traina }
2824edb46e9SPaul Traina #else
2834edb46e9SPaul Traina #include <sys/types.h>
2844edb46e9SPaul Traina #include <sys/time.h>
2854edb46e9SPaul Traina 
2862ebf6c05SBill Fenner #include <pcap.h>
2874edb46e9SPaul Traina #include <stdio.h>
2884edb46e9SPaul Traina 
2894edb46e9SPaul Traina #include "interface.h"
290699fc314SBill Fenner 
2914edb46e9SPaul Traina void
2924edb46e9SPaul Traina sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
2934edb46e9SPaul Traina {
2944edb46e9SPaul Traina 
2954edb46e9SPaul Traina 	error("not configured for slip");
2964edb46e9SPaul Traina 	/* NOTREACHED */
2974edb46e9SPaul Traina }
298699fc314SBill Fenner 
299699fc314SBill Fenner void
300699fc314SBill Fenner sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
301699fc314SBill Fenner {
302699fc314SBill Fenner 
303699fc314SBill Fenner 	error("not configured for slip");
304699fc314SBill Fenner 	/* NOTREACHED */
305699fc314SBill Fenner }
3064edb46e9SPaul Traina #endif
307