print-wb.c revision 56893
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[] =
2456893Sfenner    "@(#) $Header: /tcpdump/master/tcpdump/print-wb.c,v 1.25 1999/11/21 09:37:03 fenner Exp $ (LBL)";
2517680Spst#endif
2617680Spst
2756893Sfenner#ifdef HAVE_CONFIG_H
2856893Sfenner#include "config.h"
2956893Sfenner#endif
3056893Sfenner
3117680Spst#include <sys/types.h>
3217680Spst#include <sys/time.h>
3317680Spst
3417680Spst#include <netinet/in.h>
3517680Spst
3617680Spst#include <stdio.h>
3717680Spst
3817680Spst#include "interface.h"
3917680Spst#include "addrtoname.h"
4017680Spst
4117680Spst/* XXX need to add byte-swapping macros! */
4217680Spst
4317680Spst/*
4417680Spst * Largest packet size.  Everything should fit within this space.
4517680Spst * For instance, multiline objects are sent piecewise.
4617680Spst */
4717680Spst#define MAXFRAMESIZE 1024
4817680Spst
4917680Spst/*
5017680Spst * Multiple drawing ops can be sent in one packet.  Each one starts on a
5117680Spst * an even multiple of DOP_ALIGN bytes, which must be a power of two.
5217680Spst */
5317680Spst#define DOP_ALIGN 4
5417680Spst#define DOP_ROUNDUP(x)	((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
5517680Spst#define DOP_NEXT(d)\
5626180Sfenner	((struct dophdr *)((u_char *)(d) + \
5717680Spst			  DOP_ROUNDUP(ntohs((d)->dh_len) + sizeof(*(d)))))
5817680Spst
5917680Spst/*
6017680Spst * Format of the whiteboard packet header.
6117680Spst * The transport level header.
6217680Spst */
6317680Spststruct pkt_hdr {
6417680Spst	u_int32_t ph_src;		/* site id of source */
6517680Spst	u_int32_t ph_ts;		/* time stamp (for skew computation) */
6617680Spst	u_short ph_version;	/* version number */
6717680Spst	u_char ph_type;		/* message type */
6817680Spst	u_char ph_flags;	/* message flags */
6917680Spst};
7017680Spst
7117680Spst/* Packet types */
7217680Spst#define PT_DRAWOP	0	/* drawing operation */
7317680Spst#define PT_ID		1	/* announcement packet */
7417680Spst#define PT_RREQ		2	/* repair request */
7517680Spst#define PT_RREP		3	/* repair reply */
7617680Spst#define PT_KILL		4	/* terminate participation */
7717680Spst#define PT_PREQ         5       /* page vector request */
7817680Spst#define PT_PREP         7       /* page vector reply */
7917680Spst
8017680Spst/* flags */
8117680Spst#define PF_USER		0x01	/* hint that packet has interactive data */
8217680Spst#define PF_VIS		0x02	/* only visible ops wanted */
8317680Spst
8417680Spststruct PageID {
8517680Spst	u_int32_t p_sid;		/* session id of initiator */
8617680Spst	u_int32_t p_uid;		/* page number */
8717680Spst};
8817680Spst
8917680Spststruct dophdr {
9017680Spst	u_int32_t  dh_ts;		/* sender's timestamp */
9117680Spst	u_short	dh_len;		/* body length */
9217680Spst	u_char	dh_flags;
9317680Spst	u_char	dh_type;	/* body type */
9417680Spst	/* body follows */
9517680Spst};
9617680Spst/*
9717680Spst * Drawing op sub-types.
9817680Spst */
9917680Spst#define DT_RECT         2
10017680Spst#define DT_LINE         3
10117680Spst#define DT_ML           4
10217680Spst#define DT_DEL          5
10317680Spst#define DT_XFORM        6
10417680Spst#define DT_ELL          7
10517680Spst#define DT_CHAR         8
10617680Spst#define DT_STR          9
10717680Spst#define DT_NOP          10
10817680Spst#define DT_PSCODE       11
10917680Spst#define DT_PSCOMP       12
11017680Spst#define DT_REF          13
11117680Spst#define DT_SKIP         14
11217680Spst#define DT_HOLE         15
11317680Spst#define DT_MAXTYPE      15
11417680Spst
11517680Spst/*
11617680Spst * A drawing operation.
11717680Spst */
11817680Spststruct pkt_dop {
11917680Spst	struct PageID pd_page;	/* page that operations apply to */
12017680Spst	u_int32_t	pd_sseq;	/* start sequence number */
12117680Spst	u_int32_t	pd_eseq;	/* end sequence number */
12217680Spst	/* drawing ops follow */
12317680Spst};
12417680Spst
12517680Spst/*
12617680Spst * A repair request.
12717680Spst */
12817680Spststruct pkt_rreq {
12917680Spst        u_int32_t pr_id;           /* source id of drawops to be repaired */
13017680Spst        struct PageID pr_page;           /* page of drawops */
13117680Spst        u_int32_t pr_sseq;         /* start seqno */
13226180Sfenner        u_int32_t pr_eseq;         /* end seqno */
13317680Spst};
13417680Spst
13517680Spst/*
13617680Spst * A repair reply.
13717680Spst */
13817680Spststruct pkt_rrep {
13917680Spst	u_int32_t pr_id;	/* original site id of ops  */
14017680Spst	struct pkt_dop pr_dop;
14117680Spst	/* drawing ops follow */
14217680Spst};
14317680Spst
14417680Spststruct id_off {
14517680Spst        u_int32_t id;
14617680Spst        u_int32_t off;
14717680Spst};
14817680Spst
14917680Spststruct pgstate {
15017680Spst	u_int32_t slot;
15117680Spst	struct PageID page;
15217680Spst	u_short nid;
15317680Spst	u_short rsvd;
15417680Spst        /* seqptr's */
15517680Spst};
15617680Spst
15717680Spst/*
15817680Spst * An announcement packet.
15917680Spst */
16017680Spststruct pkt_id {
16117680Spst	u_int32_t pi_mslot;
16217680Spst        struct PageID    pi_mpage;        /* current page */
16317680Spst	struct pgstate pi_ps;
16417680Spst        /* seqptr's */
16517680Spst        /* null-terminated site name */
16617680Spst};
16717680Spst
16817680Spststruct pkt_preq {
16917680Spst        struct PageID  pp_page;
17017680Spst        u_int32_t  pp_low;
17117680Spst        u_int32_t  pp_high;
17217680Spst};
17317680Spst
17417680Spststruct pkt_prep {
17517680Spst        u_int32_t  pp_n;           /* size of pageid array */
17617680Spst        /* pgstate's follow */
17717680Spst};
17817680Spst
17917680Spststatic int
18017680Spstwb_id(const struct pkt_id *id, u_int len)
18117680Spst{
18217680Spst	int i;
18317680Spst	const char *cp;
18417680Spst	const struct id_off *io;
18517680Spst	char c;
18617680Spst	int nid;
18717680Spst
18817680Spst	printf(" wb-id:");
18939297Sfenner	if (len < sizeof(*id) || (u_char *)(id + 1) > snapend)
19039297Sfenner		return (-1);
19117680Spst	len -= sizeof(*id);
19217680Spst
19317680Spst	printf(" %u/%s:%u (max %u/%s:%u) ",
19417680Spst	       (u_int32_t)ntohl(id->pi_ps.slot),
19517680Spst	       ipaddr_string(&id->pi_ps.page.p_sid),
19617680Spst	       (u_int32_t)ntohl(id->pi_ps.page.p_uid),
19717680Spst	       (u_int32_t)ntohl(id->pi_mslot),
19817680Spst	       ipaddr_string(&id->pi_mpage.p_sid),
19917680Spst	       (u_int32_t)ntohl(id->pi_mpage.p_uid));
20017680Spst
20117680Spst	nid = ntohs(id->pi_ps.nid);
20217680Spst	len -= sizeof(*io) * nid;
20317680Spst	io = (struct id_off *)(id + 1);
20417680Spst	cp = (char *)(io + nid);
20517680Spst	if ((u_char *)cp + len <= snapend) {
20617680Spst		putchar('"');
20717680Spst		(void)fn_print((u_char *)cp, (u_char *)cp + len);
20817680Spst		putchar('"');
20917680Spst	}
21017680Spst
21117680Spst	c = '<';
21226180Sfenner	for (i = 0; i < nid && (u_char *)io < snapend; ++io, ++i) {
21317680Spst		printf("%c%s:%u",
21417680Spst		    c, ipaddr_string(&io->id), (u_int32_t)ntohl(io->off));
21517680Spst		c = ',';
21617680Spst	}
21717680Spst	if (i >= nid) {
21817680Spst		printf(">");
21917680Spst		return (0);
22017680Spst	}
22117680Spst	return (-1);
22217680Spst}
22317680Spst
22417680Spststatic int
22517680Spstwb_rreq(const struct pkt_rreq *rreq, u_int len)
22617680Spst{
22717680Spst	printf(" wb-rreq:");
22817680Spst	if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > snapend)
22917680Spst		return (-1);
23017680Spst
23117680Spst	printf(" please repair %s %s:%u<%u:%u>",
23217680Spst	       ipaddr_string(&rreq->pr_id),
23317680Spst	       ipaddr_string(&rreq->pr_page.p_sid),
23417680Spst	       (u_int32_t)ntohl(rreq->pr_page.p_uid),
23517680Spst	       (u_int32_t)ntohl(rreq->pr_sseq),
23617680Spst	       (u_int32_t)ntohl(rreq->pr_eseq));
23717680Spst	return (0);
23817680Spst}
23917680Spst
24017680Spststatic int
24117680Spstwb_preq(const struct pkt_preq *preq, u_int len)
24217680Spst{
24317680Spst	printf(" wb-preq:");
24417680Spst	if (len < sizeof(*preq) || (u_char *)(preq + 1) > snapend)
24517680Spst		return (-1);
24617680Spst
24717680Spst	printf(" need %u/%s:%u",
24817680Spst	       (u_int32_t)ntohl(preq->pp_low),
24917680Spst	       ipaddr_string(&preq->pp_page.p_sid),
25017680Spst	       (u_int32_t)ntohl(preq->pp_page.p_uid));
25117680Spst	return (0);
25217680Spst}
25317680Spst
25417680Spststatic int
25517680Spstwb_prep(const struct pkt_prep *prep, u_int len)
25617680Spst{
25717680Spst	int n;
25826180Sfenner	const struct pgstate *ps;
25926180Sfenner	const u_char *ep = snapend;
26017680Spst
26117680Spst	printf(" wb-prep:");
26217680Spst	if (len < sizeof(*prep)) {
26317680Spst		return (-1);
26417680Spst	}
26517680Spst	n = ntohl(prep->pp_n);
26626180Sfenner	ps = (const struct pgstate *)(prep + 1);
26726180Sfenner	while (--n >= 0 && (u_char *)ps < ep) {
26817680Spst		const struct id_off *io, *ie;
26917680Spst		char c = '<';
27017680Spst
27117680Spst		printf(" %u/%s:%u",
27217680Spst		    (u_int32_t)ntohl(ps->slot),
27317680Spst		    ipaddr_string(&ps->page.p_sid),
27417680Spst		    (u_int32_t)ntohl(ps->page.p_uid));
27526180Sfenner		io = (struct id_off *)(ps + 1);
27626180Sfenner		for (ie = io + ps->nid; io < ie && (u_char *)io < ep; ++io) {
27717680Spst			printf("%c%s:%u", c, ipaddr_string(&io->id),
27817680Spst			    (u_int32_t)ntohl(io->off));
27917680Spst			c = ',';
28017680Spst		}
28117680Spst		printf(">");
28226180Sfenner		ps = (struct pgstate *)io;
28317680Spst	}
28426180Sfenner	return ((u_char *)ps <= ep? 0 : -1);
28517680Spst}
28617680Spst
28717680Spst
28817680Spstchar *dopstr[] = {
28917680Spst	"dop-0!",
29017680Spst	"dop-1!",
29117680Spst	"RECT",
29217680Spst	"LINE",
29317680Spst	"ML",
29417680Spst	"DEL",
29517680Spst	"XFORM",
29617680Spst	"ELL",
29717680Spst	"CHAR",
29817680Spst	"STR",
29917680Spst	"NOP",
30017680Spst	"PSCODE",
30117680Spst	"PSCOMP",
30217680Spst	"REF",
30317680Spst	"SKIP",
30417680Spst	"HOLE",
30517680Spst};
30617680Spst
30717680Spststatic int
30817680Spstwb_dops(const struct dophdr *dh, u_int32_t ss, u_int32_t es)
30917680Spst{
31017680Spst	printf(" <");
31117680Spst	for ( ; ss <= es; ++ss) {
31217680Spst		register int t = dh->dh_type;
31317680Spst
31417680Spst		if (t > DT_MAXTYPE)
31517680Spst			printf(" dop-%d!", t);
31617680Spst		else {
31717680Spst			printf(" %s", dopstr[t]);
31817680Spst			if (t == DT_SKIP || t == DT_HOLE) {
31917680Spst				int ts = ntohl(dh->dh_ts);
32017680Spst				printf("%d", ts - ss + 1);
32117680Spst				if (ss > ts || ts > es) {
32217680Spst					printf("[|]");
32317680Spst					if (ts < ss)
32417680Spst						return (0);
32517680Spst				}
32617680Spst				ss = ts;
32717680Spst			}
32817680Spst		}
32917680Spst		dh = DOP_NEXT(dh);
33026180Sfenner		if ((u_char *)dh > snapend) {
33117680Spst			printf("[|wb]");
33217680Spst			break;
33317680Spst		}
33417680Spst	}
33517680Spst	printf(" >");
33617680Spst	return (0);
33717680Spst}
33817680Spst
33917680Spststatic int
34017680Spstwb_rrep(const struct pkt_rrep *rrep, u_int len)
34117680Spst{
34217680Spst	const struct pkt_dop *dop = &rrep->pr_dop;
34317680Spst
34417680Spst	printf(" wb-rrep:");
34539297Sfenner	if (len < sizeof(*rrep) || (u_char *)(rrep + 1) > snapend)
34639297Sfenner		return (-1);
34717680Spst	len -= sizeof(*rrep);
34817680Spst
34917680Spst	printf(" for %s %s:%u<%u:%u>",
35017680Spst	    ipaddr_string(&rrep->pr_id),
35117680Spst	    ipaddr_string(&dop->pd_page.p_sid),
35217680Spst	    (u_int32_t)ntohl(dop->pd_page.p_uid),
35317680Spst	    (u_int32_t)ntohl(dop->pd_sseq),
35417680Spst	    (u_int32_t)ntohl(dop->pd_eseq));
35517680Spst
35617680Spst	if (vflag)
35726180Sfenner		return (wb_dops((const struct dophdr *)(dop + 1),
35817680Spst		    ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
35917680Spst	return (0);
36017680Spst}
36117680Spst
36217680Spststatic int
36317680Spstwb_drawop(const struct pkt_dop *dop, u_int len)
36417680Spst{
36517680Spst	printf(" wb-dop:");
36639297Sfenner	if (len < sizeof(*dop) || (u_char *)(dop + 1) > snapend)
36739297Sfenner		return (-1);
36817680Spst	len -= sizeof(*dop);
36917680Spst
37017680Spst	printf(" %s:%u<%u:%u>",
37117680Spst	    ipaddr_string(&dop->pd_page.p_sid),
37217680Spst	    (u_int32_t)ntohl(dop->pd_page.p_uid),
37317680Spst	    (u_int32_t)ntohl(dop->pd_sseq),
37417680Spst	    (u_int32_t)ntohl(dop->pd_eseq));
37517680Spst
37617680Spst	if (vflag)
37726180Sfenner		return (wb_dops((const struct dophdr *)(dop + 1),
37817680Spst				ntohl(dop->pd_sseq), ntohl(dop->pd_eseq)));
37917680Spst	return (0);
38017680Spst}
38117680Spst
38217680Spst/*
38317680Spst * Print whiteboard multicast packets.
38417680Spst */
38517680Spstvoid
38617680Spstwb_print(register const void *hdr, register u_int len)
38717680Spst{
38826180Sfenner	register const struct pkt_hdr *ph;
38917680Spst
39026180Sfenner	ph = (const struct pkt_hdr *)hdr;
39139297Sfenner	if (len < sizeof(*ph) || (u_char *)(ph + 1) > snapend) {
39239297Sfenner		printf("[|wb]");
39339297Sfenner		return;
39439297Sfenner	}
39517680Spst	len -= sizeof(*ph);
39617680Spst
39739297Sfenner	if (ph->ph_flags)
39839297Sfenner		printf("*");
39939297Sfenner	switch (ph->ph_type) {
40017680Spst
40139297Sfenner	case PT_KILL:
40239297Sfenner		printf(" wb-kill");
40339297Sfenner		return;
40417680Spst
40539297Sfenner	case PT_ID:
40639297Sfenner		if (wb_id((struct pkt_id *)(ph + 1), len) >= 0)
40739297Sfenner			return;
40839297Sfenner		break;
40917680Spst
41039297Sfenner	case PT_RREQ:
41139297Sfenner		if (wb_rreq((struct pkt_rreq *)(ph + 1), len) >= 0)
41239297Sfenner			return;
41339297Sfenner		break;
41417680Spst
41539297Sfenner	case PT_RREP:
41639297Sfenner		if (wb_rrep((struct pkt_rrep *)(ph + 1), len) >= 0)
41739297Sfenner			return;
41839297Sfenner		break;
41917680Spst
42039297Sfenner	case PT_DRAWOP:
42139297Sfenner		if (wb_drawop((struct pkt_dop *)(ph + 1), len) >= 0)
42239297Sfenner			return;
42339297Sfenner		break;
42417680Spst
42539297Sfenner	case PT_PREQ:
42639297Sfenner		if (wb_preq((struct pkt_preq *)(ph + 1), len) >= 0)
42739297Sfenner			return;
42839297Sfenner		break;
42917680Spst
43039297Sfenner	case PT_PREP:
43139297Sfenner		if (wb_prep((struct pkt_prep *)(ph + 1), len) >= 0)
43217680Spst			return;
43339297Sfenner		break;
43439297Sfenner
43539297Sfenner	default:
43639297Sfenner		printf(" wb-%d!", ph->ph_type);
43739297Sfenner		return;
43817680Spst	}
43917680Spst}
440