Home | History | Annotate | Line # | Download | only in dist
print-sl.c revision 1.5
      1 /*
      2  * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that: (1) source code distributions
      7  * retain the above copyright notice and this paragraph in its entirety, (2)
      8  * distributions including binary code include the above copyright notice and
      9  * this paragraph in its entirety in the documentation or other materials
     10  * provided with the distribution, and (3) all advertising materials mentioning
     11  * features or use of this software display the following acknowledgement:
     12  * ``This product includes software developed by the University of California,
     13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
     14  * the University nor the names of its contributors may be used to endorse
     15  * or promote products derived from this software without specific prior
     16  * written permission.
     17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
     20  */
     21 
     22 #include <sys/cdefs.h>
     23 #ifndef lint
     24 __RCSID("$NetBSD: print-sl.c,v 1.5 2015/03/31 21:59:35 christos Exp $");
     25 #endif
     26 
     27 #define NETDISSECT_REWORKED
     28 #ifdef HAVE_CONFIG_H
     29 #include "config.h"
     30 #endif
     31 
     32 #include <tcpdump-stdinc.h>
     33 
     34 #include "interface.h"
     35 #include "extract.h"			/* must come after interface.h */
     36 
     37 #include "ip.h"
     38 #include "tcp.h"
     39 #include "slcompress.h"
     40 
     41 /*
     42  * definitions of the pseudo- link-level header attached to slip
     43  * packets grabbed by the packet filter (bpf) traffic monitor.
     44  */
     45 #define SLIP_HDRLEN 16
     46 
     47 #define SLX_DIR 0
     48 #define SLX_CHDR 1
     49 #define CHDR_LEN 15
     50 
     51 #define SLIPDIR_IN 0
     52 #define SLIPDIR_OUT 1
     53 
     54 static const char tstr[] = "[|slip]";
     55 
     56 static u_int lastlen[2][256];
     57 static u_int lastconn = 255;
     58 
     59 static void sliplink_print(netdissect_options *, const u_char *, const struct ip *, u_int);
     60 static void compressed_sl_print(netdissect_options *, const u_char *, const struct ip *, u_int, int);
     61 
     62 u_int
     63 sl_if_print(netdissect_options *ndo,
     64             const struct pcap_pkthdr *h, const u_char *p)
     65 {
     66 	register u_int caplen = h->caplen;
     67 	register u_int length = h->len;
     68 	register const struct ip *ip;
     69 
     70 	if (caplen < SLIP_HDRLEN || length < SLIP_HDRLEN) {
     71 		ND_PRINT((ndo, "%s", tstr));
     72 		return (caplen);
     73 	}
     74 
     75 	length -= SLIP_HDRLEN;
     76 
     77 	ip = (struct ip *)(p + SLIP_HDRLEN);
     78 
     79 	if (ndo->ndo_eflag)
     80 		sliplink_print(ndo, p, ip, length);
     81 
     82 	switch (IP_V(ip)) {
     83 	case 4:
     84 	        ip_print(ndo, (u_char *)ip, length);
     85 		break;
     86 	case 6:
     87 		ip6_print(ndo, (u_char *)ip, length);
     88 		break;
     89 	default:
     90 		ND_PRINT((ndo, "ip v%d", IP_V(ip)));
     91 	}
     92 
     93 	return (SLIP_HDRLEN);
     94 }
     95 
     96 u_int
     97 sl_bsdos_if_print(netdissect_options *ndo,
     98                   const struct pcap_pkthdr *h, const u_char *p)
     99 {
    100 	register u_int caplen = h->caplen;
    101 	register u_int length = h->len;
    102 	register const struct ip *ip;
    103 
    104 	if (caplen < SLIP_HDRLEN) {
    105 		ND_PRINT((ndo, "%s", tstr));
    106 		return (caplen);
    107 	}
    108 
    109 	length -= SLIP_HDRLEN;
    110 
    111 	ip = (struct ip *)(p + SLIP_HDRLEN);
    112 
    113 #ifdef notdef
    114 	if (ndo->ndo_eflag)
    115 		sliplink_print(ndo, p, ip, length);
    116 #endif
    117 
    118 	ip_print(ndo, (u_char *)ip, length);
    119 
    120 	return (SLIP_HDRLEN);
    121 }
    122 
    123 static void
    124 sliplink_print(netdissect_options *ndo,
    125                register const u_char *p, register const struct ip *ip,
    126                register u_int length)
    127 {
    128 	int dir;
    129 	u_int hlen;
    130 
    131 	dir = p[SLX_DIR];
    132 	ND_PRINT((ndo, dir == SLIPDIR_IN ? "I " : "O "));
    133 
    134 	if (ndo->ndo_nflag) {
    135 		/* XXX just dump the header */
    136 		register int i;
    137 
    138 		for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i)
    139 			ND_PRINT((ndo, "%02x.", p[i]));
    140 		ND_PRINT((ndo, "%02x: ", p[SLX_CHDR + CHDR_LEN - 1]));
    141 		return;
    142 	}
    143 	switch (p[SLX_CHDR] & 0xf0) {
    144 
    145 	case TYPE_IP:
    146 		ND_PRINT((ndo, "ip %d: ", length + SLIP_HDRLEN));
    147 		break;
    148 
    149 	case TYPE_UNCOMPRESSED_TCP:
    150 		/*
    151 		 * The connection id is stored in the IP protocol field.
    152 		 * Get it from the link layer since sl_uncompress_tcp()
    153 		 * has restored the IP header copy to IPPROTO_TCP.
    154 		 */
    155 		lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p;
    156 		hlen = IP_HL(ip);
    157 		hlen += TH_OFF((struct tcphdr *)&((int *)ip)[hlen]);
    158 		lastlen[dir][lastconn] = length - (hlen << 2);
    159 		ND_PRINT((ndo, "utcp %d: ", lastconn));
    160 		break;
    161 
    162 	default:
    163 		if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
    164 			compressed_sl_print(ndo, &p[SLX_CHDR], ip,
    165 			    length, dir);
    166 			ND_PRINT((ndo, ": "));
    167 		} else
    168 			ND_PRINT((ndo, "slip-%d!: ", p[SLX_CHDR]));
    169 	}
    170 }
    171 
    172 static const u_char *
    173 print_sl_change(netdissect_options *ndo,
    174                 const char *str, register const u_char *cp)
    175 {
    176 	register u_int i;
    177 
    178 	if ((i = *cp++) == 0) {
    179 		i = EXTRACT_16BITS(cp);
    180 		cp += 2;
    181 	}
    182 	ND_PRINT((ndo, " %s%d", str, i));
    183 	return (cp);
    184 }
    185 
    186 static const u_char *
    187 print_sl_winchange(netdissect_options *ndo,
    188                    register const u_char *cp)
    189 {
    190 	register short i;
    191 
    192 	if ((i = *cp++) == 0) {
    193 		i = EXTRACT_16BITS(cp);
    194 		cp += 2;
    195 	}
    196 	if (i >= 0)
    197 		ND_PRINT((ndo, " W+%d", i));
    198 	else
    199 		ND_PRINT((ndo, " W%d", i));
    200 	return (cp);
    201 }
    202 
    203 static void
    204 compressed_sl_print(netdissect_options *ndo,
    205                     const u_char *chdr, const struct ip *ip,
    206                     u_int length, int dir)
    207 {
    208 	register const u_char *cp = chdr;
    209 	register u_int flags, hlen;
    210 
    211 	flags = *cp++;
    212 	if (flags & NEW_C) {
    213 		lastconn = *cp++;
    214 		ND_PRINT((ndo, "ctcp %d", lastconn));
    215 	} else
    216 		ND_PRINT((ndo, "ctcp *"));
    217 
    218 	/* skip tcp checksum */
    219 	cp += 2;
    220 
    221 	switch (flags & SPECIALS_MASK) {
    222 	case SPECIAL_I:
    223 		ND_PRINT((ndo, " *SA+%d", lastlen[dir][lastconn]));
    224 		break;
    225 
    226 	case SPECIAL_D:
    227 		ND_PRINT((ndo, " *S+%d", lastlen[dir][lastconn]));
    228 		break;
    229 
    230 	default:
    231 		if (flags & NEW_U)
    232 			cp = print_sl_change(ndo, "U=", cp);
    233 		if (flags & NEW_W)
    234 			cp = print_sl_winchange(ndo, cp);
    235 		if (flags & NEW_A)
    236 			cp = print_sl_change(ndo, "A+", cp);
    237 		if (flags & NEW_S)
    238 			cp = print_sl_change(ndo, "S+", cp);
    239 		break;
    240 	}
    241 	if (flags & NEW_I)
    242 		cp = print_sl_change(ndo, "I+", cp);
    243 
    244 	/*
    245 	 * 'hlen' is the length of the uncompressed TCP/IP header (in words).
    246 	 * 'cp - chdr' is the length of the compressed header.
    247 	 * 'length - hlen' is the amount of data in the packet.
    248 	 */
    249 	hlen = IP_HL(ip);
    250 	hlen += TH_OFF((struct tcphdr *)&((int32_t *)ip)[hlen]);
    251 	lastlen[dir][lastconn] = length - (hlen << 2);
    252 	ND_PRINT((ndo, " %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr)));
    253 }
    254