示例#1
0
文件: socket.c 项目: JMR-b/qemu
/*
 * sendto() a socket
 */
int
sosendto(struct socket *so, struct mbuf *m)
{
	int ret;
	struct sockaddr_storage addr;

	DEBUG_CALL("sosendto");
	DEBUG_ARG("so = %p", so);
	DEBUG_ARG("m = %p", m);

	addr = so->fhost.ss;
	DEBUG_CALL(" sendto()ing)");
	sotranslate_out(so, &addr);

	/* Don't care what port we get */
	ret = sendto(so->s, m->m_data, m->m_len, 0,
		     (struct sockaddr *)&addr, sizeof(addr));
	if (ret < 0)
		return -1;

	/*
	 * Kill the socket if there's no reply in 4 minutes,
	 * but only if it's an expirable socket
	 */
	if (so->so_expire)
		so->so_expire = curtime + SO_EXPIRE;
	so->so_state &= SS_PERSISTENT_MASK;
	so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */
	return 0;
}
示例#2
0
int udp_output2_(struct socket *so, struct mbuf *m,
                 const SockAddress*  saddr, 
                 const SockAddress*  daddr,
                 int iptos)
{
    register struct udpiphdr *ui;
    uint32_t  saddr_ip = sock_address_get_ip(saddr);
    uint32_t  daddr_ip = sock_address_get_ip(daddr);
    int       saddr_port = sock_address_get_port(saddr);
    int       daddr_port = sock_address_get_port(daddr);
    int error = 0;

    DEBUG_CALL("udp_output");
	DEBUG_ARG("so = %lx", (long)so);
	DEBUG_ARG("m = %lx", (long)m);
    DEBUG_ARG("saddr = %lx", (long) saddr_ip);
    DEBUG_ARG("daddr = %lx", (long) daddr_ip);

	/*
	 * Adjust for header
	 */
	m->m_data -= sizeof(struct udpiphdr);
	m->m_len += sizeof(struct udpiphdr);

	/*
	 * Fill in mbuf with extended UDP header
	 * and addresses and length put into network format.
	 */
	ui = mtod(m, struct udpiphdr *);
    memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr));
	ui->ui_x1 = 0;
	ui->ui_pr = IPPROTO_UDP;
	ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
	/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
    ui->ui_src   = ip_seth(saddr_ip);
    ui->ui_dst   = ip_seth(daddr_ip);
    ui->ui_sport = port_seth(saddr_port);
    ui->ui_dport = port_seth(daddr_port);
	ui->ui_ulen = ui->ui_len;

	/*
	 * Stuff checksum and output datagram.
	 */
	ui->ui_sum = 0;
	if (UDPCKSUM) {
	    if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
		ui->ui_sum = 0xffff;
	}
	((struct ip *)ui)->ip_len = m->m_len;

	((struct ip *)ui)->ip_ttl = IPDEFTTL;
	((struct ip *)ui)->ip_tos = iptos;

	STAT(udpstat.udps_opackets++);

	error = ip_output(so, m);

	return (error);
}
示例#3
0
文件: ip6_icmp.c 项目: RodgerNO1/qemu
/*
 * Process a received ICMPv6 message.
 */
void icmp6_input(struct mbuf *m)
{
    struct icmp6 *icmp;
    struct ip6 *ip = mtod(m, struct ip6 *);
    Slirp *slirp = m->slirp;
    int hlen = sizeof(struct ip6);

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

    if (ntohs(ip->ip_pl) < ICMP6_MINLEN) {
        goto end;
    }

    if (ip6_cksum(m)) {
        goto end;
    }

    m->m_len -= hlen;
    m->m_data += hlen;
    icmp = mtod(m, struct icmp6 *);
    m->m_len += hlen;
    m->m_data -= hlen;

    DEBUG_ARG("icmp6_type = %d", icmp->icmp6_type);
    switch (icmp->icmp6_type) {
    case ICMP6_ECHO_REQUEST:
        if (in6_equal_host(&ip->ip_dst)) {
            icmp6_send_echoreply(m, slirp, ip, icmp);
        } else {
            /* TODO */
            error_report("external icmpv6 not supported yet");
        }
        break;

    case ICMP6_NDP_RS:
    case ICMP6_NDP_RA:
    case ICMP6_NDP_NS:
    case ICMP6_NDP_NA:
    case ICMP6_NDP_REDIRECT:
        ndp_input(m, slirp, ip, icmp);
        break;

    case ICMP6_UNREACH:
    case ICMP6_TOOBIG:
    case ICMP6_TIMXCEED:
    case ICMP6_PARAMPROB:
    /* XXX? report error? close socket? */
    default:
        break;
    }

end:
    m_free(m);
}
示例#4
0
文件: sbuf.c 项目: doniexun/MemCheck
/*
 * Try and write() to the socket, whatever doesn't get written
 * append to the buffer... for a host with a fast net connection,
 * this prevents an unnecessary copy of the data
 * (the socket is non-blocking, so we won't hang)
 */
void
sbappend(struct socket *so, struct mbuf *m)
{
	int ret = 0;

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

	/* Shouldn't happen, but...  e.g. foreign host closes connection */
	if (m->m_len <= 0) {
		m_free(m);
		return;
	}

	/*
	 * If there is urgent data, call sosendoob
	 * if not all was sent, sowrite will take care of the rest
	 * (The rest of this function is just an optimisation)
	 */
	if (so->so_urgc) {
		sbappendsb(&so->so_rcv, m);
		m_free(m);
		sosendoob(so);
		return;
	}

	/*
	 * We only write if there's nothing in the buffer,
	 * ottherwise it'll arrive out of order, and hence corrupt
	 */
	if (!so->so_rcv.sb_cc)
	   ret = send(so->s, m->m_data, m->m_len, 0);

	if (ret <= 0) {
		/*
		 * Nothing was written
		 * It's possible that the socket has closed, but
		 * we don't need to check because if it has closed,
		 * it will be detected in the normal way by soread()
		 */
		sbappendsb(&so->so_rcv, m);
	} else if (ret != m->m_len) {
		/*
		 * Something was written, but not everything..
		 * sbappendsb the rest
		 */
		m->m_len -= ret;
		m->m_data += ret;
		sbappendsb(&so->so_rcv, m);
	} /* else */
	/* Whatever happened, we free the mbuf */
	m_free(m);
}
示例#5
0
文件: socket.c 项目: 0-14N/NDroid
/*
 * XXX This should really be tcp_listen
 */
struct socket *
solisten(u_int port, u_int32_t laddr, u_int lport, int flags)
{
	SockAddress  addr;
	uint32_t     addr_ip;
	struct socket *so;
	int s;

	DEBUG_CALL("solisten");
	DEBUG_ARG("port = %d", port);
	DEBUG_ARG("laddr = %x", laddr);
	DEBUG_ARG("lport = %d", lport);
	DEBUG_ARG("flags = %x", flags);

	if ((so = socreate()) == NULL) {
	  /* free(so);      Not sofree() ??? free(NULL) == NOP */
	  return NULL;
	}

	/* Don't tcp_attach... we don't need so_snd nor so_rcv */
	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
		free(so);
		return NULL;
	}
	insque(so,&tcb);

	/*
	 * SS_FACCEPTONCE sockets must time out.
	 */
	if (flags & SS_FACCEPTONCE)
	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;

	so->so_state      = (SS_FACCEPTCONN|flags);
	so->so_laddr_port = lport; /* Kept in host format */
    so->so_laddr_ip   = laddr; /* Ditto */
    so->so_haddr_port = port;

    s = socket_loopback_server( port, SOCKET_STREAM );
    if (s < 0)
        return NULL;

    socket_get_address(s, &addr);

	so->so_faddr_port = sock_address_get_port(&addr);

    addr_ip = (uint32_t) 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->s = s;
	return so;
}
示例#6
0
文件: udp.c 项目: doniexun/MemCheck
int udp_output2(struct socket *so, struct mbuf *m,
                struct sockaddr_in *saddr, struct sockaddr_in *daddr,
                int iptos)
{
	register struct udpiphdr *ui;
	int error = 0;

	DEBUG_CALL("udp_output");
	DEBUG_ARG("so = %lx", (long)so);
	DEBUG_ARG("m = %lx", (long)m);
	DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr);
	DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr);

	/*
	 * Adjust for header
	 */
	m->m_data -= sizeof(struct udpiphdr);
	m->m_len += sizeof(struct udpiphdr);

	/*
	 * Fill in mbuf with extended UDP header
	 * and addresses and length put into network format.
	 */
	ui = mtod(m, struct udpiphdr *);
	ui->ui_next = ui->ui_prev = 0;
	ui->ui_x1 = 0;
	ui->ui_pr = IPPROTO_UDP;
	ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */
	/* XXXXX Check for from-one-location sockets, or from-any-location sockets */
        ui->ui_src = saddr->sin_addr;
	ui->ui_dst = daddr->sin_addr;
	ui->ui_sport = saddr->sin_port;
	ui->ui_dport = daddr->sin_port;
	ui->ui_ulen = ui->ui_len;

	/*
	 * Stuff checksum and output datagram.
	 */
	ui->ui_sum = 0;
	if (UDPCKSUM) {
	    if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0)
		ui->ui_sum = 0xffff;
	}
	((struct ip *)ui)->ip_len = m->m_len;

	((struct ip *)ui)->ip_ttl = IPDEFTTL;
	((struct ip *)ui)->ip_tos = iptos;

	STAT(udpstat.udps_opackets++);

	error = ip_output(so, m);

	return (error);
}
示例#7
0
文件: socket.c 项目: djs55/qemu
/*
 * Send urgent data
 * There's a lot duplicated code here, but...
 */
int
sosendoob(struct socket *so)
{
	struct sbuf *sb = &so->so_rcv;
	char buff[2048]; /* XXX Shouldn't be sending more oob data than this */

	int n, len;

	DEBUG_CALL("sosendoob");
	DEBUG_ARG("so = %lx", (long)so);
	DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);

	if (so->so_urgc > 2048)
	   so->so_urgc = 2048; /* XXXX */

	if (sb->sb_rptr < sb->sb_wptr) {
		/* We can send it directly */
		n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
		so->so_urgc -= n;

		DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
	} else {
		/*
		 * Since there's no sendv or sendtov like writev,
		 * we must copy all data to a linear buffer then
		 * send it all
		 */
		len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
		if (len > so->so_urgc) len = so->so_urgc;
		memcpy(buff, sb->sb_rptr, len);
		so->so_urgc -= len;
		if (so->so_urgc) {
			n = sb->sb_wptr - sb->sb_data;
			if (n > so->so_urgc) n = so->so_urgc;
			memcpy((buff + len), sb->sb_data, n);
			so->so_urgc -= n;
			len += n;
		}
		n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
#ifdef DEBUG
		if (n != len)
		   DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
#endif
		DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
	}

	sb->sb_cc -= n;
	sb->sb_rptr += n;
	if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
		sb->sb_rptr -= sb->sb_datalen;

	return n;
}
示例#8
0
struct mbuf *
m_get(void)
{
	register struct mbuf *m;
	int flags = 0;

	DEBUG_CALL("m_get");

	if (m_freelist.m_next == &m_freelist) {
		m = (struct mbuf *)malloc(SLIRP_MSIZE);
		if (m == NULL) goto end_error;
		mbuf_alloced++;
		if (mbuf_alloced > MBUF_THRESH)
			flags = M_DOFREE;
		if (mbuf_alloced > mbuf_max)
			mbuf_max = mbuf_alloced;
	} else {
		m = m_freelist.m_next;
		remque(m);
	}

	
	insque(m,&m_usedlist);
	m->m_flags = (flags | M_USEDLIST);

	
	m->m_size = SLIRP_MSIZE - sizeof(struct m_hdr);
	m->m_data = m->m_dat;
	m->m_len = 0;
        m->m_nextpkt = NULL;
        m->m_prevpkt = NULL;
end_error:
	DEBUG_ARG("m = %lx", (long )m);
	return m;
}
示例#9
0
void
m_free(struct mbuf *m)
{

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

  if(m) {
	
	if (m->m_flags & M_USEDLIST)
	   remque(m);

	
	if (m->m_flags & M_EXT)
	   free(m->m_ext);

	if (m->m_flags & M_DOFREE) {
		free(m);
		mbuf_alloced--;
	} else if ((m->m_flags & M_FREELIST) == 0) {
		insque(m,&m_freelist);
		m->m_flags = M_FREELIST; 
	}
  } 
}
示例#10
0
文件: socket.c 项目: m000/panda
/*
 * Get urgent data
 *
 * When the socket is created, we set it SO_OOBINLINE,
 * so when OOB data arrives, we soread() it and everything
 * in the send buffer is sent as urgent data
 */
int
sorecvoob(struct socket *so)
{
	struct tcpcb *tp = sototcpcb(so);
	int ret;

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

	/*
	 * We take a guess at how much urgent data has arrived.
	 * In most situations, when urgent data arrives, the next
	 * read() should get all the urgent data.  This guess will
	 * be wrong however if more data arrives just after the
	 * urgent data, or the read() doesn't return all the
	 * urgent data.
	 */
	ret = soread(so);
	if (ret > 0) {
	    tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
	    tp->t_force = 1;
	    tcp_output(tp);
	    tp->t_force = 0;
	}

	return ret;
}
示例#11
0
void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN])
{
    const uint32_t broadcast_addr =
        ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;
    ArpTable *arptbl = &slirp->arp_table;
    int i;

    DEBUG_CALL("arp_table_add");
    DEBUG_ARG("ip = 0x%x", ip_addr);
    DEBUG_ARGS(" hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
                ethaddr[0], ethaddr[1], ethaddr[2],
                ethaddr[3], ethaddr[4], ethaddr[5]);

    if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
        /* Do not register broadcast addresses */
        return;
    }

    /* Search for an entry */
    for (i = 0; i < ARP_TABLE_SIZE; i++) {
        if (arptbl->table[i].ar_sip == ip_addr) {
            /* Update the entry */
            memcpy(arptbl->table[i].ar_sha, ethaddr, ETH_ALEN);
            return;
        }
    }

    /* No entry found, create a new one */
    arptbl->table[arptbl->next_victim].ar_sip = ip_addr;
    memcpy(arptbl->table[arptbl->next_victim].ar_sha,  ethaddr, ETH_ALEN);
    arptbl->next_victim = (arptbl->next_victim + 1) % ARP_TABLE_SIZE;
}
示例#12
0
void
m_free(struct mbuf *m)
{

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

  if(m) {
	/* Remove from m_usedlist */
	if (m->m_flags & M_USEDLIST)
	   remque(m);

	/* If it's M_EXT, free() it */
	if (m->m_flags & M_EXT)
	   free(m->m_ext);

	/*
	 * Either free() it or put it on the free list
	 */
	if (m->m_flags & M_DOFREE) {
		m->slirp->mbuf_alloced--;
		free(m);
	} else if ((m->m_flags & M_FREELIST) == 0) {
		insque(m,&m->slirp->m_freelist);
		m->m_flags = M_FREELIST; /* Clobber other flags */
	}
  } /* if(m) */
}
示例#13
0
文件: socket.c 项目: 0-14N/NDroid
size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
{
	int n, lss, total;
	struct sbuf *sb = &so->so_snd;
	int len = sb->sb_datalen - sb->sb_cc;
	int mss = so->so_tcpcb->t_maxseg;

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

	len = sb->sb_datalen - sb->sb_cc;

	if (len <= 0)
		return 0;

	iov[0].iov_base = sb->sb_wptr;
        iov[1].iov_base = NULL;
        iov[1].iov_len = 0;
	if (sb->sb_wptr < sb->sb_rptr) {
		iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
		/* Should never succeed, but... */
		if (iov[0].iov_len > len)
		   iov[0].iov_len = len;
		if (iov[0].iov_len > mss)
		   iov[0].iov_len -= iov[0].iov_len%mss;
		n = 1;
	} else {
		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
		/* Should never succeed, but... */
		if (iov[0].iov_len > len) iov[0].iov_len = len;
		len -= iov[0].iov_len;
		if (len) {
			iov[1].iov_base = sb->sb_data;
			iov[1].iov_len = sb->sb_rptr - sb->sb_data;
			if(iov[1].iov_len > len)
			   iov[1].iov_len = len;
			total = iov[0].iov_len + iov[1].iov_len;
			if (total > mss) {
				lss = total%mss;
				if (iov[1].iov_len > lss) {
					iov[1].iov_len -= lss;
					n = 2;
				} else {
					lss -= iov[1].iov_len;
					iov[0].iov_len -= lss;
					n = 1;
				}
			} else
				n = 2;
		} else {
			if (iov[0].iov_len > mss)
			   iov[0].iov_len -= iov[0].iov_len%mss;
			n = 1;
		}
	}
	if (np)
		*np = n;

	return iov[0].iov_len + (n - 1) * iov[1].iov_len;
}
示例#14
0
文件: mbuf.c 项目: Pradeo/Slirp
/*
 * Get an mbuf from the free list, if there are none
 * malloc one
 * 
 * Because fragmentation can occur if we alloc new mbufs and
 * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
 * which tells m_free to actually free() it
 */
struct mbuf *
m_get()
{
	register struct mbuf *m;
	int flags = 0;
	
	DEBUG_CALL("m_get");
	
	if (m_freelist.m_next == &m_freelist) {
		m = (struct mbuf *)malloc(msize);
		if (m == NULL) goto end_error;
		mbuf_alloced++;
		if (mbuf_alloced > mbuf_thresh)
			flags = M_DOFREE;
		if (mbuf_alloced > mbuf_max)
			mbuf_max = mbuf_alloced;
	} else {
		m = m_freelist.m_next;
		remque(m);
	}
	
	/* Insert it in the used list */
	insque(m,&m_usedlist);
	m->m_flags = (flags | M_USEDLIST);
	
	/* Initialise it */
	m->m_size = msize - sizeof(struct m_hdr);
	m->m_data = m->m_dat;
	m->m_len = 0;
	m->m_nextpkt = 0;
	m->m_prevpkt = 0;
end_error:
	DEBUG_ARG("m = %lx", (long )m);
	return m;
}
示例#15
0
文件: socket.c 项目: djs55/qemu
/*
 * Read from so's socket into sb_snd, updating all relevant sbuf fields
 * NOTE: This will only be called if it is select()ed for reading, so
 * a read() of 0 (or less) means it's disconnected
 */
int
soread(struct socket *so)
{
	int n, nn;
	struct sbuf *sb = &so->so_snd;
	struct iovec iov[2];

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

	/*
	 * No need to check if there's enough room to read.
	 * soread wouldn't have been called if there weren't
	 */
	sopreprbuf(so, iov, &n);

#ifdef HAVE_READV
	nn = readv(so->s, (struct iovec *)iov, n);
	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#else
	nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
#endif
	if (nn <= 0) {
		if (nn < 0 && (errno == EINTR || errno == EAGAIN))
			return 0;
		else {
			DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
			sofcantrcvmore(so);
			tcp_sockclosed(sototcpcb(so));
			return -1;
		}
	}

#ifndef HAVE_READV
	/*
	 * If there was no error, try and read the second time round
	 * We read again if n = 2 (ie, there's another part of the buffer)
	 * and we read as much as we could in the first read
	 * We don't test for <= 0 this time, because there legitimately
	 * might not be any more data (since the socket is non-blocking),
	 * a close will be detected on next iteration.
	 * A return of -1 wont (shouldn't) happen, since it didn't happen above
	 */
	if (n == 2 && nn == iov[0].iov_len) {
            int ret;
            ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
            if (ret > 0)
                nn += ret;
        }

	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
#endif

	/* Update fields */
	sb->sb_cc += nn;
	sb->sb_wptr += nn;
	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
		sb->sb_wptr -= sb->sb_datalen;
	return nn;
}
示例#16
0
bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
                      uint8_t out_ethaddr[ETH_ALEN])
{
    const uint32_t broadcast_addr =
        ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr;
    ArpTable *arptbl = &slirp->arp_table;
    int i;

    DEBUG_CALL("arp_table_search");
    DEBUG_ARG("ip = 0x%x", ip_addr);

    /* If broadcast address */
    if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
        /* return Ethernet broadcast address */
        memset(out_ethaddr, 0xff, ETH_ALEN);
        return 1;
    }

    for (i = 0; i < ARP_TABLE_SIZE; i++) {
        if (arptbl->table[i].ar_sip == ip_addr) {
            memcpy(out_ethaddr, arptbl->table[i].ar_sha,  ETH_ALEN);
            DEBUG_ARGS(" found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
                        out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
                        out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]);
            return 1;
        }
    }

    return 0;
}
示例#17
0
/*
 * Put an ip fragment on a reassembly chain.
 * Like insque, but pointers in middle of structure.
 */
void ip_enq(struct ipasfrag *p, struct ipasfrag *prev)
{
	DEBUG_CALL("ip_enq");
	DEBUG_ARG("prev = %lx", (long)prev);
	p->ipf_prev = (ipasfragp_32) prev;
	p->ipf_next = prev->ipf_next;
	((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p;
	prev->ipf_next = (ipasfragp_32) p;
}
示例#18
0
文件: socket.c 项目: djs55/qemu
/*
 * sendto() a socket
 */
int
sosendto(struct socket *so, struct mbuf *m)
{
	Slirp *slirp = so->slirp;
	int ret;
	struct sockaddr_in addr;

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

        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;

	DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));

	/* Don't care what port we get */
	ret = sendto(so->s, m->m_data, m->m_len, 0,
		     (struct sockaddr *)&addr, sizeof (struct sockaddr));
	if (ret < 0)
		return -1;

	/*
	 * Kill the socket if there's no reply in 4 minutes,
	 * but only if it's an expirable socket
	 */
	if (so->so_expire)
		so->so_expire = curtime + SO_EXPIRE;
	so->so_state &= SS_PERSISTENT_MASK;
	so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */
	return 0;
}
示例#19
0
/*
 * sendto() a socket
 */
int
sosendto(struct socket *so, struct mbuf *m)
{
	int ret;
	struct sockaddr_in addr;

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

        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;

	DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));

	/* Don't care what port we get */
	ret = sendto(so->s, m->m_data, m->m_len, 0,
		     (struct sockaddr *)&addr, sizeof (struct sockaddr));
	if (ret < 0)
		return -1;

	/*
	 * Kill the socket if there's no reply in 4 minutes,
	 * but only if it's an expirable socket
	 */
	if (so->so_expire)
		so->so_expire = curtime + SO_EXPIRE;
	so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
	return 0;
}
示例#20
0
文件: tcp_subr.c 项目: 8tab/qemu
/*
 * Send a single message to the TCP at address specified by
 * the given TCP/IP header.  If m == 0, then we make a copy
 * of the tcpiphdr at ti and send directly to the addressed host.
 * This is used to force keep alive messages out using the TCP
 * template for a connection tp->t_template.  If flags are given
 * then we send a message back to the TCP which originated the
 * segment ti, and discard the mbuf containing it and any other
 * attached mbufs.
 *
 * In any case the ack and sequence number of the transmitted
 * segment are as specified by the parameters.
 */
void
tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
            tcp_seq ack, tcp_seq seq, int flags, unsigned short af)
{
	register int tlen;
	int win = 0;

	DEBUG_CALL("tcp_respond");
	DEBUG_ARG("tp = %p", tp);
	DEBUG_ARG("ti = %p", ti);
	DEBUG_ARG("m = %p", m);
	DEBUG_ARG("ack = %u", ack);
	DEBUG_ARG("seq = %u", seq);
	DEBUG_ARG("flags = %x", flags);

	if (tp)
		win = sbspace(&tp->t_socket->so_rcv);
        if (m == NULL) {
		if (!tp || (m = m_get(tp->t_socket->slirp)) == NULL)
			return;
		tlen = 0;
		m->m_data += IF_MAXLINKHDR;
		*mtod(m, struct tcpiphdr *) = *ti;
		ti = mtod(m, struct tcpiphdr *);
		memset(&ti->ti, 0, sizeof(ti->ti));
		flags = TH_ACK;
	} else {
示例#21
0
文件: tcp_subr.cpp 项目: engur/WinUAE
/*
 * Send a single message to the TCP at address specified by
 * the given TCP/IP header.  If m == 0, then we make a copy
 * of the tcpiphdr at ti and send directly to the addressed host.
 * This is used to force keep alive messages out using the TCP
 * template for a connection tp->t_template.  If flags are given
 * then we send a message back to the TCP which originated the
 * segment ti, and discard the mbuf containing it and any other
 * attached mbufs.
 *
 * In any case the ack and sequence number of the transmitted
 * segment are as specified by the parameters.
 */
void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags)
{
	int tlen;
	int win = 0;

	DEBUG_CALL("tcp_respond");
	DEBUG_ARG("tp = %lx", (long)tp);
	DEBUG_ARG("ti = %lx", (long)ti);
	DEBUG_ARG("m = %lx", (long)m);
	DEBUG_ARG("ack = %u", ack);
	DEBUG_ARG("seq = %u", seq);
	DEBUG_ARG("flags = %x", flags);
	
	if (tp)
		win = sbspace(&tp->t_socket->so_rcv);
	if (m == 0) {
		if ((m = m_get()) == NULL)
			return;
#ifdef TCP_COMPAT_42
		tlen = 1;
#else
		tlen = 0;
#endif
		m->m_data += if_maxlinkhdr;
		*mtod(m, struct tcpiphdr *) = *ti;
		ti = mtod(m, struct tcpiphdr *);
		flags = TH_ACK;
	} else {
示例#22
0
void tcp_xmit_timer(struct tcpcb *tp, int rtt)
{
	register short delta;

	DEBUG_CALL("tcp_xmit_timer");
	DEBUG_ARG("tp = %lx", (long)tp);
	DEBUG_ARG("rtt = %d", rtt);
	
	tcpstat.tcps_rttupdated++;
	if (tp->t_srtt != 0) {
		/*
		 * srtt is stored as fixed point with 3 bits after the
		 * binary point (i.e., scaled by 8).  The following magic
		 * is equivalent to the smoothing algorithm in rfc793 with
		 * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed
		 * point).  Adjust rtt to origin 0.
		 */
		delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT);
		if ((tp->t_srtt += delta) <= 0)
			tp->t_srtt = 1;
		/*
		 * We accumulate a smoothed rtt variance (actually, a
		 * smoothed mean difference), then set the retransmit
		 * timer to smoothed rtt + 4 times the smoothed variance.
		 * rttvar is stored as fixed point with 2 bits after the
		 * binary point (scaled by 4).  The following is
		 * equivalent to rfc793 smoothing with an alpha of .75
		 * (rttvar = rttvar*3/4 + |delta| / 4).  This replaces
		 * rfc793's wired-in beta.
		 */
		if (delta < 0)
			delta = -delta;
		delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT);
		if ((tp->t_rttvar += delta) <= 0)
			tp->t_rttvar = 1;
	} else {
示例#23
0
文件: ip6_icmp.c 项目: RodgerNO1/qemu
/*
 * Send NDP Neighbor Solitication
 */
void ndp_send_ns(Slirp *slirp, struct in6_addr addr)
{
    DEBUG_CALL("ndp_send_ns");
#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600)
    char addrstr[INET6_ADDRSTRLEN];
    inet_ntop(AF_INET6, &addr, addrstr, INET6_ADDRSTRLEN);
    DEBUG_ARG("target = %s", addrstr);
#endif

    /* Build IPv6 packet */
    struct mbuf *t = m_get(slirp);
    struct ip6 *rip = mtod(t, struct ip6 *);
    rip->ip_src = slirp->vhost_addr6;
    rip->ip_dst = (struct in6_addr)SOLICITED_NODE_PREFIX;
    memcpy(&rip->ip_dst.s6_addr[13], &addr.s6_addr[13], 3);
    rip->ip_nh = IPPROTO_ICMPV6;
    rip->ip_pl = htons(ICMP6_NDP_NS_MINLEN + NDPOPT_LINKLAYER_LEN);
    t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl);

    /* Build ICMPv6 packet */
    t->m_data += sizeof(struct ip6);
    struct icmp6 *ricmp = mtod(t, struct icmp6 *);
    ricmp->icmp6_type = ICMP6_NDP_NS;
    ricmp->icmp6_code = 0;
    ricmp->icmp6_cksum = 0;

    /* NDP */
    ricmp->icmp6_nns.reserved = 0;
    ricmp->icmp6_nns.target = addr;

    /* Build NDP option */
    t->m_data += ICMP6_NDP_NS_MINLEN;
    struct ndpopt *opt = mtod(t, struct ndpopt *);
    opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE;
    opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8;
    in6_compute_ethaddr(slirp->vhost_addr6, opt->ndpopt_linklayer);

    /* ICMPv6 Checksum */
    t->m_data -= ICMP6_NDP_NA_MINLEN;
    t->m_data -= sizeof(struct ip6);
    ricmp->icmp6_cksum = ip6_cksum(t);

    ip6_output(NULL, t, 1);
}
示例#24
0
文件: socket.c 项目: djs55/qemu
int soreadbuf(struct socket *so, const char *buf, int size)
{
    int n, nn, copy = size;
	struct sbuf *sb = &so->so_snd;
	struct iovec iov[2];

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

	/*
	 * No need to check if there's enough room to read.
	 * soread wouldn't have been called if there weren't
	 */
	if (sopreprbuf(so, iov, &n) < size)
        goto err;

    nn = MIN(iov[0].iov_len, copy);
    memcpy(iov[0].iov_base, buf, nn);

    copy -= nn;
    buf += nn;

    if (copy == 0)
        goto done;

    memcpy(iov[1].iov_base, buf, copy);

done:
    /* Update fields */
	sb->sb_cc += size;
	sb->sb_wptr += size;
	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
		sb->sb_wptr -= sb->sb_datalen;
    return size;
err:

    sofcantrcvmore(so);
    tcp_sockclosed(sototcpcb(so));
    fprintf(stderr, "soreadbuf buffer to small");
    return -1;
}
示例#25
0
bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr,
                      uint8_t out_ethaddr[ETH_ALEN])
{
    NdpTable *ndp_table = &slirp->ndp_table;
    int i;

    DEBUG_CALL("ndp_table_search");
#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600)
    char addrstr[INET6_ADDRSTRLEN];
    inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
    DEBUG_ARG("ip = %s", addrstr);
#endif

    assert(!IN6_IS_ADDR_UNSPECIFIED(&ip_addr));

    /* Multicast address: fec0::abcd:efgh/8 -> 33:33:ab:cd:ef:gh */
    if (IN6_IS_ADDR_MULTICAST(&ip_addr)) {
        out_ethaddr[0] = 0x33; out_ethaddr[1] = 0x33;
        out_ethaddr[2] = ip_addr.s6_addr[12];
        out_ethaddr[3] = ip_addr.s6_addr[13];
        out_ethaddr[4] = ip_addr.s6_addr[14];
        out_ethaddr[5] = ip_addr.s6_addr[15];
        DEBUG_ARGS((dfd, " multicast addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
                    out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
                    out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));
        return 1;
    }

    for (i = 0; i < NDP_TABLE_SIZE; i++) {
        if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) {
            memcpy(out_ethaddr, ndp_table->table[i].eth_addr,  ETH_ALEN);
            DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
                        out_ethaddr[0], out_ethaddr[1], out_ethaddr[2],
                        out_ethaddr[3], out_ethaddr[4], out_ethaddr[5]));
            return 1;
        }
    }

    DEBUG_CALL(" ip not found in table");
    return 0;
}
示例#26
0
void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr,
                    uint8_t ethaddr[ETH_ALEN])
{
    NdpTable *ndp_table = &slirp->ndp_table;
    int i;

    DEBUG_CALL("ndp_table_add");
#if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600)
    char addrstr[INET6_ADDRSTRLEN];
    inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN);
    DEBUG_ARG("ip = %s", addrstr);
#endif
    DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n",
                ethaddr[0], ethaddr[1], ethaddr[2],
                ethaddr[3], ethaddr[4], ethaddr[5]));

    if (IN6_IS_ADDR_MULTICAST(&ip_addr) || IN6_IS_ADDR_UNSPECIFIED(&ip_addr)) {
        /* Do not register multicast or unspecified addresses */
        DEBUG_CALL(" abort: do not register multicast or unspecified address");
        return;
    }

    /* Search for an entry */
    for (i = 0; i < NDP_TABLE_SIZE; i++) {
        if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) {
            DEBUG_CALL(" already in table: update the entry");
            /* Update the entry */
            memcpy(ndp_table->table[i].eth_addr, ethaddr, ETH_ALEN);
            return;
        }
    }

    /* No entry found, create a new one */
    DEBUG_CALL(" create new entry");
    ndp_table->table[ndp_table->next_victim].ip_addr = ip_addr;
    memcpy(ndp_table->table[ndp_table->next_victim].eth_addr,
            ethaddr, ETH_ALEN);
    ndp_table->next_victim = (ndp_table->next_victim + 1) % NDP_TABLE_SIZE;
}
示例#27
0
文件: if.c 项目: ayourtch/slirp
/*
 * if_input - read() the tty, do "top level" processing (ie: check for any escapes),
 * and pass onto (*ttyp->if_input)
 * 
 * XXXXX Any zeros arriving by themselves are NOT placed into the arriving packet.
 */
#define INBUFF_SIZE 2048 /* XXX */
void if_input(struct ttys *ttyp)
{
	u_char if_inbuff[INBUFF_SIZE];
	int if_n;
	
	DEBUG_CALL("if_input");
	DEBUG_ARG("ttyp = %lx", (long)ttyp);
	
	if_n = read(ttyp->fd, (char *)if_inbuff, INBUFF_SIZE);
	
	DEBUG_MISC((dfd, " read %d bytes\n", if_n));
	
	if (if_n <= 0) {
		if (if_n == 0 || (errno != EINTR && errno != EAGAIN)) {
			if (ttyp->up)
			   link_up--;
			tty_detached(ttyp, 0);
		}
		return;
	}
	if (if_n == 1) {
		if (*if_inbuff == '0') {
			ttyp->ones = 0;
			if (++ttyp->zeros >= 5)
			   slirp_exit(0);
			return;
		}
		if (*if_inbuff == '1') {
			ttyp->zeros = 0;
			if (++ttyp->ones >= 5)
			   tty_detached(ttyp, 0);
			return;
		}
	}
	ttyp->ones = ttyp->zeros = 0;
	
	(*ttyp->if_input)(ttyp, if_inbuff, if_n);
}
示例#28
0
struct mbuf *
dtom(void *dat)
{
	struct mbuf *m;

	DEBUG_CALL("dtom");
	DEBUG_ARG("dat = %lx", (long )dat);

	
	for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) {
	  if (m->m_flags & M_EXT) {
	    if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
	      return m;
	  } else {
	    if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
	      return m;
	  }
	}

	DEBUG_ERROR((dfd, "dtom failed"));

	return (struct mbuf *)0;
}
示例#29
0
/*
 * Given a pointer into an mbuf, return the mbuf
 * XXX This is a kludge, I should eliminate the need for it
 * Fortunately, it's not used often
 */
struct mbuf *
dtom(Slirp *slirp, void *dat)
{
	struct mbuf *m;

	DEBUG_CALL("dtom");
	DEBUG_ARG("dat = %p", dat);

	/* bug corrected for M_EXT buffers */
	for (m = slirp->m_usedlist.m_next; m != &slirp->m_usedlist;
	     m = m->m_next) {
	  if (m->m_flags & M_EXT) {
	    if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) )
	      return m;
	  } else {
	    if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) )
	      return m;
	  }
	}

	DEBUG_ERROR((dfd, "dtom failed"));

	return (struct mbuf *)0;
}
示例#30
0
/*
 * Get an mbuf from the free list, if there are none
 * malloc one
 *
 * Because fragmentation can occur if we alloc new mbufs and
 * free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
 * which tells m_free to actually free() it
 */
struct mbuf *
m_get(Slirp *slirp)
{
	register struct mbuf *m;
	int flags = 0;

	DEBUG_CALL("m_get");

	if (slirp->m_freelist.m_next == &slirp->m_freelist) {
		m = (struct mbuf *)malloc(SLIRP_MSIZE);
		if (m == NULL) goto end_error;
		slirp->mbuf_alloced++;
		if (slirp->mbuf_alloced > MBUF_THRESH)
			flags = M_DOFREE;
		m->slirp = slirp;
	} else {
		m = slirp->m_freelist.m_next;
		remque(m);
	}

	/* Insert it in the used list */
	insque(m,&slirp->m_usedlist);
	m->m_flags = (flags | M_USEDLIST);

	/* Initialise it */
	m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
	m->m_data = m->m_dat;
	m->m_len = 0;
        m->m_nextpkt = NULL;
        m->m_prevpkt = NULL;
        m->arp_requested = false;
        m->expiration_date = (uint64_t)-1;
end_error:
	DEBUG_ARG("m = %p", m);
	return m;
}