+ }
+
+ /*
+ * If small enough for interface, can just send directly.
+ */
+ if (ip->ip_len <= ifp->if_mtu) {
+#if vax
+ ip->ip_len = htons((u_short)ip->ip_len);
+ ip->ip_off = htons((u_short)ip->ip_off);
+#endif
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum(m, hlen);
+ error = (*ifp->if_output)(ifp, m, dst);
+ goto done;
+ }
+
+ /*
+ * Too large for interface; fragment if possible.
+ * Must be able to put at least 8 bytes per fragment.
+ */
+ if (ip->ip_off & IP_DF) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+ len = (ifp->if_mtu - hlen) &~ 7;
+ if (len < 8) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+
+ /*
+ * Discard IP header from logical mbuf for m_copy's sake.
+ * Loop through length of segment, make a copy of each
+ * part and output.
+ */
+ m->m_len -= sizeof (struct ip);
+ m->m_off += sizeof (struct ip);
+ for (off = 0; off < ip->ip_len-hlen; off += len) {
+ struct mbuf *mh = m_get(M_DONTWAIT);
+ struct ip *mhip;
+
+ if (mh == 0) {
+ error = ENOBUFS;
+ goto bad;
+ }
+ mh->m_off = MMAXOFF - hlen;
+ mhip = mtod(mh, struct ip *);
+ *mhip = *ip;
+ if (hlen > sizeof (struct ip)) {
+ int olen = ip_optcopy(ip, mhip, off);
+ mh->m_len = sizeof (struct ip) + olen;
+ } else
+ mh->m_len = sizeof (struct ip);
+ mhip->ip_off = off >> 3;
+ if (off + len >= ip->ip_len-hlen)
+ len = mhip->ip_len = ip->ip_len - hlen - off;
+ else {
+ mhip->ip_len = len;
+ mhip->ip_off |= IP_MF;