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