| 1654 | } |
| 1655 | |
| 1656 | static struct mbuf * |
| 1657 | ktls_detach_record(struct sockbuf *sb, int len) |
| 1658 | { |
| 1659 | struct mbuf *m, *n, *top; |
| 1660 | int remain; |
| 1661 | |
| 1662 | SOCKBUF_LOCK_ASSERT(sb); |
| 1663 | MPASS(len <= sb->sb_tlscc); |
| 1664 | |
| 1665 | /* |
| 1666 | * If TLS chain is the exact size of the record, |
| 1667 | * just grab the whole record. |
| 1668 | */ |
| 1669 | top = sb->sb_mtls; |
| 1670 | if (sb->sb_tlscc == len) { |
| 1671 | sb->sb_mtls = NULL; |
| 1672 | sb->sb_mtlstail = NULL; |
| 1673 | goto out; |
| 1674 | } |
| 1675 | |
| 1676 | /* |
| 1677 | * While it would be nice to use m_split() here, we need |
| 1678 | * to know exactly what m_split() allocates to update the |
| 1679 | * accounting, so do it inline instead. |
| 1680 | */ |
| 1681 | remain = len; |
| 1682 | for (m = top; remain > m->m_len; m = m->m_next) |
| 1683 | remain -= m->m_len; |
| 1684 | |
| 1685 | /* Easy case: don't have to split 'm'. */ |
| 1686 | if (remain == m->m_len) { |
| 1687 | sb->sb_mtls = m->m_next; |
| 1688 | if (sb->sb_mtls == NULL) |
| 1689 | sb->sb_mtlstail = NULL; |
| 1690 | m->m_next = NULL; |
| 1691 | goto out; |
| 1692 | } |
| 1693 | |
| 1694 | /* |
| 1695 | * Need to allocate an mbuf to hold the remainder of 'm'. Try |
| 1696 | * with M_NOWAIT first. |
| 1697 | */ |
| 1698 | n = m_get(M_NOWAIT, MT_DATA); |
| 1699 | if (n == NULL) { |
| 1700 | /* |
| 1701 | * Use M_WAITOK with socket buffer unlocked. If |
| 1702 | * 'sb_mtls' changes while the lock is dropped, return |
| 1703 | * NULL to force the caller to retry. |
| 1704 | */ |
| 1705 | SOCKBUF_UNLOCK(sb); |
| 1706 | |
| 1707 | n = m_get(M_WAITOK, MT_DATA); |
| 1708 | |
| 1709 | SOCKBUF_LOCK(sb); |
| 1710 | if (sb->sb_mtls != top) { |
| 1711 | m_free(n); |
| 1712 | return (NULL); |
| 1713 | } |
no test coverage detected