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 } 357