etc/protocols - sync with NetBSD-8
[minix.git] / external / bsd / tcpdump / dist / print-wb.c
blobca657927dabad661f8f0c816ad72056a35429e9a
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 #include <sys/cdefs.h>
23 #ifndef lint
24 __RCSID("$NetBSD: print-wb.c,v 1.5 2015/03/31 21:59:35 christos Exp $");
25 #endif
27 #define NETDISSECT_REWORKED
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
32 #include <tcpdump-stdinc.h>
34 #include "interface.h"
35 #include "addrtoname.h"
36 #include "extract.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.
53 #define DOP_ALIGN 4
54 #define DOP_ROUNDUP(x) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
55 #define DOP_NEXT(d)\
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.
63 struct pkt_hdr {
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 */
71 /* Packet types */
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 */
80 #ifdef PF_USER
81 #undef PF_USER /* {Digital,Tru64} UNIX define this, alas */
82 #endif
84 /* flags */
85 #define PF_USER 0x01 /* hint that packet has interactive data */
86 #define PF_VIS 0x02 /* only visible ops wanted */
88 struct PageID {
89 uint32_t p_sid; /* session id of initiator */
90 uint32_t p_uid; /* page number */
93 struct dophdr {
94 uint32_t dh_ts; /* sender's timestamp */
95 uint16_t dh_len; /* body length */
96 u_char dh_flags;
97 u_char dh_type; /* body type */
98 /* body follows */
101 * Drawing op sub-types.
103 #define DT_RECT 2
104 #define DT_LINE 3
105 #define DT_ML 4
106 #define DT_DEL 5
107 #define DT_XFORM 6
108 #define DT_ELL 7
109 #define DT_CHAR 8
110 #define DT_STR 9
111 #define DT_NOP 10
112 #define DT_PSCODE 11
113 #define DT_PSCOMP 12
114 #define DT_REF 13
115 #define DT_SKIP 14
116 #define DT_HOLE 15
117 #define DT_MAXTYPE 15
120 * A drawing operation.
122 struct pkt_dop {
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 */
130 * A repair request.
132 struct pkt_rreq {
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 */
140 * A repair reply.
142 struct pkt_rrep {
143 uint32_t pr_id; /* original site id of ops */
144 struct pkt_dop pr_dop;
145 /* drawing ops follow */
148 struct id_off {
149 uint32_t id;
150 uint32_t off;
153 struct pgstate {
154 uint32_t slot;
155 struct PageID page;
156 uint16_t nid;
157 uint16_t rsvd;
158 /* seqptr's */
162 * An announcement packet.
164 struct pkt_id {
165 uint32_t pi_mslot;
166 struct PageID pi_mpage; /* current page */
167 struct pgstate pi_ps;
168 /* seqptr's */
169 /* null-terminated site name */
172 struct pkt_preq {
173 struct PageID pp_page;
174 uint32_t pp_low;
175 uint32_t pp_high;
178 struct pkt_prep {
179 uint32_t pp_n; /* size of pageid array */
180 /* pgstate's follow */
183 static int
184 wb_id(netdissect_options *ndo,
185 const struct pkt_id *id, u_int len)
187 int i;
188 const char *cp;
189 const struct id_off *io;
190 char c;
191 int nid;
193 ND_PRINT((ndo, " wb-id:"));
194 if (len < sizeof(*id) || !ND_TTEST(*id))
195 return (-1);
196 len -= sizeof(*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, "\""));
216 c = '<';
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)));
220 c = ',';
222 if (i >= nid) {
223 ND_PRINT((ndo, ">"));
224 return (0);
226 return (-1);
229 static int
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))
235 return (-1);
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)));
243 return (0);
246 static int
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))
252 return (-1);
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)));
258 return (0);
261 static int
262 wb_prep(netdissect_options *ndo,
263 const struct pkt_prep *prep, u_int len)
265 int n;
266 const struct pgstate *ps;
267 const u_char *ep = ndo->ndo_snapend;
269 ND_PRINT((ndo, " wb-prep:"));
270 if (len < sizeof(*prep)) {
271 return (-1);
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;
277 char c = '<';
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)));
287 c = ',';
289 ND_PRINT((ndo, ">"));
290 ps = (struct pgstate *)io;
292 return ((u_char *)ps <= ep? 0 : -1);
296 static const char *dopstr[] = {
297 "dop-0!",
298 "dop-1!",
299 "RECT",
300 "LINE",
301 "ML",
302 "DEL",
303 "XFORM",
304 "ELL",
305 "CHAR",
306 "STR",
307 "NOP",
308 "PSCODE",
309 "PSCOMP",
310 "REF",
311 "SKIP",
312 "HOLE",
315 static int
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) {
323 int t;
325 if (!ND_TTEST(*dh)) {
326 ND_PRINT((ndo, "%s", tstr));
327 break;
329 t = dh->dh_type;
331 if (t > DT_MAXTYPE)
332 ND_PRINT((ndo, " dop-%d!", t));
333 else {
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, "[|]"));
340 if (ts < ss)
341 return (0);
343 ss = ts;
346 dh = DOP_NEXT(dh);
348 ND_PRINT((ndo, " >"));
349 return (0);
352 static int
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))
360 return (-1);
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)));
370 if (ndo->ndo_vflag)
371 return (wb_dops(ndo, dop,
372 EXTRACT_32BITS(&dop->pd_sseq),
373 EXTRACT_32BITS(&dop->pd_eseq)));
374 return (0);
377 static int
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))
383 return (-1);
384 len -= sizeof(*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)));
392 if (ndo->ndo_vflag)
393 return (wb_dops(ndo, dop,
394 EXTRACT_32BITS(&dop->pd_sseq),
395 EXTRACT_32BITS(&dop->pd_eseq)));
396 return (0);
400 * Print whiteboard multicast packets.
402 void
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));
411 return;
413 len -= sizeof(*ph);
415 if (ph->ph_flags)
416 ND_PRINT((ndo, "*"));
417 switch (ph->ph_type) {
419 case PT_KILL:
420 ND_PRINT((ndo, " wb-kill"));
421 return;
423 case PT_ID:
424 if (wb_id(ndo, (struct pkt_id *)(ph + 1), len) >= 0)
425 return;
426 break;
428 case PT_RREQ:
429 if (wb_rreq(ndo, (struct pkt_rreq *)(ph + 1), len) >= 0)
430 return;
431 break;
433 case PT_RREP:
434 if (wb_rrep(ndo, (struct pkt_rrep *)(ph + 1), len) >= 0)
435 return;
436 break;
438 case PT_DRAWOP:
439 if (wb_drawop(ndo, (struct pkt_dop *)(ph + 1), len) >= 0)
440 return;
441 break;
443 case PT_PREQ:
444 if (wb_preq(ndo, (struct pkt_preq *)(ph + 1), len) >= 0)
445 return;
446 break;
448 case PT_PREP:
449 if (wb_prep(ndo, (struct pkt_prep *)(ph + 1), len) >= 0)
450 return;
451 break;
453 default:
454 ND_PRINT((ndo, " wb-%d!", ph->ph_type));
455 return;