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
23127668Sbmsstatic const char rcsid[] _U_ =
24190207Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-wb.c,v 1.33 2004-03-24 04:06:28 guy Exp $ (LBL)";
2517680Spst#endif
2617680Spst
2756893Sfenner#ifdef HAVE_CONFIG_H
2856893Sfenner#include "config.h"
2956893Sfenner#endif
3056893Sfenner
31127668Sbms#include <tcpdump-stdinc.h>
3217680Spst
3317680Spst#include <stdio.h>
3417680Spst
3517680Spst#include "interface.h"
3617680Spst#include "addrtoname.h"
37127668Sbms#include "extract.h"
3817680Spst
3917680Spst/* XXX need to add byte-swapping macros! */
40127668Sbms/* XXX - you mean like the ones in "extract.h"? */
4117680Spst
4217680Spst/*
4317680Spst * Largest packet size.  Everything should fit within this space.
4417680Spst * For instance, multiline objects are sent piecewise.
4517680Spst */
4617680Spst#define MAXFRAMESIZE 1024
4717680Spst
4817680Spst/*
4917680Spst * Multiple drawing ops can be sent in one packet.  Each one starts on a
5017680Spst * an even multiple of DOP_ALIGN bytes, which must be a power of two.
5117680Spst */
5217680Spst#define DOP_ALIGN 4
5317680Spst#define DOP_ROUNDUP(x)	((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1))
5417680Spst#define DOP_NEXT(d)\
5526180Sfenner	((struct dophdr *)((u_char *)(d) + \
56127668Sbms			  DOP_ROUNDUP(EXTRACT_16BITS(&(d)->dh_len) + sizeof(*(d)))))
5717680Spst
5817680Spst/*
5917680Spst * Format of the whiteboard packet header.
6017680Spst * The transport level header.
6117680Spst */
6217680Spststruct pkt_hdr {
6317680Spst	u_int32_t ph_src;		/* site id of source */
6417680Spst	u_int32_t ph_ts;		/* time stamp (for skew computation) */
65127668Sbms	u_int16_t ph_version;	/* version number */
6617680Spst	u_char ph_type;		/* message type */
6717680Spst	u_char ph_flags;	/* message flags */
6817680Spst};
6917680Spst
7017680Spst/* Packet types */
7117680Spst#define PT_DRAWOP	0	/* drawing operation */
7217680Spst#define PT_ID		1	/* announcement packet */
7317680Spst#define PT_RREQ		2	/* repair request */
7417680Spst#define PT_RREP		3	/* repair reply */
7517680Spst#define PT_KILL		4	/* terminate participation */
7617680Spst#define PT_PREQ         5       /* page vector request */
7717680Spst#define PT_PREP         7       /* page vector reply */
7817680Spst
7998524Sfenner#ifdef PF_USER
8098524Sfenner#undef PF_USER			/* {Digital,Tru64} UNIX define this, alas */
8198524Sfenner#endif
8298524Sfenner
8317680Spst/* flags */
8417680Spst#define PF_USER		0x01	/* hint that packet has interactive data */
8517680Spst#define PF_VIS		0x02	/* only visible ops wanted */
8617680Spst
8717680Spststruct PageID {
8817680Spst	u_int32_t p_sid;		/* session id of initiator */
8917680Spst	u_int32_t p_uid;		/* page number */
9017680Spst};
9117680Spst
9217680Spststruct dophdr {
9317680Spst	u_int32_t  dh_ts;		/* sender's timestamp */
94127668Sbms	u_int16_t	dh_len;		/* body length */
9517680Spst	u_char	dh_flags;
9617680Spst	u_char	dh_type;	/* body type */
9717680Spst	/* body follows */
9817680Spst};
9917680Spst/*
10017680Spst * Drawing op sub-types.
10117680Spst */
10217680Spst#define DT_RECT         2
10317680Spst#define DT_LINE         3
10417680Spst#define DT_ML           4
10517680Spst#define DT_DEL          5
10617680Spst#define DT_XFORM        6
10717680Spst#define DT_ELL          7
10817680Spst#define DT_CHAR         8
10917680Spst#define DT_STR          9
11017680Spst#define DT_NOP          10
11117680Spst#define DT_PSCODE       11
11217680Spst#define DT_PSCOMP       12
11317680Spst#define DT_REF          13
11417680Spst#define DT_SKIP         14
11517680Spst#define DT_HOLE         15
11617680Spst#define DT_MAXTYPE      15
11717680Spst
11817680Spst/*
11917680Spst * A drawing operation.
12017680Spst */
12117680Spststruct pkt_dop {
12217680Spst	struct PageID pd_page;	/* page that operations apply to */
12317680Spst	u_int32_t	pd_sseq;	/* start sequence number */
12417680Spst	u_int32_t	pd_eseq;	/* end sequence number */
12517680Spst	/* drawing ops follow */
12617680Spst};
12717680Spst
12817680Spst/*
12917680Spst * A repair request.
13017680Spst */
13117680Spststruct pkt_rreq {
13217680Spst        u_int32_t pr_id;           /* source id of drawops to be repaired */
13317680Spst        struct PageID pr_page;           /* page of drawops */
13417680Spst        u_int32_t pr_sseq;         /* start seqno */
13526180Sfenner        u_int32_t pr_eseq;         /* end seqno */
13617680Spst};
13717680Spst
13817680Spst/*
13917680Spst * A repair reply.
14017680Spst */
14117680Spststruct pkt_rrep {
14217680Spst	u_int32_t pr_id;	/* original site id of ops  */
14317680Spst	struct pkt_dop pr_dop;
14417680Spst	/* drawing ops follow */
14517680Spst};
14617680Spst
14717680Spststruct id_off {
14817680Spst        u_int32_t id;
14917680Spst        u_int32_t off;
15017680Spst};
15117680Spst
15217680Spststruct pgstate {
15317680Spst	u_int32_t slot;
15417680Spst	struct PageID page;
155127668Sbms	u_int16_t nid;
156127668Sbms	u_int16_t rsvd;
15717680Spst        /* seqptr's */
15817680Spst};
15917680Spst
16017680Spst/*
16117680Spst * An announcement packet.
16217680Spst */
16317680Spststruct pkt_id {
16417680Spst	u_int32_t pi_mslot;
16517680Spst        struct PageID    pi_mpage;        /* current page */
16617680Spst	struct pgstate pi_ps;
16717680Spst        /* seqptr's */
16817680Spst        /* null-terminated site name */
16917680Spst};
17017680Spst
17117680Spststruct pkt_preq {
17217680Spst        struct PageID  pp_page;
17317680Spst        u_int32_t  pp_low;
17417680Spst        u_int32_t  pp_high;
17517680Spst};
17617680Spst
17717680Spststruct pkt_prep {
17817680Spst        u_int32_t  pp_n;           /* size of pageid array */
17917680Spst        /* pgstate's follow */
18017680Spst};
18117680Spst
18217680Spststatic int
18317680Spstwb_id(const struct pkt_id *id, u_int len)
18417680Spst{
18517680Spst	int i;
18617680Spst	const char *cp;
18717680Spst	const struct id_off *io;
18817680Spst	char c;
18917680Spst	int nid;
19017680Spst
19117680Spst	printf(" wb-id:");
19239297Sfenner	if (len < sizeof(*id) || (u_char *)(id + 1) > snapend)
19339297Sfenner		return (-1);
19417680Spst	len -= sizeof(*id);
19517680Spst
19617680Spst	printf(" %u/%s:%u (max %u/%s:%u) ",
197127668Sbms	       EXTRACT_32BITS(&id->pi_ps.slot),
19817680Spst	       ipaddr_string(&id->pi_ps.page.p_sid),
199127668Sbms	       EXTRACT_32BITS(&id->pi_ps.page.p_uid),
200127668Sbms	       EXTRACT_32BITS(&id->pi_mslot),
20117680Spst	       ipaddr_string(&id->pi_mpage.p_sid),
202127668Sbms	       EXTRACT_32BITS(&id->pi_mpage.p_uid));
20317680Spst
204127668Sbms	nid = EXTRACT_16BITS(&id->pi_ps.nid);
20517680Spst	len -= sizeof(*io) * nid;
20617680Spst	io = (struct id_off *)(id + 1);
20717680Spst	cp = (char *)(io + nid);
20817680Spst	if ((u_char *)cp + len <= snapend) {
20917680Spst		putchar('"');
21017680Spst		(void)fn_print((u_char *)cp, (u_char *)cp + len);
21117680Spst		putchar('"');
21217680Spst	}
21317680Spst
21417680Spst	c = '<';
215127668Sbms	for (i = 0; i < nid && (u_char *)(io + 1) <= snapend; ++io, ++i) {
21617680Spst		printf("%c%s:%u",
217127668Sbms		    c, ipaddr_string(&io->id), EXTRACT_32BITS(&io->off));
21817680Spst		c = ',';
21917680Spst	}
22017680Spst	if (i >= nid) {
22117680Spst		printf(">");
22217680Spst		return (0);
22317680Spst	}
22417680Spst	return (-1);
22517680Spst}
22617680Spst
22717680Spststatic int
22817680Spstwb_rreq(const struct pkt_rreq *rreq, u_int len)
22917680Spst{
23017680Spst	printf(" wb-rreq:");
23117680Spst	if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > snapend)
23217680Spst		return (-1);
23317680Spst
23417680Spst	printf(" please repair %s %s:%u<%u:%u>",
23517680Spst	       ipaddr_string(&rreq->pr_id),
23617680Spst	       ipaddr_string(&rreq->pr_page.p_sid),
237127668Sbms	       EXTRACT_32BITS(&rreq->pr_page.p_uid),
238127668Sbms	       EXTRACT_32BITS(&rreq->pr_sseq),
239127668Sbms	       EXTRACT_32BITS(&rreq->pr_eseq));
24017680Spst	return (0);
24117680Spst}
24217680Spst
24317680Spststatic int
24417680Spstwb_preq(const struct pkt_preq *preq, u_int len)
24517680Spst{
24617680Spst	printf(" wb-preq:");
24717680Spst	if (len < sizeof(*preq) || (u_char *)(preq + 1) > snapend)
24817680Spst		return (-1);
24917680Spst
25017680Spst	printf(" need %u/%s:%u",
251127668Sbms	       EXTRACT_32BITS(&preq->pp_low),
25217680Spst	       ipaddr_string(&preq->pp_page.p_sid),
253127668Sbms	       EXTRACT_32BITS(&preq->pp_page.p_uid));
25417680Spst	return (0);
25517680Spst}
25617680Spst
25717680Spststatic int
25817680Spstwb_prep(const struct pkt_prep *prep, u_int len)
25917680Spst{
26017680Spst	int n;
26126180Sfenner	const struct pgstate *ps;
26226180Sfenner	const u_char *ep = snapend;
26317680Spst
26417680Spst	printf(" wb-prep:");
26517680Spst	if (len < sizeof(*prep)) {
26617680Spst		return (-1);
26717680Spst	}
268127668Sbms	n = EXTRACT_32BITS(&prep->pp_n);
26926180Sfenner	ps = (const struct pgstate *)(prep + 1);
270127668Sbms	while (--n >= 0 && (u_char *)(ps + 1) <= ep) {
27117680Spst		const struct id_off *io, *ie;
27217680Spst		char c = '<';
27317680Spst
27417680Spst		printf(" %u/%s:%u",
275127668Sbms		    EXTRACT_32BITS(&ps->slot),
27617680Spst		    ipaddr_string(&ps->page.p_sid),
277127668Sbms		    EXTRACT_32BITS(&ps->page.p_uid));
27826180Sfenner		io = (struct id_off *)(ps + 1);
279127668Sbms		for (ie = io + ps->nid; io < ie && (u_char *)(io + 1) <= ep; ++io) {
28017680Spst			printf("%c%s:%u", c, ipaddr_string(&io->id),
281127668Sbms			    EXTRACT_32BITS(&io->off));
28217680Spst			c = ',';
28317680Spst		}
28417680Spst		printf(">");
28526180Sfenner		ps = (struct pgstate *)io;
28617680Spst	}
28726180Sfenner	return ((u_char *)ps <= ep? 0 : -1);
28817680Spst}
28917680Spst
29017680Spst
291127668Sbmsconst char *dopstr[] = {
29217680Spst	"dop-0!",
29317680Spst	"dop-1!",
29417680Spst	"RECT",
29517680Spst	"LINE",
29617680Spst	"ML",
29717680Spst	"DEL",
29817680Spst	"XFORM",
29917680Spst	"ELL",
30017680Spst	"CHAR",
30117680Spst	"STR",
30217680Spst	"NOP",
30317680Spst	"PSCODE",
30417680Spst	"PSCOMP",
30517680Spst	"REF",
30617680Spst	"SKIP",
30717680Spst	"HOLE",
30817680Spst};
30917680Spst
31017680Spststatic int
31117680Spstwb_dops(const struct dophdr *dh, u_int32_t ss, u_int32_t es)
31217680Spst{
31317680Spst	printf(" <");
31417680Spst	for ( ; ss <= es; ++ss) {
31517680Spst		register int t = dh->dh_type;
31617680Spst
31717680Spst		if (t > DT_MAXTYPE)
31817680Spst			printf(" dop-%d!", t);
31917680Spst		else {
32017680Spst			printf(" %s", dopstr[t]);
32117680Spst			if (t == DT_SKIP || t == DT_HOLE) {
322127668Sbms				u_int32_t ts = EXTRACT_32BITS(&dh->dh_ts);
32317680Spst				printf("%d", ts - ss + 1);
32417680Spst				if (ss > ts || ts > es) {
32517680Spst					printf("[|]");
32617680Spst					if (ts < ss)
32717680Spst						return (0);
32817680Spst				}
32917680Spst				ss = ts;
33017680Spst			}
33117680Spst		}
33217680Spst		dh = DOP_NEXT(dh);
33326180Sfenner		if ((u_char *)dh > snapend) {
33417680Spst			printf("[|wb]");
33517680Spst			break;
33617680Spst		}
33717680Spst	}
33817680Spst	printf(" >");
33917680Spst	return (0);
34017680Spst}
34117680Spst
34217680Spststatic int
34317680Spstwb_rrep(const struct pkt_rrep *rrep, u_int len)
34417680Spst{
34517680Spst	const struct pkt_dop *dop = &rrep->pr_dop;
34617680Spst
34717680Spst	printf(" wb-rrep:");
34839297Sfenner	if (len < sizeof(*rrep) || (u_char *)(rrep + 1) > snapend)
34939297Sfenner		return (-1);
35017680Spst	len -= sizeof(*rrep);
35117680Spst
35217680Spst	printf(" for %s %s:%u<%u:%u>",
35317680Spst	    ipaddr_string(&rrep->pr_id),
35417680Spst	    ipaddr_string(&dop->pd_page.p_sid),
355127668Sbms	    EXTRACT_32BITS(&dop->pd_page.p_uid),
356127668Sbms	    EXTRACT_32BITS(&dop->pd_sseq),
357127668Sbms	    EXTRACT_32BITS(&dop->pd_eseq));
35817680Spst
35917680Spst	if (vflag)
36026180Sfenner		return (wb_dops((const struct dophdr *)(dop + 1),
361127668Sbms		    EXTRACT_32BITS(&dop->pd_sseq),
362127668Sbms		    EXTRACT_32BITS(&dop->pd_eseq)));
36317680Spst	return (0);
36417680Spst}
36517680Spst
36617680Spststatic int
36717680Spstwb_drawop(const struct pkt_dop *dop, u_int len)
36817680Spst{
36917680Spst	printf(" wb-dop:");
37039297Sfenner	if (len < sizeof(*dop) || (u_char *)(dop + 1) > snapend)
37139297Sfenner		return (-1);
37217680Spst	len -= sizeof(*dop);
37317680Spst
37417680Spst	printf(" %s:%u<%u:%u>",
37517680Spst	    ipaddr_string(&dop->pd_page.p_sid),
376127668Sbms	    EXTRACT_32BITS(&dop->pd_page.p_uid),
377127668Sbms	    EXTRACT_32BITS(&dop->pd_sseq),
378127668Sbms	    EXTRACT_32BITS(&dop->pd_eseq));
37917680Spst
38017680Spst	if (vflag)
38126180Sfenner		return (wb_dops((const struct dophdr *)(dop + 1),
382127668Sbms				EXTRACT_32BITS(&dop->pd_sseq),
383127668Sbms				EXTRACT_32BITS(&dop->pd_eseq)));
38417680Spst	return (0);
38517680Spst}
38617680Spst
38717680Spst/*
38817680Spst * Print whiteboard multicast packets.
38917680Spst */
39017680Spstvoid
39117680Spstwb_print(register const void *hdr, register u_int len)
39217680Spst{
39326180Sfenner	register const struct pkt_hdr *ph;
39417680Spst
39526180Sfenner	ph = (const struct pkt_hdr *)hdr;
39639297Sfenner	if (len < sizeof(*ph) || (u_char *)(ph + 1) > snapend) {
39739297Sfenner		printf("[|wb]");
39839297Sfenner		return;
39939297Sfenner	}
40017680Spst	len -= sizeof(*ph);
40117680Spst
40239297Sfenner	if (ph->ph_flags)
40339297Sfenner		printf("*");
40439297Sfenner	switch (ph->ph_type) {
40517680Spst
40639297Sfenner	case PT_KILL:
40739297Sfenner		printf(" wb-kill");
40839297Sfenner		return;
40917680Spst
41039297Sfenner	case PT_ID:
41139297Sfenner		if (wb_id((struct pkt_id *)(ph + 1), len) >= 0)
41239297Sfenner			return;
41339297Sfenner		break;
41417680Spst
41539297Sfenner	case PT_RREQ:
41639297Sfenner		if (wb_rreq((struct pkt_rreq *)(ph + 1), len) >= 0)
41739297Sfenner			return;
41839297Sfenner		break;
41917680Spst
42039297Sfenner	case PT_RREP:
42139297Sfenner		if (wb_rrep((struct pkt_rrep *)(ph + 1), len) >= 0)
42239297Sfenner			return;
42339297Sfenner		break;
42417680Spst
42539297Sfenner	case PT_DRAWOP:
42639297Sfenner		if (wb_drawop((struct pkt_dop *)(ph + 1), len) >= 0)
42739297Sfenner			return;
42839297Sfenner		break;
42917680Spst
43039297Sfenner	case PT_PREQ:
43139297Sfenner		if (wb_preq((struct pkt_preq *)(ph + 1), len) >= 0)
43239297Sfenner			return;
43339297Sfenner		break;
43417680Spst
43539297Sfenner	case PT_PREP:
43639297Sfenner		if (wb_prep((struct pkt_prep *)(ph + 1), len) >= 0)
43717680Spst			return;
43839297Sfenner		break;
43939297Sfenner
44039297Sfenner	default:
44139297Sfenner		printf(" wb-%d!", ph->ph_type);
44239297Sfenner		return;
44317680Spst	}
44417680Spst}
445