+ /*
+ * XXX Only TCP seems to be passing a list of packets here.
+ * The following issue is limited to UDP datagrams with 0 checksum.
+ * For now limit it to the case when single packet is passed down.
+ */
+ if (packetchain == 0 && IS_INTF_CLAT46(ifp)) {
+ /*
+ * If it is a UDP packet that has checksum set to 0
+ * and is also not being offloaded, compute a full checksum
+ * and update the UDP checksum.
+ */
+ if (ip->ip_p == IPPROTO_UDP &&
+ !(m->m_pkthdr.csum_flags & (CSUM_UDP | CSUM_PARTIAL))) {
+ struct udphdr *uh = NULL;
+
+ if (m->m_len < hlen + sizeof (struct udphdr)) {
+ m = m_pullup(m, hlen + sizeof (struct udphdr));
+ if (m == NULL) {
+ error = ENOBUFS;
+ m0 = m;
+ goto bad;
+ }
+ m0 = m;
+ ip = mtod(m, struct ip *);
+ }
+ /*
+ * Get UDP header and if checksum is 0, then compute the full
+ * checksum.
+ */
+ uh = (struct udphdr *)(void *)((caddr_t)ip + hlen);
+ if (uh->uh_sum == 0) {
+ uh->uh_sum = inet_cksum(m, IPPROTO_UDP, hlen,
+ ip->ip_len - hlen);
+ if (uh->uh_sum == 0)
+ uh->uh_sum = 0xffff;
+ }
+ }
+ }
+
+ error = ip_fragment(m, ifp, interface_mtu, sw_csum);