+ int len;
+ struct ip ip;
+
+ /*
+ * Get IP and UDP header together in first mbuf.
+ * Note: IP leaves IP header in first mbuf.
+ */
+ ui = mtod(m, struct udpiphdr *);
+ if (iphlen > sizeof (struct ip))
+ ip_stripoptions(m, (struct mbuf *)0);
+ if (m->m_len < sizeof (struct udpiphdr)) {
+ if ((m = m_pullup(m, sizeof (struct udpiphdr))) == 0) {
+ udpstat.udps_hdrops++;
+ return;
+ }
+ ui = mtod(m, struct udpiphdr *);
+ }
+
+ /*
+ * Make mbuf data length reflect UDP length.
+ * If not enough data to reflect UDP length, drop.
+ */
+ len = ntohs((u_short)ui->ui_ulen);
+ if (((struct ip *)ui)->ip_len != len) {
+ if (len > ((struct ip *)ui)->ip_len) {
+ udpstat.udps_badlen++;
+ goto bad;
+ }
+ m_adj(m, len - ((struct ip *)ui)->ip_len);
+ /* ((struct ip *)ui)->ip_len = len; */
+ }
+ /*
+ * Save a copy of the IP header in case we want restore it for ICMP.
+ */
+ ip = *(struct ip *)ui;
+
+ /*
+ * Checksum extended UDP header and data.
+ */
+ if (udpcksum && ui->ui_sum) {
+ ui->ui_next = ui->ui_prev = 0;
+ ui->ui_x1 = 0;
+ ui->ui_len = ui->ui_ulen;
+ if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) {
+ udpstat.udps_badsum++;
+ m_freem(m);
+ return;
+ }
+ }
+
+ /*
+ * Locate pcb for datagram.
+ */
+ inp = in_pcblookup(&udb,
+ ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport,
+ INPLOOKUP_WILDCARD);
+ if (inp == 0) {
+ /* don't send ICMP response for broadcast packet */
+ if (m->m_flags & M_BCAST)
+ goto bad;
+ *(struct ip *)ui = ip;
+ icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT);
+ return;
+ }