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