static status_t compat_write(void *cookie, off_t position, const void *buffer, size_t *numBytes) { struct ifnet *ifp = cookie; struct mbuf *mb; //if_printf(ifp, "compat_write(%lld, %p, [%lu])\n", position, // buffer, *numBytes); if (*numBytes > MHLEN) mb = m_getcl(0, MT_DATA, M_PKTHDR); else mb = m_gethdr(0, MT_DATA); if (mb == NULL) return ENOBUFS; // if we waited, check after if the ifp is still valid mb->m_pkthdr.len = mb->m_len = min_c(*numBytes, (size_t)MCLBYTES); memcpy(mtod(mb, void *), buffer, mb->m_len); return ifp->if_output(ifp, mb, NULL, NULL); }
void * ff_mbuf_gethdr(void *pkt, uint16_t total, void *data, uint16_t len, uint8_t rx_csum) { struct mbuf *m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) { return NULL; } if (m_pkthdr_init(m, M_NOWAIT) != 0) { return NULL; } m_extadd(m, data, len, ff_mbuf_ext_free, pkt, NULL, 0, EXT_DISPOSABLE); m->m_pkthdr.len = total; m->m_len = len; m->m_next = NULL; m->m_nextpkt = NULL; if (rx_csum) { m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR; m->m_pkthdr.csum_data = 0xffff; } return (void *)m; }
/* * Insert IP options into preformed packet. Adjust IP destination as * required for IP source routing, as indicated by a non-zero in_addr at the * start of the options. * * XXX This routine assumes that the packet has no options in place. */ struct mbuf * ip_insertoptions(struct mbuf *m, struct mbuf *opt, int *phlen) { struct ipoption *p = mtod(opt, struct ipoption *); struct mbuf *n; struct ip *ip = mtod(m, struct ip *); unsigned optlen; optlen = opt->m_len - sizeof(p->ipopt_dst); if (optlen + ntohs(ip->ip_len) > IP_MAXPACKET) { *phlen = 0; return (m); /* XXX should fail */ } if (p->ipopt_dst.s_addr) ip->ip_dst = p->ipopt_dst; if (!M_WRITABLE(m) || M_LEADINGSPACE(m) < optlen) { n = m_gethdr(M_NOWAIT, MT_DATA); if (n == NULL) { *phlen = 0; return (m); } m_move_pkthdr(n, m); n->m_pkthdr.rcvif = NULL; n->m_pkthdr.len += optlen; m->m_len -= sizeof(struct ip); m->m_data += sizeof(struct ip); n->m_next = m; m = n; m->m_len = optlen + sizeof(struct ip); m->m_data += max_linkhdr; bcopy(ip, mtod(m, void *), sizeof(struct ip)); } else {
/* * Builds and sends a single ARP request to locate the server * * Return value: * 0 on success * errno on error */ static int netdump_send_arp(in_addr_t dst) { struct ether_addr bcast; struct mbuf *m; struct arphdr *ah; int pktlen; MPASS(nd_ifp != NULL); /* Fill-up a broadcast address. */ memset(&bcast, 0xFF, ETHER_ADDR_LEN); m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) { printf("netdump_send_arp: Out of mbufs\n"); return (ENOBUFS); } pktlen = arphdr_len2(ETHER_ADDR_LEN, sizeof(struct in_addr)); m->m_len = pktlen; m->m_pkthdr.len = pktlen; MH_ALIGN(m, pktlen); ah = mtod(m, struct arphdr *); ah->ar_hrd = htons(ARPHRD_ETHER); ah->ar_pro = htons(ETHERTYPE_IP); ah->ar_hln = ETHER_ADDR_LEN; ah->ar_pln = sizeof(struct in_addr); ah->ar_op = htons(ARPOP_REQUEST); memcpy(ar_sha(ah), IF_LLADDR(nd_ifp), ETHER_ADDR_LEN); ((struct in_addr *)ar_spa(ah))->s_addr = nd_client.s_addr; bzero(ar_tha(ah), ETHER_ADDR_LEN); ((struct in_addr *)ar_tpa(ah))->s_addr = dst; return (netdump_ether_output(m, nd_ifp, bcast, ETHERTYPE_ARP)); }
/* * Send a single message to the TCP at address specified by * the given TCP/IP header. If m == 0, then we make a copy * of the tcpiphdr at ti and send directly to the addressed host. * This is used to force keep alive messages out using the TCP * template for a connection tp->t_template. If flags are given * then we send a message back to the TCP which originated the * segment ti, and discard the mbuf containing it and any other * attached mbufs. * * In any case the ack and sequence number of the transmitted * segment are as specified by the parameters. */ void tcp_respond(PNATState pData, struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags) { register int tlen; int win = 0; LogFlowFunc(("ENTER: tp = %R[tcpcb793], ti = %lx, m = %lx, ack = %u, seq = %u, flags = %x\n", tp, (long)ti, (long)m, ack, seq, flags)); if (tp) win = sbspace(&tp->t_socket->so_rcv); if (m == 0) { if ((m = m_gethdr(pData, M_DONTWAIT, MT_HEADER)) == NULL) return; #ifdef TCP_COMPAT_42 tlen = 1; #else tlen = 0; #endif m->m_data += if_maxlinkhdr; m->m_pkthdr.header = mtod(m, void *); *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); flags = TH_ACK; } else {
struct mbuf * mbuf_construct(int proto) { struct mbuf *m; struct ip *iphdr; void *l4data; int size; m = m_gethdr(M_WAITOK, MT_HEADER); iphdr = mtod(m, struct ip *); iphdr->ip_v = IPVERSION; iphdr->ip_hl = sizeof(struct ip) >> 2; iphdr->ip_off = 0; iphdr->ip_ttl = 64; iphdr->ip_p = proto; size = sizeof(struct ip); l4data = (void *)(iphdr + 1); size += mbuf_fill_proto(proto, l4data); iphdr->ip_len = htons(size); m->m_len = size; m->m_next = NULL; return m; }
/* * Routine to copy from device local memory into mbufs. * Note that `off' argument is offset into first mbuf of target chain from * which to begin copying the data to. */ struct mbuf * m_devget(char *buf, int totlen, int off, struct ifnet *ifp, void (*copy)(char *from, caddr_t to, u_int len)) { struct mbuf *m; struct mbuf *top = NULL, **mp = ⊤ int len; if (off < 0 || off > MHLEN) return (NULL); while (totlen > 0) { if (top == NULL) { /* First one, must be PKTHDR */ if (totlen + off >= MINCLSIZE) { m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); len = MCLBYTES; } else { m = m_gethdr(M_NOWAIT, MT_DATA); len = MHLEN; /* Place initial small packet/header at end of mbuf */ if (m && totlen + off + max_linkhdr <= MLEN) { m->m_data += max_linkhdr; len -= max_linkhdr; } } if (m == NULL) return NULL; m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = totlen; } else { if (totlen + off >= MINCLSIZE) { m = m_getcl(M_NOWAIT, MT_DATA, 0); len = MCLBYTES; } else { m = m_get(M_NOWAIT, MT_DATA); len = MLEN; } if (m == NULL) { m_freem(top); return NULL; } } if (off) { m->m_data += off; len -= off; off = 0; } m->m_len = len = min(totlen, len); if (copy) copy(buf, mtod(m, caddr_t), (u_int)len); else bcopy(buf, mtod(m, caddr_t), (u_int)len); buf += len; *mp = m; mp = &m->m_next; totlen -= len; } return (top); }
struct icl_pdu * icl_cxgbei_new_pdu(int flags) { struct icl_cxgbei_pdu *icp; struct icl_pdu *ip; struct mbuf *m; uintptr_t a; m = m_gethdr(flags, MT_DATA); if (__predict_false(m == NULL)) return (NULL); a = roundup2(mtod(m, uintptr_t), _Alignof(struct icl_cxgbei_pdu)); icp = (struct icl_cxgbei_pdu *)a; bzero(icp, sizeof(*icp)); icp->icp_signature = CXGBEI_PDU_SIGNATURE; ip = &icp->ip; ip->ip_bhs_mbuf = m; a = roundup2((uintptr_t)(icp + 1), _Alignof(struct iscsi_bhs *)); ip->ip_bhs = (struct iscsi_bhs *)a; #ifdef INVARIANTS /* Everything must fit entirely in the mbuf. */ a = (uintptr_t)(ip->ip_bhs + 1); MPASS(a <= (uintptr_t)m + MSIZE); #endif bzero(ip->ip_bhs, sizeof(*ip->ip_bhs)); m->m_data = (void *)ip->ip_bhs; m->m_len = sizeof(struct iscsi_bhs); m->m_pkthdr.len = m->m_len; return (ip); }
/* * Create an mbuf chain, each of 1 byte size. */ static struct mbuf * mbuf_bytesize(size_t clen) { struct mbuf *m0 = NULL, *m = NULL; u_int i, n; /* Chain of clen (e.g. 128) mbufs, each storing 1 byte of data. */ for (i = 0, n = 0; i < clen; i++) { /* Range of offset: 0 .. 15. */ m0 = mbuf_alloc_with_off(n & 0xf, 1); /* Fill data with letters from 'a' to 'z'. */ memset(m0->m_data, 'a' + n, 1); n = ('a' + n) < 'z' ? n + 1 : 0; /* Next mbuf.. */ m0->m_next = m; m = m0; } m0 = m_gethdr(M_WAITOK, MT_HEADER); m0->m_pkthdr.len = clen; m0->m_len = 0; m0->m_next = m; return m0; }
/* * Allocate icl_pdu with empty BHS to fill up by the caller. */ struct icl_pdu * icl_soft_conn_new_pdu(struct icl_conn *ic, int flags) { struct icl_pdu *ip; #ifdef DIAGNOSTIC refcount_acquire(&ic->ic_outstanding_pdus); #endif ip = uma_zalloc(icl_pdu_zone, flags | M_ZERO); if (ip == NULL) { ICL_WARN("failed to allocate %zd bytes", sizeof(*ip)); #ifdef DIAGNOSTIC refcount_release(&ic->ic_outstanding_pdus); #endif return (NULL); } ip->ip_conn = ic; CTASSERT(sizeof(struct iscsi_bhs) <= MHLEN); ip->ip_bhs_mbuf = m_gethdr(flags, MT_DATA); if (ip->ip_bhs_mbuf == NULL) { ICL_WARN("failed to allocate BHS mbuf"); icl_soft_conn_pdu_free(ic, ip); return (NULL); } ip->ip_bhs = mtod(ip->ip_bhs_mbuf, struct iscsi_bhs *); memset(ip->ip_bhs, 0, sizeof(struct iscsi_bhs)); ip->ip_bhs_mbuf->m_len = sizeof(struct iscsi_bhs); return (ip); }
struct mbuf * m_clget(struct mbuf *m, int how, u_int pktlen) { struct mbuf *m0 = NULL; struct pool *pp; caddr_t buf; pp = m_clpool(pktlen); #ifdef DIAGNOSTIC if (pp == NULL) panic("m_clget: request for %u byte cluster", pktlen); #endif if (m == NULL) { m0 = m_gethdr(how, MT_DATA); if (m0 == NULL) return (NULL); m = m0; } buf = pool_get(pp, how == M_WAIT ? PR_WAITOK : PR_NOWAIT); if (buf == NULL) { if (m0) m_freem(m0); return (NULL); } MEXTADD(m, buf, pp->pr_size, M_EXTWR, m_extfree_pool, pp); return (m); }
/* * Re-align the payload in the mbuf. This is mainly used (right now) * to handle IP header alignment requirements on certain architectures. */ struct mbuf * ieee80211_realign(struct ieee80211vap *vap, struct mbuf *m, size_t align) { int pktlen, space; struct mbuf *n; pktlen = m->m_pkthdr.len; space = pktlen + align; if (space < MINCLSIZE) n = m_gethdr(M_NOWAIT, MT_DATA); else { n = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, space <= MCLBYTES ? MCLBYTES : #if MJUMPAGESIZE != MCLBYTES space <= MJUMPAGESIZE ? MJUMPAGESIZE : #endif space <= MJUM9BYTES ? MJUM9BYTES : MJUM16BYTES); } if (__predict_true(n != NULL)) { m_move_pkthdr(n, m); n->m_data = (caddr_t)(ALIGN(n->m_data + align) - align); m_copydata(m, 0, pktlen, mtod(n, caddr_t)); n->m_len = pktlen; } else { IEEE80211_DISCARD(vap, IEEE80211_MSG_ANY, mtod(m, const struct ieee80211_frame *), NULL, "%s", "no mbuf to realign"); vap->iv_stats.is_rx_badalign++; } m_freem(m); return n; }
/* * Allocate and setup a management frame of the specified * size. We return the mbuf and a pointer to the start * of the contiguous data area that's been reserved based * on the packet length. The data area is forced to 32-bit * alignment and the buffer length to a multiple of 4 bytes. * This is done mainly so beacon frames (that require this) * can use this interface too. */ struct mbuf * ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen) { struct mbuf *m; u_int len; /* * NB: we know the mbuf routines will align the data area * so we don't need to do anything special. */ len = roundup2(headroom + pktlen, 4); KASSERT(len <= MCLBYTES, ("802.11 mgt frame too large: %u", len)); if (len < MINCLSIZE) { m = m_gethdr(M_NOWAIT, MT_DATA); /* * Align the data in case additional headers are added. * This should only happen when a WEP header is added * which only happens for shared key authentication mgt * frames which all fit in MHLEN. */ if (m != NULL) MH_ALIGN(m, len); } else { m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); if (m != NULL) MC_ALIGN(m, len); } if (m != NULL) { m->m_data += headroom; *frm = m->m_data; } return m; }
static void virtif_worker(void *arg) { struct ifnet *ifp = arg; struct virtif_sc *sc = ifp->if_softc; struct mbuf *m; size_t plen = ETHER_MAX_LEN_JUMBO+1; ssize_t n; int error; for (;;) { m = m_gethdr(M_WAIT, MT_DATA); MEXTMALLOC(m, plen, M_WAIT); n = rumpuser_read(sc->sc_tapfd, mtod(m, void *), plen, &error); KASSERT(n < ETHER_MAX_LEN_JUMBO); if (n <= 0) { m_freem(m); break; } m->m_len = m->m_pkthdr.len = n; m->m_pkthdr.rcvif = ifp; ether_input(ifp, m); } panic("virtif_workin is a lazy boy %d\n", error); }
/* * Helper for sbappendchainaddr: prepend a struct sockaddr* to * an mbuf chain. */ static inline struct mbuf * m_prepend_sockaddr(struct sockbuf *sb, struct mbuf *m0, const struct sockaddr *asa) { struct mbuf *m; const int salen = asa->sa_len; KASSERT(solocked(sb->sb_so)); /* only the first in each chain need be a pkthdr */ m = m_gethdr(M_DONTWAIT, MT_SONAME); if (m == NULL) return NULL; MCLAIM(m, sb->sb_mowner); #ifdef notyet if (salen > MHLEN) { MEXTMALLOC(m, salen, M_NOWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); return NULL; } } #else KASSERT(salen <= MHLEN); #endif m->m_len = salen; memcpy(mtod(m, void *), asa, salen); m->m_next = m0; m->m_pkthdr.len = salen + m0->m_pkthdr.len; return m; }
errno_t mbuf_gethdr(mbuf_how_t how, mbuf_type_t type, mbuf_t *mbuf) { /* Must set *mbuf to NULL in failure case */ *mbuf = m_gethdr(how, type); return (*mbuf == NULL ? ENOMEM : 0); }
static bool_t svc_vc_backchannel_reply(SVCXPRT *xprt, struct rpc_msg *msg, struct sockaddr *addr, struct mbuf *m, uint32_t *seq) { struct ct_data *ct; XDR xdrs; struct mbuf *mrep; bool_t stat = TRUE; int error; /* * Leave space for record mark. */ mrep = m_gethdr(M_WAITOK, MT_DATA); mrep->m_data += sizeof(uint32_t); xdrmbuf_create(&xdrs, mrep, XDR_ENCODE); if (msg->rm_reply.rp_stat == MSG_ACCEPTED && msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { if (!xdr_replymsg(&xdrs, msg)) stat = FALSE; else xdrmbuf_append(&xdrs, m); } else { stat = xdr_replymsg(&xdrs, msg); } if (stat) { m_fixhdr(mrep); /* * Prepend a record marker containing the reply length. */ M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK); *mtod(mrep, uint32_t *) = htonl(0x80000000 | (mrep->m_pkthdr.len - sizeof(uint32_t))); sx_xlock(&xprt->xp_lock); ct = (struct ct_data *)xprt->xp_p2; if (ct != NULL) error = sosend(ct->ct_socket, NULL, NULL, mrep, NULL, 0, curthread); else error = EPIPE; sx_xunlock(&xprt->xp_lock); if (!error) { stat = TRUE; } } else { m_freem(mrep); } XDR_DESTROY(&xdrs); return (stat); }
/* * Allocate a given length worth of mbufs and/or clusters (whatever fits * best) and return a pointer to the top of the allocated chain. If an * existing mbuf chain is provided, then we will append the new chain * to the existing one but still return the top of the newly allocated * chain. */ struct mbuf * m_getm2(struct mbuf *m, int len, int how, short type, int flags) { struct mbuf *mb, *nm = NULL, *mtail = NULL; KASSERT(len >= 0, ("%s: len is < 0", __func__)); /* Validate flags. */ flags &= (M_PKTHDR | M_EOR); /* Packet header mbuf must be first in chain. */ if ((flags & M_PKTHDR) && m != NULL) flags &= ~M_PKTHDR; /* Loop and append maximum sized mbufs to the chain tail. */ while (len > 0) { if (len > MCLBYTES) mb = m_getjcl(how, type, (flags & M_PKTHDR), MJUMPAGESIZE); else if (len >= MINCLSIZE) mb = m_getcl(how, type, (flags & M_PKTHDR)); else if (flags & M_PKTHDR) mb = m_gethdr(how, type); else mb = m_get(how, type); /* Fail the whole operation if one mbuf can't be allocated. */ if (mb == NULL) { if (nm != NULL) m_freem(nm); return (NULL); } /* Book keeping. */ len -= M_SIZE(mb); if (mtail != NULL) mtail->m_next = mb; else nm = mb; mtail = mb; flags &= ~M_PKTHDR; /* Only valid on the first mbuf. */ } if (flags & M_EOR) mtail->m_flags |= M_EOR; /* Only valid on the last mbuf. */ /* If mbuf was supplied, append new chain to the end of it. */ if (m != NULL) { for (mtail = m; mtail->m_next != NULL; mtail = mtail->m_next) ; mtail->m_next = nm; mtail->m_flags &= ~M_EOR; } else m = nm; return (m); }
/* * Various helper functions */ int mb_init(struct mbchain *mbp) { struct mbuf *m; m = m_gethdr(M_WAIT, MT_DATA); m->m_len = 0; mb_initm(mbp, m); return 0; }
/* * Routines for fetching data from an mbuf chain */ int md_init(struct mdchain *mdp) { struct mbuf *m; m = m_gethdr(M_WAIT, MT_DATA); m->m_len = 0; md_initm(mdp, m); return 0; }
static bool_t svc_vc_reply(SVCXPRT *xprt, struct rpc_msg *msg, struct sockaddr *addr, struct mbuf *m, uint32_t *seq) { XDR xdrs; struct mbuf *mrep; bool_t stat = TRUE; int error, len; /* * Leave space for record mark. */ mrep = m_gethdr(M_WAITOK, MT_DATA); mrep->m_data += sizeof(uint32_t); xdrmbuf_create(&xdrs, mrep, XDR_ENCODE); if (msg->rm_reply.rp_stat == MSG_ACCEPTED && msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { if (!xdr_replymsg(&xdrs, msg)) stat = FALSE; else xdrmbuf_append(&xdrs, m); } else { stat = xdr_replymsg(&xdrs, msg); } if (stat) { m_fixhdr(mrep); /* * Prepend a record marker containing the reply length. */ M_PREPEND(mrep, sizeof(uint32_t), M_WAITOK); len = mrep->m_pkthdr.len; *mtod(mrep, uint32_t *) = htonl(0x80000000 | (len - sizeof(uint32_t))); atomic_add_32(&xprt->xp_snd_cnt, len); error = sosend(xprt->xp_socket, NULL, NULL, mrep, NULL, 0, curthread); if (!error) { atomic_add_rel_32(&xprt->xp_snt_cnt, len); if (seq) *seq = xprt->xp_snd_cnt; stat = TRUE; } else atomic_subtract_32(&xprt->xp_snd_cnt, len); } else { m_freem(mrep); } XDR_DESTROY(&xdrs); return (stat); }
/* * npf_return_tcp: return a TCP reset (RST) packet. */ static int npf_return_tcp(npf_cache_t *npc) { struct mbuf *m; struct ip *ip = NULL; struct ip6_hdr *ip6 = NULL; struct tcphdr *oth, *th; tcp_seq seq, ack; int tcpdlen, len; uint32_t win; /* Fetch relevant data. */ KASSERT(npf_iscached(npc, NPC_IP46)); KASSERT(npf_iscached(npc, NPC_LAYER4)); tcpdlen = npf_tcpsaw(npc, &seq, &ack, &win); oth = npc->npc_l4.tcp; if (oth->th_flags & TH_RST) { return 0; } /* Create and setup a network buffer. */ if (npf_iscached(npc, NPC_IP4)) { len = sizeof(struct ip) + sizeof(struct tcphdr); } else if (npf_iscached(npc, NPC_IP6)) { len = sizeof(struct ip6_hdr) + sizeof(struct tcphdr); } else { return EINVAL; } m = m_gethdr(M_DONTWAIT, MT_HEADER); if (m == NULL) { return ENOMEM; } m->m_data += max_linkhdr; m->m_len = len; m->m_pkthdr.len = len; if (npf_iscached(npc, NPC_IP4)) { struct ip *oip = npc->npc_ip.v4; ip = mtod(m, struct ip *); memset(ip, 0, len); /* * First, partially fill IPv4 header for TCP checksum. * Note: IP length contains TCP header length. */ ip->ip_p = IPPROTO_TCP; ip->ip_src.s_addr = oip->ip_dst.s_addr; ip->ip_dst.s_addr = oip->ip_src.s_addr; ip->ip_len = htons(sizeof(struct tcphdr)); th = (struct tcphdr *)(ip + 1); } else {
/* * Routines for fetching data from an mbuf chain */ int md_init(struct mdchain *mdp) { struct mbuf *m; m = m_gethdr(M_WAIT, MT_DATA); if (m == NULL) return ENOBUFS; m->m_len = 0; md_initm(mdp, m); return 0; }
int rump_netconfig_ipv6_gw(const char *gwaddr) { struct rt_msghdr rtm, *rtmp; struct sockaddr_in6 sin6; struct mbuf *m; int off, rv; CHECKDOMAIN(in6so); memset(&rtm, 0, sizeof(rtm)); rtm.rtm_type = RTM_ADD; rtm.rtm_flags = RTF_UP | RTF_STATIC | RTF_GATEWAY; rtm.rtm_version = RTM_VERSION; rtm.rtm_seq = 2; rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; m = m_gethdr(M_WAIT, MT_DATA); m->m_pkthdr.len = 0; m_copyback(m, 0, sizeof(rtm), &rtm); off = sizeof(rtm); /* dest */ memset(&sin6, 0, sizeof(sin6)); sin6.sin6_family = AF_INET6; sin6.sin6_len = sizeof(sin6); m_copyback(m, off, sin6.sin6_len, &sin6); RT_ADVANCE(off, (struct sockaddr *)&sin6); /* gw */ netconfig_inet_pton6(gwaddr, &sin6.sin6_addr); m_copyback(m, off, sin6.sin6_len, &sin6); RT_ADVANCE(off, (struct sockaddr *)&sin6); /* mask */ memset(&sin6.sin6_addr, 0, sizeof(sin6.sin6_addr)); m_copyback(m, off, sin6.sin6_len, &sin6); off = m->m_pkthdr.len; m = m_pullup(m, sizeof(*rtmp)); rtmp = mtod(m, struct rt_msghdr *); rtmp->rtm_msglen = off; solock(rtso); #if __NetBSD_Prereq__(7,99,26) rv = rtso->so_proto->pr_usrreqs->pr_send(rtso, m, NULL, NULL, curlwp); #else rv = rtso->so_proto->pr_output(m, rtso); #endif sounlock(rtso); return rv; }
/* * mbuf chain defragmenter. This function uses some evil tricks to defragment * an mbuf chain into a single buffer without changing the mbuf pointer. * This needs to know a lot of the mbuf internals to make this work. */ int m_defrag(struct mbuf *m, int how) { struct mbuf *m0; if (m->m_next == NULL) return (0); #ifdef DIAGNOSTIC if (!(m->m_flags & M_PKTHDR)) panic("m_defrag: no packet hdr or not a chain"); #endif if ((m0 = m_gethdr(how, m->m_type)) == NULL) return (ENOBUFS); if (m->m_pkthdr.len > MHLEN) { MCLGETI(m0, how, NULL, m->m_pkthdr.len); if (!(m0->m_flags & M_EXT)) { m_free(m0); return (ENOBUFS); } } m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t)); m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; /* free chain behind and possible ext buf on the first mbuf */ m_freem(m->m_next); m->m_next = NULL; if (m->m_flags & M_EXT) m_extfree(m); /* * Bounce copy mbuf over to the original mbuf and set everything up. * This needs to reset or clear all pointers that may go into the * original mbuf chain. */ if (m0->m_flags & M_EXT) { memcpy(&m->m_ext, &m0->m_ext, sizeof(struct mbuf_ext)); MCLINITREFERENCE(m); m->m_flags |= m0->m_flags & (M_EXT|M_EXTWR); m->m_data = m->m_ext.ext_buf; } else { m->m_data = m->m_pktdat; memcpy(m->m_data, m0->m_data, m0->m_len); } m->m_pkthdr.len = m->m_len = m0->m_len; m0->m_flags &= ~(M_EXT|M_EXTWR); /* cluster is gone */ m_free(m0); return (0); }
int mb_init(struct mbchain *mbp) { struct mbuf *m; m = m_gethdr(MB_WAIT, MT_DATA); if (m == NULL) return ENOBUFS; m->m_pkthdr.rcvif = NULL; m->m_len = 0; mb_initm(mbp, m); return 0; }
struct mbuf * mbuf_getwithdata(const void *data, size_t len) { struct mbuf *m; void *dst; m = m_gethdr(M_WAITOK, MT_HEADER); assert(m != NULL); dst = mtod(m, void *); memcpy(dst, data, len); m->m_len = len; return m; }
struct mbuf * mbuf_construct_ether(int proto) { struct mbuf *m0, *m1; struct ether_header *ethdr; m0 = m_gethdr(M_WAITOK, MT_HEADER); ethdr = mtod(m0, struct ether_header *); ethdr->ether_type = htons(ETHERTYPE_IP); m0->m_len = sizeof(struct ether_header); m1 = mbuf_construct(proto); m0->m_next = m1; m1->m_next = NULL; return m0; }
static e_RxStoreResponse dtsec_rm_fqr_rx_callback(t_Handle app, t_Handle fqr, t_Handle portal, uint32_t fqid_off, t_DpaaFD *frame) { struct dtsec_softc *sc; struct mbuf *m; m = NULL; sc = app; KASSERT(DPAA_FD_GET_FORMAT(frame) == e_DPAA_FD_FORMAT_TYPE_SHORT_SBSF, ("%s(): Got unsupported frame format 0x%02X!", __func__, DPAA_FD_GET_FORMAT(frame))); KASSERT(DPAA_FD_GET_OFFSET(frame) == 0, ("%s(): Only offset 0 is supported!", __func__)); if (DPAA_FD_GET_STATUS(frame) != 0) { device_printf(sc->sc_dev, "RX error: 0x%08X\n", DPAA_FD_GET_STATUS(frame)); goto err; } m = m_gethdr(M_NOWAIT, MT_HEADER); if (m == NULL) goto err; m_extadd(m, DPAA_FD_GET_ADDR(frame), FM_PORT_BUFFER_SIZE, dtsec_rm_fqr_mext_free, DPAA_FD_GET_ADDR(frame), sc, 0, EXT_NET_DRV); m->m_pkthdr.rcvif = sc->sc_ifnet; m->m_len = DPAA_FD_GET_LENGTH(frame); m_fixhdr(m); (*sc->sc_ifnet->if_input)(sc->sc_ifnet, m); return (e_RX_STORE_RESPONSE_CONTINUE); err: bman_put_buffer(sc->sc_rx_pool, DPAA_FD_GET_ADDR(frame)); if (m != NULL) m_freem(m); return (e_RX_STORE_RESPONSE_CONTINUE); }
static inline struct mbuf * nm_os_get_mbuf(struct ifnet *ifp, int len) { struct mbuf *m; (void)ifp; (void)len; m = m_gethdr(M_NOWAIT, MT_DATA); if (m == NULL) { return m; } m_extadd(m, NULL /* buf */, 0 /* size */, void_mbuf_dtor, NULL, NULL, 0, EXT_NET_DRV); return m; }