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