1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#include "qemu/osdep.h"
42#include "slirp.h"
43
44
45
46#define TCP_DO_RFC1323 0
47
48
49
50
51void
52tcp_init(Slirp *slirp)
53{
54 slirp->tcp_iss = 1;
55 slirp->tcb.so_next = slirp->tcb.so_prev = &slirp->tcb;
56 slirp->tcp_last_so = &slirp->tcb;
57}
58
59void tcp_cleanup(Slirp *slirp)
60{
61 while (slirp->tcb.so_next != &slirp->tcb) {
62 tcp_close(sototcpcb(slirp->tcb.so_next));
63 }
64}
65
66
67
68
69
70
71
72void
73tcp_template(struct tcpcb *tp)
74{
75 struct socket *so = tp->t_socket;
76 register struct tcpiphdr *n = &tp->t_template;
77
78 n->ti_mbuf = NULL;
79 memset(&n->ti, 0, sizeof(n->ti));
80 n->ti_x0 = 0;
81 switch (so->so_ffamily) {
82 case AF_INET:
83 n->ti_pr = IPPROTO_TCP;
84 n->ti_len = htons(sizeof(struct tcphdr));
85 n->ti_src = so->so_faddr;
86 n->ti_dst = so->so_laddr;
87 n->ti_sport = so->so_fport;
88 n->ti_dport = so->so_lport;
89 break;
90
91 case AF_INET6:
92 n->ti_nh6 = IPPROTO_TCP;
93 n->ti_len = htons(sizeof(struct tcphdr));
94 n->ti_src6 = so->so_faddr6;
95 n->ti_dst6 = so->so_laddr6;
96 n->ti_sport = so->so_fport6;
97 n->ti_dport = so->so_lport6;
98 break;
99
100 default:
101 g_assert_not_reached();
102 }
103
104 n->ti_seq = 0;
105 n->ti_ack = 0;
106 n->ti_x2 = 0;
107 n->ti_off = 5;
108 n->ti_flags = 0;
109 n->ti_win = 0;
110 n->ti_sum = 0;
111 n->ti_urp = 0;
112}
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127void
128tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m,
129 tcp_seq ack, tcp_seq seq, int flags, unsigned short af)
130{
131 register int tlen;
132 int win = 0;
133
134 DEBUG_CALL("tcp_respond");
135 DEBUG_ARG("tp = %p", tp);
136 DEBUG_ARG("ti = %p", ti);
137 DEBUG_ARG("m = %p", m);
138 DEBUG_ARG("ack = %u", ack);
139 DEBUG_ARG("seq = %u", seq);
140 DEBUG_ARG("flags = %x", flags);
141
142 if (tp)
143 win = sbspace(&tp->t_socket->so_rcv);
144 if (m == NULL) {
145 if (!tp || (m = m_get(tp->t_socket->slirp)) == NULL)
146 return;
147 tlen = 0;
148 m->m_data += IF_MAXLINKHDR;
149 *mtod(m, struct tcpiphdr *) = *ti;
150 ti = mtod(m, struct tcpiphdr *);
151 memset(&ti->ti, 0, sizeof(ti->ti));
152 flags = TH_ACK;
153 } else {
154
155
156
157
158 m->m_data = (caddr_t)ti;
159
160 m->m_len = sizeof (struct tcpiphdr);
161 tlen = 0;
162#define xchg(a,b,type) { type t; t=a; a=b; b=t; }
163 switch (af) {
164 case AF_INET:
165 xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, uint32_t);
166 xchg(ti->ti_dport, ti->ti_sport, uint16_t);
167 break;
168 case AF_INET6:
169 xchg(ti->ti_dst6, ti->ti_src6, struct in6_addr);
170 xchg(ti->ti_dport, ti->ti_sport, uint16_t);
171 break;
172 default:
173 g_assert_not_reached();
174 }
175#undef xchg
176 }
177 ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen));
178 tlen += sizeof (struct tcpiphdr);
179 m->m_len = tlen;
180
181 ti->ti_mbuf = NULL;
182 ti->ti_x0 = 0;
183 ti->ti_seq = htonl(seq);
184 ti->ti_ack = htonl(ack);
185 ti->ti_x2 = 0;
186 ti->ti_off = sizeof (struct tcphdr) >> 2;
187 ti->ti_flags = flags;
188 if (tp)
189 ti->ti_win = htons((uint16_t) (win >> tp->rcv_scale));
190 else
191 ti->ti_win = htons((uint16_t)win);
192 ti->ti_urp = 0;
193 ti->ti_sum = 0;
194 ti->ti_sum = cksum(m, tlen);
195
196 struct tcpiphdr tcpiph_save = *(mtod(m, struct tcpiphdr *));
197 struct ip *ip;
198 struct ip6 *ip6;
199
200 switch (af) {
201 case AF_INET:
202 m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
203 - sizeof(struct ip);
204 m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
205 - sizeof(struct ip);
206 ip = mtod(m, struct ip *);
207 ip->ip_len = tlen;
208 ip->ip_dst = tcpiph_save.ti_dst;
209 ip->ip_src = tcpiph_save.ti_src;
210 ip->ip_p = tcpiph_save.ti_pr;
211
212 if (flags & TH_RST) {
213 ip->ip_ttl = MAXTTL;
214 } else {
215 ip->ip_ttl = IPDEFTTL;
216 }
217
218 ip_output(NULL, m);
219 break;
220
221 case AF_INET6:
222 m->m_data += sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
223 - sizeof(struct ip6);
224 m->m_len -= sizeof(struct tcpiphdr) - sizeof(struct tcphdr)
225 - sizeof(struct ip6);
226 ip6 = mtod(m, struct ip6 *);
227 ip6->ip_pl = tlen;
228 ip6->ip_dst = tcpiph_save.ti_dst6;
229 ip6->ip_src = tcpiph_save.ti_src6;
230 ip6->ip_nh = tcpiph_save.ti_nh6;
231
232 ip6_output(NULL, m, 0);
233 break;
234
235 default:
236 g_assert_not_reached();
237 }
238}
239
240
241
242
243
244
245struct tcpcb *
246tcp_newtcpcb(struct socket *so)
247{
248 register struct tcpcb *tp;
249
250 tp = (struct tcpcb *)malloc(sizeof(*tp));
251 if (tp == NULL)
252 return ((struct tcpcb *)0);
253
254 memset((char *) tp, 0, sizeof(struct tcpcb));
255 tp->seg_next = tp->seg_prev = (struct tcpiphdr*)tp;
256 tp->t_maxseg = (so->so_ffamily == AF_INET) ? TCP_MSS : TCP6_MSS;
257
258 tp->t_flags = TCP_DO_RFC1323 ? (TF_REQ_SCALE|TF_REQ_TSTMP) : 0;
259 tp->t_socket = so;
260
261
262
263
264
265
266 tp->t_srtt = TCPTV_SRTTBASE;
267 tp->t_rttvar = TCPTV_SRTTDFLT << 2;
268 tp->t_rttmin = TCPTV_MIN;
269
270 TCPT_RANGESET(tp->t_rxtcur,
271 ((TCPTV_SRTTBASE >> 2) + (TCPTV_SRTTDFLT << 2)) >> 1,
272 TCPTV_MIN, TCPTV_REXMTMAX);
273
274 tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT;
275 tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT;
276 tp->t_state = TCPS_CLOSED;
277
278 so->so_tcpcb = tp;
279
280 return (tp);
281}
282
283
284
285
286
287
288struct tcpcb *tcp_drop(struct tcpcb *tp, int err)
289{
290 DEBUG_CALL("tcp_drop");
291 DEBUG_ARG("tp = %p", tp);
292 DEBUG_ARG("errno = %d", errno);
293
294 if (TCPS_HAVERCVDSYN(tp->t_state)) {
295 tp->t_state = TCPS_CLOSED;
296 (void) tcp_output(tp);
297 }
298 return (tcp_close(tp));
299}
300
301
302
303
304
305
306
307struct tcpcb *
308tcp_close(struct tcpcb *tp)
309{
310 register struct tcpiphdr *t;
311 struct socket *so = tp->t_socket;
312 Slirp *slirp = so->slirp;
313 register struct mbuf *m;
314
315 DEBUG_CALL("tcp_close");
316 DEBUG_ARG("tp = %p", tp);
317
318
319 t = tcpfrag_list_first(tp);
320 while (!tcpfrag_list_end(t, tp)) {
321 t = tcpiphdr_next(t);
322 m = tcpiphdr_prev(t)->ti_mbuf;
323 remque(tcpiphdr2qlink(tcpiphdr_prev(t)));
324 m_free(m);
325 }
326 free(tp);
327 so->so_tcpcb = NULL;
328
329 if (so == slirp->tcp_last_so)
330 slirp->tcp_last_so = &slirp->tcb;
331 closesocket(so->s);
332 sbfree(&so->so_rcv);
333 sbfree(&so->so_snd);
334 sofree(so);
335 return ((struct tcpcb *)0);
336}
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352void
353tcp_sockclosed(struct tcpcb *tp)
354{
355
356 DEBUG_CALL("tcp_sockclosed");
357 DEBUG_ARG("tp = %p", tp);
358
359 if (!tp) {
360 return;
361 }
362
363 switch (tp->t_state) {
364
365 case TCPS_CLOSED:
366 case TCPS_LISTEN:
367 case TCPS_SYN_SENT:
368 tp->t_state = TCPS_CLOSED;
369 tp = tcp_close(tp);
370 break;
371
372 case TCPS_SYN_RECEIVED:
373 case TCPS_ESTABLISHED:
374 tp->t_state = TCPS_FIN_WAIT_1;
375 break;
376
377 case TCPS_CLOSE_WAIT:
378 tp->t_state = TCPS_LAST_ACK;
379 break;
380 }
381 tcp_output(tp);
382}
383
384
385
386
387
388
389
390
391
392
393
394int tcp_fconnect(struct socket *so, unsigned short af)
395{
396 int ret=0;
397
398 DEBUG_CALL("tcp_fconnect");
399 DEBUG_ARG("so = %p", so);
400
401 ret = so->s = qemu_socket(af, SOCK_STREAM, 0);
402 if (ret >= 0) {
403 int opt, s=so->s;
404 struct sockaddr_storage addr;
405
406 qemu_set_nonblock(s);
407 socket_set_fast_reuse(s);
408 opt = 1;
409 qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
410
411 addr = so->fhost.ss;
412 DEBUG_CALL(" connect()ing")
413 sotranslate_out(so, &addr);
414
415
416 ret = connect(s, (struct sockaddr *)&addr, sockaddr_size(&addr));
417
418
419
420
421
422 soisfconnecting(so);
423 }
424
425 return(ret);
426}
427
428
429
430
431
432
433
434
435
436
437
438
439
440void tcp_connect(struct socket *inso)
441{
442 Slirp *slirp = inso->slirp;
443 struct socket *so;
444 struct sockaddr_storage addr;
445 socklen_t addrlen = sizeof(struct sockaddr_storage);
446 struct tcpcb *tp;
447 int s, opt;
448
449 DEBUG_CALL("tcp_connect");
450 DEBUG_ARG("inso = %p", inso);
451
452
453
454
455
456 if (inso->so_state & SS_FACCEPTONCE) {
457
458 so = inso;
459 } else {
460 so = socreate(slirp);
461 if (so == NULL) {
462
463 closesocket(accept(inso->s, (struct sockaddr *)&addr, &addrlen));
464 return;
465 }
466 if (tcp_attach(so) < 0) {
467 free(so);
468 return;
469 }
470 so->lhost = inso->lhost;
471 so->so_ffamily = inso->so_ffamily;
472 }
473
474 tcp_mss(sototcpcb(so), 0);
475
476 s = accept(inso->s, (struct sockaddr *)&addr, &addrlen);
477 if (s < 0) {
478 tcp_close(sototcpcb(so));
479 return;
480 }
481 qemu_set_nonblock(s);
482 socket_set_fast_reuse(s);
483 opt = 1;
484 qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
485 socket_set_nodelay(s);
486
487 so->fhost.ss = addr;
488 sotranslate_accept(so);
489
490
491 if (inso->so_state & SS_FACCEPTONCE) {
492
493 closesocket(so->s);
494
495
496
497 so->so_state = SS_NOFDREF;
498 }
499 so->s = s;
500 so->so_state |= SS_INCOMING;
501
502 so->so_iptos = tcp_tos(so);
503 tp = sototcpcb(so);
504
505 tcp_template(tp);
506
507 tp->t_state = TCPS_SYN_SENT;
508 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
509 tp->iss = slirp->tcp_iss;
510 slirp->tcp_iss += TCP_ISSINCR/2;
511 tcp_sendseqinit(tp);
512 tcp_output(tp);
513}
514
515
516
517
518int
519tcp_attach(struct socket *so)
520{
521 if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
522 return -1;
523
524 insque(so, &so->slirp->tcb);
525
526 return 0;
527}
528
529
530
531
532static const struct tos_t tcptos[] = {
533 {0, 20, IPTOS_THROUGHPUT, 0},
534 {21, 21, IPTOS_LOWDELAY, EMU_FTP},
535 {0, 23, IPTOS_LOWDELAY, 0},
536 {0, 80, IPTOS_THROUGHPUT, 0},
537 {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT},
538 {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT},
539 {0, 544, IPTOS_LOWDELAY, EMU_KSH},
540 {0, 543, IPTOS_LOWDELAY, 0},
541 {0, 6667, IPTOS_THROUGHPUT, EMU_IRC},
542 {0, 6668, IPTOS_THROUGHPUT, EMU_IRC},
543 {0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO },
544 {0, 113, IPTOS_LOWDELAY, EMU_IDENT },
545 {0, 0, 0, 0}
546};
547
548static struct emu_t *tcpemu = NULL;
549
550
551
552
553uint8_t
554tcp_tos(struct socket *so)
555{
556 int i = 0;
557 struct emu_t *emup;
558
559 while(tcptos[i].tos) {
560 if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
561 (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {
562 so->so_emu = tcptos[i].emu;
563 return tcptos[i].tos;
564 }
565 i++;
566 }
567
568
569 for (emup = tcpemu; emup; emup = emup->next) {
570 if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) ||
571 (emup->lport && (ntohs(so->so_lport) == emup->lport))) {
572 so->so_emu = emup->emu;
573 return emup->tos;
574 }
575 }
576
577 return 0;
578}
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604int
605tcp_emu(struct socket *so, struct mbuf *m)
606{
607 Slirp *slirp = so->slirp;
608 u_int n1, n2, n3, n4, n5, n6;
609 char buff[257];
610 uint32_t laddr;
611 u_int lport;
612 char *bptr;
613
614 DEBUG_CALL("tcp_emu");
615 DEBUG_ARG("so = %p", so);
616 DEBUG_ARG("m = %p", m);
617
618 switch(so->so_emu) {
619 int x, i;
620
621 case EMU_IDENT:
622
623
624
625
626 {
627 struct socket *tmpso;
628 struct sockaddr_in addr;
629 socklen_t addrlen = sizeof(struct sockaddr_in);
630 struct sbuf *so_rcv = &so->so_rcv;
631
632 memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
633 so_rcv->sb_wptr += m->m_len;
634 so_rcv->sb_rptr += m->m_len;
635 m->m_data[m->m_len] = 0;
636 if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
637 if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
638 HTONS(n1);
639 HTONS(n2);
640
641 for (tmpso = slirp->tcb.so_next;
642 tmpso != &slirp->tcb;
643 tmpso = tmpso->so_next) {
644 if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
645 tmpso->so_lport == n2 &&
646 tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
647 tmpso->so_fport == n1) {
648 if (getsockname(tmpso->s,
649 (struct sockaddr *)&addr, &addrlen) == 0)
650 n2 = ntohs(addr.sin_port);
651 break;
652 }
653 }
654 }
655 so_rcv->sb_cc = snprintf(so_rcv->sb_data,
656 so_rcv->sb_datalen,
657 "%d,%d\r\n", n1, n2);
658 so_rcv->sb_rptr = so_rcv->sb_data;
659 so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
660 }
661 m_free(m);
662 return 0;
663 }
664
665 case EMU_FTP:
666 *(m->m_data+m->m_len) = 0;
667 if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
668
669
670
671 x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
672 &n1, &n2, &n3, &n4, &n5, &n6, buff);
673 if (x < 6)
674 return 1;
675
676 laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
677 lport = htons((n5 << 8) | (n6));
678
679 if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
680 lport, SS_FACCEPTONCE)) == NULL) {
681 return 1;
682 }
683 n6 = ntohs(so->so_fport);
684
685 n5 = (n6 >> 8) & 0xff;
686 n6 &= 0xff;
687
688 laddr = ntohl(so->so_faddr.s_addr);
689
690 n1 = ((laddr >> 24) & 0xff);
691 n2 = ((laddr >> 16) & 0xff);
692 n3 = ((laddr >> 8) & 0xff);
693 n4 = (laddr & 0xff);
694
695 m->m_len = bptr - m->m_data;
696 m->m_len += snprintf(bptr, m->m_size - m->m_len,
697 "ORT %d,%d,%d,%d,%d,%d\r\n%s",
698 n1, n2, n3, n4, n5, n6, x==7?buff:"");
699 return 1;
700 } else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) {
701
702
703
704 x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
705 &n1, &n2, &n3, &n4, &n5, &n6, buff);
706 if (x < 6)
707 return 1;
708
709 laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
710 lport = htons((n5 << 8) | (n6));
711
712 if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
713 lport, SS_FACCEPTONCE)) == NULL) {
714 return 1;
715 }
716 n6 = ntohs(so->so_fport);
717
718 n5 = (n6 >> 8) & 0xff;
719 n6 &= 0xff;
720
721 laddr = ntohl(so->so_faddr.s_addr);
722
723 n1 = ((laddr >> 24) & 0xff);
724 n2 = ((laddr >> 16) & 0xff);
725 n3 = ((laddr >> 8) & 0xff);
726 n4 = (laddr & 0xff);
727
728 m->m_len = bptr - m->m_data;
729 m->m_len += snprintf(bptr, m->m_size - m->m_len,
730 "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
731 n1, n2, n3, n4, n5, n6, x==7?buff:"");
732
733 return 1;
734 }
735
736 return 1;
737
738 case EMU_KSH:
739
740
741
742
743
744
745 so->so_emu = 0;
746 for (lport = 0, i = 0; i < m->m_len-1; ++i) {
747 if (m->m_data[i] < '0' || m->m_data[i] > '9')
748 return 1;
749 lport *= 10;
750 lport += m->m_data[i] - '0';
751 }
752 if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
753 (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr,
754 htons(lport), SS_FACCEPTONCE)) != NULL)
755 m->m_len = snprintf(m->m_data, m->m_size, "%d",
756 ntohs(so->so_fport)) + 1;
757 return 1;
758
759 case EMU_IRC:
760
761
762
763 *(m->m_data+m->m_len) = 0;
764 if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
765 return 1;
766
767
768 if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
769 if ((so = tcp_listen(slirp, INADDR_ANY, 0,
770 htonl(laddr), htons(lport),
771 SS_FACCEPTONCE)) == NULL) {
772 return 1;
773 }
774 m->m_len = bptr - m->m_data;
775 m->m_len += snprintf(bptr, m->m_size,
776 "DCC CHAT chat %lu %u%c\n",
777 (unsigned long)ntohl(so->so_faddr.s_addr),
778 ntohs(so->so_fport), 1);
779 } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
780 if ((so = tcp_listen(slirp, INADDR_ANY, 0,
781 htonl(laddr), htons(lport),
782 SS_FACCEPTONCE)) == NULL) {
783 return 1;
784 }
785 m->m_len = bptr - m->m_data;
786 m->m_len += snprintf(bptr, m->m_size,
787 "DCC SEND %s %lu %u %u%c\n", buff,
788 (unsigned long)ntohl(so->so_faddr.s_addr),
789 ntohs(so->so_fport), n1, 1);
790 } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
791 if ((so = tcp_listen(slirp, INADDR_ANY, 0,
792 htonl(laddr), htons(lport),
793 SS_FACCEPTONCE)) == NULL) {
794 return 1;
795 }
796 m->m_len = bptr - m->m_data;
797 m->m_len += snprintf(bptr, m->m_size,
798 "DCC MOVE %s %lu %u %u%c\n", buff,
799 (unsigned long)ntohl(so->so_faddr.s_addr),
800 ntohs(so->so_fport), n1, 1);
801 }
802 return 1;
803
804 case EMU_REALAUDIO:
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841 bptr = m->m_data;
842 while (bptr < m->m_data + m->m_len) {
843 u_short p;
844 static int ra = 0;
845 char ra_tbl[4];
846
847 ra_tbl[0] = 0x50;
848 ra_tbl[1] = 0x4e;
849 ra_tbl[2] = 0x41;
850 ra_tbl[3] = 0;
851
852 switch (ra) {
853 case 0:
854 case 2:
855 case 3:
856 if (*bptr++ != ra_tbl[ra]) {
857 ra = 0;
858 continue;
859 }
860 break;
861
862 case 1:
863
864
865
866 if (*bptr == 0x50) {
867 ra = 1;
868 bptr++;
869 continue;
870 } else if (*bptr++ != ra_tbl[ra]) {
871 ra = 0;
872 continue;
873 }
874 break;
875
876 case 4:
877
878
879
880 bptr++;
881 break;
882
883 case 5:
884
885
886
887
888
889 if (*(bptr + 1) == 0x02)
890 bptr += 8;
891 else
892 bptr += 4;
893 break;
894
895 case 6:
896
897
898
899 lport = (((u_char*)bptr)[0] << 8)
900 + ((u_char *)bptr)[1];
901 if (lport < 6970)
902 lport += 256;
903 if (lport < 6970 || lport > 7170)
904 return 1;
905
906
907 for (p = 6970; p < 7071; p++) {
908 if (udp_listen(slirp, INADDR_ANY,
909 htons(p),
910 so->so_laddr.s_addr,
911 htons(lport),
912 SS_FACCEPTONCE)) {
913 break;
914 }
915 }
916 if (p == 7071)
917 p = 0;
918 *(u_char *)bptr++ = (p >> 8) & 0xff;
919 *(u_char *)bptr = p & 0xff;
920 ra = 0;
921 return 1;
922 break;
923
924 default:
925 ra = 0;
926 }
927 ra++;
928 }
929 return 1;
930
931 default:
932
933 so->so_emu = 0;
934 return 1;
935 }
936}
937
938
939
940
941
942
943int tcp_ctl(struct socket *so)
944{
945 Slirp *slirp = so->slirp;
946 struct sbuf *sb = &so->so_snd;
947 struct ex_list *ex_ptr;
948 int do_pty;
949
950 DEBUG_CALL("tcp_ctl");
951 DEBUG_ARG("so = %p", so);
952
953 if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
954
955 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
956 if (ex_ptr->ex_fport == so->so_fport &&
957 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
958 if (ex_ptr->ex_pty == 3) {
959 so->s = -1;
960 so->extra = (void *)ex_ptr->ex_exec;
961 return 1;
962 }
963 do_pty = ex_ptr->ex_pty;
964 DEBUG_MISC((dfd, " executing %s\n", ex_ptr->ex_exec));
965 return fork_exec(so, ex_ptr->ex_exec, do_pty);
966 }
967 }
968 }
969 sb->sb_cc =
970 snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),
971 "Error: No application configured.\r\n");
972 sb->sb_wptr += sb->sb_cc;
973 return 0;
974}
975