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