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