xref: /openbsd/usr.sbin/tcpdump/print-wb.c (revision 133306f0)
1 /*	$OpenBSD: print-wb.c,v 1.6 2000/10/03 14:31:58 ho Exp $	*/
2 
3 /*
4  * Copyright (c) 1993, 1994, 1995, 1996
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Header: /home/cvs/src/usr.sbin/tcpdump/print-wb.c,v 1.6 2000/10/03 14:31:58 ho Exp $ (LBL)";
27 #endif
28 
29 #include <sys/types.h>
30 #include <sys/time.h>
31 
32 #include <netinet/in.h>
33 
34 #include <stdio.h>
35 
36 #include "interface.h"
37 #include "addrtoname.h"
38 
39 /* XXX need to add byte-swapping macros! */
40 
41 /*
42  * Largest packet size.  Everything should fit within this space.
43  * For instance, multiline objects are sent piecewise.
44  */
45 #define MAXFRAMESIZE 1024
46 
47 /*
48  * Multiple drawing ops can be sent in one packet.  Each one starts on a
49  * an even multiple of DOP_ALIGN bytes, which must be a power of two.
50  */
51 #define DOP_ALIGN 4
52 #define DOP_ROUNDUP(x)	((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
53 #define DOP_NEXT(d)\
54 	((struct dophdr *)((u_char *)(d) + \
55 			  DOP_ROUNDUP(ntohs((d)->dh_len) + sizeof(*(d)))))
56 
57 /*
58  * Format of the whiteboard packet header.
59  * The transport level header.
60  */
61 struct pkt_hdr {
62 	u_int32_t ph_src;		/* site id of source */
63 	u_int32_t ph_ts;		/* time stamp (for skew computation) */
64 	u_short ph_version;	/* version number */
65 	u_char ph_type;		/* message type */
66 	u_char ph_flags;	/* message flags */
67 };
68 
69 /* Packet types */
70 #define PT_DRAWOP	0	/* drawing operation */
71 #define PT_ID		1	/* announcement packet */
72 #define PT_RREQ		2	/* repair request */
73 #define PT_RREP		3	/* repair reply */
74 #define PT_KILL		4	/* terminate participation */
75 #define PT_PREQ         5       /* page vector request */
76 #define PT_PREP         7       /* page vector reply */
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_short	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_short nid;
151 	u_short 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 	len -= sizeof(*id);
188 	if (len < 0 || (u_char *)(id + 1) > snapend)
189 		return (-1);
190 
191 	printf(" %u/%s:%u (max %u/%s:%u) ",
192 	       (u_int32_t)ntohl(id->pi_ps.slot),
193 	       ipaddr_string(&id->pi_ps.page.p_sid),
194 	       (u_int32_t)ntohl(id->pi_ps.page.p_uid),
195 	       (u_int32_t)ntohl(id->pi_mslot),
196 	       ipaddr_string(&id->pi_mpage.p_sid),
197 	       (u_int32_t)ntohl(id->pi_mpage.p_uid));
198 
199 	nid = ntohs(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 < snapend; ++io, ++i) {
211 		printf("%c%s:%u",
212 		    c, ipaddr_string(&io->id), (u_int32_t)ntohl(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 	       (u_int32_t)ntohl(rreq->pr_page.p_uid),
233 	       (u_int32_t)ntohl(rreq->pr_sseq),
234 	       (u_int32_t)ntohl(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 	       (u_int32_t)ntohl(preq->pp_low),
247 	       ipaddr_string(&preq->pp_page.p_sid),
248 	       (u_int32_t)ntohl(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 = ntohl(prep->pp_n);
264 	ps = (const struct pgstate *)(prep + 1);
265 	while (--n >= 0 && (u_char *)ps < ep) {
266 		const struct id_off *io, *ie;
267 		char c = '<';
268 
269 		printf(" %u/%s:%u",
270 		    (u_int32_t)ntohl(ps->slot),
271 		    ipaddr_string(&ps->page.p_sid),
272 		    (u_int32_t)ntohl(ps->page.p_uid));
273 		io = (struct id_off *)(ps + 1);
274 		for (ie = io + ps->nid; io < ie && (u_char *)io < ep; ++io) {
275 			printf("%c%s:%u", c, ipaddr_string(&io->id),
276 			    (u_int32_t)ntohl(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 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 				int ts = ntohl(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 	len -= sizeof(*rrep);
344 	if (len < 0 || (u_char *)(rrep + 1) > snapend)
345 		return (-1);
346 
347 	printf(" for %s %s:%u<%u:%u>",
348 	    ipaddr_string(&rrep->pr_id),
349 	    ipaddr_string(&dop->pd_page.p_sid),
350 	    (u_int32_t)ntohl(dop->pd_page.p_uid),
351 	    (u_int32_t)ntohl(dop->pd_sseq),
352 	    (u_int32_t)ntohl(dop->pd_eseq));
353 
354 	if (vflag)
355 		return (wb_dops((const struct dophdr *)(dop + 1),
356 		    ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
357 	return (0);
358 }
359 
360 static int
361 wb_drawop(const struct pkt_dop *dop, u_int len)
362 {
363 	printf(" wb-dop:");
364 	len -= sizeof(*dop);
365 	if (len < 0 || (u_char *)(dop + 1) > snapend)
366 		return (-1);
367 
368 	printf(" %s:%u<%u:%u>",
369 	    ipaddr_string(&dop->pd_page.p_sid),
370 	    (u_int32_t)ntohl(dop->pd_page.p_uid),
371 	    (u_int32_t)ntohl(dop->pd_sseq),
372 	    (u_int32_t)ntohl(dop->pd_eseq));
373 
374 	if (vflag)
375 		return (wb_dops((const struct dophdr *)(dop + 1),
376 				ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
377 	return (0);
378 }
379 
380 /*
381  * Print whiteboard multicast packets.
382  */
383 void
384 wb_print(register const void *hdr, register u_int len)
385 {
386 	register const struct pkt_hdr *ph;
387 
388 	ph = (const struct pkt_hdr *)hdr;
389 	len -= sizeof(*ph);
390 	if (len < 0 || (u_char *)(ph + 1) <= snapend) {
391 		if (ph->ph_flags)
392 			printf("*");
393 		switch (ph->ph_type) {
394 
395 		case PT_KILL:
396 			printf(" wb-kill");
397 			return;
398 
399 		case PT_ID:
400 			if (wb_id((struct pkt_id *)(ph + 1), len) >= 0)
401 				return;
402 			break;
403 
404 		case PT_RREQ:
405 			if (wb_rreq((struct pkt_rreq *)(ph + 1), len) >= 0)
406 				return;
407 			break;
408 
409 		case PT_RREP:
410 			if (wb_rrep((struct pkt_rrep *)(ph + 1), len) >= 0)
411 				return;
412 			break;
413 
414 		case PT_DRAWOP:
415 			if (wb_drawop((struct pkt_dop *)(ph + 1), len) >= 0)
416 				return;
417 			break;
418 
419 		case PT_PREQ:
420 			if (wb_preq((struct pkt_preq *)(ph + 1), len) >= 0)
421 				return;
422 			break;
423 
424 		case PT_PREP:
425 			if (wb_prep((struct pkt_prep *)(ph + 1), len) >= 0)
426 				return;
427 			break;
428 
429 		default:
430 			printf(" wb-%d!", ph->ph_type);
431 			return;
432 		}
433 	}
434 	printf("[|wb]");
435 }
436