Commit 0af03170 authored by Xin Long's avatar Xin Long Committed by David S. Miller

sctp: add dif and sdif check in asoc and ep lookup

This patch at first adds a pernet global l3mdev_accept to decide if it
accepts the packets from a l3mdev when a SCTP socket doesn't bind to
any interface. It's set to 1 to avoid any possible incompatible issue,
and in next patch, a sysctl will be introduced to allow to change it.

Then similar to inet/udp_sk_bound_dev_eq(), sctp_sk_bound_dev_eq() is
added to check either dif or sdif is equal to sk_bound_dev_if, and to
check sid is 0 or l3mdev_accept is 1 if sk_bound_dev_if is not set.
This function is used to match a association or a endpoint, namely
called by sctp_addrs_lookup_transport() and sctp_endpoint_is_match().
All functions that needs updating are:

sctp_rcv():
  asoc:
  __sctp_rcv_lookup()
    __sctp_lookup_association() -> sctp_addrs_lookup_transport()
    __sctp_rcv_lookup_harder()
      __sctp_rcv_init_lookup()
         __sctp_lookup_association() -> sctp_addrs_lookup_transport()
      __sctp_rcv_walk_lookup()
         __sctp_rcv_asconf_lookup()
           __sctp_lookup_association() -> sctp_addrs_lookup_transport()

  ep:
  __sctp_rcv_lookup_endpoint() -> sctp_endpoint_is_match()

sctp_connect():
  sctp_endpoint_is_peeled_off()
    __sctp_lookup_association()
      sctp_has_association()
        sctp_lookup_association()
          __sctp_lookup_association() -> sctp_addrs_lookup_transport()

sctp_diag_dump_one():
  sctp_transport_lookup_process() -> sctp_addrs_lookup_transport()
Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 33e93ed2
...@@ -175,6 +175,10 @@ struct netns_sctp { ...@@ -175,6 +175,10 @@ struct netns_sctp {
/* Threshold for autoclose timeout, in seconds. */ /* Threshold for autoclose timeout, in seconds. */
unsigned long max_autoclose; unsigned long max_autoclose;
#ifdef CONFIG_NET_L3_MASTER_DEV
int l3mdev_accept;
#endif
}; };
#endif /* __NETNS_SCTP_H__ */ #endif /* __NETNS_SCTP_H__ */
...@@ -109,7 +109,7 @@ struct sctp_transport *sctp_transport_get_idx(struct net *net, ...@@ -109,7 +109,7 @@ struct sctp_transport *sctp_transport_get_idx(struct net *net,
struct rhashtable_iter *iter, int pos); struct rhashtable_iter *iter, int pos);
int sctp_transport_lookup_process(sctp_callback_t cb, struct net *net, int sctp_transport_lookup_process(sctp_callback_t cb, struct net *net,
const union sctp_addr *laddr, const union sctp_addr *laddr,
const union sctp_addr *paddr, void *p); const union sctp_addr *paddr, void *p, int dif);
int sctp_transport_traverse_process(sctp_callback_t cb, sctp_callback_t cb_done, int sctp_transport_traverse_process(sctp_callback_t cb, sctp_callback_t cb_done,
struct net *net, int *pos, void *p); struct net *net, int *pos, void *p);
int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), void *p); int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), void *p);
...@@ -157,10 +157,12 @@ void sctp_unhash_transport(struct sctp_transport *t); ...@@ -157,10 +157,12 @@ void sctp_unhash_transport(struct sctp_transport *t);
struct sctp_transport *sctp_addrs_lookup_transport( struct sctp_transport *sctp_addrs_lookup_transport(
struct net *net, struct net *net,
const union sctp_addr *laddr, const union sctp_addr *laddr,
const union sctp_addr *paddr); const union sctp_addr *paddr,
int dif, int sdif);
struct sctp_transport *sctp_epaddr_lookup_transport( struct sctp_transport *sctp_epaddr_lookup_transport(
const struct sctp_endpoint *ep, const struct sctp_endpoint *ep,
const union sctp_addr *paddr); const union sctp_addr *paddr);
bool sctp_sk_bound_dev_eq(struct net *net, int bound_dev_if, int dif, int sdif);
/* /*
* sctp/proc.c * sctp/proc.c
......
...@@ -1379,10 +1379,12 @@ struct sctp_association *sctp_endpoint_lookup_assoc( ...@@ -1379,10 +1379,12 @@ struct sctp_association *sctp_endpoint_lookup_assoc(
struct sctp_transport **); struct sctp_transport **);
bool sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, bool sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
const union sctp_addr *paddr); const union sctp_addr *paddr);
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *, struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
struct net *, const union sctp_addr *); struct net *net,
const union sctp_addr *laddr,
int dif, int sdif);
bool sctp_has_association(struct net *net, const union sctp_addr *laddr, bool sctp_has_association(struct net *net, const union sctp_addr *laddr,
const union sctp_addr *paddr); const union sctp_addr *paddr, int dif, int sdif);
int sctp_verify_init(struct net *net, const struct sctp_endpoint *ep, int sctp_verify_init(struct net *net, const struct sctp_endpoint *ep,
const struct sctp_association *asoc, const struct sctp_association *asoc,
......
...@@ -426,6 +426,7 @@ static int sctp_diag_dump_one(struct netlink_callback *cb, ...@@ -426,6 +426,7 @@ static int sctp_diag_dump_one(struct netlink_callback *cb,
struct net *net = sock_net(skb->sk); struct net *net = sock_net(skb->sk);
const struct nlmsghdr *nlh = cb->nlh; const struct nlmsghdr *nlh = cb->nlh;
union sctp_addr laddr, paddr; union sctp_addr laddr, paddr;
int dif = req->id.idiag_if;
struct sctp_comm_param commp = { struct sctp_comm_param commp = {
.skb = skb, .skb = skb,
.r = req, .r = req,
...@@ -454,7 +455,7 @@ static int sctp_diag_dump_one(struct netlink_callback *cb, ...@@ -454,7 +455,7 @@ static int sctp_diag_dump_one(struct netlink_callback *cb,
} }
return sctp_transport_lookup_process(sctp_sock_dump_one, return sctp_transport_lookup_process(sctp_sock_dump_one,
net, &laddr, &paddr, &commp); net, &laddr, &paddr, &commp, dif);
} }
static void sctp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, static void sctp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
......
...@@ -246,12 +246,15 @@ void sctp_endpoint_put(struct sctp_endpoint *ep) ...@@ -246,12 +246,15 @@ void sctp_endpoint_put(struct sctp_endpoint *ep)
/* Is this the endpoint we are looking for? */ /* Is this the endpoint we are looking for? */
struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
struct net *net, struct net *net,
const union sctp_addr *laddr) const union sctp_addr *laddr,
int dif, int sdif)
{ {
int bound_dev_if = READ_ONCE(ep->base.sk->sk_bound_dev_if);
struct sctp_endpoint *retval = NULL; struct sctp_endpoint *retval = NULL;
if ((htons(ep->base.bind_addr.port) == laddr->v4.sin_port) && if (net_eq(ep->base.net, net) &&
net_eq(ep->base.net, net)) { sctp_sk_bound_dev_eq(net, bound_dev_if, dif, sdif) &&
(htons(ep->base.bind_addr.port) == laddr->v4.sin_port)) {
if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
sctp_sk(ep->base.sk))) sctp_sk(ep->base.sk)))
retval = ep; retval = ep;
...@@ -298,6 +301,7 @@ struct sctp_association *sctp_endpoint_lookup_assoc( ...@@ -298,6 +301,7 @@ struct sctp_association *sctp_endpoint_lookup_assoc(
bool sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, bool sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
const union sctp_addr *paddr) const union sctp_addr *paddr)
{ {
int bound_dev_if = READ_ONCE(ep->base.sk->sk_bound_dev_if);
struct sctp_sockaddr_entry *addr; struct sctp_sockaddr_entry *addr;
struct net *net = ep->base.net; struct net *net = ep->base.net;
struct sctp_bind_addr *bp; struct sctp_bind_addr *bp;
...@@ -307,7 +311,8 @@ bool sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, ...@@ -307,7 +311,8 @@ bool sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
* so the address_list can not change. * so the address_list can not change.
*/ */
list_for_each_entry(addr, &bp->address_list, list) { list_for_each_entry(addr, &bp->address_list, list) {
if (sctp_has_association(net, &addr->a, paddr)) if (sctp_has_association(net, &addr->a, paddr,
bound_dev_if, bound_dev_if))
return true; return true;
} }
......
...@@ -50,16 +50,19 @@ static struct sctp_association *__sctp_rcv_lookup(struct net *net, ...@@ -50,16 +50,19 @@ static struct sctp_association *__sctp_rcv_lookup(struct net *net,
struct sk_buff *skb, struct sk_buff *skb,
const union sctp_addr *paddr, const union sctp_addr *paddr,
const union sctp_addr *laddr, const union sctp_addr *laddr,
struct sctp_transport **transportp); struct sctp_transport **transportp,
int dif, int sdif);
static struct sctp_endpoint *__sctp_rcv_lookup_endpoint( static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(
struct net *net, struct sk_buff *skb, struct net *net, struct sk_buff *skb,
const union sctp_addr *laddr, const union sctp_addr *laddr,
const union sctp_addr *daddr); const union sctp_addr *daddr,
int dif, int sdif);
static struct sctp_association *__sctp_lookup_association( static struct sctp_association *__sctp_lookup_association(
struct net *net, struct net *net,
const union sctp_addr *local, const union sctp_addr *local,
const union sctp_addr *peer, const union sctp_addr *peer,
struct sctp_transport **pt); struct sctp_transport **pt,
int dif, int sdif);
static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb); static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
...@@ -92,11 +95,11 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -92,11 +95,11 @@ int sctp_rcv(struct sk_buff *skb)
struct sctp_chunk *chunk; struct sctp_chunk *chunk;
union sctp_addr src; union sctp_addr src;
union sctp_addr dest; union sctp_addr dest;
int bound_dev_if;
int family; int family;
struct sctp_af *af; struct sctp_af *af;
struct net *net = dev_net(skb->dev); struct net *net = dev_net(skb->dev);
bool is_gso = skb_is_gso(skb) && skb_is_gso_sctp(skb); bool is_gso = skb_is_gso(skb) && skb_is_gso_sctp(skb);
int dif, sdif;
if (skb->pkt_type != PACKET_HOST) if (skb->pkt_type != PACKET_HOST)
goto discard_it; goto discard_it;
...@@ -141,6 +144,8 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -141,6 +144,8 @@ int sctp_rcv(struct sk_buff *skb)
/* Initialize local addresses for lookups. */ /* Initialize local addresses for lookups. */
af->from_skb(&src, skb, 1); af->from_skb(&src, skb, 1);
af->from_skb(&dest, skb, 0); af->from_skb(&dest, skb, 0);
dif = af->skb_iif(skb);
sdif = af->skb_sdif(skb);
/* If the packet is to or from a non-unicast address, /* If the packet is to or from a non-unicast address,
* silently discard the packet. * silently discard the packet.
...@@ -157,35 +162,15 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -157,35 +162,15 @@ int sctp_rcv(struct sk_buff *skb)
!af->addr_valid(&dest, NULL, skb)) !af->addr_valid(&dest, NULL, skb))
goto discard_it; goto discard_it;
asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport); asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport, dif, sdif);
if (!asoc) if (!asoc)
ep = __sctp_rcv_lookup_endpoint(net, skb, &dest, &src); ep = __sctp_rcv_lookup_endpoint(net, skb, &dest, &src, dif, sdif);
/* Retrieve the common input handling substructure. */ /* Retrieve the common input handling substructure. */
rcvr = asoc ? &asoc->base : &ep->base; rcvr = asoc ? &asoc->base : &ep->base;
sk = rcvr->sk; sk = rcvr->sk;
/*
* If a frame arrives on an interface and the receiving socket is
* bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
*/
bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
if (bound_dev_if && (bound_dev_if != af->skb_iif(skb))) {
if (transport) {
sctp_transport_put(transport);
asoc = NULL;
transport = NULL;
} else {
sctp_endpoint_put(ep);
ep = NULL;
}
sk = net->sctp.ctl_sock;
ep = sctp_sk(sk)->ep;
sctp_endpoint_hold(ep);
rcvr = &ep->base;
}
/* /*
* RFC 2960, 8.4 - Handle "Out of the blue" Packets. * RFC 2960, 8.4 - Handle "Out of the blue" Packets.
* An SCTP packet is called an "out of the blue" (OOTB) * An SCTP packet is called an "out of the blue" (OOTB)
...@@ -485,6 +470,8 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, ...@@ -485,6 +470,8 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
struct sctp_association *asoc; struct sctp_association *asoc;
struct sctp_transport *transport = NULL; struct sctp_transport *transport = NULL;
__u32 vtag = ntohl(sctphdr->vtag); __u32 vtag = ntohl(sctphdr->vtag);
int sdif = inet_sdif(skb);
int dif = inet_iif(skb);
*app = NULL; *tpp = NULL; *app = NULL; *tpp = NULL;
...@@ -500,7 +487,7 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, ...@@ -500,7 +487,7 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
/* Look for an association that matches the incoming ICMP error /* Look for an association that matches the incoming ICMP error
* packet. * packet.
*/ */
asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport); asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport, dif, sdif);
if (!asoc) if (!asoc)
return NULL; return NULL;
...@@ -850,7 +837,8 @@ static inline __u32 sctp_hashfn(const struct net *net, __be16 lport, ...@@ -850,7 +837,8 @@ static inline __u32 sctp_hashfn(const struct net *net, __be16 lport,
static struct sctp_endpoint *__sctp_rcv_lookup_endpoint( static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(
struct net *net, struct sk_buff *skb, struct net *net, struct sk_buff *skb,
const union sctp_addr *laddr, const union sctp_addr *laddr,
const union sctp_addr *paddr) const union sctp_addr *paddr,
int dif, int sdif)
{ {
struct sctp_hashbucket *head; struct sctp_hashbucket *head;
struct sctp_endpoint *ep; struct sctp_endpoint *ep;
...@@ -863,7 +851,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint( ...@@ -863,7 +851,7 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(
head = &sctp_ep_hashtable[hash]; head = &sctp_ep_hashtable[hash];
read_lock(&head->lock); read_lock(&head->lock);
sctp_for_each_hentry(ep, &head->chain) { sctp_for_each_hentry(ep, &head->chain) {
if (sctp_endpoint_is_match(ep, net, laddr)) if (sctp_endpoint_is_match(ep, net, laddr, dif, sdif))
goto hit; goto hit;
} }
...@@ -990,14 +978,26 @@ void sctp_unhash_transport(struct sctp_transport *t) ...@@ -990,14 +978,26 @@ void sctp_unhash_transport(struct sctp_transport *t)
sctp_hash_params); sctp_hash_params);
} }
bool sctp_sk_bound_dev_eq(struct net *net, int bound_dev_if, int dif, int sdif)
{
bool l3mdev_accept = true;
#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
l3mdev_accept = !!READ_ONCE(net->sctp.l3mdev_accept);
#endif
return inet_bound_dev_eq(l3mdev_accept, bound_dev_if, dif, sdif);
}
/* return a transport with holding it */ /* return a transport with holding it */
struct sctp_transport *sctp_addrs_lookup_transport( struct sctp_transport *sctp_addrs_lookup_transport(
struct net *net, struct net *net,
const union sctp_addr *laddr, const union sctp_addr *laddr,
const union sctp_addr *paddr) const union sctp_addr *paddr,
int dif, int sdif)
{ {
struct rhlist_head *tmp, *list; struct rhlist_head *tmp, *list;
struct sctp_transport *t; struct sctp_transport *t;
int bound_dev_if;
struct sctp_hash_cmp_arg arg = { struct sctp_hash_cmp_arg arg = {
.paddr = paddr, .paddr = paddr,
.net = net, .net = net,
...@@ -1011,7 +1011,9 @@ struct sctp_transport *sctp_addrs_lookup_transport( ...@@ -1011,7 +1011,9 @@ struct sctp_transport *sctp_addrs_lookup_transport(
if (!sctp_transport_hold(t)) if (!sctp_transport_hold(t))
continue; continue;
if (sctp_bind_addr_match(&t->asoc->base.bind_addr, bound_dev_if = READ_ONCE(t->asoc->base.sk->sk_bound_dev_if);
if (sctp_sk_bound_dev_eq(net, bound_dev_if, dif, sdif) &&
sctp_bind_addr_match(&t->asoc->base.bind_addr,
laddr, sctp_sk(t->asoc->base.sk))) laddr, sctp_sk(t->asoc->base.sk)))
return t; return t;
sctp_transport_put(t); sctp_transport_put(t);
...@@ -1048,12 +1050,13 @@ static struct sctp_association *__sctp_lookup_association( ...@@ -1048,12 +1050,13 @@ static struct sctp_association *__sctp_lookup_association(
struct net *net, struct net *net,
const union sctp_addr *local, const union sctp_addr *local,
const union sctp_addr *peer, const union sctp_addr *peer,
struct sctp_transport **pt) struct sctp_transport **pt,
int dif, int sdif)
{ {
struct sctp_transport *t; struct sctp_transport *t;
struct sctp_association *asoc = NULL; struct sctp_association *asoc = NULL;
t = sctp_addrs_lookup_transport(net, local, peer); t = sctp_addrs_lookup_transport(net, local, peer, dif, sdif);
if (!t) if (!t)
goto out; goto out;
...@@ -1069,12 +1072,13 @@ static ...@@ -1069,12 +1072,13 @@ static
struct sctp_association *sctp_lookup_association(struct net *net, struct sctp_association *sctp_lookup_association(struct net *net,
const union sctp_addr *laddr, const union sctp_addr *laddr,
const union sctp_addr *paddr, const union sctp_addr *paddr,
struct sctp_transport **transportp) struct sctp_transport **transportp,
int dif, int sdif)
{ {
struct sctp_association *asoc; struct sctp_association *asoc;
rcu_read_lock(); rcu_read_lock();
asoc = __sctp_lookup_association(net, laddr, paddr, transportp); asoc = __sctp_lookup_association(net, laddr, paddr, transportp, dif, sdif);
rcu_read_unlock(); rcu_read_unlock();
return asoc; return asoc;
...@@ -1083,11 +1087,12 @@ struct sctp_association *sctp_lookup_association(struct net *net, ...@@ -1083,11 +1087,12 @@ struct sctp_association *sctp_lookup_association(struct net *net,
/* Is there an association matching the given local and peer addresses? */ /* Is there an association matching the given local and peer addresses? */
bool sctp_has_association(struct net *net, bool sctp_has_association(struct net *net,
const union sctp_addr *laddr, const union sctp_addr *laddr,
const union sctp_addr *paddr) const union sctp_addr *paddr,
int dif, int sdif)
{ {
struct sctp_transport *transport; struct sctp_transport *transport;
if (sctp_lookup_association(net, laddr, paddr, &transport)) { if (sctp_lookup_association(net, laddr, paddr, &transport, dif, sdif)) {
sctp_transport_put(transport); sctp_transport_put(transport);
return true; return true;
} }
...@@ -1115,7 +1120,8 @@ bool sctp_has_association(struct net *net, ...@@ -1115,7 +1120,8 @@ bool sctp_has_association(struct net *net,
*/ */
static struct sctp_association *__sctp_rcv_init_lookup(struct net *net, static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
struct sk_buff *skb, struct sk_buff *skb,
const union sctp_addr *laddr, struct sctp_transport **transportp) const union sctp_addr *laddr, struct sctp_transport **transportp,
int dif, int sdif)
{ {
struct sctp_association *asoc; struct sctp_association *asoc;
union sctp_addr addr; union sctp_addr addr;
...@@ -1154,7 +1160,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net, ...@@ -1154,7 +1160,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
if (!af->from_addr_param(paddr, params.addr, sh->source, 0)) if (!af->from_addr_param(paddr, params.addr, sh->source, 0))
continue; continue;
asoc = __sctp_lookup_association(net, laddr, paddr, transportp); asoc = __sctp_lookup_association(net, laddr, paddr, transportp, dif, sdif);
if (asoc) if (asoc)
return asoc; return asoc;
} }
...@@ -1181,7 +1187,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( ...@@ -1181,7 +1187,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
struct sctp_chunkhdr *ch, struct sctp_chunkhdr *ch,
const union sctp_addr *laddr, const union sctp_addr *laddr,
__be16 peer_port, __be16 peer_port,
struct sctp_transport **transportp) struct sctp_transport **transportp,
int dif, int sdif)
{ {
struct sctp_addip_chunk *asconf = (struct sctp_addip_chunk *)ch; struct sctp_addip_chunk *asconf = (struct sctp_addip_chunk *)ch;
struct sctp_af *af; struct sctp_af *af;
...@@ -1201,7 +1208,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( ...@@ -1201,7 +1208,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
if (!af->from_addr_param(&paddr, param, peer_port, 0)) if (!af->from_addr_param(&paddr, param, peer_port, 0))
return NULL; return NULL;
return __sctp_lookup_association(net, laddr, &paddr, transportp); return __sctp_lookup_association(net, laddr, &paddr, transportp, dif, sdif);
} }
...@@ -1217,7 +1224,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( ...@@ -1217,7 +1224,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net, static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
struct sk_buff *skb, struct sk_buff *skb,
const union sctp_addr *laddr, const union sctp_addr *laddr,
struct sctp_transport **transportp) struct sctp_transport **transportp,
int dif, int sdif)
{ {
struct sctp_association *asoc = NULL; struct sctp_association *asoc = NULL;
struct sctp_chunkhdr *ch; struct sctp_chunkhdr *ch;
...@@ -1260,7 +1268,7 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net, ...@@ -1260,7 +1268,7 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
asoc = __sctp_rcv_asconf_lookup( asoc = __sctp_rcv_asconf_lookup(
net, ch, laddr, net, ch, laddr,
sctp_hdr(skb)->source, sctp_hdr(skb)->source,
transportp); transportp, dif, sdif);
break; break;
default: default:
break; break;
...@@ -1285,7 +1293,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net, ...@@ -1285,7 +1293,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net, static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
struct sk_buff *skb, struct sk_buff *skb,
const union sctp_addr *laddr, const union sctp_addr *laddr,
struct sctp_transport **transportp) struct sctp_transport **transportp,
int dif, int sdif)
{ {
struct sctp_chunkhdr *ch; struct sctp_chunkhdr *ch;
...@@ -1309,9 +1318,9 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net, ...@@ -1309,9 +1318,9 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
/* If this is INIT/INIT-ACK look inside the chunk too. */ /* If this is INIT/INIT-ACK look inside the chunk too. */
if (ch->type == SCTP_CID_INIT || ch->type == SCTP_CID_INIT_ACK) if (ch->type == SCTP_CID_INIT || ch->type == SCTP_CID_INIT_ACK)
return __sctp_rcv_init_lookup(net, skb, laddr, transportp); return __sctp_rcv_init_lookup(net, skb, laddr, transportp, dif, sdif);
return __sctp_rcv_walk_lookup(net, skb, laddr, transportp); return __sctp_rcv_walk_lookup(net, skb, laddr, transportp, dif, sdif);
} }
/* Lookup an association for an inbound skb. */ /* Lookup an association for an inbound skb. */
...@@ -1319,11 +1328,12 @@ static struct sctp_association *__sctp_rcv_lookup(struct net *net, ...@@ -1319,11 +1328,12 @@ static struct sctp_association *__sctp_rcv_lookup(struct net *net,
struct sk_buff *skb, struct sk_buff *skb,
const union sctp_addr *paddr, const union sctp_addr *paddr,
const union sctp_addr *laddr, const union sctp_addr *laddr,
struct sctp_transport **transportp) struct sctp_transport **transportp,
int dif, int sdif)
{ {
struct sctp_association *asoc; struct sctp_association *asoc;
asoc = __sctp_lookup_association(net, laddr, paddr, transportp); asoc = __sctp_lookup_association(net, laddr, paddr, transportp, dif, sdif);
if (asoc) if (asoc)
goto out; goto out;
...@@ -1331,7 +1341,7 @@ static struct sctp_association *__sctp_rcv_lookup(struct net *net, ...@@ -1331,7 +1341,7 @@ static struct sctp_association *__sctp_rcv_lookup(struct net *net,
* SCTP Implementors Guide, 2.18 Handling of address * SCTP Implementors Guide, 2.18 Handling of address
* parameters within the INIT or INIT-ACK. * parameters within the INIT or INIT-ACK.
*/ */
asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp); asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp, dif, sdif);
if (asoc) if (asoc)
goto out; goto out;
......
...@@ -1394,6 +1394,10 @@ static int __net_init sctp_defaults_init(struct net *net) ...@@ -1394,6 +1394,10 @@ static int __net_init sctp_defaults_init(struct net *net)
/* Initialize maximum autoclose timeout. */ /* Initialize maximum autoclose timeout. */
net->sctp.max_autoclose = INT_MAX / HZ; net->sctp.max_autoclose = INT_MAX / HZ;
#ifdef CONFIG_NET_L3_MASTER_DEV
net->sctp.l3mdev_accept = 1;
#endif
status = sctp_sysctl_net_register(net); status = sctp_sysctl_net_register(net);
if (status) if (status)
goto err_sysctl_register; goto err_sysctl_register;
......
...@@ -5315,14 +5315,14 @@ EXPORT_SYMBOL_GPL(sctp_for_each_endpoint); ...@@ -5315,14 +5315,14 @@ EXPORT_SYMBOL_GPL(sctp_for_each_endpoint);
int sctp_transport_lookup_process(sctp_callback_t cb, struct net *net, int sctp_transport_lookup_process(sctp_callback_t cb, struct net *net,
const union sctp_addr *laddr, const union sctp_addr *laddr,
const union sctp_addr *paddr, void *p) const union sctp_addr *paddr, void *p, int dif)
{ {
struct sctp_transport *transport; struct sctp_transport *transport;
struct sctp_endpoint *ep; struct sctp_endpoint *ep;
int err = -ENOENT; int err = -ENOENT;
rcu_read_lock(); rcu_read_lock();
transport = sctp_addrs_lookup_transport(net, laddr, paddr); transport = sctp_addrs_lookup_transport(net, laddr, paddr, dif, dif);
if (!transport) { if (!transport) {
rcu_read_unlock(); rcu_read_unlock();
return err; return err;
......
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