2 * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
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.
18 * Initial contribution from Jeff Honig (jch@MITCHELL.CIT.CORNELL.EDU).
21 /* \summary: Exterior Gateway Protocol (EGP) printer */
23 /* specification: RFC 827 */
29 #include "netdissect-stdinc.h"
31 #define ND_LONGJMP_FROM_TCHECK
32 #include "netdissect.h"
33 #include "addrtoname.h"
37 nd_uint8_t egp_version
;
40 #define EGPT_ACQUIRE 3
46 #define EGPC_REQUEST 0
47 #define EGPC_CONFIRM 1
50 #define EGPC_CEASEACK 4
53 nd_uint8_t egp_status
;
56 #define EGPS_PASSIVE 2
65 #define EGPS_UNSOL 0x80
66 nd_uint16_t egp_checksum
;
68 nd_uint16_t egp_sequence
;
70 nd_uint16_t egpu_hello
;
71 nd_uint8_t egpu_gws
[2];
72 nd_uint16_t egpu_reason
;
74 #define EGPR_BADHEAD 1
75 #define EGPR_BADDATA 2
76 #define EGPR_NOREACH 3
79 #define EGPR_UVERSION 6
81 #define egp_hello egp_handg.egpu_hello
82 #define egp_intgw egp_handg.egpu_gws[0]
83 #define egp_extgw egp_handg.egpu_gws[1]
84 #define egp_reason egp_handg.egpu_reason
86 nd_uint16_t egpu_poll
;
87 nd_ipv4 egpu_sourcenet
;
89 #define egp_poll egp_pands.egpu_poll
90 #define egp_sourcenet egp_pands.egpu_sourcenet
93 static const struct tok egp_type_str
[] = {
94 { EGPT_ACQUIRE
, "acquire" },
95 { EGPT_REACH
, "reach" },
96 { EGPT_POLL
, "poll" },
97 { EGPT_UPDATE
, "update" },
98 { EGPT_ERROR
, "error" },
102 static const struct tok egp_acquire_codes_str
[] = {
103 { EGPC_REQUEST
, "request" },
104 { EGPC_CONFIRM
, "confirm" },
105 { EGPC_REFUSE
, "refuse" },
106 { EGPC_CEASE
, "cease" },
107 { EGPC_CEASEACK
, "cease_ack" },
111 static const struct tok egp_acquire_status_str
[] = {
112 { EGPS_UNSPEC
, "unspecified" },
113 { EGPS_ACTIVE
, "active_mode" },
114 { EGPS_PASSIVE
, "passive_mode" },
115 { EGPS_NORES
, "insufficient_resources" },
116 { EGPS_ADMIN
, "administratively_prohibited" },
117 { EGPS_GODOWN
, "going_down" },
118 { EGPS_PARAM
, "parameter_violation" },
119 { EGPS_PROTO
, "protocol_violation" },
123 static const struct tok egp_reach_codes_str
[] = {
124 { EGPC_HELLO
, "hello" },
125 { EGPC_HEARDU
, "i-h-u" },
129 static const struct tok egp_status_updown_str
[] = {
130 { EGPS_INDET
, "indeterminate" },
132 { EGPS_DOWN
, "down" },
136 static const struct tok egp_reasons_str
[] = {
137 { EGPR_UNSPEC
, "unspecified" },
138 { EGPR_BADHEAD
, "bad_EGP_header_format" },
139 { EGPR_BADDATA
, "bad_EGP_data_field_format" },
140 { EGPR_NOREACH
, "reachability_info_unavailable" },
141 { EGPR_XSPOLL
, "excessive_polling_rate" },
142 { EGPR_NORESP
, "no_response" },
143 { EGPR_UVERSION
, "unsupported_version" },
148 egpnr_print(netdissect_options
*ndo
,
149 const struct egp_packet
*egp
, u_int length
)
155 u_int gateways
, distances
, networks
;
156 u_int intgw
, extgw
, t_gateways
;
159 addr
= GET_IPV4_TO_NETWORK_ORDER(egp
->egp_sourcenet
);
160 if (IN_CLASSA(addr
)) {
161 net
= addr
& IN_CLASSA_NET
;
163 } else if (IN_CLASSB(addr
)) {
164 net
= addr
& IN_CLASSB_NET
;
166 } else if (IN_CLASSC(addr
)) {
167 net
= addr
& IN_CLASSC_NET
;
173 cp
= (const uint8_t *)(egp
+ 1);
174 length
-= sizeof(*egp
);
176 intgw
= GET_U_1(egp
->egp_intgw
);
177 extgw
= GET_U_1(egp
->egp_extgw
);
178 t_gateways
= intgw
+ extgw
;
179 for (gateways
= 0; gateways
< t_gateways
; ++gateways
) {
180 /* Pickup host part of gateway address */
182 if (length
< 4 - netlen
)
184 ND_TCHECK_LEN(cp
, 4 - netlen
);
192 addr
= (addr
<< 8) | GET_U_1(cp
);
196 addr
= (addr
<< 8) | GET_U_1(cp
);
201 length
-= 4 - netlen
;
204 distances
= GET_U_1(cp
);
208 gateways
< intgw
? "int" : "ext",
209 ipaddr_string(ndo
, (const u_char
*)&addr
));
213 while (distances
!= 0) {
216 ND_PRINT("%sd%u:", comma
, GET_U_1(cp
));
219 networks
= GET_U_1(cp
);
222 while (networks
!= 0) {
223 /* Pickup network number */
226 addr
= ((uint32_t) GET_U_1(cp
)) << 24;
229 if (IN_CLASSB(addr
)) {
232 addr
|= ((uint32_t) GET_U_1(cp
)) << 16;
235 } else if (!IN_CLASSA(addr
)) {
238 addr
|= ((uint32_t) GET_U_1(cp
)) << 16;
240 addr
|= ((uint32_t) GET_U_1(cp
)) << 8;
244 ND_PRINT(" %s", ipaddr_string(ndo
, (const u_char
*)&addr
));
253 nd_print_invalid(ndo
);
257 egp_print(netdissect_options
*ndo
,
258 const uint8_t *bp
, u_int length
)
260 const struct egp_packet
*egp
;
266 ndo
->ndo_protocol
= "egp";
267 egp
= (const struct egp_packet
*)bp
;
268 ND_LCHECKMSG_ZU(length
, sizeof(*egp
), "packet length");
271 version
= GET_U_1(egp
->egp_version
);
272 if (!ndo
->ndo_vflag
) {
273 ND_PRINT("EGPv%u, AS %u, seq %u, length %u",
275 GET_BE_U_2(egp
->egp_as
),
276 GET_BE_U_2(egp
->egp_sequence
),
280 ND_PRINT("EGPv%u, length %u",
284 if (version
!= EGP_VERSION
) {
285 ND_PRINT("[version %u]", version
);
289 type
= GET_U_1(egp
->egp_type
);
290 ND_PRINT(" %s", tok2str(egp_type_str
, "[type %u]", type
));
291 code
= GET_U_1(egp
->egp_code
);
292 status
= GET_U_1(egp
->egp_status
);
296 ND_PRINT(" %s", tok2str(egp_acquire_codes_str
, "[code %u]", code
));
304 ND_PRINT(" %s", tok2str(egp_acquire_status_str
, "%u", status
));
308 ND_PRINT(" [status %u]", status
);
311 ND_PRINT(" hello:%u poll:%u",
312 GET_BE_U_2(egp
->egp_hello
),
313 GET_BE_U_2(egp
->egp_poll
));
326 ND_PRINT(" %s", tok2str(egp_acquire_status_str
, "%u", status
));
330 ND_PRINT("[status %u]", status
);
338 ND_PRINT(" %s", tok2str(egp_reach_codes_str
, "[reach code %u]", code
));
342 ND_PRINT(" state:%s", tok2str(egp_status_updown_str
, "%u", status
));
348 ND_PRINT(" state:%s", tok2str(egp_status_updown_str
, "%u", status
));
349 ND_PRINT(" net:%s", GET_IPADDR_STRING(egp
->egp_sourcenet
));
353 if (status
& EGPS_UNSOL
) {
354 status
&= ~EGPS_UNSOL
;
355 ND_PRINT(" unsolicited");
357 ND_PRINT(" state:%s", tok2str(egp_status_updown_str
, "%u", status
));
358 ND_PRINT(" %s int %u ext %u",
359 GET_IPADDR_STRING(egp
->egp_sourcenet
),
360 GET_U_1(egp
->egp_intgw
),
361 GET_U_1(egp
->egp_extgw
));
363 egpnr_print(ndo
, egp
, length
);
367 ND_PRINT(" state:%s", tok2str(egp_status_updown_str
, "%u", status
));
368 ND_PRINT(" %s", tok2str(egp_reasons_str
, "[reason %u]", GET_BE_U_2(egp
->egp_reason
)));
373 nd_print_invalid(ndo
);