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
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 #include <sys/cdefs.h>
24 __RCSID("$NetBSD: print-wb.c,v 1.5 2015/03/31 21:59:35 christos Exp $");
27 #define NETDISSECT_REWORKED
32 #include <tcpdump-stdinc.h>
34 #include "interface.h"
35 #include "addrtoname.h"
38 static const char tstr
[] = "[|wb]";
40 /* XXX need to add byte-swapping macros! */
41 /* XXX - you mean like the ones in "extract.h"? */
44 * Largest packet size. Everything should fit within this space.
45 * For instance, multiline objects are sent piecewise.
47 #define MAXFRAMESIZE 1024
50 * Multiple drawing ops can be sent in one packet. Each one starts on a
51 * an even multiple of DOP_ALIGN bytes, which must be a power of two.
54 #define DOP_ROUNDUP(x) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
56 ((struct dophdr *)((u_char *)(d) + \
57 DOP_ROUNDUP(EXTRACT_16BITS(&(d)->dh_len) + sizeof(*(d)))))
60 * Format of the whiteboard packet header.
61 * The transport level header.
64 uint32_t ph_src
; /* site id of source */
65 uint32_t ph_ts
; /* time stamp (for skew computation) */
66 uint16_t ph_version
; /* version number */
67 u_char ph_type
; /* message type */
68 u_char ph_flags
; /* message flags */
72 #define PT_DRAWOP 0 /* drawing operation */
73 #define PT_ID 1 /* announcement packet */
74 #define PT_RREQ 2 /* repair request */
75 #define PT_RREP 3 /* repair reply */
76 #define PT_KILL 4 /* terminate participation */
77 #define PT_PREQ 5 /* page vector request */
78 #define PT_PREP 7 /* page vector reply */
81 #undef PF_USER /* {Digital,Tru64} UNIX define this, alas */
85 #define PF_USER 0x01 /* hint that packet has interactive data */
86 #define PF_VIS 0x02 /* only visible ops wanted */
89 uint32_t p_sid
; /* session id of initiator */
90 uint32_t p_uid
; /* page number */
94 uint32_t dh_ts
; /* sender's timestamp */
95 uint16_t dh_len
; /* body length */
97 u_char dh_type
; /* body type */
101 * Drawing op sub-types.
117 #define DT_MAXTYPE 15
120 * A drawing operation.
123 struct PageID pd_page
; /* page that operations apply to */
124 uint32_t pd_sseq
; /* start sequence number */
125 uint32_t pd_eseq
; /* end sequence number */
126 /* drawing ops follow */
133 uint32_t pr_id
; /* source id of drawops to be repaired */
134 struct PageID pr_page
; /* page of drawops */
135 uint32_t pr_sseq
; /* start seqno */
136 uint32_t pr_eseq
; /* end seqno */
143 uint32_t pr_id
; /* original site id of ops */
144 struct pkt_dop pr_dop
;
145 /* drawing ops follow */
162 * An announcement packet.
166 struct PageID pi_mpage
; /* current page */
167 struct pgstate pi_ps
;
169 /* null-terminated site name */
173 struct PageID pp_page
;
179 uint32_t pp_n
; /* size of pageid array */
180 /* pgstate's follow */
184 wb_id(netdissect_options
*ndo
,
185 const struct pkt_id
*id
, u_int len
)
189 const struct id_off
*io
;
193 ND_PRINT((ndo
, " wb-id:"));
194 if (len
< sizeof(*id
) || !ND_TTEST(*id
))
198 ND_PRINT((ndo
, " %u/%s:%u (max %u/%s:%u) ",
199 EXTRACT_32BITS(&id
->pi_ps
.slot
),
200 ipaddr_string(ndo
, &id
->pi_ps
.page
.p_sid
),
201 EXTRACT_32BITS(&id
->pi_ps
.page
.p_uid
),
202 EXTRACT_32BITS(&id
->pi_mslot
),
203 ipaddr_string(ndo
, &id
->pi_mpage
.p_sid
),
204 EXTRACT_32BITS(&id
->pi_mpage
.p_uid
)));
206 nid
= EXTRACT_16BITS(&id
->pi_ps
.nid
);
207 len
-= sizeof(*io
) * nid
;
208 io
= (struct id_off
*)(id
+ 1);
209 cp
= (char *)(io
+ nid
);
210 if (!ND_TTEST2(cp
, len
)) {
211 ND_PRINT((ndo
, "\""));
212 fn_print(ndo
, (u_char
*)cp
, (u_char
*)cp
+ len
);
213 ND_PRINT((ndo
, "\""));
217 for (i
= 0; i
< nid
&& ND_TTEST(*io
); ++io
, ++i
) {
218 ND_PRINT((ndo
, "%c%s:%u",
219 c
, ipaddr_string(ndo
, &io
->id
), EXTRACT_32BITS(&io
->off
)));
223 ND_PRINT((ndo
, ">"));
230 wb_rreq(netdissect_options
*ndo
,
231 const struct pkt_rreq
*rreq
, u_int len
)
233 ND_PRINT((ndo
, " wb-rreq:"));
234 if (len
< sizeof(*rreq
) || !ND_TTEST(*rreq
))
237 ND_PRINT((ndo
, " please repair %s %s:%u<%u:%u>",
238 ipaddr_string(ndo
, &rreq
->pr_id
),
239 ipaddr_string(ndo
, &rreq
->pr_page
.p_sid
),
240 EXTRACT_32BITS(&rreq
->pr_page
.p_uid
),
241 EXTRACT_32BITS(&rreq
->pr_sseq
),
242 EXTRACT_32BITS(&rreq
->pr_eseq
)));
247 wb_preq(netdissect_options
*ndo
,
248 const struct pkt_preq
*preq
, u_int len
)
250 ND_PRINT((ndo
, " wb-preq:"));
251 if (len
< sizeof(*preq
) || !ND_TTEST(*preq
))
254 ND_PRINT((ndo
, " need %u/%s:%u",
255 EXTRACT_32BITS(&preq
->pp_low
),
256 ipaddr_string(ndo
, &preq
->pp_page
.p_sid
),
257 EXTRACT_32BITS(&preq
->pp_page
.p_uid
)));
262 wb_prep(netdissect_options
*ndo
,
263 const struct pkt_prep
*prep
, u_int len
)
266 const struct pgstate
*ps
;
267 const u_char
*ep
= ndo
->ndo_snapend
;
269 ND_PRINT((ndo
, " wb-prep:"));
270 if (len
< sizeof(*prep
)) {
273 n
= EXTRACT_32BITS(&prep
->pp_n
);
274 ps
= (const struct pgstate
*)(prep
+ 1);
275 while (--n
>= 0 && !ND_TTEST(*ps
)) {
276 const struct id_off
*io
, *ie
;
279 ND_PRINT((ndo
, " %u/%s:%u",
280 EXTRACT_32BITS(&ps
->slot
),
281 ipaddr_string(ndo
, &ps
->page
.p_sid
),
282 EXTRACT_32BITS(&ps
->page
.p_uid
)));
283 io
= (struct id_off
*)(ps
+ 1);
284 for (ie
= io
+ ps
->nid
; io
< ie
&& !ND_TTEST(*io
); ++io
) {
285 ND_PRINT((ndo
, "%c%s:%u", c
, ipaddr_string(ndo
, &io
->id
),
286 EXTRACT_32BITS(&io
->off
)));
289 ND_PRINT((ndo
, ">"));
290 ps
= (struct pgstate
*)io
;
292 return ((u_char
*)ps
<= ep
? 0 : -1);
296 static const char *dopstr
[] = {
316 wb_dops(netdissect_options
*ndo
, const struct pkt_dop
*dop
,
317 uint32_t ss
, uint32_t es
)
319 const struct dophdr
*dh
= (const struct dophdr
*)((const u_char
*)dop
+ sizeof(*dop
));
321 ND_PRINT((ndo
, " <"));
322 for ( ; ss
<= es
; ++ss
) {
325 if (!ND_TTEST(*dh
)) {
326 ND_PRINT((ndo
, "%s", tstr
));
332 ND_PRINT((ndo
, " dop-%d!", t
));
334 ND_PRINT((ndo
, " %s", dopstr
[t
]));
335 if (t
== DT_SKIP
|| t
== DT_HOLE
) {
336 uint32_t ts
= EXTRACT_32BITS(&dh
->dh_ts
);
337 ND_PRINT((ndo
, "%d", ts
- ss
+ 1));
338 if (ss
> ts
|| ts
> es
) {
339 ND_PRINT((ndo
, "[|]"));
348 ND_PRINT((ndo
, " >"));
353 wb_rrep(netdissect_options
*ndo
,
354 const struct pkt_rrep
*rrep
, u_int len
)
356 const struct pkt_dop
*dop
= &rrep
->pr_dop
;
358 ND_PRINT((ndo
, " wb-rrep:"));
359 if (len
< sizeof(*rrep
) || !ND_TTEST(*rrep
))
361 len
-= sizeof(*rrep
);
363 ND_PRINT((ndo
, " for %s %s:%u<%u:%u>",
364 ipaddr_string(ndo
, &rrep
->pr_id
),
365 ipaddr_string(ndo
, &dop
->pd_page
.p_sid
),
366 EXTRACT_32BITS(&dop
->pd_page
.p_uid
),
367 EXTRACT_32BITS(&dop
->pd_sseq
),
368 EXTRACT_32BITS(&dop
->pd_eseq
)));
371 return (wb_dops(ndo
, dop
,
372 EXTRACT_32BITS(&dop
->pd_sseq
),
373 EXTRACT_32BITS(&dop
->pd_eseq
)));
378 wb_drawop(netdissect_options
*ndo
,
379 const struct pkt_dop
*dop
, u_int len
)
381 ND_PRINT((ndo
, " wb-dop:"));
382 if (len
< sizeof(*dop
) || !ND_TTEST(*dop
))
386 ND_PRINT((ndo
, " %s:%u<%u:%u>",
387 ipaddr_string(ndo
, &dop
->pd_page
.p_sid
),
388 EXTRACT_32BITS(&dop
->pd_page
.p_uid
),
389 EXTRACT_32BITS(&dop
->pd_sseq
),
390 EXTRACT_32BITS(&dop
->pd_eseq
)));
393 return (wb_dops(ndo
, dop
,
394 EXTRACT_32BITS(&dop
->pd_sseq
),
395 EXTRACT_32BITS(&dop
->pd_eseq
)));
400 * Print whiteboard multicast packets.
403 wb_print(netdissect_options
*ndo
,
404 register const void *hdr
, register u_int len
)
406 register const struct pkt_hdr
*ph
;
408 ph
= (const struct pkt_hdr
*)hdr
;
409 if (len
< sizeof(*ph
) || !ND_TTEST(*ph
)) {
410 ND_PRINT((ndo
, "%s", tstr
));
416 ND_PRINT((ndo
, "*"));
417 switch (ph
->ph_type
) {
420 ND_PRINT((ndo
, " wb-kill"));
424 if (wb_id(ndo
, (struct pkt_id
*)(ph
+ 1), len
) >= 0)
429 if (wb_rreq(ndo
, (struct pkt_rreq
*)(ph
+ 1), len
) >= 0)
434 if (wb_rrep(ndo
, (struct pkt_rrep
*)(ph
+ 1), len
) >= 0)
439 if (wb_drawop(ndo
, (struct pkt_dop
*)(ph
+ 1), len
) >= 0)
444 if (wb_preq(ndo
, (struct pkt_preq
*)(ph
+ 1), len
) >= 0)
449 if (wb_prep(ndo
, (struct pkt_prep
*)(ph
+ 1), len
) >= 0)
454 ND_PRINT((ndo
, " wb-%d!", ph
->ph_type
));