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