18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1982, 1986, 1988, 1990, 1993
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *	The Regents of the University of California.  All rights reserved.
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Redistribution and use in source and binary forms, with or without
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * modification, are permitted provided that the following conditions
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * are met:
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    documentation and/or other materials provided with the distribution.
135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 3. Neither the name of the University nor the names of its contributors
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    may be used to endorse or promote products derived from this software
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *    without specific prior written permission.
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SUCH DAMAGE.
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *	@(#)tcp_subr.c	8.1 (Berkeley) 6/10/93
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Changes and additions relating to SLiRP
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1995 Danny Gasparovski.
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Please read the file COPYRIGHT for the
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * terms and conditions of the copyright.
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <slirp.h>
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* patchable/settable parameters for tcp */
445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Don't do rfc1323 performance enhancements */
455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TCP_DO_RFC1323 0
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Tcp initialization
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_init(void)
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcp_iss = 1;		/* wrong */
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcb.so_next = tcb.so_prev = &tcb;
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Create template to be used to send tcp packets on a connection.
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Call after host entry created, fills
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in a skeletal tcp/ip header, minimizing the amount of work
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * necessary when the connection is used.
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* struct tcpiphdr * */
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_template(struct tcpcb *tp)
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so = tp->t_socket;
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register struct tcpiphdr *n = &tp->t_template;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_mbuf = NULL;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_x1 = 0;
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_pr = IPPROTO_TCP;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	n->ti_src = so->so_faddr;
755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	n->ti_dst = so->so_laddr;
765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	n->ti_sport = so->so_fport;
775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	n->ti_dport = so->so_lport;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_seq = 0;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_ack = 0;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_x2 = 0;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_off = 5;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_flags = 0;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_win = 0;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_sum = 0;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	n->ti_urp = 0;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Send a single message to the TCP at address specified by
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the given TCP/IP header.  If m == 0, then we make a copy
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of the tcpiphdr at ti and send directly to the addressed host.
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This is used to force keep alive messages out using the TCP
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * template for a connection tp->t_template.  If flags are given
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then we send a message back to the TCP which originated the
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * segment ti, and discard the mbuf containing it and any other
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * attached mbufs.
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * In any case the ack and sequence number of the transmitted
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * segment are as specified by the parameters.
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner            tcp_seq ack, tcp_seq seq, int flags)
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register int tlen;
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int win = 0;
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_respond");
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("tp = %lx", (long)tp);
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("ti = %lx", (long)ti);
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("m = %lx", (long)m);
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("ack = %u", ack);
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("seq = %u", seq);
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("flags = %x", flags);
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (tp)
1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		win = sbspace(&tp->t_socket->so_rcv);
1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        if (m == NULL) {
1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		if ((m = m_get()) == NULL)
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef TCP_COMPAT_42
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tlen = 1;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tlen = 0;
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		m->m_data += IF_MAXLINKHDR;
1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		*mtod(m, struct tcpiphdr *) = *ti;
1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		ti = mtod(m, struct tcpiphdr *);
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		flags = TH_ACK;
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * ti points into m so the next line is just making
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * the mbuf point to ti
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		m->m_data = (caddr_t)ti;
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		m->m_len = sizeof (struct tcpiphdr);
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tlen = 0;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t);
1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		xchg(ti->ti_dport, ti->ti_sport, u_int16_t);
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#undef xchg
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tlen += sizeof (struct tcpiphdr);
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	m->m_len = tlen;
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        ti->ti_mbuf = NULL;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_x1 = 0;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_seq = htonl(seq);
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_ack = htonl(ack);
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_x2 = 0;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_off = sizeof (struct tcphdr) >> 2;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_flags = flags;
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (tp)
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		ti->ti_win = htons((u_int16_t) (win >> tp->rcv_scale));
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	else
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		ti->ti_win = htons((u_int16_t)win);
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_urp = 0;
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_sum = 0;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	ti->ti_sum = cksum(m, tlen);
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	((struct ip *)ti)->ip_len = tlen;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if(flags & TH_RST)
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  ((struct ip *)ti)->ip_ttl = MAXTTL;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	else
1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	  ((struct ip *)ti)->ip_ttl = IPDEFTTL;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	(void) ip_output((struct socket *)0, m);
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Create a new TCP control block, making an
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * empty reassembly queue and hooking it to the argument
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * protocol control block.
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct tcpcb *
1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_newtcpcb(struct socket *so)
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register struct tcpcb *tp;
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp = (struct tcpcb *)malloc(sizeof(*tp));
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (tp == NULL)
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return ((struct tcpcb *)0);
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	memset((char *) tp, 0, sizeof(struct tcpcb));
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	tp->t_maxseg = TCP_MSS;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_socket = so;
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * reasonable initial retransmit time.
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_srtt = TCPTV_SRTTBASE;
2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	tp->t_rttvar = TCPTV_SRTTDFLT << 2;
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_rttmin = TCPTV_MIN;
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	TCPT_RANGESET(tp->t_rxtcur,
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    TCPTV_MIN, TCPTV_REXMTMAX);
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_state = TCPS_CLOSED;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_tcpcb = tp;
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return (tp);
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Drop a TCP connection, reporting
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the specified error.  If connection is synchronized,
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then send a RST to peer.
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct tcpcb *tcp_drop(struct tcpcb *tp, int err)
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* tcp_drop(tp, errno)
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register struct tcpcb *tp;
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int errno;
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_drop");
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("tp = %lx", (long)tp);
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("errno = %d", errno);
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (TCPS_HAVERCVDSYN(tp->t_state)) {
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_state = TCPS_CLOSED;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		(void) tcp_output(tp);
2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		STAT(tcpstat.tcps_drops++);
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else
2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		STAT(tcpstat.tcps_conndrops++);
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	if (errno == ETIMEDOUT && tp->t_softerror)
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *		errno = tp->t_softerror;
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	so->so_error = errno; */
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return (tcp_close(tp));
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Close a TCP control block:
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *	discard all space held by the tcp
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *	discard internet protocol block
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *	wake up any sleepers
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct tcpcb *
2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_close(struct tcpcb *tp)
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	register struct tcpiphdr *t;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so = tp->t_socket;
2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	register struct mbuf *m;
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_close");
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("tp = %lx", (long )tp);
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* free the reassembly queue, if any */
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	t = tcpfrag_list_first(tp);
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	while (!tcpfrag_list_end(t, tp)) {
2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		t = tcpiphdr_next(t);
2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		m = tcpiphdr_prev(t)->ti_mbuf;
2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		remque(tcpiphdr2qlink(tcpiphdr_prev(t)));
2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		m_freem(m);
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* It's static */
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	if (tp->t_template)
2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *		(void) m_free(dtom(tp->t_template));
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	free(tp, M_PCB);  */
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	free(tp);
2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        so->so_tcpcb = NULL;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	soisfdisconnected(so);
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* clobber input socket cache if we're closing the cached connection */
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (so == tcp_last_so)
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tcp_last_so = &tcb;
2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	closesocket(so->s);
2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	sbfree(&so->so_rcv);
2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	sbfree(&so->so_snd);
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	sofree(so);
2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	STAT(tcpstat.tcps_closed++);
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return ((struct tcpcb *)0);
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef notdef
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttcp_drain()
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* XXX */
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * When a source quench is received, close congestion window
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to one segment.  We will gradually open it again as we proceed.
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttcp_quench(i, errno)
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int errno;
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct tcpcb *tp = intotcpcb(inp);
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (tp)
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->snd_cwnd = tp->t_maxseg;
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* notdef */
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TCP protocol interface to socket abstraction.
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * User issued close, and wish to trail through shutdown states:
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * if never received SYN, just forget it.  If got a SYN from peer,
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * If already got a FIN from peer, then almost done; go to LAST_ACK
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * state.  In all other cases, have already sent FIN to peer (e.g.
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * after PRU_SHUTDOWN), and just have to play tedious game waiting
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * for peer to send FIN or not respond to keep-alives, etc.
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We can let the user exit from the close as soon as the FIN is acked.
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_sockclosed(struct tcpcb *tp)
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_sockclosed");
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("tp = %lx", (long)tp);
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	switch (tp->t_state) {
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPS_CLOSED:
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPS_LISTEN:
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPS_SYN_SENT:
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_state = TCPS_CLOSED;
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp = tcp_close(tp);
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPS_SYN_RECEIVED:
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPS_ESTABLISHED:
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_state = TCPS_FIN_WAIT_1;
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case TCPS_CLOSE_WAIT:
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tp->t_state = TCPS_LAST_ACK;
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		break;
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	soisfdisconnecting(tp->t_socket); */
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		soisfdisconnected(tp->t_socket);
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (tp)
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tcp_output(tp);
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Connect to a host on the Internet
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Called by tcp_input
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Only do a connect, the tcp fields will be set in tcp_input
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * return 0 if there's a result of the connect,
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * else return -1 means we're still connecting
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The return value is almost always -1 since the socket is
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * nonblocking.  Connect returns after the SYN is sent, and does
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * not wait for ACK+SYN.
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint tcp_fconnect(struct socket *so)
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  int ret=0;
3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  DEBUG_CALL("tcp_fconnect");
3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  DEBUG_ARG("so = %lx", (long )so);
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner  if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) {
3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    int opt, s=so->s;
3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    struct sockaddr_in addr;
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    fd_nonblock(s);
3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    opt = 1;
3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    opt = 1;
3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr.sin_family = AF_INET;
3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* It's an alias */
3895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      switch(ntohl(so->so_faddr.s_addr) & 0xff) {
3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case CTL_DNS:
3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	addr.sin_addr = dns_addr;
3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	break;
3935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      case CTL_ALIAS:
3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      default:
3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	addr.sin_addr = loopback_addr;
3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	break;
3975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      }
3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    } else
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      addr.sin_addr = so->so_faddr;
4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    addr.sin_port = so->so_fport;
4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		"addr.sin_addr.s_addr=%.16s\n",
4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /* We don't care what port we get */
4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    /*
4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * If it's not in progress, it failed, so we just return 0,
4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     * without clearing SS_NOFDREF
4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner     */
4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    soisfconnecting(so);
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  }
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project  return(ret);
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Accept the socket and connect to the local-host
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * We have a problem. The correct thing to do would be
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to first connect to the local-host, and only if the
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * connection is accepted, then do an accept() here.
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * But, a) we need to know who's trying to connect
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to the socket to be able to SYN the local-host, and
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * b) we are already connected to the foreign host by
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the time it gets to accept(), so... We simply accept
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * here and SYN the local-host.
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_connect(struct socket *inso)
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct socket *so;
4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sockaddr_in addr;
4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	socklen_t addrlen = sizeof(struct sockaddr_in);
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct tcpcb *tp;
4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	int s, opt;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_connect");
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("inso = %lx", (long)inso);
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * If it's an SS_ACCEPTONCE socket, no need to socreate()
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * another socket, just use the accept() socket.
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (inso->so_state & SS_FACCEPTONCE) {
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* FACCEPTONCE already have a tcpcb */
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so = inso;
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	} else {
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if ((so = socreate()) == NULL) {
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			/* If it failed, get rid of the pending connection */
4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return;
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (tcp_attach(so) < 0) {
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			free(so); /* NOT sofree */
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return;
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		so->so_laddr = inso->so_laddr;
4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		so->so_lport = inso->so_lport;
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	(void) tcp_mss(sototcpcb(so), 0);
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		tcp_close(sototcpcb(so)); /* This will sofree() as well */
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return;
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	fd_nonblock(s);
4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	opt = 1;
4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	opt = 1;
4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	opt = 1;
4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	so->so_fport = addr.sin_port;
4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	so->so_faddr = addr.sin_addr;
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Translate connections from localhost to the real hostname */
4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   so->so_faddr = alias_addr;
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Close the accept() socket, set right state */
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if (inso->so_state & SS_FACCEPTONCE) {
4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		closesocket(so->s); /* If we only accept once, close the accept() socket */
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					   /* if it's not FACCEPTONCE, it's already NOFDREF */
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->s = s;
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	so->so_iptos = tcp_tos(so);
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp = sototcpcb(so);
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcp_template(tp);
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/* Compute window scaling to request.  */
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *		(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *		tp->request_r_scale++;
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*	soisconnecting(so); */ /* NOFDREF used instead */
5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	STAT(tcpstat.tcps_connattempt++);
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_state = TCPS_SYN_SENT;
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tp->iss = tcp_iss;
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcp_iss += TCP_ISSINCR/2;
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcp_sendseqinit(tp);
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	tcp_output(tp);
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Attach a TCPCB to a socket.
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
5175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_attach(struct socket *so)
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	   return -1;
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	insque(so, &tcb);
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 0;
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Set the socket's type of service field
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const struct tos_t tcptos[] = {
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 20, IPTOS_THROUGHPUT, 0},	/* ftp data */
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {21, 21, IPTOS_LOWDELAY,  EMU_FTP},	/* ftp control */
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 23, IPTOS_LOWDELAY, 0},	/* telnet */
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 80, IPTOS_THROUGHPUT, 0},	/* WWW */
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT},	/* rlogin */
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT},	/* shell */
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 544, IPTOS_LOWDELAY, EMU_KSH},		/* kshell */
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 543, IPTOS_LOWDELAY, 0},	/* klogin */
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 6667, IPTOS_THROUGHPUT, EMU_IRC},	/* IRC */
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 6668, IPTOS_THROUGHPUT, EMU_IRC},	/* IRC undernet */
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO }, /* RealAudio control */
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 113, IPTOS_LOWDELAY, EMU_IDENT }, /* identd protocol */
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  {0, 0, 0, 0}
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_QEMU
5475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic
5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct emu_t *tcpemu = NULL;
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return TOS according to the above table
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectu_int8_t
5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_tos(struct socket *so)
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int i = 0;
5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct emu_t *emup;
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	while(tcptos[i].tos) {
5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		    (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			so->so_emu = tcptos[i].emu;
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return tcptos[i].tos;
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		i++;
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	/* Nope, lets see if there's a user-added one */
5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	for (emup = tcpemu; emup; emup = emup->next) {
5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) ||
5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		    (emup->lport && (ntohs(so->so_lport) == emup->lport))) {
5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so->so_emu = emup->emu;
5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			return emup->tos;
5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		}
5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	}
5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	return 0;
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint do_echo = -1;
5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Emulate programs that try and connect to us
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This includes ftp (the data connection is
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * initiated by the server) and IRC (DCC CHAT and
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * DCC SEND) for now
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * NOTE: It's possible to crash SLiRP by sending it
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * unstandard strings to emulate... if this is a problem,
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * more checks are needed here
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Assumes the whole command came in one packet
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * XXX Some ftp clients will have their TOS set to
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * LOWDELAY and so Nagel will kick in.  Because of this,
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * we'll get the first letter, followed by the rest, so
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * we simply scan for ORT instead of PORT...
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * DCC doesn't have this problem because there's other stuff
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * in the packet before the DCC command.
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return 1 if the mbuf m is still valid and should be
6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * sbappend()ed
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * NOTE: if you return 0 you MUST m_free() the mbuf!
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_emu(struct socket *so, struct mbuf *m)
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	u_int n1, n2, n3, n4, n5, n6;
6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        char buff[257];
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	u_int32_t laddr;
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	u_int lport;
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	char *bptr;
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_emu");
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long)so);
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("m = %lx", (long)m);
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	switch(so->so_emu) {
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		int x, i;
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 case EMU_IDENT:
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Identification protocol as per rfc-1413
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		{
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			struct socket *tmpso;
6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			struct sockaddr_in addr;
6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			socklen_t addrlen = sizeof(struct sockaddr_in);
6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			struct sbuf *so_rcv = &so->so_rcv;
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			so_rcv->sb_wptr += m->m_len;
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			so_rcv->sb_rptr += m->m_len;
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			m->m_data[m->m_len] = 0; /* NULL terminate */
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					HTONS(n1);
6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					HTONS(n2);
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					/* n2 is the one on our host */
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						    tmpso->so_lport == n2 &&
6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						    tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						    tmpso->so_fport == n1) {
6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner							if (getsockname(tmpso->s,
6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner								(struct sockaddr *)&addr, &addrlen) == 0)
6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner							   n2 = ntohs(addr.sin_port);
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project							break;
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project						}
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					}
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				}
6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                so_rcv->sb_cc = snprintf(so_rcv->sb_data,
6585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                                         so_rcv->sb_datalen,
6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                                         "%d,%d\r\n", n1, n2);
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				so_rcv->sb_rptr = so_rcv->sb_data;
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			}
6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			m_free(m);
6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			return 0;
6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		}
6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 case EMU_RLOGIN:
6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		/*
6705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * Rlogin emulation
6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * First we accumulate all the initial option negotiation,
6725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * then fork_exec() rlogin according to the  options
6735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 */
6745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		{
6755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			int i, i2, n;
6765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			char *ptr;
6775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			char args[100];
6785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			char term[100];
6795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			struct sbuf *so_snd = &so->so_snd;
6805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			struct sbuf *so_rcv = &so->so_rcv;
6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/* First check if they have a priveladged port, or too much data has arrived */
6835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
6845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			    (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
6855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				so_snd->sb_wptr += 18;
6875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				so_snd->sb_cc += 18;
6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tcp_sockclosed(sototcpcb(so));
6895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				m_free(m);
6905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				return 0;
6915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			}
6925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/* Append the current data */
6945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
6955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_rcv->sb_wptr += m->m_len;
6965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_rcv->sb_rptr += m->m_len;
6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			m_free(m);
6985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
6995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/*
7005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * Check if we have all the initial options,
7015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * and build argument list to rlogin while we're here
7025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 */
7035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			n = 0;
7045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			ptr = so_rcv->sb_data;
7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			args[0] = 0;
7065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			term[0] = 0;
7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			while (ptr < so_rcv->sb_wptr) {
7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				if (*ptr++ == 0) {
7095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					n++;
7105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					if (n == 2) {
7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						sprintf(args, "rlogin -l %s %s",
7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner							ptr, inet_ntoa(so->so_faddr));
7135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					} else if (n == 3) {
7145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						i2 = so_rcv->sb_wptr - ptr;
7155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						for (i = 0; i < i2; i++) {
7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner							if (ptr[i] == '/') {
7175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner								ptr[i] = 0;
7185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef HAVE_SETENV
7195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner								sprintf(term, "%s", ptr);
7205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
7215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner								sprintf(term, "TERM=%s", ptr);
7225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
7235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner								ptr[i] = '/';
7245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner								break;
7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner							}
7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						}
7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					}
7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				}
7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			}
7305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (n != 4)
7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			   return 0;
7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/* We have it, set our term variable and fork_exec() */
7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef HAVE_SETENV
7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			setenv("TERM", term, 1);
7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else
7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			putenv(term);
7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			fork_exec(so, args, 2);
7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			term[0] = 0;
7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so->so_emu = 0;
7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/* And finally, send the client a 0 character */
7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_snd->sb_wptr[0] = 0;
7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_snd->sb_wptr++;
7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_snd->sb_cc++;
7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			return 0;
7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		}
7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 case EMU_RSH:
7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		/*
7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * rsh emulation
7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * First we accumulate all the initial option negotiation,
7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * then rsh_exec() rsh according to the  options
7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 */
7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		{
7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			int  n;
7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			char *ptr;
7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			char *user;
7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			char *args;
7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			struct sbuf *so_snd = &so->so_snd;
7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			struct sbuf *so_rcv = &so->so_rcv;
7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/* First check if they have a priveladged port, or too much data has arrived */
7675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			    (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				so_snd->sb_wptr += 18;
7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				so_snd->sb_cc += 18;
7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tcp_sockclosed(sototcpcb(so));
7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				m_free(m);
7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				return 0;
7755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			}
7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/* Append the current data */
7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_rcv->sb_wptr += m->m_len;
7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_rcv->sb_rptr += m->m_len;
7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			m_free(m);
7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/*
7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * Check if we have all the initial options,
7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * and build argument list to rlogin while we're here
7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 */
7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			n = 0;
7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			ptr = so_rcv->sb_data;
7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			user="";
7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			args="";
7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (so->extra==NULL) {
7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				struct socket *ns;
7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				struct tcpcb* tp;
7945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				int port=atoi(ptr);
7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				if (port <= 0) return 0;
7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (port > 1023 || port < 512) {
7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  so_snd->sb_wptr += 18;
7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  so_snd->sb_cc += 18;
8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  tcp_sockclosed(sototcpcb(so));
8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  return 0;
8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				if ((ns=socreate()) == NULL)
8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  return 0;
8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				if (tcp_attach(ns)<0) {
8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  free(ns);
8075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  return 0;
8085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				}
8095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				ns->so_laddr=so->so_laddr;
8115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				ns->so_lport=htons(port);
8125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				(void) tcp_mss(sototcpcb(ns), 0);
8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				ns->so_faddr=so->so_faddr;
8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */
8175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				if (ns->so_faddr.s_addr == 0 ||
8195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					ns->so_faddr.s_addr == loopback_addr.s_addr)
8205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  ns->so_faddr = alias_addr;
8215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				ns->so_iptos = tcp_tos(ns);
8235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tp = sototcpcb(ns);
8245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tcp_template(tp);
8265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				/* Compute window scaling to request.  */
8285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				/*	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				 *		(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
8305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				 *		tp->request_r_scale++;
8315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				 */
8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                /*soisfconnecting(ns);*/
8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				STAT(tcpstat.tcps_connattempt++);
8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tp->t_state = TCPS_SYN_SENT;
8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tp->iss = tcp_iss;
8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tcp_iss += TCP_ISSINCR/2;
8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tcp_sendseqinit(tp);
8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				tcp_output(tp);
8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				so->extra=ns;
8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			}
8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			while (ptr < so_rcv->sb_wptr) {
8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner              if (*ptr++ == 0) {
8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                n++;
8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                if (n == 2) {
8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  user=ptr;
8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                } else if (n == 3) {
8515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                  args=ptr;
8525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                }
8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner              }
8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			}
8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (n != 4)
8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner              return 0;
8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			rsh_exec(so,so->extra, user, inet_ntoa(so->so_faddr), args);
8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so->so_emu = 0;
8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so->extra=NULL;
8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/* And finally, send the client a 0 character */
8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_snd->sb_wptr[0] = 0;
8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_snd->sb_wptr++;
8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			so_snd->sb_cc++;
8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return 0;
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 case EMU_CTL:
8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		{
8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			int num;
8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			struct sbuf *so_snd = &so->so_snd;
8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			struct sbuf *so_rcv = &so->so_rcv;
8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/*
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * If there is binary data here, we save it in so->so_m
8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 */
8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (!so->so_m) {
8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			  int rxlen;
8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			  char *rxdata;
8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			  rxdata=mtod(m, char *);
8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			  for (rxlen=m->m_len; rxlen; rxlen--) {
8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			    if (*rxdata++ & 0x80) {
8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			      so->so_m = m;
8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			      return 0;
8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			    }
8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			  }
8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			} /* if(so->so_m==NULL) */
8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/*
8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * Append the line
8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 */
8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			sbappendsb(so_rcv, m);
8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/* To avoid going over the edge of the buffer, we reset it */
8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (so_snd->sb_cc == 0)
8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			   so_snd->sb_wptr = so_snd->sb_rptr = so_snd->sb_data;
9005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			/*
9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * A bit of a hack:
9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * If the first packet we get here is 1 byte long, then it
9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * was done in telnet character mode, therefore we must echo
9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * the characters as they come.  Otherwise, we echo nothing,
9065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * because in linemode, the line is already echoed
9075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 * XXX two or more control connections won't work
9085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			 */
9095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (do_echo == -1) {
9105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				if (m->m_len == 1) do_echo = 1;
9115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				else do_echo = 0;
9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			}
9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (do_echo) {
9145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			  sbappendsb(so_snd, m);
9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			  m_free(m);
9165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			  tcp_output(sototcpcb(so)); /* XXX */
9175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			} else
9185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			  m_free(m);
9195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			num = 0;
9215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			while (num < so->so_rcv.sb_cc) {
9225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				if (*(so->so_rcv.sb_rptr + num) == '\n' ||
9235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				    *(so->so_rcv.sb_rptr + num) == '\r') {
9245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					int n;
9255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
9265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					*(so_rcv->sb_rptr + num) = 0;
9275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					if (ctl_password && !ctl_password_ok) {
9285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						/* Need a password */
9295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						if (sscanf(so_rcv->sb_rptr, "pass %256s", buff) == 1) {
9305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner							if (strcmp(buff, ctl_password) == 0) {
9315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner								ctl_password_ok = 1;
9325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner								n = sprintf(so_snd->sb_wptr,
9335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner									    "Password OK.\r\n");
9345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner								goto do_prompt;
9355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner							}
9365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						}
9375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						n = sprintf(so_snd->sb_wptr,
9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					 "Error: Password required, log on with \"pass PASSWORD\"\r\n");
9395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						goto do_prompt;
9405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					}
9415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					cfg_quitting = 0;
9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					n = do_config(so_rcv->sb_rptr, so, PRN_SPRINTF);
9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					if (!cfg_quitting) {
9445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						/* Register the printed data */
9455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerdo_prompt:
9465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						so_snd->sb_cc += n;
9475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						so_snd->sb_wptr += n;
9485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						/* Add prompt */
9495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						n = sprintf(so_snd->sb_wptr, "Slirp> ");
9505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						so_snd->sb_cc += n;
9515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						so_snd->sb_wptr += n;
9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					}
9535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					/* Drop so_rcv data */
9545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					so_rcv->sb_cc = 0;
9555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					so_rcv->sb_wptr = so_rcv->sb_rptr = so_rcv->sb_data;
9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					tcp_output(sototcpcb(so)); /* Send the reply */
9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				}
9585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				num++;
9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			}
9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			return 0;
9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		}
9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case EMU_FTP: /* ftp */
9645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                *(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			/*
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * Need to emulate the PORT command
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 */
9695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				   &n1, &n2, &n3, &n4, &n5, &n6, buff);
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (x < 6)
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   return 1;
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
9755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			lport = htons((n5 << 8) | (n6));
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   return 1;
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			n6 = ntohs(so->so_fport);
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n5 = (n6 >> 8) & 0xff;
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n6 &= 0xff;
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			laddr = ntohl(so->so_faddr.s_addr);
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n1 = ((laddr >> 24) & 0xff);
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n2 = ((laddr >> 16) & 0xff);
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n3 = ((laddr >> 8)  & 0xff);
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n4 =  (laddr & 0xff);
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			m->m_len = bptr - m->m_data; /* Adjust length */
9935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,
9945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             "ORT %d,%d,%d,%d,%d,%d\r\n%s",
9955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             n1, n2, n3, n4, n5, n6, x==7?buff:"");
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return 1;
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) {
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			/*
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 * Need to emulate the PASV response
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 */
10015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				   &n1, &n2, &n3, &n4, &n5, &n6, buff);
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (x < 6)
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   return 1;
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			lport = htons((n5 << 8) | (n6));
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   return 1;
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			n6 = ntohs(so->so_fport);
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n5 = (n6 >> 8) & 0xff;
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n6 &= 0xff;
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			laddr = ntohl(so->so_faddr.s_addr);
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n1 = ((laddr >> 24) & 0xff);
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n2 = ((laddr >> 16) & 0xff);
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n3 = ((laddr >> 8)  & 0xff);
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			n4 =  (laddr & 0xff);
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			m->m_len = bptr - m->m_data; /* Adjust length */
10255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,
10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
10275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             n1, n2, n3, n4, n5, n6, x==7?buff:"");
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			return 1;
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return 1;
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 case EMU_KSH:
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * The kshell (Kerberos rsh) and shell services both pass
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * a local port port number to carry signals to the server
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * and stderr to the client.  It is passed at the beginning
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * of the connection as a NUL-terminated decimal ASCII string.
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_emu = 0;
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		for (lport = 0, i = 0; i < m->m_len-1; ++i) {
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			if (m->m_data[i] < '0' || m->m_data[i] > '9')
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				return 1;       /* invalid number */
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			lport *= 10;
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			lport += m->m_data[i] - '0';
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		    (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                    m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d",
10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                        ntohs(so->so_fport)) + 1;
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return 1;
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 case EMU_IRC:
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Need to emulate DCC CHAT, DCC SEND and DCC MOVE
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		*(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 return 1;
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* The %256s is for the broken mIRC */
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				return 1;
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			m->m_len = bptr - m->m_data; /* Adjust length */
10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        m->m_len += snprintf(bptr, m->m_hdr.mh_size,
10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             "DCC CHAT chat %lu %u%c\n",
10705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             (unsigned long)ntohl(so->so_faddr.s_addr),
10715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             ntohs(so->so_fport), 1);
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
10735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				return 1;
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			m->m_len = bptr - m->m_data; /* Adjust length */
10775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        m->m_len += snprintf(bptr, m->m_hdr.mh_size,
10785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             "DCC SEND %s %lu %u %u%c\n", buff,
10795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             (unsigned long)ntohl(so->so_faddr.s_addr),
10805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             ntohs(so->so_fport), n1, 1);
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
10825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				return 1;
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			m->m_len = bptr - m->m_data; /* Adjust length */
10865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                        m->m_len += snprintf(bptr, m->m_hdr.mh_size,
10875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             "DCC MOVE %s %lu %u %u%c\n", buff,
10885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             (unsigned long)ntohl(so->so_faddr.s_addr),
10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                                             ntohs(so->so_fport), n1, 1);
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return 1;
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 case EMU_REALAUDIO:
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                /*
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * RealAudio emulation - JP. We must try to parse the incoming
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * data and try to find the two characters that contain the
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * port number. Then we redirect an udp port and replace the
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * number with the real port we got.
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * The 1.0 beta versions of the player are not supported
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * any more.
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * A typical packet for player version 1.0 (release version):
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * 0000:50 4E 41 00 05
11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....�..g�l�c..P
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Now the port number 0x1BD7 is found at offset 0x04 of the
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Now the port number 0x1BD7 is found at offset 0x04 of the
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * second packet. This time we received five bytes first and
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * then the rest. You never know how many bytes you get.
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * A typical packet for player version 2.0 (beta):
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........�.
11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .gux�c..Win2.0.0
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * 0040:65 2E 72 61 79 53 00 00 06 36 42                e.rayS...6B
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Port number 0x1BC1 is found at offset 0x0d.
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 *
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * This is just a horrible switch statement. Variable ra tells
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * us where we're going.
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		bptr = m->m_data;
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		while (bptr < m->m_data + m->m_len) {
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			u_short p;
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			static int ra = 0;
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			char ra_tbl[4];
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			ra_tbl[0] = 0x50;
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			ra_tbl[1] = 0x4e;
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			ra_tbl[2] = 0x41;
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			ra_tbl[3] = 0;
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			switch (ra) {
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 case 0:
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 case 2:
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 case 3:
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				if (*bptr++ != ra_tbl[ra]) {
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					ra = 0;
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					continue;
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				}
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				break;
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 case 1:
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				/*
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 * We may get 0x50 several times, ignore them
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 */
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				if (*bptr == 0x50) {
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					ra = 1;
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					bptr++;
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					continue;
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				} else if (*bptr++ != ra_tbl[ra]) {
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					ra = 0;
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					continue;
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				}
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				break;
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 case 4:
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				/*
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 * skip version number
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 */
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				bptr++;
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				break;
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 case 5:
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				/*
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 * The difference between versions 1.0 and
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 * 2.0 is here. For future versions of
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 * the player this may need to be modified.
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 */
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				if (*(bptr + 1) == 0x02)
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				   bptr += 8;
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				else
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				   bptr += 4;
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				break;
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 case 6:
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				/* This is the field containing the port
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 * number that RA-player is listening to.
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 */
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				lport = (((u_char*)bptr)[0] << 8)
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				+ ((u_char *)bptr)[1];
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				if (lport < 6970)
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				   lport += 256;   /* don't know why */
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				if (lport < 6970 || lport > 7170)
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				   return 1;       /* failed */
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				/* try to get udp port between 6970 - 7170 */
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				for (p = 6970; p < 7071; p++) {
11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					if (udp_listen( htons(p),
11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						       so->so_laddr.s_addr,
11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						       htons(lport),
12005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner						       SS_FACCEPTONCE)) {
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project						break;
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					}
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				}
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				if (p == 7071)
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				   p = 0;
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				*(u_char *)bptr++ = (p >> 8) & 0xff;
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				*(u_char *)bptr++ = p & 0xff;
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				ra = 0;
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				return 1;   /* port redirected, we're done */
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				break;
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			 default:
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				ra = 0;
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			}
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			ra++;
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		}
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return 1;
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 default:
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* Ooops, not emulated, won't call tcp_emu again */
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		so->so_emu = 0;
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return 1;
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Do misc. config of SLiRP while its running.
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Return 0 if this connections is to be closed, 1 otherwise,
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * return 2 if this is a command-line connection
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertcp_ctl(struct socket *so)
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct sbuf *sb = &so->so_snd;
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int command;
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project 	struct ex_list *ex_ptr;
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	int do_pty;
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        //	struct socket *tmpso;
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_CALL("tcp_ctl");
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	DEBUG_ARG("so = %lx", (long )so);
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	/*
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 * Check if they're authorised
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 */
12475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	if (ctl_addr.s_addr && (ctl_addr.s_addr == -1 || (so->so_laddr.s_addr != ctl_addr.s_addr))) {
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_cc = sprintf(sb->sb_wptr,"Error: Permission denied.\r\n");
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		sb->sb_wptr += sb->sb_cc;
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		return 0;
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
12535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	command = (ntohl(so->so_faddr.s_addr) & 0xff);
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	switch(command) {
12565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	default: /* Check for exec's */
12575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		/*
12595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 * Check if it's pty_exec
12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 */
12615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			if (ex_ptr->ex_fport == so->so_fport &&
12635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			    command == ex_ptr->ex_addr) {
12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				if (ex_ptr->ex_pty == 3) {
12655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					so->s = -1;
12665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					so->extra = (void *)ex_ptr->ex_exec;
12675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner					return 1;
12685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				}
12695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				do_pty = ex_ptr->ex_pty;
12705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner				goto do_exec;
12715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			}
12725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		}
12735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/*
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 * Nothing bound..
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		 */
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		/* tcp_fconnect(so); */
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		/* FALLTHROUGH */
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	case CTL_ALIAS:
12815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner          sb->sb_cc = snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),
12825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner                               "Error: No application configured.\r\n");
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  sb->sb_wptr += sb->sb_cc;
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  return(0);
12855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	do_exec:
12875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
12885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		return(fork_exec(so, ex_ptr->ex_exec, do_pty));
12895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
12905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0
12915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	case CTL_CMD:
12925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
12935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	     if (tmpso->so_emu == EMU_CTL &&
12945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		 !(tmpso->so_tcpcb?
12955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		   (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK))
12965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner		   :0)) {
12975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	       /* Ooops, control connection already active */
12985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	       sb->sb_cc = sprintf(sb->sb_wptr,"Sorry, already connected.\r\n");
12995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	       sb->sb_wptr += sb->sb_cc;
13005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	       return 0;
13015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	     }
13025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   }
13035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   so->so_emu = EMU_CTL;
13045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   ctl_password_ok = 0;
13055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> ");
13065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   sb->sb_wptr += sb->sb_cc;
13075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   do_echo=-1;
13085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	   return(2);
13095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	}
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1312