xref: /freebsd/contrib/tcpdump/print-egp.c (revision ad30f8e79bd1007cc2476e491bd21b4f5e389e0a)
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.38 2006-02-11 22:13:24 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 
230         if (!vflag) {
231             printf("EGPv%u, AS %u, seq %u, length %u",
232                    egp->egp_version,
233                    EXTRACT_16BITS(&egp->egp_as),
234                    EXTRACT_16BITS(&egp->egp_sequence),
235                    length);
236             return;
237         } else
238             printf("EGPv%u, length %u",
239                    egp->egp_version,
240                    length);
241 
242 	if (egp->egp_version != EGP_VERSION) {
243 		printf("[version %d]", egp->egp_version);
244 		return;
245 	}
246 
247 	type = egp->egp_type;
248 	code = egp->egp_code;
249 	status = egp->egp_status;
250 
251 	switch (type) {
252 	case EGPT_ACQUIRE:
253 		printf(" acquire");
254 		switch (code) {
255 		case EGPC_REQUEST:
256 		case EGPC_CONFIRM:
257 			printf(" %s", egp_acquire_codes[code]);
258 			switch (status) {
259 			case EGPS_UNSPEC:
260 			case EGPS_ACTIVE:
261 			case EGPS_PASSIVE:
262 				printf(" %s", egp_acquire_status[status]);
263 				break;
264 
265 			default:
266 				printf(" [status %d]", status);
267 				break;
268 			}
269 			printf(" hello:%d poll:%d",
270 			       EXTRACT_16BITS(&egp->egp_hello),
271 			       EXTRACT_16BITS(&egp->egp_poll));
272 			break;
273 
274 		case EGPC_REFUSE:
275 		case EGPC_CEASE:
276 		case EGPC_CEASEACK:
277 			printf(" %s", egp_acquire_codes[code]);
278 			switch (status ) {
279 			case EGPS_UNSPEC:
280 			case EGPS_NORES:
281 			case EGPS_ADMIN:
282 			case EGPS_GODOWN:
283 			case EGPS_PARAM:
284 			case EGPS_PROTO:
285 				printf(" %s", egp_acquire_status[status]);
286 				break;
287 
288 			default:
289 				printf("[status %d]", status);
290 				break;
291 			}
292 			break;
293 
294 		default:
295 			printf("[code %d]", code);
296 			break;
297 		}
298 		break;
299 
300 	case EGPT_REACH:
301 		switch (code) {
302 
303 		case EGPC_HELLO:
304 		case EGPC_HEARDU:
305 			printf(" %s", egp_reach_codes[code]);
306 			if (status <= EGPS_DOWN)
307 				printf(" state:%s", egp_status_updown[status]);
308 			else
309 				printf(" [status %d]", status);
310 			break;
311 
312 		default:
313 			printf("[reach code %d]", code);
314 			break;
315 		}
316 		break;
317 
318 	case EGPT_POLL:
319 		printf(" poll");
320 		if (egp->egp_status <= EGPS_DOWN)
321 			printf(" state:%s", egp_status_updown[status]);
322 		else
323 			printf(" [status %d]", status);
324 		printf(" net:%s", ipaddr_string(&egp->egp_sourcenet));
325 		break;
326 
327 	case EGPT_UPDATE:
328 		printf(" update");
329 		if (status & EGPS_UNSOL) {
330 			status &= ~EGPS_UNSOL;
331 			printf(" unsolicited");
332 		}
333 		if (status <= EGPS_DOWN)
334 			printf(" state:%s", egp_status_updown[status]);
335 		else
336 			printf(" [status %d]", status);
337 		printf(" %s int %d ext %d",
338 		       ipaddr_string(&egp->egp_sourcenet),
339 		       egp->egp_intgw,
340 		       egp->egp_extgw);
341 		if (vflag)
342 			egpnrprint(egp);
343 		break;
344 
345 	case EGPT_ERROR:
346 		printf(" error");
347 		if (status <= EGPS_DOWN)
348 			printf(" state:%s", egp_status_updown[status]);
349 		else
350 			printf(" [status %d]", status);
351 
352 		if (EXTRACT_16BITS(&egp->egp_reason) <= EGPR_UVERSION)
353 			printf(" %s", egp_reasons[EXTRACT_16BITS(&egp->egp_reason)]);
354 		else
355 			printf(" [reason %d]", EXTRACT_16BITS(&egp->egp_reason));
356 		break;
357 
358 	default:
359 		printf("[type %d]", type);
360 		break;
361 	}
362 }
363