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