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