/* * Print RRCP requests */ void rrcp_print(netdissect_options *ndo, register const u_char *cp, u_int length _U_) { const u_char *rrcp; uint8_t rrcp_proto; uint8_t rrcp_opcode; register const struct ether_header *ep; char proto_str[16]; char opcode_str[32]; ep = (const struct ether_header *)cp; rrcp = cp + ETHER_HDRLEN; ND_TCHECK(*(rrcp + RRCP_PROTO_OFFSET)); rrcp_proto = *(rrcp + RRCP_PROTO_OFFSET); ND_TCHECK(*(rrcp + RRCP_OPCODE_ISREPLY_OFFSET)); rrcp_opcode = (*(rrcp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK; ND_PRINT((ndo, "%s > %s, %s %s", etheraddr_string(ndo, ESRC(ep)), etheraddr_string(ndo, EDST(ep)), tok2strbuf(proto_values,"RRCP-0x%02x",rrcp_proto,proto_str,sizeof(proto_str)), ((*(rrcp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query")); if (rrcp_proto==1){ ND_PRINT((ndo, ": %s", tok2strbuf(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode,opcode_str,sizeof(opcode_str)))); } if (rrcp_opcode==1 || rrcp_opcode==2){ ND_TCHECK2(*(rrcp + RRCP_REG_ADDR_OFFSET), 6); ND_PRINT((ndo, " addr=0x%04x, data=0x%08x", EXTRACT_LE_16BITS(rrcp + RRCP_REG_ADDR_OFFSET), EXTRACT_LE_32BITS(rrcp + RRCP_REG_DATA_OFFSET))); } if (rrcp_proto==1){ ND_TCHECK2(*(rrcp + RRCP_AUTHKEY_OFFSET), 2); ND_PRINT((ndo, ", auth=0x%04x", EXTRACT_16BITS(rrcp + RRCP_AUTHKEY_OFFSET))); } if (rrcp_proto==1 && rrcp_opcode==0 && ((*(rrcp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){ ND_TCHECK2(*(rrcp + RRCP_VENDOR_ID_OFFSET), 4); ND_PRINT((ndo, " downlink_port=%d, uplink_port=%d, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ", *(rrcp + RRCP_DOWNLINK_PORT_OFFSET), *(rrcp + RRCP_UPLINK_PORT_OFFSET), etheraddr_string(ndo, rrcp + RRCP_UPLINK_MAC_OFFSET), EXTRACT_32BITS(rrcp + RRCP_VENDOR_ID_OFFSET), EXTRACT_16BITS(rrcp + RRCP_CHIP_ID_OFFSET))); }else if (rrcp_opcode==1 || rrcp_opcode==2 || rrcp_proto==2){ ND_TCHECK2(*(rrcp + RRCP_COOKIE2_OFFSET), 4); ND_PRINT((ndo, ", cookie=0x%08x%08x ", EXTRACT_32BITS(rrcp + RRCP_COOKIE2_OFFSET), EXTRACT_32BITS(rrcp + RRCP_COOKIE1_OFFSET))); } return; trunc: ND_PRINT((ndo, "[|rrcp]")); }
/* * Print RRCP requests */ void rrcp_print(netdissect_options *ndo, register const u_char *cp, u_int length _U_, const struct lladdr_info *src, const struct lladdr_info *dst) { uint8_t rrcp_proto; uint8_t rrcp_opcode; ND_TCHECK(*(cp + RRCP_PROTO_OFFSET)); rrcp_proto = *(cp + RRCP_PROTO_OFFSET); ND_TCHECK(*(cp + RRCP_OPCODE_ISREPLY_OFFSET)); rrcp_opcode = (*(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_OPCODE_MASK; if (src != NULL && dst != NULL) { ND_PRINT((ndo, "%s > %s, ", (src->addr_string)(ndo, src->addr), (dst->addr_string)(ndo, dst->addr))); } ND_PRINT((ndo, "%s %s", tok2str(proto_values,"RRCP-0x%02x",rrcp_proto), ((*(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY) ? "reply" : "query")); if (rrcp_proto==1){ ND_PRINT((ndo, ": %s", tok2str(opcode_values,"unknown opcode (0x%02x)",rrcp_opcode))); } if (rrcp_opcode==1 || rrcp_opcode==2){ ND_TCHECK2(*(cp + RRCP_REG_ADDR_OFFSET), 6); ND_PRINT((ndo, " addr=0x%04x, data=0x%08x", EXTRACT_LE_16BITS(cp + RRCP_REG_ADDR_OFFSET), EXTRACT_LE_32BITS(cp + RRCP_REG_DATA_OFFSET))); } if (rrcp_proto==1){ ND_TCHECK2(*(cp + RRCP_AUTHKEY_OFFSET), 2); ND_PRINT((ndo, ", auth=0x%04x", EXTRACT_16BITS(cp + RRCP_AUTHKEY_OFFSET))); } if (rrcp_proto==1 && rrcp_opcode==0 && ((*(cp + RRCP_OPCODE_ISREPLY_OFFSET)) & RRCP_ISREPLY)){ ND_TCHECK2(*(cp + RRCP_VENDOR_ID_OFFSET), 4); ND_PRINT((ndo, " downlink_port=%d, uplink_port=%d, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ", *(cp + RRCP_DOWNLINK_PORT_OFFSET), *(cp + RRCP_UPLINK_PORT_OFFSET), etheraddr_string(ndo, cp + RRCP_UPLINK_MAC_OFFSET), EXTRACT_32BITS(cp + RRCP_VENDOR_ID_OFFSET), EXTRACT_16BITS(cp + RRCP_CHIP_ID_OFFSET))); }else if (rrcp_opcode==1 || rrcp_opcode==2 || rrcp_proto==2){ ND_TCHECK2(*(cp + RRCP_COOKIE2_OFFSET), 4); ND_PRINT((ndo, ", cookie=0x%08x%08x ", EXTRACT_32BITS(cp + RRCP_COOKIE2_OFFSET), EXTRACT_32BITS(cp + RRCP_COOKIE1_OFFSET))); } return; trunc: ND_PRINT((ndo, "[|rrcp]")); }
/* * Print the 802.11 MAC header if eflag is set, and set "*srcp" and "*dstp" * to point to the source and destination MAC addresses in any case if * "srcp" and "dstp" aren't null. */ static void ieee_802_11_hdr_print(u_int16_t fc, const u_char *p, u_int hdrlen, u_int meshdrlen, const u_int8_t **srcp, const u_int8_t **dstp) { if (vflag) { if (FC_MORE_DATA(fc)) printf("More Data "); if (FC_MORE_FLAG(fc)) printf("More Fragments "); if (FC_POWER_MGMT(fc)) printf("Pwr Mgmt "); if (FC_RETRY(fc)) printf("Retry "); if (FC_ORDER(fc)) printf("Strictly Ordered "); if (FC_WEP(fc)) printf("WEP Encrypted "); if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL) printf("%dus ", EXTRACT_LE_16BITS( &((const struct mgmt_header_t *)p)->duration)); } if (meshdrlen != 0) { const struct meshcntl_t *mc = (const struct meshcntl_t *)&p[hdrlen - meshdrlen]; int ae = mc->flags & 3; printf("MeshData (AE %d TTL %u seq %u", ae, mc->ttl, EXTRACT_LE_32BITS(mc->seq)); if (ae > 0) printf(" A4:%s", etheraddr_string(mc->addr4)); if (ae > 1) printf(" A5:%s", etheraddr_string(mc->addr5)); if (ae > 2) printf(" A6:%s", etheraddr_string(mc->addr6)); printf(") "); } switch (FC_TYPE(fc)) { case T_MGMT: mgmt_header_print(p, srcp, dstp); break; case T_CTRL: ctrl_header_print(fc, p, srcp, dstp); break; case T_DATA: data_header_print(fc, p, srcp, dstp); break; default: printf("(header) unknown IEEE802.11 frame type (%d)", FC_TYPE(fc)); *srcp = NULL; *dstp = NULL; break; } }
static u_int ppi_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { if_printer printer; const ppi_header_t *hdr; u_int caplen = h->caplen; u_int length = h->len; uint16_t len; uint32_t dlt; uint32_t hdrlen; struct pcap_pkthdr nhdr; if (caplen < sizeof(ppi_header_t)) { ND_PRINT((ndo, "[|ppi]")); return (caplen); } hdr = (const ppi_header_t *)p; len = EXTRACT_LE_16BITS(&hdr->ppi_len); if (caplen < len) { /* * If we don't have the entire PPI header, don't * bother. */ ND_PRINT((ndo, "[|ppi]")); return (caplen); } if (len < sizeof(ppi_header_t)) { ND_PRINT((ndo, "[|ppi]")); return (len); } dlt = EXTRACT_LE_32BITS(&hdr->ppi_dlt); if (ndo->ndo_eflag) ppi_header_print(ndo, p, length); length -= len; caplen -= len; p += len; if ((printer = lookup_printer(dlt)) != NULL) { nhdr = *h; nhdr.caplen = caplen; nhdr.len = length; hdrlen = printer(ndo, &nhdr, p); } else { if (!ndo->ndo_eflag) ppi_header_print(ndo, (const u_char *)hdr, length + len); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); hdrlen = 0; } return (len + hdrlen); }
static inline void pktap_header_print(struct netdissect_options *ndo, const u_char *bp, u_int length) { const pktap_header_t *hdr; uint32_t dlt, hdrlen; hdr = (const pktap_header_t *)bp; dlt = EXTRACT_LE_32BITS(&hdr->pkt_dlt); hdrlen = EXTRACT_LE_32BITS(&hdr->pkt_len); if (!ndo->ndo_qflag) { ND_PRINT((ndo,", DLT %s (%d) len %d", pcap_datalink_val_to_name(dlt), dlt, hdrlen)); } else { ND_PRINT((ndo,", %s", pcap_datalink_val_to_name(dlt))); } ND_PRINT((ndo, ", length %u: ", length)); }
/* Unpack a 32-bit unsigned integer. */ int cpack_uint32(struct cpack_state *cs, u_int32_t *u) { u_int8_t *next; if ((next = cpack_align_and_reserve(cs, sizeof(*u))) == NULL) return -1; *u = EXTRACT_LE_32BITS(next); /* Move pointer past the u_int32_t. */ cs->c_next = next + sizeof(*u); return 0; }
static int wep_print(const u_char *p) { u_int32_t iv; if (!TTEST2(*p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN)) return 0; iv = EXTRACT_LE_32BITS(p); printf("Data IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv), IV_KEYID(iv)); return 1; }
void msnlb_print(netdissect_options *ndo, const u_char *bp, u_int length) { const struct msnlb_heartbeat_pkt *hb; hb = (struct msnlb_heartbeat_pkt *)bp; ND_TCHECK(*hb); ND_PRINT((ndo, "MS NLB heartbeat, host priority: %u,", EXTRACT_LE_32BITS(&(hb->host_prio)))); ND_PRINT((ndo, " cluster IP: %s,", ipaddr_string(&(hb->virtual_ip)))); ND_PRINT((ndo, " host IP: %s", ipaddr_string(&(hb->host_ip)))); return; trunc: ND_PRINT((ndo, "[|MS NLB]")); }
void msnlb_print(netdissect_options *ndo, packetbody_t bp, u_int length _U_) { __capability const struct msnlb_heartbeat_pkt *hb; hb = (__capability struct msnlb_heartbeat_pkt *)bp; ND_PACKET_HAS_ONE_OR_TRUNC(hb); ND_PRINT((ndo, "MS NLB heartbeat, host priority: %u,", EXTRACT_LE_32BITS(&(hb->host_prio)))); ND_PRINT((ndo, " cluster IP: %s,", ipaddr_string(&(hb->virtual_ip)))); ND_PRINT((ndo, " host IP: %s", ipaddr_string(&(hb->host_ip)))); return; trunc: ND_PRINT((ndo, "[|MS NLB]")); }
int juniper_read_tlv_value(packetbody_t p, u_int tlv_type, u_int tlv_len) { int tlv_value; /* TLVs < 128 are little endian encoded */ if (tlv_type < 128) { switch (tlv_len) { case 1: tlv_value = *p; break; case 2: tlv_value = EXTRACT_LE_16BITS(p); break; case 3: tlv_value = EXTRACT_LE_24BITS(p); break; case 4: tlv_value = EXTRACT_LE_32BITS(p); break; default: tlv_value = -1; break; } } else { /* TLVs >= 128 are big endian encoded */ switch (tlv_len) { case 1: tlv_value = *p; break; case 2: tlv_value = EXTRACT_16BITS(p); break; case 3: tlv_value = EXTRACT_24BITS(p); break; case 4: tlv_value = EXTRACT_32BITS(p); break; default: tlv_value = -1; break; } } return tlv_value; }
static inline void ppi_header_print(netdissect_options *ndo, const u_char *bp, u_int length) { const ppi_header_t *hdr; uint16_t len; uint32_t dlt; hdr = (const ppi_header_t *)bp; len = EXTRACT_LE_16BITS(&hdr->ppi_len); dlt = EXTRACT_LE_32BITS(&hdr->ppi_dlt); if (!ndo->ndo_qflag) { ND_PRINT((ndo, "V.%d DLT %s (%d) len %d", hdr->ppi_ver, pcap_datalink_val_to_name(dlt), dlt, len)); } else { ND_PRINT((ndo, "%s", pcap_datalink_val_to_name(dlt))); } ND_PRINT((ndo, ", length %u: ", length)); }
static u_int ieee802_11_radio_print(struct smartconfig *sc, const u_char * p, u_int length, u_int caplen) { #define BIT(n) (1U << n) #define IS_EXTENDED(__p) \ (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0 struct cpack_state cpacker; const struct ieee80211_radiotap_header *hdr; uint32_t presentflags; const uint32_t *presentp; u_int len; uint16_t channel = 0; uint8_t flags; if (caplen < sizeof(*hdr)) { return caplen; } hdr = (const struct ieee80211_radiotap_header *)p; len = EXTRACT_LE_16BITS(&hdr->it_len); if (caplen < len) { return caplen; } cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */ cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */ flags = 0; presentp = &hdr->it_present; presentflags = EXTRACT_LE_32BITS(presentp); print_in_radiotap_namespace(sc, &cpacker, &flags, presentflags, 0, &channel); return len + ieee802_11_print(sc, p + len, length - len, caplen - len, channel); }
/* * This is the top level routine of the printer. 'p' points * to the ether header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ u_int pktap_if_print(struct netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { uint32_t dlt, hdrlen, rectype; u_int caplen = h->caplen; u_int length = h->len; if_ndo_printer ndo_printer; if_printer printer; pktap_header_t *hdr; if (caplen < sizeof(pktap_header_t) || length < sizeof(pktap_header_t)) { ND_PRINT((ndo, "[|pktap]")); return (0); } hdr = (pktap_header_t *)p; dlt = EXTRACT_LE_32BITS(&hdr->pkt_dlt); hdrlen = EXTRACT_LE_32BITS(&hdr->pkt_len); if (hdrlen < sizeof(pktap_header_t)) { /* * Claimed header length < structure length. * XXX - does this just mean some fields aren't * being supplied, or is it truly an error (i.e., * is the length supplied so that the header can * be expanded in the future)? */ ND_PRINT((ndo, "[|pktap]")); return (0); } if (caplen < hdrlen || length < hdrlen) { ND_PRINT((ndo, "[|pktap]")); return (hdrlen); } if (ndo->ndo_eflag) pktap_header_print(ndo, p, length); length -= hdrlen; caplen -= hdrlen; p += hdrlen; rectype = EXTRACT_LE_32BITS(&hdr->pkt_rectype); switch (rectype) { case PKT_REC_NONE: ND_PRINT((ndo, "no data")); break; case PKT_REC_PACKET: if ((printer = lookup_printer(dlt)) != NULL) { printer(h, p); } else if ((ndo_printer = lookup_ndo_printer(dlt)) != NULL) { ndo_printer(ndo, h, p); } else { if (!ndo->ndo_eflag) pktap_header_print(ndo, (u_char *)hdr, length + hdrlen); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } break; } return (hdrlen); }
static u_int ieee802_11_radio_print(const u_char *p, u_int length, u_int caplen) { #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x))) #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x))) #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x))) #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x))) #define BITNO_2(x) (((x) & 2) ? 1 : 0) #define BIT(n) (1 << n) #define IS_EXTENDED(__p) \ (EXTRACT_LE_32BITS(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0 struct cpack_state cpacker; struct ieee80211_radiotap_header *hdr; u_int32_t present, next_present; u_int32_t *presentp, *last_presentp; enum ieee80211_radiotap_type bit; int bit0; const u_char *iter; u_int len; int pad; if (caplen < sizeof(*hdr)) { printf("[|802.11]"); return caplen; } hdr = (struct ieee80211_radiotap_header *)p; len = EXTRACT_LE_16BITS(&hdr->it_len); if (caplen < len) { printf("[|802.11]"); return caplen; } for (last_presentp = &hdr->it_present; IS_EXTENDED(last_presentp) && (u_char*)(last_presentp + 1) <= p + len; last_presentp++); /* are there more bitmap extensions than bytes in header? */ if (IS_EXTENDED(last_presentp)) { printf("[|802.11]"); return caplen; } iter = (u_char*)(last_presentp + 1); if (cpack_init(&cpacker, (u_int8_t*)iter, len - (iter - p)) != 0) { /* XXX */ printf("[|802.11]"); return caplen; } /* Assume no Atheros padding between 802.11 header and body */ pad = 0; for (bit0 = 0, presentp = &hdr->it_present; presentp <= last_presentp; presentp++, bit0 += 32) { for (present = EXTRACT_LE_32BITS(presentp); present; present = next_present) { /* clear the least significant bit that is set */ next_present = present & (present - 1); /* extract the least significant bit that is set */ bit = (enum ieee80211_radiotap_type) (bit0 + BITNO_32(present ^ next_present)); if (print_radiotap_field(&cpacker, bit, &pad) != 0) goto out; } } out: return len + ieee802_11_print(p + len, length - len, caplen - len, pad); #undef BITNO_32 #undef BITNO_16 #undef BITNO_8 #undef BITNO_4 #undef BITNO_2 #undef BIT }
/* * Called by pcap_loop; prints a text description of the packet. */ static void handle_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) { /* * note; there is lots of double writing in this function (first stuff is * written to tmpbuf, then its copied from there to buf) but the code is * "safer" this way (no need to keep track of buffer offsets, etc.) and so * far performance isn't an issue. */ char buf[1024] = "", tmpbuf[1024] = ""; int buflen = sizeof(buf); int tmpbuflen = sizeof(tmpbuf); ++pkt_count; if (use_numbering) snprintf(buf, buflen, "%u: ", pkt_count); switch (tsfmt) { case TS_NONE: /* do nothing */ break; case TS_ABS: snprintf(tmpbuf, tmpbuflen, "[%u.%06ld] ", h->ts.tv_sec, h->ts.tv_usec); break; case TS_REL: { static struct timeval last_ts = {0, 0}; assert(h->ts.tv_sec >= last_ts.tv_sec); if (last_ts.tv_sec == 0) { snprintf(tmpbuf, tmpbuflen, "[%u.%06ld] ", 0, 0l); } else if (h->ts.tv_usec >= last_ts.tv_usec) { snprintf(tmpbuf, tmpbuflen, "[%u.%06ld] ", h->ts.tv_sec - last_ts.tv_sec, h->ts.tv_usec - last_ts.tv_usec); } else { /* h->ts.tv_usec < last_ts.tv_usec */ assert(h->ts.tv_sec > last_ts.tv_sec); snprintf(tmpbuf, tmpbuflen, "[%u.%06ld] ", h->ts.tv_sec - last_ts.tv_sec - 1, 1000000l + h->ts.tv_usec - last_ts.tv_usec); } last_ts = h->ts; } case TS_CTIME: { char datebuf[32]; time_t t = h->ts.tv_sec; ctime_r(&t, datebuf + 1); /* move the year to the front, overwriting the day-of-week */ memcpy(datebuf, datebuf + 21, 4); datebuf[4] = ' '; datebuf[20] = '\0'; /* chop the trailing year and newline */ snprintf(tmpbuf, tmpbuflen, "[%s.%06ld] ", datebuf, h->ts.tv_usec); break; } default: assert(0); /* bad value for tsfmt */ } if (strlcat(buf, tmpbuf, buflen) >= buflen) return; int start_buflen = strlen(buf); int flags = 0; if ((enabled_layers[1] + enabled_layers[2] + enabled_layers[3]) == 0) { /* if only layer 0 (MAC) is enabled, then ignore bad LLC values */ flags |= PKTPARSE_IGNORE_BADLLC; } struct packet pkt; if (pktparse_parse(h, sp, dlt, &pkt, flags) == -1) { if (quiet) return; snprintf(tmpbuf, tmpbuflen, "bad packet: %s", pkt.errmsg); strlcat(buf, tmpbuf, buflen); goto finish; } u_char print_sep = 0; /* datalink layer */ if (enabled_layers[0] && ((pkt.ether_hdr != NULL) || (pkt.wifi_hdr != NULL))) { int flags = (enabled_layers[0] > 1) ? PKTPARSE_PRINT_VERBOSE : 0; if (pkt.ether_hdr) { pktparse_print_ethernet(tmpbuf, tmpbuflen, pkt.ether_hdr, flags); } else if (pkt.wifi_hdr) { pktparse_print_wifi(tmpbuf, tmpbuflen, pkt.wifi_hdr, pkt.mgmt_body, flags); } if (strlcat(buf, tmpbuf, buflen) >= buflen) goto finish; /* if enabled, also include the FCS field at the end */ if (print_fcs) { /* if packet was truncated at all, then we lost the FCS at the end */ if ((pkt.caplen == pkt.wirelen) && (pkt.caplen >= 4)) { uint32_t index = pkt.caplen - 4; uint32_t fcs = EXTRACT_LE_32BITS(pkt.raw_packet + index); snprintf(tmpbuf, tmpbuflen, "FCS %08x ", fcs); if (strlcat(buf, tmpbuf, buflen) >= buflen) goto finish; } } print_sep = 1; } /* if both network and transport layers are enabled, print them together */ if (enabled_layers[1] && enabled_layers[2]) { int flags = 0; if ((enabled_layers[1] > 1) || (enabled_layers[2] > 1)) flags |= PKTPARSE_PRINT_VERBOSE; tmpbuf[0] = '\0'; switch (pkt.ethertype) { case -1: /* no ethertype parsed from packet */ break; case ETHERTYPE_IP: if (pkt.ip_hdr) { if (pkt.tcp_hdr) pktparse_print_tcpip(tmpbuf, tmpbuflen, pkt.ip_hdr, pkt.tcp_hdr, pkt.trans_len, flags); else if (pkt.udp_hdr) pktparse_print_udpip(tmpbuf, tmpbuflen, pkt.ip_hdr, pkt.udp_hdr, pkt.trans_len, flags); else pktparse_print_ip_proto(tmpbuf, tmpbuflen, pkt.ip_hdr, pkt.ipproto, pkt.trans_len, flags); } else snprintf(tmpbuf, tmpbuflen, "IP "); break; case ETHERTYPE_IPV6: if (pkt.ip6_hdr) { if (pkt.tcp_hdr) pktparse_print_tcpip6(tmpbuf, tmpbuflen, pkt.ip6_hdr, pkt.tcp_hdr, pkt.trans_len, flags); else if (pkt.udp_hdr) pktparse_print_udpip6(tmpbuf, tmpbuflen, pkt.ip6_hdr, pkt.udp_hdr, pkt.trans_len, flags); else pktparse_print_ip6_proto(tmpbuf, tmpbuflen, pkt.ip6_hdr, pkt.ipproto, pkt.trans_len, flags); } else snprintf(tmpbuf, tmpbuflen, "IPv6 "); break; case ETHERTYPE_ARP: snprintf(tmpbuf, tmpbuflen, "ARP "); break; default: snprintf(tmpbuf, tmpbuflen, "ethertype 0x%04X ", pkt.ethertype); break; } if (strlen(tmpbuf) > 0) { if (print_sep) { if (strlcat(buf, "~ ", buflen) >= buflen) goto finish; print_sep = 0; } if (strlcat(buf, tmpbuf, buflen) >= buflen) goto finish; } } else { /* if we can't merge network and transport layers, print whichever is enabled */ tmpbuf[0] = '\0'; if (enabled_layers[1]) { int flags = (enabled_layers[1] > 1) ? PKTPARSE_PRINT_VERBOSE : 0; switch (pkt.ethertype) { case -1: /* no ethertype parsed from packet */ break; case ETHERTYPE_IP: if (pkt.ip_hdr) pktparse_print_ip(tmpbuf, tmpbuflen, pkt.ip_hdr, pkt.trans_len, flags); break; case ETHERTYPE_IPV6: if (pkt.ip6_hdr) pktparse_print_ip6(tmpbuf, tmpbuflen, pkt.ip6_hdr, pkt.trans_len, flags); break; case ETHERTYPE_ARP: snprintf(tmpbuf, tmpbuflen, "ARP "); break; default: snprintf(tmpbuf, tmpbuflen, "ethertype 0x%04X ", pkt.ethertype); break; } } else if (enabled_layers[2]) { int flags = (enabled_layers[2] > 1) ? PKTPARSE_PRINT_VERBOSE : 0; switch (pkt.ipproto) { case -1: /* no ip-proto parsed from packet */ break; case IPPROTO_IP: snprintf(tmpbuf, tmpbuflen, "IP (encapsulation) "); break; case IPPROTO_ICMP: snprintf(tmpbuf, tmpbuflen, "ICMP "); break; case IPPROTO_IGMP: snprintf(tmpbuf, tmpbuflen, "IGMP "); break; case IPPROTO_TCP: if (pkt.tcp_hdr) pktparse_print_tcp(tmpbuf, tmpbuflen, pkt.tcp_hdr, pkt.trans_len, flags); else snprintf(tmpbuf, tmpbuflen, "TCP "); break; case IPPROTO_UDP: if (pkt.udp_hdr) pktparse_print_udp(tmpbuf, tmpbuflen, pkt.udp_hdr, pkt.trans_len, flags); else snprintf(tmpbuf, tmpbuflen, "UDP "); break; default: snprintf(tmpbuf, tmpbuflen, "ipproto 0x%02X ", pkt.ipproto); break; } } if (strlen(tmpbuf) > 0) { if (print_sep) { if (strlcat(buf, "~ ", buflen) >= buflen) goto finish; print_sep = 0; } if (strlcat(buf, tmpbuf, buflen) >= buflen) goto finish; } } /* application layer */ if (enabled_layers[3]) { /* only HTTP request parsing is implemented so far */ struct http_request *req = NULL; if (pkt.tcp_hdr != NULL) { req = pktparse_parse_http_request((char*)pkt.unparsed, pkt.unparsed_len); } if (req != NULL) { if (req->resource[0] == '/') snprintf(tmpbuf, tmpbuflen, "%s %s%s ", req->method, req->host, req->resource); else snprintf(tmpbuf, tmpbuflen, "%s %s/%s ", req->method, req->host, req->resource); if (strlcat(buf, tmpbuf, buflen) >= buflen) goto finish; /* if verbose printing is enabled, include the User-Agent string */ if (enabled_layers[3] > 1) { snprintf(tmpbuf, tmpbuflen, "User-Agent: %s", req->user_agent); if (strlcat(buf, tmpbuf, buflen) >= buflen) goto finish; } free(req); } } finish: if (strlen(buf) > start_buflen) printf("%s\n", buf); }