print-wb.c revision 39297
161981Sbrian/*
261981Sbrian * Copyright (c) 1993, 1994, 1995, 1996
361981Sbrian *	The Regents of the University of California.  All rights reserved.
461981Sbrian *
561981Sbrian * Redistribution and use in source and binary forms, with or without
661981Sbrian * modification, are permitted provided that: (1) source code distributions
761981Sbrian * retain the above copyright notice and this paragraph in its entirety, (2)
861981Sbrian * distributions including binary code include the above copyright notice and
961981Sbrian * this paragraph in its entirety in the documentation or other materials
1061981Sbrian * provided with the distribution, and (3) all advertising materials mentioning
1161981Sbrian * features or use of this software display the following acknowledgement:
1261981Sbrian * ``This product includes software developed by the University of California,
13140771Skeramida * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14140771Skeramida * the University nor the names of its contributors may be used to endorse
15140771Skeramida * or promote products derived from this software without specific prior
1661981Sbrian * written permission.
1761981Sbrian * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1861981Sbrian * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1961981Sbrian * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2061981Sbrian */
2161981Sbrian
2261981Sbrian#ifndef lint
23170085Sdougbstatic const char rcsid[] =
2461981Sbrian    "@(#) $Header: print-wb.c,v 1.24 96/12/31 21:27:44 leres Exp $ (LBL)";
2561981Sbrian#endif
2661981Sbrian
2761981Sbrian#include <sys/types.h>
2865843Sbrian#include <sys/time.h>
2965843Sbrian
3065843Sbrian#include <netinet/in.h>
3165843Sbrian
3265843Sbrian#include <stdio.h>
3365843Sbrian
3465843Sbrian#include "interface.h"
3565843Sbrian#include "addrtoname.h"
3665843Sbrian
3765843Sbrian/* XXX need to add byte-swapping macros! */
3861981Sbrian
3961981Sbrian/*
4061981Sbrian * Largest packet size.  Everything should fit within this space.
4161981Sbrian * For instance, multiline objects are sent piecewise.
4261981Sbrian */
4361981Sbrian#define MAXFRAMESIZE 1024
4461981Sbrian
4561981Sbrian/*
4661981Sbrian * Multiple drawing ops can be sent in one packet.  Each one starts on a
4761981Sbrian * an even multiple of DOP_ALIGN bytes, which must be a power of two.
48174028Sjhb */
49205509Sjoerg#define DOP_ALIGN 4
50174028Sjhb#define DOP_ROUNDUP(x)	((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
5161981Sbrian#define DOP_NEXT(d)\
5261981Sbrian	((struct dophdr *)((u_char *)(d) + \
5361981Sbrian			  DOP_ROUNDUP(ntohs((d)->dh_len) + sizeof(*(d)))))
5461981Sbrian
5561981Sbrian/*
5661981Sbrian * Format of the whiteboard packet header.
5761981Sbrian * The transport level header.
5861981Sbrian */
5961981Sbrianstruct pkt_hdr {
6061981Sbrian	u_int32_t ph_src;		/* site id of source */
6161981Sbrian	u_int32_t ph_ts;		/* time stamp (for skew computation) */
6261981Sbrian	u_short ph_version;	/* version number */
6361981Sbrian	u_char ph_type;		/* message type */
6461981Sbrian	u_char ph_flags;	/* message flags */
6561981Sbrian};
6661981Sbrian
6761981Sbrian/* Packet types */
68108959Swollman#define PT_DRAWOP	0	/* drawing operation */
69108959Swollman#define PT_ID		1	/* announcement packet */
7061981Sbrian#define PT_RREQ		2	/* repair request */
7161981Sbrian#define PT_RREP		3	/* repair reply */
7261981Sbrian#define PT_KILL		4	/* terminate participation */
7361981Sbrian#define PT_PREQ         5       /* page vector request */
7461981Sbrian#define PT_PREP         7       /* page vector reply */
7561981Sbrian
7661981Sbrian/* flags */
7761981Sbrian#define PF_USER		0x01	/* hint that packet has interactive data */
7861981Sbrian#define PF_VIS		0x02	/* only visible ops wanted */
7961981Sbrian
8061981Sbrianstruct PageID {
8161981Sbrian	u_int32_t p_sid;		/* session id of initiator */
8262054Sbrian	u_int32_t p_uid;		/* page number */
8377496Sbrian};
8477492Sbrian
8561981Sbrianstruct dophdr {
8661981Sbrian	u_int32_t  dh_ts;		/* sender's timestamp */
8761981Sbrian	u_short	dh_len;		/* body length */
8861981Sbrian	u_char	dh_flags;
8961981Sbrian	u_char	dh_type;	/* body type */
9061981Sbrian	/* body follows */
91155060Smatteo};
9261981Sbrian/*
93168412Spjd * Drawing op sub-types.
94168412Spjd */
95168412Spjd#define DT_RECT         2
96121620Sjesper#define DT_LINE         3
97123498Sjesper#define DT_ML           4
98121620Sjesper#define DT_DEL          5
99154304Swollman#define DT_XFORM        6
100154304Swollman#define DT_ELL          7
101154304Swollman#define DT_CHAR         8
102156216Sbrueffer#define DT_STR          9
103156216Sbrueffer#define DT_NOP          10
104156216Sbrueffer#define DT_PSCODE       11
105156216Sbrueffer#define DT_PSCOMP       12
106156216Sbrueffer#define DT_REF          13
107156216Sbrueffer#define DT_SKIP         14
108156216Sbrueffer#define DT_HOLE         15
109156216Sbrueffer#define DT_MAXTYPE      15
110156216Sbrueffer
11161981Sbrian/*
11261981Sbrian * A drawing operation.
11361981Sbrian */
11461981Sbrianstruct pkt_dop {
11561981Sbrian	struct PageID pd_page;	/* page that operations apply to */
11661981Sbrian	u_int32_t	pd_sseq;	/* start sequence number */
11761981Sbrian	u_int32_t	pd_eseq;	/* end sequence number */
11861981Sbrian	/* drawing ops follow */
11961981Sbrian};
12061981Sbrian
12194342Sgshapiro/*
12261981Sbrian * A repair request.
12361981Sbrian */
12461981Sbrianstruct pkt_rreq {
12587514Scjc        u_int32_t pr_id;           /* source id of drawops to be repaired */
12661981Sbrian        struct PageID pr_page;           /* page of drawops */
12761981Sbrian        u_int32_t pr_sseq;         /* start seqno */
12861981Sbrian        u_int32_t pr_eseq;         /* end seqno */
12962274Sbrian};
130175153Sdds
13161981Sbrian/*
13275809Sdirk * A repair reply.
13375809Sdirk */
13475809Sdirkstruct pkt_rrep {
13575809Sdirk	u_int32_t pr_id;	/* original site id of ops  */
136169517Smaxim	struct pkt_dop pr_dop;
137169517Smaxim	/* drawing ops follow */
138169517Smaxim};
13972677Speter
14072677Speterstruct id_off {
14194342Sgshapiro        u_int32_t id;
14272677Speter        u_int32_t off;
14361981Sbrian};
14461981Sbrian
14561981Sbrianstruct pgstate {
14661981Sbrian	u_int32_t slot;
14787514Scjc	struct PageID page;
14887514Scjc	u_short nid;
149101607Sfanf	u_short rsvd;
15087514Scjc        /* seqptr's */
15187514Scjc};
15287514Scjc
15387514Scjc/*
15487514Scjc * An announcement packet.
155135591Sjkoshy */
15687514Scjcstruct pkt_id {
15787514Scjc	u_int32_t pi_mslot;
15887514Scjc        struct PageID    pi_mpage;        /* current page */
15987514Scjc	struct pgstate pi_ps;
16087514Scjc        /* seqptr's */
16187514Scjc        /* null-terminated site name */
16287514Scjc};
16387514Scjc
16487514Scjcstruct pkt_preq {
16587514Scjc        struct PageID  pp_page;
16687514Scjc        u_int32_t  pp_low;
16787514Scjc        u_int32_t  pp_high;
16887514Scjc};
16987514Scjc
17087514Scjcstruct pkt_prep {
171161602Strhodes        u_int32_t  pp_n;           /* size of pageid array */
172161602Strhodes        /* pgstate's follow */
173161602Strhodes};
17487514Scjc
17587514Scjcstatic int
17687514Scjcwb_id(const struct pkt_id *id, u_int len)
177105937Sthomas{
178105937Sthomas	int i;
179105937Sthomas	const char *cp;
180138061Smlaier	const struct id_off *io;
181138061Smlaier	char c;
182138061Smlaier	int nid;
18387514Scjc
18487514Scjc	printf(" wb-id:");
18587514Scjc	if (len < sizeof(*id) || (u_char *)(id + 1) > snapend)
186128473Sdarrenr		return (-1);
187128473Sdarrenr	len -= sizeof(*id);
188128473Sdarrenr
18987514Scjc	printf(" %u/%s:%u (max %u/%s:%u) ",
19087514Scjc	       (u_int32_t)ntohl(id->pi_ps.slot),
19187514Scjc	       ipaddr_string(&id->pi_ps.page.p_sid),
19287514Scjc	       (u_int32_t)ntohl(id->pi_ps.page.p_uid),
19387514Scjc	       (u_int32_t)ntohl(id->pi_mslot),
19487514Scjc	       ipaddr_string(&id->pi_mpage.p_sid),
19587514Scjc	       (u_int32_t)ntohl(id->pi_mpage.p_uid));
19687514Scjc
19787514Scjc	nid = ntohs(id->pi_ps.nid);
19887514Scjc	len -= sizeof(*io) * nid;
19961981Sbrian	io = (struct id_off *)(id + 1);
20061981Sbrian	cp = (char *)(io + nid);
20165843Sbrian	if ((u_char *)cp + len <= snapend) {
20265843Sbrian		putchar('"');
20365843Sbrian		(void)fn_print((u_char *)cp, (u_char *)cp + len);
20465843Sbrian		putchar('"');
20565843Sbrian	}
20665843Sbrian
20765843Sbrian	c = '<';
20865843Sbrian	for (i = 0; i < nid && (u_char *)io < snapend; ++io, ++i) {
20965843Sbrian		printf("%c%s:%u",
21065843Sbrian		    c, ipaddr_string(&io->id), (u_int32_t)ntohl(io->off));
21161981Sbrian		c = ',';
21261981Sbrian	}
21361981Sbrian	if (i >= nid) {
21461981Sbrian		printf(">");
21561981Sbrian		return (0);
21661981Sbrian	}
21761981Sbrian	return (-1);
21861981Sbrian}
21961981Sbrian
22061981Sbrianstatic int
22161981Sbrianwb_rreq(const struct pkt_rreq *rreq, u_int len)
22261981Sbrian{
22361981Sbrian	printf(" wb-rreq:");
22462206Sbrian	if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > snapend)
22562155Sbrian		return (-1);
226103948Sbrian
227196442Skensmith	printf(" please repair %s %s:%u<%u:%u>",
22862155Sbrian	       ipaddr_string(&rreq->pr_id),
22961981Sbrian	       ipaddr_string(&rreq->pr_page.p_sid),
23061981Sbrian	       (u_int32_t)ntohl(rreq->pr_page.p_uid),
23161981Sbrian	       (u_int32_t)ntohl(rreq->pr_sseq),
23261981Sbrian	       (u_int32_t)ntohl(rreq->pr_eseq));
23361981Sbrian	return (0);
23461981Sbrian}
23565843Sbrian
23665843Sbrianstatic int
23765843Sbrianwb_preq(const struct pkt_preq *preq, u_int len)
23865843Sbrian{
23965843Sbrian	printf(" wb-preq:");
24065843Sbrian	if (len < sizeof(*preq) || (u_char *)(preq + 1) > snapend)
24165843Sbrian		return (-1);
24265843Sbrian
24365843Sbrian	printf(" need %u/%s:%u",
24465843Sbrian	       (u_int32_t)ntohl(preq->pp_low),
24561981Sbrian	       ipaddr_string(&preq->pp_page.p_sid),
24661981Sbrian	       (u_int32_t)ntohl(preq->pp_page.p_uid));
24761981Sbrian	return (0);
24861981Sbrian}
24961981Sbrian
25061981Sbrianstatic int
25161981Sbrianwb_prep(const struct pkt_prep *prep, u_int len)
25261981Sbrian{
25361981Sbrian	int n;
25461981Sbrian	const struct pgstate *ps;
25561981Sbrian	const u_char *ep = snapend;
25661981Sbrian
25761981Sbrian	printf(" wb-prep:");
25861981Sbrian	if (len < sizeof(*prep)) {
25961981Sbrian		return (-1);
26061981Sbrian	}
26161981Sbrian	n = ntohl(prep->pp_n);
26261981Sbrian	ps = (const struct pgstate *)(prep + 1);
26361981Sbrian	while (--n >= 0 && (u_char *)ps < ep) {
26461981Sbrian		const struct id_off *io, *ie;
26561981Sbrian		char c = '<';
26661981Sbrian
26761981Sbrian		printf(" %u/%s:%u",
26861981Sbrian		    (u_int32_t)ntohl(ps->slot),
26961981Sbrian		    ipaddr_string(&ps->page.p_sid),
27061981Sbrian		    (u_int32_t)ntohl(ps->page.p_uid));
27161981Sbrian		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
284char *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
303static int
304wb_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
335static int
336wb_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
358static int
359wb_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 */
381void
382wb_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