Loading include/net/sctp/structs.h +2 −0 Original line number Diff line number Diff line Loading @@ -1211,6 +1211,8 @@ int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, struct sctp_sock *); int sctp_bind_addr_conflict(struct sctp_bind_addr *, const union sctp_addr *, struct sctp_sock *, struct sctp_sock *); int sctp_bind_addr_state(const struct sctp_bind_addr *bp, const union sctp_addr *addr); union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, Loading net/sctp/bind_addr.c +37 −0 Original line number Diff line number Diff line Loading @@ -348,6 +348,43 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, return match; } /* Does the address 'addr' conflict with any addresses in * the bp. */ int sctp_bind_addr_conflict(struct sctp_bind_addr *bp, const union sctp_addr *addr, struct sctp_sock *bp_sp, struct sctp_sock *addr_sp) { struct sctp_sockaddr_entry *laddr; int conflict = 0; struct sctp_sock *sp; /* Pick the IPv6 socket as the basis of comparison * since it's usually a superset of the IPv4. * If there is no IPv6 socket, then default to bind_addr. */ if (sctp_opt2sk(bp_sp)->sk_family == AF_INET6) sp = bp_sp; else if (sctp_opt2sk(addr_sp)->sk_family == AF_INET6) sp = addr_sp; else sp = bp_sp; rcu_read_lock(); list_for_each_entry_rcu(laddr, &bp->address_list, list) { if (!laddr->valid) continue; conflict = sp->pf->cmp_addr(&laddr->a, addr, sp); if (conflict) break; } rcu_read_unlock(); return conflict; } /* Get the state of the entry in the bind_addr_list */ int sctp_bind_addr_state(const struct sctp_bind_addr *bp, const union sctp_addr *addr) Loading net/sctp/ipv6.c +16 −4 Original line number Diff line number Diff line Loading @@ -818,7 +818,7 @@ static int sctp_inet6_af_supported(sa_family_t family, struct sctp_sock *sp) return 1; /* v4-mapped-v6 addresses */ case AF_INET: if (!__ipv6_only_sock(sctp_opt2sk(sp)) && sp->v4mapped) if (!__ipv6_only_sock(sctp_opt2sk(sp))) return 1; default: return 0; Loading @@ -840,6 +840,11 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, if (!af1 || !af2) return 0; /* If the socket is IPv6 only, v4 addrs will not match */ if (__ipv6_only_sock(sctp_opt2sk(opt)) && af1 != af2) return 0; /* Today, wildcard AF_INET/AF_INET6. */ if (sctp_is_any(addr1) || sctp_is_any(addr2)) return 1; Loading Loading @@ -876,7 +881,11 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) return 0; } dev_put(dev); } else if (type == IPV6_ADDR_MAPPED) { if (!opt->v4mapped) return 0; } af = opt->pf->af; } return af->available(addr, opt); Loading Loading @@ -919,10 +928,13 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) static int sctp_inet6_supported_addrs(const struct sctp_sock *opt, __be16 *types) { types[0] = SCTP_PARAM_IPV4_ADDRESS; types[1] = SCTP_PARAM_IPV6_ADDRESS; types[0] = SCTP_PARAM_IPV6_ADDRESS; if (!opt || !ipv6_only_sock(sctp_opt2sk(opt))) { types[1] = SCTP_PARAM_IPV4_ADDRESS; return 2; } return 1; } static const struct proto_ops inet6_seqpacket_ops = { .family = PF_INET6, Loading net/sctp/protocol.c +7 −0 Original line number Diff line number Diff line Loading @@ -381,6 +381,10 @@ static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_sock *sp, const struct sk_buff *skb) { /* IPv4 addresses not allowed */ if (sp && ipv6_only_sock(sctp_opt2sk(sp))) return 0; /* Is this a non-unicast address or a unusable SCTP address? */ if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) return 0; Loading @@ -404,6 +408,9 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) !sysctl_ip_nonlocal_bind) return 0; if (ipv6_only_sock(sctp_opt2sk(sp))) return 0; return 1; } Loading net/sctp/sm_make_chunk.c +6 −1 Original line number Diff line number Diff line Loading @@ -2364,8 +2364,13 @@ static int sctp_process_param(struct sctp_association *asoc, case SCTP_PARAM_IPV6_ADDRESS: if (PF_INET6 != asoc->base.sk->sk_family) break; /* Fall through. */ goto do_addr_param; case SCTP_PARAM_IPV4_ADDRESS: /* v4 addresses are not allowed on v6-only socket */ if (ipv6_only_sock(asoc->base.sk)) break; do_addr_param: af = sctp_get_af_specific(param_type2af(param.p->type)); af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0); scope = sctp_scope(peer_addr); Loading Loading
include/net/sctp/structs.h +2 −0 Original line number Diff line number Diff line Loading @@ -1211,6 +1211,8 @@ int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *, struct sctp_sock *); int sctp_bind_addr_conflict(struct sctp_bind_addr *, const union sctp_addr *, struct sctp_sock *, struct sctp_sock *); int sctp_bind_addr_state(const struct sctp_bind_addr *bp, const union sctp_addr *addr); union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, Loading
net/sctp/bind_addr.c +37 −0 Original line number Diff line number Diff line Loading @@ -348,6 +348,43 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp, return match; } /* Does the address 'addr' conflict with any addresses in * the bp. */ int sctp_bind_addr_conflict(struct sctp_bind_addr *bp, const union sctp_addr *addr, struct sctp_sock *bp_sp, struct sctp_sock *addr_sp) { struct sctp_sockaddr_entry *laddr; int conflict = 0; struct sctp_sock *sp; /* Pick the IPv6 socket as the basis of comparison * since it's usually a superset of the IPv4. * If there is no IPv6 socket, then default to bind_addr. */ if (sctp_opt2sk(bp_sp)->sk_family == AF_INET6) sp = bp_sp; else if (sctp_opt2sk(addr_sp)->sk_family == AF_INET6) sp = addr_sp; else sp = bp_sp; rcu_read_lock(); list_for_each_entry_rcu(laddr, &bp->address_list, list) { if (!laddr->valid) continue; conflict = sp->pf->cmp_addr(&laddr->a, addr, sp); if (conflict) break; } rcu_read_unlock(); return conflict; } /* Get the state of the entry in the bind_addr_list */ int sctp_bind_addr_state(const struct sctp_bind_addr *bp, const union sctp_addr *addr) Loading
net/sctp/ipv6.c +16 −4 Original line number Diff line number Diff line Loading @@ -818,7 +818,7 @@ static int sctp_inet6_af_supported(sa_family_t family, struct sctp_sock *sp) return 1; /* v4-mapped-v6 addresses */ case AF_INET: if (!__ipv6_only_sock(sctp_opt2sk(sp)) && sp->v4mapped) if (!__ipv6_only_sock(sctp_opt2sk(sp))) return 1; default: return 0; Loading @@ -840,6 +840,11 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1, if (!af1 || !af2) return 0; /* If the socket is IPv6 only, v4 addrs will not match */ if (__ipv6_only_sock(sctp_opt2sk(opt)) && af1 != af2) return 0; /* Today, wildcard AF_INET/AF_INET6. */ if (sctp_is_any(addr1) || sctp_is_any(addr2)) return 1; Loading Loading @@ -876,7 +881,11 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) return 0; } dev_put(dev); } else if (type == IPV6_ADDR_MAPPED) { if (!opt->v4mapped) return 0; } af = opt->pf->af; } return af->available(addr, opt); Loading Loading @@ -919,10 +928,13 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) static int sctp_inet6_supported_addrs(const struct sctp_sock *opt, __be16 *types) { types[0] = SCTP_PARAM_IPV4_ADDRESS; types[1] = SCTP_PARAM_IPV6_ADDRESS; types[0] = SCTP_PARAM_IPV6_ADDRESS; if (!opt || !ipv6_only_sock(sctp_opt2sk(opt))) { types[1] = SCTP_PARAM_IPV4_ADDRESS; return 2; } return 1; } static const struct proto_ops inet6_seqpacket_ops = { .family = PF_INET6, Loading
net/sctp/protocol.c +7 −0 Original line number Diff line number Diff line Loading @@ -381,6 +381,10 @@ static int sctp_v4_addr_valid(union sctp_addr *addr, struct sctp_sock *sp, const struct sk_buff *skb) { /* IPv4 addresses not allowed */ if (sp && ipv6_only_sock(sctp_opt2sk(sp))) return 0; /* Is this a non-unicast address or a unusable SCTP address? */ if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) return 0; Loading @@ -404,6 +408,9 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) !sysctl_ip_nonlocal_bind) return 0; if (ipv6_only_sock(sctp_opt2sk(sp))) return 0; return 1; } Loading
net/sctp/sm_make_chunk.c +6 −1 Original line number Diff line number Diff line Loading @@ -2364,8 +2364,13 @@ static int sctp_process_param(struct sctp_association *asoc, case SCTP_PARAM_IPV6_ADDRESS: if (PF_INET6 != asoc->base.sk->sk_family) break; /* Fall through. */ goto do_addr_param; case SCTP_PARAM_IPV4_ADDRESS: /* v4 addresses are not allowed on v6-only socket */ if (ipv6_only_sock(asoc->base.sk)) break; do_addr_param: af = sctp_get_af_specific(param_type2af(param.p->type)); af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0); scope = sctp_scope(peer_addr); Loading