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.26 2000/09/29 04:58:36 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/uio.h> 33 #include <sys/socket.h> 34 35 #include <netinet/in.h> 36 37 #include <netdb.h> 38 #include <stdio.h> 39 40 #include "interface.h" 41 #include "addrtoname.h" 42 43 #include "ip.h" 44 45 struct egp_packet { 46 u_char egp_version; 47 #define EGP_VERSION 2 48 u_char 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_char 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_char 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_short egp_checksum; 76 u_short egp_as; 77 u_short egp_sequence; 78 union { 79 u_short egpu_hello; 80 u_char egpu_gws[2]; 81 u_short 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_short 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 char *egp_acquire_codes[] = { 103 "request", 104 "confirm", 105 "refuse", 106 "cease", 107 "cease_ack" 108 }; 109 110 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 char *egp_reach_codes[] = { 122 "hello", 123 "i-h-u" 124 }; 125 126 char *egp_status_updown[] = { 127 "indeterminate", 128 "up", 129 "down" 130 }; 131 132 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, register u_int length) 144 { 145 register const u_char *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 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_char *)(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_char *bp, register u_int length, 223 register const u_char *bp2) 224 { 225 register const struct egp_packet *egp; 226 register const struct ip *ip; 227 register int status; 228 register int code; 229 register int type; 230 231 egp = (struct egp_packet *)bp; 232 ip = (struct ip *)bp2; 233 (void)printf("%s > %s: egp: ", 234 ipaddr_string(&ip->ip_src), 235 ipaddr_string(&ip->ip_dst)); 236 237 if (egp->egp_version != EGP_VERSION) { 238 printf("[version %d]", egp->egp_version); 239 return; 240 } 241 printf("as:%d seq:%d", ntohs(egp->egp_as), ntohs(egp->egp_sequence)); 242 243 type = egp->egp_type; 244 code = egp->egp_code; 245 status = egp->egp_status; 246 247 switch (type) { 248 case EGPT_ACQUIRE: 249 printf(" acquire"); 250 switch (code) { 251 case EGPC_REQUEST: 252 case EGPC_CONFIRM: 253 printf(" %s", egp_acquire_codes[code]); 254 switch (status) { 255 case EGPS_UNSPEC: 256 case EGPS_ACTIVE: 257 case EGPS_PASSIVE: 258 printf(" %s", egp_acquire_status[status]); 259 break; 260 261 default: 262 printf(" [status %d]", status); 263 break; 264 } 265 printf(" hello:%d poll:%d", 266 ntohs(egp->egp_hello), 267 ntohs(egp->egp_poll)); 268 break; 269 270 case EGPC_REFUSE: 271 case EGPC_CEASE: 272 case EGPC_CEASEACK: 273 printf(" %s", egp_acquire_codes[code]); 274 switch (status ) { 275 case EGPS_UNSPEC: 276 case EGPS_NORES: 277 case EGPS_ADMIN: 278 case EGPS_GODOWN: 279 case EGPS_PARAM: 280 case EGPS_PROTO: 281 printf(" %s", egp_acquire_status[status]); 282 break; 283 284 default: 285 printf("[status %d]", status); 286 break; 287 } 288 break; 289 290 default: 291 printf("[code %d]", code); 292 break; 293 } 294 break; 295 296 case EGPT_REACH: 297 switch (code) { 298 299 case EGPC_HELLO: 300 case EGPC_HEARDU: 301 printf(" %s", egp_reach_codes[code]); 302 if (status <= EGPS_DOWN) 303 printf(" state:%s", egp_status_updown[status]); 304 else 305 printf(" [status %d]", status); 306 break; 307 308 default: 309 printf("[reach code %d]", code); 310 break; 311 } 312 break; 313 314 case EGPT_POLL: 315 printf(" poll"); 316 if (egp->egp_status <= EGPS_DOWN) 317 printf(" state:%s", egp_status_updown[status]); 318 else 319 printf(" [status %d]", status); 320 printf(" net:%s", ipaddr_string(&egp->egp_sourcenet)); 321 break; 322 323 case EGPT_UPDATE: 324 printf(" update"); 325 if (status & EGPS_UNSOL) { 326 status &= ~EGPS_UNSOL; 327 printf(" unsolicited"); 328 } 329 if (status <= EGPS_DOWN) 330 printf(" state:%s", egp_status_updown[status]); 331 else 332 printf(" [status %d]", status); 333 printf(" %s int %d ext %d", 334 ipaddr_string(&egp->egp_sourcenet), 335 egp->egp_intgw, 336 egp->egp_extgw); 337 if (vflag) 338 egpnrprint(egp, length); 339 break; 340 341 case EGPT_ERROR: 342 printf(" error"); 343 if (status <= EGPS_DOWN) 344 printf(" state:%s", egp_status_updown[status]); 345 else 346 printf(" [status %d]", status); 347 348 if (ntohs(egp->egp_reason) <= EGPR_UVERSION) 349 printf(" %s", egp_reasons[ntohs(egp->egp_reason)]); 350 else 351 printf(" [reason %d]", ntohs(egp->egp_reason)); 352 break; 353 354 default: 355 printf("[type %d]", type); 356 break; 357 } 358 } 359