nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 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 | #define NETDISSECT_REWORKED |
||
22 | #ifdef HAVE_CONFIG_H |
||
23 | #include "config.h" |
||
24 | #endif |
||
25 | |||
26 | #include <tcpdump-stdinc.h> |
||
27 | |||
28 | #include "interface.h" |
||
29 | #include "addrtoname.h" |
||
30 | #include "extract.h" |
||
31 | |||
32 | struct egp_packet { |
||
33 | uint8_t egp_version; |
||
34 | #define EGP_VERSION 2 |
||
35 | uint8_t egp_type; |
||
36 | #define EGPT_ACQUIRE 3 |
||
37 | #define EGPT_REACH 5 |
||
38 | #define EGPT_POLL 2 |
||
39 | #define EGPT_UPDATE 1 |
||
40 | #define EGPT_ERROR 8 |
||
41 | uint8_t egp_code; |
||
42 | #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 |
||
49 | uint8_t egp_status; |
||
50 | #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 |
||
62 | uint16_t egp_checksum; |
||
63 | uint16_t egp_as; |
||
64 | uint16_t egp_sequence; |
||
65 | union { |
||
66 | uint16_t egpu_hello; |
||
67 | uint8_t egpu_gws[2]; |
||
68 | uint16_t egpu_reason; |
||
69 | #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 { |
||
82 | uint16_t egpu_poll; |
||
83 | uint32_t egpu_sourcenet; |
||
84 | } egp_pands; |
||
85 | #define egp_poll egp_pands.egpu_poll |
||
86 | #define egp_sourcenet egp_pands.egpu_sourcenet |
||
87 | }; |
||
88 | |||
89 | static const char *egp_acquire_codes[] = { |
||
90 | "request", |
||
91 | "confirm", |
||
92 | "refuse", |
||
93 | "cease", |
||
94 | "cease_ack" |
||
95 | }; |
||
96 | |||
97 | static const char *egp_acquire_status[] = { |
||
98 | "unspecified", |
||
99 | "active_mode", |
||
100 | "passive_mode", |
||
101 | "insufficient_resources", |
||
102 | "administratively_prohibited", |
||
103 | "going_down", |
||
104 | "parameter_violation", |
||
105 | "protocol_violation" |
||
106 | }; |
||
107 | |||
108 | static const char *egp_reach_codes[] = { |
||
109 | "hello", |
||
110 | "i-h-u" |
||
111 | }; |
||
112 | |||
113 | static const char *egp_status_updown[] = { |
||
114 | "indeterminate", |
||
115 | "up", |
||
116 | "down" |
||
117 | }; |
||
118 | |||
119 | static const char *egp_reasons[] = { |
||
120 | "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 | |||
129 | static void |
||
130 | egpnrprint(netdissect_options *ndo, |
||
131 | register const struct egp_packet *egp) |
||
132 | { |
||
133 | register const uint8_t *cp; |
||
134 | uint32_t addr; |
||
135 | register uint32_t net; |
||
136 | 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 | } |
||
155 | cp = (uint8_t *)(egp + 1); |
||
156 | |||
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; |
||
161 | ND_TCHECK2(cp[0], 4 - netlen); |
||
162 | 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; |
||
174 | ND_TCHECK2(cp[0], 1); |
||
175 | distances = *cp++; |
||
176 | ND_PRINT((ndo, " %s %s ", |
||
177 | gateways < (int)egp->egp_intgw ? "int" : "ext", |
||
178 | ipaddr_string(ndo, &addr))); |
||
179 | |||
180 | comma = ""; |
||
181 | ND_PRINT((ndo, "(")); |
||
182 | while (--distances >= 0) { |
||
183 | ND_TCHECK2(cp[0], 2); |
||
184 | ND_PRINT((ndo, "%sd%d:", comma, (int)*cp++)); |
||
185 | comma = ", "; |
||
186 | networks = *cp++; |
||
187 | while (--networks >= 0) { |
||
188 | /* Pickup network number */ |
||
189 | ND_TCHECK2(cp[0], 1); |
||
190 | addr = (uint32_t)*cp++ << 24; |
||
191 | if (IN_CLASSB(addr)) { |
||
192 | ND_TCHECK2(cp[0], 1); |
||
193 | addr |= (uint32_t)*cp++ << 16; |
||
194 | } else if (!IN_CLASSA(addr)) { |
||
195 | ND_TCHECK2(cp[0], 2); |
||
196 | addr |= (uint32_t)*cp++ << 16; |
||
197 | addr |= (uint32_t)*cp++ << 8; |
||
198 | } |
||
199 | ND_PRINT((ndo, " %s", ipaddr_string(ndo, &addr))); |
||
200 | } |
||
201 | } |
||
202 | ND_PRINT((ndo, ")")); |
||
203 | } |
||
204 | return; |
||
205 | trunc: |
||
206 | ND_PRINT((ndo, "[|]")); |
||
207 | } |
||
208 | |||
209 | void |
||
210 | egp_print(netdissect_options *ndo, |
||
211 | register const uint8_t *bp, register u_int length) |
||
212 | { |
||
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; |
||
219 | if (!ND_TTEST2(*egp, length)) { |
||
220 | ND_PRINT((ndo, "[|egp]")); |
||
221 | return; |
||
222 | } |
||
223 | |||
224 | if (!ndo->ndo_vflag) { |
||
225 | ND_PRINT((ndo, "EGPv%u, AS %u, seq %u, length %u", |
||
226 | egp->egp_version, |
||
227 | EXTRACT_16BITS(&egp->egp_as), |
||
228 | EXTRACT_16BITS(&egp->egp_sequence), |
||
229 | length)); |
||
230 | return; |
||
231 | } else |
||
232 | ND_PRINT((ndo, "EGPv%u, length %u", |
||
233 | egp->egp_version, |
||
234 | length)); |
||
235 | |||
236 | if (egp->egp_version != EGP_VERSION) { |
||
237 | ND_PRINT((ndo, "[version %d]", egp->egp_version)); |
||
238 | return; |
||
239 | } |
||
240 | |||
241 | type = egp->egp_type; |
||
242 | code = egp->egp_code; |
||
243 | status = egp->egp_status; |
||
244 | |||
245 | switch (type) { |
||
246 | case EGPT_ACQUIRE: |
||
247 | ND_PRINT((ndo, " acquire")); |
||
248 | switch (code) { |
||
249 | case EGPC_REQUEST: |
||
250 | case EGPC_CONFIRM: |
||
251 | ND_PRINT((ndo, " %s", egp_acquire_codes[code])); |
||
252 | switch (status) { |
||
253 | case EGPS_UNSPEC: |
||
254 | case EGPS_ACTIVE: |
||
255 | case EGPS_PASSIVE: |
||
256 | ND_PRINT((ndo, " %s", egp_acquire_status[status])); |
||
257 | break; |
||
258 | |||
259 | default: |
||
260 | ND_PRINT((ndo, " [status %d]", status)); |
||
261 | break; |
||
262 | } |
||
263 | ND_PRINT((ndo, " hello:%d poll:%d", |
||
264 | EXTRACT_16BITS(&egp->egp_hello), |
||
265 | EXTRACT_16BITS(&egp->egp_poll))); |
||
266 | break; |
||
267 | |||
268 | case EGPC_REFUSE: |
||
269 | case EGPC_CEASE: |
||
270 | case EGPC_CEASEACK: |
||
271 | ND_PRINT((ndo, " %s", egp_acquire_codes[code])); |
||
272 | 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: |
||
279 | ND_PRINT((ndo, " %s", egp_acquire_status[status])); |
||
280 | break; |
||
281 | |||
282 | default: |
||
283 | ND_PRINT((ndo, "[status %d]", status)); |
||
284 | break; |
||
285 | } |
||
286 | break; |
||
287 | |||
288 | default: |
||
289 | ND_PRINT((ndo, "[code %d]", code)); |
||
290 | break; |
||
291 | } |
||
292 | break; |
||
293 | |||
294 | case EGPT_REACH: |
||
295 | switch (code) { |
||
296 | |||
297 | case EGPC_HELLO: |
||
298 | case EGPC_HEARDU: |
||
299 | ND_PRINT((ndo, " %s", egp_reach_codes[code])); |
||
300 | if (status <= EGPS_DOWN) |
||
301 | ND_PRINT((ndo, " state:%s", egp_status_updown[status])); |
||
302 | else |
||
303 | ND_PRINT((ndo, " [status %d]", status)); |
||
304 | break; |
||
305 | |||
306 | default: |
||
307 | ND_PRINT((ndo, "[reach code %d]", code)); |
||
308 | break; |
||
309 | } |
||
310 | break; |
||
311 | |||
312 | case EGPT_POLL: |
||
313 | ND_PRINT((ndo, " poll")); |
||
314 | if (egp->egp_status <= EGPS_DOWN) |
||
315 | ND_PRINT((ndo, " state:%s", egp_status_updown[status])); |
||
316 | else |
||
317 | ND_PRINT((ndo, " [status %d]", status)); |
||
318 | ND_PRINT((ndo, " net:%s", ipaddr_string(ndo, &egp->egp_sourcenet))); |
||
319 | break; |
||
320 | |||
321 | case EGPT_UPDATE: |
||
322 | ND_PRINT((ndo, " update")); |
||
323 | if (status & EGPS_UNSOL) { |
||
324 | status &= ~EGPS_UNSOL; |
||
325 | ND_PRINT((ndo, " unsolicited")); |
||
326 | } |
||
327 | if (status <= EGPS_DOWN) |
||
328 | ND_PRINT((ndo, " state:%s", egp_status_updown[status])); |
||
329 | else |
||
330 | ND_PRINT((ndo, " [status %d]", status)); |
||
331 | ND_PRINT((ndo, " %s int %d ext %d", |
||
332 | ipaddr_string(ndo, &egp->egp_sourcenet), |
||
333 | egp->egp_intgw, |
||
334 | egp->egp_extgw)); |
||
335 | if (ndo->ndo_vflag) |
||
336 | egpnrprint(ndo, egp); |
||
337 | break; |
||
338 | |||
339 | case EGPT_ERROR: |
||
340 | ND_PRINT((ndo, " error")); |
||
341 | if (status <= EGPS_DOWN) |
||
342 | ND_PRINT((ndo, " state:%s", egp_status_updown[status])); |
||
343 | else |
||
344 | ND_PRINT((ndo, " [status %d]", status)); |
||
345 | |||
346 | if (EXTRACT_16BITS(&egp->egp_reason) <= EGPR_UVERSION) |
||
347 | ND_PRINT((ndo, " %s", egp_reasons[EXTRACT_16BITS(&egp->egp_reason)])); |
||
348 | else |
||
349 | ND_PRINT((ndo, " [reason %d]", EXTRACT_16BITS(&egp->egp_reason))); |
||
350 | break; |
||
351 | |||
352 | default: |
||
353 | ND_PRINT((ndo, "[type %d]", type)); |
||
354 | break; |
||
355 | } |
||
356 | } |