diff options
Diffstat (limited to 'sys/kern/uipc_sockbuf.c')
-rw-r--r-- | sys/kern/uipc_sockbuf.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/sys/kern/uipc_sockbuf.c b/sys/kern/uipc_sockbuf.c index 0c67347..d4f965a 100644 --- a/sys/kern/uipc_sockbuf.c +++ b/sys/kern/uipc_sockbuf.c @@ -439,15 +439,18 @@ sblastmbufchk(struct sockbuf *sb, const char *file, int line) } #endif /* SOCKBUF_DEBUG */ -#define SBLINKRECORD(sb, m0) do { \ +#define SBLINKRECORDCHAIN(sb, m0, mlast) do { \ SOCKBUF_LOCK_ASSERT(sb); \ if ((sb)->sb_lastrecord != NULL) \ (sb)->sb_lastrecord->m_nextpkt = (m0); \ else \ (sb)->sb_mb = (m0); \ - (sb)->sb_lastrecord = (m0); \ + (sb)->sb_lastrecord = (mlast); \ } while (/*CONSTCOND*/0) +#define SBLINKRECORD(sb, m0) \ + SBLINKRECORDCHAIN(sb, m0, m0) + /* * Append mbuf chain m to the last record in the socket buffer sb. The * additional space associated the mbuf chain is recorded in sb. Empty mbufs @@ -716,6 +719,74 @@ sbappendaddr(struct sockbuf *sb, const struct sockaddr *asa, } int +sbappendaddrchain_locked(sb, asa, m0) + struct sockbuf *sb; + const struct sockaddr *asa; + struct mbuf *m0; +{ + struct mbuf *m, *n, *n0, *nlast, *np; + + SOCKBUF_LOCK_ASSERT(sb); + +#if MSIZE <= 256 + if (asa->sa_len > MLEN) + return (0); +#endif + + n0 = np = nlast = NULL; + for (m = m0; m; m = m->m_nextpkt) { + MGET(n, M_DONTWAIT, MT_SONAME); + if (n == NULL) + goto outofmem; + n->m_len = asa->sa_len; + bcopy(asa, mtod(n, caddr_t), asa->sa_len); + n->m_next = m; + + if (n0 == NULL) + n0 = n; + else + nlast->m_nextpkt = n; + nlast = n; + + for (np = n; np->m_next; np = np->m_next) + sballoc(sb, np); + sballoc(sb, np); + } + + SBLINKRECORDCHAIN(sb, n0, nlast); + + sb->sb_mbtail = np; + SBLASTMBUFCHK(sb); + + SBLASTRECORDCHK(sb); + return (1); + +outofmem: + while ((n = n0) != NULL) { + for (np = n; np; np = np->m_next) + sbfree(sb, np); + + n0 = n->m_nextpkt; + m_free(n); + } + return (0); +} + +int +sbappendaddrchain(sb, asa, m0) + struct sockbuf *sb; + const struct sockaddr *asa; + struct mbuf *m0; +{ + int retval; + + SOCKBUF_LOCK(sb); + retval = sbappendaddrchain_locked(sb, asa, m0); + SOCKBUF_UNLOCK(sb); + return (retval); +} + +int sbappendcontrol_locked(struct sockbuf *sb, struct mbuf *m0, struct mbuf *control) { |