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