18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1995 Danny Gasparovski.
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Please read the file COPYRIGHT for the
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * terms and conditions of the copyright.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h>
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ip_icmp.h"
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __sun__
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/filio.h>
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void sofcantrcvmore(struct socket *so);
165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void sofcantsendmore(struct socket *so);
175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectso_init()
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Nothing yet */
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket *
275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersolookup(struct socket *head, struct in_addr laddr, u_int lport,
285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         struct in_addr faddr, u_int fport)
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so;
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	for (so = head->so_next; so != head; so = so->so_next) {
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		if (so->so_lport == lport &&
345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		    so->so_laddr.s_addr == laddr.s_addr &&
355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		    so->so_faddr.s_addr == faddr.s_addr &&
365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		    so->so_fport == fport)
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   break;
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so == head)
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   return (struct socket *)NULL;
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return so;
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Create a new socket, initialise the fields
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * It is the responsibility of the caller to
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * insque() it into the correct linked-list
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket *
525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersocreate(void)
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  struct socket *so;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  so = (struct socket *)malloc(sizeof(struct socket));
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  if(so) {
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset(so, 0, sizeof(struct socket));
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    so->so_state = SS_NOFDREF;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    so->s = -1;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  }
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  return(so);
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * remque and free a socket, clobber cache
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofree(struct socket *so)
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  if (so->so_emu==EMU_RSH && so->extra) {
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sofree(so->extra);
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->extra=NULL;
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  }
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  if (so == tcp_last_so)
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcp_last_so = &tcb;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  else if (so == udp_last_so)
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    udp_last_so = &udb;
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  m_free(so->so_m);
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  if(so->so_next && so->so_prev)
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    remque(so);  /* crashes if so is not in a queue */
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  free(so);
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersize_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int n, lss, total;
915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_snd;
925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int len = sb->sb_datalen - sb->sb_cc;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int mss = so->so_tcpcb->t_maxseg;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_CALL("sopreprbuf");
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long )so);
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	len = sb->sb_datalen - sb->sb_cc;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (len <= 0)
1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		return 0;
1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	iov[0].iov_base = sb->sb_wptr;
1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        iov[1].iov_base = NULL;
1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        iov[1].iov_len = 0;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_wptr < sb->sb_rptr) {
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* Should never succeed, but... */
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > len)
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   iov[0].iov_len = len;
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > mss)
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   iov[0].iov_len -= iov[0].iov_len%mss;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n = 1;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* Should never succeed, but... */
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > len) iov[0].iov_len = len;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		len -= iov[0].iov_len;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (len) {
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			iov[1].iov_base = sb->sb_data;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			iov[1].iov_len = sb->sb_rptr - sb->sb_data;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if(iov[1].iov_len > len)
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   iov[1].iov_len = len;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			total = iov[0].iov_len + iov[1].iov_len;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (total > mss) {
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				lss = total%mss;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				if (iov[1].iov_len > lss) {
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					iov[1].iov_len -= lss;
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					n = 2;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				} else {
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					lss -= iov[1].iov_len;
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					iov[0].iov_len -= lss;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					n = 1;
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				}
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			} else
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				n = 2;
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else {
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (iov[0].iov_len > mss)
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   iov[0].iov_len -= iov[0].iov_len%mss;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n = 1;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (np)
1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		*np = n;
1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	return iov[0].iov_len + (n - 1) * iov[1].iov_len;
1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Read from so's socket into sb_snd, updating all relevant sbuf fields
1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NOTE: This will only be called if it is select()ed for reading, so
1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * a read() of 0 (or less) means it's disconnected
1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint
1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoread(struct socket *so)
1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int n, nn;
1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_snd;
1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct iovec iov[2];
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_CALL("soread");
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_ARG("so = %lx", (long )so);
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	/*
1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * No need to check if there's enough room to read.
1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * soread wouldn't have been called if there weren't
1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 */
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	sopreprbuf(so, iov, &n);
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_READV
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	nn = readv(so->s, (struct iovec *)iov, n);
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0);
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (nn <= 0) {
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (nn < 0 && (errno == EINTR || errno == EAGAIN))
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return 0;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		else {
1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			sofcantrcvmore(so);
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			tcp_sockclosed(sototcpcb(so));
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return -1;
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef HAVE_READV
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * If there was no error, try and read the second time round
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * We read again if n = 2 (ie, there's another part of the buffer)
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * and we read as much as we could in the first read
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * We don't test for <= 0 this time, because there legitimately
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * might not be any more data (since the socket is non-blocking),
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * a close will be detected on next iteration.
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * A return of -1 wont (shouldn't) happen, since it didn't happen above
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (n == 2 && nn == iov[0].iov_len) {
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int ret;
1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0);
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret > 0)
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nn += ret;
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Update fields */
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_cc += nn;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_wptr += nn;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_wptr -= sb->sb_datalen;
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return nn;
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint soreadbuf(struct socket *so, const char *buf, int size)
2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int n, nn, copy = size;
2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_snd;
2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct iovec iov[2];
2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_CALL("soreadbuf");
2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_ARG("so = %lx", (long )so);
2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	/*
2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * No need to check if there's enough room to read.
2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * soread wouldn't have been called if there weren't
2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 */
2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (sopreprbuf(so, iov, &n) < size)
2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto err;
2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    nn = MIN(iov[0].iov_len, copy);
2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memcpy(iov[0].iov_base, buf, nn);
2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    copy -= nn;
2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    buf += nn;
2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (copy == 0)
2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto done;
2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memcpy(iov[1].iov_base, buf, copy);
2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerdone:
2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Update fields */
2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	sb->sb_cc += size;
2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	sb->sb_wptr += size;
2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		sb->sb_wptr -= sb->sb_datalen;
2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return size;
2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnererr:
2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sofcantrcvmore(so);
2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcp_sockclosed(sototcpcb(so));
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fprintf(stderr, "soreadbuf buffer to small");
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -1;
2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Get urgent data
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * When the socket is created, we set it SO_OOBINLINE,
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * so when OOB data arrives, we soread() it and everything
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the send buffer is sent as urgent data
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersorecvoob(struct socket *so)
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct tcpcb *tp = sototcpcb(so);
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sorecvoob");
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * We take a guess at how much urgent data has arrived.
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * In most situations, when urgent data arrives, the next
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * read() should get all the urgent data.  This guess will
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * be wrong however if more data arrives just after the
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * urgent data, or the read() doesn't return all the
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * urgent data.
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	soread(so);
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_force = 1;
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcp_output(tp);
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_force = 0;
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Send urgent data
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * There's a lot duplicated code here, but...
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersosendoob(struct socket *so)
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_rcv;
2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int n, len;
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sosendoob");
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_urgc > 2048)
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_urgc = 2048; /* XXXX */
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_rptr < sb->sb_wptr) {
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* We can send it directly */
3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_urgc -= n;
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Since there's no sendv or sendtov like writev,
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * we must copy all data to a linear buffer then
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * send it all
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (len > so->so_urgc) len = so->so_urgc;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		memcpy(buff, sb->sb_rptr, len);
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_urgc -= len;
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (so->so_urgc) {
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n = sb->sb_wptr - sb->sb_data;
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (n > so->so_urgc) n = so->so_urgc;
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			memcpy((buff + len), sb->sb_data, n);
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			so->so_urgc -= n;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			len += n;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (n != len)
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_cc -= n;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_rptr += n;
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_rptr -= sb->sb_datalen;
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return n;
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Write data from so_rcv to so's socket,
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * updating all sbuf field as necessary
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersowrite(struct socket *so)
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int  n,nn;
3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_rcv;
3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int len = sb->sb_cc;
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct iovec iov[2];
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sowrite");
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_urgc) {
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sosendoob(so);
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (sb->sb_cc == 0)
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return 0;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * No need to check if there's something to write,
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * sowrite wouldn't have been called otherwise
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = sb->sb_cc;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	iov[0].iov_base = sb->sb_rptr;
3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        iov[1].iov_base = NULL;
3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        iov[1].iov_len = 0;
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_rptr < sb->sb_wptr) {
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* Should never succeed, but... */
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > len) iov[0].iov_len = len;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n = 1;
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > len) iov[0].iov_len = len;
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		len -= iov[0].iov_len;
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (len) {
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			iov[1].iov_base = sb->sb_data;
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			iov[1].iov_len = sb->sb_wptr - sb->sb_data;
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (iov[1].iov_len > len) iov[1].iov_len = len;
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n = 2;
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n = 1;
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Check if there's urgent data to send, and if so, send it */
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_READV
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	nn = writev(so->s, (const struct iovec *)iov, n);
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* This should never happen, but people tell me it does *shrug* */
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (nn < 0 && (errno == EAGAIN || errno == EINTR))
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return 0;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (nn <= 0) {
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			so->so_state, errno));
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sofcantsendmore(so);
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tcp_sockclosed(sototcpcb(so));
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return -1;
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef HAVE_READV
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (n == 2 && nn == iov[0].iov_len) {
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int ret;
4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret > 0)
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nn += ret;
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Update sbuf */
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_cc -= nn;
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_rptr += nn;
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_rptr -= sb->sb_datalen;
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * If in DRAIN mode, and there's no more data, set
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * it CANTSENDMORE
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sofcantsendmore(so);
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return nn;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * recvfrom() a UDP socket
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersorecvfrom(struct socket *so)
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sockaddr_in addr;
4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	socklen_t addrlen = sizeof(struct sockaddr_in);
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sorecvfrom");
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_type == IPPROTO_ICMP) {   /* This is a "ping" reply */
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  char buff[256];
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  int len;
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  len = recvfrom(so->s, buff, 256, 0,
4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 (struct sockaddr *)&addr, &addrlen);
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* XXX Check if reply is "correct"? */
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  if(len == -1 || len == 0) {
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    u_char code=ICMP_UNREACH_PORT;
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			errno,strerror(errno)));
4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  } else {
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    icmp_reflect(so->so_m);
4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            so->so_m = NULL; /* Don't m_free() it again! */
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  }
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* No need for this socket anymore, udp_detach it */
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  udp_detach(so);
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {                            	/* A "normal" UDP packet */
4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  struct mbuf *m;
4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner          int len;
4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner          unsigned long n;
4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner          int n;
4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  if (!(m = m_get())) return;
4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  m->m_data += IF_MAXLINKHDR;
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /*
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * XXX Shouldn't FIONREAD packets destined for port 53,
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * but I don't know the max packet size for DNS lookups
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   */
4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  len = M_FREEROOM(m);
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* if (so->so_fport != htons(53)) { */
4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  ioctlsocket(so->s, FIONREAD, &n);
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  if (n > len) {
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    n = (m->m_data - m->m_dat) + m->m_len + n + 1;
4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    m_inc(m, n);
4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    len = M_FREEROOM(m);
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  }
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* } */
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  m->m_len = recvfrom(so->s, m->m_data, len, 0,
5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			      (struct sockaddr *)&addr, &addrlen);
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		      m->m_len, errno,strerror(errno)));
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  if(m->m_len<0) {
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    u_char code=ICMP_UNREACH_PORT;
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    m_free(m);
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  } else {
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /*
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * Hack: domain name lookup will be used the most for UDP,
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * and since they'll only be used once there's no need
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * for the 4 minute (or whatever) timeout... So we time them
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * out much quicker (10 seconds  for now...)
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   */
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if (so->so_expire) {
5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	      if (so->so_fport == htons(53))
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_expire = curtime + SO_EXPIREFAST;
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	      else
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_expire = curtime + SO_EXPIRE;
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    /*		if (m->m_len == len) {
5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	     *			m_inc(m, MINCSIZE);
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     *			m->m_len = 0;
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     *		}
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     */
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    /*
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     * If this packet was destined for CTL_ADDR,
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     * make it look like that's where it came from, done by udp_output
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     */
5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    udp_output(so, m, &addr);
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  } /* rx error */
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} /* if ping packet */
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sendto() a socket
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersosendto(struct socket *so, struct mbuf *m)
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int ret;
5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sockaddr_in addr;
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sosendto");
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("m = %lx", (long)m);
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        addr.sin_family = AF_INET;
5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* It's an alias */
5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  switch(ntohl(so->so_faddr.s_addr) & 0xff) {
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  case CTL_DNS:
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    addr.sin_addr = dns_addr;
5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    break;
5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  case CTL_ALIAS:
5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  default:
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    addr.sin_addr = loopback_addr;
5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    break;
5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  }
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else
5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  addr.sin_addr = so->so_faddr;
5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	addr.sin_port = so->so_fport;
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	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)));
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Don't care what port we get */
5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	ret = sendto(so->s, m->m_data, m->m_len, 0,
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		     (struct sockaddr *)&addr, sizeof (struct sockaddr));
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (ret < 0)
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return -1;
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * Kill the socket if there's no reply in 4 minutes,
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * but only if it's an expirable socket
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_expire)
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_expire = curtime + SO_EXPIRE;
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 0;
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX This should really be tcp_listen
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket *
5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersolisten(u_int port, u_int32_t laddr, u_int lport, int flags)
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sockaddr_in addr;
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so;
5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int s, opt = 1;
6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	socklen_t addrlen = sizeof(addr);
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("solisten");
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("port = %d", port);
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("laddr = %x", laddr);
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("lport = %d", lport);
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("flags = %x", flags);
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so = socreate()) == NULL) {
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* free(so);      Not sofree() ??? free(NULL) == NOP */
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  return NULL;
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Don't tcp_attach... we don't need so_snd nor so_rcv */
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		free(so);
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return NULL;
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	insque(so,&tcb);
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * SS_FACCEPTONCE sockets must time out.
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (flags & SS_FACCEPTONCE)
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	so->so_state = (SS_FACCEPTCONN|flags);
6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	so->so_lport = lport; /* Kept in network format */
6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	so->so_laddr.s_addr = laddr; /* Ditto */
6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	addr.sin_family = AF_INET;
6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	addr.sin_addr.s_addr = INADDR_ANY;
6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	addr.sin_port = port;
6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) ||
6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) ||
6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) ||
6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    (listen(s,1) < 0)) {
6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		int tmperrno = errno; /* Don't clobber the real reason we failed */
6395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		close(s);
6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		sofree(so);
6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		/* Restore the real errno */
6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32
6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		WSASetLastError(tmperrno);
6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		errno = tmperrno;
6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		return NULL;
6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	}
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	getsockname(s,(struct sockaddr *)&addr,&addrlen);
6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	so->so_fport = addr.sin_port;
6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   so->so_faddr = alias_addr;
6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	else
6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   so->so_faddr = addr.sin_addr;
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->s = s;
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return so;
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Data is available in so_rcv
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Just write() the data to the socket
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX not yet...
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsorwakeup(so)
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so;
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	sowrite(so); */
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	FD_CLR(so->s,&writefds); */
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Data has been freed in so_snd
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We have room for a read() if we want to
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * For now, don't read, it'll be done in the main loop
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsowwakeup(so)
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so;
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Nothing, yet */
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Various session state calls
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Should be #define's
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The socket state stuff needs work, these often get call 2 or 3
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * times each when only 1 was needed
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfconnecting(struct socket *so)
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			  SS_FCANTSENDMORE|SS_FWDRAIN);
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfconnected(struct socket *so)
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofcantrcvmore(struct socket *so)
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_state & SS_NOFDREF) == 0) {
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		shutdown(so->s,0);
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if(global_writefds) {
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		  FD_CLR(so->s,global_writefds);
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state &= ~(SS_ISFCONNECTING);
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_state & SS_FCANTSENDMORE)
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	else
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_state |= SS_FCANTRCVMORE;
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofcantsendmore(struct socket *so)
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_state & SS_NOFDREF) == 0) {
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shutdown(so->s,1);           /* send FIN to fhost */
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (global_readfds) {
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                FD_CLR(so->s,global_readfds);
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (global_xfds) {
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                FD_CLR(so->s,global_xfds);
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state &= ~(SS_ISFCONNECTING);
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_state & SS_FCANTRCVMORE)
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_state = SS_NOFDREF; /* as above */
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	else
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_state |= SS_FCANTSENDMORE;
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfdisconnected(struct socket *so)
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	close(so->s); */
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	so->so_state = SS_ISFDISCONNECTED; */
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * XXX Do nothing ... ?
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set write drain mode
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set CANTSENDMORE once all data has been write()n
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofwdrain(struct socket *so)
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_rcv.sb_cc)
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_state |= SS_FWDRAIN;
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	else
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sofcantsendmore(so);
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
769