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