Home | History | Annotate | Line # | Download | only in dist
print-sl.c revision 1.8
      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.8 2017/09/08 14:01:13 christos Exp $");
     25 #endif
     26 
     27 /* \summary: Compressed Serial Line Internet Protocol printer */
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #include "config.h"
     31 #endif
     32 
     33 #include <netdissect-stdinc.h>
     34 
     35 #include "netdissect.h"
     36 #include "extract.h"
     37 
     38 #include "ip.h"
     39 #include "tcp.h"
     40 #include "slcompress.h"
     41 
     42 /*
     43  * definitions of the pseudo- link-level header attached to slip
     44  * packets grabbed by the packet filter (bpf) traffic monitor.
     45  */
     46 #define SLIP_HDRLEN 16
     47 
     48 #define SLX_DIR 0
     49 #define SLX_CHDR 1
     50 #define CHDR_LEN 15
     51 
     52 #define SLIPDIR_IN 0
     53 #define SLIPDIR_OUT 1
     54 
     55 static const char tstr[] = "[|slip]";
     56 
     57 static u_int lastlen[2][256];
     58 static u_int lastconn = 255;
     59 
     60 static void sliplink_print(netdissect_options *, const u_char *, const struct ip *, u_int);
     61 static void compressed_sl_print(netdissect_options *, const u_char *, const struct ip *, u_int, int);
     62 
     63 u_int
     64 sl_if_print(netdissect_options *ndo,
     65             const struct pcap_pkthdr *h, const u_char *p)
     66 {
     67 	register u_int caplen = h->caplen;
     68 	register u_int length = h->len;
     69 	register const struct ip *ip;
     70 
     71 	if (caplen < SLIP_HDRLEN || length < SLIP_HDRLEN) {
     72 		ND_PRINT((ndo, "%s", tstr));
     73 		return (caplen);
     74 	}
     75 
     76 	caplen -= SLIP_HDRLEN;
     77 	length -= SLIP_HDRLEN;
     78 
     79 	ip = (const struct ip *)(p + SLIP_HDRLEN);
     80 
     81 	if (ndo->ndo_eflag)
     82 		sliplink_print(ndo, p, ip, length);
     83 
     84 	if (caplen < 1 || length < 1) {
     85 		ND_PRINT((ndo, "%s", tstr));
     86 		return (caplen + SLIP_HDRLEN);
     87 	}
     88 
     89 	switch (IP_V(ip)) {
     90 	case 4:
     91 	        ip_print(ndo, (const u_char *)ip, length);
     92 		break;
     93 	case 6:
     94 		ip6_print(ndo, (const u_char *)ip, length);
     95 		break;
     96 	default:
     97 		ND_PRINT((ndo, "ip v%d", IP_V(ip)));
     98 	}
     99 
    100 	return (SLIP_HDRLEN);
    101 }
    102 
    103 u_int
    104 sl_bsdos_if_print(netdissect_options *ndo,
    105                   const struct pcap_pkthdr *h, const u_char *p)
    106 {
    107 	register u_int caplen = h->caplen;
    108 	register u_int length = h->len;
    109 	register const struct ip *ip;
    110 
    111 	if (caplen < SLIP_HDRLEN) {
    112 		ND_PRINT((ndo, "%s", tstr));
    113 		return (caplen);
    114 	}
    115 
    116 	length -= SLIP_HDRLEN;
    117 
    118 	ip = (const struct ip *)(p + SLIP_HDRLEN);
    119 
    120 #ifdef notdef
    121 	if (ndo->ndo_eflag)
    122 		sliplink_print(ndo, p, ip, length);
    123 #endif
    124 
    125 	ip_print(ndo, (const u_char *)ip, length);
    126 
    127 	return (SLIP_HDRLEN);
    128 }
    129 
    130 static void
    131 sliplink_print(netdissect_options *ndo,
    132                register const u_char *p, register const struct ip *ip,
    133                register u_int length)
    134 {
    135 	int dir;
    136 	u_int hlen;
    137 
    138 	dir = p[SLX_DIR];
    139 	switch (dir) {
    140 
    141 	case SLIPDIR_IN:
    142 		ND_PRINT((ndo, "I "));
    143 		break;
    144 
    145 	case SLIPDIR_OUT:
    146 		ND_PRINT((ndo, "O "));
    147 		break;
    148 
    149 	default:
    150 		ND_PRINT((ndo, "Invalid direction %d ", dir));
    151 		dir = -1;
    152 		break;
    153 	}
    154 	if (ndo->ndo_nflag) {
    155 		/* XXX just dump the header */
    156 		register int i;
    157 
    158 		for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i)
    159 			ND_PRINT((ndo, "%02x.", p[i]));
    160 		ND_PRINT((ndo, "%02x: ", p[SLX_CHDR + CHDR_LEN - 1]));
    161 		return;
    162 	}
    163 	switch (p[SLX_CHDR] & 0xf0) {
    164 
    165 	case TYPE_IP:
    166 		ND_PRINT((ndo, "ip %d: ", length + SLIP_HDRLEN));
    167 		break;
    168 
    169 	case TYPE_UNCOMPRESSED_TCP:
    170 		/*
    171 		 * The connection id is stored in the IP protocol field.
    172 		 * Get it from the link layer since sl_uncompress_tcp()
    173 		 * has restored the IP header copy to IPPROTO_TCP.
    174 		 */
    175 		lastconn = ((const struct ip *)&p[SLX_CHDR])->ip_p;
    176 		ND_PRINT((ndo, "utcp %d: ", lastconn));
    177 		if (dir == -1) {
    178 			/* Direction is bogus, don't use it */
    179 			return;
    180 		}
    181 		hlen = IP_HL(ip);
    182 		hlen += TH_OFF((const struct tcphdr *)&((const int *)ip)[hlen]);
    183 		lastlen[dir][lastconn] = length - (hlen << 2);
    184 		break;
    185 
    186 	default:
    187 		if (dir == -1) {
    188 			/* Direction is bogus, don't use it */
    189 			return;
    190 		}
    191 		if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
    192 			compressed_sl_print(ndo, &p[SLX_CHDR], ip,
    193 			    length, dir);
    194 			ND_PRINT((ndo, ": "));
    195 		} else
    196 			ND_PRINT((ndo, "slip-%d!: ", p[SLX_CHDR]));
    197 	}
    198 }
    199 
    200 static const u_char *
    201 print_sl_change(netdissect_options *ndo,
    202                 const char *str, register const u_char *cp)
    203 {
    204 	register u_int i;
    205 
    206 	if ((i = *cp++) == 0) {
    207 		i = EXTRACT_16BITS(cp);
    208 		cp += 2;
    209 	}
    210 	ND_PRINT((ndo, " %s%d", str, i));
    211 	return (cp);
    212 }
    213 
    214 static const u_char *
    215 print_sl_winchange(netdissect_options *ndo,
    216                    register const u_char *cp)
    217 {
    218 	register short i;
    219 
    220 	if ((i = *cp++) == 0) {
    221 		i = EXTRACT_16BITS(cp);
    222 		cp += 2;
    223 	}
    224 	if (i >= 0)
    225 		ND_PRINT((ndo, " W+%d", i));
    226 	else
    227 		ND_PRINT((ndo, " W%d", i));
    228 	return (cp);
    229 }
    230 
    231 static void
    232 compressed_sl_print(netdissect_options *ndo,
    233                     const u_char *chdr, const struct ip *ip,
    234                     u_int length, int dir)
    235 {
    236 	register const u_char *cp = chdr;
    237 	register u_int flags, hlen;
    238 
    239 	flags = *cp++;
    240 	if (flags & NEW_C) {
    241 		lastconn = *cp++;
    242 		ND_PRINT((ndo, "ctcp %d", lastconn));
    243 	} else
    244 		ND_PRINT((ndo, "ctcp *"));
    245 
    246 	/* skip tcp checksum */
    247 	cp += 2;
    248 
    249 	switch (flags & SPECIALS_MASK) {
    250 	case SPECIAL_I:
    251 		ND_PRINT((ndo, " *SA+%d", lastlen[dir][lastconn]));
    252 		break;
    253 
    254 	case SPECIAL_D:
    255 		ND_PRINT((ndo, " *S+%d", lastlen[dir][lastconn]));
    256 		break;
    257 
    258 	default:
    259 		if (flags & NEW_U)
    260 			cp = print_sl_change(ndo, "U=", cp);
    261 		if (flags & NEW_W)
    262 			cp = print_sl_winchange(ndo, cp);
    263 		if (flags & NEW_A)
    264 			cp = print_sl_change(ndo, "A+", cp);
    265 		if (flags & NEW_S)
    266 			cp = print_sl_change(ndo, "S+", cp);
    267 		break;
    268 	}
    269 	if (flags & NEW_I)
    270 		cp = print_sl_change(ndo, "I+", cp);
    271 
    272 	/*
    273 	 * 'hlen' is the length of the uncompressed TCP/IP header (in words).
    274 	 * 'cp - chdr' is the length of the compressed header.
    275 	 * 'length - hlen' is the amount of data in the packet.
    276 	 */
    277 	hlen = IP_HL(ip);
    278 	hlen += TH_OFF((const struct tcphdr *)&((const int32_t *)ip)[hlen]);
    279 	lastlen[dir][lastconn] = length - (hlen << 2);
    280 	ND_PRINT((ndo, " %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr)));
    281 }
    282