117680Spst/*
217680Spst * Copyright (c) 1991, 1992, 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 are permitted
617680Spst * provided that the above copyright notice and this paragraph are
717680Spst * duplicated in all such forms and that any documentation,
817680Spst * advertising materials, and other materials related to such
917680Spst * distribution and use acknowledge that the software was developed
1017680Spst * by the University of California, Lawrence Berkeley Laboratory,
1117680Spst * Berkeley, CA.  The name of the University may not be used to
1217680Spst * endorse or promote products derived from this software without
1317680Spst * specific prior written permission.
1417680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1517680Spst * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1617680Spst * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1717680Spst *
1817680Spst * Initial contribution from Jeff Honig (jch@MITCHELL.CIT.CORNELL.EDU).
1917680Spst */
2017680Spst
2117680Spst#ifndef lint
22127668Sbmsstatic const char rcsid[] _U_ =
23190207Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-egp.c,v 1.38 2006-02-11 22:13:24 hannes Exp $ (LBL)";
2417680Spst#endif
2517680Spst
2656893Sfenner#ifdef HAVE_CONFIG_H
2756893Sfenner#include "config.h"
2856893Sfenner#endif
2956893Sfenner
30127668Sbms#include <tcpdump-stdinc.h>
3117680Spst
3217680Spst#include <stdio.h>
3317680Spst
3417680Spst#include "interface.h"
3517680Spst#include "addrtoname.h"
36127668Sbms#include "extract.h"
3717680Spst
3875115Sfenner#include "ip.h"
3975115Sfenner
4017680Spststruct egp_packet {
41127668Sbms	u_int8_t  egp_version;
4217680Spst#define	EGP_VERSION	2
43127668Sbms	u_int8_t  egp_type;
4417680Spst#define  EGPT_ACQUIRE	3
4517680Spst#define  EGPT_REACH	5
4617680Spst#define  EGPT_POLL	2
4717680Spst#define  EGPT_UPDATE	1
4817680Spst#define  EGPT_ERROR	8
49127668Sbms	u_int8_t  egp_code;
5017680Spst#define  EGPC_REQUEST	0
5117680Spst#define  EGPC_CONFIRM	1
5217680Spst#define  EGPC_REFUSE	2
5317680Spst#define  EGPC_CEASE	3
5417680Spst#define  EGPC_CEASEACK	4
5517680Spst#define  EGPC_HELLO	0
5617680Spst#define  EGPC_HEARDU	1
57127668Sbms	u_int8_t  egp_status;
5817680Spst#define  EGPS_UNSPEC	0
5917680Spst#define  EGPS_ACTIVE	1
6017680Spst#define  EGPS_PASSIVE	2
6117680Spst#define  EGPS_NORES	3
6217680Spst#define  EGPS_ADMIN	4
6317680Spst#define  EGPS_GODOWN	5
6417680Spst#define  EGPS_PARAM	6
6517680Spst#define  EGPS_PROTO	7
6617680Spst#define  EGPS_INDET	0
6717680Spst#define  EGPS_UP	1
6817680Spst#define  EGPS_DOWN	2
6917680Spst#define  EGPS_UNSOL	0x80
70127668Sbms	u_int16_t  egp_checksum;
71127668Sbms	u_int16_t  egp_as;
72127668Sbms	u_int16_t  egp_sequence;
7317680Spst	union {
74127668Sbms		u_int16_t  egpu_hello;
75127668Sbms		u_int8_t egpu_gws[2];
76127668Sbms		u_int16_t  egpu_reason;
7717680Spst#define  EGPR_UNSPEC	0
7817680Spst#define  EGPR_BADHEAD	1
7917680Spst#define  EGPR_BADDATA	2
8017680Spst#define  EGPR_NOREACH	3
8117680Spst#define  EGPR_XSPOLL	4
8217680Spst#define  EGPR_NORESP	5
8317680Spst#define  EGPR_UVERSION	6
8417680Spst	} egp_handg;
8517680Spst#define  egp_hello  egp_handg.egpu_hello
8617680Spst#define  egp_intgw  egp_handg.egpu_gws[0]
8717680Spst#define  egp_extgw  egp_handg.egpu_gws[1]
8817680Spst#define  egp_reason  egp_handg.egpu_reason
8917680Spst	union {
90127668Sbms		u_int16_t  egpu_poll;
9117680Spst		u_int32_t egpu_sourcenet;
9217680Spst	} egp_pands;
9317680Spst#define  egp_poll  egp_pands.egpu_poll
9417680Spst#define  egp_sourcenet  egp_pands.egpu_sourcenet
9517680Spst};
9617680Spst
9798524Sfennerconst char *egp_acquire_codes[] = {
9817680Spst	"request",
9917680Spst	"confirm",
10017680Spst	"refuse",
10117680Spst	"cease",
10217680Spst	"cease_ack"
10317680Spst};
10417680Spst
10598524Sfennerconst char *egp_acquire_status[] = {
10617680Spst	"unspecified",
10717680Spst	"active_mode",
10817680Spst	"passive_mode",
10917680Spst	"insufficient_resources",
11017680Spst	"administratively_prohibited",
11117680Spst	"going_down",
11217680Spst	"parameter_violation",
11317680Spst	"protocol_violation"
11417680Spst};
11517680Spst
11698524Sfennerconst char *egp_reach_codes[] = {
11717680Spst	"hello",
11817680Spst	"i-h-u"
11917680Spst};
12017680Spst
12198524Sfennerconst char *egp_status_updown[] = {
12217680Spst	"indeterminate",
12317680Spst	"up",
12417680Spst	"down"
12517680Spst};
12617680Spst
12798524Sfennerconst char *egp_reasons[] = {
12817680Spst	"unspecified",
12917680Spst	"bad_EGP_header_format",
13017680Spst	"bad_EGP_data_field_format",
13117680Spst	"reachability_info_unavailable",
13217680Spst	"excessive_polling_rate",
13317680Spst	"no_response",
13417680Spst	"unsupported_version"
13517680Spst};
13617680Spst
13717680Spststatic void
138127668Sbmsegpnrprint(register const struct egp_packet *egp)
13917680Spst{
140127668Sbms	register const u_int8_t *cp;
14117680Spst	u_int32_t addr;
14217680Spst	register u_int32_t net;
14317680Spst	register u_int netlen;
14417680Spst	int gateways, distances, networks;
14517680Spst	int t_gateways;
146127668Sbms	const char *comma;
14717680Spst
14817680Spst	addr = egp->egp_sourcenet;
14917680Spst	if (IN_CLASSA(addr)) {
15017680Spst		net = addr & IN_CLASSA_NET;
15117680Spst		netlen = 1;
15217680Spst	} else if (IN_CLASSB(addr)) {
15317680Spst		net = addr & IN_CLASSB_NET;
15417680Spst		netlen = 2;
15517680Spst	} else if (IN_CLASSC(addr)) {
15617680Spst		net = addr & IN_CLASSC_NET;
15717680Spst		netlen = 3;
15817680Spst	} else {
15917680Spst		net = 0;
16017680Spst		netlen = 0;
16117680Spst	}
162127668Sbms	cp = (u_int8_t *)(egp + 1);
16317680Spst
16417680Spst	t_gateways = egp->egp_intgw + egp->egp_extgw;
16517680Spst	for (gateways = 0; gateways < t_gateways; ++gateways) {
16617680Spst		/* Pickup host part of gateway address */
16717680Spst		addr = 0;
16817680Spst		TCHECK2(cp[0], 4 - netlen);
16917680Spst		switch (netlen) {
17017680Spst
17117680Spst		case 1:
17217680Spst			addr = *cp++;
17317680Spst			/* fall through */
17417680Spst		case 2:
17517680Spst			addr = (addr << 8) | *cp++;
17617680Spst			/* fall through */
17717680Spst		case 3:
17817680Spst			addr = (addr << 8) | *cp++;
17917680Spst		}
18017680Spst		addr |= net;
18117680Spst		TCHECK2(cp[0], 1);
18217680Spst		distances = *cp++;
18317680Spst		printf(" %s %s ",
18426180Sfenner		       gateways < (int)egp->egp_intgw ? "int" : "ext",
18517680Spst		       ipaddr_string(&addr));
18617680Spst
18717680Spst		comma = "";
18817680Spst		putchar('(');
18917680Spst		while (--distances >= 0) {
19017680Spst			TCHECK2(cp[0], 2);
19117680Spst			printf("%sd%d:", comma, (int)*cp++);
19217680Spst			comma = ", ";
19317680Spst			networks = *cp++;
19417680Spst			while (--networks >= 0) {
19517680Spst				/* Pickup network number */
19617680Spst				TCHECK2(cp[0], 1);
19717680Spst				addr = (u_int32_t)*cp++ << 24;
19817680Spst				if (IN_CLASSB(addr)) {
19917680Spst					TCHECK2(cp[0], 1);
20017680Spst					addr |= (u_int32_t)*cp++ << 16;
20117680Spst				} else if (!IN_CLASSA(addr)) {
20217680Spst					TCHECK2(cp[0], 2);
20317680Spst					addr |= (u_int32_t)*cp++ << 16;
20417680Spst					addr |= (u_int32_t)*cp++ << 8;
20517680Spst				}
20617680Spst				printf(" %s", ipaddr_string(&addr));
20717680Spst			}
20817680Spst		}
20917680Spst		putchar(')');
21017680Spst	}
21117680Spst	return;
21217680Spsttrunc:
21317680Spst	fputs("[|]", stdout);
21417680Spst}
21517680Spst
21617680Spstvoid
217146773Ssamegp_print(register const u_int8_t *bp, register u_int length)
21817680Spst{
21917680Spst	register const struct egp_packet *egp;
22017680Spst	register int status;
22117680Spst	register int code;
22217680Spst	register int type;
22317680Spst
22417680Spst	egp = (struct egp_packet *)bp;
225146773Ssam        if (!TTEST2(*egp, length)) {
226127668Sbms		printf("[|egp]");
227127668Sbms		return;
228127668Sbms	}
22917680Spst
230190207Srpaulo        if (!vflag) {
231190207Srpaulo            printf("EGPv%u, AS %u, seq %u, length %u",
232190207Srpaulo                   egp->egp_version,
233190207Srpaulo                   EXTRACT_16BITS(&egp->egp_as),
234190207Srpaulo                   EXTRACT_16BITS(&egp->egp_sequence),
235190207Srpaulo                   length);
236190207Srpaulo            return;
237190207Srpaulo        } else
238190207Srpaulo            printf("EGPv%u, length %u",
239190207Srpaulo                   egp->egp_version,
240190207Srpaulo                   length);
241190207Srpaulo
24217680Spst	if (egp->egp_version != EGP_VERSION) {
24317680Spst		printf("[version %d]", egp->egp_version);
24417680Spst		return;
24517680Spst	}
24617680Spst
24717680Spst	type = egp->egp_type;
24817680Spst	code = egp->egp_code;
24917680Spst	status = egp->egp_status;
25017680Spst
25117680Spst	switch (type) {
25217680Spst	case EGPT_ACQUIRE:
25317680Spst		printf(" acquire");
25417680Spst		switch (code) {
25517680Spst		case EGPC_REQUEST:
25617680Spst		case EGPC_CONFIRM:
25717680Spst			printf(" %s", egp_acquire_codes[code]);
25817680Spst			switch (status) {
25917680Spst			case EGPS_UNSPEC:
26017680Spst			case EGPS_ACTIVE:
26117680Spst			case EGPS_PASSIVE:
26217680Spst				printf(" %s", egp_acquire_status[status]);
26317680Spst				break;
26417680Spst
26517680Spst			default:
26617680Spst				printf(" [status %d]", status);
26717680Spst				break;
26817680Spst			}
26917680Spst			printf(" hello:%d poll:%d",
270127668Sbms			       EXTRACT_16BITS(&egp->egp_hello),
271127668Sbms			       EXTRACT_16BITS(&egp->egp_poll));
27217680Spst			break;
27317680Spst
27417680Spst		case EGPC_REFUSE:
27517680Spst		case EGPC_CEASE:
27617680Spst		case EGPC_CEASEACK:
27717680Spst			printf(" %s", egp_acquire_codes[code]);
27817680Spst			switch (status ) {
27917680Spst			case EGPS_UNSPEC:
28017680Spst			case EGPS_NORES:
28117680Spst			case EGPS_ADMIN:
28217680Spst			case EGPS_GODOWN:
28317680Spst			case EGPS_PARAM:
28417680Spst			case EGPS_PROTO:
28517680Spst				printf(" %s", egp_acquire_status[status]);
28617680Spst				break;
28717680Spst
28817680Spst			default:
28917680Spst				printf("[status %d]", status);
29017680Spst				break;
29117680Spst			}
29217680Spst			break;
29317680Spst
29417680Spst		default:
29517680Spst			printf("[code %d]", code);
29617680Spst			break;
29717680Spst		}
29817680Spst		break;
29917680Spst
30017680Spst	case EGPT_REACH:
30117680Spst		switch (code) {
30217680Spst
30317680Spst		case EGPC_HELLO:
30417680Spst		case EGPC_HEARDU:
30517680Spst			printf(" %s", egp_reach_codes[code]);
30617680Spst			if (status <= EGPS_DOWN)
30717680Spst				printf(" state:%s", egp_status_updown[status]);
30817680Spst			else
30917680Spst				printf(" [status %d]", status);
31017680Spst			break;
31117680Spst
31217680Spst		default:
31317680Spst			printf("[reach code %d]", code);
31417680Spst			break;
31517680Spst		}
31617680Spst		break;
31717680Spst
31817680Spst	case EGPT_POLL:
31917680Spst		printf(" poll");
32017680Spst		if (egp->egp_status <= EGPS_DOWN)
32117680Spst			printf(" state:%s", egp_status_updown[status]);
32217680Spst		else
32317680Spst			printf(" [status %d]", status);
32417680Spst		printf(" net:%s", ipaddr_string(&egp->egp_sourcenet));
32517680Spst		break;
32617680Spst
32717680Spst	case EGPT_UPDATE:
32817680Spst		printf(" update");
32917680Spst		if (status & EGPS_UNSOL) {
33017680Spst			status &= ~EGPS_UNSOL;
33117680Spst			printf(" unsolicited");
33217680Spst		}
33317680Spst		if (status <= EGPS_DOWN)
33417680Spst			printf(" state:%s", egp_status_updown[status]);
33517680Spst		else
33617680Spst			printf(" [status %d]", status);
33717680Spst		printf(" %s int %d ext %d",
33817680Spst		       ipaddr_string(&egp->egp_sourcenet),
33917680Spst		       egp->egp_intgw,
34017680Spst		       egp->egp_extgw);
34117680Spst		if (vflag)
342127668Sbms			egpnrprint(egp);
34317680Spst		break;
34417680Spst
34517680Spst	case EGPT_ERROR:
34617680Spst		printf(" error");
34717680Spst		if (status <= EGPS_DOWN)
34817680Spst			printf(" state:%s", egp_status_updown[status]);
34917680Spst		else
35017680Spst			printf(" [status %d]", status);
35117680Spst
352127668Sbms		if (EXTRACT_16BITS(&egp->egp_reason) <= EGPR_UVERSION)
353127668Sbms			printf(" %s", egp_reasons[EXTRACT_16BITS(&egp->egp_reason)]);
35417680Spst		else
355127668Sbms			printf(" [reason %d]", EXTRACT_16BITS(&egp->egp_reason));
35617680Spst		break;
35717680Spst
35817680Spst	default:
35917680Spst		printf("[type %d]", type);
36017680Spst		break;
36117680Spst	}
36217680Spst}
363