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
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define WANT_SYS_IOCTL_H
95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h"
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h>
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "ip_icmp.h"
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "main.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef __sun__
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <sys/filio.h>
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  SLIRP_COMPILATION 1
17cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/sockets.h"
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "proxy_common.h"
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void sofcantrcvmore(struct socket *so);
215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void sofcantsendmore(struct socket *so);
225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectso_init()
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Nothing yet */
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket *
325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersolookup(struct socket *head, uint32_t laddr, u_int lport,
335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         uint32_t faddr, u_int fport)
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so;
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	for (so = head->so_next; so != head; so = so->so_next) {
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (so->so_laddr_port == lport &&
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    so->so_laddr_ip   == laddr &&
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    so->so_faddr_ip   == faddr &&
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		    so->so_faddr_port == fport)
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   break;
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so == head)
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   return (struct socket *)NULL;
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return so;
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Create a new socket, initialise the fields
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * It is the responsibility of the caller to
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * insque() it into the correct linked-list
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket *
575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersocreate(void)
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  struct socket *so;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  so = (struct socket *)malloc(sizeof(struct socket));
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  if(so) {
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset(so, 0, sizeof(struct socket));
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    so->so_state = SS_NOFDREF;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    so->s = -1;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  }
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  return(so);
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * remque and free a socket, clobber cache
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofree(struct socket *so)
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  if (so->so_state & SS_PROXIFIED)
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    proxy_manager_del(so);
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  if (so->so_emu==EMU_RSH && so->extra) {
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sofree(so->extra);
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->extra=NULL;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  }
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  if (so == tcp_last_so)
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    tcp_last_so = &tcb;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  else if (so == udp_last_so)
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    udp_last_so = &udb;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  m_free(so->so_m);
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  if(so->so_next && so->so_prev)
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    remque(so);  /* crashes if so is not in a queue */
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  free(so);
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersize_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int n, lss, total;
995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_snd;
1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int len = sb->sb_datalen - sb->sb_cc;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int mss = so->so_tcpcb->t_maxseg;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_CALL("sopreprbuf");
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long )so);
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	len = sb->sb_datalen - sb->sb_cc;
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (len <= 0)
1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		return 0;
1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	iov[0].iov_base = sb->sb_wptr;
1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        iov[1].iov_base = NULL;
1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        iov[1].iov_len = 0;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_wptr < sb->sb_rptr) {
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		iov[0].iov_len = sb->sb_rptr - sb->sb_wptr;
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* Should never succeed, but... */
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > len)
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   iov[0].iov_len = len;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > mss)
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   iov[0].iov_len -= iov[0].iov_len%mss;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n = 1;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* Should never succeed, but... */
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > len) iov[0].iov_len = len;
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		len -= iov[0].iov_len;
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (len) {
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			iov[1].iov_base = sb->sb_data;
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			iov[1].iov_len = sb->sb_rptr - sb->sb_data;
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if(iov[1].iov_len > len)
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   iov[1].iov_len = len;
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			total = iov[0].iov_len + iov[1].iov_len;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (total > mss) {
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				lss = total%mss;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				if (iov[1].iov_len > lss) {
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					iov[1].iov_len -= lss;
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					n = 2;
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				} else {
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					lss -= iov[1].iov_len;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					iov[0].iov_len -= lss;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					n = 1;
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				}
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			} else
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				n = 2;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else {
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (iov[0].iov_len > mss)
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   iov[0].iov_len -= iov[0].iov_len%mss;
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n = 1;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (np)
1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		*np = n;
1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	return iov[0].iov_len + (n - 1) * iov[1].iov_len;
1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/*
1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Read from so's socket into sb_snd, updating all relevant sbuf fields
1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NOTE: This will only be called if it is select()ed for reading, so
1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * a read() of 0 (or less) means it's disconnected
1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */
1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint
1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoread(struct socket *so)
1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int n, nn;
1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_snd;
1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct iovec iov[2];
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_CALL("soread");
1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_ARG("so = %lx", (long )so);
1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	/*
1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * No need to check if there's enough room to read.
1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * soread wouldn't have been called if there weren't
1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 */
1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	sopreprbuf(so, iov, &n);
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_READV
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	nn = readv(so->s, (struct iovec *)iov, n);
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	nn = socket_recv(so->s, iov[0].iov_base, iov[0].iov_len);
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (nn <= 0) {
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (nn < 0 && (errno == EINTR || errno == EAGAIN))
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return 0;
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		else {
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,errno_str));
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			sofcantrcvmore(so);
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			tcp_sockclosed(sototcpcb(so));
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return -1;
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef HAVE_READV
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * If there was no error, try and read the second time round
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * We read again if n = 2 (ie, there's another part of the buffer)
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * and we read as much as we could in the first read
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * We don't test for <= 0 this time, because there legitimately
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * might not be any more data (since the socket is non-blocking),
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * a close will be detected on next iteration.
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * A return of -1 wont (shouldn't) happen, since it didn't happen above
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (n == 2 && nn == iov[0].iov_len) {
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int ret;
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ret = socket_recv(so->s, iov[1].iov_base, iov[1].iov_len);
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret > 0)
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nn += ret;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn));
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Update fields */
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_cc += nn;
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_wptr += nn;
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_wptr -= sb->sb_datalen;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return nn;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint soreadbuf(struct socket *so, const char *buf, int size)
2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int n, nn, copy = size;
2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_snd;
2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct iovec iov[2];
2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_CALL("soreadbuf");
2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	DEBUG_ARG("so = %lx", (long )so);
2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	/*
2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * No need to check if there's enough room to read.
2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 * soread wouldn't have been called if there weren't
2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 */
2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (sopreprbuf(so, iov, &n) < size)
2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto err;
2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    nn = MIN(iov[0].iov_len, copy);
2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memcpy(iov[0].iov_base, buf, nn);
2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    copy -= nn;
2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    buf += nn;
2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (copy == 0)
2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        goto done;
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    memcpy(iov[1].iov_base, buf, copy);
2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerdone:
2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* Update fields */
2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	sb->sb_cc += size;
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	sb->sb_wptr += size;
2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		sb->sb_wptr -= sb->sb_datalen;
2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return size;
2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnererr:
2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    sofcantrcvmore(so);
2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    tcp_sockclosed(sototcpcb(so));
2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fprintf(stderr, "soreadbuf buffer to small");
2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    return -1;
2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Get urgent data
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * When the socket is created, we set it SO_OOBINLINE,
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * so when OOB data arrives, we soread() it and everything
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the send buffer is sent as urgent data
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersorecvoob(struct socket *so)
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct tcpcb *tp = sototcpcb(so);
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sorecvoob");
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * We take a guess at how much urgent data has arrived.
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * In most situations, when urgent data arrives, the next
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * read() should get all the urgent data.  This guess will
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * be wrong however if more data arrives just after the
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * urgent data, or the read() doesn't return all the
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * urgent data.
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	soread(so);
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_force = 1;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcp_output(tp);
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_force = 0;
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Send urgent data
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * There's a lot duplicated code here, but...
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersosendoob(struct socket *so)
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_rcv;
3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	char buff[2048]; /* XXX Shouldn't be sending more oob data than this */
3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int n, len;
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sosendoob");
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc);
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_urgc > 2048)
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_urgc = 2048; /* XXXX */
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_rptr < sb->sb_wptr) {
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* We can send it directly */
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n = socket_send_oob(so->s, sb->sb_rptr, so->so_urgc); /* |MSG_DONTWAIT)); */
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_urgc -= n;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Since there's no sendv or sendtov like writev,
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * we must copy all data to a linear buffer then
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * send it all
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (len > so->so_urgc) len = so->so_urgc;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		memcpy(buff, sb->sb_rptr, len);
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_urgc -= len;
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (so->so_urgc) {
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n = sb->sb_wptr - sb->sb_data;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (n > so->so_urgc) n = so->so_urgc;
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			memcpy((buff + len), sb->sb_data, n);
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			so->so_urgc -= n;
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			len += n;
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n = socket_send_oob(so->s, buff, len); /* |MSG_DONTWAIT)); */
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef DEBUG
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (n != len)
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		   DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_cc -= n;
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_rptr += n;
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_rptr -= sb->sb_datalen;
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return n;
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Write data from so_rcv to so's socket,
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * updating all sbuf field as necessary
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersowrite(struct socket *so)
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int  n,nn;
3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_rcv;
3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int len = sb->sb_cc;
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct iovec iov[2];
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sowrite");
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_urgc) {
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sosendoob(so);
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (sb->sb_cc == 0)
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return 0;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * No need to check if there's something to write,
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * sowrite wouldn't have been called otherwise
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = sb->sb_cc;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	iov[0].iov_base = sb->sb_rptr;
3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        iov[1].iov_base = NULL;
3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        iov[1].iov_len = 0;
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_rptr < sb->sb_wptr) {
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		iov[0].iov_len = sb->sb_wptr - sb->sb_rptr;
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* Should never succeed, but... */
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > len) iov[0].iov_len = len;
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		n = 1;
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr;
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (iov[0].iov_len > len) iov[0].iov_len = len;
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		len -= iov[0].iov_len;
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (len) {
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			iov[1].iov_base = sb->sb_data;
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			iov[1].iov_len = sb->sb_wptr - sb->sb_data;
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (iov[1].iov_len > len) iov[1].iov_len = len;
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n = 2;
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n = 1;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Check if there's urgent data to send, and if so, send it */
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef HAVE_READV
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	nn = writev(so->s, (const struct iovec *)iov, n);
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	nn = socket_send(so->s, iov[0].iov_base, iov[0].iov_len);
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* This should never happen, but people tell me it does *shrug* */
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (nn < 0 && (errno == EAGAIN || errno == EINTR))
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return 0;
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (nn <= 0) {
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n",
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			so->so_state, errno));
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sofcantsendmore(so);
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tcp_sockclosed(sototcpcb(so));
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return -1;
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef HAVE_READV
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (n == 2 && nn == iov[0].iov_len) {
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int ret;
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            ret = socket_send(so->s, iov[1].iov_base, iov[1].iov_len);
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret > 0)
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                nn += ret;
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        DEBUG_MISC((dfd, "  ... wrote nn = %d bytes\n", nn));
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Update sbuf */
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_cc -= nn;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sb->sb_rptr += nn;
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen))
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_rptr -= sb->sb_datalen;
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * If in DRAIN mode, and there's no more data, set
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * it CANTSENDMORE
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0)
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sofcantsendmore(so);
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return nn;
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * recvfrom() a UDP socket
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersorecvfrom(struct socket *so)
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        SockAddress  addr;
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sorecvfrom");
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_type == IPPROTO_ICMP) {   /* This is a "ping" reply */
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  char buff[256];
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  int len;
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  len = socket_recvfrom(so->s, buff, 256, &addr);
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* XXX Check if reply is "correct"? */
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  if(len == -1 || len == 0) {
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    u_char code=ICMP_UNREACH_PORT;
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n",
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			errno,errno_str));
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str);
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  } else {
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    icmp_reflect(so->so_m);
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    so->so_m = 0; /* Don't mbuf_free() it again! */
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  }
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* No need for this socket anymore, udp_detach it */
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  udp_detach(so);
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {                            	/* A "normal" UDP packet */
4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  struct mbuf *m;
4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner          int len;
4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		  int n;
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  if (!(m = m_get())) return;
4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  m->m_data += IF_MAXLINKHDR;
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /*
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * XXX Shouldn't FIONREAD packets destined for port 53,
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * but I don't know the max packet size for DNS lookups
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   */
4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  len = M_FREEROOM(m);
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* if (so->so_fport != htons(53)) { */
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  n = socket_can_read(so->s);
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  if (n > len) {
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    n = (m->m_data - m->m_dat) + m->m_len + n + 1;
4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    m_inc(m, n);
5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    len = M_FREEROOM(m);
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  }
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* } */
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  m->m_len = socket_recvfrom(so->s, m->m_data, len, &addr);
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		      m->m_len, errno,errno_str));
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  if(m->m_len<0) {
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    u_char code=ICMP_UNREACH_PORT;
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST;
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET;
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    icmp_error(so->so_m, ICMP_UNREACH,code, 0,errno_str);
5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	    m_free(m);
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  } else {
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /*
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * Hack: domain name lookup will be used the most for UDP,
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * and since they'll only be used once there's no need
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * for the 4 minute (or whatever) timeout... So we time them
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   * out much quicker (10 seconds  for now...)
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   */
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    if (so->so_expire) {
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	      if (so->so_faddr_port == 53)
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_expire = curtime + SO_EXPIREFAST;
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	      else
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_expire = curtime + SO_EXPIRE;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    }
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    /*		if (m->m_len == len) {
5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	     *			m_inc(m, MINCSIZE);
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     *			m->m_len = 0;
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     *		}
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     */
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    /*
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     * If this packet was destined for CTL_ADDR,
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     * make it look like that's where it came from, done by udp_output
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	     */
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    udp_output_(so, m, &addr);
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  } /* rx error */
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} /* if ping packet */
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sendto() a socket
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersosendto(struct socket *so, struct mbuf *m)
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int ret;
5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    SockAddress   addr;
5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint32_t      addr_ip;
5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    uint16_t      addr_port;
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("sosendto");
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("m = %lx", (long)m);
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_faddr_ip & 0xffffff00) == special_addr_ip) {
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        /* It's an alias */
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      	int  low = so->so_faddr_ip & 0xff;
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if ( CTL_IS_DNS(low) )
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr_ip = dns_addr[low - CTL_DNS];
5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        else
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            addr_ip = loopback_addr_ip;
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    addr_ip = so->so_faddr_ip;
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	addr_port = so->so_faddr_port;
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5737339b55944e97077e4f74c4be34cd956ae44198brich cannings	/*
5747339b55944e97077e4f74c4be34cd956ae44198brich cannings	 * test for generic forwarding; this function replaces the arguments
5757339b55944e97077e4f74c4be34cd956ae44198brich cannings	 * only on success
5767339b55944e97077e4f74c4be34cd956ae44198brich cannings	 */
5777339b55944e97077e4f74c4be34cd956ae44198brich cannings	unsigned long faddr = addr_ip;
5787339b55944e97077e4f74c4be34cd956ae44198brich cannings        int fport = addr_port;
5797339b55944e97077e4f74c4be34cd956ae44198brich cannings
5807339b55944e97077e4f74c4be34cd956ae44198brich cannings	if (slirp_should_net_forward(faddr, fport, &faddr, &fport)) {
581d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings      time_t timestamp = time(NULL);
582d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings      slirp_drop_log(
5837339b55944e97077e4f74c4be34cd956ae44198brich cannings	       "Redirected UDP: src: 0x%08lx:0x%04x org dst: 0x%08lx:0x%04x "
584d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings	       "new dst: 0x%08lx:0x%04x %ld\n",
5857339b55944e97077e4f74c4be34cd956ae44198brich cannings	        so->so_laddr_ip, so->so_laddr_port,
5867339b55944e97077e4f74c4be34cd956ae44198brich cannings	        addr_ip, addr_port,
587d952f28e527175cc3df9ebd91e739e34df2194c9rich cannings	        faddr, fport, timestamp
5887339b55944e97077e4f74c4be34cd956ae44198brich cannings	    );
5897339b55944e97077e4f74c4be34cd956ae44198brich cannings	}
5907339b55944e97077e4f74c4be34cd956ae44198brich cannings	addr_ip = faddr;
5917339b55944e97077e4f74c4be34cd956ae44198brich cannings	addr_port = fport;
5927339b55944e97077e4f74c4be34cd956ae44198brich cannings
5937339b55944e97077e4f74c4be34cd956ae44198brich cannings
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sock_address_init_inet(&addr, addr_ip, addr_port);
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%08x\n", addr_port, addr_ip));
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Don't care what port we get */
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ret = socket_sendto(so->s, m->m_data, m->m_len,&addr);
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (ret < 0)
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return -1;
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * Kill the socket if there's no reply in 4 minutes,
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * but only if it's an expirable socket
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_expire)
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_expire = curtime + SO_EXPIRE;
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 0;
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX This should really be tcp_listen
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct socket *
6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersolisten(u_int port, u_int32_t laddr, u_int lport, int flags)
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	SockAddress  addr;
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	uint32_t     addr_ip;
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so;
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int s;
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("solisten");
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("port = %d", port);
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("laddr = %x", laddr);
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("lport = %d", lport);
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("flags = %x", flags);
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so = socreate()) == NULL) {
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  /* free(so);      Not sofree() ??? free(NULL) == NOP */
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  return NULL;
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Don't tcp_attach... we don't need so_snd nor so_rcv */
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) {
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		free(so);
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return NULL;
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	insque(so,&tcb);
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * SS_FACCEPTONCE sockets must time out.
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (flags & SS_FACCEPTONCE)
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2;
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state      = (SS_FACCEPTCONN|flags);
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_laddr_port = lport; /* Kept in host format */
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    so->so_laddr_ip   = laddr; /* Ditto */
6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    so->so_haddr_port = port;
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    s = socket_loopback_server( port, SOCKET_STREAM );
6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (s < 0)
6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return NULL;
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    socket_get_address(s, &addr);
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_faddr_port = sock_address_get_port(&addr);
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr_ip = (uint32_t) sock_address_get_ip(&addr);
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (addr_ip == 0 || addr_ip == loopback_addr_ip)
6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        so->so_faddr_ip = alias_addr_ip;
6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    else
6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        so->so_faddr_ip = addr_ip;
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->s = s;
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return so;
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsounlisten(u_int  port)
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct socket *so;
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (so = tcb.so_next; so != &tcb; so = so->so_next) {
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (so->so_haddr_port == port) {
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (so == &tcb) {
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sofcantrcvmore( so );
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sofcantsendmore( so );
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    close( so->s );
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    so->s = -1;
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sofree( so );
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Data is available in so_rcv
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Just write() the data to the socket
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX not yet...
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
7035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsorwakeup(so)
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so;
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	sowrite(so); */
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	FD_CLR(so->s,&writefds); */
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Data has been freed in so_snd
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We have room for a read() if we want to
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * For now, don't read, it'll be done in the main loop
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectsowwakeup(so)
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so;
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Nothing, yet */
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Various session state calls
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Should be #define's
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The socket state stuff needs work, these often get call 2 or 3
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * times each when only 1 was needed
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfconnecting(struct socket *so)
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE|
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			  SS_FCANTSENDMORE|SS_FWDRAIN);
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state |= SS_ISFCONNECTING; /* Clobber other states */
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfconnected(struct socket *so)
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF);
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state |= SS_ISFCONNECTED; /* Clobber other states */
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofcantrcvmore(struct socket *so)
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_state & SS_NOFDREF) == 0) {
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		shutdown(so->s,0);
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if(global_writefds) {
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		  FD_CLR(so->s,global_writefds);
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state &= ~(SS_ISFCONNECTING);
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_state & SS_FCANTSENDMORE)
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	else
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_state |= SS_FCANTRCVMORE;
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofcantsendmore(struct socket *so)
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_state & SS_NOFDREF) == 0) {
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shutdown(so->s,1);           /* send FIN to fhost */
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (global_readfds) {
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                FD_CLR(so->s,global_readfds);
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (global_xfds) {
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                FD_CLR(so->s,global_xfds);
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_state &= ~(SS_ISFCONNECTING);
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_state & SS_FCANTRCVMORE)
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_state = SS_NOFDREF; /* as above */
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	else
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   so->so_state |= SS_FCANTSENDMORE;
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersoisfdisconnected(struct socket *so)
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	close(so->s); */
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	so->so_state = SS_ISFDISCONNECTED; */
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * XXX Do nothing ... ?
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set write drain mode
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set CANTSENDMORE once all data has been write()n
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnersofwdrain(struct socket *so)
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so->so_rcv.sb_cc)
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_state |= SS_FWDRAIN;
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	else
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sofcantsendmore(so);
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
803