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 opt = 1;
341 qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
342 opt = 1;
343 qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt));
344
345 addr.sin_family = AF_INET;
346 if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) ==
347 slirp->vnetwork_addr.s_addr) {
348
349 if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) {
350 if (get_dns_addr(&addr.sin_addr) < 0)
351 addr.sin_addr = loopback_addr;
352 } else {
353 addr.sin_addr = loopback_addr;
354 }
355 } else
356 addr.sin_addr = so->so_faddr;
357 addr.sin_port = so->so_fport;
358
359 DEBUG_MISC((dfd, " connect()ing, addr.sin_port=%d, "
360 "addr.sin_addr.s_addr=%.16s\n",
361 ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));
362
363 ret = connect(s,(struct sockaddr *)&addr,sizeof (addr));
364
365
366
367
368
369 soisfconnecting(so);
370 }
371
372 return(ret);
373}
374
375
376
377
378
379
380
381
382
383
384
385
386
387void tcp_connect(struct socket *inso)
388{
389 Slirp *slirp = inso->slirp;
390 struct socket *so;
391 struct sockaddr_in addr;
392 socklen_t addrlen = sizeof(struct sockaddr_in);
393 struct tcpcb *tp;
394 int s, opt;
395
396 DEBUG_CALL("tcp_connect");
397 DEBUG_ARG("inso = %lx", (long)inso);
398
399
400
401
402
403 if (inso->so_state & SS_FACCEPTONCE) {
404
405 so = inso;
406 } else {
407 so = socreate(slirp);
408 if (so == NULL) {
409
410 closesocket(accept(inso->s, (struct sockaddr *)&addr, &addrlen));
411 return;
412 }
413 if (tcp_attach(so) < 0) {
414 free(so);
415 return;
416 }
417 so->so_laddr = inso->so_laddr;
418 so->so_lport = inso->so_lport;
419 }
420
421 tcp_mss(sototcpcb(so), 0);
422
423 s = accept(inso->s, (struct sockaddr *)&addr, &addrlen);
424 if (s < 0) {
425 tcp_close(sototcpcb(so));
426 return;
427 }
428 qemu_set_nonblock(s);
429 opt = 1;
430 qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int));
431 opt = 1;
432 qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
433 socket_set_nodelay(s);
434
435 so->so_fport = addr.sin_port;
436 so->so_faddr = addr.sin_addr;
437
438 if (so->so_faddr.s_addr == 0 ||
439 (so->so_faddr.s_addr & loopback_mask) ==
440 (loopback_addr.s_addr & loopback_mask)) {
441 so->so_faddr = slirp->vhost_addr;
442 }
443
444
445 if (inso->so_state & SS_FACCEPTONCE) {
446
447 closesocket(so->s);
448
449
450
451 so->so_state = SS_NOFDREF;
452 }
453 so->s = s;
454 so->so_state |= SS_INCOMING;
455
456 so->so_iptos = tcp_tos(so);
457 tp = sototcpcb(so);
458
459 tcp_template(tp);
460
461 tp->t_state = TCPS_SYN_SENT;
462 tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
463 tp->iss = slirp->tcp_iss;
464 slirp->tcp_iss += TCP_ISSINCR/2;
465 tcp_sendseqinit(tp);
466 tcp_output(tp);
467}
468
469
470
471
472int
473tcp_attach(struct socket *so)
474{
475 if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
476 return -1;
477
478 insque(so, &so->slirp->tcb);
479
480 return 0;
481}
482
483
484
485
486static const struct tos_t tcptos[] = {
487 {0, 20, IPTOS_THROUGHPUT, 0},
488 {21, 21, IPTOS_LOWDELAY, EMU_FTP},
489 {0, 23, IPTOS_LOWDELAY, 0},
490 {0, 80, IPTOS_THROUGHPUT, 0},
491 {0, 513, IPTOS_LOWDELAY, EMU_RLOGIN|EMU_NOCONNECT},
492 {0, 514, IPTOS_LOWDELAY, EMU_RSH|EMU_NOCONNECT},
493 {0, 544, IPTOS_LOWDELAY, EMU_KSH},
494 {0, 543, IPTOS_LOWDELAY, 0},
495 {0, 6667, IPTOS_THROUGHPUT, EMU_IRC},
496 {0, 6668, IPTOS_THROUGHPUT, EMU_IRC},
497 {0, 7070, IPTOS_LOWDELAY, EMU_REALAUDIO },
498 {0, 113, IPTOS_LOWDELAY, EMU_IDENT },
499 {0, 0, 0, 0}
500};
501
502static struct emu_t *tcpemu = NULL;
503
504
505
506
507uint8_t
508tcp_tos(struct socket *so)
509{
510 int i = 0;
511 struct emu_t *emup;
512
513 while(tcptos[i].tos) {
514 if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) ||
515 (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) {
516 so->so_emu = tcptos[i].emu;
517 return tcptos[i].tos;
518 }
519 i++;
520 }
521
522
523 for (emup = tcpemu; emup; emup = emup->next) {
524 if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) ||
525 (emup->lport && (ntohs(so->so_lport) == emup->lport))) {
526 so->so_emu = emup->emu;
527 return emup->tos;
528 }
529 }
530
531 return 0;
532}
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558int
559tcp_emu(struct socket *so, struct mbuf *m)
560{
561 Slirp *slirp = so->slirp;
562 u_int n1, n2, n3, n4, n5, n6;
563 char buff[257];
564 uint32_t laddr;
565 u_int lport;
566 char *bptr;
567
568 DEBUG_CALL("tcp_emu");
569 DEBUG_ARG("so = %lx", (long)so);
570 DEBUG_ARG("m = %lx", (long)m);
571
572 switch(so->so_emu) {
573 int x, i;
574
575 case EMU_IDENT:
576
577
578
579
580 {
581 struct socket *tmpso;
582 struct sockaddr_in addr;
583 socklen_t addrlen = sizeof(struct sockaddr_in);
584 struct sbuf *so_rcv = &so->so_rcv;
585
586 memcpy(so_rcv->sb_wptr, m->m_data, m->m_len);
587 so_rcv->sb_wptr += m->m_len;
588 so_rcv->sb_rptr += m->m_len;
589 m->m_data[m->m_len] = 0;
590 if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) {
591 if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) {
592 HTONS(n1);
593 HTONS(n2);
594
595 for (tmpso = slirp->tcb.so_next;
596 tmpso != &slirp->tcb;
597 tmpso = tmpso->so_next) {
598 if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr &&
599 tmpso->so_lport == n2 &&
600 tmpso->so_faddr.s_addr == so->so_faddr.s_addr &&
601 tmpso->so_fport == n1) {
602 if (getsockname(tmpso->s,
603 (struct sockaddr *)&addr, &addrlen) == 0)
604 n2 = ntohs(addr.sin_port);
605 break;
606 }
607 }
608 }
609 so_rcv->sb_cc = snprintf(so_rcv->sb_data,
610 so_rcv->sb_datalen,
611 "%d,%d\r\n", n1, n2);
612 so_rcv->sb_rptr = so_rcv->sb_data;
613 so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc;
614 }
615 m_free(m);
616 return 0;
617 }
618
619 case EMU_FTP:
620 *(m->m_data+m->m_len) = 0;
621 if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) {
622
623
624
625 x = sscanf(bptr, "ORT %u,%u,%u,%u,%u,%u\r\n%256[^\177]",
626 &n1, &n2, &n3, &n4, &n5, &n6, buff);
627 if (x < 6)
628 return 1;
629
630 laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
631 lport = htons((n5 << 8) | (n6));
632
633 if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
634 lport, SS_FACCEPTONCE)) == NULL) {
635 return 1;
636 }
637 n6 = ntohs(so->so_fport);
638
639 n5 = (n6 >> 8) & 0xff;
640 n6 &= 0xff;
641
642 laddr = ntohl(so->so_faddr.s_addr);
643
644 n1 = ((laddr >> 24) & 0xff);
645 n2 = ((laddr >> 16) & 0xff);
646 n3 = ((laddr >> 8) & 0xff);
647 n4 = (laddr & 0xff);
648
649 m->m_len = bptr - m->m_data;
650 m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,
651 "ORT %d,%d,%d,%d,%d,%d\r\n%s",
652 n1, n2, n3, n4, n5, n6, x==7?buff:"");
653 return 1;
654 } else if ((bptr = (char *)strstr(m->m_data, "27 Entering")) != NULL) {
655
656
657
658 x = sscanf(bptr, "27 Entering Passive Mode (%u,%u,%u,%u,%u,%u)\r\n%256[^\177]",
659 &n1, &n2, &n3, &n4, &n5, &n6, buff);
660 if (x < 6)
661 return 1;
662
663 laddr = htonl((n1 << 24) | (n2 << 16) | (n3 << 8) | (n4));
664 lport = htons((n5 << 8) | (n6));
665
666 if ((so = tcp_listen(slirp, INADDR_ANY, 0, laddr,
667 lport, SS_FACCEPTONCE)) == NULL) {
668 return 1;
669 }
670 n6 = ntohs(so->so_fport);
671
672 n5 = (n6 >> 8) & 0xff;
673 n6 &= 0xff;
674
675 laddr = ntohl(so->so_faddr.s_addr);
676
677 n1 = ((laddr >> 24) & 0xff);
678 n2 = ((laddr >> 16) & 0xff);
679 n3 = ((laddr >> 8) & 0xff);
680 n4 = (laddr & 0xff);
681
682 m->m_len = bptr - m->m_data;
683 m->m_len += snprintf(bptr, m->m_hdr.mh_size - m->m_len,
684 "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s",
685 n1, n2, n3, n4, n5, n6, x==7?buff:"");
686
687 return 1;
688 }
689
690 return 1;
691
692 case EMU_KSH:
693
694
695
696
697
698
699 so->so_emu = 0;
700 for (lport = 0, i = 0; i < m->m_len-1; ++i) {
701 if (m->m_data[i] < '0' || m->m_data[i] > '9')
702 return 1;
703 lport *= 10;
704 lport += m->m_data[i] - '0';
705 }
706 if (m->m_data[m->m_len-1] == '\0' && lport != 0 &&
707 (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr,
708 htons(lport), SS_FACCEPTONCE)) != NULL)
709 m->m_len = snprintf(m->m_data, m->m_hdr.mh_size, "%d",
710 ntohs(so->so_fport)) + 1;
711 return 1;
712
713 case EMU_IRC:
714
715
716
717 *(m->m_data+m->m_len) = 0;
718 if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL)
719 return 1;
720
721
722 if (sscanf(bptr, "DCC CHAT %256s %u %u", buff, &laddr, &lport) == 3) {
723 if ((so = tcp_listen(slirp, INADDR_ANY, 0,
724 htonl(laddr), htons(lport),
725 SS_FACCEPTONCE)) == NULL) {
726 return 1;
727 }
728 m->m_len = bptr - m->m_data;
729 m->m_len += snprintf(bptr, m->m_hdr.mh_size,
730 "DCC CHAT chat %lu %u%c\n",
731 (unsigned long)ntohl(so->so_faddr.s_addr),
732 ntohs(so->so_fport), 1);
733 } else if (sscanf(bptr, "DCC SEND %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
734 if ((so = tcp_listen(slirp, INADDR_ANY, 0,
735 htonl(laddr), htons(lport),
736 SS_FACCEPTONCE)) == NULL) {
737 return 1;
738 }
739 m->m_len = bptr - m->m_data;
740 m->m_len += snprintf(bptr, m->m_hdr.mh_size,
741 "DCC SEND %s %lu %u %u%c\n", buff,
742 (unsigned long)ntohl(so->so_faddr.s_addr),
743 ntohs(so->so_fport), n1, 1);
744 } else if (sscanf(bptr, "DCC MOVE %256s %u %u %u", buff, &laddr, &lport, &n1) == 4) {
745 if ((so = tcp_listen(slirp, INADDR_ANY, 0,
746 htonl(laddr), htons(lport),
747 SS_FACCEPTONCE)) == NULL) {
748 return 1;
749 }
750 m->m_len = bptr - m->m_data;
751 m->m_len += snprintf(bptr, m->m_hdr.mh_size,
752 "DCC MOVE %s %lu %u %u%c\n", buff,
753 (unsigned long)ntohl(so->so_faddr.s_addr),
754 ntohs(so->so_fport), n1, 1);
755 }
756 return 1;
757
758 case EMU_REALAUDIO:
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
794
795 bptr = m->m_data;
796 while (bptr < m->m_data + m->m_len) {
797 u_short p;
798 static int ra = 0;
799 char ra_tbl[4];
800
801 ra_tbl[0] = 0x50;
802 ra_tbl[1] = 0x4e;
803 ra_tbl[2] = 0x41;
804 ra_tbl[3] = 0;
805
806 switch (ra) {
807 case 0:
808 case 2:
809 case 3:
810 if (*bptr++ != ra_tbl[ra]) {
811 ra = 0;
812 continue;
813 }
814 break;
815
816 case 1:
817
818
819
820 if (*bptr == 0x50) {
821 ra = 1;
822 bptr++;
823 continue;
824 } else if (*bptr++ != ra_tbl[ra]) {
825 ra = 0;
826 continue;
827 }
828 break;
829
830 case 4:
831
832
833
834 bptr++;
835 break;
836
837 case 5:
838
839
840
841
842
843 if (*(bptr + 1) == 0x02)
844 bptr += 8;
845 else
846 bptr += 4;
847 break;
848
849 case 6:
850
851
852
853 lport = (((u_char*)bptr)[0] << 8)
854 + ((u_char *)bptr)[1];
855 if (lport < 6970)
856 lport += 256;
857 if (lport < 6970 || lport > 7170)
858 return 1;
859
860
861 for (p = 6970; p < 7071; p++) {
862 if (udp_listen(slirp, INADDR_ANY,
863 htons(p),
864 so->so_laddr.s_addr,
865 htons(lport),
866 SS_FACCEPTONCE)) {
867 break;
868 }
869 }
870 if (p == 7071)
871 p = 0;
872 *(u_char *)bptr++ = (p >> 8) & 0xff;
873 *(u_char *)bptr = p & 0xff;
874 ra = 0;
875 return 1;
876 break;
877
878 default:
879 ra = 0;
880 }
881 ra++;
882 }
883 return 1;
884
885 default:
886
887 so->so_emu = 0;
888 return 1;
889 }
890}
891
892
893
894
895
896
897int tcp_ctl(struct socket *so)
898{
899 Slirp *slirp = so->slirp;
900 struct sbuf *sb = &so->so_snd;
901 struct ex_list *ex_ptr;
902 int do_pty;
903
904 DEBUG_CALL("tcp_ctl");
905 DEBUG_ARG("so = %lx", (long )so);
906
907 if (so->so_faddr.s_addr != slirp->vhost_addr.s_addr) {
908
909 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
910 if (ex_ptr->ex_fport == so->so_fport &&
911 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr) {
912 if (ex_ptr->ex_pty == 3) {
913 so->s = -1;
914 so->extra = (void *)ex_ptr->ex_exec;
915 return 1;
916 }
917 do_pty = ex_ptr->ex_pty;
918 DEBUG_MISC((dfd, " executing %s\n", ex_ptr->ex_exec));
919 return fork_exec(so, ex_ptr->ex_exec, do_pty);
920 }
921 }
922 }
923 sb->sb_cc =
924 snprintf(sb->sb_wptr, sb->sb_datalen - (sb->sb_wptr - sb->sb_data),
925 "Error: No application configured.\r\n");
926 sb->sb_wptr += sb->sb_cc;
927 return 0;
928}
929