locate(1): Bring in some updates/fixes from FreeBSD
[dragonfly.git] / contrib / tcpdump / print-wb.c
blob3ae604ffed0b791de6eaf59824fed3ab172a261d
1 /*
2 * Copyright (c) 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
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.
22 #ifndef lint
23 static const char rcsid[] _U_ =
24 "@(#) $Header: /tcpdump/master/tcpdump/print-wb.c,v 1.33 2004-03-24 04:06:28 guy Exp $ (LBL)";
25 #endif
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
31 #include <tcpdump-stdinc.h>
33 #include <stdio.h>
35 #include "interface.h"
36 #include "addrtoname.h"
37 #include "extract.h"
39 /* XXX need to add byte-swapping macros! */
40 /* XXX - you mean like the ones in "extract.h"? */
43 * Largest packet size. Everything should fit within this space.
44 * For instance, multiline objects are sent piecewise.
46 #define MAXFRAMESIZE 1024
49 * Multiple drawing ops can be sent in one packet. Each one starts on a
50 * an even multiple of DOP_ALIGN bytes, which must be a power of two.
52 #define DOP_ALIGN 4
53 #define DOP_ROUNDUP(x) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
54 #define DOP_NEXT(d)\
55 ((struct dophdr *)((u_char *)(d) + \
56 DOP_ROUNDUP(EXTRACT_16BITS(&(d)->dh_len) + sizeof(*(d)))))
59 * Format of the whiteboard packet header.
60 * The transport level header.
62 struct pkt_hdr {
63 u_int32_t ph_src; /* site id of source */
64 u_int32_t ph_ts; /* time stamp (for skew computation) */
65 u_int16_t ph_version; /* version number */
66 u_char ph_type; /* message type */
67 u_char ph_flags; /* message flags */
70 /* Packet types */
71 #define PT_DRAWOP 0 /* drawing operation */
72 #define PT_ID 1 /* announcement packet */
73 #define PT_RREQ 2 /* repair request */
74 #define PT_RREP 3 /* repair reply */
75 #define PT_KILL 4 /* terminate participation */
76 #define PT_PREQ 5 /* page vector request */
77 #define PT_PREP 7 /* page vector reply */
79 #ifdef PF_USER
80 #undef PF_USER /* {Digital,Tru64} UNIX define this, alas */
81 #endif
83 /* flags */
84 #define PF_USER 0x01 /* hint that packet has interactive data */
85 #define PF_VIS 0x02 /* only visible ops wanted */
87 struct PageID {
88 u_int32_t p_sid; /* session id of initiator */
89 u_int32_t p_uid; /* page number */
92 struct dophdr {
93 u_int32_t dh_ts; /* sender's timestamp */
94 u_int16_t dh_len; /* body length */
95 u_char dh_flags;
96 u_char dh_type; /* body type */
97 /* body follows */
100 * Drawing op sub-types.
102 #define DT_RECT 2
103 #define DT_LINE 3
104 #define DT_ML 4
105 #define DT_DEL 5
106 #define DT_XFORM 6
107 #define DT_ELL 7
108 #define DT_CHAR 8
109 #define DT_STR 9
110 #define DT_NOP 10
111 #define DT_PSCODE 11
112 #define DT_PSCOMP 12
113 #define DT_REF 13
114 #define DT_SKIP 14
115 #define DT_HOLE 15
116 #define DT_MAXTYPE 15
119 * A drawing operation.
121 struct pkt_dop {
122 struct PageID pd_page; /* page that operations apply to */
123 u_int32_t pd_sseq; /* start sequence number */
124 u_int32_t pd_eseq; /* end sequence number */
125 /* drawing ops follow */
129 * A repair request.
131 struct pkt_rreq {
132 u_int32_t pr_id; /* source id of drawops to be repaired */
133 struct PageID pr_page; /* page of drawops */
134 u_int32_t pr_sseq; /* start seqno */
135 u_int32_t pr_eseq; /* end seqno */
139 * A repair reply.
141 struct pkt_rrep {
142 u_int32_t pr_id; /* original site id of ops */
143 struct pkt_dop pr_dop;
144 /* drawing ops follow */
147 struct id_off {
148 u_int32_t id;
149 u_int32_t off;
152 struct pgstate {
153 u_int32_t slot;
154 struct PageID page;
155 u_int16_t nid;
156 u_int16_t rsvd;
157 /* seqptr's */
161 * An announcement packet.
163 struct pkt_id {
164 u_int32_t pi_mslot;
165 struct PageID pi_mpage; /* current page */
166 struct pgstate pi_ps;
167 /* seqptr's */
168 /* null-terminated site name */
171 struct pkt_preq {
172 struct PageID pp_page;
173 u_int32_t pp_low;
174 u_int32_t pp_high;
177 struct pkt_prep {
178 u_int32_t pp_n; /* size of pageid array */
179 /* pgstate's follow */
182 static int
183 wb_id(const struct pkt_id *id, u_int len)
185 int i;
186 const char *cp;
187 const struct id_off *io;
188 char c;
189 int nid;
191 printf(" wb-id:");
192 if (len < sizeof(*id) || (u_char *)(id + 1) > snapend)
193 return (-1);
194 len -= sizeof(*id);
196 printf(" %u/%s:%u (max %u/%s:%u) ",
197 EXTRACT_32BITS(&id->pi_ps.slot),
198 ipaddr_string(&id->pi_ps.page.p_sid),
199 EXTRACT_32BITS(&id->pi_ps.page.p_uid),
200 EXTRACT_32BITS(&id->pi_mslot),
201 ipaddr_string(&id->pi_mpage.p_sid),
202 EXTRACT_32BITS(&id->pi_mpage.p_uid));
204 nid = EXTRACT_16BITS(&id->pi_ps.nid);
205 len -= sizeof(*io) * nid;
206 io = (struct id_off *)(id + 1);
207 cp = (char *)(io + nid);
208 if ((u_char *)cp + len <= snapend) {
209 putchar('"');
210 (void)fn_print((u_char *)cp, (u_char *)cp + len);
211 putchar('"');
214 c = '<';
215 for (i = 0; i < nid && (u_char *)(io + 1) <= snapend; ++io, ++i) {
216 printf("%c%s:%u",
217 c, ipaddr_string(&io->id), EXTRACT_32BITS(&io->off));
218 c = ',';
220 if (i >= nid) {
221 printf(">");
222 return (0);
224 return (-1);
227 static int
228 wb_rreq(const struct pkt_rreq *rreq, u_int len)
230 printf(" wb-rreq:");
231 if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > snapend)
232 return (-1);
234 printf(" please repair %s %s:%u<%u:%u>",
235 ipaddr_string(&rreq->pr_id),
236 ipaddr_string(&rreq->pr_page.p_sid),
237 EXTRACT_32BITS(&rreq->pr_page.p_uid),
238 EXTRACT_32BITS(&rreq->pr_sseq),
239 EXTRACT_32BITS(&rreq->pr_eseq));
240 return (0);
243 static int
244 wb_preq(const struct pkt_preq *preq, u_int len)
246 printf(" wb-preq:");
247 if (len < sizeof(*preq) || (u_char *)(preq + 1) > snapend)
248 return (-1);
250 printf(" need %u/%s:%u",
251 EXTRACT_32BITS(&preq->pp_low),
252 ipaddr_string(&preq->pp_page.p_sid),
253 EXTRACT_32BITS(&preq->pp_page.p_uid));
254 return (0);
257 static int
258 wb_prep(const struct pkt_prep *prep, u_int len)
260 int n;
261 const struct pgstate *ps;
262 const u_char *ep = snapend;
264 printf(" wb-prep:");
265 if (len < sizeof(*prep)) {
266 return (-1);
268 n = EXTRACT_32BITS(&prep->pp_n);
269 ps = (const struct pgstate *)(prep + 1);
270 while (--n >= 0 && (u_char *)(ps + 1) <= ep) {
271 const struct id_off *io, *ie;
272 char c = '<';
274 printf(" %u/%s:%u",
275 EXTRACT_32BITS(&ps->slot),
276 ipaddr_string(&ps->page.p_sid),
277 EXTRACT_32BITS(&ps->page.p_uid));
278 io = (struct id_off *)(ps + 1);
279 for (ie = io + ps->nid; io < ie && (u_char *)(io + 1) <= ep; ++io) {
280 printf("%c%s:%u", c, ipaddr_string(&io->id),
281 EXTRACT_32BITS(&io->off));
282 c = ',';
284 printf(">");
285 ps = (struct pgstate *)io;
287 return ((u_char *)ps <= ep? 0 : -1);
291 const char *dopstr[] = {
292 "dop-0!",
293 "dop-1!",
294 "RECT",
295 "LINE",
296 "ML",
297 "DEL",
298 "XFORM",
299 "ELL",
300 "CHAR",
301 "STR",
302 "NOP",
303 "PSCODE",
304 "PSCOMP",
305 "REF",
306 "SKIP",
307 "HOLE",
310 static int
311 wb_dops(const struct dophdr *dh, u_int32_t ss, u_int32_t es)
313 printf(" <");
314 for ( ; ss <= es; ++ss) {
315 register int t = dh->dh_type;
317 if (t > DT_MAXTYPE)
318 printf(" dop-%d!", t);
319 else {
320 printf(" %s", dopstr[t]);
321 if (t == DT_SKIP || t == DT_HOLE) {
322 u_int32_t ts = EXTRACT_32BITS(&dh->dh_ts);
323 printf("%d", ts - ss + 1);
324 if (ss > ts || ts > es) {
325 printf("[|]");
326 if (ts < ss)
327 return (0);
329 ss = ts;
332 dh = DOP_NEXT(dh);
333 if ((u_char *)dh > snapend) {
334 printf("[|wb]");
335 break;
338 printf(" >");
339 return (0);
342 static int
343 wb_rrep(const struct pkt_rrep *rrep, u_int len)
345 const struct pkt_dop *dop = &rrep->pr_dop;
347 printf(" wb-rrep:");
348 if (len < sizeof(*rrep) || (u_char *)(rrep + 1) > snapend)
349 return (-1);
350 len -= sizeof(*rrep);
352 printf(" for %s %s:%u<%u:%u>",
353 ipaddr_string(&rrep->pr_id),
354 ipaddr_string(&dop->pd_page.p_sid),
355 EXTRACT_32BITS(&dop->pd_page.p_uid),
356 EXTRACT_32BITS(&dop->pd_sseq),
357 EXTRACT_32BITS(&dop->pd_eseq));
359 if (vflag)
360 return (wb_dops((const struct dophdr *)(dop + 1),
361 EXTRACT_32BITS(&dop->pd_sseq),
362 EXTRACT_32BITS(&dop->pd_eseq)));
363 return (0);
366 static int
367 wb_drawop(const struct pkt_dop *dop, u_int len)
369 printf(" wb-dop:");
370 if (len < sizeof(*dop) || (u_char *)(dop + 1) > snapend)
371 return (-1);
372 len -= sizeof(*dop);
374 printf(" %s:%u<%u:%u>",
375 ipaddr_string(&dop->pd_page.p_sid),
376 EXTRACT_32BITS(&dop->pd_page.p_uid),
377 EXTRACT_32BITS(&dop->pd_sseq),
378 EXTRACT_32BITS(&dop->pd_eseq));
380 if (vflag)
381 return (wb_dops((const struct dophdr *)(dop + 1),
382 EXTRACT_32BITS(&dop->pd_sseq),
383 EXTRACT_32BITS(&dop->pd_eseq)));
384 return (0);
388 * Print whiteboard multicast packets.
390 void
391 wb_print(register const void *hdr, register u_int len)
393 register const struct pkt_hdr *ph;
395 ph = (const struct pkt_hdr *)hdr;
396 if (len < sizeof(*ph) || (u_char *)(ph + 1) > snapend) {
397 printf("[|wb]");
398 return;
400 len -= sizeof(*ph);
402 if (ph->ph_flags)
403 printf("*");
404 switch (ph->ph_type) {
406 case PT_KILL:
407 printf(" wb-kill");
408 return;
410 case PT_ID:
411 if (wb_id((struct pkt_id *)(ph + 1), len) >= 0)
412 return;
413 break;
415 case PT_RREQ:
416 if (wb_rreq((struct pkt_rreq *)(ph + 1), len) >= 0)
417 return;
418 break;
420 case PT_RREP:
421 if (wb_rrep((struct pkt_rrep *)(ph + 1), len) >= 0)
422 return;
423 break;
425 case PT_DRAWOP:
426 if (wb_drawop((struct pkt_dop *)(ph + 1), len) >= 0)
427 return;
428 break;
430 case PT_PREQ:
431 if (wb_preq((struct pkt_preq *)(ph + 1), len) >= 0)
432 return;
433 break;
435 case PT_PREP:
436 if (wb_prep((struct pkt_prep *)(ph + 1), len) >= 0)
437 return;
438 break;
440 default:
441 printf(" wb-%d!", ph->ph_type);
442 return;