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 24*3c602fabSXin LI #define NETDISSECT_REWORKED 25a88113a8SBill Fenner #ifdef HAVE_CONFIG_H 26a88113a8SBill Fenner #include "config.h" 274edb46e9SPaul Traina #endif 284edb46e9SPaul Traina 29cc391cceSBruce M Simpson #include <tcpdump-stdinc.h> 304edb46e9SPaul Traina 314edb46e9SPaul Traina #include "interface.h" 324edb46e9SPaul Traina #include "extract.h" /* must come after interface.h */ 334edb46e9SPaul Traina 34943ee2b1SBill Fenner #include "ip.h" 35943ee2b1SBill Fenner #include "tcp.h" 36943ee2b1SBill Fenner #include "slcompress.h" 37943ee2b1SBill Fenner 38*3c602fabSXin LI /* 39*3c602fabSXin LI * definitions of the pseudo- link-level header attached to slip 40*3c602fabSXin LI * packets grabbed by the packet filter (bpf) traffic monitor. 41*3c602fabSXin LI */ 42*3c602fabSXin LI #define SLIP_HDRLEN 16 43*3c602fabSXin LI 44*3c602fabSXin LI #define SLX_DIR 0 45*3c602fabSXin LI #define SLX_CHDR 1 46*3c602fabSXin LI #define CHDR_LEN 15 47*3c602fabSXin LI 48*3c602fabSXin LI #define SLIPDIR_IN 0 49*3c602fabSXin LI #define SLIPDIR_OUT 1 50*3c602fabSXin LI 51*3c602fabSXin LI static const char tstr[] = "[|slip]"; 52*3c602fabSXin LI 534edb46e9SPaul Traina static u_int lastlen[2][256]; 544edb46e9SPaul Traina static u_int lastconn = 255; 554edb46e9SPaul Traina 56*3c602fabSXin LI static void sliplink_print(netdissect_options *, const u_char *, const struct ip *, u_int); 57*3c602fabSXin LI static void compressed_sl_print(netdissect_options *, const u_char *, const struct ip *, u_int, int); 584edb46e9SPaul Traina 59cc391cceSBruce M Simpson u_int 60*3c602fabSXin LI sl_if_print(netdissect_options *ndo, 61*3c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p) 624edb46e9SPaul Traina { 634edb46e9SPaul Traina register u_int caplen = h->caplen; 644edb46e9SPaul Traina register u_int length = h->len; 654edb46e9SPaul Traina register const struct ip *ip; 664edb46e9SPaul Traina 674edb46e9SPaul Traina if (caplen < SLIP_HDRLEN) { 68*3c602fabSXin LI ND_PRINT((ndo, "%s", tstr)); 69cc391cceSBruce M Simpson return (caplen); 704edb46e9SPaul Traina } 714edb46e9SPaul Traina 724edb46e9SPaul Traina length -= SLIP_HDRLEN; 734edb46e9SPaul Traina 744edb46e9SPaul Traina ip = (struct ip *)(p + SLIP_HDRLEN); 754edb46e9SPaul Traina 76*3c602fabSXin LI if (ndo->ndo_eflag) 77*3c602fabSXin LI sliplink_print(ndo, p, ip, length); 784edb46e9SPaul Traina 79943ee2b1SBill Fenner switch (IP_V(ip)) { 80a88113a8SBill Fenner case 4: 81*3c602fabSXin LI ip_print(ndo, (u_char *)ip, length); 82a88113a8SBill Fenner break; 83a88113a8SBill Fenner #ifdef INET6 84a88113a8SBill Fenner case 6: 85*3c602fabSXin LI ip6_print(ndo, (u_char *)ip, length); 86a88113a8SBill Fenner break; 87a88113a8SBill Fenner #endif 88a88113a8SBill Fenner default: 89*3c602fabSXin LI ND_PRINT((ndo, "ip v%d", IP_V(ip))); 90a88113a8SBill Fenner } 914edb46e9SPaul Traina 92cc391cceSBruce M Simpson return (SLIP_HDRLEN); 934edb46e9SPaul Traina } 944edb46e9SPaul Traina 95cc391cceSBruce M Simpson u_int 96*3c602fabSXin LI sl_bsdos_if_print(netdissect_options *ndo, 97*3c602fabSXin LI const struct pcap_pkthdr *h, const u_char *p) 98699fc314SBill Fenner { 99699fc314SBill Fenner register u_int caplen = h->caplen; 100699fc314SBill Fenner register u_int length = h->len; 101699fc314SBill Fenner register const struct ip *ip; 102699fc314SBill Fenner 103699fc314SBill Fenner if (caplen < SLIP_HDRLEN) { 104*3c602fabSXin LI ND_PRINT((ndo, "%s", tstr)); 105cc391cceSBruce M Simpson return (caplen); 106699fc314SBill Fenner } 107699fc314SBill Fenner 108699fc314SBill Fenner length -= SLIP_HDRLEN; 109699fc314SBill Fenner 110699fc314SBill Fenner ip = (struct ip *)(p + SLIP_HDRLEN); 111699fc314SBill Fenner 112699fc314SBill Fenner #ifdef notdef 113*3c602fabSXin LI if (ndo->ndo_eflag) 114*3c602fabSXin LI sliplink_print(ndo, p, ip, length); 115699fc314SBill Fenner #endif 116699fc314SBill Fenner 117*3c602fabSXin LI ip_print(ndo, (u_char *)ip, length); 118699fc314SBill Fenner 119cc391cceSBruce M Simpson return (SLIP_HDRLEN); 120699fc314SBill Fenner } 121699fc314SBill Fenner 1224edb46e9SPaul Traina static void 123*3c602fabSXin LI sliplink_print(netdissect_options *ndo, 124*3c602fabSXin LI register const u_char *p, register const struct ip *ip, 1254edb46e9SPaul Traina register u_int length) 1264edb46e9SPaul Traina { 1274edb46e9SPaul Traina int dir; 1284edb46e9SPaul Traina u_int hlen; 1294edb46e9SPaul Traina 1304edb46e9SPaul Traina dir = p[SLX_DIR]; 131*3c602fabSXin LI ND_PRINT((ndo, dir == SLIPDIR_IN ? "I " : "O ")); 1324edb46e9SPaul Traina 133*3c602fabSXin LI if (ndo->ndo_nflag) { 1344edb46e9SPaul Traina /* XXX just dump the header */ 1354edb46e9SPaul Traina register int i; 1364edb46e9SPaul Traina 1374edb46e9SPaul Traina for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i) 138*3c602fabSXin LI ND_PRINT((ndo, "%02x.", p[i])); 139*3c602fabSXin LI ND_PRINT((ndo, "%02x: ", p[SLX_CHDR + CHDR_LEN - 1])); 1404edb46e9SPaul Traina return; 1414edb46e9SPaul Traina } 1424edb46e9SPaul Traina switch (p[SLX_CHDR] & 0xf0) { 1434edb46e9SPaul Traina 1444edb46e9SPaul Traina case TYPE_IP: 145*3c602fabSXin LI ND_PRINT((ndo, "ip %d: ", length + SLIP_HDRLEN)); 1464edb46e9SPaul Traina break; 1474edb46e9SPaul Traina 1484edb46e9SPaul Traina case TYPE_UNCOMPRESSED_TCP: 1494edb46e9SPaul Traina /* 1502ebf6c05SBill Fenner * The connection id is stored in the IP protocol field. 1514edb46e9SPaul Traina * Get it from the link layer since sl_uncompress_tcp() 1524edb46e9SPaul Traina * has restored the IP header copy to IPPROTO_TCP. 1534edb46e9SPaul Traina */ 1544edb46e9SPaul Traina lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p; 155943ee2b1SBill Fenner hlen = IP_HL(ip); 156943ee2b1SBill Fenner hlen += TH_OFF((struct tcphdr *)&((int *)ip)[hlen]); 1574edb46e9SPaul Traina lastlen[dir][lastconn] = length - (hlen << 2); 158*3c602fabSXin LI ND_PRINT((ndo, "utcp %d: ", lastconn)); 1594edb46e9SPaul Traina break; 1604edb46e9SPaul Traina 1614edb46e9SPaul Traina default: 1624edb46e9SPaul Traina if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { 163*3c602fabSXin LI compressed_sl_print(ndo, &p[SLX_CHDR], ip, 1644edb46e9SPaul Traina length, dir); 165*3c602fabSXin LI ND_PRINT((ndo, ": ")); 1664edb46e9SPaul Traina } else 167*3c602fabSXin LI ND_PRINT((ndo, "slip-%d!: ", p[SLX_CHDR])); 1684edb46e9SPaul Traina } 1694edb46e9SPaul Traina } 1704edb46e9SPaul Traina 1714edb46e9SPaul Traina static const u_char * 172*3c602fabSXin LI print_sl_change(netdissect_options *ndo, 173*3c602fabSXin LI const char *str, register const u_char *cp) 1744edb46e9SPaul Traina { 1754edb46e9SPaul Traina register u_int i; 1764edb46e9SPaul Traina 1774edb46e9SPaul Traina if ((i = *cp++) == 0) { 1784edb46e9SPaul Traina i = EXTRACT_16BITS(cp); 1794edb46e9SPaul Traina cp += 2; 1804edb46e9SPaul Traina } 181*3c602fabSXin LI ND_PRINT((ndo, " %s%d", str, i)); 1824edb46e9SPaul Traina return (cp); 1834edb46e9SPaul Traina } 1844edb46e9SPaul Traina 1854edb46e9SPaul Traina static const u_char * 186*3c602fabSXin LI print_sl_winchange(netdissect_options *ndo, 187*3c602fabSXin LI register const u_char *cp) 1884edb46e9SPaul Traina { 1894edb46e9SPaul Traina register short i; 1904edb46e9SPaul Traina 1914edb46e9SPaul Traina if ((i = *cp++) == 0) { 1924edb46e9SPaul Traina i = EXTRACT_16BITS(cp); 1934edb46e9SPaul Traina cp += 2; 1944edb46e9SPaul Traina } 1954edb46e9SPaul Traina if (i >= 0) 196*3c602fabSXin LI ND_PRINT((ndo, " W+%d", i)); 1974edb46e9SPaul Traina else 198*3c602fabSXin LI ND_PRINT((ndo, " W%d", i)); 1994edb46e9SPaul Traina return (cp); 2004edb46e9SPaul Traina } 2014edb46e9SPaul Traina 2024edb46e9SPaul Traina static void 203*3c602fabSXin LI compressed_sl_print(netdissect_options *ndo, 204*3c602fabSXin LI const u_char *chdr, const struct ip *ip, 2054edb46e9SPaul Traina u_int length, int dir) 2064edb46e9SPaul Traina { 2074edb46e9SPaul Traina register const u_char *cp = chdr; 2084edb46e9SPaul Traina register u_int flags, hlen; 2094edb46e9SPaul Traina 2104edb46e9SPaul Traina flags = *cp++; 2114edb46e9SPaul Traina if (flags & NEW_C) { 2124edb46e9SPaul Traina lastconn = *cp++; 213*3c602fabSXin LI ND_PRINT((ndo, "ctcp %d", lastconn)); 2144edb46e9SPaul Traina } else 215*3c602fabSXin LI ND_PRINT((ndo, "ctcp *")); 2164edb46e9SPaul Traina 2174edb46e9SPaul Traina /* skip tcp checksum */ 2184edb46e9SPaul Traina cp += 2; 2194edb46e9SPaul Traina 2204edb46e9SPaul Traina switch (flags & SPECIALS_MASK) { 2214edb46e9SPaul Traina case SPECIAL_I: 222*3c602fabSXin LI ND_PRINT((ndo, " *SA+%d", lastlen[dir][lastconn])); 2234edb46e9SPaul Traina break; 2244edb46e9SPaul Traina 2254edb46e9SPaul Traina case SPECIAL_D: 226*3c602fabSXin LI ND_PRINT((ndo, " *S+%d", lastlen[dir][lastconn])); 2274edb46e9SPaul Traina break; 2284edb46e9SPaul Traina 2294edb46e9SPaul Traina default: 2304edb46e9SPaul Traina if (flags & NEW_U) 231*3c602fabSXin LI cp = print_sl_change(ndo, "U=", cp); 2324edb46e9SPaul Traina if (flags & NEW_W) 233*3c602fabSXin LI cp = print_sl_winchange(ndo, cp); 2344edb46e9SPaul Traina if (flags & NEW_A) 235*3c602fabSXin LI cp = print_sl_change(ndo, "A+", cp); 2364edb46e9SPaul Traina if (flags & NEW_S) 237*3c602fabSXin LI cp = print_sl_change(ndo, "S+", cp); 2384edb46e9SPaul Traina break; 2394edb46e9SPaul Traina } 2404edb46e9SPaul Traina if (flags & NEW_I) 241*3c602fabSXin LI cp = print_sl_change(ndo, "I+", cp); 2424edb46e9SPaul Traina 2434edb46e9SPaul Traina /* 2444edb46e9SPaul Traina * 'hlen' is the length of the uncompressed TCP/IP header (in words). 2454edb46e9SPaul Traina * 'cp - chdr' is the length of the compressed header. 2464edb46e9SPaul Traina * 'length - hlen' is the amount of data in the packet. 2474edb46e9SPaul Traina */ 248943ee2b1SBill Fenner hlen = IP_HL(ip); 249943ee2b1SBill Fenner hlen += TH_OFF((struct tcphdr *)&((int32_t *)ip)[hlen]); 2504edb46e9SPaul Traina lastlen[dir][lastconn] = length - (hlen << 2); 251*3c602fabSXin LI ND_PRINT((ndo, " %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr))); 2524edb46e9SPaul Traina } 253