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