+
+
+void
+convert_to_pktap_header_to_v2(struct bpf_packet *bpf_pkt, bool truncate)
+{
+ struct pktap_header *pktap_header;
+ size_t extra_src_size;
+ struct pktap_buffer_v2_hdr_extra pktap_buffer_v2_hdr_extra;
+ struct pktap_v2_hdr_space *pktap_v2_hdr_space;
+ struct pktap_v2_hdr *pktap_v2_hdr;
+ uint8_t *ptr;
+
+ pktap_header = (struct pktap_header *)bpf_pkt->bpfp_header;
+
+ if (pktap_header->pth_type_next != PTH_TYPE_PACKET) {
+ return;
+ }
+
+ VERIFY(bpf_pkt->bpfp_header_length >= sizeof(struct pktap_header));
+
+ /*
+ * extra_src_size is the length of the optional link layer header
+ */
+ extra_src_size = bpf_pkt->bpfp_header_length -
+ sizeof(struct pktap_header);
+
+ VERIFY(extra_src_size <= sizeof(union pktap_header_extra));
+
+ pktap_v2_hdr_space = &pktap_buffer_v2_hdr_extra.hdr_space;
+ pktap_v2_hdr = &pktap_v2_hdr_space->pth_hdr;
+ ptr = (uint8_t *) (pktap_v2_hdr + 1);
+
+ COPY_PKTAP_COMMON_FIELDS_TO_V2(pktap_v2_hdr, pktap_header);
+
+ /*
+ * When truncating don't bother with the process UUIDs
+ */
+ if (!truncate) {
+ if ((pktap_header->pth_flags & PTH_FLAG_DELAY_PKTAP)) {
+ pktap_v2_hdr->pth_uuid_offset = pktap_v2_hdr->pth_length;
+ pktap_v2_hdr->pth_length += sizeof(uuid_t);
+ uuid_clear(*(uuid_t *)ptr);
+ ptr += sizeof(uuid_t);
+ VERIFY((void *)ptr < (void *)(pktap_v2_hdr_space + 1));
+ } else if (!uuid_is_null(pktap_header->pth_uuid)) {
+ pktap_v2_hdr->pth_uuid_offset = pktap_v2_hdr->pth_length;
+ uuid_copy(*(uuid_t *)ptr, pktap_header->pth_uuid);
+ pktap_v2_hdr->pth_length += sizeof(uuid_t);
+ ptr += sizeof(uuid_t);
+ VERIFY((void *)ptr < (void *)(pktap_v2_hdr_space + 1));
+ }
+
+ if ((pktap_header->pth_flags & PTH_FLAG_DELAY_PKTAP)) {
+ if (pktap_header->pth_flags & PTH_FLAG_PROC_DELEGATED) {
+ pktap_v2_hdr->pth_e_uuid_offset = pktap_v2_hdr->pth_length;
+ uuid_clear(*(uuid_t *)ptr);
+ pktap_v2_hdr->pth_length += sizeof(uuid_t);
+ ptr += sizeof(uuid_t);
+ VERIFY((void *)ptr < (void *)(pktap_v2_hdr_space + 1));
+ }
+ } else if (!uuid_is_null(pktap_header->pth_euuid)) {
+ pktap_v2_hdr->pth_e_uuid_offset = pktap_v2_hdr->pth_length;
+ uuid_copy(*(uuid_t *)ptr, pktap_header->pth_euuid);
+ pktap_v2_hdr->pth_length += sizeof(uuid_t);
+ ptr += sizeof(uuid_t);
+ VERIFY((void *)ptr < (void *)(pktap_v2_hdr_space + 1));
+ }
+ }
+
+ if (pktap_header->pth_ifname[0] != 0) {
+ size_t strsize;
+
+ pktap_v2_hdr->pth_ifname_offset = pktap_v2_hdr->pth_length;
+
+ /*
+ * Note: strlcpy() returns the length of the string so we need
+ * to add one for the end-of-string
+ */
+ strsize = 1 + strlcpy((char *)ptr, pktap_header->pth_ifname,
+ sizeof(pktap_v2_hdr_space->pth_ifname));
+ pktap_v2_hdr->pth_length += strsize;
+ ptr += strsize;
+ VERIFY((void *)ptr < (void *)(pktap_v2_hdr_space + 1));
+ }
+
+ /*
+ * Do not waste space with the process name if we do not have a pid
+ */
+ if (pktap_header->pth_pid != 0 && pktap_header->pth_pid != -1) {
+ if (pktap_header->pth_comm[0] != 0) {
+ size_t strsize;
+
+ pktap_v2_hdr->pth_comm_offset = pktap_v2_hdr->pth_length;
+
+ strsize = 1 + strlcpy((char *)ptr, pktap_header->pth_comm,
+ sizeof(pktap_v2_hdr_space->pth_comm));
+ pktap_v2_hdr->pth_length += strsize;
+ ptr += strsize;
+ VERIFY((void *)ptr < (void *)(pktap_v2_hdr_space + 1));
+ } else if ((pktap_header->pth_flags & PTH_FLAG_DELAY_PKTAP)) {
+ size_t strsize = sizeof(pktap_v2_hdr_space->pth_comm);
+
+ pktap_v2_hdr->pth_comm_offset = pktap_v2_hdr->pth_length;
+
+ *ptr = 0; /* empty string by default */
+ pktap_v2_hdr->pth_length += strsize;
+ ptr += strsize;
+ VERIFY((void *)ptr < (void *)(pktap_v2_hdr_space + 1));
+ }
+ }
+
+ /*
+ * Do not waste space with the effective process name if we do not have
+ * an effective pid or it's the same as the pid
+ */
+ if (pktap_header->pth_epid != 0 && pktap_header->pth_epid != -1 &&
+ pktap_header->pth_epid != pktap_header->pth_pid) {
+ if (pktap_header->pth_ecomm[0] != 0) {
+ size_t strsize;
+
+ pktap_v2_hdr->pth_e_comm_offset = pktap_v2_hdr->pth_length;
+
+ strsize = 1 + strlcpy((char *)ptr, pktap_header->pth_ecomm,
+ sizeof(pktap_v2_hdr_space->pth_e_comm));
+ pktap_v2_hdr->pth_length += strsize;
+ ptr += strsize;
+ VERIFY((void *)ptr < (void *)(pktap_v2_hdr_space + 1));
+ } else if ((pktap_header->pth_flags & PTH_FLAG_DELAY_PKTAP)) {
+ size_t strsize = sizeof(pktap_v2_hdr_space->pth_e_comm);
+
+ pktap_v2_hdr->pth_e_comm_offset = pktap_v2_hdr->pth_length;
+ *ptr = 0; /* empty string by default */
+ pktap_v2_hdr->pth_length += strsize;
+ ptr += strsize;
+ VERIFY((void *)ptr < (void *)(pktap_v2_hdr_space + 1));
+ }
+ }
+
+ if (extra_src_size > 0) {
+ char *extra_src_ptr = (char *)(pktap_header + 1);
+ char *extra_dst_ptr = ((char *)pktap_v2_hdr) +
+ pktap_v2_hdr->pth_length;
+
+ VERIFY(pktap_v2_hdr->pth_length + extra_src_size <=
+ sizeof(struct pktap_buffer_v2_hdr_extra));
+
+ memcpy(extra_dst_ptr, extra_src_ptr, extra_src_size);
+ }
+
+ VERIFY(pktap_v2_hdr->pth_length + extra_src_size <=
+ bpf_pkt->bpfp_header_length);
+
+ memcpy(bpf_pkt->bpfp_header, pktap_v2_hdr,
+ pktap_v2_hdr->pth_length + extra_src_size);
+
+ bpf_pkt->bpfp_total_length += pktap_v2_hdr->pth_length -
+ sizeof(struct pktap_header);
+ bpf_pkt->bpfp_header_length += pktap_v2_hdr->pth_length -
+ sizeof(struct pktap_header);
+}