+ /*
+ * Get IP and UDP header together in first mbuf.
+ */
+ m = m0;
+ if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct udpiphdr)) &&
+ (m = m_pullup(m, sizeof (struct udpiphdr))) == 0) {
+ udpstat.udps_hdrops++;
+ return;
+ }
+ ui = mtod(m, struct udpiphdr *);
+ if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2))
+ ip_stripoptions((struct ip *)ui, (struct mbuf *)0);
+
+ /*
+ * 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; */
+ }
+
+ /*
+ * 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 = htons((u_short)len);
+ 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 (in_lnaof(ui->ui_dst) == INADDR_ANY)
+ goto bad;
+ icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT);
+ return;
+ }
+
+ /*
+ * Construct sockaddr format source address.
+ * Stuff source address and datagram in user buffer.
+ */
+ udp_in.sin_port = ui->ui_sport;
+ udp_in.sin_addr = ui->ui_src;
+ m->m_len -= sizeof (struct udpiphdr);
+ m->m_off += sizeof (struct udpiphdr);
+ if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
+ m, (struct mbuf *)0) == 0)