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