Skip to content

Commit

Permalink
ipvs: add ipv6 support to ftp
Browse files Browse the repository at this point in the history
Add support for FTP commands with extended format (RFC 2428):

- FTP EPRT: IPv4 and IPv6, active mode, similar to PORT
- FTP EPSV: IPv4 and IPv6, passive mode, similar to PASV.
EPSV response usually contains only port but we allow real
server to provide different address

We restrict control and data connection to be from same
address family.

Allow the "(" and ")" to be optional in PASV response.

Also, add ipvsh argument to the pkt_in/pkt_out handlers to better
access the payload after transport header.

Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  • Loading branch information
Julian Anastasov authored and Pablo Neira Ayuso committed Jun 1, 2018
1 parent 0cfceb9 commit d12e122
Show file tree
Hide file tree
Showing 6 changed files with 331 additions and 182 deletions.
10 changes: 6 additions & 4 deletions include/net/ip_vs.h
Original file line number Diff line number Diff line change
Expand Up @@ -763,14 +763,14 @@ struct ip_vs_app {
* 2=Mangled but checksum was not updated
*/
int (*pkt_out)(struct ip_vs_app *, struct ip_vs_conn *,
struct sk_buff *, int *diff);
struct sk_buff *, int *diff, struct ip_vs_iphdr *ipvsh);

/* input hook: Process packet in outin direction, diff set for TCP.
* Return: 0=Error, 1=Payload Not Mangled/Mangled but checksum is ok,
* 2=Mangled but checksum was not updated
*/
int (*pkt_in)(struct ip_vs_app *, struct ip_vs_conn *,
struct sk_buff *, int *diff);
struct sk_buff *, int *diff, struct ip_vs_iphdr *ipvsh);

/* ip_vs_app initializer */
int (*init_conn)(struct ip_vs_app *, struct ip_vs_conn *);
Expand Down Expand Up @@ -1328,8 +1328,10 @@ int register_ip_vs_app_inc(struct netns_ipvs *ipvs, struct ip_vs_app *app, __u16
int ip_vs_app_inc_get(struct ip_vs_app *inc);
void ip_vs_app_inc_put(struct ip_vs_app *inc);

int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb);
int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb);
int ip_vs_app_pkt_out(struct ip_vs_conn *, struct sk_buff *skb,
struct ip_vs_iphdr *ipvsh);
int ip_vs_app_pkt_in(struct ip_vs_conn *, struct sk_buff *skb,
struct ip_vs_iphdr *ipvsh);

int register_ip_vs_pe(struct ip_vs_pe *pe);
int unregister_ip_vs_pe(struct ip_vs_pe *pe);
Expand Down
24 changes: 14 additions & 10 deletions net/netfilter/ipvs/ip_vs_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ static inline void vs_seq_update(struct ip_vs_conn *cp, struct ip_vs_seq *vseq,
}

static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,
struct ip_vs_app *app)
struct ip_vs_app *app,
struct ip_vs_iphdr *ipvsh)
{
int diff;
const unsigned int tcp_offset = ip_hdrlen(skb);
Expand Down Expand Up @@ -386,7 +387,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,
if (app->pkt_out == NULL)
return 1;

if (!app->pkt_out(app, cp, skb, &diff))
if (!app->pkt_out(app, cp, skb, &diff, ipvsh))
return 0;

/*
Expand All @@ -404,7 +405,8 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,
* called by ipvs packet handler, assumes previously checked cp!=NULL
* returns false if it can't handle packet (oom)
*/
int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb)
int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,
struct ip_vs_iphdr *ipvsh)
{
struct ip_vs_app *app;

Expand All @@ -417,20 +419,21 @@ int ip_vs_app_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb)

/* TCP is complicated */
if (cp->protocol == IPPROTO_TCP)
return app_tcp_pkt_out(cp, skb, app);
return app_tcp_pkt_out(cp, skb, app, ipvsh);

/*
* Call private output hook function
*/
if (app->pkt_out == NULL)
return 1;

return app->pkt_out(app, cp, skb, NULL);
return app->pkt_out(app, cp, skb, NULL, ipvsh);
}


static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,
struct ip_vs_app *app)
struct ip_vs_app *app,
struct ip_vs_iphdr *ipvsh)
{
int diff;
const unsigned int tcp_offset = ip_hdrlen(skb);
Expand Down Expand Up @@ -461,7 +464,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,
if (app->pkt_in == NULL)
return 1;

if (!app->pkt_in(app, cp, skb, &diff))
if (!app->pkt_in(app, cp, skb, &diff, ipvsh))
return 0;

/*
Expand All @@ -479,7 +482,8 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,
* called by ipvs packet handler, assumes previously checked cp!=NULL.
* returns false if can't handle packet (oom).
*/
int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb)
int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,
struct ip_vs_iphdr *ipvsh)
{
struct ip_vs_app *app;

Expand All @@ -492,15 +496,15 @@ int ip_vs_app_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb)

/* TCP is complicated */
if (cp->protocol == IPPROTO_TCP)
return app_tcp_pkt_in(cp, skb, app);
return app_tcp_pkt_in(cp, skb, app, ipvsh);

/*
* Call private input hook function
*/
if (app->pkt_in == NULL)
return 1;

return app->pkt_in(app, cp, skb, NULL);
return app->pkt_in(app, cp, skb, NULL, ipvsh);
}


Expand Down
Loading

0 comments on commit d12e122

Please sign in to comment.