/* XXX should probably pass in the snap header and do checks like arp_print() */ void aarp_print(netdissect_options *ndo, const u_char *bp, u_int length) { const struct aarp *ap; #define AT(member) ataddr_string(ndo, (ap->member[1]<<8)|ap->member[2],ap->member[3]) ndo->ndo_protocol = "aarp"; ND_PRINT("aarp "); ap = (const struct aarp *)bp; if (!ND_TTEST_SIZE(ap)) { /* Just bail if we don't have the whole chunk. */ nd_print_trunc(ndo); return; } if (length < sizeof(*ap)) { ND_PRINT(" [|aarp %u]", length); return; } if (EXTRACT_BE_U_2(ap->htype) == 1 && EXTRACT_BE_U_2(ap->ptype) == ETHERTYPE_ATALK && EXTRACT_U_1(ap->halen) == 6 && EXTRACT_U_1(ap->palen) == 4 ) switch (EXTRACT_BE_U_2(ap->op)) { case 1: /* request */ ND_PRINT("who-has %s tell %s", AT(pdaddr), AT(psaddr)); return; case 2: /* response */ ND_PRINT("reply %s is-at %s", AT(psaddr), etheraddr_string(ndo, ap->hsaddr)); return; case 3: /* probe (oy!) */ ND_PRINT("probe %s tell %s", AT(pdaddr), AT(psaddr)); return; } ND_PRINT("len %u op %u htype %u ptype %#x halen %u palen %u", length, EXTRACT_BE_U_2(ap->op), EXTRACT_BE_U_2(ap->htype), EXTRACT_BE_U_2(ap->ptype), EXTRACT_U_1(ap->halen), EXTRACT_U_1(ap->palen)); }
void egp_print(netdissect_options *ndo, const uint8_t *bp, u_int length) { const struct egp_packet *egp; u_int version; u_int type; u_int code; u_int status; ndo->ndo_protocol = "egp"; egp = (const struct egp_packet *)bp; if (length < sizeof(*egp) || !ND_TTEST_SIZE(egp)) { ND_PRINT("[|egp]"); return; } version = EXTRACT_U_1(egp->egp_version); if (!ndo->ndo_vflag) { ND_PRINT("EGPv%u, AS %u, seq %u, length %u", version, EXTRACT_BE_U_2(egp->egp_as), EXTRACT_BE_U_2(egp->egp_sequence), length); return; } else ND_PRINT("EGPv%u, length %u", version, length); if (version != EGP_VERSION) { ND_PRINT("[version %u]", version); return; } type = EXTRACT_U_1(egp->egp_type); code = EXTRACT_U_1(egp->egp_code); status = EXTRACT_U_1(egp->egp_status); switch (type) { case EGPT_ACQUIRE: ND_PRINT(" acquire"); switch (code) { case EGPC_REQUEST: case EGPC_CONFIRM: ND_PRINT(" %s", egp_acquire_codes[code]); switch (status) { case EGPS_UNSPEC: case EGPS_ACTIVE: case EGPS_PASSIVE: ND_PRINT(" %s", egp_acquire_status[status]); break; default: ND_PRINT(" [status %u]", status); break; } ND_PRINT(" hello:%u poll:%u", EXTRACT_BE_U_2(egp->egp_hello), EXTRACT_BE_U_2(egp->egp_poll)); break; case EGPC_REFUSE: case EGPC_CEASE: case EGPC_CEASEACK: ND_PRINT(" %s", egp_acquire_codes[code]); switch (status ) { case EGPS_UNSPEC: case EGPS_NORES: case EGPS_ADMIN: case EGPS_GODOWN: case EGPS_PARAM: case EGPS_PROTO: ND_PRINT(" %s", egp_acquire_status[status]); break; default: ND_PRINT("[status %u]", status); break; } break; default: ND_PRINT("[code %u]", code); break; } break; case EGPT_REACH: switch (code) { case EGPC_HELLO: case EGPC_HEARDU: ND_PRINT(" %s", egp_reach_codes[code]); if (status <= EGPS_DOWN) ND_PRINT(" state:%s", egp_status_updown[status]); else ND_PRINT(" [status %u]", status); break; default: ND_PRINT("[reach code %u]", code); break; } break; case EGPT_POLL: ND_PRINT(" poll"); if (status <= EGPS_DOWN) ND_PRINT(" state:%s", egp_status_updown[status]); else ND_PRINT(" [status %u]", status); ND_PRINT(" net:%s", ipaddr_string(ndo, egp->egp_sourcenet)); break; case EGPT_UPDATE: ND_PRINT(" update"); if (status & EGPS_UNSOL) { status &= ~EGPS_UNSOL; ND_PRINT(" unsolicited"); } if (status <= EGPS_DOWN) ND_PRINT(" state:%s", egp_status_updown[status]); else ND_PRINT(" [status %u]", status); ND_PRINT(" %s int %u ext %u", ipaddr_string(ndo, egp->egp_sourcenet), EXTRACT_U_1(egp->egp_intgw), EXTRACT_U_1(egp->egp_extgw)); if (ndo->ndo_vflag) egpnrprint(ndo, egp, length); break; case EGPT_ERROR: ND_PRINT(" error"); if (status <= EGPS_DOWN) ND_PRINT(" state:%s", egp_status_updown[status]); else ND_PRINT(" [status %u]", status); if (EXTRACT_BE_U_2(egp->egp_reason) <= EGPR_UVERSION) ND_PRINT(" %s", egp_reasons[EXTRACT_BE_U_2(egp->egp_reason)]); else ND_PRINT(" [reason %u]", EXTRACT_BE_U_2(egp->egp_reason)); break; default: ND_PRINT("[type %u]", type); break; } }