diff options
Diffstat (limited to 'networking/parse_pasv_epsv.c')
-rw-r--r-- | networking/parse_pasv_epsv.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/networking/parse_pasv_epsv.c b/networking/parse_pasv_epsv.c new file mode 100644 index 000000000..14f4d4258 --- /dev/null +++ b/networking/parse_pasv_epsv.c | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Utility routines. | ||
3 | * | ||
4 | * Copyright (C) 2018 Denys Vlasenko | ||
5 | * | ||
6 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
7 | */ | ||
8 | //kbuild:lib-$(CONFIG_FTPGET) += parse_pasv_epsv.o | ||
9 | //kbuild:lib-$(CONFIG_FTPPUT) += parse_pasv_epsv.o | ||
10 | //kbuild:lib-$(CONFIG_WGET) += parse_pasv_epsv.o | ||
11 | |||
12 | #include "libbb.h" | ||
13 | |||
14 | int FAST_FUNC parse_pasv_epsv(char *buf) | ||
15 | { | ||
16 | /* | ||
17 | * PASV command will not work for IPv6. RFC2428 describes | ||
18 | * IPv6-capable "extended PASV" - EPSV. | ||
19 | * | ||
20 | * "EPSV [protocol]" asks server to bind to and listen on a data port | ||
21 | * in specified protocol. Protocol is 1 for IPv4, 2 for IPv6. | ||
22 | * If not specified, defaults to "same as used for control connection". | ||
23 | * If server understood you, it should answer "229 <some text>(|||port|)" | ||
24 | * where "|" are literal pipe chars and "port" is ASCII decimal port#. | ||
25 | * | ||
26 | * There is also an IPv6-capable replacement for PORT (EPRT), | ||
27 | * but we don't need that. | ||
28 | * | ||
29 | * NB: PASV may still work for some servers even over IPv6. | ||
30 | * For example, vsftp happily answers | ||
31 | * "227 Entering Passive Mode (0,0,0,0,n,n)" and proceeds as usual. | ||
32 | */ | ||
33 | char *ptr; | ||
34 | int port; | ||
35 | |||
36 | if (!ENABLE_FEATURE_IPV6 || buf[2] == '7' /* "227" */) { | ||
37 | /* Response is "227 garbageN1,N2,N3,N4,P1,P2[)garbage]" | ||
38 | * Server's IP is N1.N2.N3.N4 (we ignore it) | ||
39 | * Server's port for data connection is P1*256+P2 */ | ||
40 | ptr = strrchr(buf, ')'); | ||
41 | if (ptr) *ptr = '\0'; | ||
42 | |||
43 | ptr = strrchr(buf, ','); | ||
44 | if (!ptr) return -1; | ||
45 | *ptr = '\0'; | ||
46 | port = xatou_range(ptr + 1, 0, 255); | ||
47 | |||
48 | ptr = strrchr(buf, ','); | ||
49 | if (!ptr) return -1; | ||
50 | *ptr = '\0'; | ||
51 | port += xatou_range(ptr + 1, 0, 255) * 256; | ||
52 | } else { | ||
53 | /* Response is "229 garbage(|||P1|)" | ||
54 | * Server's port for data connection is P1 */ | ||
55 | ptr = strrchr(buf, '|'); | ||
56 | if (!ptr) return -1; | ||
57 | *ptr = '\0'; | ||
58 | |||
59 | ptr = strrchr(buf, '|'); | ||
60 | if (!ptr) return -1; | ||
61 | *ptr = '\0'; | ||
62 | port = xatou_range(ptr + 1, 0, 65535); | ||
63 | } | ||
64 | |||
65 | return port; | ||
66 | } | ||