/* * ATTN: When changing anything here check m_inithdr() and m_defrag() those * may need to change as well. */ struct mbuf * m_gethdr(int nowait, int type) { struct mbuf *m; m = pool_get(&mbpool, nowait == M_WAIT ? PR_WAITOK : PR_NOWAIT); if (m == NULL) return (NULL); mtx_enter(&mbstatmtx); mbstat.m_mtypes[type]++; mtx_leave(&mbstatmtx); m->m_type = type; return (m_inithdr(m)); }
void pflog_bpfcopy(const void *src_arg, void *dst_arg, size_t len) { struct mbuf *m, *mp, *mhdr, *mptr; struct pfloghdr *pfloghdr; u_int count; u_char *dst, *mdst, *cp; u_short reason; int afto, hlen, mlen, off; union pf_headers { struct tcphdr tcp; struct udphdr udp; struct icmp icmp; #ifdef INET6 struct icmp6_hdr icmp6; struct mld_hdr mld; struct nd_neighbor_solicit nd_ns; #endif /* INET6 */ } pdhdrs; struct pf_pdesc pd; struct pf_addr osaddr, odaddr; u_int16_t osport = 0, odport = 0; u_int8_t proto = 0; m = (struct mbuf *)src_arg; dst = dst_arg; mhdr = pflog_mhdr; mptr = pflog_mptr; if (m == NULL) panic("pflog_bpfcopy got no mbuf"); /* first mbuf holds struct pfloghdr */ pfloghdr = mtod(m, struct pfloghdr *); afto = pfloghdr->af != pfloghdr->naf; count = min(m->m_len, len); bcopy(pfloghdr, dst, count); pfloghdr = (struct pfloghdr *)dst; dst += count; len -= count; m = m->m_next; if (len <= 0) return; /* second mbuf is pkthdr */ if (m == NULL) panic("no second mbuf"); /* * temporary mbuf will hold an ip/ip6 header and 8 bytes * of the protocol header */ m_inithdr(mhdr); mhdr->m_len = 0; /* XXX not done in m_inithdr() */ #if INET && INET6 /* offset for a new header */ if (afto && pfloghdr->af == AF_INET) mhdr->m_data += sizeof(struct ip6_hdr) - sizeof(struct ip); #endif /* INET && INET6 */ mdst = mtod(mhdr, char *); switch (pfloghdr->af) { case AF_INET: { struct ip *h; if (m->m_pkthdr.len < sizeof(*h)) goto copy; m_copydata(m, 0, sizeof(*h), mdst); h = (struct ip *)mdst; hlen = h->ip_hl << 2; if (hlen > sizeof(*h) && (m->m_pkthdr.len >= hlen)) m_copydata(m, sizeof(*h), hlen - sizeof(*h), mdst + sizeof(*h)); break; } #ifdef INET6 case AF_INET6: { struct ip6_hdr *h; if (m->m_pkthdr.len < sizeof(*h)) goto copy; hlen = sizeof(struct ip6_hdr); m_copydata(m, 0, hlen, mdst); h = (struct ip6_hdr *)mdst; proto = h->ip6_nxt; break; } #endif /* INET6 */ default: /* shouldn't happen ever :-) */ goto copy; } if (m->m_pkthdr.len < hlen + 8 && proto != IPPROTO_NONE) goto copy; else if (proto != IPPROTO_NONE) { /* copy 8 bytes of the protocol header */ m_copydata(m, hlen, 8, mdst + hlen); hlen += 8; } mhdr->m_len += hlen; mhdr->m_pkthdr.len = mhdr->m_len; /* create a chain mhdr -> mptr, mptr->m_data = (m->m_data+hlen) */ mp = m_getptr(m, hlen, &off); if (mp != NULL) { bcopy(mp, mptr, sizeof(*mptr)); cp = mtod(mp, char *); mptr->m_data += off; mptr->m_len -= off; mptr->m_flags &= ~M_PKTHDR; mhdr->m_next = mptr; mhdr->m_pkthdr.len += m->m_pkthdr.len - hlen; }
void pflog_bpfcopy(const void *src_arg, void *dst_arg, size_t len) { struct mbuf *m, *mp, *mhdr, *mptr; struct pfloghdr *pfloghdr; u_int count; u_char *dst, *mdst; int afto, hlen, mlen, off; union pf_headers { struct tcphdr tcp; struct udphdr udp; struct icmp icmp; #ifdef INET6 struct icmp6_hdr icmp6; struct mld_hdr mld; struct nd_neighbor_solicit nd_ns; #endif /* INET6 */ } pdhdrs; struct pf_pdesc pd; struct pf_addr osaddr, odaddr; u_int16_t osport = 0, odport = 0; u_int8_t proto = 0; m = (struct mbuf *)src_arg; dst = dst_arg; mhdr = pflog_mhdr; mptr = pflog_mptr; if (m == NULL) panic("pflog_bpfcopy got no mbuf"); /* first mbuf holds struct pfloghdr */ pfloghdr = mtod(m, struct pfloghdr *); afto = pfloghdr->af != pfloghdr->naf; count = min(m->m_len, len); bcopy(pfloghdr, dst, count); pfloghdr = (struct pfloghdr *)dst; dst += count; len -= count; m = m->m_next; if (len <= 0) return; /* second mbuf is pkthdr */ if (m == NULL) panic("no second mbuf"); /* * temporary mbuf will hold an ip/ip6 header and 8 bytes * of the protocol header */ m_inithdr(mhdr); mhdr->m_len = 0; /* XXX not done in m_inithdr() */ #if INET && INET6 /* offset for a new header */ if (afto && pfloghdr->af == AF_INET) mhdr->m_data += sizeof(struct ip6_hdr) - sizeof(struct ip); #endif /* INET && INET6 */ mdst = mtod(mhdr, char *); switch (pfloghdr->af) { case AF_INET: { struct ip *h; if (m->m_pkthdr.len < sizeof(*h)) goto copy; m_copydata(m, 0, sizeof(*h), mdst); h = (struct ip *)mdst; hlen = h->ip_hl << 2; if (hlen > sizeof(*h) && (m->m_pkthdr.len >= hlen)) m_copydata(m, sizeof(*h), hlen - sizeof(*h), mdst + sizeof(*h)); break; } #ifdef INET6 case AF_INET6: { struct ip6_hdr *h; if (m->m_pkthdr.len < sizeof(*h)) goto copy; hlen = sizeof(struct ip6_hdr); m_copydata(m, 0, hlen, mdst); h = (struct ip6_hdr *)mdst; proto = h->ip6_nxt; break; } #endif /* INET6 */ default: /* shouldn't happen ever :-) */ goto copy; } if (m->m_pkthdr.len < hlen + 8 && proto != IPPROTO_NONE) goto copy; else if (proto != IPPROTO_NONE) { /* copy 8 bytes of the protocol header */ m_copydata(m, hlen, 8, mdst + hlen); hlen += 8; } mhdr->m_len += hlen; mhdr->m_pkthdr.len = mhdr->m_len; /* create a chain mhdr -> mptr, mptr->m_data = (m->m_data+hlen) */ mp = m_getptr(m, hlen, &off); if (mp != NULL) { bcopy(mp, mptr, sizeof(*mptr)); mptr->m_data += off; mptr->m_len -= off; mptr->m_flags &= ~M_PKTHDR; mhdr->m_next = mptr; mhdr->m_pkthdr.len += m->m_pkthdr.len - hlen; } /* * Rewrite addresses if needed. Reason pointer must be NULL to avoid * counting the packet here again. */ if (pf_setup_pdesc(&pd, &pdhdrs, pfloghdr->af, pfloghdr->dir, NULL, mhdr, NULL) != PF_PASS) goto copy; pd.naf = pfloghdr->naf; PF_ACPY(&osaddr, pd.src, pd.af); PF_ACPY(&odaddr, pd.dst, pd.af); if (pd.sport) osport = *pd.sport; if (pd.dport) odport = *pd.dport; if (pd.virtual_proto != PF_VPROTO_FRAGMENT && (pfloghdr->rewritten = pf_translate(&pd, &pfloghdr->saddr, pfloghdr->sport, &pfloghdr->daddr, pfloghdr->dport, 0, pfloghdr->dir))) { m_copyback(pd.m, pd.off, min(pd.m->m_len - pd.off, pd.hdrlen), pd.hdr.any, M_NOWAIT); #if INET && INET6 if (afto) { PF_ACPY(&pd.nsaddr, &pfloghdr->saddr, pd.naf); PF_ACPY(&pd.ndaddr, &pfloghdr->daddr, pd.naf); } #endif /* INET && INET6 */ PF_ACPY(&pfloghdr->saddr, &osaddr, pd.af); PF_ACPY(&pfloghdr->daddr, &odaddr, pd.af); pfloghdr->sport = osport; pfloghdr->dport = odport; } pd.tot_len = min(pd.tot_len, len); pd.tot_len -= pd.m->m_data - pd.m->m_pktdat; #if INET && INET6 if (afto && pfloghdr->rewritten) pf_translate_af(&pd); #endif /* INET && INET6 */ m = pd.m; copy: mlen = min(m->m_pkthdr.len, len); m_copydata(m, 0, mlen, dst); len -= mlen; if (len > 0) bzero(dst + mlen, len); }