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 22*3340d773SGleb Smirnoff /* \summary: Compressed Serial Line Internet Protocol printer */ 23*3340d773SGleb Smirnoff 24a88113a8SBill Fenner #ifdef HAVE_CONFIG_H 25a88113a8SBill Fenner #include "config.h" 264edb46e9SPaul Traina #endif 274edb46e9SPaul Traina 28*3340d773SGleb Smirnoff #include <netdissect-stdinc.h> 294edb46e9SPaul Traina 30*3340d773SGleb Smirnoff #include "netdissect.h" 31*3340d773SGleb Smirnoff #include "extract.h" 324edb46e9SPaul Traina 33943ee2b1SBill Fenner #include "ip.h" 34943ee2b1SBill Fenner #include "tcp.h" 35943ee2b1SBill Fenner #include "slcompress.h" 36943ee2b1SBill Fenner 373c602fabSXin LI /* 383c602fabSXin LI * definitions of the pseudo- link-level header attached to slip 393c602fabSXin LI * packets grabbed by the packet filter (bpf) traffic monitor. 403c602fabSXin LI */ 413c602fabSXin LI #define SLIP_HDRLEN 16 423c602fabSXin LI 433c602fabSXin LI #define SLX_DIR 0 443c602fabSXin LI #define SLX_CHDR 1 453c602fabSXin LI #define CHDR_LEN 15 463c602fabSXin LI 473c602fabSXin LI #define SLIPDIR_IN 0 483c602fabSXin LI #define SLIPDIR_OUT 1 493c602fabSXin LI 503c602fabSXin LI static const char tstr[] = "[|slip]"; 513c602fabSXin LI 524edb46e9SPaul Traina static u_int lastlen[2][256]; 534edb46e9SPaul Traina static u_int lastconn = 255; 544edb46e9SPaul Traina 553c602fabSXin LI static void sliplink_print(netdissect_options *, const u_char *, const struct ip *, u_int); 563c602fabSXin LI static void compressed_sl_print(netdissect_options *, const u_char *, const struct ip *, u_int, int); 574edb46e9SPaul Traina 58cc391cceSBruce M Simpson u_int 593c602fabSXin LI sl_if_print(netdissect_options *ndo, 603c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p) 614edb46e9SPaul Traina { 624edb46e9SPaul Traina register u_int caplen = h->caplen; 634edb46e9SPaul Traina register u_int length = h->len; 644edb46e9SPaul Traina register const struct ip *ip; 654edb46e9SPaul Traina 6620869109SPedro F. Giffuni if (caplen < SLIP_HDRLEN || length < SLIP_HDRLEN) { 673c602fabSXin LI ND_PRINT((ndo, "%s", tstr)); 68cc391cceSBruce M Simpson return (caplen); 694edb46e9SPaul Traina } 704edb46e9SPaul Traina 71*3340d773SGleb Smirnoff caplen -= SLIP_HDRLEN; 724edb46e9SPaul Traina length -= SLIP_HDRLEN; 734edb46e9SPaul Traina 74*3340d773SGleb Smirnoff ip = (const struct ip *)(p + SLIP_HDRLEN); 754edb46e9SPaul Traina 763c602fabSXin LI if (ndo->ndo_eflag) 773c602fabSXin LI sliplink_print(ndo, p, ip, length); 784edb46e9SPaul Traina 79*3340d773SGleb Smirnoff if (caplen < 1 || length < 1) { 80*3340d773SGleb Smirnoff ND_PRINT((ndo, "%s", tstr)); 81*3340d773SGleb Smirnoff return (caplen + SLIP_HDRLEN); 82*3340d773SGleb Smirnoff } 83*3340d773SGleb Smirnoff 84943ee2b1SBill Fenner switch (IP_V(ip)) { 85a88113a8SBill Fenner case 4: 86*3340d773SGleb Smirnoff ip_print(ndo, (const u_char *)ip, length); 87a88113a8SBill Fenner break; 88a88113a8SBill Fenner case 6: 89*3340d773SGleb Smirnoff ip6_print(ndo, (const u_char *)ip, length); 90a88113a8SBill Fenner break; 91a88113a8SBill Fenner default: 923c602fabSXin LI ND_PRINT((ndo, "ip v%d", IP_V(ip))); 93a88113a8SBill Fenner } 944edb46e9SPaul Traina 95cc391cceSBruce M Simpson return (SLIP_HDRLEN); 964edb46e9SPaul Traina } 974edb46e9SPaul Traina 98cc391cceSBruce M Simpson u_int 993c602fabSXin LI sl_bsdos_if_print(netdissect_options *ndo, 1003c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p) 101699fc314SBill Fenner { 102699fc314SBill Fenner register u_int caplen = h->caplen; 103699fc314SBill Fenner register u_int length = h->len; 104699fc314SBill Fenner register const struct ip *ip; 105699fc314SBill Fenner 106699fc314SBill Fenner if (caplen < SLIP_HDRLEN) { 1073c602fabSXin LI ND_PRINT((ndo, "%s", tstr)); 108cc391cceSBruce M Simpson return (caplen); 109699fc314SBill Fenner } 110699fc314SBill Fenner 111699fc314SBill Fenner length -= SLIP_HDRLEN; 112699fc314SBill Fenner 113*3340d773SGleb Smirnoff ip = (const struct ip *)(p + SLIP_HDRLEN); 114699fc314SBill Fenner 115699fc314SBill Fenner #ifdef notdef 1163c602fabSXin LI if (ndo->ndo_eflag) 1173c602fabSXin LI sliplink_print(ndo, p, ip, length); 118699fc314SBill Fenner #endif 119699fc314SBill Fenner 120*3340d773SGleb Smirnoff ip_print(ndo, (const u_char *)ip, length); 121699fc314SBill Fenner 122cc391cceSBruce M Simpson return (SLIP_HDRLEN); 123699fc314SBill Fenner } 124699fc314SBill Fenner 1254edb46e9SPaul Traina static void 1263c602fabSXin LI sliplink_print(netdissect_options *ndo, 1273c602fabSXin LI register const u_char *p, register const struct ip *ip, 1284edb46e9SPaul Traina register u_int length) 1294edb46e9SPaul Traina { 1304edb46e9SPaul Traina int dir; 1314edb46e9SPaul Traina u_int hlen; 1324edb46e9SPaul Traina 1334edb46e9SPaul Traina dir = p[SLX_DIR]; 1343c602fabSXin LI ND_PRINT((ndo, dir == SLIPDIR_IN ? "I " : "O ")); 1354edb46e9SPaul Traina 1363c602fabSXin LI if (ndo->ndo_nflag) { 1374edb46e9SPaul Traina /* XXX just dump the header */ 1384edb46e9SPaul Traina register int i; 1394edb46e9SPaul Traina 1404edb46e9SPaul Traina for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i) 1413c602fabSXin LI ND_PRINT((ndo, "%02x.", p[i])); 1423c602fabSXin LI ND_PRINT((ndo, "%02x: ", p[SLX_CHDR + CHDR_LEN - 1])); 1434edb46e9SPaul Traina return; 1444edb46e9SPaul Traina } 1454edb46e9SPaul Traina switch (p[SLX_CHDR] & 0xf0) { 1464edb46e9SPaul Traina 1474edb46e9SPaul Traina case TYPE_IP: 1483c602fabSXin LI ND_PRINT((ndo, "ip %d: ", length + SLIP_HDRLEN)); 1494edb46e9SPaul Traina break; 1504edb46e9SPaul Traina 1514edb46e9SPaul Traina case TYPE_UNCOMPRESSED_TCP: 1524edb46e9SPaul Traina /* 1532ebf6c05SBill Fenner * The connection id is stored in the IP protocol field. 1544edb46e9SPaul Traina * Get it from the link layer since sl_uncompress_tcp() 1554edb46e9SPaul Traina * has restored the IP header copy to IPPROTO_TCP. 1564edb46e9SPaul Traina */ 157*3340d773SGleb Smirnoff lastconn = ((const struct ip *)&p[SLX_CHDR])->ip_p; 158943ee2b1SBill Fenner hlen = IP_HL(ip); 159*3340d773SGleb Smirnoff hlen += TH_OFF((const struct tcphdr *)&((const int *)ip)[hlen]); 1604edb46e9SPaul Traina lastlen[dir][lastconn] = length - (hlen << 2); 1613c602fabSXin LI ND_PRINT((ndo, "utcp %d: ", lastconn)); 1624edb46e9SPaul Traina break; 1634edb46e9SPaul Traina 1644edb46e9SPaul Traina default: 1654edb46e9SPaul Traina if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { 1663c602fabSXin LI compressed_sl_print(ndo, &p[SLX_CHDR], ip, 1674edb46e9SPaul Traina length, dir); 1683c602fabSXin LI ND_PRINT((ndo, ": ")); 1694edb46e9SPaul Traina } else 1703c602fabSXin LI ND_PRINT((ndo, "slip-%d!: ", p[SLX_CHDR])); 1714edb46e9SPaul Traina } 1724edb46e9SPaul Traina } 1734edb46e9SPaul Traina 1744edb46e9SPaul Traina static const u_char * 1753c602fabSXin LI print_sl_change(netdissect_options *ndo, 1763c602fabSXin LI const char *str, register const u_char *cp) 1774edb46e9SPaul Traina { 1784edb46e9SPaul Traina register u_int i; 1794edb46e9SPaul Traina 1804edb46e9SPaul Traina if ((i = *cp++) == 0) { 1814edb46e9SPaul Traina i = EXTRACT_16BITS(cp); 1824edb46e9SPaul Traina cp += 2; 1834edb46e9SPaul Traina } 1843c602fabSXin LI ND_PRINT((ndo, " %s%d", str, i)); 1854edb46e9SPaul Traina return (cp); 1864edb46e9SPaul Traina } 1874edb46e9SPaul Traina 1884edb46e9SPaul Traina static const u_char * 1893c602fabSXin LI print_sl_winchange(netdissect_options *ndo, 1903c602fabSXin LI register const u_char *cp) 1914edb46e9SPaul Traina { 1924edb46e9SPaul Traina register short i; 1934edb46e9SPaul Traina 1944edb46e9SPaul Traina if ((i = *cp++) == 0) { 1954edb46e9SPaul Traina i = EXTRACT_16BITS(cp); 1964edb46e9SPaul Traina cp += 2; 1974edb46e9SPaul Traina } 1984edb46e9SPaul Traina if (i >= 0) 1993c602fabSXin LI ND_PRINT((ndo, " W+%d", i)); 2004edb46e9SPaul Traina else 2013c602fabSXin LI ND_PRINT((ndo, " W%d", i)); 2024edb46e9SPaul Traina return (cp); 2034edb46e9SPaul Traina } 2044edb46e9SPaul Traina 2054edb46e9SPaul Traina static void 2063c602fabSXin LI compressed_sl_print(netdissect_options *ndo, 2073c602fabSXin LI const u_char *chdr, const struct ip *ip, 2084edb46e9SPaul Traina u_int length, int dir) 2094edb46e9SPaul Traina { 2104edb46e9SPaul Traina register const u_char *cp = chdr; 2114edb46e9SPaul Traina register u_int flags, hlen; 2124edb46e9SPaul Traina 2134edb46e9SPaul Traina flags = *cp++; 2144edb46e9SPaul Traina if (flags & NEW_C) { 2154edb46e9SPaul Traina lastconn = *cp++; 2163c602fabSXin LI ND_PRINT((ndo, "ctcp %d", lastconn)); 2174edb46e9SPaul Traina } else 2183c602fabSXin LI ND_PRINT((ndo, "ctcp *")); 2194edb46e9SPaul Traina 2204edb46e9SPaul Traina /* skip tcp checksum */ 2214edb46e9SPaul Traina cp += 2; 2224edb46e9SPaul Traina 2234edb46e9SPaul Traina switch (flags & SPECIALS_MASK) { 2244edb46e9SPaul Traina case SPECIAL_I: 2253c602fabSXin LI ND_PRINT((ndo, " *SA+%d", lastlen[dir][lastconn])); 2264edb46e9SPaul Traina break; 2274edb46e9SPaul Traina 2284edb46e9SPaul Traina case SPECIAL_D: 2293c602fabSXin LI ND_PRINT((ndo, " *S+%d", lastlen[dir][lastconn])); 2304edb46e9SPaul Traina break; 2314edb46e9SPaul Traina 2324edb46e9SPaul Traina default: 2334edb46e9SPaul Traina if (flags & NEW_U) 2343c602fabSXin LI cp = print_sl_change(ndo, "U=", cp); 2354edb46e9SPaul Traina if (flags & NEW_W) 2363c602fabSXin LI cp = print_sl_winchange(ndo, cp); 2374edb46e9SPaul Traina if (flags & NEW_A) 2383c602fabSXin LI cp = print_sl_change(ndo, "A+", cp); 2394edb46e9SPaul Traina if (flags & NEW_S) 2403c602fabSXin LI cp = print_sl_change(ndo, "S+", cp); 2414edb46e9SPaul Traina break; 2424edb46e9SPaul Traina } 2434edb46e9SPaul Traina if (flags & NEW_I) 2443c602fabSXin LI cp = print_sl_change(ndo, "I+", cp); 2454edb46e9SPaul Traina 2464edb46e9SPaul Traina /* 2474edb46e9SPaul Traina * 'hlen' is the length of the uncompressed TCP/IP header (in words). 2484edb46e9SPaul Traina * 'cp - chdr' is the length of the compressed header. 2494edb46e9SPaul Traina * 'length - hlen' is the amount of data in the packet. 2504edb46e9SPaul Traina */ 251943ee2b1SBill Fenner hlen = IP_HL(ip); 252*3340d773SGleb Smirnoff hlen += TH_OFF((const struct tcphdr *)&((const int32_t *)ip)[hlen]); 2534edb46e9SPaul Traina lastlen[dir][lastconn] = length - (hlen << 2); 2543c602fabSXin LI ND_PRINT((ndo, " %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr))); 2554edb46e9SPaul Traina } 256