Commit c860c6b1 authored by Julius Volz's avatar Julius Volz Committed by Simon Horman

IPVS: Add internal versions of sockopt interface structs

Add extended internal versions of struct ip_vs_service_user and struct
ip_vs_dest_user (the originals can't be modified as they are part
of the old sockopt interface). Adjust ip_vs_ctl.c to work with the new
data structures and add some minor AF-awareness.
Signed-off-by: default avatarJulius Volz <juliusv@google.com>
Signed-off-by: default avatarSimon Horman <horms@verge.net.au>
parent c842a3ad
...@@ -399,6 +399,45 @@ struct ip_vs_conn { ...@@ -399,6 +399,45 @@ struct ip_vs_conn {
}; };
/*
* Extended internal versions of struct ip_vs_service_user and
* ip_vs_dest_user for IPv6 support.
*
* We need these to conveniently pass around service and destination
* options, but unfortunately, we also need to keep the old definitions to
* maintain userspace backwards compatibility for the setsockopt interface.
*/
struct ip_vs_service_user_kern {
/* virtual service addresses */
u16 af;
u16 protocol;
union nf_inet_addr addr; /* virtual ip address */
u16 port;
u32 fwmark; /* firwall mark of service */
/* virtual service options */
char *sched_name;
unsigned flags; /* virtual service flags */
unsigned timeout; /* persistent timeout in sec */
u32 netmask; /* persistent netmask */
};
struct ip_vs_dest_user_kern {
/* destination server address */
union nf_inet_addr addr;
u16 port;
/* real server options */
unsigned conn_flags; /* connection flags */
int weight; /* destination weight */
/* thresholds for active connections */
u32 u_threshold; /* upper threshold */
u32 l_threshold; /* lower threshold */
};
/* /*
* The information about the virtual service offered to the net * The information about the virtual service offered to the net
* and the forwarding entries * and the forwarding entries
......
...@@ -708,7 +708,7 @@ ip_vs_zero_stats(struct ip_vs_stats *stats) ...@@ -708,7 +708,7 @@ ip_vs_zero_stats(struct ip_vs_stats *stats)
*/ */
static void static void
__ip_vs_update_dest(struct ip_vs_service *svc, __ip_vs_update_dest(struct ip_vs_service *svc,
struct ip_vs_dest *dest, struct ip_vs_dest_user *udest) struct ip_vs_dest *dest, struct ip_vs_dest_user_kern *udest)
{ {
int conn_flags; int conn_flags;
...@@ -717,7 +717,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, ...@@ -717,7 +717,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc,
conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE; conn_flags = udest->conn_flags | IP_VS_CONN_F_INACTIVE;
/* check if local node and update the flags */ /* check if local node and update the flags */
if (inet_addr_type(&init_net, udest->addr) == RTN_LOCAL) { if (inet_addr_type(&init_net, udest->addr.ip) == RTN_LOCAL) {
conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK) conn_flags = (conn_flags & ~IP_VS_CONN_F_FWD_MASK)
| IP_VS_CONN_F_LOCALNODE; | IP_VS_CONN_F_LOCALNODE;
} }
...@@ -761,7 +761,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, ...@@ -761,7 +761,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc,
* Create a destination for the given service * Create a destination for the given service
*/ */
static int static int
ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest, ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
struct ip_vs_dest **dest_p) struct ip_vs_dest **dest_p)
{ {
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
...@@ -769,7 +769,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest, ...@@ -769,7 +769,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest,
EnterFunction(2); EnterFunction(2);
atype = inet_addr_type(&init_net, udest->addr); atype = inet_addr_type(&init_net, udest->addr.ip);
if (atype != RTN_LOCAL && atype != RTN_UNICAST) if (atype != RTN_LOCAL && atype != RTN_UNICAST)
return -EINVAL; return -EINVAL;
...@@ -779,11 +779,12 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest, ...@@ -779,11 +779,12 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest,
return -ENOMEM; return -ENOMEM;
} }
dest->af = svc->af;
dest->protocol = svc->protocol; dest->protocol = svc->protocol;
dest->vaddr.ip = svc->addr.ip; dest->vaddr = svc->addr;
dest->vport = svc->port; dest->vport = svc->port;
dest->vfwmark = svc->fwmark; dest->vfwmark = svc->fwmark;
dest->addr.ip = udest->addr; ip_vs_addr_copy(svc->af, &dest->addr, &udest->addr);
dest->port = udest->port; dest->port = udest->port;
atomic_set(&dest->activeconns, 0); atomic_set(&dest->activeconns, 0);
...@@ -808,10 +809,10 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest, ...@@ -808,10 +809,10 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest,
* Add a destination into an existing service * Add a destination into an existing service
*/ */
static int static int
ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
{ {
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
__be32 daddr = udest->addr; union nf_inet_addr daddr;
__be16 dport = udest->port; __be16 dport = udest->port;
int ret; int ret;
...@@ -828,10 +829,12 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) ...@@ -828,10 +829,12 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
return -ERANGE; return -ERANGE;
} }
ip_vs_addr_copy(svc->af, &daddr, &udest->addr);
/* /*
* Check if the dest already exists in the list * Check if the dest already exists in the list
*/ */
dest = ip_vs_lookup_dest(svc, daddr, dport); dest = ip_vs_lookup_dest(svc, daddr.ip, dport);
if (dest != NULL) { if (dest != NULL) {
IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n"); IP_VS_DBG(1, "ip_vs_add_dest(): dest already exists\n");
return -EEXIST; return -EEXIST;
...@@ -841,7 +844,7 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) ...@@ -841,7 +844,7 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
* Check if the dest already exists in the trash and * Check if the dest already exists in the trash and
* is from the same service * is from the same service
*/ */
dest = ip_vs_trash_get_dest(svc, daddr, dport); dest = ip_vs_trash_get_dest(svc, daddr.ip, dport);
if (dest != NULL) { if (dest != NULL) {
IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, " IP_VS_DBG(3, "Get destination %u.%u.%u.%u:%u from trash, "
"dest->refcnt=%d, service %u/%u.%u.%u.%u:%u\n", "dest->refcnt=%d, service %u/%u.%u.%u.%u:%u\n",
...@@ -916,10 +919,10 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) ...@@ -916,10 +919,10 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
* Edit a destination in the given service * Edit a destination in the given service
*/ */
static int static int
ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
{ {
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
__be32 daddr = udest->addr; union nf_inet_addr daddr;
__be16 dport = udest->port; __be16 dport = udest->port;
EnterFunction(2); EnterFunction(2);
...@@ -935,10 +938,12 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest) ...@@ -935,10 +938,12 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user *udest)
return -ERANGE; return -ERANGE;
} }
ip_vs_addr_copy(svc->af, &daddr, &udest->addr);
/* /*
* Lookup the destination list * Lookup the destination list
*/ */
dest = ip_vs_lookup_dest(svc, daddr, dport); dest = ip_vs_lookup_dest(svc, daddr.ip, dport);
if (dest == NULL) { if (dest == NULL) {
IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n"); IP_VS_DBG(1, "ip_vs_edit_dest(): dest doesn't exist\n");
return -ENOENT; return -ENOENT;
...@@ -1029,15 +1034,15 @@ static void __ip_vs_unlink_dest(struct ip_vs_service *svc, ...@@ -1029,15 +1034,15 @@ static void __ip_vs_unlink_dest(struct ip_vs_service *svc,
* Delete a destination server in the given service * Delete a destination server in the given service
*/ */
static int static int
ip_vs_del_dest(struct ip_vs_service *svc,struct ip_vs_dest_user *udest) ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
{ {
struct ip_vs_dest *dest; struct ip_vs_dest *dest;
__be32 daddr = udest->addr;
__be16 dport = udest->port; __be16 dport = udest->port;
EnterFunction(2); EnterFunction(2);
dest = ip_vs_lookup_dest(svc, daddr, dport); dest = ip_vs_lookup_dest(svc, udest->addr.ip, dport);
if (dest == NULL) { if (dest == NULL) {
IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n"); IP_VS_DBG(1, "ip_vs_del_dest(): destination not found!\n");
return -ENOENT; return -ENOENT;
...@@ -1072,7 +1077,8 @@ ip_vs_del_dest(struct ip_vs_service *svc,struct ip_vs_dest_user *udest) ...@@ -1072,7 +1077,8 @@ ip_vs_del_dest(struct ip_vs_service *svc,struct ip_vs_dest_user *udest)
* Add a service into the service hash table * Add a service into the service hash table
*/ */
static int static int
ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p) ip_vs_add_service(struct ip_vs_service_user_kern *u,
struct ip_vs_service **svc_p)
{ {
int ret = 0; int ret = 0;
struct ip_vs_scheduler *sched = NULL; struct ip_vs_scheduler *sched = NULL;
...@@ -1101,8 +1107,9 @@ ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p) ...@@ -1101,8 +1107,9 @@ ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p)
atomic_set(&svc->usecnt, 1); atomic_set(&svc->usecnt, 1);
atomic_set(&svc->refcnt, 0); atomic_set(&svc->refcnt, 0);
svc->af = u->af;
svc->protocol = u->protocol; svc->protocol = u->protocol;
svc->addr.ip = u->addr; ip_vs_addr_copy(svc->af, &svc->addr, &u->addr);
svc->port = u->port; svc->port = u->port;
svc->fwmark = u->fwmark; svc->fwmark = u->fwmark;
svc->flags = u->flags; svc->flags = u->flags;
...@@ -1161,7 +1168,7 @@ ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p) ...@@ -1161,7 +1168,7 @@ ip_vs_add_service(struct ip_vs_service_user *u, struct ip_vs_service **svc_p)
* Edit a service and bind it with a new scheduler * Edit a service and bind it with a new scheduler
*/ */
static int static int
ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user *u) ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
{ {
struct ip_vs_scheduler *sched, *old_sched; struct ip_vs_scheduler *sched, *old_sched;
int ret = 0; int ret = 0;
...@@ -1905,14 +1912,44 @@ static const unsigned char set_arglen[SET_CMDID(IP_VS_SO_SET_MAX)+1] = { ...@@ -1905,14 +1912,44 @@ static const unsigned char set_arglen[SET_CMDID(IP_VS_SO_SET_MAX)+1] = {
[SET_CMDID(IP_VS_SO_SET_ZERO)] = SERVICE_ARG_LEN, [SET_CMDID(IP_VS_SO_SET_ZERO)] = SERVICE_ARG_LEN,
}; };
static void ip_vs_copy_usvc_compat(struct ip_vs_service_user_kern *usvc,
struct ip_vs_service_user *usvc_compat)
{
usvc->af = AF_INET;
usvc->protocol = usvc_compat->protocol;
usvc->addr.ip = usvc_compat->addr;
usvc->port = usvc_compat->port;
usvc->fwmark = usvc_compat->fwmark;
/* Deep copy of sched_name is not needed here */
usvc->sched_name = usvc_compat->sched_name;
usvc->flags = usvc_compat->flags;
usvc->timeout = usvc_compat->timeout;
usvc->netmask = usvc_compat->netmask;
}
static void ip_vs_copy_udest_compat(struct ip_vs_dest_user_kern *udest,
struct ip_vs_dest_user *udest_compat)
{
udest->addr.ip = udest_compat->addr;
udest->port = udest_compat->port;
udest->conn_flags = udest_compat->conn_flags;
udest->weight = udest_compat->weight;
udest->u_threshold = udest_compat->u_threshold;
udest->l_threshold = udest_compat->l_threshold;
}
static int static int
do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
{ {
int ret; int ret;
unsigned char arg[MAX_ARG_LEN]; unsigned char arg[MAX_ARG_LEN];
struct ip_vs_service_user *usvc; struct ip_vs_service_user *usvc_compat;
struct ip_vs_service_user_kern usvc;
struct ip_vs_service *svc; struct ip_vs_service *svc;
struct ip_vs_dest_user *udest; struct ip_vs_dest_user *udest_compat;
struct ip_vs_dest_user_kern udest;
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
...@@ -1952,35 +1989,40 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) ...@@ -1952,35 +1989,40 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
goto out_unlock; goto out_unlock;
} }
usvc = (struct ip_vs_service_user *)arg; usvc_compat = (struct ip_vs_service_user *)arg;
udest = (struct ip_vs_dest_user *)(usvc + 1); udest_compat = (struct ip_vs_dest_user *)(usvc_compat + 1);
/* We only use the new structs internally, so copy userspace compat
* structs to extended internal versions */
ip_vs_copy_usvc_compat(&usvc, usvc_compat);
ip_vs_copy_udest_compat(&udest, udest_compat);
if (cmd == IP_VS_SO_SET_ZERO) { if (cmd == IP_VS_SO_SET_ZERO) {
/* if no service address is set, zero counters in all */ /* if no service address is set, zero counters in all */
if (!usvc->fwmark && !usvc->addr && !usvc->port) { if (!usvc.fwmark && !usvc.addr.ip && !usvc.port) {
ret = ip_vs_zero_all(); ret = ip_vs_zero_all();
goto out_unlock; goto out_unlock;
} }
} }
/* Check for valid protocol: TCP or UDP, even for fwmark!=0 */ /* Check for valid protocol: TCP or UDP, even for fwmark!=0 */
if (usvc->protocol!=IPPROTO_TCP && usvc->protocol!=IPPROTO_UDP) { if (usvc.protocol != IPPROTO_TCP && usvc.protocol != IPPROTO_UDP) {
IP_VS_ERR("set_ctl: invalid protocol: %d %d.%d.%d.%d:%d %s\n", IP_VS_ERR("set_ctl: invalid protocol: %d %d.%d.%d.%d:%d %s\n",
usvc->protocol, NIPQUAD(usvc->addr), usvc.protocol, NIPQUAD(usvc.addr.ip),
ntohs(usvc->port), usvc->sched_name); ntohs(usvc.port), usvc.sched_name);
ret = -EFAULT; ret = -EFAULT;
goto out_unlock; goto out_unlock;
} }
/* Lookup the exact service by <protocol, addr, port> or fwmark */ /* Lookup the exact service by <protocol, addr, port> or fwmark */
if (usvc->fwmark == 0) if (usvc.fwmark == 0)
svc = __ip_vs_service_get(usvc->protocol, svc = __ip_vs_service_get(usvc.protocol,
usvc->addr, usvc->port); usvc.addr.ip, usvc.port);
else else
svc = __ip_vs_svc_fwm_get(usvc->fwmark); svc = __ip_vs_svc_fwm_get(usvc.fwmark);
if (cmd != IP_VS_SO_SET_ADD if (cmd != IP_VS_SO_SET_ADD
&& (svc == NULL || svc->protocol != usvc->protocol)) { && (svc == NULL || svc->protocol != usvc.protocol)) {
ret = -ESRCH; ret = -ESRCH;
goto out_unlock; goto out_unlock;
} }
...@@ -1990,10 +2032,10 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) ...@@ -1990,10 +2032,10 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
if (svc != NULL) if (svc != NULL)
ret = -EEXIST; ret = -EEXIST;
else else
ret = ip_vs_add_service(usvc, &svc); ret = ip_vs_add_service(&usvc, &svc);
break; break;
case IP_VS_SO_SET_EDIT: case IP_VS_SO_SET_EDIT:
ret = ip_vs_edit_service(svc, usvc); ret = ip_vs_edit_service(svc, &usvc);
break; break;
case IP_VS_SO_SET_DEL: case IP_VS_SO_SET_DEL:
ret = ip_vs_del_service(svc); ret = ip_vs_del_service(svc);
...@@ -2004,13 +2046,13 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) ...@@ -2004,13 +2046,13 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
ret = ip_vs_zero_service(svc); ret = ip_vs_zero_service(svc);
break; break;
case IP_VS_SO_SET_ADDDEST: case IP_VS_SO_SET_ADDDEST:
ret = ip_vs_add_dest(svc, udest); ret = ip_vs_add_dest(svc, &udest);
break; break;
case IP_VS_SO_SET_EDITDEST: case IP_VS_SO_SET_EDITDEST:
ret = ip_vs_edit_dest(svc, udest); ret = ip_vs_edit_dest(svc, &udest);
break; break;
case IP_VS_SO_SET_DELDEST: case IP_VS_SO_SET_DELDEST:
ret = ip_vs_del_dest(svc, udest); ret = ip_vs_del_dest(svc, &udest);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
...@@ -2517,7 +2559,7 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb, ...@@ -2517,7 +2559,7 @@ static int ip_vs_genl_dump_services(struct sk_buff *skb,
return skb->len; return skb->len;
} }
static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc, static int ip_vs_genl_parse_service(struct ip_vs_service_user_kern *usvc,
struct nlattr *nla, int full_entry) struct nlattr *nla, int full_entry)
{ {
struct nlattr *attrs[IPVS_SVC_ATTR_MAX + 1]; struct nlattr *attrs[IPVS_SVC_ATTR_MAX + 1];
...@@ -2537,6 +2579,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc, ...@@ -2537,6 +2579,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc,
if (!(nla_af && (nla_fwmark || (nla_port && nla_protocol && nla_addr)))) if (!(nla_af && (nla_fwmark || (nla_port && nla_protocol && nla_addr))))
return -EINVAL; return -EINVAL;
usvc->af = nla_get_u16(nla_af);
/* For now, only support IPv4 */ /* For now, only support IPv4 */
if (nla_get_u16(nla_af) != AF_INET) if (nla_get_u16(nla_af) != AF_INET)
return -EAFNOSUPPORT; return -EAFNOSUPPORT;
...@@ -2572,7 +2615,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc, ...@@ -2572,7 +2615,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc,
if (usvc->fwmark) if (usvc->fwmark)
svc = __ip_vs_svc_fwm_get(usvc->fwmark); svc = __ip_vs_svc_fwm_get(usvc->fwmark);
else else
svc = __ip_vs_service_get(usvc->protocol, usvc->addr, svc = __ip_vs_service_get(usvc->protocol, usvc->addr.ip,
usvc->port); usvc->port);
if (svc) { if (svc) {
usvc->flags = svc->flags; usvc->flags = svc->flags;
...@@ -2583,9 +2626,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc, ...@@ -2583,9 +2626,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc,
/* set new flags from userland */ /* set new flags from userland */
usvc->flags = (usvc->flags & ~flags.mask) | usvc->flags = (usvc->flags & ~flags.mask) |
(flags.flags & flags.mask); (flags.flags & flags.mask);
usvc->sched_name = nla_data(nla_sched);
strlcpy(usvc->sched_name, nla_data(nla_sched),
sizeof(usvc->sched_name));
usvc->timeout = nla_get_u32(nla_timeout); usvc->timeout = nla_get_u32(nla_timeout);
usvc->netmask = nla_get_u32(nla_netmask); usvc->netmask = nla_get_u32(nla_netmask);
} }
...@@ -2595,7 +2636,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc, ...@@ -2595,7 +2636,7 @@ static int ip_vs_genl_parse_service(struct ip_vs_service_user *usvc,
static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla) static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla)
{ {
struct ip_vs_service_user usvc; struct ip_vs_service_user_kern usvc;
int ret; int ret;
ret = ip_vs_genl_parse_service(&usvc, nla, 0); ret = ip_vs_genl_parse_service(&usvc, nla, 0);
...@@ -2605,7 +2646,7 @@ static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla) ...@@ -2605,7 +2646,7 @@ static struct ip_vs_service *ip_vs_genl_find_service(struct nlattr *nla)
if (usvc.fwmark) if (usvc.fwmark)
return __ip_vs_svc_fwm_get(usvc.fwmark); return __ip_vs_svc_fwm_get(usvc.fwmark);
else else
return __ip_vs_service_get(usvc.protocol, usvc.addr, return __ip_vs_service_get(usvc.protocol, usvc.addr.ip,
usvc.port); usvc.port);
} }
...@@ -2705,7 +2746,7 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb, ...@@ -2705,7 +2746,7 @@ static int ip_vs_genl_dump_dests(struct sk_buff *skb,
return skb->len; return skb->len;
} }
static int ip_vs_genl_parse_dest(struct ip_vs_dest_user *udest, static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
struct nlattr *nla, int full_entry) struct nlattr *nla, int full_entry)
{ {
struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1]; struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1];
...@@ -2861,8 +2902,8 @@ static int ip_vs_genl_set_config(struct nlattr **attrs) ...@@ -2861,8 +2902,8 @@ static int ip_vs_genl_set_config(struct nlattr **attrs)
static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
{ {
struct ip_vs_service *svc = NULL; struct ip_vs_service *svc = NULL;
struct ip_vs_service_user usvc; struct ip_vs_service_user_kern usvc;
struct ip_vs_dest_user udest; struct ip_vs_dest_user_kern udest;
int ret = 0, cmd; int ret = 0, cmd;
int need_full_svc = 0, need_full_dest = 0; int need_full_svc = 0, need_full_dest = 0;
...@@ -2914,7 +2955,8 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info) ...@@ -2914,7 +2955,8 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
/* Lookup the exact service by <protocol, addr, port> or fwmark */ /* Lookup the exact service by <protocol, addr, port> or fwmark */
if (usvc.fwmark == 0) if (usvc.fwmark == 0)
svc = __ip_vs_service_get(usvc.protocol, usvc.addr, usvc.port); svc = __ip_vs_service_get(usvc.protocol, usvc.addr.ip,
usvc.port);
else else
svc = __ip_vs_svc_fwm_get(usvc.fwmark); svc = __ip_vs_svc_fwm_get(usvc.fwmark);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment