]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-sl.c
Turn off the "-O2 flag TRIGGERS KNOWN OPTIMIZER BUGS" warning.
[FreeBSD/FreeBSD.git] / contrib / 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  * $FreeBSD$
22  */
23
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Header: /tcpdump/master/tcpdump/print-sl.c,v 1.57 2001/07/05 18:54:17 guy Exp $ (LBL)";
27 #endif
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <sys/param.h>
34 #include <sys/time.h>
35
36 #include <netinet/in.h>
37
38 #include <ctype.h>
39 #include <netdb.h>
40 #include <pcap.h>
41 #include <stdio.h>
42
43 #include "interface.h"
44 #include "addrtoname.h"
45 #include "extract.h"                    /* must come after interface.h */
46
47 #include "ip.h"
48 #include "tcp.h"
49 #include "slip.h"
50 #include "slcompress.h"
51
52 static u_int lastlen[2][256];
53 static u_int lastconn = 255;
54
55 static void sliplink_print(const u_char *, const struct ip *, u_int);
56 static void compressed_sl_print(const u_char *, const struct ip *, u_int, int);
57
58 void
59 sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
60 {
61         register u_int caplen = h->caplen;
62         register u_int length = h->len;
63         register const struct ip *ip;
64
65         ++infodelay;
66         ts_print(&h->ts);
67
68         if (caplen < SLIP_HDRLEN) {
69                 printf("[|slip]");
70                 goto out;
71         }
72         /*
73          * Some printers want to get back at the link level addresses,
74          * and/or check that they're not walking off the end of the packet.
75          * Rather than pass them all the way down, we set these globals.
76          */
77         packetp = p;
78         snapend = p + caplen;
79
80         length -= SLIP_HDRLEN;
81
82         ip = (struct ip *)(p + SLIP_HDRLEN);
83
84         if (eflag)
85                 sliplink_print(p, ip, length);
86
87         switch (IP_V(ip)) {
88         case 4:
89                 ip_print((u_char *)ip, length);
90                 break;
91 #ifdef INET6
92         case 6:
93                 ip6_print((u_char *)ip, length);
94                 break;
95 #endif
96         default:
97                 printf ("ip v%d", IP_V(ip));
98         }
99
100         if (xflag)
101                 default_print((u_char *)ip, caplen - SLIP_HDRLEN);
102  out:
103         putchar('\n');
104         --infodelay;
105         if (infoprint)
106                 info(0);
107 }
108
109
110 void
111 sl_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
112 {
113         register u_int caplen = h->caplen;
114         register u_int length = h->len;
115         register const struct ip *ip;
116
117         ++infodelay;
118         ts_print(&h->ts);
119
120         if (caplen < SLIP_HDRLEN) {
121                 printf("[|slip]");
122                 goto out;
123         }
124         /*
125          * Some printers want to get back at the link level addresses,
126          * and/or check that they're not walking off the end of the packet.
127          * Rather than pass them all the way down, we set these globals.
128          */
129         packetp = p;
130         snapend = p + caplen;
131
132         length -= SLIP_HDRLEN;
133
134         ip = (struct ip *)(p + SLIP_HDRLEN);
135
136 #ifdef notdef
137         if (eflag)
138                 sliplink_print(p, ip, length);
139 #endif
140
141         ip_print((u_char *)ip, length);
142
143         if (xflag)
144                 default_print((u_char *)ip, caplen - SLIP_HDRLEN);
145  out:
146         putchar('\n');
147         --infodelay;
148         if (infoprint)
149                 info(0);
150 }
151
152 static void
153 sliplink_print(register const u_char *p, register const struct ip *ip,
154                register u_int length)
155 {
156         int dir;
157         u_int hlen;
158
159         dir = p[SLX_DIR];
160         putchar(dir == SLIPDIR_IN ? 'I' : 'O');
161         putchar(' ');
162
163         if (nflag) {
164                 /* XXX just dump the header */
165                 register int i;
166
167                 for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i)
168                         printf("%02x.", p[i]);
169                 printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]);
170                 return;
171         }
172         switch (p[SLX_CHDR] & 0xf0) {
173
174         case TYPE_IP:
175                 printf("ip %d: ", length + SLIP_HDRLEN);
176                 break;
177
178         case TYPE_UNCOMPRESSED_TCP:
179                 /*
180                  * The connection id is stored in the IP protocol field.
181                  * Get it from the link layer since sl_uncompress_tcp()
182                  * has restored the IP header copy to IPPROTO_TCP.
183                  */
184                 lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p;
185                 hlen = IP_HL(ip);
186                 hlen += TH_OFF((struct tcphdr *)&((int *)ip)[hlen]);
187                 lastlen[dir][lastconn] = length - (hlen << 2);
188                 printf("utcp %d: ", lastconn);
189                 break;
190
191         default:
192                 if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) {
193                         compressed_sl_print(&p[SLX_CHDR], ip,
194                             length, dir);
195                         printf(": ");
196                 } else
197                         printf("slip-%d!: ", p[SLX_CHDR]);
198         }
199 }
200
201 static const u_char *
202 print_sl_change(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         printf(" %s%d", str, i);
211         return (cp);
212 }
213
214 static const u_char *
215 print_sl_winchange(register const u_char *cp)
216 {
217         register short i;
218
219         if ((i = *cp++) == 0) {
220                 i = EXTRACT_16BITS(cp);
221                 cp += 2;
222         }
223         if (i >= 0)
224                 printf(" W+%d", i);
225         else
226                 printf(" W%d", i);
227         return (cp);
228 }
229
230 static void
231 compressed_sl_print(const u_char *chdr, const struct ip *ip,
232                     u_int length, int dir)
233 {
234         register const u_char *cp = chdr;
235         register u_int flags, hlen;
236
237         flags = *cp++;
238         if (flags & NEW_C) {
239                 lastconn = *cp++;
240                 printf("ctcp %d", lastconn);
241         } else
242                 printf("ctcp *");
243
244         /* skip tcp checksum */
245         cp += 2;
246
247         switch (flags & SPECIALS_MASK) {
248         case SPECIAL_I:
249                 printf(" *SA+%d", lastlen[dir][lastconn]);
250                 break;
251
252         case SPECIAL_D:
253                 printf(" *S+%d", lastlen[dir][lastconn]);
254                 break;
255
256         default:
257                 if (flags & NEW_U)
258                         cp = print_sl_change("U=", cp);
259                 if (flags & NEW_W)
260                         cp = print_sl_winchange(cp);
261                 if (flags & NEW_A)
262                         cp = print_sl_change("A+", cp);
263                 if (flags & NEW_S)
264                         cp = print_sl_change("S+", cp);
265                 break;
266         }
267         if (flags & NEW_I)
268                 cp = print_sl_change("I+", cp);
269
270         /*
271          * 'hlen' is the length of the uncompressed TCP/IP header (in words).
272          * 'cp - chdr' is the length of the compressed header.
273          * 'length - hlen' is the amount of data in the packet.
274          */
275         hlen = IP_HL(ip);
276         hlen += TH_OFF((struct tcphdr *)&((int32_t *)ip)[hlen]);
277         lastlen[dir][lastconn] = length - (hlen << 2);
278         printf(" %d (%ld)", lastlen[dir][lastconn], (long)(cp - chdr));
279 }