mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 20:51:03 +02:00
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: Xin Long <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
33e93ed220
commit
0af0317063
@@ -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,
|
|||||||
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);
|
|||||||
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(
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
/* 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 @@ out:
|
|||||||
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,
|
|||||||
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
108
net/sctp/input.c
108
net/sctp/input.c
@@ -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)
|
|||||||
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)
|
|||||||
/* 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)
|
|||||||
!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,
|
|||||||
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,
|
|||||||
/* 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,
|
|||||||
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(
|
|||||||
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)
|
|||||||
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(
|
|||||||
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(
|
|||||||
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
|
|||||||
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,
|
|||||||
/* 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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
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(
|
|||||||
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(
|
|||||||
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(
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
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,
|
|||||||
* 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)
|
|||||||
/* 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);
|
|||||||
|
|
||||||
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;
|
||||||
|
Reference in New Issue
Block a user