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