xref: /freebsd/contrib/tcpdump/print-egp.c (revision 7bd6fde3)
1 /*
2  * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Lawrence Berkeley Laboratory,
11  * Berkeley, CA.  The name of the University may not be used to
12  * endorse or promote products derived from this software without
13  * specific prior written permission.
14  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * Initial contribution from Jeff Honig (jch@MITCHELL.CIT.CORNELL.EDU).
19  */
20 
21 #ifndef lint
22 static const char rcsid[] _U_ =
23     "@(#) $Header: /tcpdump/master/tcpdump/print-egp.c,v 1.37 2005/01/12 11:19:09 hannes Exp $ (LBL)";
24 #endif
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include <tcpdump-stdinc.h>
31 
32 #include <stdio.h>
33 
34 #include "interface.h"
35 #include "addrtoname.h"
36 #include "extract.h"
37 
38 #include "ip.h"
39 
40 struct egp_packet {
41 	u_int8_t  egp_version;
42 #define	EGP_VERSION	2
43 	u_int8_t  egp_type;
44 #define  EGPT_ACQUIRE	3
45 #define  EGPT_REACH	5
46 #define  EGPT_POLL	2
47 #define  EGPT_UPDATE	1
48 #define  EGPT_ERROR	8
49 	u_int8_t  egp_code;
50 #define  EGPC_REQUEST	0
51 #define  EGPC_CONFIRM	1
52 #define  EGPC_REFUSE	2
53 #define  EGPC_CEASE	3
54 #define  EGPC_CEASEACK	4
55 #define  EGPC_HELLO	0
56 #define  EGPC_HEARDU	1
57 	u_int8_t  egp_status;
58 #define  EGPS_UNSPEC	0
59 #define  EGPS_ACTIVE	1
60 #define  EGPS_PASSIVE	2
61 #define  EGPS_NORES	3
62 #define  EGPS_ADMIN	4
63 #define  EGPS_GODOWN	5
64 #define  EGPS_PARAM	6
65 #define  EGPS_PROTO	7
66 #define  EGPS_INDET	0
67 #define  EGPS_UP	1
68 #define  EGPS_DOWN	2
69 #define  EGPS_UNSOL	0x80
70 	u_int16_t  egp_checksum;
71 	u_int16_t  egp_as;
72 	u_int16_t  egp_sequence;
73 	union {
74 		u_int16_t  egpu_hello;
75 		u_int8_t egpu_gws[2];
76 		u_int16_t  egpu_reason;
77 #define  EGPR_UNSPEC	0
78 #define  EGPR_BADHEAD	1
79 #define  EGPR_BADDATA	2
80 #define  EGPR_NOREACH	3
81 #define  EGPR_XSPOLL	4
82 #define  EGPR_NORESP	5
83 #define  EGPR_UVERSION	6
84 	} egp_handg;
85 #define  egp_hello  egp_handg.egpu_hello
86 #define  egp_intgw  egp_handg.egpu_gws[0]
87 #define  egp_extgw  egp_handg.egpu_gws[1]
88 #define  egp_reason  egp_handg.egpu_reason
89 	union {
90 		u_int16_t  egpu_poll;
91 		u_int32_t egpu_sourcenet;
92 	} egp_pands;
93 #define  egp_poll  egp_pands.egpu_poll
94 #define  egp_sourcenet  egp_pands.egpu_sourcenet
95 };
96 
97 const char *egp_acquire_codes[] = {
98 	"request",
99 	"confirm",
100 	"refuse",
101 	"cease",
102 	"cease_ack"
103 };
104 
105 const char *egp_acquire_status[] = {
106 	"unspecified",
107 	"active_mode",
108 	"passive_mode",
109 	"insufficient_resources",
110 	"administratively_prohibited",
111 	"going_down",
112 	"parameter_violation",
113 	"protocol_violation"
114 };
115 
116 const char *egp_reach_codes[] = {
117 	"hello",
118 	"i-h-u"
119 };
120 
121 const char *egp_status_updown[] = {
122 	"indeterminate",
123 	"up",
124 	"down"
125 };
126 
127 const char *egp_reasons[] = {
128 	"unspecified",
129 	"bad_EGP_header_format",
130 	"bad_EGP_data_field_format",
131 	"reachability_info_unavailable",
132 	"excessive_polling_rate",
133 	"no_response",
134 	"unsupported_version"
135 };
136 
137 static void
138 egpnrprint(register const struct egp_packet *egp)
139 {
140 	register const u_int8_t *cp;
141 	u_int32_t addr;
142 	register u_int32_t net;
143 	register u_int netlen;
144 	int gateways, distances, networks;
145 	int t_gateways;
146 	const char *comma;
147 
148 	addr = egp->egp_sourcenet;
149 	if (IN_CLASSA(addr)) {
150 		net = addr & IN_CLASSA_NET;
151 		netlen = 1;
152 	} else if (IN_CLASSB(addr)) {
153 		net = addr & IN_CLASSB_NET;
154 		netlen = 2;
155 	} else if (IN_CLASSC(addr)) {
156 		net = addr & IN_CLASSC_NET;
157 		netlen = 3;
158 	} else {
159 		net = 0;
160 		netlen = 0;
161 	}
162 	cp = (u_int8_t *)(egp + 1);
163 
164 	t_gateways = egp->egp_intgw + egp->egp_extgw;
165 	for (gateways = 0; gateways < t_gateways; ++gateways) {
166 		/* Pickup host part of gateway address */
167 		addr = 0;
168 		TCHECK2(cp[0], 4 - netlen);
169 		switch (netlen) {
170 
171 		case 1:
172 			addr = *cp++;
173 			/* fall through */
174 		case 2:
175 			addr = (addr << 8) | *cp++;
176 			/* fall through */
177 		case 3:
178 			addr = (addr << 8) | *cp++;
179 		}
180 		addr |= net;
181 		TCHECK2(cp[0], 1);
182 		distances = *cp++;
183 		printf(" %s %s ",
184 		       gateways < (int)egp->egp_intgw ? "int" : "ext",
185 		       ipaddr_string(&addr));
186 
187 		comma = "";
188 		putchar('(');
189 		while (--distances >= 0) {
190 			TCHECK2(cp[0], 2);
191 			printf("%sd%d:", comma, (int)*cp++);
192 			comma = ", ";
193 			networks = *cp++;
194 			while (--networks >= 0) {
195 				/* Pickup network number */
196 				TCHECK2(cp[0], 1);
197 				addr = (u_int32_t)*cp++ << 24;
198 				if (IN_CLASSB(addr)) {
199 					TCHECK2(cp[0], 1);
200 					addr |= (u_int32_t)*cp++ << 16;
201 				} else if (!IN_CLASSA(addr)) {
202 					TCHECK2(cp[0], 2);
203 					addr |= (u_int32_t)*cp++ << 16;
204 					addr |= (u_int32_t)*cp++ << 8;
205 				}
206 				printf(" %s", ipaddr_string(&addr));
207 			}
208 		}
209 		putchar(')');
210 	}
211 	return;
212 trunc:
213 	fputs("[|]", stdout);
214 }
215 
216 void
217 egp_print(register const u_int8_t *bp, register u_int length)
218 {
219 	register const struct egp_packet *egp;
220 	register int status;
221 	register int code;
222 	register int type;
223 
224 	egp = (struct egp_packet *)bp;
225         if (!TTEST2(*egp, length)) {
226 		printf("[|egp]");
227 		return;
228 	}
229 	(void)printf("egp: ");
230 
231 	if (egp->egp_version != EGP_VERSION) {
232 		printf("[version %d]", egp->egp_version);
233 		return;
234 	}
235 	printf("as:%d seq:%d", EXTRACT_16BITS(&egp->egp_as), EXTRACT_16BITS(&egp->egp_sequence));
236 
237 	type = egp->egp_type;
238 	code = egp->egp_code;
239 	status = egp->egp_status;
240 
241 	switch (type) {
242 	case EGPT_ACQUIRE:
243 		printf(" acquire");
244 		switch (code) {
245 		case EGPC_REQUEST:
246 		case EGPC_CONFIRM:
247 			printf(" %s", egp_acquire_codes[code]);
248 			switch (status) {
249 			case EGPS_UNSPEC:
250 			case EGPS_ACTIVE:
251 			case EGPS_PASSIVE:
252 				printf(" %s", egp_acquire_status[status]);
253 				break;
254 
255 			default:
256 				printf(" [status %d]", status);
257 				break;
258 			}
259 			printf(" hello:%d poll:%d",
260 			       EXTRACT_16BITS(&egp->egp_hello),
261 			       EXTRACT_16BITS(&egp->egp_poll));
262 			break;
263 
264 		case EGPC_REFUSE:
265 		case EGPC_CEASE:
266 		case EGPC_CEASEACK:
267 			printf(" %s", egp_acquire_codes[code]);
268 			switch (status ) {
269 			case EGPS_UNSPEC:
270 			case EGPS_NORES:
271 			case EGPS_ADMIN:
272 			case EGPS_GODOWN:
273 			case EGPS_PARAM:
274 			case EGPS_PROTO:
275 				printf(" %s", egp_acquire_status[status]);
276 				break;
277 
278 			default:
279 				printf("[status %d]", status);
280 				break;
281 			}
282 			break;
283 
284 		default:
285 			printf("[code %d]", code);
286 			break;
287 		}
288 		break;
289 
290 	case EGPT_REACH:
291 		switch (code) {
292 
293 		case EGPC_HELLO:
294 		case EGPC_HEARDU:
295 			printf(" %s", egp_reach_codes[code]);
296 			if (status <= EGPS_DOWN)
297 				printf(" state:%s", egp_status_updown[status]);
298 			else
299 				printf(" [status %d]", status);
300 			break;
301 
302 		default:
303 			printf("[reach code %d]", code);
304 			break;
305 		}
306 		break;
307 
308 	case EGPT_POLL:
309 		printf(" poll");
310 		if (egp->egp_status <= EGPS_DOWN)
311 			printf(" state:%s", egp_status_updown[status]);
312 		else
313 			printf(" [status %d]", status);
314 		printf(" net:%s", ipaddr_string(&egp->egp_sourcenet));
315 		break;
316 
317 	case EGPT_UPDATE:
318 		printf(" update");
319 		if (status & EGPS_UNSOL) {
320 			status &= ~EGPS_UNSOL;
321 			printf(" unsolicited");
322 		}
323 		if (status <= EGPS_DOWN)
324 			printf(" state:%s", egp_status_updown[status]);
325 		else
326 			printf(" [status %d]", status);
327 		printf(" %s int %d ext %d",
328 		       ipaddr_string(&egp->egp_sourcenet),
329 		       egp->egp_intgw,
330 		       egp->egp_extgw);
331 		if (vflag)
332 			egpnrprint(egp);
333 		break;
334 
335 	case EGPT_ERROR:
336 		printf(" error");
337 		if (status <= EGPS_DOWN)
338 			printf(" state:%s", egp_status_updown[status]);
339 		else
340 			printf(" [status %d]", status);
341 
342 		if (EXTRACT_16BITS(&egp->egp_reason) <= EGPR_UVERSION)
343 			printf(" %s", egp_reasons[EXTRACT_16BITS(&egp->egp_reason)]);
344 		else
345 			printf(" [reason %d]", EXTRACT_16BITS(&egp->egp_reason));
346 		break;
347 
348 	default:
349 		printf("[type %d]", type);
350 		break;
351 	}
352 }
353