~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to slirp/tcp_subr.c

  • Committer: Blue Swirl
  • Date: 2009-08-31 15:14:40 UTC
  • Revision ID: git-v1:528e93a9787ccfc59582a44035f5f342caf5b84f
Fix breakage due to __thread

Thread-local storage is not supported on all hosts.

Signed-off-by: Blue Swirl <blauwirbel@gmail.com>

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
11
 *    notice, this list of conditions and the following disclaimer in the
12
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
 
13
 * 3. Neither the name of the University nor the names of its contributors
18
14
 *    may be used to endorse or promote products derived from this software
19
15
 *    without specific prior written permission.
20
16
 *
42
38
 * terms and conditions of the copyright.
43
39
 */
44
40
 
45
 
#define WANT_SYS_IOCTL_H
46
41
#include <slirp.h>
47
42
 
48
43
/* patchable/settable parameters for tcp */
53
48
 * Tcp initialization
54
49
 */
55
50
void
56
 
tcp_init()
 
51
tcp_init(Slirp *slirp)
57
52
{
58
 
        tcp_iss = 1;            /* wrong */
59
 
        tcb.so_next = tcb.so_prev = &tcb;
 
53
    slirp->tcp_iss = 1;         /* wrong */
 
54
    slirp->tcb.so_next = slirp->tcb.so_prev = &slirp->tcb;
 
55
    slirp->tcp_last_so = &slirp->tcb;
60
56
}
61
57
 
62
58
/*
65
61
 * in a skeletal tcp/ip header, minimizing the amount of work
66
62
 * necessary when the connection is used.
67
63
 */
68
 
/* struct tcpiphdr * */
69
64
void
70
 
tcp_template(tp)
71
 
        struct tcpcb *tp;
 
65
tcp_template(struct tcpcb *tp)
72
66
{
73
67
        struct socket *so = tp->t_socket;
74
68
        register struct tcpiphdr *n = &tp->t_template;
75
69
 
76
 
        n->ti_next = n->ti_prev = 0;
 
70
        n->ti_mbuf = NULL;
77
71
        n->ti_x1 = 0;
78
72
        n->ti_pr = IPPROTO_TCP;
79
73
        n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip));
106
100
 * segment are as specified by the parameters.
107
101
 */
108
102
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;
 
103
tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
 
104
            tcp_seq ack, tcp_seq seq, int flags)
115
105
{
116
106
        register int tlen;
117
107
        int win = 0;
126
116
 
127
117
        if (tp)
128
118
                win = sbspace(&tp->t_socket->so_rcv);
129
 
        if (m == 0) {
130
 
                if ((m = m_get()) == NULL)
 
119
        if (m == NULL) {
 
120
                if ((m = m_get(tp->t_socket->slirp)) == NULL)
131
121
                        return;
132
 
#ifdef TCP_COMPAT_42
133
 
                tlen = 1;
134
 
#else
135
122
                tlen = 0;
136
 
#endif
137
123
                m->m_data += IF_MAXLINKHDR;
138
124
                *mtod(m, struct tcpiphdr *) = *ti;
139
125
                ti = mtod(m, struct tcpiphdr *);
156
142
        tlen += sizeof (struct tcpiphdr);
157
143
        m->m_len = tlen;
158
144
 
159
 
        ti->ti_next = ti->ti_prev = 0;
 
145
        ti->ti_mbuf = NULL;
160
146
        ti->ti_x1 = 0;
161
147
        ti->ti_seq = htonl(seq);
162
148
        ti->ti_ack = htonl(ack);
186
172
 * protocol control block.
187
173
 */
188
174
struct tcpcb *
189
 
tcp_newtcpcb(so)
190
 
        struct socket *so;
 
175
tcp_newtcpcb(struct socket *so)
191
176
{
192
177
        register struct tcpcb *tp;
193
178
 
196
181
                return ((struct tcpcb *)0);
197
182
 
198
183
        memset((char *) tp, 0, sizeof(struct tcpcb));
199
 
        tp->seg_next = tp->seg_prev = (tcpiphdrp_32)tp;
 
184
        tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
200
185
        tp->t_maxseg = TCP_MSS;
201
186
 
202
187
        tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
231
216
 */
232
217
struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
233
218
{
234
 
/* tcp_drop(tp, errno)
235
 
        register struct tcpcb *tp;
236
 
        int errno;
237
 
{
238
 
*/
239
 
 
240
219
        DEBUG_CALL("tcp_drop");
241
220
        DEBUG_ARG("tp = %lx", (long)tp);
242
221
        DEBUG_ARG("errno = %d", errno);
244
223
        if (TCPS_HAVERCVDSYN(tp->t_state)) {
245
224
                tp->t_state = TCPS_CLOSED;
246
225
                (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; */
 
226
        }
254
227
        return (tcp_close(tp));
255
228
}
256
229
 
261
234
 *      wake up any sleepers
262
235
 */
263
236
struct tcpcb *
264
 
tcp_close(tp)
265
 
        register struct tcpcb *tp;
 
237
tcp_close(struct tcpcb *tp)
266
238
{
267
239
        register struct tcpiphdr *t;
268
240
        struct socket *so = tp->t_socket;
 
241
        Slirp *slirp = so->slirp;
269
242
        register struct mbuf *m;
270
243
 
271
244
        DEBUG_CALL("tcp_close");
272
245
        DEBUG_ARG("tp = %lx", (long )tp);
273
246
 
274
247
        /* 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);
 
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)));
280
253
                m_freem(m);
281
254
        }
282
 
        /* It's static */
283
 
/*      if (tp->t_template)
284
 
 *              (void) m_free(dtom(tp->t_template));
285
 
 */
286
 
/*      free(tp, M_PCB);  */
287
255
        free(tp);
288
 
        so->so_tcpcb = 0;
289
 
        soisfdisconnected(so);
 
256
        so->so_tcpcb = NULL;
290
257
        /* clobber input socket cache if we're closing the cached connection */
291
 
        if (so == tcp_last_so)
292
 
                tcp_last_so = &tcb;
 
258
        if (so == slirp->tcp_last_so)
 
259
                slirp->tcp_last_so = &slirp->tcb;
293
260
        closesocket(so->s);
294
261
        sbfree(&so->so_rcv);
295
262
        sbfree(&so->so_snd);
296
263
        sofree(so);
297
 
        STAT(tcpstat.tcps_closed++);
298
264
        return ((struct tcpcb *)0);
299
265
}
300
266
 
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
267
/*
326
268
 * TCP protocol interface to socket abstraction.
327
269
 */
337
279
 * We can let the user exit from the close as soon as the FIN is acked.
338
280
 */
339
281
void
340
 
tcp_sockclosed(tp)
341
 
        struct tcpcb *tp;
 
282
tcp_sockclosed(struct tcpcb *tp)
342
283
{
343
284
 
344
285
        DEBUG_CALL("tcp_sockclosed");
362
303
                tp->t_state = TCPS_LAST_ACK;
363
304
                break;
364
305
        }
365
 
/*      soisfdisconnecting(tp->t_socket); */
366
 
        if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
367
 
                soisfdisconnected(tp->t_socket);
368
306
        if (tp)
369
307
                tcp_output(tp);
370
308
}
379
317
 * nonblocking.  Connect returns after the SYN is sent, and does
380
318
 * not wait for ACK+SYN.
381
319
 */
382
 
int tcp_fconnect(so)
383
 
     struct socket *so;
 
320
int tcp_fconnect(struct socket *so)
384
321
{
 
322
  Slirp *slirp = so->slirp;
385
323
  int ret=0;
386
324
 
387
325
  DEBUG_CALL("tcp_fconnect");
398
336
    setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(opt ));
399
337
 
400
338
    addr.sin_family = AF_INET;
401
 
    if ((so->so_faddr.s_addr & htonl(0xffffff00)) == special_addr.s_addr) {
 
339
    if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
 
340
        slirp->vnetwork_addr.s_addr) {
402
341
      /* 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:
 
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 {
409
346
        addr.sin_addr = loopback_addr;
410
 
        break;
411
347
      }
412
348
    } else
413
349
      addr.sin_addr = so->so_faddr;
442
378
 * here and SYN the local-host.
443
379
 */
444
380
void
445
 
tcp_connect(inso)
446
 
        struct socket *inso;
 
381
tcp_connect(struct socket *inso)
447
382
{
 
383
        Slirp *slirp = inso->slirp;
448
384
        struct socket *so;
449
385
        struct sockaddr_in addr;
450
 
        int addrlen = sizeof(struct sockaddr_in);
 
386
        socklen_t addrlen = sizeof(struct sockaddr_in);
451
387
        struct tcpcb *tp;
452
388
        int s, opt;
453
389
 
462
398
                /* FACCEPTONCE already have a tcpcb */
463
399
                so = inso;
464
400
        } else {
465
 
                if ((so = socreate()) == NULL) {
 
401
                if ((so = socreate(slirp)) == NULL) {
466
402
                        /* If it failed, get rid of the pending connection */
467
403
                        closesocket(accept(inso->s,(struct sockaddr *)&addr,&addrlen));
468
404
                        return;
493
429
        so->so_faddr = addr.sin_addr;
494
430
        /* Translate connections from localhost to the real hostname */
495
431
        if (so->so_faddr.s_addr == 0 || so->so_faddr.s_addr == loopback_addr.s_addr)
496
 
           so->so_faddr = alias_addr;
 
432
           so->so_faddr = slirp->vhost_addr;
497
433
 
498
434
        /* Close the accept() socket, set right state */
499
435
        if (inso->so_state & SS_FACCEPTONCE) {
502
438
                                           /* if it's not FACCEPTONCE, it's already NOFDREF */
503
439
        }
504
440
        so->s = s;
 
441
        so->so_state |= SS_INCOMING;
505
442
 
506
443
        so->so_iptos = tcp_tos(so);
507
444
        tp = sototcpcb(so);
508
445
 
509
446
        tcp_template(tp);
510
447
 
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
448
        tp->t_state = TCPS_SYN_SENT;
521
449
        tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
522
 
        tp->iss = tcp_iss;
523
 
        tcp_iss += TCP_ISSINCR/2;
 
450
        tp->iss = slirp->tcp_iss;
 
451
        slirp->tcp_iss += TCP_ISSINCR/2;
524
452
        tcp_sendseqinit(tp);
525
453
        tcp_output(tp);
526
454
}
529
457
 * Attach a TCPCB to a socket.
530
458
 */
531
459
int
532
 
tcp_attach(so)
533
 
        struct socket *so;
 
460
tcp_attach(struct socket *so)
534
461
{
535
462
        if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
536
463
           return -1;
537
464
 
538
 
        insque(so, &tcb);
 
465
        insque(so, &so->slirp->tcb);
539
466
 
540
467
        return 0;
541
468
}
559
486
          {0, 0, 0, 0}
560
487
};
561
488
 
562
 
#ifdef CONFIG_QEMU
563
 
static
564
 
#endif
565
 
struct emu_t *tcpemu = 0;
 
489
static struct emu_t *tcpemu = NULL;
566
490
 
567
491
/*
568
492
 * Return TOS according to the above table
569
493
 */
570
494
u_int8_t
571
 
tcp_tos(so)
572
 
        struct socket *so;
 
495
tcp_tos(struct socket *so)
573
496
{
574
497
        int i = 0;
575
498
        struct emu_t *emup;
595
518
        return 0;
596
519
}
597
520
 
598
 
#if 0
599
 
int do_echo = -1;
600
 
#endif
601
 
 
602
521
/*
603
522
 * Emulate programs that try and connect to us
604
523
 * This includes ftp (the data connection is
624
543
 * NOTE: if you return 0 you MUST m_free() the mbuf!
625
544
 */
626
545
int
627
 
tcp_emu(so, m)
628
 
        struct socket *so;
629
 
        struct mbuf *m;
 
546
tcp_emu(struct socket *so, struct mbuf *m)
630
547
{
 
548
        Slirp *slirp = so->slirp;
631
549
        u_int n1, n2, n3, n4, n5, n6;
632
 
        char buff[256];
 
550
        char buff[257];
633
551
        u_int32_t laddr;
634
552
        u_int lport;
635
553
        char *bptr;
649
567
                {
650
568
                        struct socket *tmpso;
651
569
                        struct sockaddr_in addr;
652
 
                        int addrlen = sizeof(struct sockaddr_in);
 
570
                        socklen_t addrlen = sizeof(struct sockaddr_in);
653
571
                        struct sbuf *so_rcv = &so->so_rcv;
654
572
 
655
573
                        memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
661
579
                                        HTONS(n1);
662
580
                                        HTONS(n2);
663
581
                                        /* n2 is the one on our host */
664
 
                                        for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
 
582
                                        for (tmpso = slirp->tcb.so_next;
 
583
                                             tmpso != &slirp->tcb;
 
584
                                             tmpso = tmpso->so_next) {
665
585
                                                if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
666
586
                                                    tmpso->so_lport == n2 &&
667
587
                                                    tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
673
593
                                                }
674
594
                                        }
675
595
                                }
676
 
                                so_rcv->sb_cc = sprintf(so_rcv->sb_data, "%d,%d\r\n", n1, n2);
 
596
                                so_rcv->sb_cc = snprintf(so_rcv->sb_data,
 
597
                                                         so_rcv->sb_datalen,
 
598
                                                         "%d,%d\r\n", n1, n2);
677
599
                                so_rcv->sb_rptr = so_rcv->sb_data;
678
600
                                so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
679
601
                        }
681
603
                        return 0;
682
604
                }
683
605
 
684
 
#if 0
685
 
         case EMU_RLOGIN:
686
 
                /*
687
 
                 * Rlogin emulation
688
 
                 * First we accumulate all the initial option negotiation,
689
 
                 * then fork_exec() rlogin according to the  options
690
 
                 */
691
 
                {
692
 
                        int i, i2, n;
693
 
                        char *ptr;
694
 
                        char args[100];
695
 
                        char term[100];
696
 
                        struct sbuf *so_snd = &so->so_snd;
697
 
                        struct sbuf *so_rcv = &so->so_rcv;
698
 
 
699
 
                        /* First check if they have a priveladged port, or too much data has arrived */
700
 
                        if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
701
 
                            (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
702
 
                                memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
703
 
                                so_snd->sb_wptr += 18;
704
 
                                so_snd->sb_cc += 18;
705
 
                                tcp_sockclosed(sototcpcb(so));
706
 
                                m_free(m);
707
 
                                return 0;
708
 
                        }
709
 
 
710
 
                        /* Append the current data */
711
 
                        memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
712
 
                        so_rcv->sb_wptr += m->m_len;
713
 
                        so_rcv->sb_rptr += m->m_len;
714
 
                        m_free(m);
715
 
 
716
 
                        /*
717
 
                         * Check if we have all the initial options,
718
 
                         * and build argument list to rlogin while we're here
719
 
                         */
720
 
                        n = 0;
721
 
                        ptr = so_rcv->sb_data;
722
 
                        args[0] = 0;
723
 
                        term[0] = 0;
724
 
                        while (ptr < so_rcv->sb_wptr) {
725
 
                                if (*ptr++ == 0) {
726
 
                                        n++;
727
 
                                        if (n == 2) {
728
 
                                                sprintf(args, "rlogin -l %s %s",
729
 
                                                        ptr, inet_ntoa(so->so_faddr));
730
 
                                        } else if (n == 3) {
731
 
                                                i2 = so_rcv->sb_wptr - ptr;
732
 
                                                for (i = 0; i < i2; i++) {
733
 
                                                        if (ptr[i] == '/') {
734
 
                                                                ptr[i] = 0;
735
 
#ifdef HAVE_SETENV
736
 
                                                                sprintf(term, "%s", ptr);
737
 
#else
738
 
                                                                sprintf(term, "TERM=%s", ptr);
739
 
#endif
740
 
                                                                ptr[i] = '/';
741
 
                                                                break;
742
 
                                                        }
743
 
                                                }
744
 
                                        }
745
 
                                }
746
 
                        }
747
 
 
748
 
                        if (n != 4)
749
 
                           return 0;
750
 
 
751
 
                        /* We have it, set our term variable and fork_exec() */
752
 
#ifdef HAVE_SETENV
753
 
                        setenv("TERM", term, 1);
754
 
#else
755
 
                        putenv(term);
756
 
#endif
757
 
                        fork_exec(so, args, 2);
758
 
                        term[0] = 0;
759
 
                        so->so_emu = 0;
760
 
 
761
 
                        /* And finally, send the client a 0 character */
762
 
                        so_snd->sb_wptr[0] = 0;
763
 
                        so_snd->sb_wptr++;
764
 
                        so_snd->sb_cc++;
765
 
 
766
 
                        return 0;
767
 
                }
768
 
 
769
 
         case EMU_RSH:
770
 
                /*
771
 
                 * rsh emulation
772
 
                 * First we accumulate all the initial option negotiation,
773
 
                 * then rsh_exec() rsh according to the  options
774
 
                 */
775
 
                {
776
 
                        int  n;
777
 
                        char *ptr;
778
 
                        char *user;
779
 
                        char *args;
780
 
                        struct sbuf *so_snd = &so->so_snd;
781
 
                        struct sbuf *so_rcv = &so->so_rcv;
782
 
 
783
 
                        /* First check if they have a priveladged port, or too much data has arrived */
784
 
                        if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 ||
785
 
                            (m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) {
786
 
                                memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
787
 
                                so_snd->sb_wptr += 18;
788
 
                                so_snd->sb_cc += 18;
789
 
                                tcp_sockclosed(sototcpcb(so));
790
 
                                m_free(m);
791
 
                                return 0;
792
 
                        }
793
 
 
794
 
                        /* Append the current data */
795
 
                        memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
796
 
                        so_rcv->sb_wptr += m->m_len;
797
 
                        so_rcv->sb_rptr += m->m_len;
798
 
                        m_free(m);
799
 
 
800
 
                        /*
801
 
                         * Check if we have all the initial options,
802
 
                         * and build argument list to rlogin while we're here
803
 
                         */
804
 
                        n = 0;
805
 
                        ptr = so_rcv->sb_data;
806
 
                        user="";
807
 
                        args="";
808
 
                        if (so->extra==NULL) {
809
 
                                struct socket *ns;
810
 
                                struct tcpcb* tp;
811
 
                                int port=atoi(ptr);
812
 
                                if (port <= 0) return 0;
813
 
                if (port > 1023 || port < 512) {
814
 
                  memcpy(so_snd->sb_wptr, "Permission denied\n", 18);
815
 
                  so_snd->sb_wptr += 18;
816
 
                  so_snd->sb_cc += 18;
817
 
                  tcp_sockclosed(sototcpcb(so));
818
 
                  return 0;
819
 
                }
820
 
                                if ((ns=socreate()) == NULL)
821
 
                  return 0;
822
 
                                if (tcp_attach(ns)<0) {
823
 
                  free(ns);
824
 
                  return 0;
825
 
                                }
826
 
 
827
 
                                ns->so_laddr=so->so_laddr;
828
 
                                ns->so_lport=htons(port);
829
 
 
830
 
                                (void) tcp_mss(sototcpcb(ns), 0);
831
 
 
832
 
                                ns->so_faddr=so->so_faddr;
833
 
                                ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */
834
 
 
835
 
                                if (ns->so_faddr.s_addr == 0 ||
836
 
                                        ns->so_faddr.s_addr == loopback_addr.s_addr)
837
 
                  ns->so_faddr = alias_addr;
838
 
 
839
 
                                ns->so_iptos = tcp_tos(ns);
840
 
                                tp = sototcpcb(ns);
841
 
 
842
 
                                tcp_template(tp);
843
 
 
844
 
                                /* Compute window scaling to request.  */
845
 
                                /*      while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
846
 
                                 *              (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
847
 
                                 *              tp->request_r_scale++;
848
 
                                 */
849
 
 
850
 
                /*soisfconnecting(ns);*/
851
 
 
852
 
                                STAT(tcpstat.tcps_connattempt++);
853
 
 
854
 
                                tp->t_state = TCPS_SYN_SENT;
855
 
                                tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
856
 
                                tp->iss = tcp_iss;
857
 
                                tcp_iss += TCP_ISSINCR/2;
858
 
                                tcp_sendseqinit(tp);
859
 
                                tcp_output(tp);
860
 
                                so->extra=ns;
861
 
                        }
862
 
                        while (ptr < so_rcv->sb_wptr) {
863
 
              if (*ptr++ == 0) {
864
 
                n++;
865
 
                if (n == 2) {
866
 
                  user=ptr;
867
 
                } else if (n == 3) {
868
 
                  args=ptr;
869
 
                }
870
 
              }
871
 
                        }
872
 
 
873
 
                        if (n != 4)
874
 
              return 0;
875
 
 
876
 
                        rsh_exec(so,so->extra, user, inet_ntoa(so->so_faddr), args);
877
 
                        so->so_emu = 0;
878
 
                        so->extra=NULL;
879
 
 
880
 
                        /* And finally, send the client a 0 character */
881
 
                        so_snd->sb_wptr[0] = 0;
882
 
                        so_snd->sb_wptr++;
883
 
                        so_snd->sb_cc++;
884
 
 
885
 
                        return 0;
886
 
                }
887
 
 
888
 
         case EMU_CTL:
889
 
                {
890
 
                        int num;
891
 
                        struct sbuf *so_snd = &so->so_snd;
892
 
                        struct sbuf *so_rcv = &so->so_rcv;
893
 
 
894
 
                        /*
895
 
                         * If there is binary data here, we save it in so->so_m
896
 
                         */
897
 
                        if (!so->so_m) {
898
 
                          int rxlen;
899
 
                          char *rxdata;
900
 
                          rxdata=mtod(m, char *);
901
 
                          for (rxlen=m->m_len; rxlen; rxlen--) {
902
 
                            if (*rxdata++ & 0x80) {
903
 
                              so->so_m = m;
904
 
                              return 0;
905
 
                            }
906
 
                          }
907
 
                        } /* if(so->so_m==NULL) */
908
 
 
909
 
                        /*
910
 
                         * Append the line
911
 
                         */
912
 
                        sbappendsb(so_rcv, m);
913
 
 
914
 
                        /* To avoid going over the edge of the buffer, we reset it */
915
 
                        if (so_snd->sb_cc == 0)
916
 
                           so_snd->sb_wptr = so_snd->sb_rptr = so_snd->sb_data;
917
 
 
918
 
                        /*
919
 
                         * A bit of a hack:
920
 
                         * If the first packet we get here is 1 byte long, then it
921
 
                         * was done in telnet character mode, therefore we must echo
922
 
                         * the characters as they come.  Otherwise, we echo nothing,
923
 
                         * because in linemode, the line is already echoed
924
 
                         * XXX two or more control connections won't work
925
 
                         */
926
 
                        if (do_echo == -1) {
927
 
                                if (m->m_len == 1) do_echo = 1;
928
 
                                else do_echo = 0;
929
 
                        }
930
 
                        if (do_echo) {
931
 
                          sbappendsb(so_snd, m);
932
 
                          m_free(m);
933
 
                          tcp_output(sototcpcb(so)); /* XXX */
934
 
                        } else
935
 
                          m_free(m);
936
 
 
937
 
                        num = 0;
938
 
                        while (num < so->so_rcv.sb_cc) {
939
 
                                if (*(so->so_rcv.sb_rptr + num) == '\n' ||
940
 
                                    *(so->so_rcv.sb_rptr + num) == '\r') {
941
 
                                        int n;
942
 
 
943
 
                                        *(so_rcv->sb_rptr + num) = 0;
944
 
                                        if (ctl_password && !ctl_password_ok) {
945
 
                                                /* Need a password */
946
 
                                                if (sscanf(so_rcv->sb_rptr, "pass %256s", buff) == 1) {
947
 
                                                        if (strcmp(buff, ctl_password) == 0) {
948
 
                                                                ctl_password_ok = 1;
949
 
                                                                n = sprintf(so_snd->sb_wptr,
950
 
                                                                            "Password OK.\r\n");
951
 
                                                                goto do_prompt;
952
 
                                                        }
953
 
                                                }
954
 
                                                n = sprintf(so_snd->sb_wptr,
955
 
                                         "Error: Password required, log on with \"pass PASSWORD\"\r\n");
956
 
                                                goto do_prompt;
957
 
                                        }
958
 
                                        cfg_quitting = 0;
959
 
                                        n = do_config(so_rcv->sb_rptr, so, PRN_SPRINTF);
960
 
                                        if (!cfg_quitting) {
961
 
                                                /* Register the printed data */
962
 
do_prompt:
963
 
                                                so_snd->sb_cc += n;
964
 
                                                so_snd->sb_wptr += n;
965
 
                                                /* Add prompt */
966
 
                                                n = sprintf(so_snd->sb_wptr, "Slirp> ");
967
 
                                                so_snd->sb_cc += n;
968
 
                                                so_snd->sb_wptr += n;
969
 
                                        }
970
 
                                        /* Drop so_rcv data */
971
 
                                        so_rcv->sb_cc = 0;
972
 
                                        so_rcv->sb_wptr = so_rcv->sb_rptr = so_rcv->sb_data;
973
 
                                        tcp_output(sototcpcb(so)); /* Send the reply */
974
 
                                }
975
 
                                num++;
976
 
                        }
977
 
                        return 0;
978
 
                }
979
 
#endif
980
606
        case EMU_FTP: /* ftp */
981
 
                *(m->m_data+m->m_len) = 0; /* NULL terminate for strstr */
 
607
                *(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */
982
608
                if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
983
609
                        /*
984
610
                         * Need to emulate the PORT command
991
617
                        laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
992
618
                        lport = htons((n5 << 8) | (n6));
993
619
 
994
 
                        if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
 
620
                        if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
 
621
                                             lport, SS_FACCEPTONCE)) == NULL) {
995
622
                           return 1;
996
 
 
 
623
                        }
997
624
                        n6 = ntohs(so->so_fport);
998
625
 
999
626
                        n5 = (n6 >> 8) & 0xff;
1007
634
                        n4 =  (laddr & 0xff);
1008
635
 
1009
636
                        m->m_len = bptr - m->m_data; /* Adjust length */
1010
 
                        m->m_len += sprintf(bptr,"ORT %d,%d,%d,%d,%d,%d\r\n%s",
1011
 
                                            n1, n2, n3, n4, n5, n6, x==7?buff:"");
 
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:"");
1012
640
                        return 1;
1013
641
                } else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) {
1014
642
                        /*
1022
650
                        laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
1023
651
                        lport = htons((n5 << 8) | (n6));
1024
652
 
1025
 
                        if ((so = solisten(0, laddr, lport, SS_FACCEPTONCE)) == NULL)
 
653
                        if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
 
654
                                             lport, SS_FACCEPTONCE)) == NULL) {
1026
655
                           return 1;
1027
 
 
 
656
                        }
1028
657
                        n6 = ntohs(so->so_fport);
1029
658
 
1030
659
                        n5 = (n6 >> 8) & 0xff;
1038
667
                        n4 =  (laddr & 0xff);
1039
668
 
1040
669
                        m->m_len = bptr - m->m_data; /* Adjust length */
1041
 
                        m->m_len += sprintf(bptr,"27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
1042
 
                                            n1, n2, n3, n4, n5, n6, x==7?buff:"");
 
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:"");
1043
673
 
1044
674
                        return 1;
1045
675
                }
1061
691
                        lport += m->m_data[i] - '0';
1062
692
                }
1063
693
                if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
1064
 
                    (so = solisten(0, so->so_laddr.s_addr, htons(lport), SS_FACCEPTONCE)) != NULL)
1065
 
                        m->m_len = sprintf(m->m_data, "%d", ntohs(so->so_fport))+1;
 
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;
1066
698
                return 1;
1067
699
 
1068
700
         case EMU_IRC:
1075
707
 
1076
708
                /* The %256s is for the broken mIRC */
1077
709
                if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
1078
 
                        if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 
710
                        if ((so = tcp_listen(slirp, INADDR_ANY, 0,
 
711
                                             htonl(laddr), htons(lport),
 
712
                                             SS_FACCEPTONCE)) == NULL) {
1079
713
                                return 1;
1080
 
 
 
714
                        }
1081
715
                        m->m_len = bptr - m->m_data; /* Adjust length */
1082
 
                        m->m_len += sprintf(bptr, "DCC CHAT chat %lu %u%c\n",
1083
 
                             (unsigned long)ntohl(so->so_faddr.s_addr),
1084
 
                             ntohs(so->so_fport), 1);
 
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);
1085
720
                } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
1086
 
                        if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 
721
                        if ((so = tcp_listen(slirp, INADDR_ANY, 0,
 
722
                                             htonl(laddr), htons(lport),
 
723
                                             SS_FACCEPTONCE)) == NULL) {
1087
724
                                return 1;
1088
 
 
 
725
                        }
1089
726
                        m->m_len = bptr - m->m_data; /* Adjust length */
1090
 
                        m->m_len += sprintf(bptr, "DCC SEND %s %lu %u %u%c\n",
1091
 
                              buff, (unsigned long)ntohl(so->so_faddr.s_addr),
1092
 
                              ntohs(so->so_fport), n1, 1);
 
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);
1093
731
                } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
1094
 
                        if ((so = solisten(0, htonl(laddr), htons(lport), SS_FACCEPTONCE)) == NULL)
 
732
                        if ((so = tcp_listen(slirp, INADDR_ANY, 0,
 
733
                                             htonl(laddr), htons(lport),
 
734
                                             SS_FACCEPTONCE)) == NULL) {
1095
735
                                return 1;
1096
 
 
 
736
                        }
1097
737
                        m->m_len = bptr - m->m_data; /* Adjust length */
1098
 
                        m->m_len += sprintf(bptr, "DCC MOVE %s %lu %u %u%c\n",
1099
 
                              buff, (unsigned long)ntohl(so->so_faddr.s_addr),
1100
 
                              ntohs(so->so_fport), n1, 1);
 
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);
1101
742
                }
1102
743
                return 1;
1103
744
 
1114
755
                 * A typical packet for player version 1.0 (release version):
1115
756
                 *
1116
757
                 * 0000:50 4E 41 00 05
1117
 
                 * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....�..g�l�c..P
 
758
                 * 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 ........g.l.c..P
1118
759
                 * 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH
1119
760
                 * 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v
1120
761
                 * 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB
1126
767
                 *
1127
768
                 * A typical packet for player version 2.0 (beta):
1128
769
                 *
1129
 
                 * 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........�.
1130
 
                 * 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .gux�c..Win2.0.0
 
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
1131
772
                 * 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/
1132
773
                 * 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas
1133
774
                 * 0040:65 2E 72 61 79 53 00 00 06 36 42                e.rayS...6B
1205
846
 
1206
847
                                /* try to get udp port between 6970 - 7170 */
1207
848
                                for (p = 6970; p < 7071; p++) {
1208
 
                                        if (udp_listen( htons(p),
 
849
                                        if (udp_listen(slirp, INADDR_ANY,
 
850
                                                       htons(p),
1209
851
                                                       so->so_laddr.s_addr,
1210
852
                                                       htons(lport),
1211
853
                                                       SS_FACCEPTONCE)) {
1239
881
 * Return 0 if this connections is to be closed, 1 otherwise,
1240
882
 * return 2 if this is a command-line connection
1241
883
 */
1242
 
int
1243
 
tcp_ctl(so)
1244
 
        struct socket *so;
 
884
int tcp_ctl(struct socket *so)
1245
885
{
1246
 
        struct sbuf *sb = &so->so_snd;
1247
 
        int command;
1248
 
        struct ex_list *ex_ptr;
1249
 
        int do_pty;
1250
 
        //      struct socket *tmpso;
1251
 
 
1252
 
        DEBUG_CALL("tcp_ctl");
1253
 
        DEBUG_ARG("so = %lx", (long )so);
1254
 
 
1255
 
#if 0
1256
 
        /*
1257
 
         * Check if they're authorised
1258
 
         */
1259
 
        if (ctl_addr.s_addr && (ctl_addr.s_addr == -1 || (so->so_laddr.s_addr != ctl_addr.s_addr))) {
1260
 
                sb->sb_cc = sprintf(sb->sb_wptr,"Error: Permission denied.\r\n");
1261
 
                sb->sb_wptr += sb->sb_cc;
1262
 
                return 0;
1263
 
        }
1264
 
#endif
1265
 
        command = (ntohl(so->so_faddr.s_addr) & 0xff);
1266
 
 
1267
 
        switch(command) {
1268
 
        default: /* Check for exec's */
1269
 
 
1270
 
                /*
1271
 
                 * Check if it's pty_exec
1272
 
                 */
1273
 
                for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
1274
 
                        if (ex_ptr->ex_fport == so->so_fport &&
1275
 
                            command == ex_ptr->ex_addr) {
1276
 
                                do_pty = ex_ptr->ex_pty;
1277
 
                                goto do_exec;
1278
 
                        }
1279
 
                }
1280
 
 
1281
 
                /*
1282
 
                 * Nothing bound..
1283
 
                 */
1284
 
                /* tcp_fconnect(so); */
1285
 
 
1286
 
                /* FALLTHROUGH */
1287
 
        case CTL_ALIAS:
1288
 
          sb->sb_cc = sprintf(sb->sb_wptr,
1289
 
                              "Error: No application configured.\r\n");
1290
 
          sb->sb_wptr += sb->sb_cc;
1291
 
          return(0);
1292
 
 
1293
 
        do_exec:
1294
 
                DEBUG_MISC((dfd, " executing %s \n",ex_ptr->ex_exec));
1295
 
                return(fork_exec(so, ex_ptr->ex_exec, do_pty));
1296
 
 
1297
 
#if 0
1298
 
        case CTL_CMD:
1299
 
           for (tmpso = tcb.so_next; tmpso != &tcb; tmpso = tmpso->so_next) {
1300
 
             if (tmpso->so_emu == EMU_CTL &&
1301
 
                 !(tmpso->so_tcpcb?
1302
 
                   (tmpso->so_tcpcb->t_state & (TCPS_TIME_WAIT|TCPS_LAST_ACK))
1303
 
                   :0)) {
1304
 
               /* Ooops, control connection already active */
1305
 
               sb->sb_cc = sprintf(sb->sb_wptr,"Sorry, already connected.\r\n");
1306
 
               sb->sb_wptr += sb->sb_cc;
1307
 
               return 0;
1308
 
             }
1309
 
           }
1310
 
           so->so_emu = EMU_CTL;
1311
 
           ctl_password_ok = 0;
1312
 
           sb->sb_cc = sprintf(sb->sb_wptr, "Slirp command-line ready (type \"help\" for help).\r\nSlirp> ");
1313
 
           sb->sb_wptr += sb->sb_cc;
1314
 
           do_echo=-1;
1315
 
           return(2);
1316
 
#endif
1317
 
        }
 
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;
1318
915
}