symbian-qemu-0.9.1-12/qemu-symbian-svp/slirp/tcp_subr.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  * Copyright (c) 1982, 1986, 1988, 1990, 1993
       
     3  *	The Regents of the University of California.  All rights reserved.
       
     4  *
       
     5  * Redistribution and use in source and binary forms, with or without
       
     6  * modification, are permitted provided that the following conditions
       
     7  * are met:
       
     8  * 1. Redistributions of source code must retain the above copyright
       
     9  *    notice, this list of conditions and the following disclaimer.
       
    10  * 2. Redistributions in binary form must reproduce the above copyright
       
    11  *    notice, this list of conditions and the following disclaimer in the
       
    12  *    documentation and/or other materials provided with the distribution.
       
    13  * 3. All advertising materials mentioning features or use of this software
       
    14  *    must display the following acknowledgement:
       
    15  *	This product includes software developed by the University of
       
    16  *	California, Berkeley and its contributors.
       
    17  * 4. Neither the name of the University nor the names of its contributors
       
    18  *    may be used to endorse or promote products derived from this software
       
    19  *    without specific prior written permission.
       
    20  *
       
    21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
       
    22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       
    24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
       
    25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
       
    26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
       
    27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       
    28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
       
    29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
       
    30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       
    31  * SUCH DAMAGE.
       
    32  *
       
    33  *	@(#)tcp_subr.c	8.1 (Berkeley) 6/10/93
       
    34  * tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp
       
    35  */
       
    36 
       
    37 /*
       
    38  * Changes and additions relating to SLiRP
       
    39  * Copyright (c) 1995 Danny Gasparovski.
       
    40  *
       
    41  * Please read the file COPYRIGHT for the
       
    42  * terms and conditions of the copyright.
       
    43  */
       
    44 
       
    45 #define WANT_SYS_IOCTL_H
       
    46 #include <slirp.h>
       
    47 
       
    48 /* patchable/settable parameters for tcp */
       
    49 /* Don't do rfc1323 performance enhancements */
       
    50 #define TCP_DO_RFC1323 0
       
    51 
       
    52 /*
       
    53  * Tcp initialization
       
    54  */
       
    55 void
       
    56 tcp_init()
       
    57 {
       
    58 	tcp_iss = 1;		/* wrong */
       
    59 	tcb.so_next = tcb.so_prev = &tcb;
       
    60 }
       
    61 
       
    62 /*
       
    63  * Create template to be used to send tcp packets on a connection.
       
    64  * Call after host entry created, fills
       
    65  * in a skeletal tcp/ip header, minimizing the amount of work
       
    66  * necessary when the connection is used.
       
    67  */
       
    68 /* struct tcpiphdr * */
       
    69 void
       
    70 tcp_template(tp)
       
    71 	struct tcpcb *tp;
       
    72 {
       
    73 	struct socket *so = tp->t_socket;
       
    74 	register struct tcpiphdr *n = &tp->t_template;
       
    75 
       
    76 	n->ti_next = n->ti_prev = 0;
       
    77 	n->ti_x1 = 0;
       
    78 	n->ti_pr = IPPROTO_TCP;
       
    79 	n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
       
    80 	n->ti_src = so->so_faddr;
       
    81 	n->ti_dst = so->so_laddr;
       
    82 	n->ti_sport = so->so_fport;
       
    83 	n->ti_dport = so->so_lport;
       
    84 
       
    85 	n->ti_seq = 0;
       
    86 	n->ti_ack = 0;
       
    87 	n->ti_x2 = 0;
       
    88 	n->ti_off = 5;
       
    89 	n->ti_flags = 0;
       
    90 	n->ti_win = 0;
       
    91 	n->ti_sum = 0;
       
    92 	n->ti_urp = 0;
       
    93 }
       
    94 
       
    95 /*
       
    96  * Send a single message to the TCP at address specified by
       
    97  * the given TCP/IP header.  If m == 0, then we make a copy
       
    98  * of the tcpiphdr at ti and send directly to the addressed host.
       
    99  * This is used to force keep alive messages out using the TCP
       
   100  * template for a connection tp->t_template.  If flags are given
       
   101  * then we send a message back to the TCP which originated the
       
   102  * segment ti, and discard the mbuf containing it and any other
       
   103  * attached mbufs.
       
   104  *
       
   105  * In any case the ack and sequence number of the transmitted
       
   106  * segment are as specified by the parameters.
       
   107  */
       
   108 void
       
   109 tcp_respond(tp, ti, m, ack, seq, flags)
       
   110 	struct tcpcb *tp;
       
   111 	register struct tcpiphdr *ti;
       
   112 	register struct mbuf *m;
       
   113 	tcp_seq ack, seq;
       
   114 	int flags;
       
   115 {
       
   116 	register int tlen;
       
   117 	int win = 0;
       
   118 
       
   119 	DEBUG_CALL("tcp_respond");
       
   120 	DEBUG_ARG("tp = %lx", (long)tp);
       
   121 	DEBUG_ARG("ti = %lx", (long)ti);
       
   122 	DEBUG_ARG("m = %lx", (long)m);
       
   123 	DEBUG_ARG("ack = %u", ack);
       
   124 	DEBUG_ARG("seq = %u", seq);
       
   125 	DEBUG_ARG("flags = %x", flags);
       
   126 
       
   127 	if (tp)
       
   128 		win = sbspace(&tp->t_socket->so_rcv);
       
   129 	if (m == 0) {
       
   130 		if ((m = m_get()) == NULL)
       
   131 			return;
       
   132 #ifdef TCP_COMPAT_42
       
   133 		tlen = 1;
       
   134 #else
       
   135 		tlen = 0;
       
   136 #endif
       
   137 		m->m_data += IF_MAXLINKHDR;
       
   138 		*mtod(m, struct tcpiphdr *) = *ti;
       
   139 		ti = mtod(m, struct tcpiphdr *);
       
   140 		flags = TH_ACK;
       
   141 	} else {
       
   142 		/*
       
   143 		 * ti points into m so the next line is just making
       
   144 		 * the mbuf point to ti
       
   145 		 */
       
   146 		m->m_data = (caddr_t)ti;
       
   147 
       
   148 		m->m_len = sizeof (struct tcpiphdr);
       
   149 		tlen = 0;
       
   150 #define xchg(a,b,type) { type t; t=a; a=b; b=t; }
       
   151 		xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_int32_t);
       
   152 		xchg(ti->ti_dport, ti->ti_sport, u_int16_t);
       
   153 #undef xchg
       
   154 	}
       
   155 	ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
       
   156 	tlen += sizeof (struct tcpiphdr);
       
   157 	m->m_len = tlen;
       
   158 
       
   159 	ti->ti_next = ti->ti_prev = 0;
       
   160 	ti->ti_x1 = 0;
       
   161 	ti->ti_seq = htonl(seq);
       
   162 	ti->ti_ack = htonl(ack);
       
   163 	ti->ti_x2 = 0;
       
   164 	ti->ti_off = sizeof (struct tcphdr) >> 2;
       
   165 	ti->ti_flags = flags;
       
   166 	if (tp)
       
   167 		ti->ti_win = htons((u_int16_t) (win >> tp->rcv_scale));
       
   168 	else
       
   169 		ti->ti_win = htons((u_int16_t)win);
       
   170 	ti->ti_urp = 0;
       
   171 	ti->ti_sum = 0;
       
   172 	ti->ti_sum = cksum(m, tlen);
       
   173 	((struct ip *)ti)->ip_len = tlen;
       
   174 
       
   175 	if(flags & TH_RST)
       
   176 	  ((struct ip *)ti)->ip_ttl = MAXTTL;
       
   177 	else
       
   178 	  ((struct ip *)ti)->ip_ttl = IPDEFTTL;
       
   179 
       
   180 	(void) ip_output((struct socket *)0, m);
       
   181 }
       
   182 
       
   183 /*
       
   184  * Create a new TCP control block, making an
       
   185  * empty reassembly queue and hooking it to the argument
       
   186  * protocol control block.
       
   187  */
       
   188 struct tcpcb *
       
   189 tcp_newtcpcb(so)
       
   190 	struct socket *so;
       
   191 {
       
   192 	register struct tcpcb *tp;
       
   193 
       
   194 	tp = (struct tcpcb *)malloc(sizeof(*tp));
       
   195 	if (tp == NULL)
       
   196 		return ((struct tcpcb *)0);
       
   197 
       
   198 	memset((char *) tp, 0, sizeof(struct tcpcb));
       
   199 	tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
       
   200 	tp->t_maxseg = TCP_MSS;
       
   201 
       
   202 	tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
       
   203 	tp->t_socket = so;
       
   204 
       
   205 	/*
       
   206 	 * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
       
   207 	 * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
       
   208 	 * reasonable initial retransmit time.
       
   209 	 */
       
   210 	tp->t_srtt = TCPTV_SRTTBASE;
       
   211 	tp->t_rttvar = TCPTV_SRTTDFLT << 2;
       
   212 	tp->t_rttmin = TCPTV_MIN;
       
   213 
       
   214 	TCPT_RANGESET(tp->t_rxtcur,
       
   215 	    ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
       
   216 	    TCPTV_MIN, TCPTV_REXMTMAX);
       
   217 
       
   218 	tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
       
   219 	tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
       
   220 	tp->t_state = TCPS_CLOSED;
       
   221 
       
   222 	so->so_tcpcb = tp;
       
   223 
       
   224 	return (tp);
       
   225 }
       
   226 
       
   227 /*
       
   228  * Drop a TCP connection, reporting
       
   229  * the specified error.  If connection is synchronized,
       
   230  * then send a RST to peer.
       
   231  */
       
   232 struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
       
   233 {
       
   234 /* tcp_drop(tp, errno)
       
   235 	register struct tcpcb *tp;
       
   236 	int errno;
       
   237 {
       
   238 */
       
   239 
       
   240 	DEBUG_CALL("tcp_drop");
       
   241 	DEBUG_ARG("tp = %lx", (long)tp);
       
   242 	DEBUG_ARG("errno = %d", errno);
       
   243 
       
   244 	if (TCPS_HAVERCVDSYN(tp->t_state)) {
       
   245 		tp->t_state = TCPS_CLOSED;
       
   246 		(void) tcp_output(tp);
       
   247 		STAT(tcpstat.tcps_drops++);
       
   248 	} else
       
   249 		STAT(tcpstat.tcps_conndrops++);
       
   250 /*	if (errno == ETIMEDOUT && tp->t_softerror)
       
   251  *		errno = tp->t_softerror;
       
   252  */
       
   253 /*	so->so_error = errno; */
       
   254 	return (tcp_close(tp));
       
   255 }
       
   256 
       
   257 /*
       
   258  * Close a TCP control block:
       
   259  *	discard all space held by the tcp
       
   260  *	discard internet protocol block
       
   261  *	wake up any sleepers
       
   262  */
       
   263 struct tcpcb *
       
   264 tcp_close(tp)
       
   265 	register struct tcpcb *tp;
       
   266 {
       
   267 	register struct tcpiphdr *t;
       
   268 	struct socket *so = tp->t_socket;
       
   269 	register struct mbuf *m;
       
   270 
       
   271 	DEBUG_CALL("tcp_close");
       
   272 	DEBUG_ARG("tp = %lx", (long )tp);
       
   273 
       
   274 	/* free the reassembly queue, if any */
       
   275 	t = (struct tcpiphdr *) tp->seg_next;
       
   276 	while (t != (struct tcpiphdr *)tp) {
       
   277 		t = (struct tcpiphdr *)t->ti_next;
       
   278 		m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)t->ti_prev);
       
   279 		remque_32((struct tcpiphdr *) t->ti_prev);
       
   280 		m_freem(m);
       
   281 	}
       
   282 	/* It's static */
       
   283 /*	if (tp->t_template)
       
   284  *		(void) m_free(dtom(tp->t_template));
       
   285  */
       
   286 /*	free(tp, M_PCB);  */
       
   287 	free(tp);
       
   288 	so->so_tcpcb = 0;
       
   289 	soisfdisconnected(so);
       
   290 	/* clobber input socket cache if we're closing the cached connection */
       
   291 	if (so == tcp_last_so)
       
   292 		tcp_last_so = &tcb;
       
   293 	closesocket(so->s);
       
   294 	sbfree(&so->so_rcv);
       
   295 	sbfree(&so->so_snd);
       
   296 	sofree(so);
       
   297 	STAT(tcpstat.tcps_closed++);
       
   298 	return ((struct tcpcb *)0);
       
   299 }
       
   300 
       
   301 #ifdef notdef
       
   302 void
       
   303 tcp_drain()
       
   304 {
       
   305 	/* XXX */
       
   306 }
       
   307 
       
   308 /*
       
   309  * When a source quench is received, close congestion window
       
   310  * to one segment.  We will gradually open it again as we proceed.
       
   311  */
       
   312 void
       
   313 tcp_quench(i, errno)
       
   314 
       
   315 	int errno;
       
   316 {
       
   317 	struct tcpcb *tp = intotcpcb(inp);
       
   318 
       
   319 	if (tp)
       
   320 		tp->snd_cwnd = tp->t_maxseg;
       
   321 }
       
   322 
       
   323 #endif /* notdef */
       
   324 
       
   325 /*
       
   326  * TCP protocol interface to socket abstraction.
       
   327  */
       
   328 
       
   329 /*
       
   330  * User issued close, and wish to trail through shutdown states:
       
   331  * if never received SYN, just forget it.  If got a SYN from peer,
       
   332  * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
       
   333  * If already got a FIN from peer, then almost done; go to LAST_ACK
       
   334  * state.  In all other cases, have already sent FIN to peer (e.g.
       
   335  * after PRU_SHUTDOWN), and just have to play tedious game waiting
       
   336  * for peer to send FIN or not respond to keep-alives, etc.
       
   337  * We can let the user exit from the close as soon as the FIN is acked.
       
   338  */
       
   339 void
       
   340 tcp_sockclosed(tp)
       
   341 	struct tcpcb *tp;
       
   342 {
       
   343 
       
   344 	DEBUG_CALL("tcp_sockclosed");
       
   345 	DEBUG_ARG("tp = %lx", (long)tp);
       
   346 
       
   347 	switch (tp->t_state) {
       
   348 
       
   349 	case TCPS_CLOSED:
       
   350 	case TCPS_LISTEN:
       
   351 	case TCPS_SYN_SENT:
       
   352 		tp->t_state = TCPS_CLOSED;
       
   353 		tp = tcp_close(tp);
       
   354 		break;
       
   355 
       
   356 	case TCPS_SYN_RECEIVED:
       
   357 	case TCPS_ESTABLISHED:
       
   358 		tp->t_state = TCPS_FIN_WAIT_1;
       
   359 		break;
       
   360 
       
   361 	case TCPS_CLOSE_WAIT:
       
   362 		tp->t_state = TCPS_LAST_ACK;
       
   363 		break;
       
   364 	}
       
   365 /*	soisfdisconnecting(tp->t_socket); */
       
   366 	if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
       
   367 		soisfdisconnected(tp->t_socket);
       
   368 	if (tp)
       
   369 		tcp_output(tp);
       
   370 }
       
   371 
       
   372 /*
       
   373  * Connect to a host on the Internet
       
   374  * Called by tcp_input
       
   375  * Only do a connect, the tcp fields will be set in tcp_input
       
   376  * return 0 if there's a result of the connect,
       
   377  * else return -1 means we're still connecting
       
   378  * The return value is almost always -1 since the socket is
       
   379  * nonblocking.  Connect returns after the SYN is sent, and does
       
   380  * not wait for ACK+SYN.
       
   381  */
       
   382 int tcp_fconnect(so)
       
   383      struct socket *so;
       
   384 {
       
   385   int ret=0;
       
   386 
       
   387   DEBUG_CALL("tcp_fconnect");
       
   388   DEBUG_ARG("so = %lx", (long )so);
       
   389 
       
   390   if( (ret=so->s=socket(AF_INET,SOCK_STREAM,0)) >= 0) {
       
   391     int opt, s=so->s;
       
   392     struct sockaddr_in addr;
       
   393 
       
   394     fd_nonblock(s);
       
   395     opt = 1;
       
   396     setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
       
   397     opt = 1;
       
   398     setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
       
   399 
       
   400     addr.sin_family = AF_INET;
       
   401     if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
       
   402       /* It's an alias */
       
   403       switch(ntohl(so->so_faddr.s_addr) & 0xff) {
       
   404       case CTL_DNS:
       
   405 	addr.sin_addr = dns_addr;
       
   406 	break;
       
   407       case CTL_ALIAS:
       
   408       default:
       
   409 	addr.sin_addr = loopback_addr;
       
   410 	break;
       
   411       }
       
   412     } else
       
   413       addr.sin_addr = so->so_faddr;
       
   414     addr.sin_port = so->so_fport;
       
   415 
       
   416     DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
       
   417 		"addr.sin_addr.s_addr=%.16s\n",
       
   418 		ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
       
   419     /* We don't care what port we get */
       
   420     ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
       
   421 
       
   422     /*
       
   423      * If it's not in progress, it failed, so we just return 0,
       
   424      * without clearing SS_NOFDREF
       
   425      */
       
   426     soisfconnecting(so);
       
   427   }
       
   428 
       
   429   return(ret);
       
   430 }
       
   431 
       
   432 /*
       
   433  * Accept the socket and connect to the local-host
       
   434  *
       
   435  * We have a problem. The correct thing to do would be
       
   436  * to first connect to the local-host, and only if the
       
   437  * connection is accepted, then do an accept() here.
       
   438  * But, a) we need to know who's trying to connect
       
   439  * to the socket to be able to SYN the local-host, and
       
   440  * b) we are already connected to the foreign host by
       
   441  * the time it gets to accept(), so... We simply accept
       
   442  * here and SYN the local-host.
       
   443  */
       
   444 void
       
   445 tcp_connect(inso)
       
   446 	struct socket *inso;
       
   447 {
       
   448 	struct socket *so;
       
   449 	struct sockaddr_in addr;
       
   450 	socklen_t addrlen = sizeof(struct sockaddr_in);
       
   451 	struct tcpcb *tp;
       
   452 	int s, opt;
       
   453 
       
   454 	DEBUG_CALL("tcp_connect");
       
   455 	DEBUG_ARG("inso = %lx", (long)inso);
       
   456 
       
   457 	/*
       
   458 	 * If it's an SS_ACCEPTONCE socket, no need to socreate()
       
   459 	 * another socket, just use the accept() socket.
       
   460 	 */
       
   461 	if (inso->so_state & SS_FACCEPTONCE) {
       
   462 		/* FACCEPTONCE already have a tcpcb */
       
   463 		so = inso;
       
   464 	} else {
       
   465 		if ((so = socreate()) == NULL) {
       
   466 			/* If it failed, get rid of the pending connection */
       
   467 			closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
       
   468 			return;
       
   469 		}
       
   470 		if (tcp_attach(so) < 0) {
       
   471 			free(so); /* NOT sofree */
       
   472 			return;
       
   473 		}
       
   474 		so->so_laddr = inso->so_laddr;
       
   475 		so->so_lport = inso->so_lport;
       
   476 	}
       
   477 
       
   478 	(void) tcp_mss(sototcpcb(so), 0);
       
   479 
       
   480 	if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
       
   481 		tcp_close(sototcpcb(so)); /* This will sofree() as well */
       
   482 		return;
       
   483 	}
       
   484 	fd_nonblock(s);
       
   485 	opt = 1;
       
   486 	setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
       
   487 	opt = 1;
       
   488 	setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
       
   489 	opt = 1;
       
   490 	setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
       
   491 
       
   492 	so->so_fport = addr.sin_port;
       
   493 	so->so_faddr = addr.sin_addr;
       
   494 	/* Translate connections from localhost to the real hostname */
       
   495 	if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
       
   496 	   so->so_faddr = alias_addr;
       
   497 
       
   498 	/* Close the accept() socket, set right state */
       
   499 	if (inso->so_state & SS_FACCEPTONCE) {
       
   500 		closesocket(so->s); /* If we only accept once, close the accept() socket */
       
   501 		so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
       
   502 					   /* if it's not FACCEPTONCE, it's already NOFDREF */
       
   503 	}
       
   504 	so->s = s;
       
   505 
       
   506 	so->so_iptos = tcp_tos(so);
       
   507 	tp = sototcpcb(so);
       
   508 
       
   509 	tcp_template(tp);
       
   510 
       
   511 	/* Compute window scaling to request.  */
       
   512 /*	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
       
   513  *		(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
       
   514  *		tp->request_r_scale++;
       
   515  */
       
   516 
       
   517 /*	soisconnecting(so); */ /* NOFDREF used instead */
       
   518 	STAT(tcpstat.tcps_connattempt++);
       
   519 
       
   520 	tp->t_state = TCPS_SYN_SENT;
       
   521 	tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
       
   522 	tp->iss = tcp_iss;
       
   523 	tcp_iss += TCP_ISSINCR/2;
       
   524 	tcp_sendseqinit(tp);
       
   525 	tcp_output(tp);
       
   526 }
       
   527 
       
   528 /*
       
   529  * Attach a TCPCB to a socket.
       
   530  */
       
   531 int
       
   532 tcp_attach(so)
       
   533 	struct socket *so;
       
   534 {
       
   535 	if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
       
   536 	   return -1;
       
   537 
       
   538 	insque(so, &tcb);
       
   539 
       
   540 	return 0;
       
   541 }
       
   542 
       
   543 /*
       
   544  * Set the socket's type of service field
       
   545  */
       
   546 static const struct tos_t tcptos[] = {
       
   547 	  {0, 20, IPTOS_THROUGHPUT, 0},	/* ftp data */
       
   548 	  {21, 21, IPTOS_LOWDELAY,  EMU_FTP},	/* ftp control */
       
   549 	  {0, 23, IPTOS_LOWDELAY, 0},	/* telnet */
       
   550 	  {0, 80, IPTOS_THROUGHPUT, 0},	/* WWW */
       
   551 	  {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT},	/* rlogin */
       
   552 	  {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT},	/* shell */
       
   553 	  {0, 544, IPTOS_LOWDELAY, EMU_KSH},		/* kshell */
       
   554 	  {0, 543, IPTOS_LOWDELAY, 0},	/* klogin */
       
   555 	  {0, 6667, IPTOS_THROUGHPUT, EMU_IRC},	/* IRC */
       
   556 	  {0, 6668, IPTOS_THROUGHPUT, EMU_IRC},	/* IRC undernet */
       
   557 	  {0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO }, /* RealAudio control */
       
   558 	  {0, 113, IPTOS_LOWDELAY, EMU_IDENT }, /* identd protocol */
       
   559 	  {0, 0, 0, 0}
       
   560 };
       
   561 
       
   562 #ifdef CONFIG_QEMU
       
   563 static
       
   564 #endif
       
   565 struct emu_t *tcpemu = 0;
       
   566 
       
   567 /*
       
   568  * Return TOS according to the above table
       
   569  */
       
   570 u_int8_t
       
   571 tcp_tos(so)
       
   572 	struct socket *so;
       
   573 {
       
   574 	int i = 0;
       
   575 	struct emu_t *emup;
       
   576 
       
   577 	while(tcptos[i].tos) {
       
   578 		if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
       
   579 		    (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {
       
   580 			so->so_emu = tcptos[i].emu;
       
   581 			return tcptos[i].tos;
       
   582 		}
       
   583 		i++;
       
   584 	}
       
   585 
       
   586 	/* Nope, lets see if there's a user-added one */
       
   587 	for (emup = tcpemu; emup; emup = emup->next) {
       
   588 		if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) ||
       
   589 		    (emup->lport && (ntohs(so->so_lport) == emup->lport))) {
       
   590 			so->so_emu = emup->emu;
       
   591 			return emup->tos;
       
   592 		}
       
   593 	}
       
   594 
       
   595 	return 0;
       
   596 }
       
   597 
       
   598 #if 0
       
   599 int do_echo = -1;
       
   600 #endif
       
   601 
       
   602 /*
       
   603  * Emulate programs that try and connect to us
       
   604  * This includes ftp (the data connection is
       
   605  * initiated by the server) and IRC (DCC CHAT and
       
   606  * DCC SEND) for now
       
   607  *
       
   608  * NOTE: It's possible to crash SLiRP by sending it
       
   609  * unstandard strings to emulate... if this is a problem,
       
   610  * more checks are needed here
       
   611  *
       
   612  * XXX Assumes the whole command came in one packet
       
   613  *
       
   614  * XXX Some ftp clients will have their TOS set to
       
   615  * LOWDELAY and so Nagel will kick in.  Because of this,
       
   616  * we'll get the first letter, followed by the rest, so
       
   617  * we simply scan for ORT instead of PORT...
       
   618  * DCC doesn't have this problem because there's other stuff
       
   619  * in the packet before the DCC command.
       
   620  *
       
   621  * Return 1 if the mbuf m is still valid and should be
       
   622  * sbappend()ed
       
   623  *
       
   624  * NOTE: if you return 0 you MUST m_free() the mbuf!
       
   625  */
       
   626 int
       
   627 tcp_emu(so, m)
       
   628 	struct socket *so;
       
   629 	struct mbuf *m;
       
   630 {
       
   631 	u_int n1, n2, n3, n4, n5, n6;
       
   632         char buff[257];
       
   633 	u_int32_t laddr;
       
   634 	u_int lport;
       
   635 	char *bptr;
       
   636 
       
   637 	DEBUG_CALL("tcp_emu");
       
   638 	DEBUG_ARG("so = %lx", (long)so);
       
   639 	DEBUG_ARG("m = %lx", (long)m);
       
   640 
       
   641 	switch(so->so_emu) {
       
   642 		int x, i;
       
   643 
       
   644 	 case EMU_IDENT:
       
   645 		/*
       
   646 		 * Identification protocol as per rfc-1413
       
   647 		 */
       
   648 
       
   649 		{
       
   650 			struct socket *tmpso;
       
   651 			struct sockaddr_in addr;
       
   652 			socklen_t addrlen = sizeof(struct sockaddr_in);
       
   653 			struct sbuf *so_rcv = &so->so_rcv;
       
   654 
       
   655 			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
       
   656 			so_rcv->sb_wptr += m->m_len;
       
   657 			so_rcv->sb_rptr += m->m_len;
       
   658 			m->m_data[m->m_len] = 0; /* NULL terminate */
       
   659 			if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
       
   660 				if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
       
   661 					HTONS(n1);
       
   662 					HTONS(n2);
       
   663 					/* n2 is the one on our host */
       
   664 					for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
       
   665 						if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
       
   666 						    tmpso->so_lport == n2 &&
       
   667 						    tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
       
   668 						    tmpso->so_fport == n1) {
       
   669 							if (getsockname(tmpso->s,
       
   670 								(struct sockaddr *)&addr, &addrlen) == 0)
       
   671 							   n2 = ntohs(addr.sin_port);
       
   672 							break;
       
   673 						}
       
   674 					}
       
   675 				}
       
   676                                 so_rcv->sb_cc = snprintf(so_rcv->sb_data,
       
   677                                                          so_rcv->sb_datalen,
       
   678                                                          "%d,%d\r\n", n1, n2);
       
   679 				so_rcv->sb_rptr = so_rcv->sb_data;
       
   680 				so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
       
   681 			}
       
   682 			m_free(m);
       
   683 			return 0;
       
   684 		}
       
   685 
       
   686 #if 0
       
   687 	 case EMU_RLOGIN:
       
   688 		/*
       
   689 		 * Rlogin emulation
       
   690 		 * First we accumulate all the initial option negotiation,
       
   691 		 * then fork_exec() rlogin according to the  options
       
   692 		 */
       
   693 		{
       
   694 			int i, i2, n;
       
   695 			char *ptr;
       
   696 			char args[100];
       
   697 			char term[100];
       
   698 			struct sbuf *so_snd = &so->so_snd;
       
   699 			struct sbuf *so_rcv = &so->so_rcv;
       
   700 
       
   701 			/* First check if they have a priveladged port, or too much data has arrived */
       
   702 			if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
       
   703 			    (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
       
   704 				memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
       
   705 				so_snd->sb_wptr += 18;
       
   706 				so_snd->sb_cc += 18;
       
   707 				tcp_sockclosed(sototcpcb(so));
       
   708 				m_free(m);
       
   709 				return 0;
       
   710 			}
       
   711 
       
   712 			/* Append the current data */
       
   713 			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
       
   714 			so_rcv->sb_wptr += m->m_len;
       
   715 			so_rcv->sb_rptr += m->m_len;
       
   716 			m_free(m);
       
   717 
       
   718 			/*
       
   719 			 * Check if we have all the initial options,
       
   720 			 * and build argument list to rlogin while we're here
       
   721 			 */
       
   722 			n = 0;
       
   723 			ptr = so_rcv->sb_data;
       
   724 			args[0] = 0;
       
   725 			term[0] = 0;
       
   726 			while (ptr < so_rcv->sb_wptr) {
       
   727 				if (*ptr++ == 0) {
       
   728 					n++;
       
   729 					if (n == 2) {
       
   730 						sprintf(args, "rlogin -l %s %s",
       
   731 							ptr, inet_ntoa(so->so_faddr));
       
   732 					} else if (n == 3) {
       
   733 						i2 = so_rcv->sb_wptr - ptr;
       
   734 						for (i = 0; i < i2; i++) {
       
   735 							if (ptr[i] == '/') {
       
   736 								ptr[i] = 0;
       
   737 #ifdef HAVE_SETENV
       
   738 								sprintf(term, "%s", ptr);
       
   739 #else
       
   740 								sprintf(term, "TERM=%s", ptr);
       
   741 #endif
       
   742 								ptr[i] = '/';
       
   743 								break;
       
   744 							}
       
   745 						}
       
   746 					}
       
   747 				}
       
   748 			}
       
   749 
       
   750 			if (n != 4)
       
   751 			   return 0;
       
   752 
       
   753 			/* We have it, set our term variable and fork_exec() */
       
   754 #ifdef HAVE_SETENV
       
   755 			setenv("TERM", term, 1);
       
   756 #else
       
   757 			putenv(term);
       
   758 #endif
       
   759 			fork_exec(so, args, 2);
       
   760 			term[0] = 0;
       
   761 			so->so_emu = 0;
       
   762 
       
   763 			/* And finally, send the client a 0 character */
       
   764 			so_snd->sb_wptr[0] = 0;
       
   765 			so_snd->sb_wptr++;
       
   766 			so_snd->sb_cc++;
       
   767 
       
   768 			return 0;
       
   769 		}
       
   770 
       
   771 	 case EMU_RSH:
       
   772 		/*
       
   773 		 * rsh emulation
       
   774 		 * First we accumulate all the initial option negotiation,
       
   775 		 * then rsh_exec() rsh according to the  options
       
   776 		 */
       
   777 		{
       
   778 			int  n;
       
   779 			char *ptr;
       
   780 			char *user;
       
   781 			char *args;
       
   782 			struct sbuf *so_snd = &so->so_snd;
       
   783 			struct sbuf *so_rcv = &so->so_rcv;
       
   784 
       
   785 			/* First check if they have a priveladged port, or too much data has arrived */
       
   786 			if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
       
   787 			    (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
       
   788 				memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
       
   789 				so_snd->sb_wptr += 18;
       
   790 				so_snd->sb_cc += 18;
       
   791 				tcp_sockclosed(sototcpcb(so));
       
   792 				m_free(m);
       
   793 				return 0;
       
   794 			}
       
   795 
       
   796 			/* Append the current data */
       
   797 			memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
       
   798 			so_rcv->sb_wptr += m->m_len;
       
   799 			so_rcv->sb_rptr += m->m_len;
       
   800 			m_free(m);
       
   801 
       
   802 			/*
       
   803 			 * Check if we have all the initial options,
       
   804 			 * and build argument list to rlogin while we're here
       
   805 			 */
       
   806 			n = 0;
       
   807 			ptr = so_rcv->sb_data;
       
   808 			user="";
       
   809 			args="";
       
   810 			if (so->extra==NULL) {
       
   811 				struct socket *ns;
       
   812 				struct tcpcb* tp;
       
   813 				int port=atoi(ptr);
       
   814 				if (port <= 0) return 0;
       
   815                 if (port > 1023 || port < 512) {
       
   816                   memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
       
   817                   so_snd->sb_wptr += 18;
       
   818                   so_snd->sb_cc += 18;
       
   819                   tcp_sockclosed(sototcpcb(so));
       
   820                   return 0;
       
   821                 }
       
   822 				if ((ns=socreate()) == NULL)
       
   823                   return 0;
       
   824 				if (tcp_attach(ns)<0) {
       
   825                   free(ns);
       
   826                   return 0;
       
   827 				}
       
   828 
       
   829 				ns->so_laddr=so->so_laddr;
       
   830 				ns->so_lport=htons(port);
       
   831 
       
   832 				(void) tcp_mss(sototcpcb(ns), 0);
       
   833 
       
   834 				ns->so_faddr=so->so_faddr;
       
   835 				ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */
       
   836 
       
   837 				if (ns->so_faddr.s_addr == 0 ||
       
   838 					ns->so_faddr.s_addr == loopback_addr.s_addr)
       
   839                   ns->so_faddr = alias_addr;
       
   840 
       
   841 				ns->so_iptos = tcp_tos(ns);
       
   842 				tp = sototcpcb(ns);
       
   843 
       
   844 				tcp_template(tp);
       
   845 
       
   846 				/* Compute window scaling to request.  */
       
   847 				/*	while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
       
   848 				 *		(TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
       
   849 				 *		tp->request_r_scale++;
       
   850 				 */
       
   851 
       
   852                 /*soisfconnecting(ns);*/
       
   853 
       
   854 				STAT(tcpstat.tcps_connattempt++);
       
   855 
       
   856 				tp->t_state = TCPS_SYN_SENT;
       
   857 				tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
       
   858 				tp->iss = tcp_iss;
       
   859 				tcp_iss += TCP_ISSINCR/2;
       
   860 				tcp_sendseqinit(tp);
       
   861 				tcp_output(tp);
       
   862 				so->extra=ns;
       
   863 			}
       
   864 			while (ptr < so_rcv->sb_wptr) {
       
   865               if (*ptr++ == 0) {
       
   866                 n++;
       
   867                 if (n == 2) {
       
   868                   user=ptr;
       
   869                 } else if (n == 3) {
       
   870                   args=ptr;
       
   871                 }
       
   872               }
       
   873 			}
       
   874 
       
   875 			if (n != 4)
       
   876               return 0;
       
   877 
       
   878 			rsh_exec(so,so->extra, user, inet_ntoa(so->so_faddr), args);
       
   879 			so->so_emu = 0;
       
   880 			so->extra=NULL;
       
   881 
       
   882 			/* And finally, send the client a 0 character */
       
   883 			so_snd->sb_wptr[0] = 0;
       
   884 			so_snd->sb_wptr++;
       
   885 			so_snd->sb_cc++;
       
   886 
       
   887 			return 0;
       
   888 		}
       
   889 
       
   890 	 case EMU_CTL:
       
   891 		{
       
   892 			int num;
       
   893 			struct sbuf *so_snd = &so->so_snd;
       
   894 			struct sbuf *so_rcv = &so->so_rcv;
       
   895 
       
   896 			/*
       
   897 			 * If there is binary data here, we save it in so->so_m
       
   898 			 */
       
   899 			if (!so->so_m) {
       
   900 			  int rxlen;
       
   901 			  char *rxdata;
       
   902 			  rxdata=mtod(m, char *);
       
   903 			  for (rxlen=m->m_len; rxlen; rxlen--) {
       
   904 			    if (*rxdata++ & 0x80) {
       
   905 			      so->so_m = m;
       
   906 			      return 0;
       
   907 			    }
       
   908 			  }
       
   909 			} /* if(so->so_m==NULL) */
       
   910 
       
   911 			/*
       
   912 			 * Append the line
       
   913 			 */
       
   914 			sbappendsb(so_rcv, m);
       
   915 
       
   916 			/* To avoid going over the edge of the buffer, we reset it */
       
   917 			if (so_snd->sb_cc == 0)
       
   918 			   so_snd->sb_wptr = so_snd->sb_rptr = so_snd->sb_data;
       
   919 
       
   920 			/*
       
   921 			 * A bit of a hack:
       
   922 			 * If the first packet we get here is 1 byte long, then it
       
   923 			 * was done in telnet character mode, therefore we must echo
       
   924 			 * the characters as they come.  Otherwise, we echo nothing,
       
   925 			 * because in linemode, the line is already echoed
       
   926 			 * XXX two or more control connections won't work
       
   927 			 */
       
   928 			if (do_echo == -1) {
       
   929 				if (m->m_len == 1) do_echo = 1;
       
   930 				else do_echo = 0;
       
   931 			}
       
   932 			if (do_echo) {
       
   933 			  sbappendsb(so_snd, m);
       
   934 			  m_free(m);
       
   935 			  tcp_output(sototcpcb(so)); /* XXX */
       
   936 			} else
       
   937 			  m_free(m);
       
   938 
       
   939 			num = 0;
       
   940 			while (num < so->so_rcv.sb_cc) {
       
   941 				if (*(so->so_rcv.sb_rptr + num) == '\n' ||
       
   942 				    *(so->so_rcv.sb_rptr + num) == '\r') {
       
   943 					int n;
       
   944 
       
   945 					*(so_rcv->sb_rptr + num) = 0;
       
   946 					if (ctl_password && !ctl_password_ok) {
       
   947 						/* Need a password */
       
   948 						if (sscanf(so_rcv->sb_rptr, "pass %256s", buff) == 1) {
       
   949 							if (strcmp(buff, ctl_password) == 0) {
       
   950 								ctl_password_ok = 1;
       
   951 								n = sprintf(so_snd->sb_wptr,
       
   952 									    "Password OK.\r\n");
       
   953 								goto do_prompt;
       
   954 							}
       
   955 						}
       
   956 						n = sprintf(so_snd->sb_wptr,
       
   957 					 "Error: Password required, log on with \"pass PASSWORD\"\r\n");
       
   958 						goto do_prompt;
       
   959 					}
       
   960 					cfg_quitting = 0;
       
   961 					n = do_config(so_rcv->sb_rptr, so, PRN_SPRINTF);
       
   962 					if (!cfg_quitting) {
       
   963 						/* Register the printed data */
       
   964 do_prompt:
       
   965 						so_snd->sb_cc += n;
       
   966 						so_snd->sb_wptr += n;
       
   967 						/* Add prompt */
       
   968 						n = sprintf(so_snd->sb_wptr, "Slirp> ");
       
   969 						so_snd->sb_cc += n;
       
   970 						so_snd->sb_wptr += n;
       
   971 					}
       
   972 					/* Drop so_rcv data */
       
   973 					so_rcv->sb_cc = 0;
       
   974 					so_rcv->sb_wptr = so_rcv->sb_rptr = so_rcv->sb_data;
       
   975 					tcp_output(sototcpcb(so)); /* Send the reply */
       
   976 				}
       
   977 				num++;
       
   978 			}
       
   979 			return 0;
       
   980 		}
       
   981 #endif
       
   982         case EMU_FTP: /* ftp */
       
   983 		*(m->m_data+m->m_len) = 0; /* NULL terminate for strstr */
       
   984 		if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
       
   985 			/*
       
   986 			 * Need to emulate the PORT command
       
   987 			 */
       
   988 			x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
       
   989 				   &n1, &n2, &n3, &n4, &n5, &n6, buff);
       
   990 			if (x < 6)
       
   991 			   return 1;
       
   992 
       
   993 			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
       
   994 			lport = htons((n5 << 8) | (n6));
       
   995 
       
   996 			if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
       
   997 			   return 1;
       
   998 
       
   999 			n6 = ntohs(so->so_fport);
       
  1000 
       
  1001 			n5 = (n6 >> 8) & 0xff;
       
  1002 			n6 &= 0xff;
       
  1003 
       
  1004 			laddr = ntohl(so->so_faddr.s_addr);
       
  1005 
       
  1006 			n1 = ((laddr >> 24) & 0xff);
       
  1007 			n2 = ((laddr >> 16) & 0xff);
       
  1008 			n3 = ((laddr >> 8)  & 0xff);
       
  1009 			n4 =  (laddr & 0xff);
       
  1010 
       
  1011 			m->m_len = bptr - m->m_data; /* Adjust length */
       
  1012                         m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,
       
  1013                                              "ORT %d,%d,%d,%d,%d,%d\r\n%s",
       
  1014                                              n1, n2, n3, n4, n5, n6, x==7?buff:"");
       
  1015 			return 1;
       
  1016 		} else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) {
       
  1017 			/*
       
  1018 			 * Need to emulate the PASV response
       
  1019 			 */
       
  1020 			x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
       
  1021 				   &n1, &n2, &n3, &n4, &n5, &n6, buff);
       
  1022 			if (x < 6)
       
  1023 			   return 1;
       
  1024 
       
  1025 			laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
       
  1026 			lport = htons((n5 << 8) | (n6));
       
  1027 
       
  1028 			if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
       
  1029 			   return 1;
       
  1030 
       
  1031 			n6 = ntohs(so->so_fport);
       
  1032 
       
  1033 			n5 = (n6 >> 8) & 0xff;
       
  1034 			n6 &= 0xff;
       
  1035 
       
  1036 			laddr = ntohl(so->so_faddr.s_addr);
       
  1037 
       
  1038 			n1 = ((laddr >> 24) & 0xff);
       
  1039 			n2 = ((laddr >> 16) & 0xff);
       
  1040 			n3 = ((laddr >> 8)  & 0xff);
       
  1041 			n4 =  (laddr & 0xff);
       
  1042 
       
  1043 			m->m_len = bptr - m->m_data; /* Adjust length */
       
  1044 			m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,
       
  1045                                              "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
       
  1046                                              n1, n2, n3, n4, n5, n6, x==7?buff:"");
       
  1047 
       
  1048 			return 1;
       
  1049 		}
       
  1050 
       
  1051 		return 1;
       
  1052 
       
  1053 	 case EMU_KSH:
       
  1054 		/*
       
  1055 		 * The kshell (Kerberos rsh) and shell services both pass
       
  1056 		 * a local port port number to carry signals to the server
       
  1057 		 * and stderr to the client.  It is passed at the beginning
       
  1058 		 * of the connection as a NUL-terminated decimal ASCII string.
       
  1059 		 */
       
  1060 		so->so_emu = 0;
       
  1061 		for (lport = 0, i = 0; i < m->m_len-1; ++i) {
       
  1062 			if (m->m_data[i] < '0' || m->m_data[i] > '9')
       
  1063 				return 1;       /* invalid number */
       
  1064 			lport *= 10;
       
  1065 			lport += m->m_data[i] - '0';
       
  1066 		}
       
  1067 		if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
       
  1068 		    (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
       
  1069                     m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d",
       
  1070                                         ntohs(so->so_fport)) + 1;
       
  1071 		return 1;
       
  1072 
       
  1073 	 case EMU_IRC:
       
  1074 		/*
       
  1075 		 * Need to emulate DCC CHAT, DCC SEND and DCC MOVE
       
  1076 		 */
       
  1077 		*(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */
       
  1078 		if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
       
  1079 			 return 1;
       
  1080 
       
  1081 		/* The %256s is for the broken mIRC */
       
  1082 		if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
       
  1083 			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
       
  1084 				return 1;
       
  1085 
       
  1086 			m->m_len = bptr - m->m_data; /* Adjust length */
       
  1087                         m->m_len += snprintf(bptr, m->m_hdr.mh_size,
       
  1088                                              "DCC CHAT chat %lu %u%c\n",
       
  1089                                              (unsigned long)ntohl(so->so_faddr.s_addr),
       
  1090                                              ntohs(so->so_fport), 1);
       
  1091 		} else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
       
  1092 			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
       
  1093 				return 1;
       
  1094 
       
  1095 			m->m_len = bptr - m->m_data; /* Adjust length */
       
  1096                         m->m_len += snprintf(bptr, m->m_hdr.mh_size,
       
  1097                                              "DCC SEND %s %lu %u %u%c\n", buff,
       
  1098                                              (unsigned long)ntohl(so->so_faddr.s_addr),
       
  1099                                              ntohs(so->so_fport), n1, 1);
       
  1100 		} else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
       
  1101 			if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
       
  1102 				return 1;
       
  1103 
       
  1104 			m->m_len = bptr - m->m_data; /* Adjust length */
       
  1105                         m->m_len += snprintf(bptr, m->m_hdr.mh_size,
       
  1106                                              "DCC MOVE %s %lu %u %u%c\n", buff,
       
  1107                                              (unsigned long)ntohl(so->so_faddr.s_addr),
       
  1108                                              ntohs(so->so_fport), n1, 1);
       
  1109 		}
       
  1110 		return 1;
       
  1111 
       
  1112 	 case EMU_REALAUDIO:
       
  1113                 /*
       
  1114 		 * RealAudio emulation - JP. We must try to parse the incoming
       
  1115 		 * data and try to find the two characters that contain the
       
  1116 		 * port number. Then we redirect an udp port and replace the
       
  1117 		 * number with the real port we got.
       
  1118 		 *
       
  1119 		 * The 1.0 beta versions of the player are not supported
       
  1120 		 * any more.
       
  1121 		 *
       
  1122 		 * A typical packet for player version 1.0 (release version):
       
  1123 		 *
       
  1124 		 * 0000:50 4E 41 00 05
       
  1125 		 * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....×..gælÜc..P
       
  1126 		 * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
       
  1127 		 * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
       
  1128 		 * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
       
  1129 		 *
       
  1130 		 * Now the port number 0x1BD7 is found at offset 0x04 of the
       
  1131 		 * Now the port number 0x1BD7 is found at offset 0x04 of the
       
  1132 		 * second packet. This time we received five bytes first and
       
  1133 		 * then the rest. You never know how many bytes you get.
       
  1134 		 *
       
  1135 		 * A typical packet for player version 2.0 (beta):
       
  1136 		 *
       
  1137 		 * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........Á.
       
  1138 		 * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .guxõc..Win2.0.0
       
  1139 		 * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
       
  1140 		 * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
       
  1141 		 * 0040:65 2E 72 61 79 53 00 00 06 36 42                e.rayS...6B
       
  1142 		 *
       
  1143 		 * Port number 0x1BC1 is found at offset 0x0d.
       
  1144 		 *
       
  1145 		 * This is just a horrible switch statement. Variable ra tells
       
  1146 		 * us where we're going.
       
  1147 		 */
       
  1148 
       
  1149 		bptr = m->m_data;
       
  1150 		while (bptr < m->m_data + m->m_len) {
       
  1151 			u_short p;
       
  1152 			static int ra = 0;
       
  1153 			char ra_tbl[4];
       
  1154 
       
  1155 			ra_tbl[0] = 0x50;
       
  1156 			ra_tbl[1] = 0x4e;
       
  1157 			ra_tbl[2] = 0x41;
       
  1158 			ra_tbl[3] = 0;
       
  1159 
       
  1160 			switch (ra) {
       
  1161 			 case 0:
       
  1162 			 case 2:
       
  1163 			 case 3:
       
  1164 				if (*bptr++ != ra_tbl[ra]) {
       
  1165 					ra = 0;
       
  1166 					continue;
       
  1167 				}
       
  1168 				break;
       
  1169 
       
  1170 			 case 1:
       
  1171 				/*
       
  1172 				 * We may get 0x50 several times, ignore them
       
  1173 				 */
       
  1174 				if (*bptr == 0x50) {
       
  1175 					ra = 1;
       
  1176 					bptr++;
       
  1177 					continue;
       
  1178 				} else if (*bptr++ != ra_tbl[ra]) {
       
  1179 					ra = 0;
       
  1180 					continue;
       
  1181 				}
       
  1182 				break;
       
  1183 
       
  1184 			 case 4:
       
  1185 				/*
       
  1186 				 * skip version number
       
  1187 				 */
       
  1188 				bptr++;
       
  1189 				break;
       
  1190 
       
  1191 			 case 5:
       
  1192 				/*
       
  1193 				 * The difference between versions 1.0 and
       
  1194 				 * 2.0 is here. For future versions of
       
  1195 				 * the player this may need to be modified.
       
  1196 				 */
       
  1197 				if (*(bptr + 1) == 0x02)
       
  1198 				   bptr += 8;
       
  1199 				else
       
  1200 				   bptr += 4;
       
  1201 				break;
       
  1202 
       
  1203 			 case 6:
       
  1204 				/* This is the field containing the port
       
  1205 				 * number that RA-player is listening to.
       
  1206 				 */
       
  1207 				lport = (((u_char*)bptr)[0] << 8)
       
  1208 				+ ((u_char *)bptr)[1];
       
  1209 				if (lport < 6970)
       
  1210 				   lport += 256;   /* don't know why */
       
  1211 				if (lport < 6970 || lport > 7170)
       
  1212 				   return 1;       /* failed */
       
  1213 
       
  1214 				/* try to get udp port between 6970 - 7170 */
       
  1215 				for (p = 6970; p < 7071; p++) {
       
  1216 					if (udp_listen( htons(p),
       
  1217 						       so->so_laddr.s_addr,
       
  1218 						       htons(lport),
       
  1219 						       SS_FACCEPTONCE)) {
       
  1220 						break;
       
  1221 					}
       
  1222 				}
       
  1223 				if (p == 7071)
       
  1224 				   p = 0;
       
  1225 				*(u_char *)bptr++ = (p >> 8) & 0xff;
       
  1226 				*(u_char *)bptr++ = p & 0xff;
       
  1227 				ra = 0;
       
  1228 				return 1;   /* port redirected, we're done */
       
  1229 				break;
       
  1230 
       
  1231 			 default:
       
  1232 				ra = 0;
       
  1233 			}
       
  1234 			ra++;
       
  1235 		}
       
  1236 		return 1;
       
  1237 
       
  1238 	 default:
       
  1239 		/* Ooops, not emulated, won't call tcp_emu again */
       
  1240 		so->so_emu = 0;
       
  1241 		return 1;
       
  1242 	}
       
  1243 }
       
  1244 
       
  1245 /*
       
  1246  * Do misc. config of SLiRP while its running.
       
  1247  * Return 0 if this connections is to be closed, 1 otherwise,
       
  1248  * return 2 if this is a command-line connection
       
  1249  */
       
  1250 int
       
  1251 tcp_ctl(so)
       
  1252 	struct socket *so;
       
  1253 {
       
  1254 	struct sbuf *sb = &so->so_snd;
       
  1255 	int command;
       
  1256  	struct ex_list *ex_ptr;
       
  1257 	int do_pty;
       
  1258         //	struct socket *tmpso;
       
  1259 
       
  1260 	DEBUG_CALL("tcp_ctl");
       
  1261 	DEBUG_ARG("so = %lx", (long )so);
       
  1262 
       
  1263 #if 0
       
  1264 	/*
       
  1265 	 * Check if they're authorised
       
  1266 	 */
       
  1267 	if (ctl_addr.s_addr && (ctl_addr.s_addr == -1 || (so->so_laddr.s_addr != ctl_addr.s_addr))) {
       
  1268 		sb->sb_cc = sprintf(sb->sb_wptr,"Error: Permission denied.\r\n");
       
  1269 		sb->sb_wptr += sb->sb_cc;
       
  1270 		return 0;
       
  1271 	}
       
  1272 #endif
       
  1273 	command = (ntohl(so->so_faddr.s_addr) & 0xff);
       
  1274 
       
  1275 	switch(command) {
       
  1276 	default: /* Check for exec's */
       
  1277 
       
  1278 		/*
       
  1279 		 * Check if it's pty_exec
       
  1280 		 */
       
  1281 		for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
       
  1282 			if (ex_ptr->ex_fport == so->so_fport &&
       
  1283 			    command == ex_ptr->ex_addr) {
       
  1284 				do_pty = ex_ptr->ex_pty;
       
  1285 				goto do_exec;
       
  1286 			}
       
  1287 		}
       
  1288 
       
  1289 		/*
       
  1290 		 * Nothing bound..
       
  1291 		 */
       
  1292 		/* tcp_fconnect(so); */
       
  1293 
       
  1294 		/* FALLTHROUGH */
       
  1295 	case CTL_ALIAS:
       
  1296           sb->sb_cc = snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),
       
  1297                                "Error: No application configured.\r\n");
       
  1298 	  sb->sb_wptr += sb->sb_cc;
       
  1299 	  return(0);
       
  1300 
       
  1301 	do_exec:
       
  1302 		DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
       
  1303 		return(fork_exec(so, ex_ptr->ex_exec, do_pty));
       
  1304 
       
  1305 #if 0
       
  1306 	case CTL_CMD:
       
  1307 	   for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
       
  1308 	     if (tmpso->so_emu == EMU_CTL &&
       
  1309 		 !(tmpso->so_tcpcb?
       
  1310 		   (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK))
       
  1311 		   :0)) {
       
  1312 	       /* Ooops, control connection already active */
       
  1313 	       sb->sb_cc = sprintf(sb->sb_wptr,"Sorry, already connected.\r\n");
       
  1314 	       sb->sb_wptr += sb->sb_cc;
       
  1315 	       return 0;
       
  1316 	     }
       
  1317 	   }
       
  1318 	   so->so_emu = EMU_CTL;
       
  1319 	   ctl_password_ok = 0;
       
  1320 	   sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> ");
       
  1321 	   sb->sb_wptr += sb->sb_cc;
       
  1322 	   do_echo=-1;
       
  1323 	   return(2);
       
  1324 #endif
       
  1325 	}
       
  1326 }