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