udp_input(register struct mbuf *m, int iphlen)

{

	Slirp *slirp = m->slirp;

	register struct ip *ip;

	register struct udphdr *uh;

	int len;

	struct ip save_ip;

	struct socket *so;



	DEBUG_CALL("udp_input");

	DEBUG_ARG("m = %lx", (long)m);

	DEBUG_ARG("iphlen = %d", iphlen);



	/*

	 * Strip IP options, if any; should skip this,

	 * make available to user, and use on returned packets,

	 * but we don't yet have a way to check the checksum

	 * with options still present.

	 */

	if(iphlen > sizeof(struct ip)) {

		ip_stripoptions(m, (struct mbuf *)0);

		iphlen = sizeof(struct ip);

	}



	/*

	 * Get IP and UDP header together in first mbuf.

	 */

	ip = mtod(m, struct ip *);

	uh = (struct udphdr *)((caddr_t)ip + iphlen);



	/*

	 * Make mbuf data length reflect UDP length.

	 * If not enough data to reflect UDP length, drop.

	 */

	len = ntohs((uint16_t)uh->uh_ulen);



	if (ip->ip_len != len) {

		if (len > ip->ip_len) {

			goto bad;

		}

		m_adj(m, len - ip->ip_len);

		ip->ip_len = len;

	}



	/*

	 * Save a copy of the IP header in case we want restore it

	 * for sending an ICMP error message in response.

	 */

	save_ip = *ip;

	save_ip.ip_len+= iphlen;         /* tcp_input subtracts this */



	/*

	 * Checksum extended UDP header and data.

	 */

	if (uh->uh_sum) {

      memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));

	  ((struct ipovly *)ip)->ih_x1 = 0;

	  ((struct ipovly *)ip)->ih_len = uh->uh_ulen;

	  if(cksum(m, len + sizeof(struct ip))) {

	    goto bad;

	  }

	}



        /*

         *  handle DHCP/BOOTP

         */

        if (ntohs(uh->uh_dport) == BOOTP_SERVER &&

            (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr ||

             ip->ip_dst.s_addr == 0xffffffff)) {

                bootp_input(m);

                goto bad;

            }



        /*

         *  handle TFTP

         */

        if (ntohs(uh->uh_dport) == TFTP_SERVER &&

            ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {

            tftp_input(m);

            goto bad;

        }



        if (slirp->restricted) {

            goto bad;

        }



	/*

	 * Locate pcb for datagram.

	 */

	so = slirp->udp_last_so;

	if (so->so_lport != uh->uh_sport ||

	    so->so_laddr.s_addr != ip->ip_src.s_addr) {

		struct socket *tmp;



		for (tmp = slirp->udb.so_next; tmp != &slirp->udb;

		     tmp = tmp->so_next) {

			if (tmp->so_lport == uh->uh_sport &&

			    tmp->so_laddr.s_addr == ip->ip_src.s_addr) {

				so = tmp;

				break;

			}

		}

		if (tmp == &slirp->udb) {

		  so = NULL;

		} else {

		  slirp->udp_last_so = so;

		}

	}



	if (so == NULL) {

	  /*

	   * If there's no socket for this packet,

	   * create one

	   */

	  so = socreate(slirp);

	  if (!so) {

	      goto bad;

	  }

	  if(udp_attach(so) == -1) {

	    DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",

			errno,strerror(errno)));

	    sofree(so);

	    goto bad;

	  }



	  /*

	   * Setup fields

	   */

	  so->so_laddr = ip->ip_src;

	  so->so_lport = uh->uh_sport;



	  if ((so->so_iptos = udp_tos(so)) == 0)

	    so->so_iptos = ip->ip_tos;



	  /*

	   * XXXXX Here, check if it's in udpexec_list,

	   * and if it is, do the fork_exec() etc.

	   */

	}



        so->so_faddr = ip->ip_dst; /* XXX */

        so->so_fport = uh->uh_dport; /* XXX */



	iphlen += sizeof(struct udphdr);

	m->m_len -= iphlen;

	m->m_data += iphlen;



	/*

	 * Now we sendto() the packet.

	 */

	if(sosendto(so,m) == -1) {

	  m->m_len += iphlen;

	  m->m_data -= iphlen;

	  *ip=save_ip;

	  DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));

	  icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));

	}



	m_free(so->so_m);   /* used for ICMP if error on sorecvfrom */



	/* restore the orig mbuf packet */

	m->m_len += iphlen;

	m->m_data -= iphlen;

	*ip=save_ip;

	so->so_m=m;         /* ICMP backup */



	return;

bad:

	m_free(m);

}

udp_input(register struct mbuf *m, int iphlen)

{

	Slirp *slirp = m->slirp;

	register struct ip *ip;

	register struct udphdr *uh;

	int len;

	struct ip save_ip;

	struct socket *so;



	DEBUG_CALL("udp_input");

	DEBUG_ARG("m = %lx", (long)m);

	DEBUG_ARG("iphlen = %d", iphlen);



	











	if(iphlen > sizeof(struct ip)) {

		ip_stripoptions(m, (struct mbuf *)0);

		iphlen = sizeof(struct ip);

	}



	





	ip = mtod(m, struct ip *);

	uh = (struct udphdr *)((caddr_t)ip + iphlen);



	







	len = ntohs((uint16_t)uh->uh_ulen);



	if (ip->ip_len != len) {

		if (len > ip->ip_len) {

			goto bad;

		}

		m_adj(m, len - ip->ip_len);

		ip->ip_len = len;

	}



	







	save_ip = *ip;

	save_ip.ip_len+= iphlen;         



	





	if (uh->uh_sum) {

      memset(&((struct ipovly *)ip)->ih_mbuf, 0, sizeof(struct mbuf_ptr));

	  ((struct ipovly *)ip)->ih_x1 = 0;

	  ((struct ipovly *)ip)->ih_len = uh->uh_ulen;

	  if(cksum(m, len + sizeof(struct ip))) {

	    goto bad;

	  }

	}



        





        if (ntohs(uh->uh_dport) == BOOTP_SERVER &&

            (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr ||

             ip->ip_dst.s_addr == 0xffffffff)) {

                bootp_input(m);

                goto bad;

            }



        





        if (ntohs(uh->uh_dport) == TFTP_SERVER &&

            ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) {

            tftp_input(m);

            goto bad;

        }



        if (slirp->restricted) {

            goto bad;

        }



	





	so = slirp->udp_last_so;

	if (so->so_lport != uh->uh_sport ||

	    so->so_laddr.s_addr != ip->ip_src.s_addr) {

		struct socket *tmp;



		for (tmp = slirp->udb.so_next; tmp != &slirp->udb;

		     tmp = tmp->so_next) {

			if (tmp->so_lport == uh->uh_sport &&

			    tmp->so_laddr.s_addr == ip->ip_src.s_addr) {

				so = tmp;

				break;

			}

		}

		if (tmp == &slirp->udb) {

		  so = NULL;

		} else {

		  slirp->udp_last_so = so;

		}

	}



	if (so == NULL) {

	  







	  so = socreate(slirp);

	  if (!so) {

	      goto bad;

	  }

	  if(udp_attach(so) == -1) {

	    DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",

			errno,strerror(errno)));

	    sofree(so);

	    goto bad;

	  }



	  





	  so->so_laddr = ip->ip_src;

	  so->so_lport = uh->uh_sport;



	  if ((so->so_iptos = udp_tos(so)) == 0)

	    so->so_iptos = ip->ip_tos;



	  







	}



        so->so_faddr = ip->ip_dst; 

        so->so_fport = uh->uh_dport; 



	iphlen += sizeof(struct udphdr);

	m->m_len -= iphlen;

	m->m_data += iphlen;



	





	if(sosendto(so,m) == -1) {

	  m->m_len += iphlen;

	  m->m_data -= iphlen;

	  *ip=save_ip;

	  DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));

	  icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));

	}



	m_free(so->so_m);   



	

	m->m_len += iphlen;

	m->m_data -= iphlen;

	*ip=save_ip;

	so->so_m=m;         



	return;

bad:

	m_free(m);

}

	if (so->so_lport != uh->uh_sport ||
FUNC_0(register struct mbuf *VAR_0, int VAR_1)

{

	Slirp *slirp = VAR_0->slirp;

	register struct VAR_2 *VAR_2;

	register struct udphdr *VAR_3;

	int VAR_4;

	struct VAR_2 VAR_5;

	struct socket *VAR_6;



	DEBUG_CALL("FUNC_0");

	DEBUG_ARG("VAR_0 = %lx", (long)VAR_0);

	DEBUG_ARG("VAR_1 = %d", VAR_1);



	











	if(VAR_1 > sizeof(struct VAR_2)) {

		ip_stripoptions(VAR_0, (struct mbuf *)0);

		VAR_1 = sizeof(struct VAR_2);

	}



	





	VAR_2 = mtod(VAR_0, struct VAR_2 *);

	VAR_3 = (struct udphdr *)((caddr_t)VAR_2 + VAR_1);



	







	VAR_4 = ntohs((uint16_t)VAR_3->uh_ulen);



	if (VAR_2->ip_len != VAR_4) {

		if (VAR_4 > VAR_2->ip_len) {

			goto bad;

		}

		m_adj(VAR_0, VAR_4 - VAR_2->ip_len);

		VAR_2->ip_len = VAR_4;

	}



	







	VAR_5 = *VAR_2;

	VAR_5.ip_len+= VAR_1;         



	





	if (VAR_3->uh_sum) {

      memset(&((struct ipovly *)VAR_2)->ih_mbuf, 0, sizeof(struct mbuf_ptr));

	  ((struct ipovly *)VAR_2)->ih_x1 = 0;

	  ((struct ipovly *)VAR_2)->ih_len = VAR_3->uh_ulen;

	  if(cksum(VAR_0, VAR_4 + sizeof(struct VAR_2))) {

	    goto bad;

	  }

	}



        





        if (ntohs(VAR_3->uh_dport) == BOOTP_SERVER &&

            (VAR_2->ip_dst.s_addr == slirp->vhost_addr.s_addr ||

             VAR_2->ip_dst.s_addr == 0xffffffff)) {

                bootp_input(VAR_0);

                goto bad;

            }



        





        if (ntohs(VAR_3->uh_dport) == TFTP_SERVER &&

            VAR_2->ip_dst.s_addr == slirp->vhost_addr.s_addr) {

            tftp_input(VAR_0);

            goto bad;

        }



        if (slirp->restricted) {

            goto bad;

        }



	





	VAR_6 = slirp->udp_last_so;

	if (VAR_6->so_lport != VAR_3->uh_sport ||

	    VAR_6->so_laddr.s_addr != VAR_2->ip_src.s_addr) {

		struct socket *VAR_7;



		for (VAR_7 = slirp->udb.so_next; VAR_7 != &slirp->udb;

		     VAR_7 = VAR_7->so_next) {

			if (VAR_7->so_lport == VAR_3->uh_sport &&

			    VAR_7->so_laddr.s_addr == VAR_2->ip_src.s_addr) {

				VAR_6 = VAR_7;

				break;

			}

		}

		if (VAR_7 == &slirp->udb) {

		  VAR_6 = NULL;

		} else {

		  slirp->udp_last_so = VAR_6;

		}

	}



	if (VAR_6 == NULL) {

	  







	  VAR_6 = socreate(slirp);

	  if (!VAR_6) {

	      goto bad;

	  }

	  if(udp_attach(VAR_6) == -1) {

	    DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",

			errno,strerror(errno)));

	    sofree(VAR_6);

	    goto bad;

	  }



	  





	  VAR_6->so_laddr = VAR_2->ip_src;

	  VAR_6->so_lport = VAR_3->uh_sport;



	  if ((VAR_6->so_iptos = udp_tos(VAR_6)) == 0)

	    VAR_6->so_iptos = VAR_2->ip_tos;



	  







	}



        VAR_6->so_faddr = VAR_2->ip_dst; 

        VAR_6->so_fport = VAR_3->uh_dport; 



	VAR_1 += sizeof(struct udphdr);

	VAR_0->m_len -= VAR_1;

	VAR_0->m_data += VAR_1;



	





	if(sosendto(VAR_6,VAR_0) == -1) {

	  VAR_0->m_len += VAR_1;

	  VAR_0->m_data -= VAR_1;

	  *VAR_2=VAR_5;

	  DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno)));

	  icmp_error(VAR_0, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno));

	}



	m_free(VAR_6->so_m);   



	

	VAR_0->m_len += VAR_1;

	VAR_0->m_data -= VAR_1;

	*VAR_2=VAR_5;

	VAR_6->so_m=VAR_0;         



	return;

bad:

	m_free(VAR_0);

}

FUNC_0(register struct mbuf *VAR_0, int VAR_1)
{ Slirp *slirp = VAR_0->slirp; register struct VAR_2 *VAR_2; register struct udphdr *VAR_3; int VAR_4; struct VAR_2 VAR_5; struct socket *VAR_6; DEBUG_CALL("FUNC_0"); DEBUG_ARG("VAR_0 = %lx", (long)VAR_0); DEBUG_ARG("VAR_1 = %d", VAR_1); if(VAR_1 > sizeof(struct VAR_2)) { ip_stripoptions(VAR_0, (struct mbuf *)0); VAR_1 = sizeof(struct VAR_2); } VAR_2 = mtod(VAR_0, struct VAR_2 *); VAR_3 = (struct udphdr *)((caddr_t)VAR_2 + VAR_1); VAR_4 = ntohs((uint16_t)VAR_3->uh_ulen); if (VAR_2->ip_len != VAR_4) { if (VAR_4 > VAR_2->ip_len) { goto bad; } m_adj(VAR_0, VAR_4 - VAR_2->ip_len); VAR_2->ip_len = VAR_4; } VAR_5 = *VAR_2; VAR_5.ip_len+= VAR_1; if (VAR_3->uh_sum) { memset(&((struct ipovly *)VAR_2)->ih_mbuf, 0, sizeof(struct mbuf_ptr)); ((struct ipovly *)VAR_2)->ih_x1 = 0; ((struct ipovly *)VAR_2)->ih_len = VAR_3->uh_ulen; if(cksum(VAR_0, VAR_4 + sizeof(struct VAR_2))) { goto bad; } } if (ntohs(VAR_3->uh_dport) == BOOTP_SERVER &&
(VAR_2->ip_dst.s_addr == slirp->vhost_addr.s_addr ||
VAR_2->ip_dst.s_addr == 0xffffffff)) { bootp_input(VAR_0); goto bad; } if (ntohs(VAR_3->uh_dport) == TFTP_SERVER &&
VAR_2->ip_dst.s_addr == slirp->vhost_addr.s_addr) { tftp_input(VAR_0); goto bad; } if (slirp->restricted) { goto bad; } VAR_6 = slirp->udp_last_so; if (VAR_6->so_lport != VAR_3->uh_sport ||
VAR_6->so_laddr.s_addr != VAR_2->ip_src.s_addr) { struct socket *VAR_7; for (VAR_7 = slirp->udb.so_next; VAR_7 != &slirp->udb; VAR_7 = VAR_7->so_next) { if (VAR_7->so_lport == VAR_3->uh_sport &&
VAR_7->so_laddr.s_addr == VAR_2->ip_src.s_addr) { VAR_6 = VAR_7; break; } } if (VAR_7 == &slirp->udb) { VAR_6 = NULL; } else { slirp->udp_last_so = VAR_6; } } if (VAR_6 == NULL) { VAR_6 = socreate(slirp); if (!VAR_6) { goto bad; } if(udp_attach(VAR_6) == -1) { DEBUG_MISC((dfd," udp_attach errno = %d-%s\n",
errno,strerror(errno))); sofree(VAR_6); goto bad; } VAR_6->so_laddr = VAR_2->ip_src; VAR_6->so_lport = VAR_3->uh_sport; if ((VAR_6->so_iptos = udp_tos(VAR_6)) == 0)
VAR_6->so_iptos = VAR_2->ip_tos; } VAR_6->so_faddr = VAR_2->ip_dst; VAR_6->so_fport = VAR_3->uh_dport; VAR_1 += sizeof(struct udphdr); VAR_0->m_len -= VAR_1; VAR_0->m_data += VAR_1; if(sosendto(VAR_6,VAR_0) == -1) { VAR_0->m_len += VAR_1; VAR_0->m_data -= VAR_1; *VAR_2=VAR_5; DEBUG_MISC((dfd,"udp tx errno = %d-%s\n",errno,strerror(errno))); icmp_error(VAR_0, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); } m_free(VAR_6->so_m); VAR_0->m_len += VAR_1; VAR_0->m_data -= VAR_1; *VAR_2=VAR_5; VAR_6->so_m=VAR_0; return; bad:
m_free(VAR_0); }