print-wb.c revision 26180
117680Spst/*
217680Spst * Copyright (c) 1993, 1994, 1995, 1996
317680Spst *	The Regents of the University of California.  All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that: (1) source code distributions
717680Spst * retain the above copyright notice and this paragraph in its entirety, (2)
817680Spst * distributions including binary code include the above copyright notice and
917680Spst * this paragraph in its entirety in the documentation or other materials
1017680Spst * provided with the distribution, and (3) all advertising materials mentioning
1117680Spst * features or use of this software display the following acknowledgement:
1217680Spst * ``This product includes software developed by the University of California,
1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1417680Spst * the University nor the names of its contributors may be used to endorse
1517680Spst * or promote products derived from this software without specific prior
1617680Spst * written permission.
1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2017680Spst */
2117680Spst
2217680Spst#ifndef lint
2326180Sfennerstatic const char rcsid[] =
2426180Sfenner    "@(#) $Header: print-wb.c,v 1.23 96/12/10 23:21:43 leres Exp $ (LBL)";
2517680Spst#endif
2617680Spst
2717680Spst#include <sys/types.h>
2817680Spst#include <sys/time.h>
2917680Spst
3017680Spst#include <netinet/in.h>
3117680Spst
3217680Spst#include <stdio.h>
3317680Spst
3417680Spst#include "interface.h"
3517680Spst#include "addrtoname.h"
3617680Spst
3717680Spst/* XXX need to add byte-swapping macros! */
3817680Spst
3917680Spst/*
4017680Spst * Largest packet size.  Everything should fit within this space.
4117680Spst * For instance, multiline objects are sent piecewise.
4217680Spst */
4317680Spst#define MAXFRAMESIZE 1024
4417680Spst
4517680Spst/*
4617680Spst * Multiple drawing ops can be sent in one packet.  Each one starts on a
4717680Spst * an even multiple of DOP_ALIGN bytes, which must be a power of two.
4817680Spst */
4917680Spst#define DOP_ALIGN 4
5017680Spst#define DOP_ROUNDUP(x)	((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
5117680Spst#define DOP_NEXT(d)\
5226180Sfenner	((struct dophdr *)((u_char *)(d) + \
5317680Spst			  DOP_ROUNDUP(ntohs((d)->dh_len) + sizeof(*(d)))))
5417680Spst
5517680Spst/*
5617680Spst * Format of the whiteboard packet header.
5717680Spst * The transport level header.
5817680Spst */
5917680Spststruct pkt_hdr {
6017680Spst	u_int32_t ph_src;		/* site id of source */
6117680Spst	u_int32_t ph_ts;		/* time stamp (for skew computation) */
6217680Spst	u_short ph_version;	/* version number */
6317680Spst	u_char ph_type;		/* message type */
6417680Spst	u_char ph_flags;	/* message flags */
6517680Spst};
6617680Spst
6717680Spst/* Packet types */
6817680Spst#define PT_DRAWOP	0	/* drawing operation */
6917680Spst#define PT_ID		1	/* announcement packet */
7017680Spst#define PT_RREQ		2	/* repair request */
7117680Spst#define PT_RREP		3	/* repair reply */
7217680Spst#define PT_KILL		4	/* terminate participation */
7317680Spst#define PT_PREQ         5       /* page vector request */
7417680Spst#define PT_PREP         7       /* page vector reply */
7517680Spst
7617680Spst/* flags */
7717680Spst#define PF_USER		0x01	/* hint that packet has interactive data */
7817680Spst#define PF_VIS		0x02	/* only visible ops wanted */
7917680Spst
8017680Spststruct PageID {
8117680Spst	u_int32_t p_sid;		/* session id of initiator */
8217680Spst	u_int32_t p_uid;		/* page number */
8317680Spst};
8417680Spst
8517680Spststruct dophdr {
8617680Spst	u_int32_t  dh_ts;		/* sender's timestamp */
8717680Spst	u_short	dh_len;		/* body length */
8817680Spst	u_char	dh_flags;
8917680Spst	u_char	dh_type;	/* body type */
9017680Spst	/* body follows */
9117680Spst};
9217680Spst/*
9317680Spst * Drawing op sub-types.
9417680Spst */
9517680Spst#define DT_RECT         2
9617680Spst#define DT_LINE         3
9717680Spst#define DT_ML           4
9817680Spst#define DT_DEL          5
9917680Spst#define DT_XFORM        6
10017680Spst#define DT_ELL          7
10117680Spst#define DT_CHAR         8
10217680Spst#define DT_STR          9
10317680Spst#define DT_NOP          10
10417680Spst#define DT_PSCODE       11
10517680Spst#define DT_PSCOMP       12
10617680Spst#define DT_REF          13
10717680Spst#define DT_SKIP         14
10817680Spst#define DT_HOLE         15
10917680Spst#define DT_MAXTYPE      15
11017680Spst
11117680Spst/*
11217680Spst * A drawing operation.
11317680Spst */
11417680Spststruct pkt_dop {
11517680Spst	struct PageID pd_page;	/* page that operations apply to */
11617680Spst	u_int32_t	pd_sseq;	/* start sequence number */
11717680Spst	u_int32_t	pd_eseq;	/* end sequence number */
11817680Spst	/* drawing ops follow */
11917680Spst};
12017680Spst
12117680Spst/*
12217680Spst * A repair request.
12317680Spst */
12417680Spststruct pkt_rreq {
12517680Spst        u_int32_t pr_id;           /* source id of drawops to be repaired */
12617680Spst        struct PageID pr_page;           /* page of drawops */
12717680Spst        u_int32_t pr_sseq;         /* start seqno */
12826180Sfenner        u_int32_t pr_eseq;         /* end seqno */
12917680Spst};
13017680Spst
13117680Spst/*
13217680Spst * A repair reply.
13317680Spst */
13417680Spststruct pkt_rrep {
13517680Spst	u_int32_t pr_id;	/* original site id of ops  */
13617680Spst	struct pkt_dop pr_dop;
13717680Spst	/* drawing ops follow */
13817680Spst};
13917680Spst
14017680Spststruct id_off {
14117680Spst        u_int32_t id;
14217680Spst        u_int32_t off;
14317680Spst};
14417680Spst
14517680Spststruct pgstate {
14617680Spst	u_int32_t slot;
14717680Spst	struct PageID page;
14817680Spst	u_short nid;
14917680Spst	u_short rsvd;
15017680Spst        /* seqptr's */
15117680Spst};
15217680Spst
15317680Spst/*
15417680Spst * An announcement packet.
15517680Spst */
15617680Spststruct pkt_id {
15717680Spst	u_int32_t pi_mslot;
15817680Spst        struct PageID    pi_mpage;        /* current page */
15917680Spst	struct pgstate pi_ps;
16017680Spst        /* seqptr's */
16117680Spst        /* null-terminated site name */
16217680Spst};
16317680Spst
16417680Spststruct pkt_preq {
16517680Spst        struct PageID  pp_page;
16617680Spst        u_int32_t  pp_low;
16717680Spst        u_int32_t  pp_high;
16817680Spst};
16917680Spst
17017680Spststruct pkt_prep {
17117680Spst        u_int32_t  pp_n;           /* size of pageid array */
17217680Spst        /* pgstate's follow */
17317680Spst};
17417680Spst
17517680Spststatic int
17617680Spstwb_id(const struct pkt_id *id, u_int len)
17717680Spst{
17817680Spst	int i;
17917680Spst	const char *cp;
18017680Spst	const struct id_off *io;
18117680Spst	char c;
18217680Spst	int nid;
18317680Spst
18417680Spst	printf(" wb-id:");
18517680Spst	len -= sizeof(*id);
18617680Spst	if (len < 0 || (u_char *)(id + 1) > snapend)
18717680Spst		return (-1);
18817680Spst
18917680Spst	printf(" %u/%s:%u (max %u/%s:%u) ",
19017680Spst	       (u_int32_t)ntohl(id->pi_ps.slot),
19117680Spst	       ipaddr_string(&id->pi_ps.page.p_sid),
19217680Spst	       (u_int32_t)ntohl(id->pi_ps.page.p_uid),
19317680Spst	       (u_int32_t)ntohl(id->pi_mslot),
19417680Spst	       ipaddr_string(&id->pi_mpage.p_sid),
19517680Spst	       (u_int32_t)ntohl(id->pi_mpage.p_uid));
19617680Spst
19717680Spst	nid = ntohs(id->pi_ps.nid);
19817680Spst	len -= sizeof(*io) * nid;
19917680Spst	io = (struct id_off *)(id + 1);
20017680Spst	cp = (char *)(io + nid);
20117680Spst	if ((u_char *)cp + len <= snapend) {
20217680Spst		putchar('"');
20317680Spst		(void)fn_print((u_char *)cp, (u_char *)cp + len);
20417680Spst		putchar('"');
20517680Spst	}
20617680Spst
20717680Spst	c = '<';
20826180Sfenner	for (i = 0; i < nid && (u_char *)io < snapend; ++io, ++i) {
20917680Spst		printf("%c%s:%u",
21017680Spst		    c, ipaddr_string(&io->id), (u_int32_t)ntohl(io->off));
21117680Spst		c = ',';
21217680Spst	}
21317680Spst	if (i >= nid) {
21417680Spst		printf(">");
21517680Spst		return (0);
21617680Spst	}
21717680Spst	return (-1);
21817680Spst}
21917680Spst
22017680Spststatic int
22117680Spstwb_rreq(const struct pkt_rreq *rreq, u_int len)
22217680Spst{
22317680Spst	printf(" wb-rreq:");
22417680Spst	if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > snapend)
22517680Spst		return (-1);
22617680Spst
22717680Spst	printf(" please repair %s %s:%u<%u:%u>",
22817680Spst	       ipaddr_string(&rreq->pr_id),
22917680Spst	       ipaddr_string(&rreq->pr_page.p_sid),
23017680Spst	       (u_int32_t)ntohl(rreq->pr_page.p_uid),
23117680Spst	       (u_int32_t)ntohl(rreq->pr_sseq),
23217680Spst	       (u_int32_t)ntohl(rreq->pr_eseq));
23317680Spst	return (0);
23417680Spst}
23517680Spst
23617680Spststatic int
23717680Spstwb_preq(const struct pkt_preq *preq, u_int len)
23817680Spst{
23917680Spst	printf(" wb-preq:");
24017680Spst	if (len < sizeof(*preq) || (u_char *)(preq + 1) > snapend)
24117680Spst		return (-1);
24217680Spst
24317680Spst	printf(" need %u/%s:%u",
24417680Spst	       (u_int32_t)ntohl(preq->pp_low),
24517680Spst	       ipaddr_string(&preq->pp_page.p_sid),
24617680Spst	       (u_int32_t)ntohl(preq->pp_page.p_uid));
24717680Spst	return (0);
24817680Spst}
24917680Spst
25017680Spststatic int
25117680Spstwb_prep(const struct pkt_prep *prep, u_int len)
25217680Spst{
25317680Spst	int n;
25426180Sfenner	const struct pgstate *ps;
25526180Sfenner	const u_char *ep = snapend;
25617680Spst
25717680Spst	printf(" wb-prep:");
25817680Spst	if (len < sizeof(*prep)) {
25917680Spst		return (-1);
26017680Spst	}
26117680Spst	n = ntohl(prep->pp_n);
26226180Sfenner	ps = (const struct pgstate *)(prep + 1);
26326180Sfenner	while (--n >= 0 && (u_char *)ps < ep) {
26417680Spst		const struct id_off *io, *ie;
26517680Spst		char c = '<';
26617680Spst
26717680Spst		printf(" %u/%s:%u",
26817680Spst		    (u_int32_t)ntohl(ps->slot),
26917680Spst		    ipaddr_string(&ps->page.p_sid),
27017680Spst		    (u_int32_t)ntohl(ps->page.p_uid));
27126180Sfenner		io = (struct id_off *)(ps + 1);
27226180Sfenner		for (ie = io + ps->nid; io < ie && (u_char *)io < ep; ++io) {
27317680Spst			printf("%c%s:%u", c, ipaddr_string(&io->id),
27417680Spst			    (u_int32_t)ntohl(io->off));
27517680Spst			c = ',';
27617680Spst		}
27717680Spst		printf(">");
27826180Sfenner		ps = (struct pgstate *)io;
27917680Spst	}
28026180Sfenner	return ((u_char *)ps <= ep? 0 : -1);
28117680Spst}
28217680Spst
28317680Spst
28417680Spstchar *dopstr[] = {
28517680Spst	"dop-0!",
28617680Spst	"dop-1!",
28717680Spst	"RECT",
28817680Spst	"LINE",
28917680Spst	"ML",
29017680Spst	"DEL",
29117680Spst	"XFORM",
29217680Spst	"ELL",
29317680Spst	"CHAR",
29417680Spst	"STR",
29517680Spst	"NOP",
29617680Spst	"PSCODE",
29717680Spst	"PSCOMP",
29817680Spst	"REF",
29917680Spst	"SKIP",
30017680Spst	"HOLE",
30117680Spst};
30217680Spst
30317680Spststatic int
30417680Spstwb_dops(const struct dophdr *dh, u_int32_t ss, u_int32_t es)
30517680Spst{
30617680Spst	printf(" <");
30717680Spst	for ( ; ss <= es; ++ss) {
30817680Spst		register int t = dh->dh_type;
30917680Spst
31017680Spst		if (t > DT_MAXTYPE)
31117680Spst			printf(" dop-%d!", t);
31217680Spst		else {
31317680Spst			printf(" %s", dopstr[t]);
31417680Spst			if (t == DT_SKIP || t == DT_HOLE) {
31517680Spst				int ts = ntohl(dh->dh_ts);
31617680Spst				printf("%d", ts - ss + 1);
31717680Spst				if (ss > ts || ts > es) {
31817680Spst					printf("[|]");
31917680Spst					if (ts < ss)
32017680Spst						return (0);
32117680Spst				}
32217680Spst				ss = ts;
32317680Spst			}
32417680Spst		}
32517680Spst		dh = DOP_NEXT(dh);
32626180Sfenner		if ((u_char *)dh > snapend) {
32717680Spst			printf("[|wb]");
32817680Spst			break;
32917680Spst		}
33017680Spst	}
33117680Spst	printf(" >");
33217680Spst	return (0);
33317680Spst}
33417680Spst
33517680Spststatic int
33617680Spstwb_rrep(const struct pkt_rrep *rrep, u_int len)
33717680Spst{
33817680Spst	const struct pkt_dop *dop = &rrep->pr_dop;
33917680Spst
34017680Spst	printf(" wb-rrep:");
34117680Spst	len -= sizeof(*rrep);
34217680Spst	if (len < 0 || (u_char *)(rrep + 1) > snapend)
34317680Spst		return (-1);
34417680Spst
34517680Spst	printf(" for %s %s:%u<%u:%u>",
34617680Spst	    ipaddr_string(&rrep->pr_id),
34717680Spst	    ipaddr_string(&dop->pd_page.p_sid),
34817680Spst	    (u_int32_t)ntohl(dop->pd_page.p_uid),
34917680Spst	    (u_int32_t)ntohl(dop->pd_sseq),
35017680Spst	    (u_int32_t)ntohl(dop->pd_eseq));
35117680Spst
35217680Spst	if (vflag)
35326180Sfenner		return (wb_dops((const struct dophdr *)(dop + 1),
35417680Spst		    ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
35517680Spst	return (0);
35617680Spst}
35717680Spst
35817680Spststatic int
35917680Spstwb_drawop(const struct pkt_dop *dop, u_int len)
36017680Spst{
36117680Spst	printf(" wb-dop:");
36217680Spst	len -= sizeof(*dop);
36317680Spst	if (len < 0 || (u_char *)(dop + 1) > snapend)
36417680Spst		return (-1);
36517680Spst
36617680Spst	printf(" %s:%u<%u:%u>",
36717680Spst	    ipaddr_string(&dop->pd_page.p_sid),
36817680Spst	    (u_int32_t)ntohl(dop->pd_page.p_uid),
36917680Spst	    (u_int32_t)ntohl(dop->pd_sseq),
37017680Spst	    (u_int32_t)ntohl(dop->pd_eseq));
37117680Spst
37217680Spst	if (vflag)
37326180Sfenner		return (wb_dops((const struct dophdr *)(dop + 1),
37417680Spst				ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
37517680Spst	return (0);
37617680Spst}
37717680Spst
37817680Spst/*
37917680Spst * Print whiteboard multicast packets.
38017680Spst */
38117680Spstvoid
38217680Spstwb_print(register const void *hdr, register u_int len)
38317680Spst{
38426180Sfenner	register const struct pkt_hdr *ph;
38517680Spst
38626180Sfenner	ph = (const struct pkt_hdr *)hdr;
38717680Spst	len -= sizeof(*ph);
38817680Spst	if (len < 0 || (u_char *)(ph + 1) <= snapend) {
38917680Spst		if (ph->ph_flags)
39017680Spst			printf("*");
39117680Spst		switch (ph->ph_type) {
39217680Spst
39317680Spst		case PT_KILL:
39417680Spst			printf(" wb-kill");
39517680Spst			return;
39617680Spst
39717680Spst		case PT_ID:
39817680Spst			if (wb_id((struct pkt_id *)(ph + 1), len) >= 0)
39917680Spst				return;
40017680Spst			break;
40117680Spst
40217680Spst		case PT_RREQ:
40317680Spst			if (wb_rreq((struct pkt_rreq *)(ph + 1), len) >= 0)
40417680Spst				return;
40517680Spst			break;
40617680Spst
40717680Spst		case PT_RREP:
40817680Spst			if (wb_rrep((struct pkt_rrep *)(ph + 1), len) >= 0)
40917680Spst				return;
41017680Spst			break;
41117680Spst
41217680Spst		case PT_DRAWOP:
41317680Spst			if (wb_drawop((struct pkt_dop *)(ph + 1), len) >= 0)
41417680Spst				return;
41517680Spst			break;
41617680Spst
41717680Spst		case PT_PREQ:
41817680Spst			if (wb_preq((struct pkt_preq *)(ph + 1), len) >= 0)
41917680Spst				return;
42017680Spst			break;
42117680Spst
42217680Spst		case PT_PREP:
42317680Spst			if (wb_prep((struct pkt_prep *)(ph + 1), len) >= 0)
42417680Spst				return;
42517680Spst			break;
42617680Spst
42717680Spst		default:
42817680Spst			printf(" wb-%d!", ph->ph_type);
42917680Spst			return;
43017680Spst		}
43117680Spst	}
43217680Spst	printf("[|wb]");
43317680Spst}
434