* Create a chain of fragments which fit the given mtu. m_frag points to the * mbuf to be fragmented; on return it points to the chain with the fragments. * Return 0 if no error. If error, m_frag may contain a partially built * chain of fragments that should be freed by the caller. * * if_hwassist_flags is the hw offload capabilities (see if_data.ifi_hwassist) */
| 871 | * if_hwassist_flags is the hw offload capabilities (see if_data.ifi_hwassist) |
| 872 | */ |
| 873 | int |
| 874 | ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu, |
| 875 | u_long if_hwassist_flags) |
| 876 | { |
| 877 | int error = 0; |
| 878 | int hlen = ip->ip_hl << 2; |
| 879 | int len = (mtu - hlen) & ~7; /* size of payload in each fragment */ |
| 880 | int off; |
| 881 | struct mbuf *m0 = *m_frag; /* the original packet */ |
| 882 | int firstlen; |
| 883 | struct mbuf **mnext; |
| 884 | int nfrags; |
| 885 | uint16_t ip_len, ip_off; |
| 886 | |
| 887 | ip_len = ntohs(ip->ip_len); |
| 888 | ip_off = ntohs(ip->ip_off); |
| 889 | |
| 890 | if (ip_off & IP_DF) { /* Fragmentation not allowed */ |
| 891 | IPSTAT_INC(ips_cantfrag); |
| 892 | return EMSGSIZE; |
| 893 | } |
| 894 | |
| 895 | /* |
| 896 | * Must be able to put at least 8 bytes per fragment. |
| 897 | */ |
| 898 | if (len < 8) |
| 899 | return EMSGSIZE; |
| 900 | |
| 901 | /* |
| 902 | * If the interface will not calculate checksums on |
| 903 | * fragmented packets, then do it here. |
| 904 | */ |
| 905 | if (m0->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { |
| 906 | m0 = mb_unmapped_to_ext(m0); |
| 907 | if (m0 == NULL) { |
| 908 | error = ENOBUFS; |
| 909 | IPSTAT_INC(ips_odropped); |
| 910 | goto done; |
| 911 | } |
| 912 | in_delayed_cksum(m0); |
| 913 | m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; |
| 914 | } |
| 915 | #if defined(SCTP) || defined(SCTP_SUPPORT) |
| 916 | if (m0->m_pkthdr.csum_flags & CSUM_SCTP) { |
| 917 | m0 = mb_unmapped_to_ext(m0); |
| 918 | if (m0 == NULL) { |
| 919 | error = ENOBUFS; |
| 920 | IPSTAT_INC(ips_odropped); |
| 921 | goto done; |
| 922 | } |
| 923 | sctp_delayed_cksum(m0, hlen); |
| 924 | m0->m_pkthdr.csum_flags &= ~CSUM_SCTP; |
| 925 | } |
| 926 | #endif |
| 927 | if (len > PAGE_SIZE) { |
| 928 | /* |
| 929 | * Fragment large datagrams such that each segment |
| 930 | * contains a multiple of PAGE_SIZE amount of data, |
no test coverage detected