icmp_input(struct mbuf *m, int hlen)

{

  register struct icmp *icp;

  register struct ip *ip=mtod(m, struct ip *);

  int icmplen=ip->ip_len;

  Slirp *slirp = m->slirp;



  DEBUG_CALL("icmp_input");

  DEBUG_ARG("m = %p", m);

  DEBUG_ARG("m_len = %d", m->m_len);



  /*

   * Locate icmp structure in mbuf, and check

   * that its not corrupted and of at least minimum length.

   */

  if (icmplen < ICMP_MINLEN) {          /* min 8 bytes payload */

  freeit:

    m_free(m);

    goto end_error;

  }



  m->m_len -= hlen;

  m->m_data += hlen;

  icp = mtod(m, struct icmp *);

  if (cksum(m, icmplen)) {

    goto freeit;

  }

  m->m_len += hlen;

  m->m_data -= hlen;



  DEBUG_ARG("icmp_type = %d", icp->icmp_type);

  switch (icp->icmp_type) {

  case ICMP_ECHO:

    ip->ip_len += hlen;	             /* since ip_input subtracts this */

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

      icmp_reflect(m);

    } else if (slirp->restricted) {

        goto freeit;

    } else {

      struct socket *so;

      struct sockaddr_in addr;

      if ((so = socreate(slirp)) == NULL) goto freeit;

      if (icmp_send(so, m, hlen) == 0) {

        return;

      }

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

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

		    errno,strerror(errno)));

	sofree(so);

	m_free(m);

	goto end_error;

      }

      so->so_m = m;

      so->so_ffamily = AF_INET;

      so->so_faddr = ip->ip_dst;

      so->so_fport = htons(7);

      so->so_lfamily = AF_INET;

      so->so_laddr = ip->ip_src;

      so->so_lport = htons(9);

      so->so_iptos = ip->ip_tos;

      so->so_type = IPPROTO_ICMP;

      so->so_state = SS_ISFCONNECTED;



      /* Send the packet */

      addr.sin_family = AF_INET;

      if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==

          slirp->vnetwork_addr.s_addr) {

	/* It's an alias */

	if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {

	  if (get_dns_addr(&addr.sin_addr) < 0)

	    addr.sin_addr = loopback_addr;

	} else {

	  addr.sin_addr = loopback_addr;

	}

      } else {

	addr.sin_addr = so->so_faddr;

      }

      addr.sin_port = so->so_fport;

      if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,

		(struct sockaddr *)&addr, sizeof(addr)) == -1) {

	DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",

		    errno,strerror(errno)));

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

	udp_detach(so);

      }

    } /* if ip->ip_dst.s_addr == alias_addr.s_addr */

    break;

  case ICMP_UNREACH:

    /* XXX? report error? close socket? */

  case ICMP_TIMXCEED:

  case ICMP_PARAMPROB:

  case ICMP_SOURCEQUENCH:

  case ICMP_TSTAMP:

  case ICMP_MASKREQ:

  case ICMP_REDIRECT:

    m_free(m);

    break;



  default:

    m_free(m);

  } /* swith */



end_error:

  /* m is m_free()'d xor put in a socket xor or given to ip_send */

  return;

}

icmp_input(struct mbuf *m, int hlen)

{

  register struct icmp *icp;

  register struct ip *ip=mtod(m, struct ip *);

  int icmplen=ip->ip_len;

  Slirp *slirp = m->slirp;



  DEBUG_CALL("icmp_input");

  DEBUG_ARG("m = %p", m);

  DEBUG_ARG("m_len = %d", m->m_len);



  







  if (icmplen < ICMP_MINLEN) {          

  freeit:

    m_free(m);

    goto end_error;

  }



  m->m_len -= hlen;

  m->m_data += hlen;

  icp = mtod(m, struct icmp *);

  if (cksum(m, icmplen)) {

    goto freeit;

  }

  m->m_len += hlen;

  m->m_data -= hlen;



  DEBUG_ARG("icmp_type = %d", icp->icmp_type);

  switch (icp->icmp_type) {

  case ICMP_ECHO:

    ip->ip_len += hlen;	             

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

      icmp_reflect(m);

    } else if (slirp->restricted) {

        goto freeit;

    } else {

      struct socket *so;

      struct sockaddr_in addr;

      if ((so = socreate(slirp)) == NULL) goto freeit;

      if (icmp_send(so, m, hlen) == 0) {

        return;

      }

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

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

		    errno,strerror(errno)));

	sofree(so);

	m_free(m);

	goto end_error;

      }

      so->so_m = m;

      so->so_ffamily = AF_INET;

      so->so_faddr = ip->ip_dst;

      so->so_fport = htons(7);

      so->so_lfamily = AF_INET;

      so->so_laddr = ip->ip_src;

      so->so_lport = htons(9);

      so->so_iptos = ip->ip_tos;

      so->so_type = IPPROTO_ICMP;

      so->so_state = SS_ISFCONNECTED;



      

      addr.sin_family = AF_INET;

      if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==

          slirp->vnetwork_addr.s_addr) {

	

	if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {

	  if (get_dns_addr(&addr.sin_addr) < 0)

	    addr.sin_addr = loopback_addr;

	} else {

	  addr.sin_addr = loopback_addr;

	}

      } else {

	addr.sin_addr = so->so_faddr;

      }

      addr.sin_port = so->so_fport;

      if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,

		(struct sockaddr *)&addr, sizeof(addr)) == -1) {

	DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",

		    errno,strerror(errno)));

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

	udp_detach(so);

      }

    } 

    break;

  case ICMP_UNREACH:

    

  case ICMP_TIMXCEED:

  case ICMP_PARAMPROB:

  case ICMP_SOURCEQUENCH:

  case ICMP_TSTAMP:

  case ICMP_MASKREQ:

  case ICMP_REDIRECT:

    m_free(m);

    break;



  default:

    m_free(m);

  } 



end_error:

  

  return;

}

FUNC_0(struct mbuf *VAR_0, int VAR_1)

{

  register struct icmp *VAR_2;

  register struct VAR_3 *VAR_3=mtod(VAR_0, struct VAR_3 *);

  int VAR_4=VAR_3->ip_len;

  Slirp *slirp = VAR_0->slirp;



  DEBUG_CALL("FUNC_0");

  DEBUG_ARG("VAR_0 = %p", VAR_0);

  DEBUG_ARG("m_len = %d", VAR_0->m_len);



  







  if (VAR_4 < ICMP_MINLEN) {          

  freeit:

    m_free(VAR_0);

    goto end_error;

  }



  VAR_0->m_len -= VAR_1;

  VAR_0->m_data += VAR_1;

  VAR_2 = mtod(VAR_0, struct icmp *);

  if (cksum(VAR_0, VAR_4)) {

    goto freeit;

  }

  VAR_0->m_len += VAR_1;

  VAR_0->m_data -= VAR_1;



  DEBUG_ARG("icmp_type = %d", VAR_2->icmp_type);

  switch (VAR_2->icmp_type) {

  case ICMP_ECHO:

    VAR_3->ip_len += VAR_1;	             

    if (VAR_3->ip_dst.s_addr == slirp->vhost_addr.s_addr) {

      icmp_reflect(VAR_0);

    } else if (slirp->restricted) {

        goto freeit;

    } else {

      struct socket *VAR_5;

      struct sockaddr_in VAR_6;

      if ((VAR_5 = socreate(slirp)) == NULL) goto freeit;

      if (icmp_send(VAR_5, VAR_0, VAR_1) == 0) {

        return;

      }

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

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

		    errno,strerror(errno)));

	sofree(VAR_5);

	m_free(VAR_0);

	goto end_error;

      }

      VAR_5->so_m = VAR_0;

      VAR_5->so_ffamily = AF_INET;

      VAR_5->so_faddr = VAR_3->ip_dst;

      VAR_5->so_fport = htons(7);

      VAR_5->so_lfamily = AF_INET;

      VAR_5->so_laddr = VAR_3->ip_src;

      VAR_5->so_lport = htons(9);

      VAR_5->so_iptos = VAR_3->ip_tos;

      VAR_5->so_type = IPPROTO_ICMP;

      VAR_5->so_state = SS_ISFCONNECTED;



      

      VAR_6.sin_family = AF_INET;

      if ((VAR_5->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==

          slirp->vnetwork_addr.s_addr) {

	

	if (VAR_5->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {

	  if (get_dns_addr(&VAR_6.sin_addr) < 0)

	    VAR_6.sin_addr = loopback_addr;

	} else {

	  VAR_6.sin_addr = loopback_addr;

	}

      } else {

	VAR_6.sin_addr = VAR_5->so_faddr;

      }

      VAR_6.sin_port = VAR_5->so_fport;

      if(sendto(VAR_5->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,

		(struct sockaddr *)&VAR_6, sizeof(VAR_6)) == -1) {

	DEBUG_MISC((dfd,"FUNC_0 udp sendto tx errno = %d-%s\n",

		    errno,strerror(errno)));

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

	udp_detach(VAR_5);

      }

    } 

    break;

  case ICMP_UNREACH:

    

  case ICMP_TIMXCEED:

  case ICMP_PARAMPROB:

  case ICMP_SOURCEQUENCH:

  case ICMP_TSTAMP:

  case ICMP_MASKREQ:

  case ICMP_REDIRECT:

    m_free(VAR_0);

    break;



  default:

    m_free(VAR_0);

  } 



end_error:

  

  return;

}

FUNC_0(struct mbuf *VAR_0, int VAR_1)
{ register struct icmp *VAR_2; register struct VAR_3 *VAR_3=mtod(VAR_0, struct VAR_3 *); int VAR_4=VAR_3->ip_len; Slirp *slirp = VAR_0->slirp; DEBUG_CALL("FUNC_0"); DEBUG_ARG("VAR_0 = %p", VAR_0); DEBUG_ARG("m_len = %d", VAR_0->m_len); if (VAR_4 < ICMP_MINLEN) { freeit:
m_free(VAR_0); goto end_error; } VAR_0->m_len -= VAR_1; VAR_0->m_data += VAR_1; VAR_2 = mtod(VAR_0, struct icmp *); if (cksum(VAR_0, VAR_4)) { goto freeit; } VAR_0->m_len += VAR_1; VAR_0->m_data -= VAR_1; DEBUG_ARG("icmp_type = %d", VAR_2->icmp_type); switch (VAR_2->icmp_type) { case ICMP_ECHO:
VAR_3->ip_len += VAR_1; if (VAR_3->ip_dst.s_addr == slirp->vhost_addr.s_addr) { icmp_reflect(VAR_0); } else if (slirp->restricted) { goto freeit; } else { struct socket *VAR_5; struct sockaddr_in VAR_6; if ((VAR_5 = socreate(slirp)) == NULL) goto freeit; if (icmp_send(VAR_5, VAR_0, VAR_1) == 0) { return; } if(udp_attach(VAR_5) == -1) { DEBUG_MISC((dfd,"FUNC_0 udp_attach errno = %d-%s\n",
errno,strerror(errno))); sofree(VAR_5); m_free(VAR_0); goto end_error; } VAR_5->so_m = VAR_0; VAR_5->so_ffamily = AF_INET; VAR_5->so_faddr = VAR_3->ip_dst; VAR_5->so_fport = htons(7); VAR_5->so_lfamily = AF_INET; VAR_5->so_laddr = VAR_3->ip_src; VAR_5->so_lport = htons(9); VAR_5->so_iptos = VAR_3->ip_tos; VAR_5->so_type = IPPROTO_ICMP; VAR_5->so_state = SS_ISFCONNECTED; VAR_6.sin_family = AF_INET; if ((VAR_5->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
slirp->vnetwork_addr.s_addr) { if (VAR_5->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { if (get_dns_addr(&VAR_6.sin_addr) < 0)
VAR_6.sin_addr = loopback_addr; } else { VAR_6.sin_addr = loopback_addr; } } else { VAR_6.sin_addr = VAR_5->so_faddr; } VAR_6.sin_port = VAR_5->so_fport; if(sendto(VAR_5->s, icmp_ping_msg, strlen(icmp_ping_msg), 0,
(struct sockaddr *)&VAR_6, sizeof(VAR_6)) == -1) { DEBUG_MISC((dfd,"FUNC_0 udp sendto tx errno = %d-%s\n",
errno,strerror(errno))); icmp_error(VAR_0, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); udp_detach(VAR_5); } } break; case ICMP_UNREACH:
case ICMP_TIMXCEED:
case ICMP_PARAMPROB:
case ICMP_SOURCEQUENCH:
case ICMP_TSTAMP:
case ICMP_MASKREQ:
case ICMP_REDIRECT:
m_free(VAR_0); break; default:
m_free(VAR_0); } end_error:
return; }