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