blob: 9c5c811e74e53bc399a555866e8a27298b52e055 [file] [log] [blame]
The Android Open Source Project2949f582009-03-03 19:30:46 -08001/*
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
Elliott Hughes892a68b2015-10-19 14:43:53 -070021#define NETDISSECT_REWORKED
The Android Open Source Project2949f582009-03-03 19:30:46 -080022#ifdef HAVE_CONFIG_H
23#include "config.h"
24#endif
25
26#include <tcpdump-stdinc.h>
27
The Android Open Source Project2949f582009-03-03 19:30:46 -080028#include "interface.h"
29#include "addrtoname.h"
30#include "extract.h"
31
The Android Open Source Project2949f582009-03-03 19:30:46 -080032struct egp_packet {
Elliott Hughes892a68b2015-10-19 14:43:53 -070033 uint8_t egp_version;
The Android Open Source Project2949f582009-03-03 19:30:46 -080034#define EGP_VERSION 2
Elliott Hughes892a68b2015-10-19 14:43:53 -070035 uint8_t egp_type;
The Android Open Source Project2949f582009-03-03 19:30:46 -080036#define EGPT_ACQUIRE 3
37#define EGPT_REACH 5
38#define EGPT_POLL 2
39#define EGPT_UPDATE 1
40#define EGPT_ERROR 8
Elliott Hughes892a68b2015-10-19 14:43:53 -070041 uint8_t egp_code;
The Android Open Source Project2949f582009-03-03 19:30:46 -080042#define EGPC_REQUEST 0
43#define EGPC_CONFIRM 1
44#define EGPC_REFUSE 2
45#define EGPC_CEASE 3
46#define EGPC_CEASEACK 4
47#define EGPC_HELLO 0
48#define EGPC_HEARDU 1
Elliott Hughes892a68b2015-10-19 14:43:53 -070049 uint8_t egp_status;
The Android Open Source Project2949f582009-03-03 19:30:46 -080050#define EGPS_UNSPEC 0
51#define EGPS_ACTIVE 1
52#define EGPS_PASSIVE 2
53#define EGPS_NORES 3
54#define EGPS_ADMIN 4
55#define EGPS_GODOWN 5
56#define EGPS_PARAM 6
57#define EGPS_PROTO 7
58#define EGPS_INDET 0
59#define EGPS_UP 1
60#define EGPS_DOWN 2
61#define EGPS_UNSOL 0x80
Elliott Hughes892a68b2015-10-19 14:43:53 -070062 uint16_t egp_checksum;
63 uint16_t egp_as;
64 uint16_t egp_sequence;
The Android Open Source Project2949f582009-03-03 19:30:46 -080065 union {
Elliott Hughes892a68b2015-10-19 14:43:53 -070066 uint16_t egpu_hello;
67 uint8_t egpu_gws[2];
68 uint16_t egpu_reason;
The Android Open Source Project2949f582009-03-03 19:30:46 -080069#define EGPR_UNSPEC 0
70#define EGPR_BADHEAD 1
71#define EGPR_BADDATA 2
72#define EGPR_NOREACH 3
73#define EGPR_XSPOLL 4
74#define EGPR_NORESP 5
75#define EGPR_UVERSION 6
76 } egp_handg;
77#define egp_hello egp_handg.egpu_hello
78#define egp_intgw egp_handg.egpu_gws[0]
79#define egp_extgw egp_handg.egpu_gws[1]
80#define egp_reason egp_handg.egpu_reason
81 union {
Elliott Hughes892a68b2015-10-19 14:43:53 -070082 uint16_t egpu_poll;
83 uint32_t egpu_sourcenet;
The Android Open Source Project2949f582009-03-03 19:30:46 -080084 } egp_pands;
85#define egp_poll egp_pands.egpu_poll
86#define egp_sourcenet egp_pands.egpu_sourcenet
87};
88
Elliott Hughes892a68b2015-10-19 14:43:53 -070089static const char *egp_acquire_codes[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -080090 "request",
91 "confirm",
92 "refuse",
93 "cease",
94 "cease_ack"
95};
96
Elliott Hughes892a68b2015-10-19 14:43:53 -070097static const char *egp_acquire_status[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -080098 "unspecified",
99 "active_mode",
100 "passive_mode",
101 "insufficient_resources",
102 "administratively_prohibited",
103 "going_down",
104 "parameter_violation",
105 "protocol_violation"
106};
107
Elliott Hughes892a68b2015-10-19 14:43:53 -0700108static const char *egp_reach_codes[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800109 "hello",
110 "i-h-u"
111};
112
Elliott Hughes892a68b2015-10-19 14:43:53 -0700113static const char *egp_status_updown[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800114 "indeterminate",
115 "up",
116 "down"
117};
118
Elliott Hughes892a68b2015-10-19 14:43:53 -0700119static const char *egp_reasons[] = {
The Android Open Source Project2949f582009-03-03 19:30:46 -0800120 "unspecified",
121 "bad_EGP_header_format",
122 "bad_EGP_data_field_format",
123 "reachability_info_unavailable",
124 "excessive_polling_rate",
125 "no_response",
126 "unsupported_version"
127};
128
129static void
Elliott Hughes892a68b2015-10-19 14:43:53 -0700130egpnrprint(netdissect_options *ndo,
131 register const struct egp_packet *egp)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800132{
Elliott Hughes892a68b2015-10-19 14:43:53 -0700133 register const uint8_t *cp;
134 uint32_t addr;
135 register uint32_t net;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800136 register u_int netlen;
137 int gateways, distances, networks;
138 int t_gateways;
139 const char *comma;
140
141 addr = egp->egp_sourcenet;
142 if (IN_CLASSA(addr)) {
143 net = addr & IN_CLASSA_NET;
144 netlen = 1;
145 } else if (IN_CLASSB(addr)) {
146 net = addr & IN_CLASSB_NET;
147 netlen = 2;
148 } else if (IN_CLASSC(addr)) {
149 net = addr & IN_CLASSC_NET;
150 netlen = 3;
151 } else {
152 net = 0;
153 netlen = 0;
154 }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700155 cp = (uint8_t *)(egp + 1);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800156
157 t_gateways = egp->egp_intgw + egp->egp_extgw;
158 for (gateways = 0; gateways < t_gateways; ++gateways) {
159 /* Pickup host part of gateway address */
160 addr = 0;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700161 ND_TCHECK2(cp[0], 4 - netlen);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800162 switch (netlen) {
163
164 case 1:
165 addr = *cp++;
166 /* fall through */
167 case 2:
168 addr = (addr << 8) | *cp++;
169 /* fall through */
170 case 3:
171 addr = (addr << 8) | *cp++;
172 }
173 addr |= net;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700174 ND_TCHECK2(cp[0], 1);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800175 distances = *cp++;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700176 ND_PRINT((ndo, " %s %s ",
The Android Open Source Project2949f582009-03-03 19:30:46 -0800177 gateways < (int)egp->egp_intgw ? "int" : "ext",
Elliott Hughes892a68b2015-10-19 14:43:53 -0700178 ipaddr_string(ndo, &addr)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800179
180 comma = "";
Elliott Hughes892a68b2015-10-19 14:43:53 -0700181 ND_PRINT((ndo, "("));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800182 while (--distances >= 0) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700183 ND_TCHECK2(cp[0], 2);
184 ND_PRINT((ndo, "%sd%d:", comma, (int)*cp++));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800185 comma = ", ";
186 networks = *cp++;
187 while (--networks >= 0) {
188 /* Pickup network number */
Elliott Hughes892a68b2015-10-19 14:43:53 -0700189 ND_TCHECK2(cp[0], 1);
190 addr = (uint32_t)*cp++ << 24;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800191 if (IN_CLASSB(addr)) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700192 ND_TCHECK2(cp[0], 1);
193 addr |= (uint32_t)*cp++ << 16;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800194 } else if (!IN_CLASSA(addr)) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700195 ND_TCHECK2(cp[0], 2);
196 addr |= (uint32_t)*cp++ << 16;
197 addr |= (uint32_t)*cp++ << 8;
The Android Open Source Project2949f582009-03-03 19:30:46 -0800198 }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700199 ND_PRINT((ndo, " %s", ipaddr_string(ndo, &addr)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800200 }
201 }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700202 ND_PRINT((ndo, ")"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800203 }
204 return;
205trunc:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700206 ND_PRINT((ndo, "[|]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800207}
208
209void
Elliott Hughes892a68b2015-10-19 14:43:53 -0700210egp_print(netdissect_options *ndo,
211 register const uint8_t *bp, register u_int length)
The Android Open Source Project2949f582009-03-03 19:30:46 -0800212{
213 register const struct egp_packet *egp;
214 register int status;
215 register int code;
216 register int type;
217
218 egp = (struct egp_packet *)bp;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700219 if (!ND_TTEST2(*egp, length)) {
220 ND_PRINT((ndo, "[|egp]"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800221 return;
222 }
JP Abgrall53f17a92014-02-12 14:02:41 -0800223
Elliott Hughes892a68b2015-10-19 14:43:53 -0700224 if (!ndo->ndo_vflag) {
225 ND_PRINT((ndo, "EGPv%u, AS %u, seq %u, length %u",
JP Abgrall53f17a92014-02-12 14:02:41 -0800226 egp->egp_version,
227 EXTRACT_16BITS(&egp->egp_as),
228 EXTRACT_16BITS(&egp->egp_sequence),
Elliott Hughes892a68b2015-10-19 14:43:53 -0700229 length));
JP Abgrall53f17a92014-02-12 14:02:41 -0800230 return;
231 } else
Elliott Hughes892a68b2015-10-19 14:43:53 -0700232 ND_PRINT((ndo, "EGPv%u, length %u",
JP Abgrall53f17a92014-02-12 14:02:41 -0800233 egp->egp_version,
Elliott Hughes892a68b2015-10-19 14:43:53 -0700234 length));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800235
236 if (egp->egp_version != EGP_VERSION) {
Elliott Hughes892a68b2015-10-19 14:43:53 -0700237 ND_PRINT((ndo, "[version %d]", egp->egp_version));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800238 return;
239 }
The Android Open Source Project2949f582009-03-03 19:30:46 -0800240
241 type = egp->egp_type;
242 code = egp->egp_code;
243 status = egp->egp_status;
244
245 switch (type) {
246 case EGPT_ACQUIRE:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700247 ND_PRINT((ndo, " acquire"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800248 switch (code) {
249 case EGPC_REQUEST:
250 case EGPC_CONFIRM:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700251 ND_PRINT((ndo, " %s", egp_acquire_codes[code]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800252 switch (status) {
253 case EGPS_UNSPEC:
254 case EGPS_ACTIVE:
255 case EGPS_PASSIVE:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700256 ND_PRINT((ndo, " %s", egp_acquire_status[status]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800257 break;
258
259 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700260 ND_PRINT((ndo, " [status %d]", status));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800261 break;
262 }
Elliott Hughes892a68b2015-10-19 14:43:53 -0700263 ND_PRINT((ndo, " hello:%d poll:%d",
The Android Open Source Project2949f582009-03-03 19:30:46 -0800264 EXTRACT_16BITS(&egp->egp_hello),
Elliott Hughes892a68b2015-10-19 14:43:53 -0700265 EXTRACT_16BITS(&egp->egp_poll)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800266 break;
267
268 case EGPC_REFUSE:
269 case EGPC_CEASE:
270 case EGPC_CEASEACK:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700271 ND_PRINT((ndo, " %s", egp_acquire_codes[code]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800272 switch (status ) {
273 case EGPS_UNSPEC:
274 case EGPS_NORES:
275 case EGPS_ADMIN:
276 case EGPS_GODOWN:
277 case EGPS_PARAM:
278 case EGPS_PROTO:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700279 ND_PRINT((ndo, " %s", egp_acquire_status[status]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800280 break;
281
282 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700283 ND_PRINT((ndo, "[status %d]", status));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800284 break;
285 }
286 break;
287
288 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700289 ND_PRINT((ndo, "[code %d]", code));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800290 break;
291 }
292 break;
293
294 case EGPT_REACH:
295 switch (code) {
296
297 case EGPC_HELLO:
298 case EGPC_HEARDU:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700299 ND_PRINT((ndo, " %s", egp_reach_codes[code]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800300 if (status <= EGPS_DOWN)
Elliott Hughes892a68b2015-10-19 14:43:53 -0700301 ND_PRINT((ndo, " state:%s", egp_status_updown[status]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800302 else
Elliott Hughes892a68b2015-10-19 14:43:53 -0700303 ND_PRINT((ndo, " [status %d]", status));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800304 break;
305
306 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700307 ND_PRINT((ndo, "[reach code %d]", code));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800308 break;
309 }
310 break;
311
312 case EGPT_POLL:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700313 ND_PRINT((ndo, " poll"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800314 if (egp->egp_status <= EGPS_DOWN)
Elliott Hughes892a68b2015-10-19 14:43:53 -0700315 ND_PRINT((ndo, " state:%s", egp_status_updown[status]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800316 else
Elliott Hughes892a68b2015-10-19 14:43:53 -0700317 ND_PRINT((ndo, " [status %d]", status));
318 ND_PRINT((ndo, " net:%s", ipaddr_string(ndo, &egp->egp_sourcenet)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800319 break;
320
321 case EGPT_UPDATE:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700322 ND_PRINT((ndo, " update"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800323 if (status & EGPS_UNSOL) {
324 status &= ~EGPS_UNSOL;
Elliott Hughes892a68b2015-10-19 14:43:53 -0700325 ND_PRINT((ndo, " unsolicited"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800326 }
327 if (status <= EGPS_DOWN)
Elliott Hughes892a68b2015-10-19 14:43:53 -0700328 ND_PRINT((ndo, " state:%s", egp_status_updown[status]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800329 else
Elliott Hughes892a68b2015-10-19 14:43:53 -0700330 ND_PRINT((ndo, " [status %d]", status));
331 ND_PRINT((ndo, " %s int %d ext %d",
332 ipaddr_string(ndo, &egp->egp_sourcenet),
The Android Open Source Project2949f582009-03-03 19:30:46 -0800333 egp->egp_intgw,
Elliott Hughes892a68b2015-10-19 14:43:53 -0700334 egp->egp_extgw));
335 if (ndo->ndo_vflag)
336 egpnrprint(ndo, egp);
The Android Open Source Project2949f582009-03-03 19:30:46 -0800337 break;
338
339 case EGPT_ERROR:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700340 ND_PRINT((ndo, " error"));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800341 if (status <= EGPS_DOWN)
Elliott Hughes892a68b2015-10-19 14:43:53 -0700342 ND_PRINT((ndo, " state:%s", egp_status_updown[status]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800343 else
Elliott Hughes892a68b2015-10-19 14:43:53 -0700344 ND_PRINT((ndo, " [status %d]", status));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800345
346 if (EXTRACT_16BITS(&egp->egp_reason) <= EGPR_UVERSION)
Elliott Hughes892a68b2015-10-19 14:43:53 -0700347 ND_PRINT((ndo, " %s", egp_reasons[EXTRACT_16BITS(&egp->egp_reason)]));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800348 else
Elliott Hughes892a68b2015-10-19 14:43:53 -0700349 ND_PRINT((ndo, " [reason %d]", EXTRACT_16BITS(&egp->egp_reason)));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800350 break;
351
352 default:
Elliott Hughes892a68b2015-10-19 14:43:53 -0700353 ND_PRINT((ndo, "[type %d]", type));
The Android Open Source Project2949f582009-03-03 19:30:46 -0800354 break;
355 }
356}