예제 #1
0
struct socket *
udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr,
           u_int lport, int flags)
{
	struct sockaddr_in addr;
	struct socket *so;
	socklen_t addrlen = sizeof(struct sockaddr_in);

	so = socreate(slirp);
	if (!so) {
	    return NULL;
	}
	so->s = qemu_socket(AF_INET,SOCK_DGRAM,0);
	so->so_expire = curtime + SO_EXPIRE;
	insque(so, &slirp->udb);

	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = haddr;
	addr.sin_port = hport;

	if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0) {
		udp_detach(so);
		return NULL;
	}
	socket_set_fast_reuse(so->s);

	getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
	so->so_fport = addr.sin_port;
	if (addr.sin_addr.s_addr == 0 ||
	    addr.sin_addr.s_addr == loopback_addr.s_addr) {
	   so->so_faddr = slirp->vhost_addr;
	} else {
	   so->so_faddr = addr.sin_addr;
	}
	so->so_lport = lport;
	so->so_laddr.s_addr = laddr;
	if (flags != SS_FACCEPTONCE)
	   so->so_expire = 0;

	so->so_state &= SS_PERSISTENT_MASK;
	so->so_state |= SS_ISFCONNECTED | flags;

	return so;
}
예제 #2
0
struct socket *
udp_listen(u_int port, u_int32_t laddr, u_int lport, int flags)
{
	struct socket *so;
	SockAddress    addr;
	uint32_t       addr_ip;

	if ((so = socreate()) == NULL) {
		free(so);
		return NULL;
	}
	so->s = socket_anyaddr_server( port, SOCKET_DGRAM );
	so->so_expire = curtime + SO_EXPIRE;
    so->so_haddr_port = port;
	insque(so,&udb);

	if (so->s < 0) {
		udp_detach(so);
		return NULL;
	}

        socket_get_address(so->s, &addr);

	so->so_faddr_port = sock_address_get_port(&addr);
	addr_ip = sock_address_get_ip(&addr);

	if (addr_ip == 0 || addr_ip == loopback_addr_ip)
	   so->so_faddr_ip = alias_addr_ip;
	else
	   so->so_faddr_ip = addr_ip;

	so->so_laddr_port = lport;
	so->so_laddr_ip   = laddr;
	if (flags != SS_FACCEPTONCE)
	   so->so_expire = 0;

	so->so_state = SS_ISFCONNECTED;

	return so;
}
예제 #3
0
파일: socket.c 프로젝트: djs55/qemu
/*
 * recvfrom() a UDP socket
 */
void
sorecvfrom(struct socket *so)
{
	struct sockaddr_in addr;
	socklen_t addrlen = sizeof(struct sockaddr_in);

	DEBUG_CALL("sorecvfrom");
	DEBUG_ARG("so = %lx", (long)so);

	if (so->so_type == IPPROTO_ICMP) {   /* This is a "ping" reply */
	  char buff[256];
	  int len;

	  len = recvfrom(so->s, buff, 256, 0,
			 (struct sockaddr *)&addr, &addrlen);
	  /* XXX Check if reply is "correct"? */

	  if(len == -1 || len == 0) {
	    u_char code=ICMP_UNREACH_PORT;

	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;

	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
			errno,strerror(errno)));
	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
	  } else {
	    icmp_reflect(so->so_m);
            so->so_m = NULL; /* Don't m_free() it again! */
	  }
	  /* No need for this socket anymore, udp_detach it */
	  udp_detach(so);
	} else {                            	/* A "normal" UDP packet */
	  struct mbuf *m;
          int len;
#ifdef _WIN32
          unsigned long n;
#else
          int n;
#endif

	  m = m_get(so->slirp);
	  if (!m) {
	      return;
	  }
	  m->m_data += IF_MAXLINKHDR;

	  /*
	   * XXX Shouldn't FIONREAD packets destined for port 53,
	   * but I don't know the max packet size for DNS lookups
	   */
	  len = M_FREEROOM(m);
	  /* if (so->so_fport != htons(53)) { */
	  ioctlsocket(so->s, FIONREAD, &n);

	  if (n > len) {
	    n = (m->m_data - m->m_dat) + m->m_len + n + 1;
	    m_inc(m, n);
	    len = M_FREEROOM(m);
	  }
	  /* } */

	  m->m_len = recvfrom(so->s, m->m_data, len, 0,
			      (struct sockaddr *)&addr, &addrlen);
	  DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
		      m->m_len, errno,strerror(errno)));
	  if(m->m_len<0) {
	    u_char code=ICMP_UNREACH_PORT;

	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;

	    DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
	    m_free(m);
	  } else {
	  /*
	   * Hack: domain name lookup will be used the most for UDP,
	   * and since they'll only be used once there's no need
	   * for the 4 minute (or whatever) timeout... So we time them
	   * out much quicker (10 seconds  for now...)
	   */
	    if (so->so_expire) {
	      if (so->so_fport == htons(53))
		so->so_expire = curtime + SO_EXPIREFAST;
	      else
		so->so_expire = curtime + SO_EXPIRE;
	    }

	    /*
	     * If this packet was destined for CTL_ADDR,
	     * make it look like that's where it came from, done by udp_output
	     */
	    udp_output(so, m, &addr);
	  } /* rx error */
	} /* if ping packet */
}
예제 #4
0
파일: slirp.c 프로젝트: AlexandreCo/macemu
int slirp_select_fill(int *pnfds, 
					  fd_set *readfds, fd_set *writefds, fd_set *xfds)
{
    struct socket *so, *so_next;
    int nfds;
    int timeout, tmp_time;

    /* fail safe */
    global_readfds = NULL;
    global_writefds = NULL;
    global_xfds = NULL;
    
    nfds = *pnfds;
	/*
	 * First, TCP sockets
	 */
	do_slowtimo = 0;
	if (link_up) {
		/* 
		 * *_slowtimo needs calling if there are IP fragments
		 * in the fragment queue, or there are TCP connections active
		 */
		do_slowtimo = ((tcb.so_next != &tcb) ||
			       ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
		
		for (so = tcb.so_next; so != &tcb; so = so_next) {
			so_next = so->so_next;
			
			/*
			 * See if we need a tcp_fasttimo
			 */
			if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
			   time_fasttimo = curtime; /* Flag when we want a fasttimo */
			
			/*
			 * NOFDREF can include still connecting to local-host,
			 * newly socreated() sockets etc. Don't want to select these.
	 		 */
			if (so->so_state & SS_NOFDREF || so->s == -1)
			   continue;
			
			/*
			 * Set for reading sockets which are accepting
			 */
			if (so->so_state & SS_FACCEPTCONN) {
                                FD_SET(so->s, readfds);
				UPD_NFDS(so->s);
				continue;
			}
			
			/*
			 * Set for writing sockets which are connecting
			 */
			if (so->so_state & SS_ISFCONNECTING) {
				FD_SET(so->s, writefds);
				UPD_NFDS(so->s);
				continue;
			}
			
			/*
			 * Set for writing if we are connected, can send more, and
			 * we have something to send
			 */
			if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
				FD_SET(so->s, writefds);
				UPD_NFDS(so->s);
			}
			
			/*
			 * Set for reading (and urgent data) if we are connected, can
			 * receive more, and we have room for it XXX /2 ?
			 */
			if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
				FD_SET(so->s, readfds);
				FD_SET(so->s, xfds);
				UPD_NFDS(so->s);
			}
		}
		
		/*
		 * UDP sockets
		 */
		for (so = udb.so_next; so != &udb; so = so_next) {
			so_next = so->so_next;
			
			/*
			 * See if it's timed out
			 */
			if (so->so_expire) {
				if (so->so_expire <= curtime) {
					udp_detach(so);
					continue;
				} else
					do_slowtimo = 1; /* Let socket expire */
			}
			
			/*
			 * When UDP packets are received from over the
			 * link, they're sendto()'d straight away, so
			 * no need for setting for writing
			 * Limit the number of packets queued by this session
			 * to 4.  Note that even though we try and limit this
			 * to 4 packets, the session could have more queued
			 * if the packets needed to be fragmented
			 * (XXX <= 4 ?)
			 */
			if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
				FD_SET(so->s, readfds);
				UPD_NFDS(so->s);
			}
		}
	}
	
	/*
	 * Setup timeout to use minimum CPU usage, especially when idle
	 */

	timeout = -1;

	/*
	 * If a slowtimo is needed, set timeout to 5ms from the last
	 * slow timeout. If a fast timeout is needed, set timeout within
	 * 2ms of when it was requested.
	 */
#	define SLOW_TIMO 5
#	define FAST_TIMO 2
	if (do_slowtimo) {
		timeout = (SLOW_TIMO - (curtime - last_slowtimo)) * 1000;
		if (timeout < 0)
		   timeout = 0;
		else if (timeout > (SLOW_TIMO * 1000))
		   timeout = SLOW_TIMO * 1000;
		
		/* Can only fasttimo if we also slowtimo */
		if (time_fasttimo) {
			tmp_time = (FAST_TIMO - (curtime - time_fasttimo)) * 1000;
			if (tmp_time < 0)
				tmp_time = 0;
			
			/* Choose the smallest of the 2 */
			if (tmp_time < timeout)
			   timeout = tmp_time;
		}
	}
	*pnfds = nfds;

	/*
	 * Adjust the timeout to make the minimum timeout
	 * 2ms (XXX?) to lessen the CPU load
	 */
	if (timeout < (FAST_TIMO * 1000))
		timeout = FAST_TIMO * 1000;

	return timeout;
}	
예제 #5
0
파일: ip_icmp.c 프로젝트: 0bliv10n/s2e
/*
 * Process a received ICMP message.
 */
void
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 = %lx", (long )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_faddr = ip->ip_dst;
      so->so_fport = htons(7);
      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;
}
예제 #6
0
struct socket *
udp_listen(PNATState pData, u_int32_t bind_addr, u_int port, u_int32_t laddr, u_int lport, int flags)
{
    struct sockaddr_in addr;
    struct socket *so;
    socklen_t addrlen = sizeof(struct sockaddr_in);
    int opt = 1;
    LogFlowFunc(("ENTER: bind_addr:%RTnaipv4, port:%d, laddr:%RTnaipv4, lport:%d, flags:%x\n",
                 bind_addr, RT_N2H_U16(port), laddr, RT_N2H_U16(lport), flags));

    if ((so = socreate()) == NULL)
    {
        LogFlowFunc(("LEAVE: NULL\n"));
        return NULL;
    }

    so->s = socket(AF_INET, SOCK_DGRAM, 0);
    if (so->s == -1)
    {
        LogRel(("NAT: can't create datagram socket\n"));
        RTMemFree(so);
        LogFlowFunc(("LEAVE: NULL\n"));
        return NULL;
    }
    so->so_expire = curtime + SO_EXPIRE;
    so->so_type = IPPROTO_UDP;
    fd_nonblock(so->s);
    so->so_sottl = 0;
    so->so_sotos = 0;
    so->so_sodf = -1;
    SOCKET_LOCK_CREATE(so);
    QSOCKET_LOCK(udb);
    insque(pData, so, &udb);
    NSOCK_INC();
    QSOCKET_UNLOCK(udb);

    memset(&addr, 0, sizeof(addr));
#ifdef RT_OS_DARWIN
    addr.sin_len = sizeof(addr);
#endif
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = bind_addr;
    addr.sin_port = port;

    if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0)
    {
        LogRel(("NAT: udp bind to %RTnaipv4:%d failed, error %d\n",
                addr.sin_addr, RT_N2H_U16(port), errno));
        udp_detach(pData, so);
        LogFlowFunc(("LEAVE: NULL\n"));
        return NULL;
    }
    setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR,(char *)&opt, sizeof(int));
/*  setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE,(char *)&opt, sizeof(int)); */

    getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
    so->so_hladdr = addr.sin_addr;
    so->so_hlport = addr.sin_port;

    /* XXX: wtf are we setting so_faddr/so_fport here? */
    so->so_fport = addr.sin_port;
#if 0
    /* The original check was completely broken, as the commented out
     * if statement was always true (INADDR_ANY=0). */
    /** @todo vvl - alias_addr should be set (if required)
     * later by liabalias module.
     */
    if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
        so->so_faddr = alias_addr;
    else
#endif
        so->so_faddr = addr.sin_addr;

    so->so_lport = lport;
    so->so_laddr.s_addr = laddr;
    if (flags != SS_FACCEPTONCE)
        so->so_expire = 0;

    so->so_state = SS_ISFCONNECTED;

    LogFlowFunc(("LEAVE: %R[natsock]\n", so));
    return so;
}
예제 #7
0
void slirp_select_fill(int *pnfds,
                       fd_set *readfds, fd_set *writefds, fd_set *xfds)
{
    struct socket *so, *so_next;
    struct timeval timeout;
    int nfds;
    int tmp_time;

    
    global_readfds = NULL;
    global_writefds = NULL;
    global_xfds = NULL;

    nfds = *pnfds;
	do_slowtimo = 0;
	if (link_up) {
		do_slowtimo = ((tcb.so_next != &tcb) ||
                (&ipq.ip_link != ipq.ip_link.next));

		for (so = tcb.so_next; so != &tcb; so = so_next) {
			so_next = so->so_next;

			if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
			   time_fasttimo = curtime; 

			if (so->so_state & SS_NOFDREF || so->s == -1)
			   continue;

            if ((so->so_state & SS_PROXIFIED) != 0)
	            continue;

			if (so->so_state & SS_FACCEPTCONN) {
                                FD_SET(so->s, readfds);
				UPD_NFDS(so->s);
				continue;
			}

			if (so->so_state & SS_ISFCONNECTING) {
				FD_SET(so->s, writefds);
				UPD_NFDS(so->s);
				continue;
			}

			if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
				FD_SET(so->s, writefds);
				UPD_NFDS(so->s);
			}

			if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
				FD_SET(so->s, readfds);
				FD_SET(so->s, xfds);
				UPD_NFDS(so->s);
			}
		}

		for (so = udb.so_next; so != &udb; so = so_next) {
			so_next = so->so_next;

            if ((so->so_state & SS_PROXIFIED) != 0)
                continue;

			if (so->so_expire) {
				if (so->so_expire <= curtime) {
					udp_detach(so);
					continue;
				} else
					do_slowtimo = 1; 
			}

			if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
				FD_SET(so->s, readfds);
				UPD_NFDS(so->s);
			}
		}
	}


	timeout.tv_sec = 0;
	timeout.tv_usec = -1;
	if (do_slowtimo) {
		
		timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
		if (timeout.tv_usec < 0)
		   timeout.tv_usec = 0;
		else if (timeout.tv_usec > 510000)
		   timeout.tv_usec = 510000;

		
		if (time_fasttimo) {
			tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
			if (tmp_time < 0)
			   tmp_time = 0;

			
			if (tmp_time < timeout.tv_usec)
			   timeout.tv_usec = (u_int)tmp_time;
		}
	}
    proxy_manager_select_fill(&nfds, readfds, writefds, xfds);

        *pnfds = nfds;
}
예제 #8
0
void slirp_select_fill(int *pnfds,
                       fd_set *readfds, fd_set *writefds, fd_set *xfds)
{
    struct socket *so, *so_next;
    struct timeval timeout;
    int nfds;
    int tmp_time;

    /* fail safe */
    global_readfds = NULL;
    global_writefds = NULL;
    global_xfds = NULL;

    nfds = *pnfds;
	/*
	 * First, TCP sockets
	 */
	do_slowtimo = 0;
	if (link_up) {
		/*
		 * *_slowtimo needs calling if there are IP fragments
		 * in the fragment queue, or there are TCP connections active
		 */
		do_slowtimo = ((tcb.so_next != &tcb) ||
                (&ipq.ip_link != ipq.ip_link.next));

		for (so = tcb.so_next; so != &tcb; so = so_next) {
			so_next = so->so_next;

			/*
			 * See if we need a tcp_fasttimo
			 */
			if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
			   time_fasttimo = curtime; /* Flag when we want a fasttimo */

			/*
			 * NOFDREF can include still connecting to local-host,
			 * newly socreated() sockets etc. Don't want to select these.
	 		 */
			if (so->so_state & SS_NOFDREF || so->s == -1)
			   continue;

            /*
             * don't register proxified socked connections here
             */
            if ((so->so_state & SS_PROXIFIED) != 0)
	            continue;

			/*
			 * Set for reading sockets which are accepting
			 */
			if (so->so_state & SS_FACCEPTCONN) {
                                FD_SET(so->s, readfds);
				UPD_NFDS(so->s);
				continue;
			}

			/*
			 * Set for writing sockets which are connecting
			 */
			if (so->so_state & SS_ISFCONNECTING) {
				FD_SET(so->s, writefds);
				UPD_NFDS(so->s);
				continue;
			}

			/*
			 * Set for writing if we are connected, can send more, and
			 * we have something to send
			 */
			if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
				FD_SET(so->s, writefds);
				UPD_NFDS(so->s);
			}

			/*
			 * Set for reading (and urgent data) if we are connected, can
			 * receive more, and we have room for it XXX /2 ?
			 */
			if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
				FD_SET(so->s, readfds);
				FD_SET(so->s, xfds);
				UPD_NFDS(so->s);
			}
		}

		/*
		 * UDP sockets
		 */
		for (so = udb.so_next; so != &udb; so = so_next) {
			so_next = so->so_next;

            if ((so->so_state & SS_PROXIFIED) != 0)
                continue;

			/*
			 * See if it's timed out
			 */
			if (so->so_expire) {
				if (so->so_expire <= curtime) {
					udp_detach(so);
					continue;
				} else
					do_slowtimo = 1; /* Let socket expire */
			}

			/*
			 * When UDP packets are received from over the
			 * link, they're sendto()'d straight away, so
			 * no need for setting for writing
			 * Limit the number of packets queued by this session
			 * to 4.  Note that even though we try and limit this
			 * to 4 packets, the session could have more queued
			 * if the packets needed to be fragmented
			 * (XXX <= 4 ?)
			 */
			if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
				FD_SET(so->s, readfds);
				UPD_NFDS(so->s);
			}
		}
	}

	/*
	 * Setup timeout to use minimum CPU usage, especially when idle
	 */

	/*
	 * First, see the timeout needed by *timo
	 */
	timeout.tv_sec = 0;
	timeout.tv_usec = -1;
	/*
	 * If a slowtimo is needed, set timeout to 500ms from the last
	 * slow timeout. If a fast timeout is needed, set timeout within
	 * 200ms of when it was requested.
	 */
	if (do_slowtimo) {
		/* XXX + 10000 because some select()'s aren't that accurate */
		timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
		if (timeout.tv_usec < 0)
		   timeout.tv_usec = 0;
		else if (timeout.tv_usec > 510000)
		   timeout.tv_usec = 510000;

		/* Can only fasttimo if we also slowtimo */
		if (time_fasttimo) {
			tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
			if (tmp_time < 0)
			   tmp_time = 0;

			/* Choose the smallest of the 2 */
			if (tmp_time < timeout.tv_usec)
			   timeout.tv_usec = (u_int)tmp_time;
		}
	}
    /*
     * now, the proxified sockets
     */
    proxy_manager_select_fill(&nfds, readfds, writefds, xfds);

        *pnfds = nfds;
}
예제 #9
0
void
icmp_input(struct mbuf *m, int hlen)
{
  register struct icmp *icp;
  register struct ip *ip=mtod(m, struct ip *);
  int icmplen=ip->ip_len;
  /* int code; */

  DEBUG_CALL("icmp_input");
  DEBUG_ARG("m = %lx", (long )m);
  DEBUG_ARG("m_len = %d", m->m_len);

  STAT(icmpstat.icps_received++);

  /*
   * 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 */
    STAT(icmpstat.icps_tooshort++);
  freeit:
    m_freem(m);
    goto end_error;
  }

  m->m_len -= hlen;
  m->m_data += hlen;
  icp = mtod(m, struct icmp *);
  if (cksum(m, icmplen)) {
    STAT(icmpstat.icps_checksum++);
    goto freeit;
  }
  m->m_len += hlen;
  m->m_data -= hlen;

  /*	icmpstat.icps_inhist[icp->icmp_type]++; */
  /* code = icp->icmp_code; */

  DEBUG_ARG("icmp_type = %d", icp->icmp_type);
  switch (icp->icmp_type) {
  case ICMP_ECHO:
    icp->icmp_type = ICMP_ECHOREPLY;
    ip->ip_len += hlen;	             /* since ip_input subtracts this */
    if (ip_geth(ip->ip_dst) == alias_addr_ip) {
      icmp_reflect(m);
    } else {
      struct socket *so;
      SockAddress  addr;
      uint32_t     addr_ip;
      uint16_t     addr_port;

      if ((so = socreate()) == NULL) goto freeit;
      if(udp_attach(so) == -1) {
	DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n",
		    errno,errno_str));
	sofree(so);
	m_free(m);
	goto end_error;
      }
      so->so_m = m;
      so->so_faddr_ip   = ip_geth(ip->ip_dst);
      so->so_faddr_port = 7;
      so->so_laddr_ip   = ip_geth(ip->ip_src);
      so->so_laddr_port = 9;
      so->so_iptos = ip->ip_tos;
      so->so_type = IPPROTO_ICMP;
      so->so_state = SS_ISFCONNECTED;

      /* Send the packet */
      if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) {
        /* It's an alias */
        int  low = so->so_faddr_ip & 0xff;

        if (low >= CTL_DNS && low < CTL_DNS + dns_addr_count)
            addr_ip = dns_addr[low - CTL_DNS];
        else
            addr_ip = loopback_addr_ip;
      } else {
            addr_ip = so->so_faddr_ip;
      }
      addr_port = so->so_faddr_port;

      sock_address_init_inet( &addr, addr_ip, addr_port );

      if(socket_sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), &addr) < 0) {
        DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n",
                    errno,errno_str));
        icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,errno_str);
        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:
    STAT(icmpstat.icps_notsupp++);
    m_freem(m);
    break;

  default:
    STAT(icmpstat.icps_badtype++);
    m_freem(m);
  } /* swith */

end_error:
  /* m is m_free()'d xor put in a socket xor or given to ip_send */
  return;
}
예제 #10
0
void udp_cleanup(Slirp *slirp)
{
    while (slirp->udb.so_next != &slirp->udb) {
        udp_detach(slirp->udb.so_next);
    }
}
예제 #11
0
파일: ip_icmp.cpp 프로젝트: Blonder/WinUAE
/*
 * Process a received ICMP message.
 */
void icmp_input(struct mbuf *m, int hlen)
{
  register struct icmp *icp;
  register struct ip *ip=mtod(m, struct ip *);
  int icmplen=ip->ip_len;
  /* int code; */
	
  DEBUG_CALL("icmp_input");
  DEBUG_ARG("m = %p", m);
  DEBUG_ARG("m_len = %d", m->m_len);

  icmpstat.icps_received++;
	
  /*
   * 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 */
    icmpstat.icps_tooshort++;
  freeit:
    m_freem(m);
    goto end_error;
  }

  m->m_len -= hlen;
  m->m_data += hlen;
  icp = mtod(m, struct icmp *);
  if (cksum(m, icmplen)) {
    icmpstat.icps_checksum++;
    goto freeit;
  }
  m->m_len += hlen;
  m->m_data -= hlen;
  
  /*	icmpstat.icps_inhist[icp->icmp_type]++; */
  /* code = icp->icmp_code; */

  DEBUG_ARG("icmp_type = %d", icp->icmp_type);
  switch (icp->icmp_type) {
  case ICMP_ECHO:
    icp->icmp_type = ICMP_ECHOREPLY;
    ip->ip_len += hlen;	             /* since ip_input subtracts this */
    if (ip->ip_dst.s_addr == alias_addr.s_addr) {
      icmp_reflect(m);
    } else {
      struct socket *so;
      struct sockaddr_in addr;
      if ((so = socreate()) == NULL) goto freeit;
      if (icmp_send(so, m, hlen) == 0)
        return;
      if(udp_attach(so) == -1) {
	DEBUG_MISC(("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_faddr = ip->ip_dst;
      so->so_fport = htons(7);
      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 & htonl(0xffffff00)) == special_addr.s_addr) {
	/* It's an alias */
	switch(ntohl(so->so_faddr.s_addr) & 0xff) {
	case CTL_DNS:
	  addr.sin_addr = dns_addr;
	  break;
	case CTL_ALIAS:
	default:
	  addr.sin_addr = loopback_addr;
	  break;
	}
      } 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(("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:
    icmpstat.icps_notsupp++;
    m_freem(m);
    break;
    
  default:
    icmpstat.icps_badtype++;
    m_freem(m);
  } /* swith */

end_error:
  /* m is m_free()'d xor put in a socket xor or given to ip_send */
  return;
}
예제 #12
0
파일: socket.c 프로젝트: m000/panda
/*
 * recvfrom() a UDP socket
 */
void
sorecvfrom(struct socket *so)
{
	struct sockaddr_storage addr;
	struct sockaddr_storage saddr, daddr;
	socklen_t addrlen = sizeof(struct sockaddr_storage);

	DEBUG_CALL("sorecvfrom");
	DEBUG_ARG("so = %p", so);

	if (so->so_type == IPPROTO_ICMP) {   /* This is a "ping" reply */
	  char buff[256];
	  int len;

	  len = recvfrom(so->s, buff, 256, 0,
			 (struct sockaddr *)&addr, &addrlen);
	  /* XXX Check if reply is "correct"? */

	  if(len == -1 || len == 0) {
	    u_char code=ICMP_UNREACH_PORT;

	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;

	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
			errno,strerror(errno)));
	    icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
	  } else {
	    icmp_reflect(so->so_m);
            so->so_m = NULL; /* Don't m_free() it again! */
	  }
	  /* No need for this socket anymore, udp_detach it */
	  udp_detach(so);
	} else {                            	/* A "normal" UDP packet */
	  struct mbuf *m;
          int len;
#ifdef _WIN32
          unsigned long n;
#else
          int n;
#endif

	  m = m_get(so->slirp);
	  if (!m) {
	      return;
	  }
	  switch (so->so_ffamily) {
	  case AF_INET:
	      m->m_data += IF_MAXLINKHDR + sizeof(struct udpiphdr);
	      break;
	  case AF_INET6:
	      m->m_data += IF_MAXLINKHDR + sizeof(struct ip6)
	                                 + sizeof(struct udphdr);
	      break;
	  default:
	      g_assert_not_reached();
	      break;
	  }

	  /*
	   * XXX Shouldn't FIONREAD packets destined for port 53,
	   * but I don't know the max packet size for DNS lookups
	   */
	  len = M_FREEROOM(m);
	  /* if (so->so_fport != htons(53)) { */
	  ioctlsocket(so->s, FIONREAD, &n);

	  if (n > len) {
	    n = (m->m_data - m->m_dat) + m->m_len + n + 1;
	    m_inc(m, n);
	    len = M_FREEROOM(m);
	  }
	  /* } */

	  m->m_len = recvfrom(so->s, m->m_data, len, 0,
			      (struct sockaddr *)&addr, &addrlen);
	  DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
		      m->m_len, errno,strerror(errno)));
	  if(m->m_len<0) {
	    /* Report error as ICMP */
	    switch (so->so_lfamily) {
	    uint8_t code;
	    case AF_INET:
	      code = ICMP_UNREACH_PORT;

	      if (errno == EHOSTUNREACH) {
		code = ICMP_UNREACH_HOST;
	      } else if (errno == ENETUNREACH) {
		code = ICMP_UNREACH_NET;
	      }

	      DEBUG_MISC((dfd, " rx error, tx icmp ICMP_UNREACH:%i\n", code));
	      icmp_send_error(so->so_m, ICMP_UNREACH, code, 0, strerror(errno));
	      break;
	    case AF_INET6:
	      code = ICMP6_UNREACH_PORT;

	      if (errno == EHOSTUNREACH) {
		code = ICMP6_UNREACH_ADDRESS;
	      } else if (errno == ENETUNREACH) {
		code = ICMP6_UNREACH_NO_ROUTE;
	      }

	      DEBUG_MISC((dfd, " rx error, tx icmp6 ICMP_UNREACH:%i\n", code));
	      icmp6_send_error(so->so_m, ICMP6_UNREACH, code);
	      break;
	    default:
	      g_assert_not_reached();
	      break;
	    }
	    m_free(m);
	  } else {
	  /*
	   * Hack: domain name lookup will be used the most for UDP,
	   * and since they'll only be used once there's no need
	   * for the 4 minute (or whatever) timeout... So we time them
	   * out much quicker (10 seconds  for now...)
	   */
	    if (so->so_expire) {
	      if (so->so_fport == htons(53))
		so->so_expire = curtime + SO_EXPIREFAST;
	      else
		so->so_expire = curtime + SO_EXPIRE;
	    }

	    /*
	     * If this packet was destined for CTL_ADDR,
	     * make it look like that's where it came from
	     */
	    saddr = addr;
	    sotranslate_in(so, &saddr);
	    daddr = so->lhost.ss;

	    switch (so->so_ffamily) {
	    case AF_INET:
	        udp_output(so, m, (struct sockaddr_in *) &saddr,
	                   (struct sockaddr_in *) &daddr,
	                   so->so_iptos);
	        break;
	    case AF_INET6:
	        udp6_output(so, m, (struct sockaddr_in6 *) &saddr,
	                    (struct sockaddr_in6 *) &daddr);
	        break;
	    default:
	        g_assert_not_reached();
	        break;
	    }
	  } /* rx error */
	} /* if ping packet */
}