print-wb.c revision 1.2.8.1 1 1.1 christos /*
2 1.1 christos * Copyright (c) 1993, 1994, 1995, 1996
3 1.1 christos * The Regents of the University of California. All rights reserved.
4 1.1 christos *
5 1.1 christos * Redistribution and use in source and binary forms, with or without
6 1.1 christos * modification, are permitted provided that: (1) source code distributions
7 1.1 christos * retain the above copyright notice and this paragraph in its entirety, (2)
8 1.1 christos * distributions including binary code include the above copyright notice and
9 1.1 christos * this paragraph in its entirety in the documentation or other materials
10 1.1 christos * provided with the distribution, and (3) all advertising materials mentioning
11 1.1 christos * features or use of this software display the following acknowledgement:
12 1.1 christos * ``This product includes software developed by the University of California,
13 1.1 christos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 1.1 christos * the University nor the names of its contributors may be used to endorse
15 1.1 christos * or promote products derived from this software without specific prior
16 1.1 christos * written permission.
17 1.1 christos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 1.1 christos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 1.1 christos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 1.1 christos */
21 1.1 christos
22 1.2 christos #include <sys/cdefs.h>
23 1.1 christos #ifndef lint
24 1.2.8.1 snj __RCSID("$NetBSD: print-wb.c,v 1.2.8.1 2017/02/19 07:37:09 snj Exp $");
25 1.1 christos #endif
26 1.1 christos
27 1.2.8.1 snj /* \summary: White Board printer */
28 1.2.8.1 snj
29 1.1 christos #ifdef HAVE_CONFIG_H
30 1.1 christos #include "config.h"
31 1.1 christos #endif
32 1.1 christos
33 1.2.8.1 snj #include <netdissect-stdinc.h>
34 1.1 christos
35 1.2.8.1 snj #include "netdissect.h"
36 1.1 christos #include "addrtoname.h"
37 1.1 christos #include "extract.h"
38 1.1 christos
39 1.2.8.1 snj static const char tstr[] = "[|wb]";
40 1.2.8.1 snj
41 1.1 christos /* XXX need to add byte-swapping macros! */
42 1.1 christos /* XXX - you mean like the ones in "extract.h"? */
43 1.1 christos
44 1.1 christos /*
45 1.1 christos * Largest packet size. Everything should fit within this space.
46 1.1 christos * For instance, multiline objects are sent piecewise.
47 1.1 christos */
48 1.1 christos #define MAXFRAMESIZE 1024
49 1.1 christos
50 1.1 christos /*
51 1.1 christos * Multiple drawing ops can be sent in one packet. Each one starts on a
52 1.1 christos * an even multiple of DOP_ALIGN bytes, which must be a power of two.
53 1.1 christos */
54 1.1 christos #define DOP_ALIGN 4
55 1.1 christos #define DOP_ROUNDUP(x) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
56 1.1 christos #define DOP_NEXT(d)\
57 1.2.8.1 snj ((const struct dophdr *)((const u_char *)(d) + \
58 1.2.8.1 snj DOP_ROUNDUP(EXTRACT_16BITS(&(d)->dh_len) + sizeof(*(d)))))
59 1.1 christos
60 1.1 christos /*
61 1.1 christos * Format of the whiteboard packet header.
62 1.1 christos * The transport level header.
63 1.1 christos */
64 1.1 christos struct pkt_hdr {
65 1.2.8.1 snj uint32_t ph_src; /* site id of source */
66 1.2.8.1 snj uint32_t ph_ts; /* time stamp (for skew computation) */
67 1.2.8.1 snj uint16_t ph_version; /* version number */
68 1.1 christos u_char ph_type; /* message type */
69 1.1 christos u_char ph_flags; /* message flags */
70 1.1 christos };
71 1.1 christos
72 1.1 christos /* Packet types */
73 1.1 christos #define PT_DRAWOP 0 /* drawing operation */
74 1.1 christos #define PT_ID 1 /* announcement packet */
75 1.1 christos #define PT_RREQ 2 /* repair request */
76 1.1 christos #define PT_RREP 3 /* repair reply */
77 1.1 christos #define PT_KILL 4 /* terminate participation */
78 1.1 christos #define PT_PREQ 5 /* page vector request */
79 1.1 christos #define PT_PREP 7 /* page vector reply */
80 1.1 christos
81 1.1 christos #ifdef PF_USER
82 1.1 christos #undef PF_USER /* {Digital,Tru64} UNIX define this, alas */
83 1.1 christos #endif
84 1.1 christos
85 1.1 christos /* flags */
86 1.1 christos #define PF_USER 0x01 /* hint that packet has interactive data */
87 1.1 christos #define PF_VIS 0x02 /* only visible ops wanted */
88 1.1 christos
89 1.1 christos struct PageID {
90 1.2.8.1 snj uint32_t p_sid; /* session id of initiator */
91 1.2.8.1 snj uint32_t p_uid; /* page number */
92 1.1 christos };
93 1.1 christos
94 1.1 christos struct dophdr {
95 1.2.8.1 snj uint32_t dh_ts; /* sender's timestamp */
96 1.2.8.1 snj uint16_t dh_len; /* body length */
97 1.1 christos u_char dh_flags;
98 1.1 christos u_char dh_type; /* body type */
99 1.1 christos /* body follows */
100 1.1 christos };
101 1.1 christos /*
102 1.1 christos * Drawing op sub-types.
103 1.1 christos */
104 1.1 christos #define DT_RECT 2
105 1.1 christos #define DT_LINE 3
106 1.1 christos #define DT_ML 4
107 1.1 christos #define DT_DEL 5
108 1.1 christos #define DT_XFORM 6
109 1.1 christos #define DT_ELL 7
110 1.1 christos #define DT_CHAR 8
111 1.1 christos #define DT_STR 9
112 1.1 christos #define DT_NOP 10
113 1.1 christos #define DT_PSCODE 11
114 1.1 christos #define DT_PSCOMP 12
115 1.1 christos #define DT_REF 13
116 1.1 christos #define DT_SKIP 14
117 1.1 christos #define DT_HOLE 15
118 1.1 christos #define DT_MAXTYPE 15
119 1.1 christos
120 1.1 christos /*
121 1.1 christos * A drawing operation.
122 1.1 christos */
123 1.1 christos struct pkt_dop {
124 1.1 christos struct PageID pd_page; /* page that operations apply to */
125 1.2.8.1 snj uint32_t pd_sseq; /* start sequence number */
126 1.2.8.1 snj uint32_t pd_eseq; /* end sequence number */
127 1.1 christos /* drawing ops follow */
128 1.1 christos };
129 1.1 christos
130 1.1 christos /*
131 1.1 christos * A repair request.
132 1.1 christos */
133 1.1 christos struct pkt_rreq {
134 1.2.8.1 snj uint32_t pr_id; /* source id of drawops to be repaired */
135 1.1 christos struct PageID pr_page; /* page of drawops */
136 1.2.8.1 snj uint32_t pr_sseq; /* start seqno */
137 1.2.8.1 snj uint32_t pr_eseq; /* end seqno */
138 1.1 christos };
139 1.1 christos
140 1.1 christos /*
141 1.1 christos * A repair reply.
142 1.1 christos */
143 1.1 christos struct pkt_rrep {
144 1.2.8.1 snj uint32_t pr_id; /* original site id of ops */
145 1.1 christos struct pkt_dop pr_dop;
146 1.1 christos /* drawing ops follow */
147 1.1 christos };
148 1.1 christos
149 1.1 christos struct id_off {
150 1.2.8.1 snj uint32_t id;
151 1.2.8.1 snj uint32_t off;
152 1.1 christos };
153 1.1 christos
154 1.1 christos struct pgstate {
155 1.2.8.1 snj uint32_t slot;
156 1.1 christos struct PageID page;
157 1.2.8.1 snj uint16_t nid;
158 1.2.8.1 snj uint16_t rsvd;
159 1.1 christos /* seqptr's */
160 1.1 christos };
161 1.1 christos
162 1.1 christos /*
163 1.1 christos * An announcement packet.
164 1.1 christos */
165 1.1 christos struct pkt_id {
166 1.2.8.1 snj uint32_t pi_mslot;
167 1.1 christos struct PageID pi_mpage; /* current page */
168 1.1 christos struct pgstate pi_ps;
169 1.1 christos /* seqptr's */
170 1.1 christos /* null-terminated site name */
171 1.1 christos };
172 1.1 christos
173 1.1 christos struct pkt_preq {
174 1.1 christos struct PageID pp_page;
175 1.2.8.1 snj uint32_t pp_low;
176 1.2.8.1 snj uint32_t pp_high;
177 1.1 christos };
178 1.1 christos
179 1.1 christos struct pkt_prep {
180 1.2.8.1 snj uint32_t pp_n; /* size of pageid array */
181 1.1 christos /* pgstate's follow */
182 1.1 christos };
183 1.1 christos
184 1.1 christos static int
185 1.2.8.1 snj wb_id(netdissect_options *ndo,
186 1.2.8.1 snj const struct pkt_id *id, u_int len)
187 1.1 christos {
188 1.1 christos int i;
189 1.1 christos const char *cp;
190 1.1 christos const struct id_off *io;
191 1.1 christos char c;
192 1.1 christos int nid;
193 1.1 christos
194 1.2.8.1 snj ND_PRINT((ndo, " wb-id:"));
195 1.2.8.1 snj if (len < sizeof(*id) || !ND_TTEST(*id))
196 1.1 christos return (-1);
197 1.1 christos len -= sizeof(*id);
198 1.1 christos
199 1.2.8.1 snj ND_PRINT((ndo, " %u/%s:%u (max %u/%s:%u) ",
200 1.1 christos EXTRACT_32BITS(&id->pi_ps.slot),
201 1.2.8.1 snj ipaddr_string(ndo, &id->pi_ps.page.p_sid),
202 1.1 christos EXTRACT_32BITS(&id->pi_ps.page.p_uid),
203 1.1 christos EXTRACT_32BITS(&id->pi_mslot),
204 1.2.8.1 snj ipaddr_string(ndo, &id->pi_mpage.p_sid),
205 1.2.8.1 snj EXTRACT_32BITS(&id->pi_mpage.p_uid)));
206 1.1 christos
207 1.1 christos nid = EXTRACT_16BITS(&id->pi_ps.nid);
208 1.1 christos len -= sizeof(*io) * nid;
209 1.2.8.1 snj io = (const struct id_off *)(id + 1);
210 1.2.8.1 snj cp = (const char *)(io + nid);
211 1.2.8.1 snj if (ND_TTEST2(cp, len)) {
212 1.2.8.1 snj ND_PRINT((ndo, "\""));
213 1.2.8.1 snj fn_print(ndo, (const u_char *)cp, (const u_char *)cp + len);
214 1.2.8.1 snj ND_PRINT((ndo, "\""));
215 1.1 christos }
216 1.1 christos
217 1.1 christos c = '<';
218 1.2.8.1 snj for (i = 0; i < nid && ND_TTEST(*io); ++io, ++i) {
219 1.2.8.1 snj ND_PRINT((ndo, "%c%s:%u",
220 1.2.8.1 snj c, ipaddr_string(ndo, &io->id), EXTRACT_32BITS(&io->off)));
221 1.1 christos c = ',';
222 1.1 christos }
223 1.1 christos if (i >= nid) {
224 1.2.8.1 snj ND_PRINT((ndo, ">"));
225 1.1 christos return (0);
226 1.1 christos }
227 1.1 christos return (-1);
228 1.1 christos }
229 1.1 christos
230 1.1 christos static int
231 1.2.8.1 snj wb_rreq(netdissect_options *ndo,
232 1.2.8.1 snj const struct pkt_rreq *rreq, u_int len)
233 1.1 christos {
234 1.2.8.1 snj ND_PRINT((ndo, " wb-rreq:"));
235 1.2.8.1 snj if (len < sizeof(*rreq) || !ND_TTEST(*rreq))
236 1.1 christos return (-1);
237 1.1 christos
238 1.2.8.1 snj ND_PRINT((ndo, " please repair %s %s:%u<%u:%u>",
239 1.2.8.1 snj ipaddr_string(ndo, &rreq->pr_id),
240 1.2.8.1 snj ipaddr_string(ndo, &rreq->pr_page.p_sid),
241 1.1 christos EXTRACT_32BITS(&rreq->pr_page.p_uid),
242 1.1 christos EXTRACT_32BITS(&rreq->pr_sseq),
243 1.2.8.1 snj EXTRACT_32BITS(&rreq->pr_eseq)));
244 1.1 christos return (0);
245 1.1 christos }
246 1.1 christos
247 1.1 christos static int
248 1.2.8.1 snj wb_preq(netdissect_options *ndo,
249 1.2.8.1 snj const struct pkt_preq *preq, u_int len)
250 1.1 christos {
251 1.2.8.1 snj ND_PRINT((ndo, " wb-preq:"));
252 1.2.8.1 snj if (len < sizeof(*preq) || !ND_TTEST(*preq))
253 1.1 christos return (-1);
254 1.1 christos
255 1.2.8.1 snj ND_PRINT((ndo, " need %u/%s:%u",
256 1.1 christos EXTRACT_32BITS(&preq->pp_low),
257 1.2.8.1 snj ipaddr_string(ndo, &preq->pp_page.p_sid),
258 1.2.8.1 snj EXTRACT_32BITS(&preq->pp_page.p_uid)));
259 1.1 christos return (0);
260 1.1 christos }
261 1.1 christos
262 1.1 christos static int
263 1.2.8.1 snj wb_prep(netdissect_options *ndo,
264 1.2.8.1 snj const struct pkt_prep *prep, u_int len)
265 1.1 christos {
266 1.1 christos int n;
267 1.1 christos const struct pgstate *ps;
268 1.2.8.1 snj const u_char *ep = ndo->ndo_snapend;
269 1.1 christos
270 1.2.8.1 snj ND_PRINT((ndo, " wb-prep:"));
271 1.1 christos if (len < sizeof(*prep)) {
272 1.1 christos return (-1);
273 1.1 christos }
274 1.1 christos n = EXTRACT_32BITS(&prep->pp_n);
275 1.1 christos ps = (const struct pgstate *)(prep + 1);
276 1.2.8.1 snj while (--n >= 0 && ND_TTEST(*ps)) {
277 1.1 christos const struct id_off *io, *ie;
278 1.1 christos char c = '<';
279 1.1 christos
280 1.2.8.1 snj ND_PRINT((ndo, " %u/%s:%u",
281 1.1 christos EXTRACT_32BITS(&ps->slot),
282 1.2.8.1 snj ipaddr_string(ndo, &ps->page.p_sid),
283 1.2.8.1 snj EXTRACT_32BITS(&ps->page.p_uid)));
284 1.2.8.1 snj io = (const struct id_off *)(ps + 1);
285 1.2.8.1 snj for (ie = io + ps->nid; io < ie && ND_TTEST(*io); ++io) {
286 1.2.8.1 snj ND_PRINT((ndo, "%c%s:%u", c, ipaddr_string(ndo, &io->id),
287 1.2.8.1 snj EXTRACT_32BITS(&io->off)));
288 1.1 christos c = ',';
289 1.1 christos }
290 1.2.8.1 snj ND_PRINT((ndo, ">"));
291 1.2.8.1 snj ps = (const struct pgstate *)io;
292 1.1 christos }
293 1.2.8.1 snj return ((const u_char *)ps <= ep? 0 : -1);
294 1.1 christos }
295 1.1 christos
296 1.1 christos
297 1.2.8.1 snj static const char *dopstr[] = {
298 1.1 christos "dop-0!",
299 1.1 christos "dop-1!",
300 1.1 christos "RECT",
301 1.1 christos "LINE",
302 1.1 christos "ML",
303 1.1 christos "DEL",
304 1.1 christos "XFORM",
305 1.1 christos "ELL",
306 1.1 christos "CHAR",
307 1.1 christos "STR",
308 1.1 christos "NOP",
309 1.1 christos "PSCODE",
310 1.1 christos "PSCOMP",
311 1.1 christos "REF",
312 1.1 christos "SKIP",
313 1.1 christos "HOLE",
314 1.1 christos };
315 1.1 christos
316 1.1 christos static int
317 1.2.8.1 snj wb_dops(netdissect_options *ndo, const struct pkt_dop *dop,
318 1.2.8.1 snj uint32_t ss, uint32_t es)
319 1.1 christos {
320 1.2.8.1 snj const struct dophdr *dh = (const struct dophdr *)((const u_char *)dop + sizeof(*dop));
321 1.2.8.1 snj
322 1.2.8.1 snj ND_PRINT((ndo, " <"));
323 1.1 christos for ( ; ss <= es; ++ss) {
324 1.2.8.1 snj int t;
325 1.2.8.1 snj
326 1.2.8.1 snj if (!ND_TTEST(*dh)) {
327 1.2.8.1 snj ND_PRINT((ndo, "%s", tstr));
328 1.2.8.1 snj break;
329 1.2.8.1 snj }
330 1.2.8.1 snj t = dh->dh_type;
331 1.1 christos
332 1.1 christos if (t > DT_MAXTYPE)
333 1.2.8.1 snj ND_PRINT((ndo, " dop-%d!", t));
334 1.1 christos else {
335 1.2.8.1 snj ND_PRINT((ndo, " %s", dopstr[t]));
336 1.1 christos if (t == DT_SKIP || t == DT_HOLE) {
337 1.2.8.1 snj uint32_t ts = EXTRACT_32BITS(&dh->dh_ts);
338 1.2.8.1 snj ND_PRINT((ndo, "%d", ts - ss + 1));
339 1.1 christos if (ss > ts || ts > es) {
340 1.2.8.1 snj ND_PRINT((ndo, "[|]"));
341 1.1 christos if (ts < ss)
342 1.1 christos return (0);
343 1.1 christos }
344 1.1 christos ss = ts;
345 1.1 christos }
346 1.1 christos }
347 1.1 christos dh = DOP_NEXT(dh);
348 1.1 christos }
349 1.2.8.1 snj ND_PRINT((ndo, " >"));
350 1.1 christos return (0);
351 1.1 christos }
352 1.1 christos
353 1.1 christos static int
354 1.2.8.1 snj wb_rrep(netdissect_options *ndo,
355 1.2.8.1 snj const struct pkt_rrep *rrep, u_int len)
356 1.1 christos {
357 1.1 christos const struct pkt_dop *dop = &rrep->pr_dop;
358 1.1 christos
359 1.2.8.1 snj ND_PRINT((ndo, " wb-rrep:"));
360 1.2.8.1 snj if (len < sizeof(*rrep) || !ND_TTEST(*rrep))
361 1.1 christos return (-1);
362 1.1 christos len -= sizeof(*rrep);
363 1.1 christos
364 1.2.8.1 snj ND_PRINT((ndo, " for %s %s:%u<%u:%u>",
365 1.2.8.1 snj ipaddr_string(ndo, &rrep->pr_id),
366 1.2.8.1 snj ipaddr_string(ndo, &dop->pd_page.p_sid),
367 1.1 christos EXTRACT_32BITS(&dop->pd_page.p_uid),
368 1.1 christos EXTRACT_32BITS(&dop->pd_sseq),
369 1.2.8.1 snj EXTRACT_32BITS(&dop->pd_eseq)));
370 1.1 christos
371 1.2.8.1 snj if (ndo->ndo_vflag)
372 1.2.8.1 snj return (wb_dops(ndo, dop,
373 1.1 christos EXTRACT_32BITS(&dop->pd_sseq),
374 1.1 christos EXTRACT_32BITS(&dop->pd_eseq)));
375 1.1 christos return (0);
376 1.1 christos }
377 1.1 christos
378 1.1 christos static int
379 1.2.8.1 snj wb_drawop(netdissect_options *ndo,
380 1.2.8.1 snj const struct pkt_dop *dop, u_int len)
381 1.1 christos {
382 1.2.8.1 snj ND_PRINT((ndo, " wb-dop:"));
383 1.2.8.1 snj if (len < sizeof(*dop) || !ND_TTEST(*dop))
384 1.1 christos return (-1);
385 1.1 christos len -= sizeof(*dop);
386 1.1 christos
387 1.2.8.1 snj ND_PRINT((ndo, " %s:%u<%u:%u>",
388 1.2.8.1 snj ipaddr_string(ndo, &dop->pd_page.p_sid),
389 1.1 christos EXTRACT_32BITS(&dop->pd_page.p_uid),
390 1.1 christos EXTRACT_32BITS(&dop->pd_sseq),
391 1.2.8.1 snj EXTRACT_32BITS(&dop->pd_eseq)));
392 1.1 christos
393 1.2.8.1 snj if (ndo->ndo_vflag)
394 1.2.8.1 snj return (wb_dops(ndo, dop,
395 1.1 christos EXTRACT_32BITS(&dop->pd_sseq),
396 1.1 christos EXTRACT_32BITS(&dop->pd_eseq)));
397 1.1 christos return (0);
398 1.1 christos }
399 1.1 christos
400 1.1 christos /*
401 1.1 christos * Print whiteboard multicast packets.
402 1.1 christos */
403 1.1 christos void
404 1.2.8.1 snj wb_print(netdissect_options *ndo,
405 1.2.8.1 snj register const void *hdr, register u_int len)
406 1.1 christos {
407 1.1 christos register const struct pkt_hdr *ph;
408 1.1 christos
409 1.1 christos ph = (const struct pkt_hdr *)hdr;
410 1.2.8.1 snj if (len < sizeof(*ph) || !ND_TTEST(*ph)) {
411 1.2.8.1 snj ND_PRINT((ndo, "%s", tstr));
412 1.1 christos return;
413 1.1 christos }
414 1.1 christos len -= sizeof(*ph);
415 1.1 christos
416 1.1 christos if (ph->ph_flags)
417 1.2.8.1 snj ND_PRINT((ndo, "*"));
418 1.1 christos switch (ph->ph_type) {
419 1.1 christos
420 1.1 christos case PT_KILL:
421 1.2.8.1 snj ND_PRINT((ndo, " wb-kill"));
422 1.1 christos return;
423 1.1 christos
424 1.1 christos case PT_ID:
425 1.2.8.1 snj if (wb_id(ndo, (const struct pkt_id *)(ph + 1), len) >= 0)
426 1.1 christos return;
427 1.1 christos break;
428 1.1 christos
429 1.1 christos case PT_RREQ:
430 1.2.8.1 snj if (wb_rreq(ndo, (const struct pkt_rreq *)(ph + 1), len) >= 0)
431 1.1 christos return;
432 1.1 christos break;
433 1.1 christos
434 1.1 christos case PT_RREP:
435 1.2.8.1 snj if (wb_rrep(ndo, (const struct pkt_rrep *)(ph + 1), len) >= 0)
436 1.1 christos return;
437 1.1 christos break;
438 1.1 christos
439 1.1 christos case PT_DRAWOP:
440 1.2.8.1 snj if (wb_drawop(ndo, (const struct pkt_dop *)(ph + 1), len) >= 0)
441 1.1 christos return;
442 1.1 christos break;
443 1.1 christos
444 1.1 christos case PT_PREQ:
445 1.2.8.1 snj if (wb_preq(ndo, (const struct pkt_preq *)(ph + 1), len) >= 0)
446 1.1 christos return;
447 1.1 christos break;
448 1.1 christos
449 1.1 christos case PT_PREP:
450 1.2.8.1 snj if (wb_prep(ndo, (const struct pkt_prep *)(ph + 1), len) >= 0)
451 1.1 christos return;
452 1.1 christos break;
453 1.1 christos
454 1.1 christos default:
455 1.2.8.1 snj ND_PRINT((ndo, " wb-%d!", ph->ph_type));
456 1.1 christos return;
457 1.1 christos }
458 1.1 christos }
459