8498 ficl: variable 'count' might be clobbered by 'longjmp' or 'vfork'
[unleashed.git] / contrib / tcpdump / print-wb.c
blobc0df48d747185e9d82699cf12299ba761a17a9a7
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 /* \summary: White Board printer */
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
28 #include <netdissect-stdinc.h>
30 #include "netdissect.h"
31 #include "addrtoname.h"
32 #include "extract.h"
34 static const char tstr[] = "[|wb]";
36 /* XXX need to add byte-swapping macros! */
37 /* XXX - you mean like the ones in "extract.h"? */
40 * Largest packet size. Everything should fit within this space.
41 * For instance, multiline objects are sent piecewise.
43 #define MAXFRAMESIZE 1024
46 * Multiple drawing ops can be sent in one packet. Each one starts on a
47 * an even multiple of DOP_ALIGN bytes, which must be a power of two.
49 #define DOP_ALIGN 4
50 #define DOP_ROUNDUP(x) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
51 #define DOP_NEXT(d)\
52 ((const struct dophdr *)((const u_char *)(d) + \
53 DOP_ROUNDUP(EXTRACT_16BITS(&(d)->dh_len) + sizeof(*(d)))))
56 * Format of the whiteboard packet header.
57 * The transport level header.
59 struct pkt_hdr {
60 uint32_t ph_src; /* site id of source */
61 uint32_t ph_ts; /* time stamp (for skew computation) */
62 uint16_t ph_version; /* version number */
63 u_char ph_type; /* message type */
64 u_char ph_flags; /* message flags */
67 /* Packet types */
68 #define PT_DRAWOP 0 /* drawing operation */
69 #define PT_ID 1 /* announcement packet */
70 #define PT_RREQ 2 /* repair request */
71 #define PT_RREP 3 /* repair reply */
72 #define PT_KILL 4 /* terminate participation */
73 #define PT_PREQ 5 /* page vector request */
74 #define PT_PREP 7 /* page vector reply */
76 #ifdef PF_USER
77 #undef PF_USER /* {Digital,Tru64} UNIX define this, alas */
78 #endif
80 /* flags */
81 #define PF_USER 0x01 /* hint that packet has interactive data */
82 #define PF_VIS 0x02 /* only visible ops wanted */
84 struct PageID {
85 uint32_t p_sid; /* session id of initiator */
86 uint32_t p_uid; /* page number */
89 struct dophdr {
90 uint32_t dh_ts; /* sender's timestamp */
91 uint16_t dh_len; /* body length */
92 u_char dh_flags;
93 u_char dh_type; /* body type */
94 /* body follows */
97 * Drawing op sub-types.
99 #define DT_RECT 2
100 #define DT_LINE 3
101 #define DT_ML 4
102 #define DT_DEL 5
103 #define DT_XFORM 6
104 #define DT_ELL 7
105 #define DT_CHAR 8
106 #define DT_STR 9
107 #define DT_NOP 10
108 #define DT_PSCODE 11
109 #define DT_PSCOMP 12
110 #define DT_REF 13
111 #define DT_SKIP 14
112 #define DT_HOLE 15
113 #define DT_MAXTYPE 15
116 * A drawing operation.
118 struct pkt_dop {
119 struct PageID pd_page; /* page that operations apply to */
120 uint32_t pd_sseq; /* start sequence number */
121 uint32_t pd_eseq; /* end sequence number */
122 /* drawing ops follow */
126 * A repair request.
128 struct pkt_rreq {
129 uint32_t pr_id; /* source id of drawops to be repaired */
130 struct PageID pr_page; /* page of drawops */
131 uint32_t pr_sseq; /* start seqno */
132 uint32_t pr_eseq; /* end seqno */
136 * A repair reply.
138 struct pkt_rrep {
139 uint32_t pr_id; /* original site id of ops */
140 struct pkt_dop pr_dop;
141 /* drawing ops follow */
144 struct id_off {
145 uint32_t id;
146 uint32_t off;
149 struct pgstate {
150 uint32_t slot;
151 struct PageID page;
152 uint16_t nid;
153 uint16_t rsvd;
154 /* seqptr's */
158 * An announcement packet.
160 struct pkt_id {
161 uint32_t pi_mslot;
162 struct PageID pi_mpage; /* current page */
163 struct pgstate pi_ps;
164 /* seqptr's */
165 /* null-terminated site name */
168 struct pkt_preq {
169 struct PageID pp_page;
170 uint32_t pp_low;
171 uint32_t pp_high;
174 struct pkt_prep {
175 uint32_t pp_n; /* size of pageid array */
176 /* pgstate's follow */
179 static int
180 wb_id(netdissect_options *ndo,
181 const struct pkt_id *id, u_int len)
183 int i;
184 const char *cp;
185 const struct id_off *io;
186 char c;
187 int nid;
189 ND_PRINT((ndo, " wb-id:"));
190 if (len < sizeof(*id) || !ND_TTEST(*id))
191 return (-1);
192 len -= sizeof(*id);
194 ND_PRINT((ndo, " %u/%s:%u (max %u/%s:%u) ",
195 EXTRACT_32BITS(&id->pi_ps.slot),
196 ipaddr_string(ndo, &id->pi_ps.page.p_sid),
197 EXTRACT_32BITS(&id->pi_ps.page.p_uid),
198 EXTRACT_32BITS(&id->pi_mslot),
199 ipaddr_string(ndo, &id->pi_mpage.p_sid),
200 EXTRACT_32BITS(&id->pi_mpage.p_uid)));
202 nid = EXTRACT_16BITS(&id->pi_ps.nid);
203 len -= sizeof(*io) * nid;
204 io = (const struct id_off *)(id + 1);
205 cp = (const char *)(io + nid);
206 if (ND_TTEST2(cp, len)) {
207 ND_PRINT((ndo, "\""));
208 fn_print(ndo, (const u_char *)cp, (const u_char *)cp + len);
209 ND_PRINT((ndo, "\""));
212 c = '<';
213 for (i = 0; i < nid && ND_TTEST(*io); ++io, ++i) {
214 ND_PRINT((ndo, "%c%s:%u",
215 c, ipaddr_string(ndo, &io->id), EXTRACT_32BITS(&io->off)));
216 c = ',';
218 if (i >= nid) {
219 ND_PRINT((ndo, ">"));
220 return (0);
222 return (-1);
225 static int
226 wb_rreq(netdissect_options *ndo,
227 const struct pkt_rreq *rreq, u_int len)
229 ND_PRINT((ndo, " wb-rreq:"));
230 if (len < sizeof(*rreq) || !ND_TTEST(*rreq))
231 return (-1);
233 ND_PRINT((ndo, " please repair %s %s:%u<%u:%u>",
234 ipaddr_string(ndo, &rreq->pr_id),
235 ipaddr_string(ndo, &rreq->pr_page.p_sid),
236 EXTRACT_32BITS(&rreq->pr_page.p_uid),
237 EXTRACT_32BITS(&rreq->pr_sseq),
238 EXTRACT_32BITS(&rreq->pr_eseq)));
239 return (0);
242 static int
243 wb_preq(netdissect_options *ndo,
244 const struct pkt_preq *preq, u_int len)
246 ND_PRINT((ndo, " wb-preq:"));
247 if (len < sizeof(*preq) || !ND_TTEST(*preq))
248 return (-1);
250 ND_PRINT((ndo, " need %u/%s:%u",
251 EXTRACT_32BITS(&preq->pp_low),
252 ipaddr_string(ndo, &preq->pp_page.p_sid),
253 EXTRACT_32BITS(&preq->pp_page.p_uid)));
254 return (0);
257 static int
258 wb_prep(netdissect_options *ndo,
259 const struct pkt_prep *prep, u_int len)
261 int n;
262 const struct pgstate *ps;
263 const u_char *ep = ndo->ndo_snapend;
265 ND_PRINT((ndo, " wb-prep:"));
266 if (len < sizeof(*prep) || !ND_TTEST(*prep))
267 return (-1);
268 n = EXTRACT_32BITS(&prep->pp_n);
269 ps = (const struct pgstate *)(prep + 1);
270 while (--n >= 0 && ND_TTEST(*ps)) {
271 const struct id_off *io, *ie;
272 char c = '<';
274 ND_PRINT((ndo, " %u/%s:%u",
275 EXTRACT_32BITS(&ps->slot),
276 ipaddr_string(ndo, &ps->page.p_sid),
277 EXTRACT_32BITS(&ps->page.p_uid)));
278 io = (const struct id_off *)(ps + 1);
279 for (ie = io + ps->nid; io < ie && ND_TTEST(*io); ++io) {
280 ND_PRINT((ndo, "%c%s:%u", c, ipaddr_string(ndo, &io->id),
281 EXTRACT_32BITS(&io->off)));
282 c = ',';
284 ND_PRINT((ndo, ">"));
285 ps = (const struct pgstate *)io;
287 return ((const u_char *)ps <= ep? 0 : -1);
291 static 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(netdissect_options *ndo, const struct pkt_dop *dop,
312 uint32_t ss, uint32_t es)
314 const struct dophdr *dh = (const struct dophdr *)((const u_char *)dop + sizeof(*dop));
316 ND_PRINT((ndo, " <"));
317 for ( ; ss <= es; ++ss) {
318 int t;
320 if (!ND_TTEST(*dh)) {
321 ND_PRINT((ndo, "%s", tstr));
322 break;
324 t = dh->dh_type;
326 if (t > DT_MAXTYPE)
327 ND_PRINT((ndo, " dop-%d!", t));
328 else {
329 ND_PRINT((ndo, " %s", dopstr[t]));
330 if (t == DT_SKIP || t == DT_HOLE) {
331 uint32_t ts = EXTRACT_32BITS(&dh->dh_ts);
332 ND_PRINT((ndo, "%d", ts - ss + 1));
333 if (ss > ts || ts > es) {
334 ND_PRINT((ndo, "[|]"));
335 if (ts < ss)
336 return (0);
338 ss = ts;
341 dh = DOP_NEXT(dh);
343 ND_PRINT((ndo, " >"));
344 return (0);
347 static int
348 wb_rrep(netdissect_options *ndo,
349 const struct pkt_rrep *rrep, u_int len)
351 const struct pkt_dop *dop = &rrep->pr_dop;
353 ND_PRINT((ndo, " wb-rrep:"));
354 if (len < sizeof(*rrep) || !ND_TTEST(*rrep))
355 return (-1);
356 len -= sizeof(*rrep);
358 ND_PRINT((ndo, " for %s %s:%u<%u:%u>",
359 ipaddr_string(ndo, &rrep->pr_id),
360 ipaddr_string(ndo, &dop->pd_page.p_sid),
361 EXTRACT_32BITS(&dop->pd_page.p_uid),
362 EXTRACT_32BITS(&dop->pd_sseq),
363 EXTRACT_32BITS(&dop->pd_eseq)));
365 if (ndo->ndo_vflag)
366 return (wb_dops(ndo, dop,
367 EXTRACT_32BITS(&dop->pd_sseq),
368 EXTRACT_32BITS(&dop->pd_eseq)));
369 return (0);
372 static int
373 wb_drawop(netdissect_options *ndo,
374 const struct pkt_dop *dop, u_int len)
376 ND_PRINT((ndo, " wb-dop:"));
377 if (len < sizeof(*dop) || !ND_TTEST(*dop))
378 return (-1);
379 len -= sizeof(*dop);
381 ND_PRINT((ndo, " %s:%u<%u:%u>",
382 ipaddr_string(ndo, &dop->pd_page.p_sid),
383 EXTRACT_32BITS(&dop->pd_page.p_uid),
384 EXTRACT_32BITS(&dop->pd_sseq),
385 EXTRACT_32BITS(&dop->pd_eseq)));
387 if (ndo->ndo_vflag)
388 return (wb_dops(ndo, dop,
389 EXTRACT_32BITS(&dop->pd_sseq),
390 EXTRACT_32BITS(&dop->pd_eseq)));
391 return (0);
395 * Print whiteboard multicast packets.
397 void
398 wb_print(netdissect_options *ndo,
399 register const void *hdr, register u_int len)
401 register const struct pkt_hdr *ph;
403 ph = (const struct pkt_hdr *)hdr;
404 if (len < sizeof(*ph) || !ND_TTEST(*ph)) {
405 ND_PRINT((ndo, "%s", tstr));
406 return;
408 len -= sizeof(*ph);
410 if (ph->ph_flags)
411 ND_PRINT((ndo, "*"));
412 switch (ph->ph_type) {
414 case PT_KILL:
415 ND_PRINT((ndo, " wb-kill"));
416 return;
418 case PT_ID:
419 if (wb_id(ndo, (const struct pkt_id *)(ph + 1), len) >= 0)
420 return;
421 ND_PRINT((ndo, "%s", tstr));
422 break;
424 case PT_RREQ:
425 if (wb_rreq(ndo, (const struct pkt_rreq *)(ph + 1), len) >= 0)
426 return;
427 ND_PRINT((ndo, "%s", tstr));
428 break;
430 case PT_RREP:
431 if (wb_rrep(ndo, (const struct pkt_rrep *)(ph + 1), len) >= 0)
432 return;
433 ND_PRINT((ndo, "%s", tstr));
434 break;
436 case PT_DRAWOP:
437 if (wb_drawop(ndo, (const struct pkt_dop *)(ph + 1), len) >= 0)
438 return;
439 ND_PRINT((ndo, "%s", tstr));
440 break;
442 case PT_PREQ:
443 if (wb_preq(ndo, (const struct pkt_preq *)(ph + 1), len) >= 0)
444 return;
445 ND_PRINT((ndo, "%s", tstr));
446 break;
448 case PT_PREP:
449 if (wb_prep(ndo, (const struct pkt_prep *)(ph + 1), len) >= 0)
450 return;
451 ND_PRINT((ndo, "%s", tstr));
452 break;
454 default:
455 ND_PRINT((ndo, " wb-%d!", ph->ph_type));
456 return;