xref: /freebsd/contrib/tcpdump/print-wb.c (revision d74e86d9e30043893d6b308468008b65640ddcae)
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: print-wb.c,v 1.24 96/12/31 21:27:44 leres 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 }
436