qemu/slirp/tcp_subr.c
<<
>>
Prefs
   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. Neither the name of the University nor the names of its contributors
  14 *    may be used to endorse or promote products derived from this software
  15 *    without specific prior written permission.
  16 *
  17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27 * SUCH DAMAGE.
  28 *
  29 *      @(#)tcp_subr.c  8.1 (Berkeley) 6/10/93
  30 * tcp_subr.c,v 1.5 1994/10/08 22:39:58 phk Exp
  31 */
  32
  33/*
  34 * Changes and additions relating to SLiRP
  35 * Copyright (c) 1995 Danny Gasparovski.
  36 *
  37 * Please read the file COPYRIGHT for the
  38 * terms and conditions of the copyright.
  39 */
  40
  41#include <slirp.h>
  42
  43/* patchable/settable parameters for tcp */
  44/* Don't do rfc1323 performance enhancements */
  45#define TCP_DO_RFC1323 0
  46
  47/*
  48 * Tcp initialization
  49 */
  50void
  51tcp_init(Slirp *slirp)
  52{
  53    slirp->tcp_iss = 1;         /* wrong */
  54    slirp->tcb.so_next = slirp->tcb.so_prev = &slirp->tcb;
  55    slirp->tcp_last_so = &slirp->tcb;
  56}
  57
  58/*
  59 * Create template to be used to send tcp packets on a connection.
  60 * Call after host entry created, fills
  61 * in a skeletal tcp/ip header, minimizing the amount of work
  62 * necessary when the connection is used.
  63 */
  64void
  65tcp_template(struct tcpcb *tp)
  66{
  67        struct socket *so = tp->t_socket;
  68        register struct tcpiphdr *n = &tp->t_template;
  69
  70        n->ti_mbuf = NULL;
  71        n->ti_x1 = 0;
  72        n->ti_pr = IPPROTO_TCP;
  73        n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
  74        n->ti_src = so->so_faddr;
  75        n->ti_dst = so->so_laddr;
  76        n->ti_sport = so->so_fport;
  77        n->ti_dport = so->so_lport;
  78
  79        n->ti_seq = 0;
  80        n->ti_ack = 0;
  81        n->ti_x2 = 0;
  82        n->ti_off = 5;
  83        n->ti_flags = 0;
  84        n->ti_win = 0;
  85        n->ti_sum = 0;
  86        n->ti_urp = 0;
  87}
  88
  89/*
  90 * Send a single message to the TCP at address specified by
  91 * the given TCP/IP header.  If m == 0, then we make a copy
  92 * of the tcpiphdr at ti and send directly to the addressed host.
  93 * This is used to force keep alive messages out using the TCP
  94 * template for a connection tp->t_template.  If flags are given
  95 * then we send a message back to the TCP which originated the
  96 * segment ti, and discard the mbuf containing it and any other
  97 * attached mbufs.
  98 *
  99 * In any case the ack and sequence number of the transmitted
 100 * segment are as specified by the parameters.
 101 */
 102void
 103tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 104            tcp_seq ack, tcp_seq seq, int flags)
 105{
 106        register int tlen;
 107        int win = 0;
 108
 109        DEBUG_CALL("tcp_respond");
 110        DEBUG_ARG("tp = %lx", (long)tp);
 111        DEBUG_ARG("ti = %lx", (long)ti);
 112        DEBUG_ARG("m = %lx", (long)m);
 113        DEBUG_ARG("ack = %u", ack);
 114        DEBUG_ARG("seq = %u", seq);
 115        DEBUG_ARG("flags = %x", flags);
 116
 117        if (tp)
 118                win = sbspace(&tp->t_socket->so_rcv);
 119        if (m == NULL) {
 120                if ((m = m_get(tp->t_socket->slirp)) == NULL)
 121                        return;
 122                tlen = 0;
 123                m->m_data += IF_MAXLINKHDR;
 124                *mtod(m, struct tcpiphdr *) = *ti;
 125                ti = mtod(m, struct tcpiphdr *);
 126                flags = TH_ACK;
 127        } else {
 128                /*
 129                 * ti points into m so the next line is just making
 130                 * the mbuf point to ti
 131                 */
 132                m->m_data = (caddr_t)ti;
 133
 134                m->m_len = sizeof (struct tcpiphdr);
 135                tlen = 0;
 136#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
 137                xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);
 138                xchg(ti->ti_dport, ti->ti_sport, uint16_t);
 139#undef xchg
 140        }
 141        ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
 142        tlen += sizeof (struct tcpiphdr);
 143        m->m_len = tlen;
 144
 145        ti->ti_mbuf = NULL;
 146        ti->ti_x1 = 0;
 147        ti->ti_seq = htonl(seq);
 148        ti->ti_ack = htonl(ack);
 149        ti->ti_x2 = 0;
 150        ti->ti_off = sizeof (struct tcphdr) >> 2;
 151        ti->ti_flags = flags;
 152        if (tp)
 153                ti->ti_win = htons((uint16_t) (win >> tp->rcv_scale));
 154        else
 155                ti->ti_win = htons((uint16_t)win);
 156        ti->ti_urp = 0;
 157        ti->ti_sum = 0;
 158        ti->ti_sum = cksum(m, tlen);
 159        ((struct ip *)ti)->ip_len = tlen;
 160
 161        if(flags & TH_RST)
 162          ((struct ip *)ti)->ip_ttl = MAXTTL;
 163        else
 164          ((struct ip *)ti)->ip_ttl = IPDEFTTL;
 165
 166        (void) ip_output((struct socket *)0, m);
 167}
 168
 169/*
 170 * Create a new TCP control block, making an
 171 * empty reassembly queue and hooking it to the argument
 172 * protocol control block.
 173 */
 174struct tcpcb *
 175tcp_newtcpcb(struct socket *so)
 176{
 177        register struct tcpcb *tp;
 178
 179        tp = (struct tcpcb *)malloc(sizeof(*tp));
 180        if (tp == NULL)
 181                return ((struct tcpcb *)0);
 182
 183        memset((char *) tp, 0, sizeof(struct tcpcb));
 184        tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
 185        tp->t_maxseg = TCP_MSS;
 186
 187        tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
 188        tp->t_socket = so;
 189
 190        /*
 191         * Init srtt to TCPTV_SRTTBASE (0), so we can tell that we have no
 192         * rtt estimate.  Set rttvar so that srtt + 2 * rttvar gives
 193         * reasonable initial retransmit time.
 194         */
 195        tp->t_srtt = TCPTV_SRTTBASE;
 196        tp->t_rttvar = TCPTV_SRTTDFLT << 2;
 197        tp->t_rttmin = TCPTV_MIN;
 198
 199        TCPT_RANGESET(tp->t_rxtcur,
 200            ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
 201            TCPTV_MIN, TCPTV_REXMTMAX);
 202
 203        tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
 204        tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
 205        tp->t_state = TCPS_CLOSED;
 206
 207        so->so_tcpcb = tp;
 208
 209        return (tp);
 210}
 211
 212/*
 213 * Drop a TCP connection, reporting
 214 * the specified error.  If connection is synchronized,
 215 * then send a RST to peer.
 216 */
 217struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
 218{
 219        DEBUG_CALL("tcp_drop");
 220        DEBUG_ARG("tp = %lx", (long)tp);
 221        DEBUG_ARG("errno = %d", errno);
 222
 223        if (TCPS_HAVERCVDSYN(tp->t_state)) {
 224                tp->t_state = TCPS_CLOSED;
 225                (void) tcp_output(tp);
 226        }
 227        return (tcp_close(tp));
 228}
 229
 230/*
 231 * Close a TCP control block:
 232 *      discard all space held by the tcp
 233 *      discard internet protocol block
 234 *      wake up any sleepers
 235 */
 236struct tcpcb *
 237tcp_close(struct tcpcb *tp)
 238{
 239        register struct tcpiphdr *t;
 240        struct socket *so = tp->t_socket;
 241        Slirp *slirp = so->slirp;
 242        register struct mbuf *m;
 243
 244        DEBUG_CALL("tcp_close");
 245        DEBUG_ARG("tp = %lx", (long )tp);
 246
 247        /* free the reassembly queue, if any */
 248        t = tcpfrag_list_first(tp);
 249        while (!tcpfrag_list_end(t, tp)) {
 250                t = tcpiphdr_next(t);
 251                m = tcpiphdr_prev(t)->ti_mbuf;
 252                remque(tcpiphdr2qlink(tcpiphdr_prev(t)));
 253                m_freem(m);
 254        }
 255        free(tp);
 256        so->so_tcpcb = NULL;
 257        /* clobber input socket cache if we're closing the cached connection */
 258        if (so == slirp->tcp_last_so)
 259                slirp->tcp_last_so = &slirp->tcb;
 260        closesocket(so->s);
 261        sbfree(&so->so_rcv);
 262        sbfree(&so->so_snd);
 263        sofree(so);
 264        return ((struct tcpcb *)0);
 265}
 266
 267/*
 268 * TCP protocol interface to socket abstraction.
 269 */
 270
 271/*
 272 * User issued close, and wish to trail through shutdown states:
 273 * if never received SYN, just forget it.  If got a SYN from peer,
 274 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
 275 * If already got a FIN from peer, then almost done; go to LAST_ACK
 276 * state.  In all other cases, have already sent FIN to peer (e.g.
 277 * after PRU_SHUTDOWN), and just have to play tedious game waiting
 278 * for peer to send FIN or not respond to keep-alives, etc.
 279 * We can let the user exit from the close as soon as the FIN is acked.
 280 */
 281void
 282tcp_sockclosed(struct tcpcb *tp)
 283{
 284
 285        DEBUG_CALL("tcp_sockclosed");
 286        DEBUG_ARG("tp = %lx", (long)tp);
 287
 288        switch (tp->t_state) {
 289
 290        case TCPS_CLOSED:
 291        case TCPS_LISTEN:
 292        case TCPS_SYN_SENT:
 293                tp->t_state = TCPS_CLOSED;
 294                tp = tcp_close(tp);
 295                break;
 296
 297        case TCPS_SYN_RECEIVED:
 298        case TCPS_ESTABLISHED:
 299                tp->t_state = TCPS_FIN_WAIT_1;
 300                break;
 301
 302        case TCPS_CLOSE_WAIT:
 303                tp->t_state = TCPS_LAST_ACK;
 304                break;
 305        }
 306        if (tp)
 307                tcp_output(tp);
 308}
 309
 310/*
 311 * Connect to a host on the Internet
 312 * Called by tcp_input
 313 * Only do a connect, the tcp fields will be set in tcp_input
 314 * return 0 if there's a result of the connect,
 315 * else return -1 means we're still connecting
 316 * The return value is almost always -1 since the socket is
 317 * nonblocking.  Connect returns after the SYN is sent, and does
 318 * not wait for ACK+SYN.
 319 */
 320int tcp_fconnect(struct socket *so)
 321{
 322  Slirp *slirp = so->slirp;
 323  int ret=0;
 324
 325  DEBUG_CALL("tcp_fconnect");
 326  DEBUG_ARG("so = %lx", (long )so);
 327
 328  if( (ret = so->s = qemu_socket(AF_INET,SOCK_STREAM,0)) >= 0) {
 329    int opt, s=so->s;
 330    struct sockaddr_in addr;
 331
 332    fd_nonblock(s);
 333    opt = 1;
 334    setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(opt ));
 335    opt = 1;
 336    setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
 337
 338    addr.sin_family = AF_INET;
 339    if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
 340        slirp->vnetwork_addr.s_addr) {
 341      /* It's an alias */
 342      if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
 343        if (get_dns_addr(&addr.sin_addr) < 0)
 344          addr.sin_addr = loopback_addr;
 345      } else {
 346        addr.sin_addr = loopback_addr;
 347      }
 348    } else
 349      addr.sin_addr = so->so_faddr;
 350    addr.sin_port = so->so_fport;
 351
 352    DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
 353                "addr.sin_addr.s_addr=%.16s\n",
 354                ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
 355    /* We don't care what port we get */
 356    ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
 357
 358    /*
 359     * If it's not in progress, it failed, so we just return 0,
 360     * without clearing SS_NOFDREF
 361     */
 362    soisfconnecting(so);
 363  }
 364
 365  return(ret);
 366}
 367
 368/*
 369 * Accept the socket and connect to the local-host
 370 *
 371 * We have a problem. The correct thing to do would be
 372 * to first connect to the local-host, and only if the
 373 * connection is accepted, then do an accept() here.
 374 * But, a) we need to know who's trying to connect
 375 * to the socket to be able to SYN the local-host, and
 376 * b) we are already connected to the foreign host by
 377 * the time it gets to accept(), so... We simply accept
 378 * here and SYN the local-host.
 379 */
 380void
 381tcp_connect(struct socket *inso)
 382{
 383        Slirp *slirp = inso->slirp;
 384        struct socket *so;
 385        struct sockaddr_in addr;
 386        socklen_t addrlen = sizeof(struct sockaddr_in);
 387        struct tcpcb *tp;
 388        int s, opt;
 389
 390        DEBUG_CALL("tcp_connect");
 391        DEBUG_ARG("inso = %lx", (long)inso);
 392
 393        /*
 394         * If it's an SS_ACCEPTONCE socket, no need to socreate()
 395         * another socket, just use the accept() socket.
 396         */
 397        if (inso->so_state & SS_FACCEPTONCE) {
 398                /* FACCEPTONCE already have a tcpcb */
 399                so = inso;
 400        } else {
 401                if ((so = socreate(slirp)) == NULL) {
 402                        /* If it failed, get rid of the pending connection */
 403                        closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
 404                        return;
 405                }
 406                if (tcp_attach(so) < 0) {
 407                        free(so); /* NOT sofree */
 408                        return;
 409                }
 410                so->so_laddr = inso->so_laddr;
 411                so->so_lport = inso->so_lport;
 412        }
 413
 414        (void) tcp_mss(sototcpcb(so), 0);
 415
 416        if ((s = accept(inso->s,(struct sockaddr *)&addr,&addrlen)) < 0) {
 417                tcp_close(sototcpcb(so)); /* This will sofree() as well */
 418                return;
 419        }
 420        fd_nonblock(s);
 421        opt = 1;
 422        setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
 423        opt = 1;
 424        setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
 425        opt = 1;
 426        setsockopt(s,IPPROTO_TCP,TCP_NODELAY,(char *)&opt,sizeof(int));
 427
 428        so->so_fport = addr.sin_port;
 429        so->so_faddr = addr.sin_addr;
 430        /* Translate connections from localhost to the real hostname */
 431        if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
 432           so->so_faddr = slirp->vhost_addr;
 433
 434        /* Close the accept() socket, set right state */
 435        if (inso->so_state & SS_FACCEPTONCE) {
 436                closesocket(so->s); /* If we only accept once, close the accept() socket */
 437                so->so_state = SS_NOFDREF; /* Don't select it yet, even though we have an FD */
 438                                           /* if it's not FACCEPTONCE, it's already NOFDREF */
 439        }
 440        so->s = s;
 441        so->so_state |= SS_INCOMING;
 442
 443        so->so_iptos = tcp_tos(so);
 444        tp = sototcpcb(so);
 445
 446        tcp_template(tp);
 447
 448        tp->t_state = TCPS_SYN_SENT;
 449        tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
 450        tp->iss = slirp->tcp_iss;
 451        slirp->tcp_iss += TCP_ISSINCR/2;
 452        tcp_sendseqinit(tp);
 453        tcp_output(tp);
 454}
 455
 456/*
 457 * Attach a TCPCB to a socket.
 458 */
 459int
 460tcp_attach(struct socket *so)
 461{
 462        if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
 463           return -1;
 464
 465        insque(so, &so->slirp->tcb);
 466
 467        return 0;
 468}
 469
 470/*
 471 * Set the socket's type of service field
 472 */
 473static const struct tos_t tcptos[] = {
 474          {0, 20, IPTOS_THROUGHPUT, 0}, /* ftp data */
 475          {21, 21, IPTOS_LOWDELAY,  EMU_FTP},   /* ftp control */
 476          {0, 23, IPTOS_LOWDELAY, 0},   /* telnet */
 477          {0, 80, IPTOS_THROUGHPUT, 0}, /* WWW */
 478          {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT},   /* rlogin */
 479          {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT},      /* shell */
 480          {0, 544, IPTOS_LOWDELAY, EMU_KSH},            /* kshell */
 481          {0, 543, IPTOS_LOWDELAY, 0},  /* klogin */
 482          {0, 6667, IPTOS_THROUGHPUT, EMU_IRC}, /* IRC */
 483          {0, 6668, IPTOS_THROUGHPUT, EMU_IRC}, /* IRC undernet */
 484          {0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO }, /* RealAudio control */
 485          {0, 113, IPTOS_LOWDELAY, EMU_IDENT }, /* identd protocol */
 486          {0, 0, 0, 0}
 487};
 488
 489static struct emu_t *tcpemu = NULL;
 490
 491/*
 492 * Return TOS according to the above table
 493 */
 494uint8_t
 495tcp_tos(struct socket *so)
 496{
 497        int i = 0;
 498        struct emu_t *emup;
 499
 500        while(tcptos[i].tos) {
 501                if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
 502                    (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {
 503                        so->so_emu = tcptos[i].emu;
 504                        return tcptos[i].tos;
 505                }
 506                i++;
 507        }
 508
 509        /* Nope, lets see if there's a user-added one */
 510        for (emup = tcpemu; emup; emup = emup->next) {
 511                if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) ||
 512                    (emup->lport && (ntohs(so->so_lport) == emup->lport))) {
 513                        so->so_emu = emup->emu;
 514                        return emup->tos;
 515                }
 516        }
 517
 518        return 0;
 519}
 520
 521/*
 522 * Emulate programs that try and connect to us
 523 * This includes ftp (the data connection is
 524 * initiated by the server) and IRC (DCC CHAT and
 525 * DCC SEND) for now
 526 *
 527 * NOTE: It's possible to crash SLiRP by sending it
 528 * unstandard strings to emulate... if this is a problem,
 529 * more checks are needed here
 530 *
 531 * XXX Assumes the whole command came in one packet
 532 *
 533 * XXX Some ftp clients will have their TOS set to
 534 * LOWDELAY and so Nagel will kick in.  Because of this,
 535 * we'll get the first letter, followed by the rest, so
 536 * we simply scan for ORT instead of PORT...
 537 * DCC doesn't have this problem because there's other stuff
 538 * in the packet before the DCC command.
 539 *
 540 * Return 1 if the mbuf m is still valid and should be
 541 * sbappend()ed
 542 *
 543 * NOTE: if you return 0 you MUST m_free() the mbuf!
 544 */
 545int
 546tcp_emu(struct socket *so, struct mbuf *m)
 547{
 548        Slirp *slirp = so->slirp;
 549        u_int n1, n2, n3, n4, n5, n6;
 550        char buff[257];
 551        uint32_t laddr;
 552        u_int lport;
 553        char *bptr;
 554
 555        DEBUG_CALL("tcp_emu");
 556        DEBUG_ARG("so = %lx", (long)so);
 557        DEBUG_ARG("m = %lx", (long)m);
 558
 559        switch(so->so_emu) {
 560                int x, i;
 561
 562         case EMU_IDENT:
 563                /*
 564                 * Identification protocol as per rfc-1413
 565                 */
 566
 567                {
 568                        struct socket *tmpso;
 569                        struct sockaddr_in addr;
 570                        socklen_t addrlen = sizeof(struct sockaddr_in);
 571                        struct sbuf *so_rcv = &so->so_rcv;
 572
 573                        memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
 574                        so_rcv->sb_wptr += m->m_len;
 575                        so_rcv->sb_rptr += m->m_len;
 576                        m->m_data[m->m_len] = 0; /* NULL terminate */
 577                        if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
 578                                if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
 579                                        HTONS(n1);
 580                                        HTONS(n2);
 581                                        /* n2 is the one on our host */
 582                                        for (tmpso = slirp->tcb.so_next;
 583                                             tmpso != &slirp->tcb;
 584                                             tmpso = tmpso->so_next) {
 585                                                if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
 586                                                    tmpso->so_lport == n2 &&
 587                                                    tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
 588                                                    tmpso->so_fport == n1) {
 589                                                        if (getsockname(tmpso->s,
 590                                                                (struct sockaddr *)&addr, &addrlen) == 0)
 591                                                           n2 = ntohs(addr.sin_port);
 592                                                        break;
 593                                                }
 594                                        }
 595                                }
 596                                so_rcv->sb_cc = snprintf(so_rcv->sb_data,
 597                                                         so_rcv->sb_datalen,
 598                                                         "%d,%d\r\n", n1, n2);
 599                                so_rcv->sb_rptr = so_rcv->sb_data;
 600                                so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
 601                        }
 602                        m_free(m);
 603                        return 0;
 604                }
 605
 606        case EMU_FTP: /* ftp */
 607                *(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */
 608                if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
 609                        /*
 610                         * Need to emulate the PORT command
 611                         */
 612                        x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
 613                                   &n1, &n2, &n3, &n4, &n5, &n6, buff);
 614                        if (x < 6)
 615                           return 1;
 616
 617                        laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
 618                        lport = htons((n5 << 8) | (n6));
 619
 620                        if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
 621                                             lport, SS_FACCEPTONCE)) == NULL) {
 622                           return 1;
 623                        }
 624                        n6 = ntohs(so->so_fport);
 625
 626                        n5 = (n6 >> 8) & 0xff;
 627                        n6 &= 0xff;
 628
 629                        laddr = ntohl(so->so_faddr.s_addr);
 630
 631                        n1 = ((laddr >> 24) & 0xff);
 632                        n2 = ((laddr >> 16) & 0xff);
 633                        n3 = ((laddr >> 8)  & 0xff);
 634                        n4 =  (laddr & 0xff);
 635
 636                        m->m_len = bptr - m->m_data; /* Adjust length */
 637                        m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,
 638                                             "ORT %d,%d,%d,%d,%d,%d\r\n%s",
 639                                             n1, n2, n3, n4, n5, n6, x==7?buff:"");
 640                        return 1;
 641                } else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) {
 642                        /*
 643                         * Need to emulate the PASV response
 644                         */
 645                        x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
 646                                   &n1, &n2, &n3, &n4, &n5, &n6, buff);
 647                        if (x < 6)
 648                           return 1;
 649
 650                        laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
 651                        lport = htons((n5 << 8) | (n6));
 652
 653                        if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
 654                                             lport, SS_FACCEPTONCE)) == NULL) {
 655                           return 1;
 656                        }
 657                        n6 = ntohs(so->so_fport);
 658
 659                        n5 = (n6 >> 8) & 0xff;
 660                        n6 &= 0xff;
 661
 662                        laddr = ntohl(so->so_faddr.s_addr);
 663
 664                        n1 = ((laddr >> 24) & 0xff);
 665                        n2 = ((laddr >> 16) & 0xff);
 666                        n3 = ((laddr >> 8)  & 0xff);
 667                        n4 =  (laddr & 0xff);
 668
 669                        m->m_len = bptr - m->m_data; /* Adjust length */
 670                        m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,
 671                                             "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
 672                                             n1, n2, n3, n4, n5, n6, x==7?buff:"");
 673
 674                        return 1;
 675                }
 676
 677                return 1;
 678
 679         case EMU_KSH:
 680                /*
 681                 * The kshell (Kerberos rsh) and shell services both pass
 682                 * a local port port number to carry signals to the server
 683                 * and stderr to the client.  It is passed at the beginning
 684                 * of the connection as a NUL-terminated decimal ASCII string.
 685                 */
 686                so->so_emu = 0;
 687                for (lport = 0, i = 0; i < m->m_len-1; ++i) {
 688                        if (m->m_data[i] < '0' || m->m_data[i] > '9')
 689                                return 1;       /* invalid number */
 690                        lport *= 10;
 691                        lport += m->m_data[i] - '0';
 692                }
 693                if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
 694                    (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr,
 695                                     htons(lport), SS_FACCEPTONCE)) != NULL)
 696                    m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d",
 697                                        ntohs(so->so_fport)) + 1;
 698                return 1;
 699
 700         case EMU_IRC:
 701                /*
 702                 * Need to emulate DCC CHAT, DCC SEND and DCC MOVE
 703                 */
 704                *(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */
 705                if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
 706                         return 1;
 707
 708                /* The %256s is for the broken mIRC */
 709                if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
 710                        if ((so = tcp_listen(slirp, INADDR_ANY, 0,
 711                                             htonl(laddr), htons(lport),
 712                                             SS_FACCEPTONCE)) == NULL) {
 713                                return 1;
 714                        }
 715                        m->m_len = bptr - m->m_data; /* Adjust length */
 716                        m->m_len += snprintf(bptr, m->m_hdr.mh_size,
 717                                             "DCC CHAT chat %lu %u%c\n",
 718                                             (unsigned long)ntohl(so->so_faddr.s_addr),
 719                                             ntohs(so->so_fport), 1);
 720                } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
 721                        if ((so = tcp_listen(slirp, INADDR_ANY, 0,
 722                                             htonl(laddr), htons(lport),
 723                                             SS_FACCEPTONCE)) == NULL) {
 724                                return 1;
 725                        }
 726                        m->m_len = bptr - m->m_data; /* Adjust length */
 727                        m->m_len += snprintf(bptr, m->m_hdr.mh_size,
 728                                             "DCC SEND %s %lu %u %u%c\n", buff,
 729                                             (unsigned long)ntohl(so->so_faddr.s_addr),
 730                                             ntohs(so->so_fport), n1, 1);
 731                } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
 732                        if ((so = tcp_listen(slirp, INADDR_ANY, 0,
 733                                             htonl(laddr), htons(lport),
 734                                             SS_FACCEPTONCE)) == NULL) {
 735                                return 1;
 736                        }
 737                        m->m_len = bptr - m->m_data; /* Adjust length */
 738                        m->m_len += snprintf(bptr, m->m_hdr.mh_size,
 739                                             "DCC MOVE %s %lu %u %u%c\n", buff,
 740                                             (unsigned long)ntohl(so->so_faddr.s_addr),
 741                                             ntohs(so->so_fport), n1, 1);
 742                }
 743                return 1;
 744
 745         case EMU_REALAUDIO:
 746                /*
 747                 * RealAudio emulation - JP. We must try to parse the incoming
 748                 * data and try to find the two characters that contain the
 749                 * port number. Then we redirect an udp port and replace the
 750                 * number with the real port we got.
 751                 *
 752                 * The 1.0 beta versions of the player are not supported
 753                 * any more.
 754                 *
 755                 * A typical packet for player version 1.0 (release version):
 756                 *
 757                 * 0000:50 4E 41 00 05
 758                 * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 ........g.l.c..P
 759                 * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
 760                 * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
 761                 * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
 762                 *
 763                 * Now the port number 0x1BD7 is found at offset 0x04 of the
 764                 * Now the port number 0x1BD7 is found at offset 0x04 of the
 765                 * second packet. This time we received five bytes first and
 766                 * then the rest. You never know how many bytes you get.
 767                 *
 768                 * A typical packet for player version 2.0 (beta):
 769                 *
 770                 * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA.............
 771                 * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .gux.c..Win2.0.0
 772                 * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
 773                 * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
 774                 * 0040:65 2E 72 61 79 53 00 00 06 36 42                e.rayS...6B
 775                 *
 776                 * Port number 0x1BC1 is found at offset 0x0d.
 777                 *
 778                 * This is just a horrible switch statement. Variable ra tells
 779                 * us where we're going.
 780                 */
 781
 782                bptr = m->m_data;
 783                while (bptr < m->m_data + m->m_len) {
 784                        u_short p;
 785                        static int ra = 0;
 786                        char ra_tbl[4];
 787
 788                        ra_tbl[0] = 0x50;
 789                        ra_tbl[1] = 0x4e;
 790                        ra_tbl[2] = 0x41;
 791                        ra_tbl[3] = 0;
 792
 793                        switch (ra) {
 794                         case 0:
 795                         case 2:
 796                         case 3:
 797                                if (*bptr++ != ra_tbl[ra]) {
 798                                        ra = 0;
 799                                        continue;
 800                                }
 801                                break;
 802
 803                         case 1:
 804                                /*
 805                                 * We may get 0x50 several times, ignore them
 806                                 */
 807                                if (*bptr == 0x50) {
 808                                        ra = 1;
 809                                        bptr++;
 810                                        continue;
 811                                } else if (*bptr++ != ra_tbl[ra]) {
 812                                        ra = 0;
 813                                        continue;
 814                                }
 815                                break;
 816
 817                         case 4:
 818                                /*
 819                                 * skip version number
 820                                 */
 821                                bptr++;
 822                                break;
 823
 824                         case 5:
 825                                /*
 826                                 * The difference between versions 1.0 and
 827                                 * 2.0 is here. For future versions of
 828                                 * the player this may need to be modified.
 829                                 */
 830                                if (*(bptr + 1) == 0x02)
 831                                   bptr += 8;
 832                                else
 833                                   bptr += 4;
 834                                break;
 835
 836                         case 6:
 837                                /* This is the field containing the port
 838                                 * number that RA-player is listening to.
 839                                 */
 840                                lport = (((u_char*)bptr)[0] << 8)
 841                                + ((u_char *)bptr)[1];
 842                                if (lport < 6970)
 843                                   lport += 256;   /* don't know why */
 844                                if (lport < 6970 || lport > 7170)
 845                                   return 1;       /* failed */
 846
 847                                /* try to get udp port between 6970 - 7170 */
 848                                for (p = 6970; p < 7071; p++) {
 849                                        if (udp_listen(slirp, INADDR_ANY,
 850                                                       htons(p),
 851                                                       so->so_laddr.s_addr,
 852                                                       htons(lport),
 853                                                       SS_FACCEPTONCE)) {
 854                                                break;
 855                                        }
 856                                }
 857                                if (p == 7071)
 858                                   p = 0;
 859                                *(u_char *)bptr++ = (p >> 8) & 0xff;
 860                                *(u_char *)bptr = p & 0xff;
 861                                ra = 0;
 862                                return 1;   /* port redirected, we're done */
 863                                break;
 864
 865                         default:
 866                                ra = 0;
 867                        }
 868                        ra++;
 869                }
 870                return 1;
 871
 872         default:
 873                /* Ooops, not emulated, won't call tcp_emu again */
 874                so->so_emu = 0;
 875                return 1;
 876        }
 877}
 878
 879/*
 880 * Do misc. config of SLiRP while its running.
 881 * Return 0 if this connections is to be closed, 1 otherwise,
 882 * return 2 if this is a command-line connection
 883 */
 884int tcp_ctl(struct socket *so)
 885{
 886    Slirp *slirp = so->slirp;
 887    struct sbuf *sb = &so->so_snd;
 888    struct ex_list *ex_ptr;
 889    int do_pty;
 890
 891    DEBUG_CALL("tcp_ctl");
 892    DEBUG_ARG("so = %lx", (long )so);
 893
 894    if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
 895        /* Check if it's pty_exec */
 896        for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
 897            if (ex_ptr->ex_fport == so->so_fport &&
 898                so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
 899                if (ex_ptr->ex_pty == 3) {
 900                    so->s = -1;
 901                    so->extra = (void *)ex_ptr->ex_exec;
 902                    return 1;
 903                }
 904                do_pty = ex_ptr->ex_pty;
 905                DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
 906                return fork_exec(so, ex_ptr->ex_exec, do_pty);
 907            }
 908        }
 909    }
 910    sb->sb_cc =
 911        snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),
 912                 "Error: No application configured.\r\n");
 913    sb->sb_wptr += sb->sb_cc;
 914    return 0;
 915}
 916