* Make space for a new header of length hlen at skip bytes * into the packet. When doing this we allocate new mbufs only * when absolutely necessary. The mbuf where the new header * is to go is returned together with an offset into the mbuf. * If NULL is returned then the mbuf chain may have been modified; * the caller is assumed to always free the chain. */
| 53 | * the caller is assumed to always free the chain. |
| 54 | */ |
| 55 | struct mbuf * |
| 56 | m_makespace(struct mbuf *m0, int skip, int hlen, int *off) |
| 57 | { |
| 58 | struct mbuf *m; |
| 59 | unsigned remain; |
| 60 | |
| 61 | IPSEC_ASSERT(m0 != NULL, ("null mbuf")); |
| 62 | IPSEC_ASSERT(hlen < MHLEN, ("hlen too big: %u", hlen)); |
| 63 | |
| 64 | for (m = m0; m && skip > m->m_len; m = m->m_next) |
| 65 | skip -= m->m_len; |
| 66 | if (m == NULL) |
| 67 | return (NULL); |
| 68 | /* |
| 69 | * At this point skip is the offset into the mbuf m |
| 70 | * where the new header should be placed. Figure out |
| 71 | * if there's space to insert the new header. If so, |
| 72 | * and copying the remainder makes sense then do so. |
| 73 | * Otherwise insert a new mbuf in the chain, splitting |
| 74 | * the contents of m as needed. |
| 75 | */ |
| 76 | remain = m->m_len - skip; /* data to move */ |
| 77 | if (remain > skip && |
| 78 | hlen + max_linkhdr < M_LEADINGSPACE(m)) { |
| 79 | /* |
| 80 | * mbuf has enough free space at the beginning. |
| 81 | * XXX: which operation is the most heavy - copying of |
| 82 | * possible several hundred of bytes or allocation |
| 83 | * of new mbuf? We can remove max_linkhdr check |
| 84 | * here, but it is possible that this will lead |
| 85 | * to allocation of new mbuf in Layer 2 code. |
| 86 | */ |
| 87 | m->m_data -= hlen; |
| 88 | bcopy(mtodo(m, hlen), mtod(m, caddr_t), skip); |
| 89 | m->m_len += hlen; |
| 90 | *off = skip; |
| 91 | } else if (hlen > M_TRAILINGSPACE(m)) { |
| 92 | struct mbuf *n0, *n, **np; |
| 93 | int todo, len, done, alloc; |
| 94 | |
| 95 | n0 = NULL; |
| 96 | np = &n0; |
| 97 | alloc = 0; |
| 98 | done = 0; |
| 99 | todo = remain; |
| 100 | while (todo > 0) { |
| 101 | if (todo > MHLEN) { |
| 102 | n = m_getcl(M_NOWAIT, m->m_type, 0); |
| 103 | len = MCLBYTES; |
| 104 | } |
| 105 | else { |
| 106 | n = m_get(M_NOWAIT, m->m_type); |
| 107 | len = MHLEN; |
| 108 | } |
| 109 | if (n == NULL) { |
| 110 | m_freem(n0); |
| 111 | return NULL; |
| 112 | } |
no test coverage detected