xref: /freebsd/contrib/tcpdump/print-egp.c (revision f9218d3d4fd34f082473b3a021c6d4d109fb47cf)
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[] =
23     "@(#) $Header: /tcpdump/master/tcpdump/print-egp.c,v 1.28.4.1 2002/06/01 23:51:12 guy Exp $ (LBL)";
24 #endif
25 
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29 
30 #include <sys/param.h>
31 #include <sys/time.h>
32 #include <sys/socket.h>
33 
34 #include <netinet/in.h>
35 
36 #include <netdb.h>
37 #include <stdio.h>
38 
39 #include "interface.h"
40 #include "addrtoname.h"
41 
42 #include "ip.h"
43 
44 struct egp_packet {
45 	u_char  egp_version;
46 #define	EGP_VERSION	2
47 	u_char  egp_type;
48 #define  EGPT_ACQUIRE	3
49 #define  EGPT_REACH	5
50 #define  EGPT_POLL	2
51 #define  EGPT_UPDATE	1
52 #define  EGPT_ERROR	8
53 	u_char  egp_code;
54 #define  EGPC_REQUEST	0
55 #define  EGPC_CONFIRM	1
56 #define  EGPC_REFUSE	2
57 #define  EGPC_CEASE	3
58 #define  EGPC_CEASEACK	4
59 #define  EGPC_HELLO	0
60 #define  EGPC_HEARDU	1
61 	u_char  egp_status;
62 #define  EGPS_UNSPEC	0
63 #define  EGPS_ACTIVE	1
64 #define  EGPS_PASSIVE	2
65 #define  EGPS_NORES	3
66 #define  EGPS_ADMIN	4
67 #define  EGPS_GODOWN	5
68 #define  EGPS_PARAM	6
69 #define  EGPS_PROTO	7
70 #define  EGPS_INDET	0
71 #define  EGPS_UP	1
72 #define  EGPS_DOWN	2
73 #define  EGPS_UNSOL	0x80
74 	u_short  egp_checksum;
75 	u_short  egp_as;
76 	u_short  egp_sequence;
77 	union {
78 		u_short  egpu_hello;
79 		u_char egpu_gws[2];
80 		u_short  egpu_reason;
81 #define  EGPR_UNSPEC	0
82 #define  EGPR_BADHEAD	1
83 #define  EGPR_BADDATA	2
84 #define  EGPR_NOREACH	3
85 #define  EGPR_XSPOLL	4
86 #define  EGPR_NORESP	5
87 #define  EGPR_UVERSION	6
88 	} egp_handg;
89 #define  egp_hello  egp_handg.egpu_hello
90 #define  egp_intgw  egp_handg.egpu_gws[0]
91 #define  egp_extgw  egp_handg.egpu_gws[1]
92 #define  egp_reason  egp_handg.egpu_reason
93 	union {
94 		u_short  egpu_poll;
95 		u_int32_t egpu_sourcenet;
96 	} egp_pands;
97 #define  egp_poll  egp_pands.egpu_poll
98 #define  egp_sourcenet  egp_pands.egpu_sourcenet
99 };
100 
101 const char *egp_acquire_codes[] = {
102 	"request",
103 	"confirm",
104 	"refuse",
105 	"cease",
106 	"cease_ack"
107 };
108 
109 const char *egp_acquire_status[] = {
110 	"unspecified",
111 	"active_mode",
112 	"passive_mode",
113 	"insufficient_resources",
114 	"administratively_prohibited",
115 	"going_down",
116 	"parameter_violation",
117 	"protocol_violation"
118 };
119 
120 const char *egp_reach_codes[] = {
121 	"hello",
122 	"i-h-u"
123 };
124 
125 const char *egp_status_updown[] = {
126 	"indeterminate",
127 	"up",
128 	"down"
129 };
130 
131 const char *egp_reasons[] = {
132 	"unspecified",
133 	"bad_EGP_header_format",
134 	"bad_EGP_data_field_format",
135 	"reachability_info_unavailable",
136 	"excessive_polling_rate",
137 	"no_response",
138 	"unsupported_version"
139 };
140 
141 static void
142 egpnrprint(register const struct egp_packet *egp, register u_int length)
143 {
144 	register const u_char *cp;
145 	u_int32_t addr;
146 	register u_int32_t net;
147 	register u_int netlen;
148 	int gateways, distances, networks;
149 	int t_gateways;
150 	char *comma;
151 
152 	addr = egp->egp_sourcenet;
153 	if (IN_CLASSA(addr)) {
154 		net = addr & IN_CLASSA_NET;
155 		netlen = 1;
156 	} else if (IN_CLASSB(addr)) {
157 		net = addr & IN_CLASSB_NET;
158 		netlen = 2;
159 	} else if (IN_CLASSC(addr)) {
160 		net = addr & IN_CLASSC_NET;
161 		netlen = 3;
162 	} else {
163 		net = 0;
164 		netlen = 0;
165 	}
166 	cp = (u_char *)(egp + 1);
167 
168 	t_gateways = egp->egp_intgw + egp->egp_extgw;
169 	for (gateways = 0; gateways < t_gateways; ++gateways) {
170 		/* Pickup host part of gateway address */
171 		addr = 0;
172 		TCHECK2(cp[0], 4 - netlen);
173 		switch (netlen) {
174 
175 		case 1:
176 			addr = *cp++;
177 			/* fall through */
178 		case 2:
179 			addr = (addr << 8) | *cp++;
180 			/* fall through */
181 		case 3:
182 			addr = (addr << 8) | *cp++;
183 		}
184 		addr |= net;
185 		TCHECK2(cp[0], 1);
186 		distances = *cp++;
187 		printf(" %s %s ",
188 		       gateways < (int)egp->egp_intgw ? "int" : "ext",
189 		       ipaddr_string(&addr));
190 
191 		comma = "";
192 		putchar('(');
193 		while (--distances >= 0) {
194 			TCHECK2(cp[0], 2);
195 			printf("%sd%d:", comma, (int)*cp++);
196 			comma = ", ";
197 			networks = *cp++;
198 			while (--networks >= 0) {
199 				/* Pickup network number */
200 				TCHECK2(cp[0], 1);
201 				addr = (u_int32_t)*cp++ << 24;
202 				if (IN_CLASSB(addr)) {
203 					TCHECK2(cp[0], 1);
204 					addr |= (u_int32_t)*cp++ << 16;
205 				} else if (!IN_CLASSA(addr)) {
206 					TCHECK2(cp[0], 2);
207 					addr |= (u_int32_t)*cp++ << 16;
208 					addr |= (u_int32_t)*cp++ << 8;
209 				}
210 				printf(" %s", ipaddr_string(&addr));
211 			}
212 		}
213 		putchar(')');
214 	}
215 	return;
216 trunc:
217 	fputs("[|]", stdout);
218 }
219 
220 void
221 egp_print(register const u_char *bp, register u_int length,
222 	  register const u_char *bp2)
223 {
224 	register const struct egp_packet *egp;
225 	register const struct ip *ip;
226 	register int status;
227 	register int code;
228 	register int type;
229 
230 	egp = (struct egp_packet *)bp;
231 	ip = (struct ip *)bp2;
232 	(void)printf("egp: ");
233 
234 	if (egp->egp_version != EGP_VERSION) {
235 		printf("[version %d]", egp->egp_version);
236 		return;
237 	}
238 	printf("as:%d seq:%d", ntohs(egp->egp_as), ntohs(egp->egp_sequence));
239 
240 	type = egp->egp_type;
241 	code = egp->egp_code;
242 	status = egp->egp_status;
243 
244 	switch (type) {
245 	case EGPT_ACQUIRE:
246 		printf(" acquire");
247 		switch (code) {
248 		case EGPC_REQUEST:
249 		case EGPC_CONFIRM:
250 			printf(" %s", egp_acquire_codes[code]);
251 			switch (status) {
252 			case EGPS_UNSPEC:
253 			case EGPS_ACTIVE:
254 			case EGPS_PASSIVE:
255 				printf(" %s", egp_acquire_status[status]);
256 				break;
257 
258 			default:
259 				printf(" [status %d]", status);
260 				break;
261 			}
262 			printf(" hello:%d poll:%d",
263 			       ntohs(egp->egp_hello),
264 			       ntohs(egp->egp_poll));
265 			break;
266 
267 		case EGPC_REFUSE:
268 		case EGPC_CEASE:
269 		case EGPC_CEASEACK:
270 			printf(" %s", egp_acquire_codes[code]);
271 			switch (status ) {
272 			case EGPS_UNSPEC:
273 			case EGPS_NORES:
274 			case EGPS_ADMIN:
275 			case EGPS_GODOWN:
276 			case EGPS_PARAM:
277 			case EGPS_PROTO:
278 				printf(" %s", egp_acquire_status[status]);
279 				break;
280 
281 			default:
282 				printf("[status %d]", status);
283 				break;
284 			}
285 			break;
286 
287 		default:
288 			printf("[code %d]", code);
289 			break;
290 		}
291 		break;
292 
293 	case EGPT_REACH:
294 		switch (code) {
295 
296 		case EGPC_HELLO:
297 		case EGPC_HEARDU:
298 			printf(" %s", egp_reach_codes[code]);
299 			if (status <= EGPS_DOWN)
300 				printf(" state:%s", egp_status_updown[status]);
301 			else
302 				printf(" [status %d]", status);
303 			break;
304 
305 		default:
306 			printf("[reach code %d]", code);
307 			break;
308 		}
309 		break;
310 
311 	case EGPT_POLL:
312 		printf(" poll");
313 		if (egp->egp_status <= EGPS_DOWN)
314 			printf(" state:%s", egp_status_updown[status]);
315 		else
316 			printf(" [status %d]", status);
317 		printf(" net:%s", ipaddr_string(&egp->egp_sourcenet));
318 		break;
319 
320 	case EGPT_UPDATE:
321 		printf(" update");
322 		if (status & EGPS_UNSOL) {
323 			status &= ~EGPS_UNSOL;
324 			printf(" unsolicited");
325 		}
326 		if (status <= EGPS_DOWN)
327 			printf(" state:%s", egp_status_updown[status]);
328 		else
329 			printf(" [status %d]", status);
330 		printf(" %s int %d ext %d",
331 		       ipaddr_string(&egp->egp_sourcenet),
332 		       egp->egp_intgw,
333 		       egp->egp_extgw);
334 		if (vflag)
335 			egpnrprint(egp, length);
336 		break;
337 
338 	case EGPT_ERROR:
339 		printf(" error");
340 		if (status <= EGPS_DOWN)
341 			printf(" state:%s", egp_status_updown[status]);
342 		else
343 			printf(" [status %d]", status);
344 
345 		if (ntohs(egp->egp_reason) <= EGPR_UVERSION)
346 			printf(" %s", egp_reasons[ntohs(egp->egp_reason)]);
347 		else
348 			printf(" [reason %d]", ntohs(egp->egp_reason));
349 		break;
350 
351 	default:
352 		printf("[type %d]", type);
353 		break;
354 	}
355 }
356