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$ 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 25127675Sbmsstatic const char rcsid[] _U_ = 26190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-sl.c,v 1.65 2005-04-06 21:32:42 mcr Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2956896Sfenner#ifdef HAVE_CONFIG_H 3056896Sfenner#include "config.h" 3156896Sfenner#endif 3256896Sfenner 33127675Sbms#include <tcpdump-stdinc.h> 3417680Spst 3517680Spst#include <pcap.h> 3617680Spst#include <stdio.h> 3717680Spst 3817680Spst#include "interface.h" 3917680Spst#include "addrtoname.h" 4017680Spst#include "extract.h" /* must come after interface.h */ 4117680Spst 4275118Sfenner#include "ip.h" 4375118Sfenner#include "tcp.h" 4475118Sfenner#include "slip.h" 4575118Sfenner#include "slcompress.h" 4675118Sfenner 4717680Spststatic u_int lastlen[2][256]; 4817680Spststatic u_int lastconn = 255; 4917680Spst 5017680Spststatic void sliplink_print(const u_char *, const struct ip *, u_int); 5117680Spststatic void compressed_sl_print(const u_char *, const struct ip *, u_int, int); 5217680Spst 53127675Sbmsu_int 54127675Sbmssl_if_print(const struct pcap_pkthdr *h, const u_char *p) 5517680Spst{ 5617680Spst register u_int caplen = h->caplen; 5717680Spst register u_int length = h->len; 5817680Spst register const struct ip *ip; 5917680Spst 6017680Spst if (caplen < SLIP_HDRLEN) { 6117680Spst printf("[|slip]"); 62127675Sbms return (caplen); 6317680Spst } 6417680Spst 6517680Spst length -= SLIP_HDRLEN; 6617680Spst 6717680Spst ip = (struct ip *)(p + SLIP_HDRLEN); 6817680Spst 6917680Spst if (eflag) 7017680Spst sliplink_print(p, ip, length); 7117680Spst 7275118Sfenner switch (IP_V(ip)) { 7356896Sfenner case 4: 74146778Ssam ip_print(gndo, (u_char *)ip, length); 7556896Sfenner break; 7656896Sfenner#ifdef INET6 7756896Sfenner case 6: 78235530Sdelphij ip6_print(gndo, (u_char *)ip, length); 7956896Sfenner break; 8056896Sfenner#endif 8156896Sfenner default: 8275118Sfenner printf ("ip v%d", IP_V(ip)); 8356896Sfenner } 8417680Spst 85127675Sbms return (SLIP_HDRLEN); 8617680Spst} 8717680Spst 88127675Sbmsu_int 89127675Sbmssl_bsdos_if_print(const struct pcap_pkthdr *h, const u_char *p) 9039300Sfenner{ 9139300Sfenner register u_int caplen = h->caplen; 9239300Sfenner register u_int length = h->len; 9339300Sfenner register const struct ip *ip; 9439300Sfenner 9539300Sfenner if (caplen < SLIP_HDRLEN) { 9639300Sfenner printf("[|slip]"); 97127675Sbms return (caplen); 9839300Sfenner } 9939300Sfenner 10039300Sfenner length -= SLIP_HDRLEN; 10139300Sfenner 10239300Sfenner ip = (struct ip *)(p + SLIP_HDRLEN); 10339300Sfenner 10439300Sfenner#ifdef notdef 10539300Sfenner if (eflag) 10639300Sfenner sliplink_print(p, ip, length); 10739300Sfenner#endif 10839300Sfenner 109146778Ssam ip_print(gndo, (u_char *)ip, length); 11039300Sfenner 111127675Sbms return (SLIP_HDRLEN); 11239300Sfenner} 11339300Sfenner 11417680Spststatic void 11517680Spstsliplink_print(register const u_char *p, register const struct ip *ip, 11617680Spst register u_int length) 11717680Spst{ 11817680Spst int dir; 11917680Spst u_int hlen; 12017680Spst 12117680Spst dir = p[SLX_DIR]; 12217680Spst putchar(dir == SLIPDIR_IN ? 'I' : 'O'); 12317680Spst putchar(' '); 12417680Spst 12517680Spst if (nflag) { 12617680Spst /* XXX just dump the header */ 12717680Spst register int i; 12817680Spst 12917680Spst for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i) 13017680Spst printf("%02x.", p[i]); 13117680Spst printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]); 13217680Spst return; 13317680Spst } 13417680Spst switch (p[SLX_CHDR] & 0xf0) { 13517680Spst 13617680Spst case TYPE_IP: 13717680Spst printf("ip %d: ", length + SLIP_HDRLEN); 13817680Spst break; 13917680Spst 14017680Spst case TYPE_UNCOMPRESSED_TCP: 14117680Spst /* 14226183Sfenner * The connection id is stored in the IP protocol field. 14317680Spst * Get it from the link layer since sl_uncompress_tcp() 14417680Spst * has restored the IP header copy to IPPROTO_TCP. 14517680Spst */ 14617680Spst lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p; 14775118Sfenner hlen = IP_HL(ip); 14875118Sfenner hlen += TH_OFF((struct tcphdr *)&((int *)ip)[hlen]); 14917680Spst lastlen[dir][lastconn] = length - (hlen << 2); 15017680Spst printf("utcp %d: ", lastconn); 15117680Spst break; 15217680Spst 15317680Spst default: 15417680Spst if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { 15517680Spst compressed_sl_print(&p[SLX_CHDR], ip, 15617680Spst length, dir); 15717680Spst printf(": "); 15817680Spst } else 15917680Spst printf("slip-%d!: ", p[SLX_CHDR]); 16017680Spst } 16117680Spst} 16217680Spst 16317680Spststatic const u_char * 16417680Spstprint_sl_change(const char *str, register const u_char *cp) 16517680Spst{ 16617680Spst register u_int i; 16717680Spst 16817680Spst if ((i = *cp++) == 0) { 16917680Spst i = EXTRACT_16BITS(cp); 17017680Spst cp += 2; 17117680Spst } 17217680Spst printf(" %s%d", str, i); 17317680Spst return (cp); 17417680Spst} 17517680Spst 17617680Spststatic const u_char * 17717680Spstprint_sl_winchange(register const u_char *cp) 17817680Spst{ 17917680Spst register short i; 18017680Spst 18117680Spst if ((i = *cp++) == 0) { 18217680Spst i = EXTRACT_16BITS(cp); 18317680Spst cp += 2; 18417680Spst } 18517680Spst if (i >= 0) 18617680Spst printf(" W+%d", i); 18717680Spst else 18817680Spst printf(" W%d", i); 18917680Spst return (cp); 19017680Spst} 19117680Spst 19217680Spststatic void 19317680Spstcompressed_sl_print(const u_char *chdr, const struct ip *ip, 19417680Spst u_int length, int dir) 19517680Spst{ 19617680Spst register const u_char *cp = chdr; 19717680Spst register u_int flags, hlen; 19817680Spst 19917680Spst flags = *cp++; 20017680Spst if (flags & NEW_C) { 20117680Spst lastconn = *cp++; 20217680Spst printf("ctcp %d", lastconn); 20317680Spst } else 20417680Spst printf("ctcp *"); 20517680Spst 20617680Spst /* skip tcp checksum */ 20717680Spst cp += 2; 20817680Spst 20917680Spst switch (flags & SPECIALS_MASK) { 21017680Spst case SPECIAL_I: 21117680Spst printf(" *SA+%d", lastlen[dir][lastconn]); 21217680Spst break; 21317680Spst 21417680Spst case SPECIAL_D: 21517680Spst printf(" *S+%d", lastlen[dir][lastconn]); 21617680Spst break; 21717680Spst 21817680Spst default: 21917680Spst if (flags & NEW_U) 22017680Spst cp = print_sl_change("U=", cp); 22117680Spst if (flags & NEW_W) 22217680Spst cp = print_sl_winchange(cp); 22317680Spst if (flags & NEW_A) 22417680Spst cp = print_sl_change("A+", cp); 22517680Spst if (flags & NEW_S) 22617680Spst cp = print_sl_change("S+", cp); 22717680Spst break; 22817680Spst } 22917680Spst if (flags & NEW_I) 23017680Spst cp = print_sl_change("I+", cp); 23117680Spst 23217680Spst /* 23317680Spst * 'hlen' is the length of the uncompressed TCP/IP header (in words). 23417680Spst * 'cp - chdr' is the length of the compressed header. 23517680Spst * 'length - hlen' is the amount of data in the packet. 23617680Spst */ 23775118Sfenner hlen = IP_HL(ip); 23875118Sfenner hlen += TH_OFF((struct tcphdr *)&((int32_t *)ip)[hlen]); 23917680Spst lastlen[dir][lastconn] = length - (hlen << 2); 24075118Sfenner printf(" %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr)); 24117680Spst} 242