Revision 0d62c4cf slirp/tcp_subr.c
b/slirp/tcp_subr.c | ||
---|---|---|
60 | 60 |
* in a skeletal tcp/ip header, minimizing the amount of work |
61 | 61 |
* necessary when the connection is used. |
62 | 62 |
*/ |
63 |
/* struct tcpiphdr * */ |
|
64 | 63 |
void |
65 | 64 |
tcp_template(struct tcpcb *tp) |
66 | 65 |
{ |
... | ... | |
119 | 118 |
if (m == NULL) { |
120 | 119 |
if ((m = m_get()) == NULL) |
121 | 120 |
return; |
122 |
#ifdef TCP_COMPAT_42 |
|
123 |
tlen = 1; |
|
124 |
#else |
|
125 | 121 |
tlen = 0; |
126 |
#endif |
|
127 | 122 |
m->m_data += IF_MAXLINKHDR; |
128 | 123 |
*mtod(m, struct tcpiphdr *) = *ti; |
129 | 124 |
ti = mtod(m, struct tcpiphdr *); |
... | ... | |
220 | 215 |
*/ |
221 | 216 |
struct tcpcb *tcp_drop(struct tcpcb *tp, int err) |
222 | 217 |
{ |
223 |
/* tcp_drop(tp, errno) |
|
224 |
register struct tcpcb *tp; |
|
225 |
int errno; |
|
226 |
{ |
|
227 |
*/ |
|
228 |
|
|
229 | 218 |
DEBUG_CALL("tcp_drop"); |
230 | 219 |
DEBUG_ARG("tp = %lx", (long)tp); |
231 | 220 |
DEBUG_ARG("errno = %d", errno); |
... | ... | |
236 | 225 |
STAT(tcpstat.tcps_drops++); |
237 | 226 |
} else |
238 | 227 |
STAT(tcpstat.tcps_conndrops++); |
239 |
/* if (errno == ETIMEDOUT && tp->t_softerror) |
|
240 |
* errno = tp->t_softerror; |
|
241 |
*/ |
|
242 |
/* so->so_error = errno; */ |
|
243 | 228 |
return (tcp_close(tp)); |
244 | 229 |
} |
245 | 230 |
|
... | ... | |
267 | 252 |
remque(tcpiphdr2qlink(tcpiphdr_prev(t))); |
268 | 253 |
m_freem(m); |
269 | 254 |
} |
270 |
/* It's static */ |
|
271 |
/* if (tp->t_template) |
|
272 |
* (void) m_free(dtom(tp->t_template)); |
|
273 |
*/ |
|
274 |
/* free(tp, M_PCB); */ |
|
275 | 255 |
free(tp); |
276 | 256 |
so->so_tcpcb = NULL; |
277 |
soisfdisconnected(so); |
|
278 | 257 |
/* clobber input socket cache if we're closing the cached connection */ |
279 | 258 |
if (so == tcp_last_so) |
280 | 259 |
tcp_last_so = &tcb; |
... | ... | |
286 | 265 |
return ((struct tcpcb *)0); |
287 | 266 |
} |
288 | 267 |
|
289 |
#ifdef notdef |
|
290 |
void |
|
291 |
tcp_drain() |
|
292 |
{ |
|
293 |
/* XXX */ |
|
294 |
} |
|
295 |
|
|
296 |
/* |
|
297 |
* When a source quench is received, close congestion window |
|
298 |
* to one segment. We will gradually open it again as we proceed. |
|
299 |
*/ |
|
300 |
void |
|
301 |
tcp_quench(i, errno) |
|
302 |
|
|
303 |
int errno; |
|
304 |
{ |
|
305 |
struct tcpcb *tp = intotcpcb(inp); |
|
306 |
|
|
307 |
if (tp) |
|
308 |
tp->snd_cwnd = tp->t_maxseg; |
|
309 |
} |
|
310 |
|
|
311 |
#endif /* notdef */ |
|
312 |
|
|
313 | 268 |
/* |
314 | 269 |
* TCP protocol interface to socket abstraction. |
315 | 270 |
*/ |
... | ... | |
349 | 304 |
tp->t_state = TCPS_LAST_ACK; |
350 | 305 |
break; |
351 | 306 |
} |
352 |
/* soisfdisconnecting(tp->t_socket); */ |
|
353 |
if (tp && tp->t_state >= TCPS_FIN_WAIT_2) |
|
354 |
soisfdisconnected(tp->t_socket); |
|
355 | 307 |
if (tp) |
356 | 308 |
tcp_output(tp); |
357 | 309 |
} |
... | ... | |
490 | 442 |
|
491 | 443 |
tcp_template(tp); |
492 | 444 |
|
493 |
/* Compute window scaling to request. */ |
|
494 |
/* while (tp->request_r_scale < TCP_MAX_WINSHIFT && |
|
495 |
* (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) |
|
496 |
* tp->request_r_scale++; |
|
497 |
*/ |
|
498 |
|
|
499 |
/* soisconnecting(so); */ /* NOFDREF used instead */ |
|
500 | 445 |
STAT(tcpstat.tcps_connattempt++); |
501 | 446 |
|
502 | 447 |
tp->t_state = TCPS_SYN_SENT; |
... | ... | |
540 | 485 |
{0, 0, 0, 0} |
541 | 486 |
}; |
542 | 487 |
|
543 |
#ifdef CONFIG_QEMU |
|
544 |
static |
|
545 |
#endif |
|
546 |
struct emu_t *tcpemu = NULL; |
|
488 |
static struct emu_t *tcpemu = NULL; |
|
547 | 489 |
|
548 | 490 |
/* |
549 | 491 |
* Return TOS according to the above table |
... | ... | |
575 | 517 |
return 0; |
576 | 518 |
} |
577 | 519 |
|
578 |
#if 0 |
|
579 |
int do_echo = -1; |
|
580 |
#endif |
|
581 |
|
|
582 | 520 |
/* |
583 | 521 |
* Emulate programs that try and connect to us |
584 | 522 |
* This includes ftp (the data connection is |
... | ... | |
661 | 599 |
return 0; |
662 | 600 |
} |
663 | 601 |
|
664 |
#if 0 |
|
665 |
case EMU_RLOGIN: |
|
666 |
/* |
|
667 |
* Rlogin emulation |
|
668 |
* First we accumulate all the initial option negotiation, |
|
669 |
* then fork_exec() rlogin according to the options |
|
670 |
*/ |
|
671 |
{ |
|
672 |
int i, i2, n; |
|
673 |
char *ptr; |
|
674 |
char args[100]; |
|
675 |
char term[100]; |
|
676 |
struct sbuf *so_snd = &so->so_snd; |
|
677 |
struct sbuf *so_rcv = &so->so_rcv; |
|
678 |
|
|
679 |
/* First check if they have a priveladged port, or too much data has arrived */ |
|
680 |
if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 || |
|
681 |
(m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) { |
|
682 |
memcpy(so_snd->sb_wptr, "Permission denied\n", 18); |
|
683 |
so_snd->sb_wptr += 18; |
|
684 |
so_snd->sb_cc += 18; |
|
685 |
tcp_sockclosed(sototcpcb(so)); |
|
686 |
m_free(m); |
|
687 |
return 0; |
|
688 |
} |
|
689 |
|
|
690 |
/* Append the current data */ |
|
691 |
memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); |
|
692 |
so_rcv->sb_wptr += m->m_len; |
|
693 |
so_rcv->sb_rptr += m->m_len; |
|
694 |
m_free(m); |
|
695 |
|
|
696 |
/* |
|
697 |
* Check if we have all the initial options, |
|
698 |
* and build argument list to rlogin while we're here |
|
699 |
*/ |
|
700 |
n = 0; |
|
701 |
ptr = so_rcv->sb_data; |
|
702 |
args[0] = 0; |
|
703 |
term[0] = 0; |
|
704 |
while (ptr < so_rcv->sb_wptr) { |
|
705 |
if (*ptr++ == 0) { |
|
706 |
n++; |
|
707 |
if (n == 2) { |
|
708 |
sprintf(args, "rlogin -l %s %s", |
|
709 |
ptr, inet_ntoa(so->so_faddr)); |
|
710 |
} else if (n == 3) { |
|
711 |
i2 = so_rcv->sb_wptr - ptr; |
|
712 |
for (i = 0; i < i2; i++) { |
|
713 |
if (ptr[i] == '/') { |
|
714 |
ptr[i] = 0; |
|
715 |
#ifdef HAVE_SETENV |
|
716 |
sprintf(term, "%s", ptr); |
|
717 |
#else |
|
718 |
sprintf(term, "TERM=%s", ptr); |
|
719 |
#endif |
|
720 |
ptr[i] = '/'; |
|
721 |
break; |
|
722 |
} |
|
723 |
} |
|
724 |
} |
|
725 |
} |
|
726 |
} |
|
727 |
|
|
728 |
if (n != 4) |
|
729 |
return 0; |
|
730 |
|
|
731 |
/* We have it, set our term variable and fork_exec() */ |
|
732 |
#ifdef HAVE_SETENV |
|
733 |
setenv("TERM", term, 1); |
|
734 |
#else |
|
735 |
putenv(term); |
|
736 |
#endif |
|
737 |
fork_exec(so, args, 2); |
|
738 |
term[0] = 0; |
|
739 |
so->so_emu = 0; |
|
740 |
|
|
741 |
/* And finally, send the client a 0 character */ |
|
742 |
so_snd->sb_wptr[0] = 0; |
|
743 |
so_snd->sb_wptr++; |
|
744 |
so_snd->sb_cc++; |
|
745 |
|
|
746 |
return 0; |
|
747 |
} |
|
748 |
|
|
749 |
case EMU_RSH: |
|
750 |
/* |
|
751 |
* rsh emulation |
|
752 |
* First we accumulate all the initial option negotiation, |
|
753 |
* then rsh_exec() rsh according to the options |
|
754 |
*/ |
|
755 |
{ |
|
756 |
int n; |
|
757 |
char *ptr; |
|
758 |
char *user; |
|
759 |
char *args; |
|
760 |
struct sbuf *so_snd = &so->so_snd; |
|
761 |
struct sbuf *so_rcv = &so->so_rcv; |
|
762 |
|
|
763 |
/* First check if they have a priveladged port, or too much data has arrived */ |
|
764 |
if (ntohs(so->so_lport) > 1023 || ntohs(so->so_lport) < 512 || |
|
765 |
(m->m_len + so_rcv->sb_wptr) > (so_rcv->sb_data + so_rcv->sb_datalen)) { |
|
766 |
memcpy(so_snd->sb_wptr, "Permission denied\n", 18); |
|
767 |
so_snd->sb_wptr += 18; |
|
768 |
so_snd->sb_cc += 18; |
|
769 |
tcp_sockclosed(sototcpcb(so)); |
|
770 |
m_free(m); |
|
771 |
return 0; |
|
772 |
} |
|
773 |
|
|
774 |
/* Append the current data */ |
|
775 |
memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); |
|
776 |
so_rcv->sb_wptr += m->m_len; |
|
777 |
so_rcv->sb_rptr += m->m_len; |
|
778 |
m_free(m); |
|
779 |
|
|
780 |
/* |
|
781 |
* Check if we have all the initial options, |
|
782 |
* and build argument list to rlogin while we're here |
|
783 |
*/ |
|
784 |
n = 0; |
|
785 |
ptr = so_rcv->sb_data; |
|
786 |
user=""; |
|
787 |
args=""; |
|
788 |
if (so->extra==NULL) { |
|
789 |
struct socket *ns; |
|
790 |
struct tcpcb* tp; |
|
791 |
int port=atoi(ptr); |
|
792 |
if (port <= 0) return 0; |
|
793 |
if (port > 1023 || port < 512) { |
|
794 |
memcpy(so_snd->sb_wptr, "Permission denied\n", 18); |
|
795 |
so_snd->sb_wptr += 18; |
|
796 |
so_snd->sb_cc += 18; |
|
797 |
tcp_sockclosed(sototcpcb(so)); |
|
798 |
return 0; |
|
799 |
} |
|
800 |
if ((ns=socreate()) == NULL) |
|
801 |
return 0; |
|
802 |
if (tcp_attach(ns)<0) { |
|
803 |
free(ns); |
|
804 |
return 0; |
|
805 |
} |
|
806 |
|
|
807 |
ns->so_laddr=so->so_laddr; |
|
808 |
ns->so_lport=htons(port); |
|
809 |
|
|
810 |
(void) tcp_mss(sototcpcb(ns), 0); |
|
811 |
|
|
812 |
ns->so_faddr=so->so_faddr; |
|
813 |
ns->so_fport=htons(IPPORT_RESERVED-1); /* Use a fake port. */ |
|
814 |
|
|
815 |
if (ns->so_faddr.s_addr == 0 || |
|
816 |
ns->so_faddr.s_addr == loopback_addr.s_addr) |
|
817 |
ns->so_faddr = alias_addr; |
|
818 |
|
|
819 |
ns->so_iptos = tcp_tos(ns); |
|
820 |
tp = sototcpcb(ns); |
|
821 |
|
|
822 |
tcp_template(tp); |
|
823 |
|
|
824 |
/* Compute window scaling to request. */ |
|
825 |
/* while (tp->request_r_scale < TCP_MAX_WINSHIFT && |
|
826 |
* (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) |
|
827 |
* tp->request_r_scale++; |
|
828 |
*/ |
|
829 |
|
|
830 |
/*soisfconnecting(ns);*/ |
|
831 |
|
|
832 |
STAT(tcpstat.tcps_connattempt++); |
|
833 |
|
|
834 |
tp->t_state = TCPS_SYN_SENT; |
|
835 |
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; |
|
836 |
tp->iss = tcp_iss; |
|
837 |
tcp_iss += TCP_ISSINCR/2; |
|
838 |
tcp_sendseqinit(tp); |
|
839 |
tcp_output(tp); |
|
840 |
so->extra=ns; |
|
841 |
} |
|
842 |
while (ptr < so_rcv->sb_wptr) { |
|
843 |
if (*ptr++ == 0) { |
|
844 |
n++; |
|
845 |
if (n == 2) { |
|
846 |
user=ptr; |
|
847 |
} else if (n == 3) { |
|
848 |
args=ptr; |
|
849 |
} |
|
850 |
} |
|
851 |
} |
|
852 |
|
|
853 |
if (n != 4) |
|
854 |
return 0; |
|
855 |
|
|
856 |
rsh_exec(so,so->extra, user, inet_ntoa(so->so_faddr), args); |
|
857 |
so->so_emu = 0; |
|
858 |
so->extra=NULL; |
|
859 |
|
|
860 |
/* And finally, send the client a 0 character */ |
|
861 |
so_snd->sb_wptr[0] = 0; |
|
862 |
so_snd->sb_wptr++; |
|
863 |
so_snd->sb_cc++; |
|
864 |
|
|
865 |
return 0; |
|
866 |
} |
|
867 |
|
|
868 |
case EMU_CTL: |
|
869 |
{ |
|
870 |
int num; |
|
871 |
struct sbuf *so_snd = &so->so_snd; |
|
872 |
struct sbuf *so_rcv = &so->so_rcv; |
|
873 |
|
|
874 |
/* |
|
875 |
* If there is binary data here, we save it in so->so_m |
|
876 |
*/ |
|
877 |
if (!so->so_m) { |
|
878 |
int rxlen; |
|
879 |
char *rxdata; |
|
880 |
rxdata=mtod(m, char *); |
|
881 |
for (rxlen=m->m_len; rxlen; rxlen--) { |
|
882 |
if (*rxdata++ & 0x80) { |
|
883 |
so->so_m = m; |
|
884 |
return 0; |
|
885 |
} |
|
886 |
} |
|
887 |
} /* if(so->so_m==NULL) */ |
|
888 |
|
|
889 |
/* |
|
890 |
* Append the line |
|
891 |
*/ |
|
892 |
sbappendsb(so_rcv, m); |
|
893 |
|
|
894 |
/* To avoid going over the edge of the buffer, we reset it */ |
|
895 |
if (so_snd->sb_cc == 0) |
|
896 |
so_snd->sb_wptr = so_snd->sb_rptr = so_snd->sb_data; |
|
897 |
|
|
898 |
/* |
|
899 |
* A bit of a hack: |
|
900 |
* If the first packet we get here is 1 byte long, then it |
|
901 |
* was done in telnet character mode, therefore we must echo |
|
902 |
* the characters as they come. Otherwise, we echo nothing, |
|
903 |
* because in linemode, the line is already echoed |
|
904 |
* XXX two or more control connections won't work |
|
905 |
*/ |
|
906 |
if (do_echo == -1) { |
|
907 |
if (m->m_len == 1) do_echo = 1; |
|
908 |
else do_echo = 0; |
|
909 |
} |
|
910 |
if (do_echo) { |
|
911 |
sbappendsb(so_snd, m); |
|
912 |
m_free(m); |
|
913 |
tcp_output(sototcpcb(so)); /* XXX */ |
|
914 |
} else |
|
915 |
m_free(m); |
|
916 |
|
|
917 |
num = 0; |
|
918 |
while (num < so->so_rcv.sb_cc) { |
|
919 |
if (*(so->so_rcv.sb_rptr + num) == '\n' || |
|
920 |
*(so->so_rcv.sb_rptr + num) == '\r') { |
|
921 |
int n; |
|
922 |
|
|
923 |
*(so_rcv->sb_rptr + num) = 0; |
|
924 |
if (ctl_password && !ctl_password_ok) { |
|
925 |
/* Need a password */ |
|
926 |
if (sscanf(so_rcv->sb_rptr, "pass %256s", buff) == 1) { |
|
927 |
if (strcmp(buff, ctl_password) == 0) { |
|
928 |
ctl_password_ok = 1; |
|
929 |
n = sprintf(so_snd->sb_wptr, |
|
930 |
"Password OK.\r\n"); |
|
931 |
goto do_prompt; |
|
932 |
} |
|
933 |
} |
|
934 |
n = sprintf(so_snd->sb_wptr, |
|
935 |
"Error: Password required, log on with \"pass PASSWORD\"\r\n"); |
|
936 |
goto do_prompt; |
|
937 |
} |
|
938 |
cfg_quitting = 0; |
|
939 |
n = do_config(so_rcv->sb_rptr, so, PRN_SPRINTF); |
|
940 |
if (!cfg_quitting) { |
|
941 |
/* Register the printed data */ |
|
942 |
do_prompt: |
|
943 |
so_snd->sb_cc += n; |
|
944 |
so_snd->sb_wptr += n; |
|
945 |
/* Add prompt */ |
|
946 |
n = sprintf(so_snd->sb_wptr, "Slirp> "); |
|
947 |
so_snd->sb_cc += n; |
|
948 |
so_snd->sb_wptr += n; |
|
949 |
} |
|
950 |
/* Drop so_rcv data */ |
|
951 |
so_rcv->sb_cc = 0; |
|
952 |
so_rcv->sb_wptr = so_rcv->sb_rptr = so_rcv->sb_data; |
|
953 |
tcp_output(sototcpcb(so)); /* Send the reply */ |
|
954 |
} |
|
955 |
num++; |
|
956 |
} |
|
957 |
return 0; |
|
958 |
} |
|
959 |
#endif |
|
960 | 602 |
case EMU_FTP: /* ftp */ |
961 | 603 |
*(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */ |
962 | 604 |
if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) { |
... | ... | |
1100 | 742 |
* A typical packet for player version 1.0 (release version): |
1101 | 743 |
* |
1102 | 744 |
* 0000:50 4E 41 00 05 |
1103 |
* 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 .....?..g?l?c..P
|
|
745 |
* 0000:00 01 00 02 1B D7 00 00 67 E6 6C DC 63 00 12 50 ........g.l.c..P
|
|
1104 | 746 |
* 0010:4E 43 4C 49 45 4E 54 20 31 30 31 20 41 4C 50 48 NCLIENT 101 ALPH |
1105 | 747 |
* 0020:41 6C 00 00 52 00 17 72 61 66 69 6C 65 73 2F 76 Al..R..rafiles/v |
1106 | 748 |
* 0030:6F 61 2F 65 6E 67 6C 69 73 68 5F 2E 72 61 79 42 oa/english_.rayB |
... | ... | |
1112 | 754 |
* |
1113 | 755 |
* A typical packet for player version 2.0 (beta): |
1114 | 756 |
* |
1115 |
* 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA...........?.
|
|
1116 |
* 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .gux?c..Win2.0.0
|
|
757 |
* 0000:50 4E 41 00 06 00 02 00 00 00 01 00 02 1B C1 00 PNA.............
|
|
758 |
* 0010:00 67 75 78 F5 63 00 0A 57 69 6E 32 2E 30 2E 30 .gux.c..Win2.0.0
|
|
1117 | 759 |
* 0020:2E 35 6C 00 00 52 00 1C 72 61 66 69 6C 65 73 2F .5l..R..rafiles/ |
1118 | 760 |
* 0030:77 65 62 73 69 74 65 2F 32 30 72 65 6C 65 61 73 website/20releas |
1119 | 761 |
* 0040:65 2E 72 61 79 53 00 00 06 36 42 e.rayS...6B |
Also available in: Unified diff