117680Spst/* 239300Sfenner * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2056896Sfenner * 2156896Sfenner * $FreeBSD: releng/11.0/contrib/tcpdump/print-sl.c 285275 2015-07-08 16:19:32Z pkelsey $ 2217680Spst */ 2317680Spst 24276788Sdelphij#define NETDISSECT_REWORKED 2556896Sfenner#ifdef HAVE_CONFIG_H 2656896Sfenner#include "config.h" 2756896Sfenner#endif 2856896Sfenner 29127675Sbms#include <tcpdump-stdinc.h> 3017680Spst 3117680Spst#include "interface.h" 3217680Spst#include "extract.h" /* must come after interface.h */ 3317680Spst 3475118Sfenner#include "ip.h" 3575118Sfenner#include "tcp.h" 3675118Sfenner#include "slcompress.h" 3775118Sfenner 38276788Sdelphij/* 39276788Sdelphij * definitions of the pseudo- link-level header attached to slip 40276788Sdelphij * packets grabbed by the packet filter (bpf) traffic monitor. 41276788Sdelphij */ 42276788Sdelphij#define SLIP_HDRLEN 16 43276788Sdelphij 44276788Sdelphij#define SLX_DIR 0 45276788Sdelphij#define SLX_CHDR 1 46276788Sdelphij#define CHDR_LEN 15 47276788Sdelphij 48276788Sdelphij#define SLIPDIR_IN 0 49276788Sdelphij#define SLIPDIR_OUT 1 50276788Sdelphij 51276788Sdelphijstatic const char tstr[] = "[|slip]"; 52276788Sdelphij 5317680Spststatic u_int lastlen[2][256]; 5417680Spststatic u_int lastconn = 255; 5517680Spst 56276788Sdelphijstatic void sliplink_print(netdissect_options *, const u_char *, const struct ip *, u_int); 57276788Sdelphijstatic void compressed_sl_print(netdissect_options *, const u_char *, const struct ip *, u_int, int); 5817680Spst 59127675Sbmsu_int 60276788Sdelphijsl_if_print(netdissect_options *ndo, 61276788Sdelphij const struct pcap_pkthdr *h, const u_char *p) 6217680Spst{ 6317680Spst register u_int caplen = h->caplen; 6417680Spst register u_int length = h->len; 6517680Spst register const struct ip *ip; 6617680Spst 67277783Spfg if (caplen < SLIP_HDRLEN || length < SLIP_HDRLEN) { 68276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 69127675Sbms return (caplen); 7017680Spst } 7117680Spst 7217680Spst length -= SLIP_HDRLEN; 7317680Spst 7417680Spst ip = (struct ip *)(p + SLIP_HDRLEN); 7517680Spst 76276788Sdelphij if (ndo->ndo_eflag) 77276788Sdelphij sliplink_print(ndo, p, ip, length); 7817680Spst 7975118Sfenner switch (IP_V(ip)) { 8056896Sfenner case 4: 81276788Sdelphij ip_print(ndo, (u_char *)ip, length); 8256896Sfenner break; 8356896Sfenner case 6: 84276788Sdelphij ip6_print(ndo, (u_char *)ip, length); 8556896Sfenner break; 8656896Sfenner default: 87276788Sdelphij ND_PRINT((ndo, "ip v%d", IP_V(ip))); 8856896Sfenner } 8917680Spst 90127675Sbms return (SLIP_HDRLEN); 9117680Spst} 9217680Spst 93127675Sbmsu_int 94276788Sdelphijsl_bsdos_if_print(netdissect_options *ndo, 95276788Sdelphij const struct pcap_pkthdr *h, const u_char *p) 9639300Sfenner{ 9739300Sfenner register u_int caplen = h->caplen; 9839300Sfenner register u_int length = h->len; 9939300Sfenner register const struct ip *ip; 10039300Sfenner 10139300Sfenner if (caplen < SLIP_HDRLEN) { 102276788Sdelphij ND_PRINT((ndo, "%s", tstr)); 103127675Sbms return (caplen); 10439300Sfenner } 10539300Sfenner 10639300Sfenner length -= SLIP_HDRLEN; 10739300Sfenner 10839300Sfenner ip = (struct ip *)(p + SLIP_HDRLEN); 10939300Sfenner 11039300Sfenner#ifdef notdef 111276788Sdelphij if (ndo->ndo_eflag) 112276788Sdelphij sliplink_print(ndo, p, ip, length); 11339300Sfenner#endif 11439300Sfenner 115276788Sdelphij ip_print(ndo, (u_char *)ip, length); 11639300Sfenner 117127675Sbms return (SLIP_HDRLEN); 11839300Sfenner} 11939300Sfenner 12017680Spststatic void 121276788Sdelphijsliplink_print(netdissect_options *ndo, 122276788Sdelphij register const u_char *p, register const struct ip *ip, 123276788Sdelphij register u_int length) 12417680Spst{ 12517680Spst int dir; 12617680Spst u_int hlen; 12717680Spst 12817680Spst dir = p[SLX_DIR]; 129276788Sdelphij ND_PRINT((ndo, dir == SLIPDIR_IN ? "I " : "O ")); 13017680Spst 131276788Sdelphij if (ndo->ndo_nflag) { 13217680Spst /* XXX just dump the header */ 13317680Spst register int i; 13417680Spst 13517680Spst for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i) 136276788Sdelphij ND_PRINT((ndo, "%02x.", p[i])); 137276788Sdelphij ND_PRINT((ndo, "%02x: ", p[SLX_CHDR + CHDR_LEN - 1])); 13817680Spst return; 13917680Spst } 14017680Spst switch (p[SLX_CHDR] & 0xf0) { 14117680Spst 14217680Spst case TYPE_IP: 143276788Sdelphij ND_PRINT((ndo, "ip %d: ", length + SLIP_HDRLEN)); 14417680Spst break; 14517680Spst 14617680Spst case TYPE_UNCOMPRESSED_TCP: 14717680Spst /* 14826183Sfenner * The connection id is stored in the IP protocol field. 14917680Spst * Get it from the link layer since sl_uncompress_tcp() 15017680Spst * has restored the IP header copy to IPPROTO_TCP. 15117680Spst */ 15217680Spst lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p; 15375118Sfenner hlen = IP_HL(ip); 15475118Sfenner hlen += TH_OFF((struct tcphdr *)&((int *)ip)[hlen]); 15517680Spst lastlen[dir][lastconn] = length - (hlen << 2); 156276788Sdelphij ND_PRINT((ndo, "utcp %d: ", lastconn)); 15717680Spst break; 15817680Spst 15917680Spst default: 16017680Spst if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { 161276788Sdelphij compressed_sl_print(ndo, &p[SLX_CHDR], ip, 16217680Spst length, dir); 163276788Sdelphij ND_PRINT((ndo, ": ")); 16417680Spst } else 165276788Sdelphij ND_PRINT((ndo, "slip-%d!: ", p[SLX_CHDR])); 16617680Spst } 16717680Spst} 16817680Spst 16917680Spststatic const u_char * 170276788Sdelphijprint_sl_change(netdissect_options *ndo, 171276788Sdelphij const char *str, register const u_char *cp) 17217680Spst{ 17317680Spst register u_int i; 17417680Spst 17517680Spst if ((i = *cp++) == 0) { 17617680Spst i = EXTRACT_16BITS(cp); 17717680Spst cp += 2; 17817680Spst } 179276788Sdelphij ND_PRINT((ndo, " %s%d", str, i)); 18017680Spst return (cp); 18117680Spst} 18217680Spst 18317680Spststatic const u_char * 184276788Sdelphijprint_sl_winchange(netdissect_options *ndo, 185276788Sdelphij register const u_char *cp) 18617680Spst{ 18717680Spst register short i; 18817680Spst 18917680Spst if ((i = *cp++) == 0) { 19017680Spst i = EXTRACT_16BITS(cp); 19117680Spst cp += 2; 19217680Spst } 19317680Spst if (i >= 0) 194276788Sdelphij ND_PRINT((ndo, " W+%d", i)); 19517680Spst else 196276788Sdelphij ND_PRINT((ndo, " W%d", i)); 19717680Spst return (cp); 19817680Spst} 19917680Spst 20017680Spststatic void 201276788Sdelphijcompressed_sl_print(netdissect_options *ndo, 202276788Sdelphij const u_char *chdr, const struct ip *ip, 203276788Sdelphij u_int length, int dir) 20417680Spst{ 20517680Spst register const u_char *cp = chdr; 20617680Spst register u_int flags, hlen; 20717680Spst 20817680Spst flags = *cp++; 20917680Spst if (flags & NEW_C) { 21017680Spst lastconn = *cp++; 211276788Sdelphij ND_PRINT((ndo, "ctcp %d", lastconn)); 21217680Spst } else 213276788Sdelphij ND_PRINT((ndo, "ctcp *")); 21417680Spst 21517680Spst /* skip tcp checksum */ 21617680Spst cp += 2; 21717680Spst 21817680Spst switch (flags & SPECIALS_MASK) { 21917680Spst case SPECIAL_I: 220276788Sdelphij ND_PRINT((ndo, " *SA+%d", lastlen[dir][lastconn])); 22117680Spst break; 22217680Spst 22317680Spst case SPECIAL_D: 224276788Sdelphij ND_PRINT((ndo, " *S+%d", lastlen[dir][lastconn])); 22517680Spst break; 22617680Spst 22717680Spst default: 22817680Spst if (flags & NEW_U) 229276788Sdelphij cp = print_sl_change(ndo, "U=", cp); 23017680Spst if (flags & NEW_W) 231276788Sdelphij cp = print_sl_winchange(ndo, cp); 23217680Spst if (flags & NEW_A) 233276788Sdelphij cp = print_sl_change(ndo, "A+", cp); 23417680Spst if (flags & NEW_S) 235276788Sdelphij cp = print_sl_change(ndo, "S+", cp); 23617680Spst break; 23717680Spst } 23817680Spst if (flags & NEW_I) 239276788Sdelphij cp = print_sl_change(ndo, "I+", cp); 24017680Spst 24117680Spst /* 24217680Spst * 'hlen' is the length of the uncompressed TCP/IP header (in words). 24317680Spst * 'cp - chdr' is the length of the compressed header. 24417680Spst * 'length - hlen' is the amount of data in the packet. 24517680Spst */ 24675118Sfenner hlen = IP_HL(ip); 24775118Sfenner hlen += TH_OFF((struct tcphdr *)&((int32_t *)ip)[hlen]); 24817680Spst lastlen[dir][lastconn] = length - (hlen << 2); 249276788Sdelphij ND_PRINT((ndo, " %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr))); 25017680Spst} 251