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