]> git.saurik.com Git - apple/network_cmds.git/blob - tcpdump.tproj/print-wb.c
3b0c1601748d2f86dbb9cde06ee6ae2d56660b12
[apple/network_cmds.git] / tcpdump.tproj / print-wb.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) 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-wb.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)";
48 #endif
49
50 #include <sys/types.h>
51 #include <sys/time.h>
52
53 #include <netinet/in.h>
54
55 #include <stdio.h>
56
57 #include "interface.h"
58 #include "addrtoname.h"
59
60 /* XXX need to add byte-swapping macros! */
61
62 /*
63 * Largest packet size. Everything should fit within this space.
64 * For instance, multiline objects are sent piecewise.
65 */
66 #define MAXFRAMESIZE 1024
67
68 /*
69 * Multiple drawing ops can be sent in one packet. Each one starts on a
70 * an even multiple of DOP_ALIGN bytes, which must be a power of two.
71 */
72 #define DOP_ALIGN 4
73 #define DOP_ROUNDUP(x) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
74 #define DOP_NEXT(d)\
75 ((struct dophdr *)((u_char *)(d) + \
76 DOP_ROUNDUP(ntohs((d)->dh_len) + sizeof(*(d)))))
77
78 /*
79 * Format of the whiteboard packet header.
80 * The transport level header.
81 */
82 struct pkt_hdr {
83 u_int32_t ph_src; /* site id of source */
84 u_int32_t ph_ts; /* time stamp (for skew computation) */
85 u_short ph_version; /* version number */
86 u_char ph_type; /* message type */
87 u_char ph_flags; /* message flags */
88 };
89
90 /* Packet types */
91 #define PT_DRAWOP 0 /* drawing operation */
92 #define PT_ID 1 /* announcement packet */
93 #define PT_RREQ 2 /* repair request */
94 #define PT_RREP 3 /* repair reply */
95 #define PT_KILL 4 /* terminate participation */
96 #define PT_PREQ 5 /* page vector request */
97 #define PT_PREP 7 /* page vector reply */
98
99 /* flags */
100 #define PF_USER 0x01 /* hint that packet has interactive data */
101 #define PF_VIS 0x02 /* only visible ops wanted */
102
103 struct PageID {
104 u_int32_t p_sid; /* session id of initiator */
105 u_int32_t p_uid; /* page number */
106 };
107
108 struct dophdr {
109 u_int32_t dh_ts; /* sender's timestamp */
110 u_short dh_len; /* body length */
111 u_char dh_flags;
112 u_char dh_type; /* body type */
113 /* body follows */
114 };
115 /*
116 * Drawing op sub-types.
117 */
118 #define DT_RECT 2
119 #define DT_LINE 3
120 #define DT_ML 4
121 #define DT_DEL 5
122 #define DT_XFORM 6
123 #define DT_ELL 7
124 #define DT_CHAR 8
125 #define DT_STR 9
126 #define DT_NOP 10
127 #define DT_PSCODE 11
128 #define DT_PSCOMP 12
129 #define DT_REF 13
130 #define DT_SKIP 14
131 #define DT_HOLE 15
132 #define DT_MAXTYPE 15
133
134 /*
135 * A drawing operation.
136 */
137 struct pkt_dop {
138 struct PageID pd_page; /* page that operations apply to */
139 u_int32_t pd_sseq; /* start sequence number */
140 u_int32_t pd_eseq; /* end sequence number */
141 /* drawing ops follow */
142 };
143
144 /*
145 * A repair request.
146 */
147 struct pkt_rreq {
148 u_int32_t pr_id; /* source id of drawops to be repaired */
149 struct PageID pr_page; /* page of drawops */
150 u_int32_t pr_sseq; /* start seqno */
151 u_int32_t pr_eseq; /* end seqno */
152 };
153
154 /*
155 * A repair reply.
156 */
157 struct pkt_rrep {
158 u_int32_t pr_id; /* original site id of ops */
159 struct pkt_dop pr_dop;
160 /* drawing ops follow */
161 };
162
163 struct id_off {
164 u_int32_t id;
165 u_int32_t off;
166 };
167
168 struct pgstate {
169 u_int32_t slot;
170 struct PageID page;
171 u_short nid;
172 u_short rsvd;
173 /* seqptr's */
174 };
175
176 /*
177 * An announcement packet.
178 */
179 struct pkt_id {
180 u_int32_t pi_mslot;
181 struct PageID pi_mpage; /* current page */
182 struct pgstate pi_ps;
183 /* seqptr's */
184 /* null-terminated site name */
185 };
186
187 struct pkt_preq {
188 struct PageID pp_page;
189 u_int32_t pp_low;
190 u_int32_t pp_high;
191 };
192
193 struct pkt_prep {
194 u_int32_t pp_n; /* size of pageid array */
195 /* pgstate's follow */
196 };
197
198 static int
199 wb_id(const struct pkt_id *id, u_int len)
200 {
201 int i;
202 const char *cp;
203 const struct id_off *io;
204 char c;
205 int nid;
206
207 printf(" wb-id:");
208 len -= sizeof(*id);
209 if (len < 0 || (u_char *)(id + 1) > snapend)
210 return (-1);
211
212 printf(" %u/%s:%u (max %u/%s:%u) ",
213 (u_int32_t)ntohl(id->pi_ps.slot),
214 ipaddr_string(&id->pi_ps.page.p_sid),
215 (u_int32_t)ntohl(id->pi_ps.page.p_uid),
216 (u_int32_t)ntohl(id->pi_mslot),
217 ipaddr_string(&id->pi_mpage.p_sid),
218 (u_int32_t)ntohl(id->pi_mpage.p_uid));
219
220 nid = ntohs(id->pi_ps.nid);
221 len -= sizeof(*io) * nid;
222 io = (struct id_off *)(id + 1);
223 cp = (char *)(io + nid);
224 if ((u_char *)cp + len <= snapend) {
225 putchar('"');
226 (void)fn_print((u_char *)cp, (u_char *)cp + len);
227 putchar('"');
228 }
229
230 c = '<';
231 for (i = 0; i < nid && (u_char *)io < snapend; ++io, ++i) {
232 printf("%c%s:%u",
233 c, ipaddr_string(&io->id), (u_int32_t)ntohl(io->off));
234 c = ',';
235 }
236 if (i >= nid) {
237 printf(">");
238 return (0);
239 }
240 return (-1);
241 }
242
243 static int
244 wb_rreq(const struct pkt_rreq *rreq, u_int len)
245 {
246 printf(" wb-rreq:");
247 if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > snapend)
248 return (-1);
249
250 printf(" please repair %s %s:%u<%u:%u>",
251 ipaddr_string(&rreq->pr_id),
252 ipaddr_string(&rreq->pr_page.p_sid),
253 (u_int32_t)ntohl(rreq->pr_page.p_uid),
254 (u_int32_t)ntohl(rreq->pr_sseq),
255 (u_int32_t)ntohl(rreq->pr_eseq));
256 return (0);
257 }
258
259 static int
260 wb_preq(const struct pkt_preq *preq, u_int len)
261 {
262 printf(" wb-preq:");
263 if (len < sizeof(*preq) || (u_char *)(preq + 1) > snapend)
264 return (-1);
265
266 printf(" need %u/%s:%u",
267 (u_int32_t)ntohl(preq->pp_low),
268 ipaddr_string(&preq->pp_page.p_sid),
269 (u_int32_t)ntohl(preq->pp_page.p_uid));
270 return (0);
271 }
272
273 static int
274 wb_prep(const struct pkt_prep *prep, u_int len)
275 {
276 int n;
277 const struct pgstate *ps;
278 const u_char *ep = snapend;
279
280 printf(" wb-prep:");
281 if (len < sizeof(*prep)) {
282 return (-1);
283 }
284 n = ntohl(prep->pp_n);
285 ps = (const struct pgstate *)(prep + 1);
286 while (--n >= 0 && (u_char *)ps < ep) {
287 const struct id_off *io, *ie;
288 char c = '<';
289
290 printf(" %u/%s:%u",
291 (u_int32_t)ntohl(ps->slot),
292 ipaddr_string(&ps->page.p_sid),
293 (u_int32_t)ntohl(ps->page.p_uid));
294 io = (struct id_off *)(ps + 1);
295 for (ie = io + ps->nid; io < ie && (u_char *)io < ep; ++io) {
296 printf("%c%s:%u", c, ipaddr_string(&io->id),
297 (u_int32_t)ntohl(io->off));
298 c = ',';
299 }
300 printf(">");
301 ps = (struct pgstate *)io;
302 }
303 return ((u_char *)ps <= ep? 0 : -1);
304 }
305
306
307 char *dopstr[] = {
308 "dop-0!",
309 "dop-1!",
310 "RECT",
311 "LINE",
312 "ML",
313 "DEL",
314 "XFORM",
315 "ELL",
316 "CHAR",
317 "STR",
318 "NOP",
319 "PSCODE",
320 "PSCOMP",
321 "REF",
322 "SKIP",
323 "HOLE",
324 };
325
326 static int
327 wb_dops(const struct dophdr *dh, u_int32_t ss, u_int32_t es)
328 {
329 printf(" <");
330 for ( ; ss <= es; ++ss) {
331 register int t = dh->dh_type;
332
333 if (t > DT_MAXTYPE)
334 printf(" dop-%d!", t);
335 else {
336 printf(" %s", dopstr[t]);
337 if (t == DT_SKIP || t == DT_HOLE) {
338 int ts = ntohl(dh->dh_ts);
339 printf("%d", ts - ss + 1);
340 if (ss > ts || ts > es) {
341 printf("[|]");
342 if (ts < ss)
343 return (0);
344 }
345 ss = ts;
346 }
347 }
348 dh = DOP_NEXT(dh);
349 if ((u_char *)dh > snapend) {
350 printf("[|wb]");
351 break;
352 }
353 }
354 printf(" >");
355 return (0);
356 }
357
358 static int
359 wb_rrep(const struct pkt_rrep *rrep, u_int len)
360 {
361 const struct pkt_dop *dop = &rrep->pr_dop;
362
363 printf(" wb-rrep:");
364 len -= sizeof(*rrep);
365 if (len < 0 || (u_char *)(rrep + 1) > snapend)
366 return (-1);
367
368 printf(" for %s %s:%u<%u:%u>",
369 ipaddr_string(&rrep->pr_id),
370 ipaddr_string(&dop->pd_page.p_sid),
371 (u_int32_t)ntohl(dop->pd_page.p_uid),
372 (u_int32_t)ntohl(dop->pd_sseq),
373 (u_int32_t)ntohl(dop->pd_eseq));
374
375 if (vflag)
376 return (wb_dops((const struct dophdr *)(dop + 1),
377 ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
378 return (0);
379 }
380
381 static int
382 wb_drawop(const struct pkt_dop *dop, u_int len)
383 {
384 printf(" wb-dop:");
385 len -= sizeof(*dop);
386 if (len < 0 || (u_char *)(dop + 1) > snapend)
387 return (-1);
388
389 printf(" %s:%u<%u:%u>",
390 ipaddr_string(&dop->pd_page.p_sid),
391 (u_int32_t)ntohl(dop->pd_page.p_uid),
392 (u_int32_t)ntohl(dop->pd_sseq),
393 (u_int32_t)ntohl(dop->pd_eseq));
394
395 if (vflag)
396 return (wb_dops((const struct dophdr *)(dop + 1),
397 ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
398 return (0);
399 }
400
401 /*
402 * Print whiteboard multicast packets.
403 */
404 void
405 wb_print(register const void *hdr, register u_int len)
406 {
407 register const struct pkt_hdr *ph;
408
409 ph = (const struct pkt_hdr *)hdr;
410 len -= sizeof(*ph);
411 if (len < 0 || (u_char *)(ph + 1) <= snapend) {
412 if (ph->ph_flags)
413 printf("*");
414 switch (ph->ph_type) {
415
416 case PT_KILL:
417 printf(" wb-kill");
418 return;
419
420 case PT_ID:
421 if (wb_id((struct pkt_id *)(ph + 1), len) >= 0)
422 return;
423 break;
424
425 case PT_RREQ:
426 if (wb_rreq((struct pkt_rreq *)(ph + 1), len) >= 0)
427 return;
428 break;
429
430 case PT_RREP:
431 if (wb_rrep((struct pkt_rrep *)(ph + 1), len) >= 0)
432 return;
433 break;
434
435 case PT_DRAWOP:
436 if (wb_drawop((struct pkt_dop *)(ph + 1), len) >= 0)
437 return;
438 break;
439
440 case PT_PREQ:
441 if (wb_preq((struct pkt_preq *)(ph + 1), len) >= 0)
442 return;
443 break;
444
445 case PT_PREP:
446 if (wb_prep((struct pkt_prep *)(ph + 1), len) >= 0)
447 return;
448 break;
449
450 default:
451 printf(" wb-%d!", ph->ph_type);
452 return;
453 }
454 }
455 printf("[|wb]");
456 }