]> git.saurik.com Git - apple/network_cmds.git/blob - tcpdump.tproj/print-udp.c
f8e4366faeb58ee5e437817f3c5ca8608f335c61
[apple/network_cmds.git] / tcpdump.tproj / print-udp.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that: (1) source code distributions
30 * retain the above copyright notice and this paragraph in its entirety, (2)
31 * distributions including binary code include the above copyright notice and
32 * this paragraph in its entirety in the documentation or other materials
33 * provided with the distribution, and (3) all advertising materials mentioning
34 * features or use of this software display the following acknowledgement:
35 * ``This product includes software developed by the University of California,
36 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
37 * the University nor the names of its contributors may be used to endorse
38 * or promote products derived from this software without specific prior
39 * written permission.
40 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
41 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
42 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
43 */
44
45 #ifndef lint
46 static const char rcsid[] =
47 "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-udp.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)";
48 #endif
49
50 #include <sys/param.h>
51 #include <sys/time.h>
52 #include <sys/socket.h>
53
54 #include <netinet/in.h>
55 #include <netinet/in_systm.h>
56 #include <netinet/ip.h>
57 #include <netinet/ip_var.h>
58 #include <netinet/udp.h>
59 #include <netinet/udp_var.h>
60
61 #undef NOERROR /* Solaris sucks */
62 #undef T_UNSPEC /* SINIX does too */
63 #include <arpa/nameser.h>
64 #include <arpa/tftp.h>
65
66 #include <rpc/rpc.h>
67
68 #include <stdio.h>
69
70 #include "interface.h"
71 #include "addrtoname.h"
72 #include "appletalk.h"
73
74 #include "nfsv2.h"
75 #include "bootp.h"
76
77 struct rtcphdr {
78 u_short rh_flags; /* T:2 P:1 CNT:5 PT:8 */
79 u_short rh_len; /* length of message (in words) */
80 u_int rh_ssrc; /* synchronization src id */
81 };
82
83 typedef struct {
84 u_int upper; /* more significant 32 bits */
85 u_int lower; /* less significant 32 bits */
86 } ntp64;
87
88 /*
89 * Sender report.
90 */
91 struct rtcp_sr {
92 ntp64 sr_ntp; /* 64-bit ntp timestamp */
93 u_int sr_ts; /* reference media timestamp */
94 u_int sr_np; /* no. packets sent */
95 u_int sr_nb; /* no. bytes sent */
96 };
97
98 /*
99 * Receiver report.
100 * Time stamps are middle 32-bits of ntp timestamp.
101 */
102 struct rtcp_rr {
103 u_int rr_srcid; /* sender being reported */
104 u_int rr_nl; /* no. packets lost */
105 u_int rr_ls; /* extended last seq number received */
106 u_int rr_dv; /* jitter (delay variance) */
107 u_int rr_lsr; /* orig. ts from last rr from this src */
108 u_int rr_dlsr; /* time from recpt of last rr to xmit time */
109 };
110
111 /*XXX*/
112 #define RTCP_PT_SR 200
113 #define RTCP_PT_RR 201
114 #define RTCP_PT_SDES 202
115 #define RTCP_SDES_CNAME 1
116 #define RTCP_SDES_NAME 2
117 #define RTCP_SDES_EMAIL 3
118 #define RTCP_SDES_PHONE 4
119 #define RTCP_SDES_LOC 5
120 #define RTCP_SDES_TOOL 6
121 #define RTCP_SDES_NOTE 7
122 #define RTCP_SDES_PRIV 8
123 #define RTCP_PT_BYE 203
124 #define RTCP_PT_APP 204
125
126 static void
127 vat_print(const void *hdr, u_int len, register const struct udphdr *up)
128 {
129 /* vat/vt audio */
130 u_int ts = *(u_short *)hdr;
131 if ((ts & 0xf060) != 0) {
132 /* probably vt */
133 (void)printf(" udp/vt %u %d / %d",
134 (u_int32_t)(ntohs(up->uh_ulen) - sizeof(*up)),
135 ts & 0x3ff, ts >> 10);
136 } else {
137 /* probably vat */
138 u_int i0 = ntohl(((u_int *)hdr)[0]);
139 u_int i1 = ntohl(((u_int *)hdr)[1]);
140 printf(" udp/vat %u c%d %u%s",
141 (u_int32_t)(ntohs(up->uh_ulen) - sizeof(*up) - 8),
142 i0 & 0xffff,
143 i1, i0 & 0x800000? "*" : "");
144 /* audio format */
145 if (i0 & 0x1f0000)
146 printf(" f%d", (i0 >> 16) & 0x1f);
147 if (i0 & 0x3f000000)
148 printf(" s%d", (i0 >> 24) & 0x3f);
149 }
150 }
151
152 static void
153 rtp_print(const void *hdr, u_int len, register const struct udphdr *up)
154 {
155 /* rtp v1 or v2 */
156 u_int *ip = (u_int *)hdr;
157 u_int hasopt, hasext, contype, hasmarker;
158 u_int i0 = ntohl(((u_int *)hdr)[0]);
159 u_int i1 = ntohl(((u_int *)hdr)[1]);
160 u_int dlen = ntohs(up->uh_ulen) - sizeof(*up) - 8;
161 const char * ptype;
162
163 ip += 2;
164 len >>= 2;
165 len -= 2;
166 hasopt = 0;
167 hasext = 0;
168 if ((i0 >> 30) == 1) {
169 /* rtp v1 */
170 hasopt = i0 & 0x800000;
171 contype = (i0 >> 16) & 0x3f;
172 hasmarker = i0 & 0x400000;
173 ptype = "rtpv1";
174 } else {
175 /* rtp v2 */
176 hasext = i0 & 0x10000000;
177 contype = (i0 >> 16) & 0x7f;
178 hasmarker = i0 & 0x800000;
179 dlen -= 4;
180 ptype = "rtp";
181 ip += 1;
182 len -= 1;
183 }
184 printf(" udp/%s %d c%d %s%s %d %u",
185 ptype,
186 dlen,
187 contype,
188 (hasopt || hasext)? "+" : "",
189 hasmarker? "*" : "",
190 i0 & 0xffff,
191 i1);
192 if (vflag) {
193 printf(" %u", i1);
194 if (hasopt) {
195 u_int i2, optlen;
196 do {
197 i2 = ip[0];
198 optlen = (i2 >> 16) & 0xff;
199 if (optlen == 0 || optlen > len) {
200 printf(" !opt");
201 return;
202 }
203 ip += optlen;
204 len -= optlen;
205 } while ((int)i2 >= 0);
206 }
207 if (hasext) {
208 u_int i2, extlen;
209 i2 = ip[0];
210 extlen = (i2 & 0xffff) + 1;
211 if (extlen > len) {
212 printf(" !ext");
213 return;
214 }
215 ip += extlen;
216 }
217 if (contype == 0x1f) /*XXX H.261 */
218 printf(" 0x%04x", ip[0] >> 16);
219 }
220 }
221
222 static const u_char *
223 rtcp_print(const u_char *hdr, const u_char *ep)
224 {
225 /* rtp v2 control (rtcp) */
226 struct rtcp_rr *rr = 0;
227 struct rtcp_sr *sr;
228 struct rtcphdr *rh = (struct rtcphdr *)hdr;
229 u_int len;
230 u_short flags;
231 int cnt;
232 double ts, dts;
233 if ((u_char *)(rh + 1) > ep) {
234 printf(" [|rtcp]");
235 return (ep);
236 }
237 len = (ntohs(rh->rh_len) + 1) * 4;
238 flags = ntohs(rh->rh_flags);
239 cnt = (flags >> 8) & 0x1f;
240 switch (flags & 0xff) {
241 case RTCP_PT_SR:
242 sr = (struct rtcp_sr *)(rh + 1);
243 printf(" sr");
244 if (len != cnt * sizeof(*rr) + sizeof(*sr) + sizeof(*rh))
245 printf(" [%d]", len);
246 if (vflag)
247 printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc));
248 if ((u_char *)(sr + 1) > ep) {
249 printf(" [|rtcp]");
250 return (ep);
251 }
252 ts = (double)((u_int32_t)ntohl(sr->sr_ntp.upper)) +
253 ((double)((u_int32_t)ntohl(sr->sr_ntp.lower)) /
254 4294967296.0);
255 printf(" @%.2f %u %up %ub", ts, (u_int32_t)ntohl(sr->sr_ts),
256 (u_int32_t)ntohl(sr->sr_np), (u_int32_t)ntohl(sr->sr_nb));
257 rr = (struct rtcp_rr *)(sr + 1);
258 break;
259 case RTCP_PT_RR:
260 printf(" rr");
261 if (len != cnt * sizeof(*rr) + sizeof(*rh))
262 printf(" [%d]", len);
263 rr = (struct rtcp_rr *)(rh + 1);
264 if (vflag)
265 printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc));
266 break;
267 case RTCP_PT_SDES:
268 printf(" sdes %d", len);
269 if (vflag)
270 printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc));
271 cnt = 0;
272 break;
273 case RTCP_PT_BYE:
274 printf(" bye %d", len);
275 if (vflag)
276 printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc));
277 cnt = 0;
278 break;
279 default:
280 printf(" type-0x%x %d", flags & 0xff, len);
281 cnt = 0;
282 break;
283 }
284 if (cnt > 1)
285 printf(" c%d", cnt);
286 while (--cnt >= 0) {
287 if ((u_char *)(rr + 1) > ep) {
288 printf(" [|rtcp]");
289 return (ep);
290 }
291 if (vflag)
292 printf(" %u", (u_int32_t)ntohl(rr->rr_srcid));
293 ts = (double)((u_int32_t)ntohl(rr->rr_lsr)) / 65536.;
294 dts = (double)((u_int32_t)ntohl(rr->rr_dlsr)) / 65536.;
295 printf(" %ul %us %uj @%.2f+%.2f",
296 (u_int32_t)ntohl(rr->rr_nl) & 0x00ffffff,
297 (u_int32_t)ntohl(rr->rr_ls),
298 (u_int32_t)ntohl(rr->rr_dv), ts, dts);
299 }
300 return (hdr + len);
301 }
302
303 /* XXX probably should use getservbyname() and cache answers */
304 #define TFTP_PORT 69 /*XXX*/
305 #define KERBEROS_PORT 88 /*XXX*/
306 #define SUNRPC_PORT 111 /*XXX*/
307 #define SNMP_PORT 161 /*XXX*/
308 #define NTP_PORT 123 /*XXX*/
309 #define SNMPTRAP_PORT 162 /*XXX*/
310 #define RIP_PORT 520 /*XXX*/
311 #define KERBEROS_SEC_PORT 750 /*XXX*/
312
313 void
314 udp_print(register const u_char *bp, u_int length, register const u_char *bp2)
315 {
316 register const struct udphdr *up;
317 register const struct ip *ip;
318 register const u_char *cp;
319 register const u_char *ep = bp + length;
320 u_short sport, dport, ulen;
321
322 if (ep > snapend)
323 ep = snapend;
324 up = (struct udphdr *)bp;
325 ip = (struct ip *)bp2;
326 cp = (u_char *)(up + 1);
327 if (cp > snapend) {
328 printf("[|udp]");
329 return;
330 }
331 if (length < sizeof(struct udphdr)) {
332 (void)printf(" truncated-udp %d", length);
333 return;
334 }
335 length -= sizeof(struct udphdr);
336
337 sport = ntohs(up->uh_sport);
338 dport = ntohs(up->uh_dport);
339 ulen = ntohs(up->uh_ulen);
340 if (packettype) {
341 register struct rpc_msg *rp;
342 enum msg_type direction;
343
344 switch (packettype) {
345
346 case PT_VAT:
347 (void)printf("%s.%s > %s.%s:",
348 ipaddr_string(&ip->ip_src),
349 udpport_string(sport),
350 ipaddr_string(&ip->ip_dst),
351 udpport_string(dport));
352 vat_print((void *)(up + 1), length, up);
353 break;
354
355 case PT_WB:
356 (void)printf("%s.%s > %s.%s:",
357 ipaddr_string(&ip->ip_src),
358 udpport_string(sport),
359 ipaddr_string(&ip->ip_dst),
360 udpport_string(dport));
361 wb_print((void *)(up + 1), length);
362 break;
363
364 case PT_RPC:
365 rp = (struct rpc_msg *)(up + 1);
366 direction = (enum msg_type)ntohl(rp->rm_direction);
367 if (direction == CALL)
368 sunrpcrequest_print((u_char *)rp, length,
369 (u_char *)ip);
370 else
371 nfsreply_print((u_char *)rp, length,
372 (u_char *)ip); /*XXX*/
373 break;
374
375 case PT_RTP:
376 (void)printf("%s.%s > %s.%s:",
377 ipaddr_string(&ip->ip_src),
378 udpport_string(sport),
379 ipaddr_string(&ip->ip_dst),
380 udpport_string(dport));
381 rtp_print((void *)(up + 1), length, up);
382 break;
383
384 case PT_RTCP:
385 (void)printf("%s.%s > %s.%s:",
386 ipaddr_string(&ip->ip_src),
387 udpport_string(sport),
388 ipaddr_string(&ip->ip_dst),
389 udpport_string(dport));
390 while (cp < ep)
391 cp = rtcp_print(cp, ep);
392 break;
393 }
394 return;
395 }
396
397 if (!qflag) {
398 register struct rpc_msg *rp;
399 enum msg_type direction;
400
401 rp = (struct rpc_msg *)(up + 1);
402 if (TTEST(rp->rm_direction)) {
403 direction = (enum msg_type)ntohl(rp->rm_direction);
404 if (dport == NFS_PORT && direction == CALL) {
405 nfsreq_print((u_char *)rp, length,
406 (u_char *)ip);
407 return;
408 }
409 if (sport == NFS_PORT && direction == REPLY) {
410 nfsreply_print((u_char *)rp, length,
411 (u_char *)ip);
412 return;
413 }
414 #ifdef notdef
415 if (dport == SUNRPC_PORT && direction == CALL) {
416 sunrpcrequest_print((u_char *)rp, length, (u_char *)ip);
417 return;
418 }
419 #endif
420 }
421 if (TTEST(((struct LAP *)cp)->type) &&
422 ((struct LAP *)cp)->type == lapDDP &&
423 (atalk_port(sport) || atalk_port(dport))) {
424 if (vflag)
425 fputs("kip ", stdout);
426 atalk_print(cp, length);
427 return;
428 }
429 }
430 (void)printf("%s.%s > %s.%s:",
431 ipaddr_string(&ip->ip_src), udpport_string(sport),
432 ipaddr_string(&ip->ip_dst), udpport_string(dport));
433
434 if (!qflag) {
435 #define ISPORT(p) (dport == (p) || sport == (p))
436 if (ISPORT(NAMESERVER_PORT))
437 ns_print((const u_char *)(up + 1), length);
438 else if (ISPORT(TFTP_PORT))
439 tftp_print((const u_char *)(up + 1), length);
440 else if (ISPORT(IPPORT_BOOTPC) || ISPORT(IPPORT_BOOTPS))
441 bootp_print((const u_char *)(up + 1), length,
442 sport, dport);
443 else if (ISPORT(RIP_PORT))
444 rip_print((const u_char *)(up + 1), length);
445 else if (ISPORT(SNMP_PORT) || ISPORT(SNMPTRAP_PORT))
446 snmp_print((const u_char *)(up + 1), length);
447 else if (ISPORT(NTP_PORT))
448 ntp_print((const u_char *)(up + 1), length);
449 else if (ISPORT(KERBEROS_PORT) || ISPORT(KERBEROS_SEC_PORT))
450 krb_print((const void *)(up + 1), length);
451 else if (dport == 3456)
452 vat_print((const void *)(up + 1), length, up);
453 /*
454 * Kludge in test for whiteboard packets.
455 */
456 else if (dport == 4567)
457 wb_print((const void *)(up + 1), length);
458 else
459 (void)printf(" udp %u",
460 (u_int32_t)(ulen - sizeof(*up)));
461 #undef ISPORT
462 } else
463 (void)printf(" udp %u", (u_int32_t)(ulen - sizeof(*up)));
464 }