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 24static 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$"); 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 45struct 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 102const char *egp_acquire_codes[] = { 103 "request", 104 "confirm", 105 "refuse", 106 "cease", 107 "cease_ack" 108}; 109 110const 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 121const char *egp_reach_codes[] = { 122 "hello", 123 "i-h-u" 124}; 125 126const char *egp_status_updown[] = { 127 "indeterminate", 128 "up", 129 "down" 130}; 131 132const 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 142static void 143egpnrprint(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; 217trunc: 218 fputs("[|]", stdout); 219} 220 221void 222egp_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