xref: /freebsd/contrib/tcpdump/print-sl.c (revision 943ee2b15a8e008b2087495c2986bac507caef79)
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[] =
26943ee2b1SBill Fenner     "@(#) $Header: /tcpdump/master/tcpdump/print-sl.c,v 1.56 2000/10/10 05:06:10 guy 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 #include <sys/param.h>
344edb46e9SPaul Traina #include <sys/time.h>
354edb46e9SPaul Traina 
364edb46e9SPaul Traina #include <netinet/in.h>
374edb46e9SPaul Traina 
384edb46e9SPaul Traina #include <ctype.h>
394edb46e9SPaul Traina #include <netdb.h>
404edb46e9SPaul Traina #include <pcap.h>
414edb46e9SPaul Traina #include <stdio.h>
424edb46e9SPaul Traina 
434edb46e9SPaul Traina #include "interface.h"
444edb46e9SPaul Traina #include "addrtoname.h"
454edb46e9SPaul Traina #include "extract.h"			/* must come after interface.h */
464edb46e9SPaul Traina 
47943ee2b1SBill Fenner #include "ip.h"
48943ee2b1SBill Fenner #include "tcp.h"
49943ee2b1SBill Fenner #include "slip.h"
50943ee2b1SBill Fenner #include "slcompress.h"
51943ee2b1SBill Fenner 
524edb46e9SPaul Traina static u_int lastlen[2][256];
534edb46e9SPaul Traina static u_int lastconn = 255;
544edb46e9SPaul Traina 
554edb46e9SPaul Traina static void sliplink_print(const u_char *, const struct ip *, u_int);
564edb46e9SPaul Traina static void compressed_sl_print(const u_char *, const struct ip *, u_int, int);
574edb46e9SPaul Traina 
584edb46e9SPaul Traina void
594edb46e9SPaul Traina sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
604edb46e9SPaul Traina {
614edb46e9SPaul Traina 	register u_int caplen = h->caplen;
624edb46e9SPaul Traina 	register u_int length = h->len;
634edb46e9SPaul Traina 	register const struct ip *ip;
644edb46e9SPaul Traina 
654edb46e9SPaul Traina 	ts_print(&h->ts);
664edb46e9SPaul Traina 
674edb46e9SPaul Traina 	if (caplen < SLIP_HDRLEN) {
684edb46e9SPaul Traina 		printf("[|slip]");
694edb46e9SPaul Traina 		goto out;
704edb46e9SPaul Traina 	}
714edb46e9SPaul Traina 	/*
724edb46e9SPaul Traina 	 * Some printers want to get back at the link level addresses,
734edb46e9SPaul Traina 	 * and/or check that they're not walking off the end of the packet.
744edb46e9SPaul Traina 	 * Rather than pass them all the way down, we set these globals.
754edb46e9SPaul Traina 	 */
764edb46e9SPaul Traina 	packetp = p;
774edb46e9SPaul Traina 	snapend = p + caplen;
784edb46e9SPaul Traina 
794edb46e9SPaul Traina 	length -= SLIP_HDRLEN;
804edb46e9SPaul Traina 
814edb46e9SPaul Traina 	ip = (struct ip *)(p + SLIP_HDRLEN);
824edb46e9SPaul Traina 
834edb46e9SPaul Traina 	if (eflag)
844edb46e9SPaul Traina 		sliplink_print(p, ip, length);
854edb46e9SPaul Traina 
86943ee2b1SBill Fenner 	switch (IP_V(ip)) {
87a88113a8SBill Fenner 	case 4:
884edb46e9SPaul Traina 		ip_print((u_char *)ip, length);
89a88113a8SBill Fenner 		break;
90a88113a8SBill Fenner #ifdef INET6
91a88113a8SBill Fenner 	case 6:
92a88113a8SBill Fenner 		ip6_print((u_char *)ip, length);
93a88113a8SBill Fenner 		break;
94a88113a8SBill Fenner #endif
95a88113a8SBill Fenner 	default:
96943ee2b1SBill Fenner 		printf ("ip v%d", IP_V(ip));
97a88113a8SBill Fenner 	}
984edb46e9SPaul Traina 
994edb46e9SPaul Traina 	if (xflag)
1004edb46e9SPaul Traina 		default_print((u_char *)ip, caplen - SLIP_HDRLEN);
1014edb46e9SPaul Traina  out:
1024edb46e9SPaul Traina 	putchar('\n');
1034edb46e9SPaul Traina }
1044edb46e9SPaul Traina 
105699fc314SBill Fenner 
106699fc314SBill Fenner void
107699fc314SBill Fenner sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
108699fc314SBill Fenner {
109699fc314SBill Fenner 	register u_int caplen = h->caplen;
110699fc314SBill Fenner 	register u_int length = h->len;
111699fc314SBill Fenner 	register const struct ip *ip;
112699fc314SBill Fenner 
113699fc314SBill Fenner 	ts_print(&h->ts);
114699fc314SBill Fenner 
115699fc314SBill Fenner 	if (caplen < SLIP_HDRLEN) {
116699fc314SBill Fenner 		printf("[|slip]");
117699fc314SBill Fenner 		goto out;
118699fc314SBill Fenner 	}
119699fc314SBill Fenner 	/*
120699fc314SBill Fenner 	 * Some printers want to get back at the link level addresses,
121699fc314SBill Fenner 	 * and/or check that they're not walking off the end of the packet.
122699fc314SBill Fenner 	 * Rather than pass them all the way down, we set these globals.
123699fc314SBill Fenner 	 */
124699fc314SBill Fenner 	packetp = p;
125699fc314SBill Fenner 	snapend = p + caplen;
126699fc314SBill Fenner 
127699fc314SBill Fenner 	length -= SLIP_HDRLEN;
128699fc314SBill Fenner 
129699fc314SBill Fenner 	ip = (struct ip *)(p + SLIP_HDRLEN);
130699fc314SBill Fenner 
131699fc314SBill Fenner #ifdef notdef
132699fc314SBill Fenner 	if (eflag)
133699fc314SBill Fenner 		sliplink_print(p, ip, length);
134699fc314SBill Fenner #endif
135699fc314SBill Fenner 
136699fc314SBill Fenner 	ip_print((u_char *)ip, length);
137699fc314SBill Fenner 
138699fc314SBill Fenner 	if (xflag)
139699fc314SBill Fenner 		default_print((u_char *)ip, caplen - SLIP_HDRLEN);
140699fc314SBill Fenner  out:
141699fc314SBill Fenner 	putchar('\n');
142699fc314SBill Fenner }
143699fc314SBill Fenner 
1444edb46e9SPaul Traina static void
1454edb46e9SPaul Traina sliplink_print(register const u_char *p, register const struct ip *ip,
1464edb46e9SPaul Traina 	       register u_int length)
1474edb46e9SPaul Traina {
1484edb46e9SPaul Traina 	int dir;
1494edb46e9SPaul Traina 	u_int hlen;
1504edb46e9SPaul Traina 
1514edb46e9SPaul Traina 	dir = p[SLX_DIR];
1524edb46e9SPaul Traina 	putchar(dir == SLIPDIR_IN ? 'I' : 'O');
1534edb46e9SPaul Traina 	putchar(' ');
1544edb46e9SPaul Traina 
1554edb46e9SPaul Traina 	if (nflag) {
1564edb46e9SPaul Traina 		/* XXX just dump the header */
1574edb46e9SPaul Traina 		register int i;
1584edb46e9SPaul Traina 
1594edb46e9SPaul Traina 		for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i)
1604edb46e9SPaul Traina 			printf("%02x.", p[i]);
1614edb46e9SPaul Traina 		printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]);
1624edb46e9SPaul Traina 		return;
1634edb46e9SPaul Traina 	}
1644edb46e9SPaul Traina 	switch (p[SLX_CHDR] & 0xf0) {
1654edb46e9SPaul Traina 
1664edb46e9SPaul Traina 	case TYPE_IP:
1674edb46e9SPaul Traina 		printf("ip %d: ", length + SLIP_HDRLEN);
1684edb46e9SPaul Traina 		break;
1694edb46e9SPaul Traina 
1704edb46e9SPaul Traina 	case TYPE_UNCOMPRESSED_TCP:
1714edb46e9SPaul Traina 		/*
1722ebf6c05SBill Fenner 		 * The connection id is stored in the IP protocol field.
1734edb46e9SPaul Traina 		 * Get it from the link layer since sl_uncompress_tcp()
1744edb46e9SPaul Traina 		 * has restored the IP header copy to IPPROTO_TCP.
1754edb46e9SPaul Traina 		 */
1764edb46e9SPaul Traina 		lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p;
177943ee2b1SBill Fenner 		hlen = IP_HL(ip);
178943ee2b1SBill Fenner 		hlen += TH_OFF((struct tcphdr *)&((int *)ip)[hlen]);
1794edb46e9SPaul Traina 		lastlen[dir][lastconn] = length - (hlen << 2);
1804edb46e9SPaul Traina 		printf("utcp %d: ", lastconn);
1814edb46e9SPaul Traina 		break;
1824edb46e9SPaul Traina 
1834edb46e9SPaul Traina 	default:
1844edb46e9SPaul Traina 		if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
1854edb46e9SPaul Traina 			compressed_sl_print(&p[SLX_CHDR], ip,
1864edb46e9SPaul Traina 			    length, dir);
1874edb46e9SPaul Traina 			printf(": ");
1884edb46e9SPaul Traina 		} else
1894edb46e9SPaul Traina 			printf("slip-%d!: ", p[SLX_CHDR]);
1904edb46e9SPaul Traina 	}
1914edb46e9SPaul Traina }
1924edb46e9SPaul Traina 
1934edb46e9SPaul Traina static const u_char *
1944edb46e9SPaul Traina print_sl_change(const char *str, register const u_char *cp)
1954edb46e9SPaul Traina {
1964edb46e9SPaul Traina 	register u_int i;
1974edb46e9SPaul Traina 
1984edb46e9SPaul Traina 	if ((i = *cp++) == 0) {
1994edb46e9SPaul Traina 		i = EXTRACT_16BITS(cp);
2004edb46e9SPaul Traina 		cp += 2;
2014edb46e9SPaul Traina 	}
2024edb46e9SPaul Traina 	printf(" %s%d", str, i);
2034edb46e9SPaul Traina 	return (cp);
2044edb46e9SPaul Traina }
2054edb46e9SPaul Traina 
2064edb46e9SPaul Traina static const u_char *
2074edb46e9SPaul Traina print_sl_winchange(register const u_char *cp)
2084edb46e9SPaul Traina {
2094edb46e9SPaul Traina 	register short i;
2104edb46e9SPaul Traina 
2114edb46e9SPaul Traina 	if ((i = *cp++) == 0) {
2124edb46e9SPaul Traina 		i = EXTRACT_16BITS(cp);
2134edb46e9SPaul Traina 		cp += 2;
2144edb46e9SPaul Traina 	}
2154edb46e9SPaul Traina 	if (i >= 0)
2164edb46e9SPaul Traina 		printf(" W+%d", i);
2174edb46e9SPaul Traina 	else
2184edb46e9SPaul Traina 		printf(" W%d", i);
2194edb46e9SPaul Traina 	return (cp);
2204edb46e9SPaul Traina }
2214edb46e9SPaul Traina 
2224edb46e9SPaul Traina static void
2234edb46e9SPaul Traina compressed_sl_print(const u_char *chdr, const struct ip *ip,
2244edb46e9SPaul Traina 		    u_int length, int dir)
2254edb46e9SPaul Traina {
2264edb46e9SPaul Traina 	register const u_char *cp = chdr;
2274edb46e9SPaul Traina 	register u_int flags, hlen;
2284edb46e9SPaul Traina 
2294edb46e9SPaul Traina 	flags = *cp++;
2304edb46e9SPaul Traina 	if (flags & NEW_C) {
2314edb46e9SPaul Traina 		lastconn = *cp++;
2324edb46e9SPaul Traina 		printf("ctcp %d", lastconn);
2334edb46e9SPaul Traina 	} else
2344edb46e9SPaul Traina 		printf("ctcp *");
2354edb46e9SPaul Traina 
2364edb46e9SPaul Traina 	/* skip tcp checksum */
2374edb46e9SPaul Traina 	cp += 2;
2384edb46e9SPaul Traina 
2394edb46e9SPaul Traina 	switch (flags & SPECIALS_MASK) {
2404edb46e9SPaul Traina 	case SPECIAL_I:
2414edb46e9SPaul Traina 		printf(" *SA+%d", lastlen[dir][lastconn]);
2424edb46e9SPaul Traina 		break;
2434edb46e9SPaul Traina 
2444edb46e9SPaul Traina 	case SPECIAL_D:
2454edb46e9SPaul Traina 		printf(" *S+%d", lastlen[dir][lastconn]);
2464edb46e9SPaul Traina 		break;
2474edb46e9SPaul Traina 
2484edb46e9SPaul Traina 	default:
2494edb46e9SPaul Traina 		if (flags & NEW_U)
2504edb46e9SPaul Traina 			cp = print_sl_change("U=", cp);
2514edb46e9SPaul Traina 		if (flags & NEW_W)
2524edb46e9SPaul Traina 			cp = print_sl_winchange(cp);
2534edb46e9SPaul Traina 		if (flags & NEW_A)
2544edb46e9SPaul Traina 			cp = print_sl_change("A+", cp);
2554edb46e9SPaul Traina 		if (flags & NEW_S)
2564edb46e9SPaul Traina 			cp = print_sl_change("S+", cp);
2574edb46e9SPaul Traina 		break;
2584edb46e9SPaul Traina 	}
2594edb46e9SPaul Traina 	if (flags & NEW_I)
2604edb46e9SPaul Traina 		cp = print_sl_change("I+", cp);
2614edb46e9SPaul Traina 
2624edb46e9SPaul Traina 	/*
2634edb46e9SPaul Traina 	 * 'hlen' is the length of the uncompressed TCP/IP header (in words).
2644edb46e9SPaul Traina 	 * 'cp - chdr' is the length of the compressed header.
2654edb46e9SPaul Traina 	 * 'length - hlen' is the amount of data in the packet.
2664edb46e9SPaul Traina 	 */
267943ee2b1SBill Fenner 	hlen = IP_HL(ip);
268943ee2b1SBill Fenner 	hlen += TH_OFF((struct tcphdr *)&((int32_t *)ip)[hlen]);
2694edb46e9SPaul Traina 	lastlen[dir][lastconn] = length - (hlen << 2);
270943ee2b1SBill Fenner 	printf(" %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr));
2714edb46e9SPaul Traina }
272