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