1 /*
2 * Copyright (c) 1988-1990 The Regents of the University of California.
3 * 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 #ifndef lint
23 static char rcsid[] =
24 "@(#) $Header: print-ip.c,v 1.23 91/06/09 17:16:10 van Exp $ (LBL)";
25 #endif
26
27 #include <sys/param.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <netinet/in_systm.h>
32 #include <netinet/ip.h>
33 #include <netinet/ip_var.h>
34 #include <netinet/udp.h>
35 #include <netinet/udp_var.h>
36 #include <netinet/tcp.h>
37 #include <netinet/tcpip.h>
38
39 #include "interface.h"
40 #include "addrtoname.h"
41
42 void
igmp_print(cp,len,ip)43 igmp_print(cp, len, ip)
44 register u_char *cp;
45 register int len;
46 register struct ip *ip;
47 {
48 register u_char *ep = (u_char *)snapend;
49
50 (void)printf("%s > %s: ",
51 ipaddr_string(&ip->ip_src),
52 ipaddr_string(&ip->ip_dst));
53
54 if (cp + 7 > ep) {
55 (void)printf("[|igmp]");
56 return;
57 }
58 switch (cp[0] & 0xf) {
59 case 1:
60 (void)printf("igmp query");
61 if (*(int *)&cp[4])
62 (void)printf(" [gaddr %s]", ipaddr_string(&cp[4]));
63 if (len != 8)
64 (void)printf(" [len %d]", len);
65 break;
66 case 2:
67 (void)printf("igmp report %s", ipaddr_string(&cp[4]));
68 if (len != 8)
69 (void)printf(" [len %d]", len);
70 break;
71 case 3:
72 (void)printf("igmp dvmrp", ipaddr_string(&cp[4]));
73 if (len < 8)
74 (void)printf(" [len %d]", len);
75 break;
76 default:
77 (void)printf("igmp-%d", cp[0] & 0xf);
78 break;
79 }
80 if ((cp[0] >> 4) != 1)
81 (void)printf(" [v%d]", cp[0] >> 4);
82 if (cp[1])
83 (void)printf(" [b1=0x%x]", cp[1]);
84 }
85
86 /*
87 * print the recorded route in an IP RR, LSRR or SSRR option.
88 */
89 static void
ip_printroute(type,cp,length)90 ip_printroute(type, cp, length)
91 char *type;
92 register u_char *cp;
93 int length;
94 {
95 int ptr = cp[2] - 1;
96 int len;
97
98 printf(" %s{", type);
99 if ((length + 1) & 3)
100 printf(" [bad length %d]", length);
101 if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1)
102 printf(" [bad ptr %d]", cp[2]);
103
104 type = "";
105 for (len = 3; len < length; len += 4) {
106 if (ptr == len)
107 type = "#";
108 #ifdef ALIGN
109 {
110 struct in_addr addr;
111 bcopy((char *)&cp[len], (char *)&addr, sizeof(addr));
112 printf("%s%s", type, ipaddr_string(&addr));
113 }
114 #else
115 printf("%s%s", type, ipaddr_string(&cp[len]));
116 #endif
117 type = " ";
118 }
119 printf("%s}", ptr == len? "#" : "");
120 }
121
122 /*
123 * print IP options.
124 */
125 static void
ip_optprint(cp,length)126 ip_optprint(cp, length)
127 register u_char *cp;
128 int length;
129 {
130 int len;
131
132 for (; length > 0; cp += len, length -= len) {
133 int tt = *cp;
134
135 len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1];
136 if (&cp[1] >= snapend || cp + len > snapend) {
137 printf("[|ip]");
138 return;
139 }
140 switch (tt) {
141
142 case IPOPT_EOL:
143 printf(" EOL");
144 if (length > 1)
145 printf("-%d", length - 1);
146 return;
147
148 case IPOPT_NOP:
149 printf(" NOP");
150 break;
151
152 case IPOPT_TS:
153 printf(" TS{%d}", len);
154 break;
155
156 case IPOPT_SECURITY:
157 printf(" SECURITY{%d}", len);
158 break;
159
160 case IPOPT_RR:
161 printf(" RR{%d}=", len);
162 ip_printroute("RR", cp, len);
163 break;
164
165 case IPOPT_SSRR:
166 ip_printroute("SSRR", cp, len);
167 break;
168
169 case IPOPT_LSRR:
170 ip_printroute("LSRR", cp, len);
171 break;
172
173 default:
174 printf(" IPOPT-%d{%d}", cp[0], len);
175 break;
176 }
177 }
178 }
179
180 /*
181 * print an IP datagram.
182 */
183 void
ip_print(ip,length)184 ip_print(ip, length)
185 register struct ip *ip;
186 register int length;
187 {
188 register int hlen;
189 register int len;
190 register unsigned char *cp;
191
192 #ifdef ALIGN
193 static u_char *abuf;
194 /*
195 * The IP header is not word aligned, so copy into abuf.
196 * This will never happen with BPF. Maybe with should #ifdef
197 * on that too. XXX
198 */
199 if ((int)ip & (sizeof(long)-1)) {
200 if (abuf == 0)
201 abuf = (u_char *)malloc(snaplen);
202 bcopy((char *)ip, (char *)abuf, min(length, snaplen));
203 snapend += abuf - (u_char *)ip;
204 packetp = abuf;
205 ip = (struct ip *)abuf;
206 }
207 #endif
208 if ((u_char *)(ip + 1) > snapend) {
209 printf("[|ip]");
210 return;
211 }
212 if (length < sizeof (struct ip)) {
213 (void)printf("truncated-ip %d", length);
214 return;
215 }
216 hlen = ip->ip_hl * 4;
217
218 NTOHS(ip->ip_len);
219 NTOHS(ip->ip_off);
220 NTOHS(ip->ip_id);
221
222 len = ip->ip_len - hlen;
223 if (length < ip->ip_len)
224 (void)printf("truncated-ip - %d bytes missing!",
225 ip->ip_len - length);
226
227 /*
228 * If this is fragment zero, hand it to the next higher
229 * level protocol.
230 */
231 if ((ip->ip_off & 0x1fff) == 0) {
232 cp = (unsigned char *)ip + hlen;
233 switch (ip->ip_p) {
234
235 case IPPROTO_TCP:
236 tcp_print((struct tcphdr *)cp, len, ip);
237 break;
238 case IPPROTO_UDP:
239 udp_print((struct udphdr *)cp, len, ip);
240 break;
241 case IPPROTO_ICMP:
242 icmp_print((struct icmp *)cp, ip);
243 break;
244 case IPPROTO_ND:
245 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
246 ipaddr_string(&ip->ip_dst));
247 (void)printf(" nd %d", len);
248 break;
249 case 2: /* XXX - IPPROTO_IGMP */
250 igmp_print(cp, len, ip);
251 break;
252 default:
253 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
254 ipaddr_string(&ip->ip_dst));
255 (void)printf(" ip-proto-%d %d", ip->ip_p, len);
256 break;
257 }
258 }
259 /*
260 * for fragmented datagrams, print id:size@offset. On all
261 * but the last stick a "+". For unfragmented datagrams, note
262 * the don't fragment flag.
263 */
264 if (ip->ip_off & 0x3fff) {
265 /*
266 * if this isn't the first frag, we're missing the
267 * next level protocol header. print the ip addr.
268 */
269 if (ip->ip_off & 0x1fff)
270 (void)printf("%s > %s:", ipaddr_string(&ip->ip_src),
271 ipaddr_string(&ip->ip_dst));
272 (void)printf(" (frag %x:%d@%d%s)", ip->ip_id, len,
273 (ip->ip_off & 0x1fff) * 8,
274 (ip->ip_off & IP_MF)? "+" : "");
275 } else if (ip->ip_off & IP_DF)
276 (void)printf(" (DF)");
277
278 if (ip->ip_tos)
279 (void)printf(" [tos 0x%x]", (int)ip->ip_tos);
280 if (ip->ip_ttl <= 1)
281 (void)printf(" [ttl %d]", (int)ip->ip_ttl);
282
283 if (vflag) {
284 char *sep = "";
285
286 printf(" (");
287 if (ip->ip_ttl > 1) {
288 (void)printf("%sttl %d", sep, (int)ip->ip_ttl);
289 sep = ", ";
290 }
291 if ((ip->ip_off & 0x3fff) == 0) {
292 (void)printf("%sid %d", sep, (int)ip->ip_id);
293 sep = ", ";
294 }
295 if ((hlen -= sizeof(struct ip)) > 0) {
296 (void)printf("%soptlen=%d", sep, hlen);
297 ip_optprint((u_char *)(ip + 1), hlen);
298 }
299 printf(")");
300 }
301 }
302