* Copy an entire packet, including header (which must be present). * An optimization of the common case `m_copym(m, 0, M_COPYALL, how)'. * Note that the copy is read-only, because clusters are not copied, * only their reference counts are incremented. * Preserve alignment of the first mbuf so if the creator has left * some room at the beginning (e.g. for inserting protocol headers) * the cop
| 563 | * the copies still have the room available. |
| 564 | */ |
| 565 | struct mbuf * |
| 566 | m_copypacket(struct mbuf *m, int how) |
| 567 | { |
| 568 | struct mbuf *top, *n, *o; |
| 569 | |
| 570 | MBUF_CHECKSLEEP(how); |
| 571 | n = m_get(how, m->m_type); |
| 572 | top = n; |
| 573 | if (n == NULL) |
| 574 | goto nospace; |
| 575 | |
| 576 | if (!m_dup_pkthdr(n, m, how)) |
| 577 | goto nospace; |
| 578 | n->m_len = m->m_len; |
| 579 | if (m->m_flags & (M_EXT|M_EXTPG)) { |
| 580 | n->m_data = m->m_data; |
| 581 | mb_dupcl(n, m); |
| 582 | } else { |
| 583 | n->m_data = n->m_pktdat + (m->m_data - m->m_pktdat ); |
| 584 | bcopy(mtod(m, char *), mtod(n, char *), n->m_len); |
| 585 | } |
| 586 | |
| 587 | m = m->m_next; |
| 588 | while (m) { |
| 589 | o = m_get(how, m->m_type); |
| 590 | if (o == NULL) |
| 591 | goto nospace; |
| 592 | |
| 593 | n->m_next = o; |
| 594 | n = n->m_next; |
| 595 | |
| 596 | n->m_len = m->m_len; |
| 597 | if (m->m_flags & (M_EXT|M_EXTPG)) { |
| 598 | n->m_data = m->m_data; |
| 599 | mb_dupcl(n, m); |
| 600 | } else { |
| 601 | bcopy(mtod(m, char *), mtod(n, char *), n->m_len); |
| 602 | } |
| 603 | |
| 604 | m = m->m_next; |
| 605 | } |
| 606 | return top; |
| 607 | nospace: |
| 608 | m_freem(top); |
| 609 | return (NULL); |
| 610 | } |
| 611 | |
| 612 | static void |
| 613 | m_copyfromunmapped(const struct mbuf *m, int off, int len, caddr_t cp) |
no test coverage detected