* Copy data from a buffer back into the indicated mbuf chain, * starting "off" bytes from the beginning, extending the mbuf * chain if necessary. */
| 1122 | * chain if necessary. |
| 1123 | */ |
| 1124 | void |
| 1125 | m_copyback(struct mbuf *m0, int off, int len, c_caddr_t cp) |
| 1126 | { |
| 1127 | int mlen; |
| 1128 | struct mbuf *m = m0, *n; |
| 1129 | int totlen = 0; |
| 1130 | |
| 1131 | if (m0 == NULL) |
| 1132 | return; |
| 1133 | while (off > (mlen = m->m_len)) { |
| 1134 | off -= mlen; |
| 1135 | totlen += mlen; |
| 1136 | if (m->m_next == NULL) { |
| 1137 | n = m_get(M_NOWAIT, m->m_type); |
| 1138 | if (n == NULL) |
| 1139 | goto out; |
| 1140 | bzero(mtod(n, caddr_t), MLEN); |
| 1141 | n->m_len = min(MLEN, len + off); |
| 1142 | m->m_next = n; |
| 1143 | } |
| 1144 | m = m->m_next; |
| 1145 | } |
| 1146 | while (len > 0) { |
| 1147 | if (m->m_next == NULL && (len > m->m_len - off)) { |
| 1148 | m->m_len += min(len - (m->m_len - off), |
| 1149 | M_TRAILINGSPACE(m)); |
| 1150 | } |
| 1151 | mlen = min (m->m_len - off, len); |
| 1152 | bcopy(cp, off + mtod(m, caddr_t), (u_int)mlen); |
| 1153 | cp += mlen; |
| 1154 | len -= mlen; |
| 1155 | mlen += off; |
| 1156 | off = 0; |
| 1157 | totlen += mlen; |
| 1158 | if (len == 0) |
| 1159 | break; |
| 1160 | if (m->m_next == NULL) { |
| 1161 | n = m_get(M_NOWAIT, m->m_type); |
| 1162 | if (n == NULL) |
| 1163 | break; |
| 1164 | n->m_len = min(MLEN, len); |
| 1165 | m->m_next = n; |
| 1166 | } |
| 1167 | m = m->m_next; |
| 1168 | } |
| 1169 | out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) |
| 1170 | m->m_pkthdr.len = totlen; |
| 1171 | } |
| 1172 | |
| 1173 | /* |
| 1174 | * Append the specified data to the indicated mbuf chain, |
no test coverage detected