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