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 (at) 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.37 2005/01/12 11:19:09 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 (void)printf("egp: "); 230 231 if (egp->egp_version != EGP_VERSION) { 232 printf("[version %d]", egp->egp_version); 233 return; 234 } 235 printf("as:%d seq:%d", EXTRACT_16BITS(&egp->egp_as), EXTRACT_16BITS(&egp->egp_sequence)); 236 237 type = egp->egp_type; 238 code = egp->egp_code; 239 status = egp->egp_status; 240 241 switch (type) { 242 case EGPT_ACQUIRE: 243 printf(" acquire"); 244 switch (code) { 245 case EGPC_REQUEST: 246 case EGPC_CONFIRM: 247 printf(" %s", egp_acquire_codes[code]); 248 switch (status) { 249 case EGPS_UNSPEC: 250 case EGPS_ACTIVE: 251 case EGPS_PASSIVE: 252 printf(" %s", egp_acquire_status[status]); 253 break; 254 255 default: 256 printf(" [status %d]", status); 257 break; 258 } 259 printf(" hello:%d poll:%d", 260 EXTRACT_16BITS(&egp->egp_hello), 261 EXTRACT_16BITS(&egp->egp_poll)); 262 break; 263 264 case EGPC_REFUSE: 265 case EGPC_CEASE: 266 case EGPC_CEASEACK: 267 printf(" %s", egp_acquire_codes[code]); 268 switch (status ) { 269 case EGPS_UNSPEC: 270 case EGPS_NORES: 271 case EGPS_ADMIN: 272 case EGPS_GODOWN: 273 case EGPS_PARAM: 274 case EGPS_PROTO: 275 printf(" %s", egp_acquire_status[status]); 276 break; 277 278 default: 279 printf("[status %d]", status); 280 break; 281 } 282 break; 283 284 default: 285 printf("[code %d]", code); 286 break; 287 } 288 break; 289 290 case EGPT_REACH: 291 switch (code) { 292 293 case EGPC_HELLO: 294 case EGPC_HEARDU: 295 printf(" %s", egp_reach_codes[code]); 296 if (status <= EGPS_DOWN) 297 printf(" state:%s", egp_status_updown[status]); 298 else 299 printf(" [status %d]", status); 300 break; 301 302 default: 303 printf("[reach code %d]", code); 304 break; 305 } 306 break; 307 308 case EGPT_POLL: 309 printf(" poll"); 310 if (egp->egp_status <= EGPS_DOWN) 311 printf(" state:%s", egp_status_updown[status]); 312 else 313 printf(" [status %d]", status); 314 printf(" net:%s", ipaddr_string(&egp->egp_sourcenet)); 315 break; 316 317 case EGPT_UPDATE: 318 printf(" update"); 319 if (status & EGPS_UNSOL) { 320 status &= ~EGPS_UNSOL; 321 printf(" unsolicited"); 322 } 323 if (status <= EGPS_DOWN) 324 printf(" state:%s", egp_status_updown[status]); 325 else 326 printf(" [status %d]", status); 327 printf(" %s int %d ext %d", 328 ipaddr_string(&egp->egp_sourcenet), 329 egp->egp_intgw, 330 egp->egp_extgw); 331 if (vflag) 332 egpnrprint(egp); 333 break; 334 335 case EGPT_ERROR: 336 printf(" error"); 337 if (status <= EGPS_DOWN) 338 printf(" state:%s", egp_status_updown[status]); 339 else 340 printf(" [status %d]", status); 341 342 if (EXTRACT_16BITS(&egp->egp_reason) <= EGPR_UVERSION) 343 printf(" %s", egp_reasons[EXTRACT_16BITS(&egp->egp_reason)]); 344 else 345 printf(" [reason %d]", EXTRACT_16BITS(&egp->egp_reason)); 346 break; 347 348 default: 349 printf("[type %d]", type); 350 break; 351 } 352 } 353