static int juniper_parse_header (packetbody_t p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) { struct juniper_cookie_table_t *lp = juniper_cookie_table; u_int idx, jnx_ext_len, jnx_header_len = 0; u_int8_t tlv_type,tlv_len; u_int32_t control_word; int tlv_value; packetbody_t tptr; l2info->header_len = 0; l2info->cookie_len = 0; l2info->proto = 0; l2info->length = h->len; l2info->caplen = h->caplen; PACKET_HAS_SPACE_OR_TRUNC(p,4); l2info->flags = p[3]; l2info->direction = p[3]&JUNIPER_BPF_PKT_IN; if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */ printf("no magic-number found!"); return 0; } if (eflag) /* print direction */ printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction)); /* magic number + flags */ jnx_header_len = 4; if (vflag>1) printf("\n\tJuniper PCAP Flags [%s]", bittok2str(jnx_flag_values, "none", l2info->flags)); /* extensions present ? - calculate how much bytes to skip */ if ((l2info->flags & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) { tptr = p+jnx_header_len; /* ok to read extension length ? */ PACKET_HAS_SPACE_OR_TRUNC(tptr, 2); jnx_ext_len = EXTRACT_16BITS(tptr); jnx_header_len += 2; tptr +=2; /* nail up the total length - * just in case something goes wrong * with TLV parsing */ jnx_header_len += jnx_ext_len; if (vflag>1) printf(", PCAP Extension(s) total length %u", jnx_ext_len); PACKET_HAS_SPACE_OR_TRUNC(tptr, jnx_ext_len); while (jnx_ext_len > JUNIPER_EXT_TLV_OVERHEAD) { tlv_type = *(tptr++); tlv_len = *(tptr++); tlv_value = 0; /* sanity check */ if (tlv_type == 0 || tlv_len == 0) break; if (vflag>1) printf("\n\t %s Extension TLV #%u, length %u, value ", tok2str(jnx_ext_tlv_values,"Unknown",tlv_type), tlv_type, tlv_len); tlv_value = juniper_read_tlv_value(tptr, tlv_type, tlv_len); switch (tlv_type) { case JUNIPER_EXT_TLV_IFD_NAME: /* FIXME */ break; case JUNIPER_EXT_TLV_IFD_MEDIATYPE: case JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE: if (tlv_value != -1) { if (vflag>1) printf("%s (%u)", tok2str(juniper_ifmt_values, "Unknown", tlv_value), tlv_value); } break; case JUNIPER_EXT_TLV_IFL_ENCAPS: case JUNIPER_EXT_TLV_TTP_IFL_ENCAPS: if (tlv_value != -1) { if (vflag>1) printf("%s (%u)", tok2str(juniper_ifle_values, "Unknown", tlv_value), tlv_value); } break; case JUNIPER_EXT_TLV_IFL_IDX: /* fall through */ case JUNIPER_EXT_TLV_IFL_UNIT: case JUNIPER_EXT_TLV_IFD_IDX: default: if (tlv_value != -1) { if (vflag>1) printf("%u",tlv_value); } break; } tptr+=tlv_len; jnx_ext_len -= tlv_len+JUNIPER_EXT_TLV_OVERHEAD; } if (vflag>1) printf("\n\t-----original packet-----\n\t"); } if ((l2info->flags & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) { if (eflag) printf("no-L2-hdr, "); /* there is no link-layer present - * perform the v4/v6 heuristics * to figure out what it is */ PACKET_HAS_SPACE_OR_TRUNC(p, (jnx_header_len+4) + 1); if(ip_heuristic_guess(p+jnx_header_len+4,l2info->length-(jnx_header_len+4)) == 0) printf("no IP-hdr found!"); l2info->header_len=jnx_header_len+4; return 0; /* stop parsing the output further */ } l2info->header_len = jnx_header_len; p+=l2info->header_len; l2info->length -= l2info->header_len; l2info->caplen -= l2info->header_len; /* search through the cookie table and copy values matching for our PIC type */ while (lp->s != NULL) { if (lp->pictype == l2info->pictype) { l2info->cookie_len += lp->cookie_len; switch (p[0]) { case LS_COOKIE_ID: l2info->cookie_type = LS_COOKIE_ID; l2info->cookie_len += 2; break; case AS_COOKIE_ID: l2info->cookie_type = AS_COOKIE_ID; l2info->cookie_len = 8; break; default: l2info->bundle = l2info->cookie[0]; break; } #ifdef DLT_JUNIPER_MFR /* MFR child links don't carry cookies */ if (l2info->pictype == DLT_JUNIPER_MFR && (p[0] & MFR_BE_MASK) == MFR_BE_MASK) { l2info->cookie_len = 0; } #endif l2info->header_len += l2info->cookie_len; l2info->length -= l2info->cookie_len; l2info->caplen -= l2info->cookie_len; if (eflag) printf("%s-PIC, cookie-len %u", lp->s, l2info->cookie_len); if (l2info->cookie_len > 0) { PACKET_HAS_SPACE_OR_TRUNC(p,l2info->cookie_len); if (eflag) printf(", cookie 0x"); for (idx = 0; idx < l2info->cookie_len; idx++) { l2info->cookie[idx] = p[idx]; /* copy cookie data */ if (eflag) printf("%02x",p[idx]); } } if (eflag) printf(": "); /* print demarc b/w L2/L3*/ l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len); break; } ++lp; } p+=l2info->cookie_len; /* DLT_ specific parsing */ switch(l2info->pictype) { #ifdef DLT_JUNIPER_MLPPP case DLT_JUNIPER_MLPPP: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(cheri_ptr(&l2info->cookie[6], 2))>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; break; } break; #endif #ifdef DLT_JUNIPER_MLFR case DLT_JUNIPER_MLFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; l2info->proto = EXTRACT_16BITS(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(cheri_ptr(&l2info->cookie[6], 2))>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; } break; #endif #ifdef DLT_JUNIPER_MFR case DLT_JUNIPER_MFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; l2info->proto = EXTRACT_16BITS(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(cheri_ptr(&l2info->cookie[6], 2))>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; break; } break; #endif #ifdef DLT_JUNIPER_ATM2 case DLT_JUNIPER_ATM2: PACKET_HAS_SPACE_OR_TRUNC(p,4); /* ATM cell relay control word present ? */ if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) { control_word = EXTRACT_32BITS(p); /* some control word heuristics */ switch(control_word) { case 0: /* zero control word */ case 0x08000000: /* < JUNOS 7.4 control-word */ case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/ l2info->header_len += 4; break; default: break; } if (eflag) printf("control-word 0x%08x ", control_word); } break; #endif #ifdef DLT_JUNIPER_GGSN case DLT_JUNIPER_GGSN: break; #endif #ifdef DLT_JUNIPER_ATM1 case DLT_JUNIPER_ATM1: break; #endif #ifdef DLT_JUNIPER_PPP case DLT_JUNIPER_PPP: break; #endif #ifdef DLT_JUNIPER_CHDLC case DLT_JUNIPER_CHDLC: break; #endif #ifdef DLT_JUNIPER_ETHER case DLT_JUNIPER_ETHER: break; #endif #ifdef DLT_JUNIPER_FRELAY case DLT_JUNIPER_FRELAY: break; #endif default: printf("Unknown Juniper DLT_ type %u: ", l2info->pictype); break; } if (eflag > 1) printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto); return 1; /* everything went ok so far. continue parsing */ trunc: printf("[|juniper_hdr], length %u",h->len); return 0; }
void ospf_print(register const u_char *bp, register u_int length, register const u_char *bp2) { register const struct ospfhdr *op; register const struct ip *ip; register const u_char *dataend; register const char *cp; op = (struct ospfhdr *)bp; ip = (struct ip *)bp2; /* Print the source and destination address */ (void) printf("%s > %s:", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); /* XXX Before we do anything else, strip off the MD5 trailer */ TCHECK(op->ospf_authtype); if (ntohs(op->ospf_authtype) == OSPF_AUTH_MD5) { length -= OSPF_AUTH_MD5_LEN; snapend -= OSPF_AUTH_MD5_LEN; } /* If the type is valid translate it, or just print the type */ /* value. If it's not valid, say so and return */ TCHECK(op->ospf_type); cp = tok2str(type2str, "type%d", op->ospf_type); printf(" OSPFv%d-%s %d:", op->ospf_version, cp, length); if (*cp == 't') return; TCHECK(op->ospf_len); if (length != ntohs(op->ospf_len)) { printf(" [len %d]", ntohs(op->ospf_len)); return; } dataend = bp + length; /* Print the routerid if it is not the same as the source */ TCHECK(op->ospf_routerid); if (ip->ip_src.s_addr != op->ospf_routerid.s_addr) printf(" rtrid %s", ipaddr_string(&op->ospf_routerid)); TCHECK(op->ospf_areaid); if (op->ospf_areaid.s_addr != 0) printf(" area %s", ipaddr_string(&op->ospf_areaid)); else printf(" backbone"); if (vflag) { /* Print authentication data (should we really do this?) */ TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata)); switch (ntohs(op->ospf_authtype)) { case OSPF_AUTH_NONE: break; case OSPF_AUTH_SIMPLE: printf(" auth \""); (void)fn_printn(op->ospf_authdata, sizeof(op->ospf_authdata), NULL); printf("\""); break; case OSPF_AUTH_MD5: printf(" auth MD5"); break; default: printf(" ??authtype-%d??", ntohs(op->ospf_authtype)); return; } } /* Do rest according to version. */ switch (op->ospf_version) { case 2: /* ospf version 2 */ if (ospf_decode_v2(op, dataend)) goto trunc; break; default: printf(" ospf [version %d]", op->ospf_version); break; } /* end switch on version */ return; trunc: fputs(tstr, stdout); }
void vtp_print (netdissect_options *ndo, const u_char *pptr, u_int length) { int type, len, tlv_len, tlv_value; const u_char *tptr; const struct vtp_vlan_ *vtp_vlan; if (length < VTP_HEADER_LEN) goto trunc; tptr = pptr; if (!ND_TTEST2(*tptr, VTP_HEADER_LEN)) goto trunc; type = *(tptr+1); ND_PRINT((ndo, "VTPv%u, Message %s (0x%02x), length %u", *tptr, tok2str(vtp_message_type_values,"Unknown message type", type), *(tptr+1), length)); /* In non-verbose mode, just print version and message type */ if (ndo->ndo_vflag < 1) { return; } /* verbose mode print all fields */ ND_PRINT((ndo, "\n\tDomain name: %s, %s: %u", (tptr+4), tok2str(vtp_header_values,"Unknown",*(tptr+1)), *(tptr+2))); tptr += VTP_HEADER_LEN; switch (type) { case VTP_SUMMARY_ADV: /* * SUMMARY ADVERTISEMENT * * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Version | Code | Followers | MmgtD Len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Management Domain Name | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Configuration revision number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Updater Identity IP address | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Update Timestamp (12 bytes) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | MD5 digest (16 bytes) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ ND_PRINT((ndo, "\n\t Config Rev %x, Updater %s", EXTRACT_32BITS(tptr), ipaddr_string(tptr+4))); tptr += 8; ND_PRINT((ndo, ", Timestamp 0x%08x 0x%08x 0x%08x", EXTRACT_32BITS(tptr), EXTRACT_32BITS(tptr + 4), EXTRACT_32BITS(tptr + 8))); tptr += VTP_UPDATE_TIMESTAMP_LEN; ND_PRINT((ndo, ", MD5 digest: %08x%08x%08x%08x", EXTRACT_32BITS(tptr), EXTRACT_32BITS(tptr + 4), EXTRACT_32BITS(tptr + 8), EXTRACT_32BITS(tptr + 12))); tptr += VTP_MD5_DIGEST_LEN; break; case VTP_SUBSET_ADV: /* * SUBSET ADVERTISEMENT * * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Version | Code | Seq number | MmgtD Len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Management Domain Name | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Configuration revision number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VLAN info field 1 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ................ | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VLAN info field N | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ ND_PRINT((ndo, ", Config Rev %x", EXTRACT_32BITS(tptr))); /* * VLAN INFORMATION * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | V info len | Status | VLAN type | VLAN name len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | ISL vlan id | MTU size | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | 802.10 index (SAID) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VLAN name | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ tptr += 4; while (tptr < (pptr+length)) { len = *tptr; if (len == 0) break; if (!ND_TTEST2(*tptr, len)) goto trunc; vtp_vlan = (struct vtp_vlan_*)tptr; ND_PRINT((ndo, "\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name %s", tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status), tok2str(vtp_vlan_type_values,"Unknown",vtp_vlan->type), EXTRACT_16BITS(&vtp_vlan->vlanid), EXTRACT_16BITS(&vtp_vlan->mtu), EXTRACT_32BITS(&vtp_vlan->index), (tptr + VTP_VLAN_INFO_OFFSET))); /* * Vlan names are aligned to 32-bit boundaries. */ len -= VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); tptr += VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4); /* TLV information follows */ while (len > 0) { /* * Cisco specs says 2 bytes for type + 2 bytes for length, take only 1 * See: http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm */ type = *tptr; tlv_len = *(tptr+1); ND_PRINT((ndo, "\n\t\t%s (0x%04x) TLV", tok2str(vtp_vlan_tlv_values, "Unknown", type), type)); /* * infinite loop check */ if (type == 0 || tlv_len == 0) { return; } if (!ND_TTEST2(*tptr, tlv_len*2 +2)) goto trunc; tlv_value = EXTRACT_16BITS(tptr+2); switch (type) { case VTP_VLAN_STE_HOP_COUNT: ND_PRINT((ndo, ", %u", tlv_value)); break; case VTP_VLAN_PRUNING: ND_PRINT((ndo, ", %s (%u)", tlv_value == 1 ? "Enabled" : "Disabled", tlv_value)); break; case VTP_VLAN_STP_TYPE: ND_PRINT((ndo, ", %s (%u)", tok2str(vtp_stp_type_values, "Unknown", tlv_value), tlv_value)); break; case VTP_VLAN_BRIDGE_TYPE: ND_PRINT((ndo, ", %s (%u)", tlv_value == 1 ? "SRB" : "SRT", tlv_value)); break; case VTP_VLAN_BACKUP_CRF_MODE: ND_PRINT((ndo, ", %s (%u)", tlv_value == 1 ? "Backup" : "Not backup", tlv_value)); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER: case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER: case VTP_VLAN_PARENT_VLAN: case VTP_VLAN_TRANS_BRIDGED_VLAN: case VTP_VLAN_ARP_HOP_COUNT: default: print_unknown_data(ndo, tptr, "\n\t\t ", 2 + tlv_len*2); break; } len -= 2 + tlv_len*2; tptr += 2 + tlv_len*2; } } break; case VTP_ADV_REQUEST: /* * ADVERTISEMENT REQUEST * * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Version | Code | Reserved | MmgtD Len | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Management Domain Name | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Start value | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ ND_PRINT((ndo, "\n\tStart value: %u", EXTRACT_32BITS(tptr))); break; case VTP_JOIN_MESSAGE: /* FIXME - Could not find message format */ break; default: break; } return; trunc: ND_PRINT((ndo, "[|vtp]")); }
void dtp_print (netdissect_options *ndo, const u_char *pptr, u_int length) { int type, len; const u_char *tptr; if (length < DTP_HEADER_LEN) goto trunc; tptr = pptr; ND_TCHECK2(*tptr, DTP_HEADER_LEN); ND_PRINT((ndo, "DTPv%u, length %u", (*tptr), length)); /* * In non-verbose mode, just print version. */ if (ndo->ndo_vflag < 1) { return; } tptr += DTP_HEADER_LEN; while (tptr < (pptr+length)) { ND_TCHECK2(*tptr, 4); type = EXTRACT_16BITS(tptr); len = EXTRACT_16BITS(tptr+2); /* infinite loop check */ if (type == 0 || len == 0) { return; } ND_PRINT((ndo, "\n\t%s (0x%04x) TLV, length %u", tok2str(dtp_tlv_values, "Unknown", type), type, len)); switch (type) { case DTP_DOMAIN_TLV: ND_PRINT((ndo, ", %s", tptr+4)); break; case DTP_STATUS_TLV: case DTP_DTP_TYPE_TLV: ND_PRINT((ndo, ", 0x%x", *(tptr+4))); break; case DTP_NEIGHBOR_TLV: ND_PRINT((ndo, ", %s", etheraddr_string(ndo, tptr+4))); break; default: break; } tptr += len; } return; trunc: ND_PRINT((ndo, "[|dtp]")); }
static void print_attr_string(netdissect_options *ndo, register u_char *data, u_int length, u_short attr_code) { register u_int i; ND_TCHECK2(data[0],length); switch(attr_code) { case TUNNEL_PASS: if (length < 3) { ND_PRINT((ndo, "%s", tstr)); return; } if (*data && (*data <=0x1F) ) ND_PRINT((ndo, "Tag[%u] ", *data)); else ND_PRINT((ndo, "Tag[Unused] ")); data++; length--; ND_PRINT((ndo, "Salt %u ", EXTRACT_16BITS(data))); data+=2; length-=2; break; case TUNNEL_CLIENT_END: case TUNNEL_SERVER_END: case TUNNEL_PRIV_GROUP: case TUNNEL_ASSIGN_ID: case TUNNEL_CLIENT_AUTH: case TUNNEL_SERVER_AUTH: if (*data <= 0x1F) { if (length < 1) { ND_PRINT((ndo, "%s", tstr)); return; } if (*data) ND_PRINT((ndo, "Tag[%u] ", *data)); else ND_PRINT((ndo, "Tag[Unused] ")); data++; length--; } break; case EGRESS_VLAN_NAME: ND_PRINT((ndo, "%s (0x%02x) ", tok2str(rfc4675_tagged,"Unknown tag",*data), *data)); data++; length--; break; } for (i=0; *data && i < length ; i++, data++) ND_PRINT((ndo, "%c", (*data < 32 || *data > 128) ? '.' : *data)); return; trunc: ND_PRINT((ndo, "%s", tstr)); }
u_int juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p) { struct juniper_l2info_t l2info; struct juniper_ipsec_header { u_int8_t sa_index[2]; u_int8_t ttl; u_int8_t type; u_int8_t spi[4]; u_int8_t src_ip[4]; u_int8_t dst_ip[4]; }; u_int rewrite_len,es_type_bundle; const struct juniper_ipsec_header *ih; l2info.pictype = DLT_JUNIPER_ES; if(juniper_parse_header(p, h, &l2info) == 0) return l2info.header_len; p+=l2info.header_len; ih = (struct juniper_ipsec_header *)p; switch (ih->type) { case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE: case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE: rewrite_len = 0; es_type_bundle = 1; break; case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE: case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE: case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE: rewrite_len = 16; es_type_bundle = 0; default: printf("ES Invalid type %u, length %u", ih->type, l2info.length); return l2info.header_len; } l2info.length-=rewrite_len; p+=rewrite_len; if (eflag) { if (!es_type_bundle) { printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n", EXTRACT_16BITS(&ih->sa_index), ih->ttl, tok2str(juniper_ipsec_type_values,"Unknown",ih->type), ih->type, EXTRACT_32BITS(&ih->spi), ipaddr_string(EXTRACT_32BITS(&ih->src_ip)), ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)), l2info.length); } else { printf("ES SA, index %u, ttl %u type %s (%u), length %u\n", EXTRACT_16BITS(&ih->sa_index), ih->ttl, tok2str(juniper_ipsec_type_values,"Unknown",ih->type), ih->type, l2info.length); } } ip_print(gndo, p, l2info.length); return l2info.header_len; }
static void krb4_print(const u_char *cp) { register const struct krb *kp; u_char type; u_short len; #define PRINT if ((cp = c_print(cp, snapend)) == NULL) goto trunc /* True if struct krb is little endian */ #define IS_LENDIAN(kp) (((kp)->type & 0x01) != 0) #define KTOHSP(kp, cp) (IS_LENDIAN(kp) ? EXTRACT_LE_16BITS(cp) : EXTRACT_16BITS(cp)) kp = (struct krb *)cp; if ((&kp->type) >= snapend) { fputs(tstr, stdout); return; } type = kp->type & (0xFF << 1); printf(" %s %s: ", IS_LENDIAN(kp) ? "le" : "be", tok2str(type2str, NULL, type)); switch (type) { case AUTH_MSG_KDC_REQUEST: if ((cp = krb4_print_hdr(cp)) == NULL) return; cp += 4; /* ctime */ TCHECK(*cp); printf(" %dmin ", *cp++ * 5); PRINT; putchar('.'); PRINT; break; case AUTH_MSG_APPL_REQUEST: cp += 2; TCHECK(*cp); printf("v%d ", *cp++); PRINT; TCHECK(*cp); printf(" (%d)", *cp++); TCHECK(*cp); printf(" (%d)", *cp); break; case AUTH_MSG_KDC_REPLY: if ((cp = krb4_print_hdr(cp)) == NULL) return; cp += 10; /* timestamp + n + exp + kvno */ TCHECK2(*cp, sizeof(short)); len = KTOHSP(kp, cp); printf(" (%d)", len); break; case AUTH_MSG_ERR_REPLY: if ((cp = krb4_print_hdr(cp)) == NULL) return; cp += 4; /* timestamp */ TCHECK2(*cp, sizeof(short)); printf(" %s ", tok2str(kerr2str, NULL, KTOHSP(kp, cp))); cp += 4; PRINT; break; default: fputs("(unknown)", stdout); break; } return; trunc: fputs(tstr, stdout); }
/* * Sub-TLVs consume the "extra data" of Babel TLVs (see Section 4.3 of RFC6126), * their encoding is similar to the encoding of TLVs, but the type namespace is * different: * * o Type 0 stands for Pad1 sub-TLV with the same encoding as the Pad1 TLV. * o Type 1 stands for PadN sub-TLV with the same encoding as the PadN TLV. * o Type 2 stands for Diversity sub-TLV, which propagates diversity routing * data. Its body is a variable-length sequence of 8-bit unsigned integers, * each representing per-hop number of interferring radio channel for the * prefix. Channel 0 is invalid and must not be used in the sub-TLV, channel * 255 interferes with any other channel. * o Type 3 stands for Timestamp sub-TLV, used to compute RTT between * neighbours. In the case of a Hello TLV, the body stores a 32-bits * timestamp, while in the case of a IHU TLV, two 32-bits timestamps are * stored. * * Sub-TLV types 0 and 1 are valid for any TLV type, whether sub-TLV type 2 is * only valid for TLV type 8 (Update). Note that within an Update TLV a missing * Diversity sub-TLV is not the same as a Diversity sub-TLV with an empty body. * The former would mean a lack of any claims about the interference, and the * latter would state that interference is definitely absent. * A type 3 sub-TLV is valid both for Hello and IHU TLVs, though the exact * semantic of the sub-TLV is different in each case. */ static void subtlvs_print(netdissect_options *ndo, const u_char *cp, const u_char *ep, const uint8_t tlv_type) { uint8_t subtype, sublen; const char *sep; uint32_t t1, t2; while (cp < ep) { subtype = *cp++; if(subtype == MESSAGE_SUB_PAD1) { ND_PRINT((ndo, " sub-pad1")); continue; } if(cp == ep) goto corrupt; sublen = *cp++; if(cp + sublen > ep) goto corrupt; switch(subtype) { case MESSAGE_SUB_PADN: ND_PRINT((ndo, " sub-padn")); cp += sublen; break; case MESSAGE_SUB_DIVERSITY: ND_PRINT((ndo, " sub-diversity")); if (sublen == 0) { ND_PRINT((ndo, " empty")); break; } sep = " "; while(sublen--) { ND_PRINT((ndo, "%s%s", sep, tok2str(diversity_str, "%u", *cp++))); sep = "-"; } if(tlv_type != MESSAGE_UPDATE && tlv_type != MESSAGE_UPDATE_SRC_SPECIFIC) ND_PRINT((ndo, " (bogus)")); break; case MESSAGE_SUB_TIMESTAMP: ND_PRINT((ndo, " sub-timestamp")); if(tlv_type == MESSAGE_HELLO) { if(sublen < 4) goto corrupt; t1 = EXTRACT_32BITS(cp); ND_PRINT((ndo, " %s", format_timestamp(t1))); } else if(tlv_type == MESSAGE_IHU) { if(sublen < 8) goto corrupt; t1 = EXTRACT_32BITS(cp); ND_PRINT((ndo, " %s", format_timestamp(t1))); t2 = EXTRACT_32BITS(cp + 4); ND_PRINT((ndo, "|%s", format_timestamp(t2))); } else ND_PRINT((ndo, " (bogus)")); cp += sublen; break; default: ND_PRINT((ndo, " sub-unknown-0x%02x", subtype)); cp += sublen; } /* switch */ } /* while */ return; corrupt: ND_PRINT((ndo, " (corrupt)")); }
/* * Print a single PDU. */ static void rpki_rtr_pdu_print (const u_char *tptr, u_int indent) { const rpki_rtr_pdu *pdu_header; u_int pdu_type, pdu_len, hexdump; const u_char *msg; pdu_header = (rpki_rtr_pdu *)tptr; pdu_type = pdu_header->pdu_type; pdu_len = EXTRACT_32BITS(pdu_header->length); hexdump = FALSE; printf("%sRPKI-RTRv%u, %s PDU (%u), length: %u", indent_string(8), pdu_header->version, tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type), pdu_type, pdu_len); switch (pdu_type) { /* * The following PDUs share the message format. */ case RPKI_RTR_SERIAL_NOTIFY_PDU: case RPKI_RTR_SERIAL_QUERY_PDU: case RPKI_RTR_END_OF_DATA_PDU: msg = (const u_char *)(pdu_header + 1); printf("%sCache-Nonce: 0x%04x, Serial: %u", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.cache_nonce), EXTRACT_32BITS(msg)); break; /* * The following PDUs share the message format. */ case RPKI_RTR_RESET_QUERY_PDU: case RPKI_RTR_CACHE_RESET_PDU: /* * Zero payload PDUs. */ break; case RPKI_RTR_CACHE_RESPONSE_PDU: printf("%sCache-Nonce: 0x%04x", indent_string(indent+2), EXTRACT_16BITS(pdu_header->u.cache_nonce)); break; case RPKI_RTR_IPV4_PREFIX_PDU: { rpki_rtr_pdu_ipv4_prefix *pdu; pdu = (rpki_rtr_pdu_ipv4_prefix *)tptr; printf("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ipaddr_string(pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags); } break; #ifdef INET6 case RPKI_RTR_IPV6_PREFIX_PDU: { rpki_rtr_pdu_ipv6_prefix *pdu; pdu = (rpki_rtr_pdu_ipv6_prefix *)tptr; printf("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), ip6addr_string(pdu->prefix), pdu->prefix_length, pdu->max_length, EXTRACT_32BITS(pdu->as), pdu->flags); } break; #endif case RPKI_RTR_ERROR_REPORT_PDU: { rpki_rtr_pdu_error_report *pdu; u_int encapsulated_pdu_length, text_length, tlen, error_code; u_char buf[80]; pdu = (rpki_rtr_pdu_error_report *)tptr; encapsulated_pdu_length = EXTRACT_32BITS(pdu->encapsulated_pdu_length); tlen = pdu_len; error_code = EXTRACT_16BITS(pdu->pdu_header.u.error_code); printf("%sError code: %s (%u), Encapsulated PDU length: %u", indent_string(indent+2), tok2str(rpki_rtr_error_codes, "Unknown", error_code), error_code, encapsulated_pdu_length); tptr += sizeof(*pdu); tlen -= sizeof(*pdu); /* * Recurse if there is an encapsulated PDU. */ if (encapsulated_pdu_length && (encapsulated_pdu_length <= tlen)) { printf("%s-----encapsulated PDU-----", indent_string(indent+4)); rpki_rtr_pdu_print(tptr, indent+2); } tptr += encapsulated_pdu_length; tlen -= encapsulated_pdu_length; /* * Extract, trail-zero and print the Error message. */ text_length = 0; if (tlen > 4) { text_length = EXTRACT_32BITS(tptr); tptr += 4; tlen -= 4; } if (text_length && (text_length <= tlen )) { memcpy(buf, tptr, MIN(sizeof(buf)-1, text_length)); buf[text_length] = '\0'; printf("%sError text: %s", indent_string(indent+2), buf); } } break; default: /* * Unknown data, please hexdump. */ hexdump = TRUE; } /* do we also want to see a hex dump ? */ if (vflag > 1 || (vflag && hexdump)) { print_unknown_data(tptr,"\n\t ", pdu_len); } }
/* * Print bootp requests */ void bootp_print(netdissect_options *ndo, register const u_char *cp, u_int length) { register const struct bootp *bp; static const u_char vm_cmu[4] = VM_CMU; static const u_char vm_rfc1048[4] = VM_RFC1048; bp = (const struct bootp *)cp; ND_TCHECK(bp->bp_op); ND_PRINT((ndo, "BOOTP/DHCP, %s", tok2str(bootp_op_values, "unknown (0x%02x)", bp->bp_op))); if (bp->bp_htype == 1 && bp->bp_hlen == 6 && bp->bp_op == BOOTPREQUEST) { ND_TCHECK2(bp->bp_chaddr[0], 6); ND_PRINT((ndo, " from %s", etheraddr_string(ndo, bp->bp_chaddr))); } ND_PRINT((ndo, ", length %u", length)); if (!ndo->ndo_vflag) return; ND_TCHECK(bp->bp_secs); /* The usual hardware address type is 1 (10Mb Ethernet) */ if (bp->bp_htype != 1) ND_PRINT((ndo, ", htype %d", bp->bp_htype)); /* The usual length for 10Mb Ethernet address is 6 bytes */ if (bp->bp_htype != 1 || bp->bp_hlen != 6) ND_PRINT((ndo, ", hlen %d", bp->bp_hlen)); /* Only print interesting fields */ if (bp->bp_hops) ND_PRINT((ndo, ", hops %d", bp->bp_hops)); if (EXTRACT_32BITS(&bp->bp_xid)) ND_PRINT((ndo, ", xid 0x%x", EXTRACT_32BITS(&bp->bp_xid))); if (EXTRACT_16BITS(&bp->bp_secs)) ND_PRINT((ndo, ", secs %d", EXTRACT_16BITS(&bp->bp_secs))); ND_PRINT((ndo, ", Flags [%s]", bittok2str(bootp_flag_values, "none", EXTRACT_16BITS(&bp->bp_flags)))); if (ndo->ndo_vflag > 1) ND_PRINT((ndo, " (0x%04x)", EXTRACT_16BITS(&bp->bp_flags))); /* Client's ip address */ ND_TCHECK(bp->bp_ciaddr); if (EXTRACT_32BITS(&bp->bp_ciaddr.s_addr)) ND_PRINT((ndo, "\n\t Client-IP %s", ipaddr_string(ndo, &bp->bp_ciaddr))); /* 'your' ip address (bootp client) */ ND_TCHECK(bp->bp_yiaddr); if (EXTRACT_32BITS(&bp->bp_yiaddr.s_addr)) ND_PRINT((ndo, "\n\t Your-IP %s", ipaddr_string(ndo, &bp->bp_yiaddr))); /* Server's ip address */ ND_TCHECK(bp->bp_siaddr); if (EXTRACT_32BITS(&bp->bp_siaddr.s_addr)) ND_PRINT((ndo, "\n\t Server-IP %s", ipaddr_string(ndo, &bp->bp_siaddr))); /* Gateway's ip address */ ND_TCHECK(bp->bp_giaddr); if (EXTRACT_32BITS(&bp->bp_giaddr.s_addr)) ND_PRINT((ndo, "\n\t Gateway-IP %s", ipaddr_string(ndo, &bp->bp_giaddr))); /* Client's Ethernet address */ if (bp->bp_htype == 1 && bp->bp_hlen == 6) { ND_TCHECK2(bp->bp_chaddr[0], 6); ND_PRINT((ndo, "\n\t Client-Ethernet-Address %s", etheraddr_string(ndo, bp->bp_chaddr))); } ND_TCHECK2(bp->bp_sname[0], 1); /* check first char only */ if (*bp->bp_sname) { ND_PRINT((ndo, "\n\t sname \"")); if (fn_print(ndo, bp->bp_sname, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); ND_PRINT((ndo, "%s", tstr + 1)); return; } ND_PRINT((ndo, "\"")); } ND_TCHECK2(bp->bp_file[0], 1); /* check first char only */ if (*bp->bp_file) { ND_PRINT((ndo, "\n\t file \"")); if (fn_print(ndo, bp->bp_file, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); ND_PRINT((ndo, "%s", tstr + 1)); return; } ND_PRINT((ndo, "\"")); } /* Decode the vendor buffer */ ND_TCHECK(bp->bp_vend[0]); if (memcmp((const char *)bp->bp_vend, vm_rfc1048, sizeof(uint32_t)) == 0) rfc1048_print(ndo, bp->bp_vend); else if (memcmp((const char *)bp->bp_vend, vm_cmu, sizeof(uint32_t)) == 0) cmu_print(ndo, bp->bp_vend); else { uint32_t ul; ul = EXTRACT_32BITS(&bp->bp_vend); if (ul != 0) ND_PRINT((ndo, "\n\t Vendor-#0x%x", ul)); } return; trunc: ND_PRINT((ndo, "%s", tstr)); }
static void rfc1048_print(netdissect_options *ndo, register const u_char *bp) { register uint16_t tag; register u_int len; register const char *cp; register char c; int first, idx; uint32_t ul; uint16_t us; uint8_t uc, subopt, suboptlen; ND_PRINT((ndo, "\n\t Vendor-rfc1048 Extensions")); /* Step over magic cookie */ ND_PRINT((ndo, "\n\t Magic Cookie 0x%08x", EXTRACT_32BITS(bp))); bp += sizeof(int32_t); /* Loop while we there is a tag left in the buffer */ while (ND_TTEST2(*bp, 1)) { tag = *bp++; if (tag == TAG_PAD && ndo->ndo_vflag < 3) continue; if (tag == TAG_END && ndo->ndo_vflag < 3) return; if (tag == TAG_EXTENDED_OPTION) { ND_TCHECK2(*(bp + 1), 2); tag = EXTRACT_16BITS(bp + 1); /* XXX we don't know yet if the IANA will * preclude overlap of 1-byte and 2-byte spaces. * If not, we need to offset tag after this step. */ cp = tok2str(xtag2str, "?xT%u", tag); } else cp = tok2str(tag2str, "?T%u", tag); c = *cp++; if (tag == TAG_PAD || tag == TAG_END) len = 0; else { /* Get the length; check for truncation */ ND_TCHECK2(*bp, 1); len = *bp++; } ND_PRINT((ndo, "\n\t %s Option %u, length %u%s", cp, tag, len, len > 0 ? ": " : "")); if (tag == TAG_PAD && ndo->ndo_vflag > 2) { u_int ntag = 1; while (ND_TTEST2(*bp, 1) && *bp == TAG_PAD) { bp++; ntag++; } if (ntag > 1) ND_PRINT((ndo, ", occurs %u", ntag)); } if (!ND_TTEST2(*bp, len)) { ND_PRINT((ndo, "[|rfc1048 %u]", len)); return; } if (tag == TAG_DHCP_MESSAGE && len == 1) { uc = *bp++; ND_PRINT((ndo, "%s", tok2str(dhcp_msg_values, "Unknown (%u)", uc))); continue; } if (tag == TAG_PARM_REQUEST) { idx = 0; while (len-- > 0) { uc = *bp++; cp = tok2str(tag2str, "?Option %u", uc); if (idx % 4 == 0) ND_PRINT((ndo, "\n\t ")); else ND_PRINT((ndo, ", ")); ND_PRINT((ndo, "%s", cp + 1)); idx++; } continue; } if (tag == TAG_EXTENDED_REQUEST) { first = 1; while (len > 1) { len -= 2; us = EXTRACT_16BITS(bp); bp += 2; cp = tok2str(xtag2str, "?xT%u", us); if (!first) ND_PRINT((ndo, "+")); ND_PRINT((ndo, "%s", cp + 1)); first = 0; } continue; } /* Print data */ if (c == '?') { /* Base default formats for unknown tags on data size */ if (len & 1) c = 'b'; else if (len & 2) c = 's'; else c = 'l'; } first = 1; switch (c) { case 'a': /* ascii strings */ ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, len, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); bp += len; len = 0; break; case 'i': case 'l': case 'L': /* ip addresses/32-bit words */ while (len >= sizeof(ul)) { if (!first) ND_PRINT((ndo, ",")); ul = EXTRACT_32BITS(bp); if (c == 'i') { ul = htonl(ul); ND_PRINT((ndo, "%s", ipaddr_string(ndo, &ul))); } else if (c == 'L') ND_PRINT((ndo, "%d", ul)); else ND_PRINT((ndo, "%u", ul)); bp += sizeof(ul); len -= sizeof(ul); first = 0; } break; case 'p': /* IP address pairs */ while (len >= 2*sizeof(ul)) { if (!first) ND_PRINT((ndo, ",")); memcpy((char *)&ul, (const char *)bp, sizeof(ul)); ND_PRINT((ndo, "(%s:", ipaddr_string(ndo, &ul))); bp += sizeof(ul); memcpy((char *)&ul, (const char *)bp, sizeof(ul)); ND_PRINT((ndo, "%s)", ipaddr_string(ndo, &ul))); bp += sizeof(ul); len -= 2*sizeof(ul); first = 0; } break; case 's': /* shorts */ while (len >= sizeof(us)) { if (!first) ND_PRINT((ndo, ",")); us = EXTRACT_16BITS(bp); ND_PRINT((ndo, "%u", us)); bp += sizeof(us); len -= sizeof(us); first = 0; } break; case 'B': /* boolean */ while (len > 0) { if (!first) ND_PRINT((ndo, ",")); switch (*bp) { case 0: ND_PRINT((ndo, "N")); break; case 1: ND_PRINT((ndo, "Y")); break; default: ND_PRINT((ndo, "%u?", *bp)); break; } ++bp; --len; first = 0; } break; case 'b': case 'x': default: /* Bytes */ while (len > 0) { if (!first) ND_PRINT((ndo, c == 'x' ? ":" : ".")); if (c == 'x') ND_PRINT((ndo, "%02x", *bp)); else ND_PRINT((ndo, "%u", *bp)); ++bp; --len; first = 0; } break; case '$': /* Guys we can't handle with one of the usual cases */ switch (tag) { case TAG_NETBIOS_NODE: /* this option should be at least 1 byte long */ if (len < 1) { ND_PRINT((ndo, "ERROR: length < 1 bytes")); break; } tag = *bp++; --len; ND_PRINT((ndo, "%s", tok2str(nbo2str, NULL, tag))); break; case TAG_OPT_OVERLOAD: /* this option should be at least 1 byte long */ if (len < 1) { ND_PRINT((ndo, "ERROR: length < 1 bytes")); break; } tag = *bp++; --len; ND_PRINT((ndo, "%s", tok2str(oo2str, NULL, tag))); break; case TAG_CLIENT_FQDN: /* this option should be at least 3 bytes long */ if (len < 3) { ND_PRINT((ndo, "ERROR: length < 3 bytes")); bp += len; len = 0; break; } if (*bp) ND_PRINT((ndo, "[%s] ", client_fqdn_flags(*bp))); bp++; if (*bp || *(bp+1)) ND_PRINT((ndo, "%u/%u ", *bp, *(bp+1))); bp += 2; ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, len - 3, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); bp += len - 3; len = 0; break; case TAG_CLIENT_ID: { int type; /* this option should be at least 1 byte long */ if (len < 1) { ND_PRINT((ndo, "ERROR: length < 1 bytes")); break; } type = *bp++; len--; if (type == 0) { ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, len, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); bp += len; len = 0; break; } else { ND_PRINT((ndo, "%s ", tok2str(arp2str, "hardware-type %u,", type))); while (len > 0) { if (!first) ND_PRINT((ndo, ":")); ND_PRINT((ndo, "%02x", *bp)); ++bp; --len; first = 0; } } break; } case TAG_AGENT_CIRCUIT: while (len >= 2) { subopt = *bp++; suboptlen = *bp++; len -= 2; if (suboptlen > len) { ND_PRINT((ndo, "\n\t %s SubOption %u, length %u: length goes past end of option", tok2str(agent_suboption_values, "Unknown", subopt), subopt, suboptlen)); bp += len; len = 0; break; } ND_PRINT((ndo, "\n\t %s SubOption %u, length %u: ", tok2str(agent_suboption_values, "Unknown", subopt), subopt, suboptlen)); switch (subopt) { case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */ case AGENT_SUBOPTION_REMOTE_ID: case AGENT_SUBOPTION_SUBSCRIBER_ID: if (fn_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) goto trunc; break; default: print_unknown_data(ndo, bp, "\n\t\t", suboptlen); } len -= suboptlen; bp += suboptlen; } break; case TAG_CLASSLESS_STATIC_RT: case TAG_CLASSLESS_STA_RT_MS: { u_int mask_width, significant_octets, i; /* this option should be at least 5 bytes long */ if (len < 5) { ND_PRINT((ndo, "ERROR: length < 5 bytes")); bp += len; len = 0; break; } while (len > 0) { if (!first) ND_PRINT((ndo, ",")); mask_width = *bp++; len--; /* mask_width <= 32 */ if (mask_width > 32) { ND_PRINT((ndo, "[ERROR: Mask width (%d) > 32]", mask_width)); bp += len; len = 0; break; } significant_octets = (mask_width + 7) / 8; /* significant octets + router(4) */ if (len < significant_octets + 4) { ND_PRINT((ndo, "[ERROR: Remaining length (%u) < %u bytes]", len, significant_octets + 4)); bp += len; len = 0; break; } ND_PRINT((ndo, "(")); if (mask_width == 0) ND_PRINT((ndo, "default")); else { for (i = 0; i < significant_octets ; i++) { if (i > 0) ND_PRINT((ndo, ".")); ND_PRINT((ndo, "%d", *bp++)); } for (i = significant_octets ; i < 4 ; i++) ND_PRINT((ndo, ".0")); ND_PRINT((ndo, "/%d", mask_width)); } memcpy((char *)&ul, (const char *)bp, sizeof(ul)); ND_PRINT((ndo, ":%s)", ipaddr_string(ndo, &ul))); bp += sizeof(ul); len -= (significant_octets + 4); first = 0; } break; } case TAG_USER_CLASS: { u_int suboptnumber = 1; first = 1; if (len < 2) { ND_PRINT((ndo, "ERROR: length < 2 bytes")); bp += len; len = 0; break; } while (len > 0) { suboptlen = *bp++; len--; ND_PRINT((ndo, "\n\t ")); ND_PRINT((ndo, "instance#%u: ", suboptnumber)); if (suboptlen == 0) { ND_PRINT((ndo, "ERROR: suboption length must be non-zero")); bp += len; len = 0; break; } if (len < suboptlen) { ND_PRINT((ndo, "ERROR: invalid option")); bp += len; len = 0; break; } ND_PRINT((ndo, "\"")); if (fn_printn(ndo, bp, suboptlen, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); ND_PRINT((ndo, ", length %d", suboptlen)); suboptnumber++; len -= suboptlen; bp += suboptlen; } break; } default: ND_PRINT((ndo, "[unknown special tag %u, size %u]", tag, len)); bp += len; len = 0; break; } break; } /* Data left over? */ if (len) { ND_PRINT((ndo, "\n\t trailing data length %u", len)); bp += len; } } return; trunc: ND_PRINT((ndo, "|[rfc1048]")); }
static int pdatacnt_print(netdissect_options *ndo, register const u_char * pptr, register u_int len, u_int16_t IDcnt, u_int16_t op_msk, int indent) { u_int i; u_int32_t id; char *ib = indent_pr(indent, 0); if ((op_msk & B_APPND) && ndo->ndo_vflag >= 3) { ND_PRINT((ndo, "%sTABLE APPEND\n", ib)); } for (i = 0; i < IDcnt; i++) { ND_TCHECK2(*pptr, 4); if (len < 4) goto trunc; id = EXTRACT_32BITS(pptr); if (ndo->ndo_vflag >= 3) ND_PRINT((ndo, "%sID#%02u: %d\n", ib, i + 1, id)); len -= 4; pptr += 4; } if ((op_msk & B_TRNG) || (op_msk & B_KEYIN)) { if (op_msk & B_TRNG) { u_int32_t starti, endi; if (len < PTH_DESC_SIZE) { ND_PRINT((ndo, "pathlength %d with key/range too short %d\n", len, PTH_DESC_SIZE)); return -1; } pptr += sizeof(struct forces_tlv); len -= sizeof(struct forces_tlv); starti = EXTRACT_32BITS(pptr); pptr += 4; len -= 4; endi = EXTRACT_32BITS(pptr); pptr += 4; len -= 4; if (ndo->ndo_vflag >= 3) ND_PRINT((ndo, "%sTable range: [%d,%d]\n", ib, starti, endi)); } if (op_msk & B_KEYIN) { struct forces_tlv *keytlv; u_int16_t tll; if (len < PTH_DESC_SIZE) { ND_PRINT((ndo, "pathlength %d with key/range too short %d\n", len, PTH_DESC_SIZE)); return -1; } /* skip keyid */ pptr += 4; len -= 4; keytlv = (struct forces_tlv *)pptr; /* skip header */ pptr += sizeof(struct forces_tlv); len -= sizeof(struct forces_tlv); /* skip key content */ tll = EXTRACT_16BITS(&keytlv->length); if (tll < TLV_HDRL) { ND_PRINT((ndo, "key content length %u < %u\n", tll, TLV_HDRL)); return -1; } tll -= TLV_HDRL; if (len < tll) { ND_PRINT((ndo, "key content too short\n")); return -1; } pptr += tll; len -= tll; } } if (len) { const struct forces_tlv *pdtlv = (struct forces_tlv *)pptr; u_int16_t type; u_int16_t tll; int pad = 0; u_int aln; u_int invtlv; ND_TCHECK(*pdtlv); type = EXTRACT_16BITS(&pdtlv->type); invtlv = tlv_valid(pdtlv, len); if (invtlv) { ND_PRINT((ndo, "%s Outstanding bytes %d for TLV type 0x%x TLV len %d\n", tok2str(ForCES_TLV_err, NULL, invtlv), len, type, EXTRACT_16BITS(&pdtlv->length))); goto pd_err; } /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ tll = EXTRACT_16BITS(&pdtlv->length) - TLV_HDRL; aln = F_ALN_LEN(EXTRACT_16BITS(&pdtlv->length)); if (aln > EXTRACT_16BITS(&pdtlv->length)) { if (aln > len) { ND_PRINT((ndo, "Invalid padded pathdata TLV type 0x%x len %d missing %d pad bytes\n", type, EXTRACT_16BITS(&pdtlv->length), aln - len)); } else { pad = aln - EXTRACT_16BITS(&pdtlv->length); } } if (pd_valid(type)) { const struct pdata_ops *ops = get_forces_pd(type); if (ndo->ndo_vflag >= 3 && ops->v != F_TLV_PDAT) { if (pad) ND_PRINT((ndo, "%s %s (Length %d DataLen %d pad %d Bytes)\n", ib, ops->s, EXTRACT_16BITS(&pdtlv->length), tll, pad)); else ND_PRINT((ndo, "%s %s (Length %d DataLen %d Bytes)\n", ib, ops->s, EXTRACT_16BITS(&pdtlv->length), tll)); } chk_op_type(ndo, type, op_msk, ops->op_msk); if (ops->print(ndo, (const u_char *)pdtlv, tll + pad + TLV_HDRL, op_msk, indent + 2) == -1) return -1; len -= (TLV_HDRL + pad + tll); } else { ND_PRINT((ndo, "Invalid path data content type 0x%x len %d\n", type, EXTRACT_16BITS(&pdtlv->length))); pd_err: if (EXTRACT_16BITS(&pdtlv->length)) { hex_print_with_offset(ndo, "Bad Data val\n\t [", pptr, len, 0); ND_PRINT((ndo, "]\n")); return -1; } } } return len; trunc: ND_PRINT((ndo, "%s", tstr)); return -1; }
int ether_encap_print(u_short ether_type, const u_char *p, u_int length, u_int caplen, u_short *extracted_ether_type) { recurse: *extracted_ether_type = ether_type; switch (ether_type) { /* case ETHERTYPE_DN: decnet_print(p, length, caplen); return (1); case ETHERTYPE_ATALK: if (ArgusParser->vflag) sprintf(&ArgusBuf[strlen(ArgusBuf)],"et1 "); atalk_print(p, length); return (1); case ETHERTYPE_AARP: aarp_print(p, length); return (1); case ETHERTYPE_IPX: sprintf(&ArgusBuf[strlen(ArgusBuf)],"(NOV-ETHII) "); ipx_print(p, length); return (1); case ETHERTYPE_8021Q: if (ArgusParser->eflag) sprintf(&ArgusBuf[strlen(ArgusBuf)],"vlan %u, p %u%s, ", ntohs(*(u_int16_t *)p) & 0xfff, ntohs(*(u_int16_t *)p) >> 13, (ntohs(*(u_int16_t *)p) & 0x1000) ? ", CFI" : ""); ether_type = ntohs(*(u_int16_t *)(p + 2)); p += 4; length -= 4; caplen -= 4; if (ether_type > ETHERMTU) { if (ArgusParser->eflag) sprintf(&ArgusBuf[strlen(ArgusBuf)],"ethertype %s, ", tok2str(ethertype_values,"0x%04x", ether_type)); goto recurse; } *extracted_ether_type = 0; if (llc_print(p, length, caplen, p - 18, p - 12, extracted_ether_type) == 0) { ether_hdr_print(p - 18, length + 4); } if (!suppress_default_print) default_print(p - 18, caplen + 4); return (1); */ case ETHERTYPE_JUMBO: ether_type = ntohs(*(u_int16_t *)(p)); p += 2; length -= 2; caplen -= 2; if (ether_type > ETHERMTU) { if (ArgusParser->eflag) sprintf(&ArgusBuf[strlen(ArgusBuf)],"ethertype %s, ", tok2str(ethertype_values,"0x%04x", ether_type)); goto recurse; } *extracted_ether_type = 0; /* if (llc_print(p, length, caplen, p - 16, p - 10, extracted_ether_type) == 0) { ether_hdr_print(p - 16, length + 2); } if (!suppress_default_print) default_print(p - 16, caplen + 2); */ return (1); case ETHERTYPE_ISO: isoclns_print(p+1, length-1, length-1); return(1); /* case ETHERTYPE_PPPOED: case ETHERTYPE_PPPOES: pppoe_print(p, length); return (1); case ETHERTYPE_EAPOL: eap_print(gndo, p, length); return (1); case ETHERTYPE_PPP: if (length) { sprintf(&ArgusBuf[strlen(ArgusBuf)],": "); ppp_print(p, length); } return (1); case ETHERTYPE_SLOW: slow_print(p, length); return (1); case ETHERTYPE_LOOPBACK: return (1); case ETHERTYPE_MPLS: case ETHERTYPE_MPLS_MULTI: mpls_print(p, length); return (1); case ETHERTYPE_LAT: case ETHERTYPE_SCA: case ETHERTYPE_MOPRC: case ETHERTYPE_MOPDL: */ /* default_print for now */ default: return (0); } }
void tcp_print(netdissect_options *ndo, const u_char *bp, u_int length, const u_char *bp2, int fragmented) { const struct tcphdr *tp; const struct ip *ip; u_char flags; u_int hlen; char ch; uint16_t sport, dport, win, urp; uint32_t seq, ack, thseq, thack; u_int utoval; uint16_t magic; int rev; const struct ip6_hdr *ip6; ndo->ndo_protocol = "tcp"; tp = (const struct tcphdr *)bp; ip = (const struct ip *)bp2; if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; ch = '\0'; if (!ND_TTEST_2(tp->th_dport)) { if (ip6) { ND_PRINT("%s > %s:", ip6addr_string(ndo, ip6->ip6_src), ip6addr_string(ndo, ip6->ip6_dst)); } else { ND_PRINT("%s > %s:", ipaddr_string(ndo, ip->ip_src), ipaddr_string(ndo, ip->ip_dst)); } nd_print_trunc(ndo); return; } sport = GET_BE_U_2(tp->th_sport); dport = GET_BE_U_2(tp->th_dport); if (ip6) { if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) { ND_PRINT("%s.%s > %s.%s: ", ip6addr_string(ndo, ip6->ip6_src), tcpport_string(ndo, sport), ip6addr_string(ndo, ip6->ip6_dst), tcpport_string(ndo, dport)); } else { ND_PRINT("%s > %s: ", tcpport_string(ndo, sport), tcpport_string(ndo, dport)); } } else { if (GET_U_1(ip->ip_p) == IPPROTO_TCP) { ND_PRINT("%s.%s > %s.%s: ", ipaddr_string(ndo, ip->ip_src), tcpport_string(ndo, sport), ipaddr_string(ndo, ip->ip_dst), tcpport_string(ndo, dport)); } else { ND_PRINT("%s > %s: ", tcpport_string(ndo, sport), tcpport_string(ndo, dport)); } } ND_TCHECK_SIZE(tp); hlen = TH_OFF(tp) * 4; if (hlen < sizeof(*tp)) { ND_PRINT(" tcp %u [bad hdr length %u - too short, < %lu]", length - hlen, hlen, (unsigned long)sizeof(*tp)); return; } seq = GET_BE_U_4(tp->th_seq); ack = GET_BE_U_4(tp->th_ack); win = GET_BE_U_2(tp->th_win); urp = GET_BE_U_2(tp->th_urp); if (ndo->ndo_qflag) { ND_PRINT("tcp %u", length - hlen); if (hlen > length) { ND_PRINT(" [bad hdr length %u - too long, > %u]", hlen, length); } return; } flags = GET_U_1(tp->th_flags); ND_PRINT("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); if (!ndo->ndo_Sflag && (flags & TH_ACK)) { /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ rev = 0; if (ip6) { struct tcp_seq_hash6 *th; struct tcp_seq_hash6 *tcp_seq_hash; const void *src, *dst; struct tha6 tha; tcp_seq_hash = tcp_seq_hash6; src = (const void *)ip6->ip6_src; dst = (const void *)ip6->ip6_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(src, dst, sizeof(ip6->ip6_dst)) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, dst, sizeof(ip6->ip6_dst)); UNALIGNED_MEMCPY(&tha.dst, src, sizeof(ip6->ip6_src)); tha.port = ((u_int)dport) << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, dst, sizeof(ip6->ip6_dst)); UNALIGNED_MEMCPY(&tha.src, src, sizeof(ip6->ip6_src)); tha.port = ((u_int)sport) << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ /* calloc() return used by the 'tcp_seq_hash6' hash table: do not free() */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash6 *) calloc(1, sizeof(*th)); if (th->nxt == NULL) (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } else { struct tcp_seq_hash *th; struct tcp_seq_hash *tcp_seq_hash; struct tha tha; tcp_seq_hash = tcp_seq_hash4; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(ip->ip_src, ip->ip_dst, sizeof(ip->ip_dst)) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, ip->ip_dst, sizeof(ip->ip_dst)); UNALIGNED_MEMCPY(&tha.dst, ip->ip_src, sizeof(ip->ip_src)); tha.port = ((u_int)dport) << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, ip->ip_dst, sizeof(ip->ip_dst)); UNALIGNED_MEMCPY(&tha.src, ip->ip_src, sizeof(ip->ip_src)); tha.port = ((u_int)sport) << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ /* calloc() return used by the 'tcp_seq_hash4' hash table: do not free() */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } } else { /*fool gcc*/ thseq = thack = rev = 0; } if (hlen > length) { ND_PRINT(" [bad hdr length %u - too long, > %u]", hlen, length); return; } if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) { /* Check the checksum, if possible. */ uint16_t sum, tcp_sum; if (IP_V(ip) == 4) { if (ND_TTEST_LEN(tp->th_sport, length)) { sum = tcp_cksum(ndo, ip, tp, length); tcp_sum = GET_BE_U_2(tp->th_sum); ND_PRINT(", cksum 0x%04x", tcp_sum); if (sum != 0) ND_PRINT(" (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum)); else ND_PRINT(" (correct)"); } } else if (IP_V(ip) == 6 && ip6->ip6_plen) { if (ND_TTEST_LEN(tp->th_sport, length)) { sum = tcp6_cksum(ndo, ip6, tp, length); tcp_sum = GET_BE_U_2(tp->th_sum); ND_PRINT(", cksum 0x%04x", tcp_sum); if (sum != 0) ND_PRINT(" (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum)); else ND_PRINT(" (correct)"); } } } length -= hlen; if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { ND_PRINT(", seq %u", seq); if (length > 0) { ND_PRINT(":%u", seq + length); } } if (flags & TH_ACK) { ND_PRINT(", ack %u", ack); } ND_PRINT(", win %u", win); if (flags & TH_URG) ND_PRINT(", urg %u", urp); /* * Handle any options. */ if (hlen > sizeof(*tp)) { const u_char *cp; u_int i, opt, datalen; u_int len; hlen -= sizeof(*tp); cp = (const u_char *)tp + sizeof(*tp); ND_PRINT(", options ["); while (hlen > 0) { if (ch != '\0') ND_PRINT("%c", ch); ND_TCHECK_1(cp); opt = GET_U_1(cp); cp++; if (ZEROLENOPT(opt)) len = 1; else { ND_TCHECK_1(cp); len = GET_U_1(cp); cp++; /* total including type, len */ if (len < 2 || len > hlen) goto bad; --hlen; /* account for length byte */ } --hlen; /* account for type byte */ datalen = 0; /* Bail if "l" bytes of data are not left or were not captured */ #define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK_LEN(cp, l); } ND_PRINT("%s", tok2str(tcp_option_values, "unknown-%u", opt)); switch (opt) { case TCPOPT_MAXSEG: datalen = 2; LENCHECK(datalen); ND_PRINT(" %u", GET_BE_U_2(cp)); break; case TCPOPT_WSCALE: datalen = 1; LENCHECK(datalen); ND_PRINT(" %u", GET_U_1(cp)); break; case TCPOPT_SACK: datalen = len - 2; if (datalen % 8 != 0) { ND_PRINT(" invalid sack"); } else { uint32_t s, e; ND_PRINT(" %u ", datalen / 8); for (i = 0; i < datalen; i += 8) { LENCHECK(i + 4); s = GET_BE_U_4(cp + i); LENCHECK(i + 8); e = GET_BE_U_4(cp + i + 4); if (rev) { s -= thseq; e -= thseq; } else { s -= thack; e -= thack; } ND_PRINT("{%u:%u}", s, e); } } break; case TCPOPT_CC: case TCPOPT_CCNEW: case TCPOPT_CCECHO: case TCPOPT_ECHO: case TCPOPT_ECHOREPLY: /* * those options share their semantics. * fall through */ datalen = 4; LENCHECK(datalen); ND_PRINT(" %u", GET_BE_U_4(cp)); break; case TCPOPT_TIMESTAMP: datalen = 8; LENCHECK(datalen); ND_PRINT(" val %u ecr %u", GET_BE_U_4(cp), GET_BE_U_4(cp + 4)); break; case TCPOPT_SIGNATURE: datalen = TCP_SIGLEN; LENCHECK(datalen); ND_PRINT(" "); #ifdef HAVE_LIBCRYPTO switch (tcp_verify_signature(ndo, ip, tp, bp + TH_OFF(tp) * 4, length, cp)) { case SIGNATURE_VALID: ND_PRINT("valid"); break; case SIGNATURE_INVALID: nd_print_invalid(ndo); break; case CANT_CHECK_SIGNATURE: ND_PRINT("can't check - "); for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); break; } #else for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); #endif break; case TCPOPT_SCPS: datalen = 2; LENCHECK(datalen); ND_PRINT(" cap %02x id %u", GET_U_1(cp), GET_U_1(cp + 1)); break; case TCPOPT_TCPAO: datalen = len - 2; /* RFC 5925 Section 2.2: * "The Length value MUST be greater than or equal to 4." * (This includes the Kind and Length fields already processed * at this point.) */ if (datalen < 2) { nd_print_invalid(ndo); } else { LENCHECK(1); ND_PRINT(" keyid %u", GET_U_1(cp)); LENCHECK(2); ND_PRINT(" rnextkeyid %u", GET_U_1(cp + 1)); if (datalen > 2) { ND_PRINT(" mac 0x"); for (i = 2; i < datalen; i++) { LENCHECK(i + 1); ND_PRINT("%02x", GET_U_1(cp + i)); } } } break; case TCPOPT_EOL: case TCPOPT_NOP: case TCPOPT_SACKOK: /* * Nothing interesting. * fall through */ break; case TCPOPT_UTO: datalen = 2; LENCHECK(datalen); utoval = GET_BE_U_2(cp); ND_PRINT(" 0x%x", utoval); if (utoval & 0x0001) utoval = (utoval >> 1) * 60; else utoval >>= 1; ND_PRINT(" %u", utoval); break; case TCPOPT_MPTCP: datalen = len - 2; LENCHECK(datalen); if (!mptcp_print(ndo, cp-2, len, flags)) goto bad; break; case TCPOPT_FASTOPEN: datalen = len - 2; LENCHECK(datalen); ND_PRINT(" "); print_tcp_fastopen_option(ndo, cp, datalen, FALSE); break; case TCPOPT_EXPERIMENT2: datalen = len - 2; LENCHECK(datalen); if (datalen < 2) goto bad; /* RFC6994 */ magic = GET_BE_U_2(cp); ND_PRINT("-"); switch(magic) { case 0xf989: /* TCP Fast Open RFC 7413 */ print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE); break; default: /* Unknown magic number */ ND_PRINT("%04x", magic); break; } break; default: datalen = len - 2; if (datalen) ND_PRINT(" 0x"); for (i = 0; i < datalen; ++i) { LENCHECK(i + 1); ND_PRINT("%02x", GET_U_1(cp + i)); } break; } /* Account for data printed */ cp += datalen; hlen -= datalen; /* Check specification against observed length */ ++datalen; /* option octet */ if (!ZEROLENOPT(opt)) ++datalen; /* size octet */ if (datalen != len) ND_PRINT("[len %u]", len); ch = ','; if (opt == TCPOPT_EOL) break; } ND_PRINT("]"); }
void mldv2_report_print(const u_char *bp, u_int len) { struct icmp6_hdr *icp = (struct icmp6_hdr *) bp; u_int group, nsrcs, ngroups; u_int i, j; if (len < MLDV2_REPORT_MINLEN) { printf(" [invalid len %d]", len); return; } TCHECK(icp->icmp6_data16[1]); ngroups = ntohs(icp->icmp6_data16[1]); printf(", %d group record(s)", ngroups); if (vflag > 0) { /* Print the group records */ group = MLDV2_REPORT_GROUP0; for (i = 0; i < ngroups; i++) { /* type(1) + auxlen(1) + numsrc(2) + grp(16) */ if (len < group + MLDV2_REPORT_MINGRPLEN) { printf(" [invalid number of groups]"); return; } TCHECK2(bp[group + MLDV2_RGROUP_MADDR], sizeof(struct in6_addr)); printf(" [gaddr %s", ip6addr_string(&bp[group + MLDV2_RGROUP_MADDR])); printf(" %s", tok2str(mldv2report2str, " [v2-report-#%d]", bp[group])); nsrcs = (bp[group + MLDV2_RGROUP_NSRCS] << 8) + bp[group + MLDV2_RGROUP_NSRCS + 1]; /* Check the number of sources and print them */ if (len < group + MLDV2_REPORT_MINGRPLEN + (nsrcs * sizeof(struct in6_addr))) { printf(" [invalid number of sources %d]", nsrcs); return; } if (vflag == 1) printf(", %d source(s)", nsrcs); else { /* Print the sources */ (void)printf(" {"); for (j = 0; j < nsrcs; j++) { TCHECK2(bp[group + MLDV2_REPORT_MINGRPLEN + j * sizeof(struct in6_addr)], sizeof(struct in6_addr)); printf(" %s", ip6addr_string(&bp[group + MLDV2_REPORT_MINGRPLEN + j * sizeof(struct in6_addr)])); } (void)printf(" }"); } /* Next group record */ group += MLDV2_REPORT_MINGRPLEN + nsrcs * sizeof(struct in6_addr); printf("]"); } } return; trunc: (void)printf("[|icmp6]"); return; }
static void atmarp_print(netdissect_options *ndo, const u_char *bp, u_int length, u_int caplen) { const struct atmarp_pkthdr *ap; u_short pro, hrd, op; ap = (const struct atmarp_pkthdr *)bp; ND_TCHECK(*ap); hrd = ATMHRD(ap); pro = ATMPRO(ap); op = ATMOP(ap); if (!ND_TTEST2(*aar_tpa(ap), ATMTPROTO_LEN(ap))) { ND_PRINT((ndo, "[|ARP]")); ND_DEFAULTPRINT((const u_char *)ap, length); return; } if (!ndo->ndo_eflag) { ND_PRINT((ndo, "ARP, ")); } if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) || ATMSPROTO_LEN(ap) != 4 || ATMTPROTO_LEN(ap) != 4 || ndo->ndo_vflag) { ND_PRINT((ndo, "%s, %s (len %u/%u)", tok2str(arphrd_values, "Unknown Hardware (%u)", hrd), tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro), ATMSPROTO_LEN(ap), ATMTPROTO_LEN(ap))); /* don't know know about the address formats */ if (!ndo->ndo_vflag) { goto out; } } /* print operation */ printf("%s%s ", ndo->ndo_vflag ? ", " : "", tok2str(arpop_values, "Unknown (%u)", op)); switch (op) { case ARPOP_REQUEST: ND_PRINT((ndo, "who-has %s", ipaddr_string(ATMTPA(ap)))); if (ATMTHRD_LEN(ap) != 0) { ND_PRINT((ndo, " (")); atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap), ATMTSLN(ap)); ND_PRINT((ndo, ")")); } ND_PRINT((ndo, "tell %s", ipaddr_string(ATMSPA(ap)))); break; case ARPOP_REPLY: ND_PRINT((ndo, "%s is-at ", ipaddr_string(ATMSPA(ap)))); atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), ATMSSLN(ap)); break; case ARPOP_INVREQUEST: ND_PRINT((ndo, "who-is ")); atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap), ATMTSLN(ap)); ND_PRINT((ndo, " tell ")); atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), ATMSSLN(ap)); break; case ARPOP_INVREPLY: atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap), ATMSSLN(ap)); ND_PRINT((ndo, "at %s", ipaddr_string(ATMSPA(ap)))); break; case ARPOP_NAK: ND_PRINT((ndo, "for %s", ipaddr_string(ATMSPA(ap)))); break; default: ND_DEFAULTPRINT((const u_char *)ap, caplen); return; } out: ND_PRINT((ndo, ", length %u", length)); return; trunc: ND_PRINT((ndo, "[|ARP]")); }
/* * Print trivial file transfer program requests */ void tftp_print(register const u_char *bp, u_int length) { register const struct tftphdr *tp; register const char *cp; register const u_char *p; register int opcode, i; static char tstr[] = " [|tftp]"; tp = (const struct tftphdr *)bp; /* Print length */ printf(" %d", length); /* Print tftp request type */ TCHECK(tp->th_opcode); opcode = EXTRACT_16BITS(&tp->th_opcode); cp = tok2str(op2str, "tftp-#%d", opcode); printf(" %s", cp); /* Bail if bogus opcode */ if (*cp == 't') return; switch (opcode) { case RRQ: case WRQ: case OACK: /* * XXX Not all arpa/tftp.h's specify th_stuff as any * array; use address of th_block instead */ #ifdef notdef p = (u_char *)tp->th_stuff; #else p = (u_char *)&tp->th_block; #endif putchar(' '); /* Print filename or first option */ if (opcode != OACK) putchar('"'); i = fn_print(p, snapend); if (opcode != OACK) putchar('"'); /* Print the mode (RRQ and WRQ only) and any options */ while ((p = (const u_char *)strchr((const char *)p, '\0')) != NULL) { if (length <= (u_int)(p - (const u_char *)&tp->th_block)) break; p++; if (*p != '\0') { putchar(' '); fn_print(p, snapend); } } if (i) goto trunc; break; case ACK: case DATA: TCHECK(tp->th_block); printf(" block %d", EXTRACT_16BITS(&tp->th_block)); break; case ERROR: /* Print error code string */ TCHECK(tp->th_code); printf(" %s \"", tok2str(err2str, "tftp-err-#%d \"", EXTRACT_16BITS(&tp->th_code))); /* Print error message string */ i = fn_print((const u_char *)tp->th_data, snapend); putchar('"'); if (i) goto trunc; break; default: /* We shouldn't get here */ printf("(unknown #%d)", opcode); break; } return; trunc: fputs(tstr, stdout); return; }
void arp_print(netdissect_options *ndo, const u_char *bp, u_int length, u_int caplen) { const struct arp_pkthdr *ap; u_short pro, hrd, op, linkaddr; ap = (const struct arp_pkthdr *)bp; ND_TCHECK(*ap); hrd = HRD(ap); pro = PRO(ap); op = OP(ap); /* if its ATM then call the ATM ARP printer for Frame-relay ARP most of the fields are similar to Ethernet so overload the Ethernet Printer and set the linkaddr type for linkaddr_string() accordingly */ switch(hrd) { case ARPHRD_ATM2225: atmarp_print(ndo, bp, length, caplen); return; case ARPHRD_FRELAY: linkaddr = LINKADDR_FRELAY; break; default: linkaddr = LINKADDR_ETHER; break; } if (!ND_TTEST2(*ar_tpa(ap), PROTO_LEN(ap))) { ND_PRINT((ndo, "[|ARP]")); ND_DEFAULTPRINT((const u_char *)ap, length); return; } if (!ndo->ndo_eflag) { ND_PRINT((ndo, "ARP, ")); } /* print hardware type/len and proto type/len */ if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) || PROTO_LEN(ap) != 4 || HRD_LEN(ap) == 0 || ndo->ndo_vflag) { ND_PRINT((ndo, "%s (len %u), %s (len %u)", tok2str(arphrd_values, "Unknown Hardware (%u)", hrd), HRD_LEN(ap), tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro), PROTO_LEN(ap))); /* don't know know about the address formats */ if (!ndo->ndo_vflag) { goto out; } } /* print operation */ printf("%s%s ", ndo->ndo_vflag ? ", " : "", tok2str(arpop_values, "Unknown (%u)", op)); switch (op) { case ARPOP_REQUEST: ND_PRINT((ndo, "who-has %s", ipaddr_string(TPA(ap)))); if (memcmp((const char *)ezero, (const char *)THA(ap), HRD_LEN(ap)) != 0) ND_PRINT((ndo, " (%s)", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)))); ND_PRINT((ndo, " tell %s", ipaddr_string(SPA(ap)))); break; case ARPOP_REPLY: ND_PRINT((ndo, "%s is-at %s", ipaddr_string(SPA(ap)), linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap)))); break; case ARPOP_REVREQUEST: ND_PRINT((ndo, "who-is %s tell %s", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap)))); break; case ARPOP_REVREPLY: ND_PRINT((ndo, "%s at %s", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), ipaddr_string(TPA(ap)))); break; case ARPOP_INVREQUEST: ND_PRINT((ndo, "who-is %s tell %s", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap)))); break; case ARPOP_INVREPLY: ND_PRINT((ndo,"%s at %s", linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)), ipaddr_string(TPA(ap)))); break; default: ND_DEFAULTPRINT((const u_char *)ap, caplen); return; } out: ND_PRINT((ndo, ", length %u", length)); return; trunc: ND_PRINT((ndo, "[|ARP]")); }
static int juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) { struct juniper_cookie_table_t *lp = juniper_cookie_table; u_int idx, offset; #ifdef DLT_JUNIPER_ATM2 u_int32_t control_word; #endif l2info->header_len = 0; l2info->cookie_len = 0; l2info->proto = 0; l2info->length = h->len; l2info->caplen = h->caplen; l2info->direction = p[3]&JUNIPER_BPF_PKT_IN; TCHECK2(p[0],4); if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */ printf("no magic-number found!"); return 0; } if (eflag) /* print direction */ printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction)); /* extensions present ? - calculate how much bytes to skip */ if ((p[3] & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) { offset = 6 + EXTRACT_16BITS(p+4); if (eflag>1) printf("ext-len %u, ",EXTRACT_16BITS(p+4)); } else offset = 4; if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) { if (eflag) printf("no-L2-hdr, "); /* there is no link-layer present - * perform the v4/v6 heuristics * to figure out what it is */ TCHECK2(p[offset+4],1); if(ip_heuristic_guess(p+offset+4,l2info->length-(offset+4)) == 0) printf("no IP-hdr found!"); l2info->header_len=offset+4; return 0; /* stop parsing the output further */ } l2info->header_len = offset; p+=l2info->header_len; l2info->length -= l2info->header_len; l2info->caplen -= l2info->header_len; /* search through the cookie table and copy values matching for our PIC type */ while (lp->s != NULL) { if (lp->pictype == l2info->pictype) { l2info->cookie_len += lp->cookie_len; switch (p[0]) { case LS_COOKIE_ID: l2info->cookie_type = LS_COOKIE_ID; l2info->cookie_len += 2; break; case AS_COOKIE_ID: l2info->cookie_type = AS_COOKIE_ID; l2info->cookie_len = 8; break; default: l2info->bundle = l2info->cookie[0]; break; } #ifdef DLT_JUNIPER_MFR /* MFR child links don't carry cookies */ if (l2info->pictype == DLT_JUNIPER_MFR && (p[0] & MFR_BE_MASK) == MFR_BE_MASK) { l2info->cookie_len = 0; } #endif l2info->header_len += l2info->cookie_len; l2info->length -= l2info->cookie_len; l2info->caplen -= l2info->cookie_len; if (eflag) printf("%s-PIC, cookie-len %u", lp->s, l2info->cookie_len); if (l2info->cookie_len > 0) { TCHECK2(p[0],l2info->cookie_len); if (eflag) printf(", cookie 0x"); for (idx = 0; idx < l2info->cookie_len; idx++) { l2info->cookie[idx] = p[idx]; /* copy cookie data */ if (eflag) printf("%02x",p[idx]); } } if (eflag) printf(": "); /* print demarc b/w L2/L3*/ l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len); break; } ++lp; } p+=l2info->cookie_len; /* DLT_ specific parsing */ switch(l2info->pictype) { #ifdef DLT_JUNIPER_MLPPP case DLT_JUNIPER_MLPPP: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; break; } break; #endif #ifdef DLT_JUNIPER_MLFR case DLT_JUNIPER_MLFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; l2info->proto = EXTRACT_16BITS(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; } break; #endif #ifdef DLT_JUNIPER_MFR case DLT_JUNIPER_MFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; l2info->proto = EXTRACT_16BITS(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; break; } break; #endif #ifdef DLT_JUNIPER_ATM2 case DLT_JUNIPER_ATM2: TCHECK2(p[0],4); /* ATM cell relay control word present ? */ if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) { control_word = EXTRACT_32BITS(p); /* some control word heuristics */ switch(control_word) { case 0: /* zero control word */ case 0x08000000: /* < JUNOS 7.4 control-word */ case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/ l2info->header_len += 4; break; default: break; } if (eflag) printf("control-word 0x%08x ", control_word); } break; #endif #ifdef DLT_JUNIPER_ATM1 case DLT_JUNIPER_ATM1: break; #endif #ifdef DLT_JUNIPER_PPP case DLT_JUNIPER_PPP: break; #endif #ifdef DLT_JUNIPER_CHDLC case DLT_JUNIPER_CHDLC: break; #endif #ifdef DLT_JUNIPER_ETHER case DLT_JUNIPER_ETHER: break; #endif #ifdef DLT_JUNIPER_FRELAY case DLT_JUNIPER_FRELAY: break; #endif default: printf("Unknown Juniper DLT_ type %u: ", l2info->pictype); break; } if (eflag > 1) printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto); return 1; /* everything went ok so far. continue parsing */ trunc: printf("[|juniper_hdr], length %u",h->len); return 0; }
static int ldp_tlv_print(netdissect_options *ndo, const u_char *tptr, u_short msg_tlen) { struct ldp_tlv_header { nd_uint16_t type; nd_uint16_t length; }; const struct ldp_tlv_header *ldp_tlv_header; u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; u_char fec_type; u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx; char buf[100]; int i; ldp_tlv_header = (const struct ldp_tlv_header *)tptr; ND_TCHECK_SIZE(ldp_tlv_header); tlv_len=EXTRACT_BE_U_2(ldp_tlv_header->length); if (tlv_len + 4 > msg_tlen) { ND_PRINT("\n\t\t TLV contents go past end of message"); return 0; } tlv_tlen=tlv_len; tlv_type=LDP_MASK_TLV_TYPE(EXTRACT_BE_U_2(ldp_tlv_header->type)); /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", tok2str(ldp_tlv_values, "Unknown", tlv_type), tlv_type, tlv_len, LDP_MASK_U_BIT(EXTRACT_BE_U_2(ldp_tlv_header->type)) ? "continue processing" : "ignore", LDP_MASK_F_BIT(EXTRACT_BE_U_2(ldp_tlv_header->type)) ? "do" : "don't"); tptr+=sizeof(struct ldp_tlv_header); switch(tlv_type) { case LDP_TLV_COMMON_HELLO: TLV_TCHECK(4); ND_PRINT("\n\t Hold Time: %us, Flags: [%s Hello%s]", EXTRACT_BE_U_2(tptr), (EXTRACT_BE_U_2(tptr + 2)&0x8000) ? "Targeted" : "Link", (EXTRACT_BE_U_2(tptr + 2)&0x4000) ? ", Request for targeted Hellos" : ""); break; case LDP_TLV_IPV4_TRANSPORT_ADDR: TLV_TCHECK(4); ND_PRINT("\n\t IPv4 Transport Address: %s", ipaddr_string(ndo, tptr)); break; case LDP_TLV_IPV6_TRANSPORT_ADDR: TLV_TCHECK(16); ND_PRINT("\n\t IPv6 Transport Address: %s", ip6addr_string(ndo, tptr)); break; case LDP_TLV_CONFIG_SEQ_NUMBER: TLV_TCHECK(4); ND_PRINT("\n\t Sequence Number: %u", EXTRACT_BE_U_4(tptr)); break; case LDP_TLV_ADDRESS_LIST: TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); af = EXTRACT_BE_U_2(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; ND_PRINT("\n\t Address Family: %s, addresses", tok2str(af_values, "Unknown (%u)", af)); switch (af) { case AFNUM_INET: while(tlv_tlen >= sizeof(struct in_addr)) { ND_TCHECK_LEN(tptr, sizeof(struct in_addr)); ND_PRINT(" %s", ipaddr_string(ndo, tptr)); tlv_tlen-=sizeof(struct in_addr); tptr+=sizeof(struct in_addr); } break; case AFNUM_INET6: while(tlv_tlen >= sizeof(struct in6_addr)) { ND_TCHECK_LEN(tptr, sizeof(struct in6_addr)); ND_PRINT(" %s", ip6addr_string(ndo, tptr)); tlv_tlen-=sizeof(struct in6_addr); tptr+=sizeof(struct in6_addr); } break; default: /* unknown AF */ break; } break; case LDP_TLV_COMMON_SESSION: TLV_TCHECK(8); ND_PRINT("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", EXTRACT_BE_U_2(tptr), EXTRACT_BE_U_2(tptr + 2), (EXTRACT_BE_U_2(tptr + 6)&0x8000) ? "On Demand" : "Unsolicited", (EXTRACT_BE_U_2(tptr + 6)&0x4000) ? "Enabled" : "Disabled" ); break; case LDP_TLV_FEC: TLV_TCHECK(1); fec_type = EXTRACT_U_1(tptr); ND_PRINT("\n\t %s FEC (0x%02x)", tok2str(ldp_fec_values, "Unknown", fec_type), fec_type); tptr+=1; tlv_tlen-=1; switch(fec_type) { case LDP_FEC_WILDCARD: break; case LDP_FEC_PREFIX: TLV_TCHECK(2); af = EXTRACT_BE_U_2(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen-=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; if (af == AFNUM_INET) { i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) ND_PRINT(": IPv4 prefix (invalid length)"); else ND_PRINT(": IPv4 prefix %s", buf); } else if (af == AFNUM_INET6) { i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) ND_PRINT(": IPv6 prefix (invalid length)"); else ND_PRINT(": IPv6 prefix %s", buf); } else ND_PRINT(": Address family %u prefix", af); break; case LDP_FEC_HOSTADDRESS: break; case LDP_FEC_MARTINI_VC: /* * We assume the type was supposed to be one of the MPLS * Pseudowire Types. */ TLV_TCHECK(7); vc_info_len = EXTRACT_U_1(tptr + 2); /* * According to RFC 4908, the VC info Length field can be zero, * in which case not only are there no interface parameters, * there's no VC ID. */ if (vc_info_len == 0) { ND_PRINT(": %s, %scontrol word, group-ID %u, VC-info-length: %u", tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff), EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ", EXTRACT_BE_U_4(tptr + 3), vc_info_len); break; } /* Make sure we have the VC ID as well */ TLV_TCHECK(11); ND_PRINT(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", tok2str(mpls_pw_types_values, "Unknown", EXTRACT_BE_U_2(tptr)&0x7fff), EXTRACT_BE_U_2(tptr)&0x8000 ? "" : "no ", EXTRACT_BE_U_4(tptr + 3), EXTRACT_BE_U_4(tptr + 7), vc_info_len); if (vc_info_len < 4) { /* minimum 4, for the VC ID */ ND_PRINT(" (invalid, < 4"); return(tlv_len+4); /* Type & Length fields not included */ } vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */ /* Skip past the fixed information and the VC ID */ tptr+=11; tlv_tlen-=11; TLV_TCHECK(vc_info_len); while (vc_info_len > 2) { vc_info_tlv_type = EXTRACT_U_1(tptr); vc_info_tlv_len = EXTRACT_U_1(tptr + 1); if (vc_info_tlv_len < 2) break; if (vc_info_len < vc_info_tlv_len) break; ND_PRINT("\n\t\tInterface Parameter: %s (0x%02x), len %u", tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type), vc_info_tlv_type, vc_info_tlv_len); switch(vc_info_tlv_type) { case LDP_FEC_MARTINI_IFPARM_MTU: ND_PRINT(": %u", EXTRACT_BE_U_2(tptr + 2)); break; case LDP_FEC_MARTINI_IFPARM_DESC: ND_PRINT(": "); for (idx = 2; idx < vc_info_tlv_len; idx++) safeputchar(ndo, EXTRACT_U_1(tptr + idx)); break; case LDP_FEC_MARTINI_IFPARM_VCCV: ND_PRINT("\n\t\t Control Channels (0x%02x) = [%s]", EXTRACT_U_1((tptr + 2)), bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", EXTRACT_U_1((tptr + 2)))); ND_PRINT("\n\t\t CV Types (0x%02x) = [%s]", EXTRACT_U_1((tptr + 3)), bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", EXTRACT_U_1((tptr + 3)))); break; default: print_unknown_data(ndo, tptr+2, "\n\t\t ", vc_info_tlv_len-2); break; } vc_info_len -= vc_info_tlv_len; tptr += vc_info_tlv_len; } break; } break; case LDP_TLV_GENERIC_LABEL: TLV_TCHECK(4); ND_PRINT("\n\t Label: %u", EXTRACT_BE_U_4(tptr) & 0xfffff); break; case LDP_TLV_STATUS: TLV_TCHECK(8); ui = EXTRACT_BE_U_4(tptr); tptr+=4; ND_PRINT("\n\t Status: 0x%02x, Flags: [%s and %s forward]", ui&0x3fffffff, ui&0x80000000 ? "Fatal error" : "Advisory Notification", ui&0x40000000 ? "do" : "don't"); ui = EXTRACT_BE_U_4(tptr); tptr+=4; if (ui) ND_PRINT(", causing Message ID: 0x%08x", ui); break; case LDP_TLV_FT_SESSION: TLV_TCHECK(8); ft_flags = EXTRACT_BE_U_2(tptr); ND_PRINT("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", ft_flags&0x8000 ? "" : "No ", ft_flags&0x8 ? "" : "Don't ", ft_flags&0x4 ? "" : "No ", ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", ft_flags&0x1 ? "" : "Don't "); tptr+=4; ui = EXTRACT_BE_U_4(tptr); if (ui) ND_PRINT(", Reconnect Timeout: %ums", ui); tptr+=4; ui = EXTRACT_BE_U_4(tptr); if (ui) ND_PRINT(", Recovery Time: %ums", ui); break; case LDP_TLV_MTU: TLV_TCHECK(2); ND_PRINT("\n\t MTU: %u", EXTRACT_BE_U_2(tptr)); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case LDP_TLV_HOP_COUNT: case LDP_TLV_PATH_VECTOR: case LDP_TLV_ATM_LABEL: case LDP_TLV_FR_LABEL: case LDP_TLV_EXTD_STATUS: case LDP_TLV_RETURNED_PDU: case LDP_TLV_RETURNED_MSG: case LDP_TLV_ATM_SESSION_PARM: case LDP_TLV_FR_SESSION_PARM: case LDP_TLV_LABEL_REQUEST_MSG_ID: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tptr, "\n\t ", tlv_tlen); break; } return(tlv_len+4); /* Type & Length fields not included */ trunc: ND_PRINT("\n\t\t packet exceeded snapshot"); return 0; badtlv: ND_PRINT("\n\t\t TLV contents go past end of TLV"); return(tlv_len+4); /* Type & Length fields not included */ }
void tcp_print(register const u_char *bp, register u_int length, register const u_char *bp2, int fragmented) { register const struct tcphdr *tp; register const struct ip *ip; register u_char flags; register u_int hlen; register char ch; u_int16_t sport, dport, win, urp; u_int32_t seq, ack, thseq, thack; u_int utoval; int threv; #ifdef INET6 register const struct ip6_hdr *ip6; #endif tp = (struct tcphdr *)bp; ip = (struct ip *)bp2; #ifdef INET6 if (IP_V(ip) == 6) ip6 = (struct ip6_hdr *)bp2; else ip6 = NULL; #endif /*INET6*/ ch = '\0'; if (!TTEST(tp->th_dport)) { (void)printf("%s > %s: [|tcp]", ipaddr_string(&ip->ip_src), ipaddr_string(&ip->ip_dst)); return; } sport = EXTRACT_16BITS(&tp->th_sport); dport = EXTRACT_16BITS(&tp->th_dport); hlen = TH_OFF(tp) * 4; /* * If data present, header length valid, and NFS port used, * assume NFS. * Pass offset of data plus 4 bytes for RPC TCP msg length * to NFS print routines. */ if (!qflag && hlen >= sizeof(*tp) && hlen <= length && (length - hlen) >= 4) { u_char *fraglenp; u_int32_t fraglen; register struct sunrpc_msg *rp; enum sunrpc_msg_type direction; fraglenp = (u_char *)tp + hlen; if (TTEST2(*fraglenp, 4)) { fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF; if (fraglen > (length - hlen) - 4) fraglen = (length - hlen) - 4; rp = (struct sunrpc_msg *)(fraglenp + 4); if (TTEST(rp->rm_direction)) { direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction); if (dport == NFS_PORT && direction == SUNRPC_CALL) { nfsreq_print((u_char *)rp, fraglen, (u_char *)ip); return; } if (sport == NFS_PORT && direction == SUNRPC_REPLY) { nfsreply_print((u_char *)rp, fraglen, (u_char *)ip); return; } } } } #ifdef INET6 if (ip6) { if (ip6->ip6_nxt == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ip6addr_string(&ip6->ip6_src), tcpport_string(sport), ip6addr_string(&ip6->ip6_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } else #endif /*INET6*/ { if (ip->ip_p == IPPROTO_TCP) { (void)printf("%s.%s > %s.%s: ", ipaddr_string(&ip->ip_src), tcpport_string(sport), ipaddr_string(&ip->ip_dst), tcpport_string(dport)); } else { (void)printf("%s > %s: ", tcpport_string(sport), tcpport_string(dport)); } } if (hlen < sizeof(*tp)) { (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]", length - hlen, hlen, (unsigned long)sizeof(*tp)); return; } TCHECK(*tp); seq = EXTRACT_32BITS(&tp->th_seq); ack = EXTRACT_32BITS(&tp->th_ack); win = EXTRACT_16BITS(&tp->th_win); urp = EXTRACT_16BITS(&tp->th_urp); if (qflag) { (void)printf("tcp %d", length - hlen); if (hlen > length) { (void)printf(" [bad hdr length %u - too long, > %u]", hlen, length); } return; } flags = tp->th_flags; printf("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); if (!Sflag && (flags & TH_ACK)) { register struct tcp_seq_hash *th; const void *src, *dst; register int rev; struct tha tha; /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ #ifdef INET6 rev = 0; if (ip6) { src = &ip6->ip6_src; dst = &ip6->ip6_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0) rev = 1; } if (rev) { memcpy(&tha.src, dst, sizeof ip6->ip6_dst); memcpy(&tha.dst, src, sizeof ip6->ip6_src); tha.port = dport << 16 | sport; } else { memcpy(&tha.dst, dst, sizeof ip6->ip6_dst); memcpy(&tha.src, src, sizeof ip6->ip6_src); tha.port = sport << 16 | dport; } } else { /* * Zero out the tha structure; the src and dst * fields are big enough to hold an IPv6 * address, but we only have IPv4 addresses * and thus must clear out the remaining 124 * bits. * * XXX - should we just clear those bytes after * copying the IPv4 addresses, rather than * zeroing out the entire structure and then * overwriting some of the zeroes? * * XXX - this could fail if we see TCP packets * with an IPv6 address with the lower 124 bits * all zero and also see TCP packes with an * IPv4 address with the same 32 bits as the * upper 32 bits of the IPv6 address in question. * Can that happen? Is it likely enough to be * an issue? */ memset(&tha, 0, sizeof(tha)); src = &ip->ip_src; dst = &ip->ip_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (memcmp(src, dst, sizeof ip->ip_dst) > 0) rev = 1; } if (rev) { memcpy(&tha.src, dst, sizeof ip->ip_dst); memcpy(&tha.dst, src, sizeof ip->ip_src); tha.port = dport << 16 | sport; } else { memcpy(&tha.dst, dst, sizeof ip->ip_dst); memcpy(&tha.src, src, sizeof ip->ip_src); tha.port = sport << 16 | dport; } } #else rev = 0; src = &ip->ip_src; dst = &ip->ip_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (memcmp(src, dst, sizeof ip->ip_dst) > 0) rev = 1; } if (rev) { memcpy(&tha.src, dst, sizeof ip->ip_dst); memcpy(&tha.dst, src, sizeof ip->ip_src); tha.port = dport << 16 | sport; } else { memcpy(&tha.dst, dst, sizeof ip->ip_dst); memcpy(&tha.src, src, sizeof ip->ip_src); tha.port = sport << 16 | dport; } #endif threv = rev; for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) error("tcp_print: calloc"); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } else { /*fool gcc*/ thseq = thack = threv = 0; } if (hlen > length) { (void)printf(" [bad hdr length %u - too long, > %u]", hlen, length); return; } if (IP_V(ip) == 4 && vflag && !Kflag && !fragmented) { u_int16_t sum, tcp_sum; if (TTEST2(tp->th_sport, length)) { sum = tcp_cksum(ip, tp, length); (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" (correct)"); } } #ifdef INET6 if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !Kflag && !fragmented) { u_int16_t sum,tcp_sum; if (TTEST2(tp->th_sport, length)) { sum = nextproto6_cksum(ip6, (u_short *)tp, length, IPPROTO_TCP); (void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum)); if (sum != 0) { tcp_sum = EXTRACT_16BITS(&tp->th_sum); (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum)); } else (void)printf(" (correct)"); } } #endif length -= hlen; if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { (void)printf(", seq %u", seq); if (length > 0) { (void)printf(":%u", seq + length); } } if (flags & TH_ACK) { (void)printf(", ack %u", ack); } (void)printf(", win %d", win); if (flags & TH_URG) (void)printf(", urg %d", urp); /* * Handle any options. */ if (hlen > sizeof(*tp)) { register const u_char *cp; register u_int i, opt, datalen; register u_int len; hlen -= sizeof(*tp); cp = (const u_char *)tp + sizeof(*tp); printf(", options ["); while (hlen > 0) { if (ch != '\0') putchar(ch); TCHECK(*cp); opt = *cp++; if (ZEROLENOPT(opt)) len = 1; else { TCHECK(*cp); len = *cp++; /* total including type, len */ if (len < 2 || len > hlen) goto bad; --hlen; /* account for length byte */ } --hlen; /* account for type byte */ datalen = 0; /* Bail if "l" bytes of data are not left or were not captured */ #define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); } printf("%s", tok2str(tcp_option_values, "Unknown Option %u", opt)); switch (opt) { case TCPOPT_MAXSEG: datalen = 2; LENCHECK(datalen); (void)printf(" %u", EXTRACT_16BITS(cp)); break; case TCPOPT_WSCALE: datalen = 1; LENCHECK(datalen); (void)printf(" %u", *cp); break; case TCPOPT_SACK: datalen = len - 2; if (datalen % 8 != 0) { (void)printf("malformed sack"); } else { u_int32_t s, e; (void)printf(" %d ", datalen / 8); for (i = 0; i < datalen; i += 8) { LENCHECK(i + 4); s = EXTRACT_32BITS(cp + i); LENCHECK(i + 8); e = EXTRACT_32BITS(cp + i + 4); if (threv) { s -= thseq; e -= thseq; } else { s -= thack; e -= thack; } (void)printf("{%u:%u}", s, e); } } break; case TCPOPT_CC: case TCPOPT_CCNEW: case TCPOPT_CCECHO: case TCPOPT_ECHO: case TCPOPT_ECHOREPLY: /* * those options share their semantics. * fall through */ datalen = 4; LENCHECK(datalen); (void)printf(" %u", EXTRACT_32BITS(cp)); break; case TCPOPT_TIMESTAMP: datalen = 8; LENCHECK(datalen); (void)printf(" val %u ecr %u", EXTRACT_32BITS(cp), EXTRACT_32BITS(cp + 4)); break; case TCPOPT_SIGNATURE: datalen = TCP_SIGLEN; LENCHECK(datalen); #ifdef HAVE_LIBCRYPTO switch (tcp_verify_signature(ip, tp, bp + TH_OFF(tp) * 4, length, cp)) { case SIGNATURE_VALID: (void)printf("valid"); break; case SIGNATURE_INVALID: (void)printf("invalid"); break; case CANT_CHECK_SIGNATURE: (void)printf("can't check - "); for (i = 0; i < TCP_SIGLEN; ++i) (void)printf("%02x", cp[i]); break; } #else for (i = 0; i < TCP_SIGLEN; ++i) (void)printf("%02x", cp[i]); #endif break; case TCPOPT_AUTH: (void)printf("keyid %d", *cp++); datalen = len - 3; for (i = 0; i < datalen; ++i) { LENCHECK(i); (void)printf("%02x", cp[i]); } break; case TCPOPT_EOL: case TCPOPT_NOP: case TCPOPT_SACKOK: /* * Nothing interesting. * fall through */ break; case TCPOPT_UTO: datalen = 2; LENCHECK(datalen); utoval = EXTRACT_16BITS(cp); (void)printf("0x%x", utoval); if (utoval & 0x0001) utoval = (utoval >> 1) * 60; else utoval >>= 1; (void)printf(" %u", utoval); break; default: datalen = len - 2; for (i = 0; i < datalen; ++i) { LENCHECK(i); (void)printf("%02x", cp[i]); } break; } /* Account for data printed */ cp += datalen; hlen -= datalen; /* Check specification against observed length */ ++datalen; /* option octet */ if (!ZEROLENOPT(opt)) ++datalen; /* size octet */ if (datalen != len) (void)printf("[len %d]", len); ch = ','; if (opt == TCPOPT_EOL) break; } putchar(']'); }
static int ldp_pdu_print(netdissect_options *ndo, const u_char *pptr) { const struct ldp_common_header *ldp_com_header; const struct ldp_msg_header *ldp_msg_header; const u_char *tptr,*msg_tptr; u_short tlen; u_short pdu_len,msg_len,msg_type,msg_tlen; int hexdump,processed; ldp_com_header = (const struct ldp_common_header *)pptr; ND_TCHECK_SIZE(ldp_com_header); /* * Sanity checking of the header. */ if (EXTRACT_BE_U_2(ldp_com_header->version) != LDP_VERSION) { ND_PRINT("%sLDP version %u packet not supported", (ndo->ndo_vflag < 1) ? "" : "\n\t", EXTRACT_BE_U_2(ldp_com_header->version)); return 0; } pdu_len = EXTRACT_BE_U_2(ldp_com_header->pdu_length); if (pdu_len < sizeof(struct ldp_common_header)-4) { /* length too short */ ND_PRINT("%sLDP, pdu-length: %u (too short, < %u)", (ndo->ndo_vflag < 1) ? "" : "\n\t", pdu_len, (u_int)(sizeof(struct ldp_common_header)-4)); return 0; } /* print the LSR-ID, label-space & length */ ND_PRINT("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", (ndo->ndo_vflag < 1) ? "" : "\n\t", ipaddr_string(ndo, &ldp_com_header->lsr_id), EXTRACT_BE_U_2(ldp_com_header->label_space), pdu_len); /* bail out if non-verbose */ if (ndo->ndo_vflag < 1) return 0; /* ok they seem to want to know everything - lets fully decode it */ tptr = pptr + sizeof(struct ldp_common_header); tlen = pdu_len - (sizeof(struct ldp_common_header)-4); /* Type & Length fields not included */ while(tlen>0) { /* did we capture enough for fully decoding the msg header ? */ ND_TCHECK_LEN(tptr, sizeof(struct ldp_msg_header)); ldp_msg_header = (const struct ldp_msg_header *)tptr; msg_len=EXTRACT_BE_U_2(ldp_msg_header->length); msg_type=LDP_MASK_MSG_TYPE(EXTRACT_BE_U_2(ldp_msg_header->type)); if (msg_len < sizeof(struct ldp_msg_header)-4) { /* length too short */ /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s Message (0x%04x), length: %u (too short, < %u)", tok2str(ldp_msg_values, "Unknown", msg_type), msg_type, msg_len, (u_int)(sizeof(struct ldp_msg_header)-4)); return 0; } /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", tok2str(ldp_msg_values, "Unknown", msg_type), msg_type, msg_len, EXTRACT_BE_U_4(ldp_msg_header->id), LDP_MASK_U_BIT(EXTRACT_BE_U_2(ldp_msg_header->type)) ? "continue processing" : "ignore"); msg_tptr=tptr+sizeof(struct ldp_msg_header); msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */ /* did we capture enough for fully decoding the message ? */ ND_TCHECK_LEN(tptr, msg_len); hexdump=FALSE; switch(msg_type) { case LDP_MSG_NOTIF: case LDP_MSG_HELLO: case LDP_MSG_INIT: case LDP_MSG_KEEPALIVE: case LDP_MSG_ADDRESS: case LDP_MSG_LABEL_MAPPING: case LDP_MSG_ADDRESS_WITHDRAW: case LDP_MSG_LABEL_WITHDRAW: while(msg_tlen >= 4) { processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen); if (processed == 0) break; msg_tlen-=processed; msg_tptr+=processed; } break; /* * FIXME those are the defined messages that lack a decoder * you are welcome to contribute code ;-) */ case LDP_MSG_LABEL_REQUEST: case LDP_MSG_LABEL_RELEASE: case LDP_MSG_LABEL_ABORT_REQUEST: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, msg_tptr, "\n\t ", msg_tlen); break; } /* do we want to see an additionally hexdump ? */ if (ndo->ndo_vflag > 1 || hexdump==TRUE) print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t ", msg_len); tptr += msg_len+4; tlen -= msg_len+4; } return pdu_len+4; trunc: ND_PRINT("\n\t\t packet exceeded snapshot"); return 0; }
/* print a reply */ static const u_char * ns_rprint(register const u_char *cp, register const u_char *bp) { register u_int i; register u_short typ, len; register const u_char *rp; if (vflag) { putchar(' '); cp = ns_nprint(cp, bp); } else cp = ns_nskip(cp, bp); if (cp + 10 > snapend) return (snapend); /* print the type/qtype and class (if it's not IN) */ typ = *cp++ << 8; typ |= *cp++; i = *cp++ << 8; i |= *cp++; if (i != C_IN) printf(" %s", tok2str(class2str, "(Class %d)", i)); /* ignore ttl */ cp += 4; len = *cp++ << 8; len |= *cp++; rp = cp + len; printf(" %s", tok2str(type2str, "Type%d", typ)); switch (typ) { case T_A: printf(" %s", ipaddr_string(cp)); break; case T_NS: case T_CNAME: case T_PTR: putchar(' '); (void)ns_nprint(cp, bp); break; case T_MX: putchar(' '); (void)ns_nprint(cp + 2, bp); printf(" %d", EXTRACT_16BITS(cp)); break; case T_TXT: putchar(' '); (void)ns_cprint(cp, bp); break; case T_UNSPECA: /* One long string */ printf(" %.*s", len, cp); break; } return (rp); /* XXX This isn't always right */ }
void lwapp_control_print(netdissect_options *ndo, const u_char *pptr, u_int len, int has_ap_ident) { const struct lwapp_transport_header *lwapp_trans_header; const struct lwapp_control_header *lwapp_control_header; const u_char *tptr; int tlen; int msg_tlen; tptr=pptr; if (has_ap_ident) { /* check if enough bytes for AP identity */ ND_TCHECK2(*tptr, 6); lwapp_trans_header = (const struct lwapp_transport_header *)(pptr+6); } else { lwapp_trans_header = (const struct lwapp_transport_header *)pptr; } ND_TCHECK(*lwapp_trans_header); /* * Sanity checking of the header. */ if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) { ND_PRINT((ndo, "LWAPP version %u packet not supported", LWAPP_EXTRACT_VERSION(lwapp_trans_header->version))); return; } /* non-verbose */ if (ndo->ndo_vflag < 1) { ND_PRINT((ndo, "LWAPPv%u, %s frame, Flags [%s], length %u", LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), len)); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=EXTRACT_16BITS(lwapp_trans_header->length); ND_PRINT((ndo, "LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u", LWAPP_EXTRACT_VERSION(lwapp_trans_header->version), LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data", LWAPP_EXTRACT_RID(lwapp_trans_header->version), bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07), lwapp_trans_header->frag_id, tlen)); if (has_ap_ident) { ND_PRINT((ndo, "\n\tAP identity: %s", etheraddr_string(ndo, tptr))); tptr+=sizeof(const struct lwapp_transport_header)+6; } else { tptr+=sizeof(const struct lwapp_transport_header); } while(tlen>0) { /* did we capture enough for fully decoding the object header ? */ ND_TCHECK2(*tptr, sizeof(struct lwapp_control_header)); lwapp_control_header = (const struct lwapp_control_header *)tptr; msg_tlen = EXTRACT_16BITS(lwapp_control_header->len); /* print message header */ ND_PRINT((ndo, "\n\t Msg type: %s (%u), Seqnum: %u, Msg len: %d, Session: 0x%08x", tok2str(lwapp_msg_type_values,"Unknown",lwapp_control_header->msg_type), lwapp_control_header->msg_type, lwapp_control_header->seq_num, msg_tlen, EXTRACT_32BITS(lwapp_control_header->session_id))); /* did we capture enough for fully decoding the message */ ND_TCHECK2(*tptr, msg_tlen); /* XXX - Decode sub messages for each message */ switch(lwapp_control_header->msg_type) { case LWAPP_MSGTYPE_DISCOVERY_REQUEST: case LWAPP_MSGTYPE_DISCOVERY_RESPONSE: case LWAPP_MSGTYPE_JOIN_REQUEST: case LWAPP_MSGTYPE_JOIN_RESPONSE: case LWAPP_MSGTYPE_JOIN_ACK: case LWAPP_MSGTYPE_JOIN_CONFIRM: case LWAPP_MSGTYPE_CONFIGURE_REQUEST: case LWAPP_MSGTYPE_CONFIGURE_RESPONSE: case LWAPP_MSGTYPE_CONF_UPDATE_REQUEST: case LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE: case LWAPP_MSGTYPE_WTP_EVENT_REQUEST: case LWAPP_MSGTYPE_WTP_EVENT_RESPONSE: case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST: case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE: case LWAPP_MSGTYPE_ECHO_REQUEST: case LWAPP_MSGTYPE_ECHO_RESPONSE: case LWAPP_MSGTYPE_IMAGE_DATA_REQUEST: case LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE: case LWAPP_MSGTYPE_RESET_REQUEST: case LWAPP_MSGTYPE_RESET_RESPONSE: case LWAPP_MSGTYPE_KEY_UPDATE_REQUEST: case LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE: case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST: case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE: case LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST: case LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE: case LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION: case LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST: case LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE: case LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST: case LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE: default: break; } tptr += sizeof(struct lwapp_control_header) + msg_tlen; tlen -= sizeof(struct lwapp_control_header) + msg_tlen; } return; trunc: ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); }
static void print_attr_num(netdissect_options *ndo, register u_char *data, u_int length, u_short attr_code) { uint32_t timeout; if (length != 4) { ND_PRINT((ndo, "ERROR: length %u != 4", length)); return; } ND_TCHECK2(data[0],4); /* This attribute has standard values */ if (attr_type[attr_code].siz_subtypes) { static const char **table; uint32_t data_value; table = attr_type[attr_code].subtypes; if ( (attr_code == TUNNEL_TYPE) || (attr_code == TUNNEL_MEDIUM) ) { if (!*data) ND_PRINT((ndo, "Tag[Unused] ")); else ND_PRINT((ndo, "Tag[%d] ", *data)); data++; data_value = EXTRACT_24BITS(data); } else { data_value = EXTRACT_32BITS(data); } if ( data_value <= (uint32_t)(attr_type[attr_code].siz_subtypes - 1 + attr_type[attr_code].first_subtype) && data_value >= attr_type[attr_code].first_subtype ) ND_PRINT((ndo, "%s", table[data_value])); else ND_PRINT((ndo, "#%u", data_value)); } else { switch(attr_code) /* Be aware of special cases... */ { case FRM_IPX: if (EXTRACT_32BITS( data) == 0xFFFFFFFE ) ND_PRINT((ndo, "NAS Select")); else ND_PRINT((ndo, "%d", EXTRACT_32BITS(data))); break; case SESSION_TIMEOUT: case IDLE_TIMEOUT: case ACCT_DELAY: case ACCT_SESSION_TIME: case ACCT_INT_INTERVAL: timeout = EXTRACT_32BITS( data); if ( timeout < 60 ) ND_PRINT((ndo, "%02d secs", timeout)); else { if ( timeout < 3600 ) ND_PRINT((ndo, "%02d:%02d min", timeout / 60, timeout % 60)); else ND_PRINT((ndo, "%02d:%02d:%02d hours", timeout / 3600, (timeout % 3600) / 60, timeout % 60)); } break; case FRM_ATALK_LINK: if (EXTRACT_32BITS(data) ) ND_PRINT((ndo, "%d", EXTRACT_32BITS(data))); else ND_PRINT((ndo, "Unnumbered")); break; case FRM_ATALK_NETWORK: if (EXTRACT_32BITS(data) ) ND_PRINT((ndo, "%d", EXTRACT_32BITS(data))); else ND_PRINT((ndo, "NAS assigned")); break; case TUNNEL_PREFERENCE: if (*data) ND_PRINT((ndo, "Tag[%d] ", *data)); else ND_PRINT((ndo, "Tag[Unused] ")); data++; ND_PRINT((ndo, "%d", EXTRACT_24BITS(data))); break; case EGRESS_VLAN_ID: ND_PRINT((ndo, "%s (0x%02x) ", tok2str(rfc4675_tagged,"Unknown tag",*data), *data)); data++; ND_PRINT((ndo, "%d", EXTRACT_24BITS(data))); break; default: ND_PRINT((ndo, "%d", EXTRACT_32BITS(data))); break; } /* switch */ } /* if-else */ return; trunc: ND_PRINT((ndo, "%s", tstr)); }
void eigrp_print(register const u_char *pptr, register u_int len) { const struct eigrp_common_header *eigrp_com_header; const struct eigrp_tlv_header *eigrp_tlv_header; const u_char *tptr,*tlv_tptr; u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length; u_int8_t prefix[4]; union { const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm; const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version; const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int; const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext; const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup; const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int; const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext; } tlv_ptr; tptr=pptr; eigrp_com_header = (const struct eigrp_common_header *)pptr; TCHECK(*eigrp_com_header); /* * Sanity checking of the header. */ if (eigrp_com_header->version != EIGRP_VERSION) { printf("EIGRP version %u packet not supported",eigrp_com_header->version); return; } /* in non-verbose mode just lets print the basic Message Type*/ if (vflag < 1) { printf("EIGRP %s, length: %u", tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode), len); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=len-sizeof(struct eigrp_common_header); /* FIXME print other header info */ printf("\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]\n\tseq: 0x%08x, ack: 0x%08x, AS: %u, length: %u", eigrp_com_header->version, tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode), eigrp_com_header->opcode, EXTRACT_16BITS(&eigrp_com_header->checksum), tok2str(eigrp_common_header_flag_values, "none", EXTRACT_32BITS(&eigrp_com_header->flags)), EXTRACT_32BITS(&eigrp_com_header->seq), EXTRACT_32BITS(&eigrp_com_header->ack), EXTRACT_32BITS(&eigrp_com_header->asn), tlen); tptr+=sizeof(const struct eigrp_common_header); while(tlen>0) { /* did we capture enough for fully decoding the object header ? */ TCHECK2(*tptr, sizeof(struct eigrp_tlv_header)); eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr; eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length); eigrp_tlv_type=EXTRACT_16BITS(&eigrp_tlv_header->type); if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) || eigrp_tlv_len > tlen) { print_unknown_data(tptr+sizeof(sizeof(struct eigrp_tlv_header)),"\n\t ",tlen); return; } printf("\n\t %s TLV (0x%04x), length: %u", tok2str(eigrp_tlv_values, "Unknown", eigrp_tlv_type), eigrp_tlv_type, eigrp_tlv_len); tlv_tptr=tptr+sizeof(struct eigrp_tlv_header); tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header); /* did we capture enough for fully decoding the object ? */ TCHECK2(*tptr, eigrp_tlv_len); switch(eigrp_tlv_type) { case EIGRP_TLV_GENERAL_PARM: tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr; printf("\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u", EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime), tlv_ptr.eigrp_tlv_general_parm->k1, tlv_ptr.eigrp_tlv_general_parm->k2, tlv_ptr.eigrp_tlv_general_parm->k3, tlv_ptr.eigrp_tlv_general_parm->k4, tlv_ptr.eigrp_tlv_general_parm->k5); break; case EIGRP_TLV_SW_VERSION: tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr; printf("\n\t IOS version: %u.%u, EIGRP version %u.%u", tlv_ptr.eigrp_tlv_sw_version->ios_major, tlv_ptr.eigrp_tlv_sw_version->ios_minor, tlv_ptr.eigrp_tlv_sw_version->eigrp_major, tlv_ptr.eigrp_tlv_sw_version->eigrp_minor); break; case EIGRP_TLV_IP_INT: tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr; bit_length = tlv_ptr.eigrp_tlv_ip_int->plen; if (bit_length > 32) { printf("\n\t illegal prefix length %u",bit_length); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length); printf("\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(prefix), bit_length); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0) printf("self"); else printf("%s",ipaddr_string(&tlv_ptr.eigrp_tlv_ip_int->nexthop)); printf("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu), tlv_ptr.eigrp_tlv_ip_int->hopcount, tlv_ptr.eigrp_tlv_ip_int->reliability, tlv_ptr.eigrp_tlv_ip_int->load); break; case EIGRP_TLV_IP_EXT: tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr; bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen; if (bit_length > 32) { printf("\n\t illegal prefix length %u",bit_length); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length); printf("\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(prefix), bit_length); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0) printf("self"); else printf("%s",ipaddr_string(&tlv_ptr.eigrp_tlv_ip_ext->nexthop)); printf("\n\t origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", ipaddr_string(tlv_ptr.eigrp_tlv_ip_ext->origin_router), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id), tlv_ptr.eigrp_tlv_ip_ext->flags, EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric)); printf("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu), tlv_ptr.eigrp_tlv_ip_ext->hopcount, tlv_ptr.eigrp_tlv_ip_ext->reliability, tlv_ptr.eigrp_tlv_ip_ext->load); break; case EIGRP_TLV_AT_CABLE_SETUP: tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr; printf("\n\t Cable-range: %u-%u, Router-ID %u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->router_id)); break; case EIGRP_TLV_AT_INT: tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr; printf("\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end)); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0) printf("self"); else printf("%u.%u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2])); printf("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu), tlv_ptr.eigrp_tlv_at_int->hopcount, tlv_ptr.eigrp_tlv_at_int->reliability, tlv_ptr.eigrp_tlv_at_int->load); break; case EIGRP_TLV_AT_EXT: tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr; printf("\n\t Cable-Range: %u-%u, nexthop: ", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end)); if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0) printf("self"); else printf("%u.%u", EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop), EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2])); printf("\n\t origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router), EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id), tlv_ptr.eigrp_tlv_at_ext->flags, EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag), EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric)); printf("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100), EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth), EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu), tlv_ptr.eigrp_tlv_at_ext->hopcount, tlv_ptr.eigrp_tlv_at_ext->reliability, tlv_ptr.eigrp_tlv_at_ext->load); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case EIGRP_TLV_AUTH: case EIGRP_TLV_SEQ: case EIGRP_TLV_MCAST_SEQ: case EIGRP_TLV_IPX_INT: case EIGRP_TLV_IPX_EXT: default: if (vflag <= 1) print_unknown_data(tlv_tptr,"\n\t ",tlv_tlen); break; } /* do we want to see an additionally hexdump ? */ if (vflag > 1) print_unknown_data(tptr+sizeof(sizeof(struct eigrp_tlv_header)),"\n\t ", eigrp_tlv_len-sizeof(struct eigrp_tlv_header)); tptr+=eigrp_tlv_len; tlen-=eigrp_tlv_len; } return; trunc: printf("\n\t\t packet exceeded snapshot"); }
void icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented) { char *cp; const struct icmp *dp; const struct icmp_ext_t *ext_dp; const struct ip *ip; const char *str, *fmt; const struct ip *oip; const struct udphdr *ouh; const u_int8_t *obj_tptr; u_int32_t raw_label; const u_char *snapend_save; const struct icmp_mpls_ext_object_header_t *icmp_mpls_ext_object_header; u_int hlen, dport, mtu, obj_tlen, obj_class_num, obj_ctype; char buf[MAXHOSTNAMELEN + 100]; struct cksum_vec vec[1]; dp = (struct icmp *)bp; ext_dp = (struct icmp_ext_t *)bp; ip = (struct ip *)bp2; str = buf; TCHECK(dp->icmp_code); switch (dp->icmp_type) { case ICMP_ECHO: case ICMP_ECHOREPLY: TCHECK(dp->icmp_seq); (void)snprintf(buf, sizeof(buf), "echo %s, id %u, seq %u", dp->icmp_type == ICMP_ECHO ? "request" : "reply", EXTRACT_16BITS(&dp->icmp_id), EXTRACT_16BITS(&dp->icmp_seq)); break; case ICMP_UNREACH: TCHECK(dp->icmp_ip.ip_dst); switch (dp->icmp_code) { case ICMP_UNREACH_PROTOCOL: TCHECK(dp->icmp_ip.ip_p); (void)snprintf(buf, sizeof(buf), "%s protocol %d unreachable", ipaddr_string(&dp->icmp_ip.ip_dst), dp->icmp_ip.ip_p); break; case ICMP_UNREACH_PORT: TCHECK(dp->icmp_ip.ip_p); oip = &dp->icmp_ip; hlen = IP_HL(oip) * 4; ouh = (struct udphdr *)(((u_char *)oip) + hlen); TCHECK(ouh->uh_dport); dport = EXTRACT_16BITS(&ouh->uh_dport); switch (oip->ip_p) { case IPPROTO_TCP: (void)snprintf(buf, sizeof(buf), "%s tcp port %s unreachable", ipaddr_string(&oip->ip_dst), tcpport_string(dport)); break; case IPPROTO_UDP: (void)snprintf(buf, sizeof(buf), "%s udp port %s unreachable", ipaddr_string(&oip->ip_dst), udpport_string(dport)); break; default: (void)snprintf(buf, sizeof(buf), "%s protocol %d port %d unreachable", ipaddr_string(&oip->ip_dst), oip->ip_p, dport); break; } break; case ICMP_UNREACH_NEEDFRAG: { register const struct mtu_discovery *mp; mp = (struct mtu_discovery *)(u_char *)&dp->icmp_void; mtu = EXTRACT_16BITS(&mp->nexthopmtu); if (mtu) { (void)snprintf(buf, sizeof(buf), "%s unreachable - need to frag (mtu %d)", ipaddr_string(&dp->icmp_ip.ip_dst), mtu); } else { (void)snprintf(buf, sizeof(buf), "%s unreachable - need to frag", ipaddr_string(&dp->icmp_ip.ip_dst)); } } break; default: fmt = tok2str(unreach2str, "#%d %%s unreachable", dp->icmp_code); (void)snprintf(buf, sizeof(buf), fmt, ipaddr_string(&dp->icmp_ip.ip_dst)); break; } break; case ICMP_REDIRECT: TCHECK(dp->icmp_ip.ip_dst); fmt = tok2str(type2str, "redirect-#%d %%s to net %%s", dp->icmp_code); (void)snprintf(buf, sizeof(buf), fmt, ipaddr_string(&dp->icmp_ip.ip_dst), ipaddr_string(&dp->icmp_gwaddr)); break; case ICMP_ROUTERADVERT: { register const struct ih_rdiscovery *ihp; register const struct id_rdiscovery *idp; u_int lifetime, num, size; (void)snprintf(buf, sizeof(buf), "router advertisement"); cp = buf + strlen(buf); ihp = (struct ih_rdiscovery *)&dp->icmp_void; TCHECK(*ihp); (void)strncpy(cp, " lifetime ", sizeof(buf) - (cp - buf)); cp = buf + strlen(buf); lifetime = EXTRACT_16BITS(&ihp->ird_lifetime); if (lifetime < 60) { (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u", lifetime); } else if (lifetime < 60 * 60) { (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u:%02u", lifetime / 60, lifetime % 60); } else { (void)snprintf(cp, sizeof(buf) - (cp - buf), "%u:%02u:%02u", lifetime / 3600, (lifetime % 3600) / 60, lifetime % 60); } cp = buf + strlen(buf); num = ihp->ird_addrnum; (void)snprintf(cp, sizeof(buf) - (cp - buf), " %d:", num); cp = buf + strlen(buf); size = ihp->ird_addrsiz; if (size != 2) { (void)snprintf(cp, sizeof(buf) - (cp - buf), " [size %d]", size); break; } idp = (struct id_rdiscovery *)&dp->icmp_data; while (num-- > 0) { TCHECK(*idp); (void)snprintf(cp, sizeof(buf) - (cp - buf), " {%s %u}", ipaddr_string(&idp->ird_addr), EXTRACT_32BITS(&idp->ird_pref)); cp = buf + strlen(buf); ++idp; } } break; case ICMP_TIMXCEED: TCHECK(dp->icmp_ip.ip_dst); switch (dp->icmp_code) { case ICMP_TIMXCEED_INTRANS: str = "time exceeded in-transit"; break; case ICMP_TIMXCEED_REASS: str = "ip reassembly time exceeded"; break; default: (void)snprintf(buf, sizeof(buf), "time exceeded-#%d", dp->icmp_code); break; } break; case ICMP_PARAMPROB: if (dp->icmp_code) (void)snprintf(buf, sizeof(buf), "parameter problem - code %d", dp->icmp_code); else { TCHECK(dp->icmp_pptr); (void)snprintf(buf, sizeof(buf), "parameter problem - octet %d", dp->icmp_pptr); } break; case ICMP_MASKREPLY: TCHECK(dp->icmp_mask); (void)snprintf(buf, sizeof(buf), "address mask is 0x%08x", EXTRACT_32BITS(&dp->icmp_mask)); break; case ICMP_TSTAMP: TCHECK(dp->icmp_seq); (void)snprintf(buf, sizeof(buf), "time stamp query id %u seq %u", EXTRACT_16BITS(&dp->icmp_id), EXTRACT_16BITS(&dp->icmp_seq)); break; case ICMP_TSTAMPREPLY: TCHECK(dp->icmp_ttime); (void)snprintf(buf, sizeof(buf), "time stamp reply id %u seq %u: org %s", EXTRACT_16BITS(&dp->icmp_id), EXTRACT_16BITS(&dp->icmp_seq), icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_otime))); (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", recv %s", icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_rtime))); (void)snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),", xmit %s", icmp_tstamp_print(EXTRACT_32BITS(&dp->icmp_ttime))); break; default: str = tok2str(icmp2str, "type-#%d", dp->icmp_type); break; } (void)printf("ICMP %s, length %u", str, plen); if (vflag && !fragmented) { /* don't attempt checksumming if this is a frag */ u_int16_t sum, icmp_sum; struct cksum_vec vec[1]; if (TTEST2(*bp, plen)) { vec[0].ptr = (const u_int8_t *)(void *)dp; vec[0].len = plen; sum = in_cksum(vec, 1); if (sum != 0) { icmp_sum = EXTRACT_16BITS(&dp->icmp_cksum); (void)printf(" (wrong icmp cksum %x (->%x)!)", icmp_sum, in_cksum_shouldbe(icmp_sum, sum)); } } } /* * print the remnants of the IP packet. * save the snaplength as this may get overidden in the IP printer. */ if (vflag >= 1 && !ICMP_INFOTYPE(dp->icmp_type)) { bp += 8; (void)printf("\n\t"); ip = (struct ip *)bp; snaplen = snapend - bp; snapend_save = snapend; ip_print(gndo, bp, EXTRACT_16BITS(&ip->ip_len)); snapend = snapend_save; } /* * Attempt to decode the MPLS extensions only for some ICMP types. */ if (vflag >= 1 && plen > ICMP_EXTD_MINLEN && ICMP_MPLS_EXT_TYPE(dp->icmp_type)) { TCHECK(*ext_dp); /* * Check first if the mpls extension header shows a non-zero length. * If the length field is not set then silently verify the checksum * to check if an extension header is present. This is expedient, * however not all implementations set the length field proper. */ if (!ext_dp->icmp_length) { vec[0].ptr = (const u_int8_t *)(void *)&ext_dp->icmp_ext_version_res; vec[0].len = plen - ICMP_EXTD_MINLEN; if (in_cksum(vec, 1)) { return; } } printf("\n\tMPLS extension v%u", ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res))); /* * Sanity checking of the header. */ if (ICMP_MPLS_EXT_EXTRACT_VERSION(*(ext_dp->icmp_ext_version_res)) != ICMP_MPLS_EXT_VERSION) { printf(" packet not supported"); return; } hlen = plen - ICMP_EXTD_MINLEN; vec[0].ptr = (const u_int8_t *)(void *)&ext_dp->icmp_ext_version_res; vec[0].len = hlen; printf(", checksum 0x%04x (%scorrect), length %u", EXTRACT_16BITS(ext_dp->icmp_ext_checksum), in_cksum(vec, 1) ? "in" : "", hlen); hlen -= 4; /* subtract common header size */ obj_tptr = (u_int8_t *)ext_dp->icmp_ext_data; while (hlen > sizeof(struct icmp_mpls_ext_object_header_t)) { icmp_mpls_ext_object_header = (struct icmp_mpls_ext_object_header_t *)obj_tptr; TCHECK(*icmp_mpls_ext_object_header); obj_tlen = EXTRACT_16BITS(icmp_mpls_ext_object_header->length); obj_class_num = icmp_mpls_ext_object_header->class_num; obj_ctype = icmp_mpls_ext_object_header->ctype; obj_tptr += sizeof(struct icmp_mpls_ext_object_header_t); printf("\n\t %s Object (%u), Class-Type: %u, length %u", tok2str(icmp_mpls_ext_obj_values,"unknown",obj_class_num), obj_class_num, obj_ctype, obj_tlen); hlen-=sizeof(struct icmp_mpls_ext_object_header_t); /* length field includes tlv header */ /* infinite loop protection */ if ((obj_class_num == 0) || (obj_tlen < sizeof(struct icmp_mpls_ext_object_header_t))) { return; } obj_tlen-=sizeof(struct icmp_mpls_ext_object_header_t); switch (obj_class_num) { case 1: switch(obj_ctype) { case 1: TCHECK2(*obj_tptr, 4); raw_label = EXTRACT_32BITS(obj_tptr); printf("\n\t label %u, exp %u", MPLS_LABEL(raw_label), MPLS_EXP(raw_label)); if (MPLS_STACK(raw_label)) printf(", [S]"); printf(", ttl %u", MPLS_TTL(raw_label)); break; default: print_unknown_data(obj_tptr, "\n\t ", obj_tlen); } break; /* * FIXME those are the defined objects that lack a decoder * you are welcome to contribute code ;-) */ case 2: default: print_unknown_data(obj_tptr, "\n\t ", obj_tlen); break; } if (hlen < obj_tlen) break; hlen -= obj_tlen; obj_tptr += obj_tlen; } } return; trunc: fputs("[|icmp]", stdout); }
static int stp_print_mstp_bpdu(netdissect_options *ndo, const struct stp_bpdu_ *stp_bpdu, u_int length) { const u_char *ptr; uint8_t bpdu_flags; uint16_t v3len; uint16_t len; uint16_t msti; u_int offset; ptr = (const u_char *)stp_bpdu; ND_TCHECK_1(stp_bpdu->flags); bpdu_flags = EXTRACT_U_1(stp_bpdu->flags); ND_PRINT(", CIST Flags [%s], length %u", bittok2str(stp_bpdu_flag_values, "none", bpdu_flags), length); /* * in non-verbose mode just print the flags. */ if (!ndo->ndo_vflag) { return 1; } ND_PRINT("\n\tport-role %s, ", tok2str(rstp_obj_port_role_values, "Unknown", RSTP_EXTRACT_PORT_ROLE(bpdu_flags))); ND_TCHECK_4(stp_bpdu->root_path_cost); ND_PRINT("CIST root-id %s, CIST ext-pathcost %u", stp_print_bridge_id((const u_char *)&stp_bpdu->root_id), EXTRACT_BE_U_4(stp_bpdu->root_path_cost)); ND_TCHECK_SIZE(&stp_bpdu->bridge_id); ND_PRINT("\n\tCIST regional-root-id %s, ", stp_print_bridge_id((const u_char *)&stp_bpdu->bridge_id)); ND_TCHECK_2(stp_bpdu->port_id); ND_PRINT("CIST port-id %04x,", EXTRACT_BE_U_2(stp_bpdu->port_id)); ND_TCHECK_2(stp_bpdu->forward_delay); ND_PRINT("\n\tmessage-age %.2fs, max-age %.2fs" ", hello-time %.2fs, forwarding-delay %.2fs", (float) EXTRACT_BE_U_2(stp_bpdu->message_age) / STP_TIME_BASE, (float) EXTRACT_BE_U_2(stp_bpdu->max_age) / STP_TIME_BASE, (float) EXTRACT_BE_U_2(stp_bpdu->hello_time) / STP_TIME_BASE, (float) EXTRACT_BE_U_2(stp_bpdu->forward_delay) / STP_TIME_BASE); ND_TCHECK_2(ptr + MST_BPDU_VER3_LEN_OFFSET); ND_PRINT("\n\tv3len %u, ", EXTRACT_BE_U_2(ptr + MST_BPDU_VER3_LEN_OFFSET)); ND_TCHECK_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 12); ND_PRINT("MCID Name "); if (fn_printzp(ndo, ptr + MST_BPDU_CONFIG_NAME_OFFSET, 32, ndo->ndo_snapend)) goto trunc; ND_PRINT(", rev %u," "\n\t\tdigest %08x%08x%08x%08x, ", EXTRACT_BE_U_2(ptr + MST_BPDU_CONFIG_NAME_OFFSET + 32), EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET), EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 4), EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 8), EXTRACT_BE_U_4(ptr + MST_BPDU_CONFIG_DIGEST_OFFSET + 12)); ND_TCHECK_4(ptr + MST_BPDU_CIST_INT_PATH_COST_OFFSET); ND_PRINT("CIST int-root-pathcost %u,", EXTRACT_BE_U_4(ptr + MST_BPDU_CIST_INT_PATH_COST_OFFSET)); ND_TCHECK_BRIDGE_ID(ptr + MST_BPDU_CIST_BRIDGE_ID_OFFSET); ND_PRINT("\n\tCIST bridge-id %s, ", stp_print_bridge_id(ptr + MST_BPDU_CIST_BRIDGE_ID_OFFSET)); ND_TCHECK_1(ptr + MST_BPDU_CIST_REMAIN_HOPS_OFFSET); ND_PRINT("CIST remaining-hops %u", EXTRACT_U_1(ptr + MST_BPDU_CIST_REMAIN_HOPS_OFFSET)); /* Dump all MSTI's */ ND_TCHECK_2(ptr + MST_BPDU_VER3_LEN_OFFSET); v3len = EXTRACT_BE_U_2(ptr + MST_BPDU_VER3_LEN_OFFSET); if (v3len > MST_BPDU_CONFIG_INFO_LENGTH) { len = v3len - MST_BPDU_CONFIG_INFO_LENGTH; offset = MST_BPDU_MSTI_OFFSET; while (len >= MST_BPDU_MSTI_LENGTH) { ND_TCHECK_LEN(ptr + offset, MST_BPDU_MSTI_LENGTH); msti = EXTRACT_BE_U_2(ptr + offset + MST_BPDU_MSTI_ROOT_PRIO_OFFSET); msti = msti & 0x0FFF; ND_PRINT("\n\tMSTI %u, Flags [%s], port-role %s", msti, bittok2str(stp_bpdu_flag_values, "none", EXTRACT_U_1(ptr + offset)), tok2str(rstp_obj_port_role_values, "Unknown", RSTP_EXTRACT_PORT_ROLE(EXTRACT_U_1(ptr + offset)))); ND_PRINT("\n\t\tMSTI regional-root-id %s, pathcost %u", stp_print_bridge_id(ptr + offset + MST_BPDU_MSTI_ROOT_PRIO_OFFSET), EXTRACT_BE_U_4(ptr + offset + MST_BPDU_MSTI_ROOT_PATH_COST_OFFSET)); ND_PRINT("\n\t\tMSTI bridge-prio %u, port-prio %u, hops %u", EXTRACT_U_1(ptr + offset + MST_BPDU_MSTI_BRIDGE_PRIO_OFFSET) >> 4, EXTRACT_U_1(ptr + offset + MST_BPDU_MSTI_PORT_PRIO_OFFSET) >> 4, EXTRACT_U_1(ptr + offset + MST_BPDU_MSTI_REMAIN_HOPS_OFFSET)); len -= MST_BPDU_MSTI_LENGTH; offset += MST_BPDU_MSTI_LENGTH; } }
void geneve_print(netdissect_options *ndo, const u_char *bp, u_int len) { uint8_t ver_opt; u_int version; uint8_t flags; uint16_t prot; uint32_t vni; uint8_t reserved; u_int opts_len; ND_PRINT((ndo, "Geneve")); ND_TCHECK2(*bp, 8); ver_opt = *bp; bp += 1; len -= 1; version = ver_opt >> VER_SHIFT; if (version != 0) { ND_PRINT((ndo, " ERROR: unknown-version %u", version)); return; } flags = *bp; bp += 1; len -= 1; prot = EXTRACT_16BITS(bp); bp += 2; len -= 2; vni = EXTRACT_24BITS(bp); bp += 3; len -= 3; reserved = *bp; bp += 1; len -= 1; ND_PRINT((ndo, ", Flags [%s]", bittok2str_nosep(geneve_flag_values, "none", flags))); ND_PRINT((ndo, ", vni 0x%x", vni)); if (reserved) ND_PRINT((ndo, ", rsvd 0x%x", reserved)); if (ndo->ndo_eflag) ND_PRINT((ndo, ", proto %s (0x%04x)", tok2str(ethertype_values, "unknown", prot), prot)); opts_len = (ver_opt & HDR_OPTS_LEN_MASK) * 4; if (len < opts_len) { ND_PRINT((ndo, " truncated-geneve - %u bytes missing", opts_len - len)); return; } ND_TCHECK2(*bp, opts_len); if (opts_len > 0) { ND_PRINT((ndo, ", options [")); if (ndo->ndo_vflag) geneve_opts_print(ndo, bp, opts_len); else ND_PRINT((ndo, "%u bytes", opts_len)); ND_PRINT((ndo, "]")); } bp += opts_len; len -= opts_len; if (ndo->ndo_vflag < 1) ND_PRINT((ndo, ": ")); else ND_PRINT((ndo, "\n\t")); if (ethertype_print(ndo, prot, bp, len, len) == 0) { if (prot == ETHERTYPE_TEB) ether_print(ndo, bp, len, len, NULL, NULL); else ND_PRINT((ndo, "geneve-proto-0x%x", prot)); } return; trunc: ND_PRINT((ndo, " [|geneve]")); }
void vrrp_print(netdissect_options *ndo, register const u_char *bp, register u_int len, register const u_char *bp2, int ttl) { int version, type, auth_type = VRRP_AUTH_NONE; /* keep compiler happy */ const char *type_s; ND_TCHECK(bp[0]); version = (bp[0] & 0xf0) >> 4; type = bp[0] & 0x0f; type_s = tok2str(type2str, "unknown type (%u)", type); ND_PRINT((ndo, "VRRPv%u, %s", version, type_s)); if (ttl != 255) ND_PRINT((ndo, ", (ttl %u)", ttl)); if (version < 2 || version > 3 || type != VRRP_TYPE_ADVERTISEMENT) return; ND_TCHECK(bp[2]); ND_PRINT((ndo, ", vrid %u, prio %u", bp[1], bp[2])); ND_TCHECK(bp[5]); if (version == 2) { auth_type = bp[4]; ND_PRINT((ndo, ", authtype %s", tok2str(auth2str, NULL, auth_type))); ND_PRINT((ndo, ", intvl %us, length %u", bp[5], len)); } else { /* version == 3 */ uint16_t intvl = (bp[4] & 0x0f) << 8 | bp[5]; ND_PRINT((ndo, ", intvl %ucs, length %u", intvl, len)); } if (ndo->ndo_vflag) { int naddrs = bp[3]; int i; char c; if (version == 2 && ND_TTEST2(bp[0], len)) { struct cksum_vec vec[1]; vec[0].ptr = bp; vec[0].len = len; if (in_cksum(vec, 1)) ND_PRINT((ndo, ", (bad vrrp cksum %x)", EXTRACT_16BITS(&bp[6]))); } if (version == 3 && ND_TTEST2(bp[0], len)) { uint16_t cksum = nextproto4_cksum(ndo, (const struct ip *)bp2, bp, len, len, IPPROTO_VRRP); if (cksum) ND_PRINT((ndo, ", (bad vrrp cksum %x)", EXTRACT_16BITS(&bp[6]))); } ND_PRINT((ndo, ", addrs")); if (naddrs > 1) ND_PRINT((ndo, "(%d)", naddrs)); ND_PRINT((ndo, ":")); c = ' '; bp += 8; for (i = 0; i < naddrs; i++) { ND_TCHECK(bp[3]); ND_PRINT((ndo, "%c%s", c, ipaddr_string(ndo, bp))); c = ','; bp += 4; } if (version == 2 && auth_type == VRRP_AUTH_SIMPLE) { /* simple text password */ ND_TCHECK(bp[7]); ND_PRINT((ndo, " auth \"")); if (fn_printn(ndo, bp, 8, ndo->ndo_snapend)) { ND_PRINT((ndo, "\"")); goto trunc; } ND_PRINT((ndo, "\"")); } } return; trunc: ND_PRINT((ndo, "[|vrrp]")); }