1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* SCTP kernel implementation
3*4882a593Smuzhiyun * (C) Copyright IBM Corp. 2002, 2004
4*4882a593Smuzhiyun * Copyright (c) 2001 Nokia, Inc.
5*4882a593Smuzhiyun * Copyright (c) 2001 La Monte H.P. Yarroll
6*4882a593Smuzhiyun * Copyright (c) 2002-2003 Intel Corp.
7*4882a593Smuzhiyun *
8*4882a593Smuzhiyun * This file is part of the SCTP kernel implementation
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * SCTP over IPv6.
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * Please send any bug reports or fixes you make to the
13*4882a593Smuzhiyun * email address(es):
14*4882a593Smuzhiyun * lksctp developers <linux-sctp@vger.kernel.org>
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * Written or modified by:
17*4882a593Smuzhiyun * Le Yanqun <yanqun.le@nokia.com>
18*4882a593Smuzhiyun * Hui Huang <hui.huang@nokia.com>
19*4882a593Smuzhiyun * La Monte H.P. Yarroll <piggy@acm.org>
20*4882a593Smuzhiyun * Sridhar Samudrala <sri@us.ibm.com>
21*4882a593Smuzhiyun * Jon Grimm <jgrimm@us.ibm.com>
22*4882a593Smuzhiyun * Ardelle Fan <ardelle.fan@intel.com>
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * Based on:
25*4882a593Smuzhiyun * linux/net/ipv6/tcp_ipv6.c
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include <linux/module.h>
31*4882a593Smuzhiyun #include <linux/errno.h>
32*4882a593Smuzhiyun #include <linux/types.h>
33*4882a593Smuzhiyun #include <linux/socket.h>
34*4882a593Smuzhiyun #include <linux/sockios.h>
35*4882a593Smuzhiyun #include <linux/net.h>
36*4882a593Smuzhiyun #include <linux/in.h>
37*4882a593Smuzhiyun #include <linux/in6.h>
38*4882a593Smuzhiyun #include <linux/netdevice.h>
39*4882a593Smuzhiyun #include <linux/init.h>
40*4882a593Smuzhiyun #include <linux/ipsec.h>
41*4882a593Smuzhiyun #include <linux/slab.h>
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun #include <linux/ipv6.h>
44*4882a593Smuzhiyun #include <linux/icmpv6.h>
45*4882a593Smuzhiyun #include <linux/random.h>
46*4882a593Smuzhiyun #include <linux/seq_file.h>
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #include <net/protocol.h>
49*4882a593Smuzhiyun #include <net/ndisc.h>
50*4882a593Smuzhiyun #include <net/ip.h>
51*4882a593Smuzhiyun #include <net/ipv6.h>
52*4882a593Smuzhiyun #include <net/transp_v6.h>
53*4882a593Smuzhiyun #include <net/addrconf.h>
54*4882a593Smuzhiyun #include <net/ip6_route.h>
55*4882a593Smuzhiyun #include <net/inet_common.h>
56*4882a593Smuzhiyun #include <net/inet_ecn.h>
57*4882a593Smuzhiyun #include <net/sctp/sctp.h>
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun #include <linux/uaccess.h>
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
62*4882a593Smuzhiyun union sctp_addr *s2);
63*4882a593Smuzhiyun static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr,
64*4882a593Smuzhiyun __be16 port);
65*4882a593Smuzhiyun static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
66*4882a593Smuzhiyun const union sctp_addr *addr2);
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /* Event handler for inet6 address addition/deletion events.
69*4882a593Smuzhiyun * The sctp_local_addr_list needs to be protocted by a spin lock since
70*4882a593Smuzhiyun * multiple notifiers (say IPv4 and IPv6) may be running at the same
71*4882a593Smuzhiyun * time and thus corrupt the list.
72*4882a593Smuzhiyun * The reader side is protected with RCU.
73*4882a593Smuzhiyun */
sctp_inet6addr_event(struct notifier_block * this,unsigned long ev,void * ptr)74*4882a593Smuzhiyun static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
75*4882a593Smuzhiyun void *ptr)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
78*4882a593Smuzhiyun struct sctp_sockaddr_entry *addr = NULL;
79*4882a593Smuzhiyun struct sctp_sockaddr_entry *temp;
80*4882a593Smuzhiyun struct net *net = dev_net(ifa->idev->dev);
81*4882a593Smuzhiyun int found = 0;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun switch (ev) {
84*4882a593Smuzhiyun case NETDEV_UP:
85*4882a593Smuzhiyun addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
86*4882a593Smuzhiyun if (addr) {
87*4882a593Smuzhiyun addr->a.v6.sin6_family = AF_INET6;
88*4882a593Smuzhiyun addr->a.v6.sin6_addr = ifa->addr;
89*4882a593Smuzhiyun addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
90*4882a593Smuzhiyun addr->valid = 1;
91*4882a593Smuzhiyun spin_lock_bh(&net->sctp.local_addr_lock);
92*4882a593Smuzhiyun list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
93*4882a593Smuzhiyun sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW);
94*4882a593Smuzhiyun spin_unlock_bh(&net->sctp.local_addr_lock);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun break;
97*4882a593Smuzhiyun case NETDEV_DOWN:
98*4882a593Smuzhiyun spin_lock_bh(&net->sctp.local_addr_lock);
99*4882a593Smuzhiyun list_for_each_entry_safe(addr, temp,
100*4882a593Smuzhiyun &net->sctp.local_addr_list, list) {
101*4882a593Smuzhiyun if (addr->a.sa.sa_family == AF_INET6 &&
102*4882a593Smuzhiyun ipv6_addr_equal(&addr->a.v6.sin6_addr,
103*4882a593Smuzhiyun &ifa->addr)) {
104*4882a593Smuzhiyun sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
105*4882a593Smuzhiyun found = 1;
106*4882a593Smuzhiyun addr->valid = 0;
107*4882a593Smuzhiyun list_del_rcu(&addr->list);
108*4882a593Smuzhiyun break;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun spin_unlock_bh(&net->sctp.local_addr_lock);
112*4882a593Smuzhiyun if (found)
113*4882a593Smuzhiyun kfree_rcu(addr, rcu);
114*4882a593Smuzhiyun break;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun return NOTIFY_DONE;
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun static struct notifier_block sctp_inet6addr_notifier = {
121*4882a593Smuzhiyun .notifier_call = sctp_inet6addr_event,
122*4882a593Smuzhiyun };
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /* ICMP error handler. */
sctp_v6_err(struct sk_buff * skb,struct inet6_skb_parm * opt,u8 type,u8 code,int offset,__be32 info)125*4882a593Smuzhiyun static int sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
126*4882a593Smuzhiyun u8 type, u8 code, int offset, __be32 info)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun struct inet6_dev *idev;
129*4882a593Smuzhiyun struct sock *sk;
130*4882a593Smuzhiyun struct sctp_association *asoc;
131*4882a593Smuzhiyun struct sctp_transport *transport;
132*4882a593Smuzhiyun struct ipv6_pinfo *np;
133*4882a593Smuzhiyun __u16 saveip, savesctp;
134*4882a593Smuzhiyun int err, ret = 0;
135*4882a593Smuzhiyun struct net *net = dev_net(skb->dev);
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun idev = in6_dev_get(skb->dev);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /* Fix up skb to look at the embedded net header. */
140*4882a593Smuzhiyun saveip = skb->network_header;
141*4882a593Smuzhiyun savesctp = skb->transport_header;
142*4882a593Smuzhiyun skb_reset_network_header(skb);
143*4882a593Smuzhiyun skb_set_transport_header(skb, offset);
144*4882a593Smuzhiyun sk = sctp_err_lookup(net, AF_INET6, skb, sctp_hdr(skb), &asoc, &transport);
145*4882a593Smuzhiyun /* Put back, the original pointers. */
146*4882a593Smuzhiyun skb->network_header = saveip;
147*4882a593Smuzhiyun skb->transport_header = savesctp;
148*4882a593Smuzhiyun if (!sk) {
149*4882a593Smuzhiyun __ICMP6_INC_STATS(net, idev, ICMP6_MIB_INERRORS);
150*4882a593Smuzhiyun ret = -ENOENT;
151*4882a593Smuzhiyun goto out;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* Warning: The sock lock is held. Remember to call
155*4882a593Smuzhiyun * sctp_err_finish!
156*4882a593Smuzhiyun */
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun switch (type) {
159*4882a593Smuzhiyun case ICMPV6_PKT_TOOBIG:
160*4882a593Smuzhiyun if (ip6_sk_accept_pmtu(sk))
161*4882a593Smuzhiyun sctp_icmp_frag_needed(sk, asoc, transport, ntohl(info));
162*4882a593Smuzhiyun goto out_unlock;
163*4882a593Smuzhiyun case ICMPV6_PARAMPROB:
164*4882a593Smuzhiyun if (ICMPV6_UNK_NEXTHDR == code) {
165*4882a593Smuzhiyun sctp_icmp_proto_unreachable(sk, asoc, transport);
166*4882a593Smuzhiyun goto out_unlock;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun break;
169*4882a593Smuzhiyun case NDISC_REDIRECT:
170*4882a593Smuzhiyun sctp_icmp_redirect(sk, transport, skb);
171*4882a593Smuzhiyun goto out_unlock;
172*4882a593Smuzhiyun default:
173*4882a593Smuzhiyun break;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun np = inet6_sk(sk);
177*4882a593Smuzhiyun icmpv6_err_convert(type, code, &err);
178*4882a593Smuzhiyun if (!sock_owned_by_user(sk) && np->recverr) {
179*4882a593Smuzhiyun sk->sk_err = err;
180*4882a593Smuzhiyun sk->sk_error_report(sk);
181*4882a593Smuzhiyun } else { /* Only an error on timeout */
182*4882a593Smuzhiyun sk->sk_err_soft = err;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun out_unlock:
186*4882a593Smuzhiyun sctp_err_finish(sk, transport);
187*4882a593Smuzhiyun out:
188*4882a593Smuzhiyun if (likely(idev != NULL))
189*4882a593Smuzhiyun in6_dev_put(idev);
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun return ret;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
sctp_v6_xmit(struct sk_buff * skb,struct sctp_transport * transport)194*4882a593Smuzhiyun static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun struct sock *sk = skb->sk;
197*4882a593Smuzhiyun struct ipv6_pinfo *np = inet6_sk(sk);
198*4882a593Smuzhiyun struct flowi6 *fl6 = &transport->fl.u.ip6;
199*4882a593Smuzhiyun __u8 tclass = np->tclass;
200*4882a593Smuzhiyun int res;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun pr_debug("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb,
203*4882a593Smuzhiyun skb->len, &fl6->saddr, &fl6->daddr);
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun if (transport->dscp & SCTP_DSCP_SET_MASK)
206*4882a593Smuzhiyun tclass = transport->dscp & SCTP_DSCP_VAL_MASK;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun if (INET_ECN_is_capable(tclass))
209*4882a593Smuzhiyun IP6_ECN_flow_xmit(sk, fl6->flowlabel);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (!(transport->param_flags & SPP_PMTUD_ENABLE))
212*4882a593Smuzhiyun skb->ignore_df = 1;
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS);
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun rcu_read_lock();
217*4882a593Smuzhiyun res = ip6_xmit(sk, skb, fl6, sk->sk_mark, rcu_dereference(np->opt),
218*4882a593Smuzhiyun tclass, sk->sk_priority);
219*4882a593Smuzhiyun rcu_read_unlock();
220*4882a593Smuzhiyun return res;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun /* Returns the dst cache entry for the given source and destination ip
224*4882a593Smuzhiyun * addresses.
225*4882a593Smuzhiyun */
sctp_v6_get_dst(struct sctp_transport * t,union sctp_addr * saddr,struct flowi * fl,struct sock * sk)226*4882a593Smuzhiyun static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
227*4882a593Smuzhiyun struct flowi *fl, struct sock *sk)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun struct sctp_association *asoc = t->asoc;
230*4882a593Smuzhiyun struct dst_entry *dst = NULL;
231*4882a593Smuzhiyun struct flowi _fl;
232*4882a593Smuzhiyun struct flowi6 *fl6 = &_fl.u.ip6;
233*4882a593Smuzhiyun struct sctp_bind_addr *bp;
234*4882a593Smuzhiyun struct ipv6_pinfo *np = inet6_sk(sk);
235*4882a593Smuzhiyun struct sctp_sockaddr_entry *laddr;
236*4882a593Smuzhiyun union sctp_addr *daddr = &t->ipaddr;
237*4882a593Smuzhiyun union sctp_addr dst_saddr;
238*4882a593Smuzhiyun struct in6_addr *final_p, final;
239*4882a593Smuzhiyun enum sctp_scope scope;
240*4882a593Smuzhiyun __u8 matchlen = 0;
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun memset(&_fl, 0, sizeof(_fl));
243*4882a593Smuzhiyun fl6->daddr = daddr->v6.sin6_addr;
244*4882a593Smuzhiyun fl6->fl6_dport = daddr->v6.sin6_port;
245*4882a593Smuzhiyun fl6->flowi6_proto = IPPROTO_SCTP;
246*4882a593Smuzhiyun if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
247*4882a593Smuzhiyun fl6->flowi6_oif = daddr->v6.sin6_scope_id;
248*4882a593Smuzhiyun else if (asoc)
249*4882a593Smuzhiyun fl6->flowi6_oif = asoc->base.sk->sk_bound_dev_if;
250*4882a593Smuzhiyun if (t->flowlabel & SCTP_FLOWLABEL_SET_MASK)
251*4882a593Smuzhiyun fl6->flowlabel = htonl(t->flowlabel & SCTP_FLOWLABEL_VAL_MASK);
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun if (np->sndflow && (fl6->flowlabel & IPV6_FLOWLABEL_MASK)) {
254*4882a593Smuzhiyun struct ip6_flowlabel *flowlabel;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun flowlabel = fl6_sock_lookup(sk, fl6->flowlabel);
257*4882a593Smuzhiyun if (IS_ERR(flowlabel))
258*4882a593Smuzhiyun goto out;
259*4882a593Smuzhiyun fl6_sock_release(flowlabel);
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun pr_debug("%s: dst=%pI6 ", __func__, &fl6->daddr);
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun if (asoc)
265*4882a593Smuzhiyun fl6->fl6_sport = htons(asoc->base.bind_addr.port);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun if (saddr) {
268*4882a593Smuzhiyun fl6->saddr = saddr->v6.sin6_addr;
269*4882a593Smuzhiyun if (!fl6->fl6_sport)
270*4882a593Smuzhiyun fl6->fl6_sport = saddr->v6.sin6_port;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun pr_debug("src=%pI6 - ", &fl6->saddr);
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun rcu_read_lock();
276*4882a593Smuzhiyun final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
277*4882a593Smuzhiyun rcu_read_unlock();
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
280*4882a593Smuzhiyun if (!asoc || saddr) {
281*4882a593Smuzhiyun t->dst = dst;
282*4882a593Smuzhiyun memcpy(fl, &_fl, sizeof(_fl));
283*4882a593Smuzhiyun goto out;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun bp = &asoc->base.bind_addr;
287*4882a593Smuzhiyun scope = sctp_scope(daddr);
288*4882a593Smuzhiyun /* ip6_dst_lookup has filled in the fl6->saddr for us. Check
289*4882a593Smuzhiyun * to see if we can use it.
290*4882a593Smuzhiyun */
291*4882a593Smuzhiyun if (!IS_ERR(dst)) {
292*4882a593Smuzhiyun /* Walk through the bind address list and look for a bind
293*4882a593Smuzhiyun * address that matches the source address of the returned dst.
294*4882a593Smuzhiyun */
295*4882a593Smuzhiyun sctp_v6_to_addr(&dst_saddr, &fl6->saddr, htons(bp->port));
296*4882a593Smuzhiyun rcu_read_lock();
297*4882a593Smuzhiyun list_for_each_entry_rcu(laddr, &bp->address_list, list) {
298*4882a593Smuzhiyun if (!laddr->valid || laddr->state == SCTP_ADDR_DEL ||
299*4882a593Smuzhiyun (laddr->state != SCTP_ADDR_SRC &&
300*4882a593Smuzhiyun !asoc->src_out_of_asoc_ok))
301*4882a593Smuzhiyun continue;
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun /* Do not compare against v4 addrs */
304*4882a593Smuzhiyun if ((laddr->a.sa.sa_family == AF_INET6) &&
305*4882a593Smuzhiyun (sctp_v6_cmp_addr(&dst_saddr, &laddr->a))) {
306*4882a593Smuzhiyun rcu_read_unlock();
307*4882a593Smuzhiyun t->dst = dst;
308*4882a593Smuzhiyun memcpy(fl, &_fl, sizeof(_fl));
309*4882a593Smuzhiyun goto out;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun rcu_read_unlock();
313*4882a593Smuzhiyun /* None of the bound addresses match the source address of the
314*4882a593Smuzhiyun * dst. So release it.
315*4882a593Smuzhiyun */
316*4882a593Smuzhiyun dst_release(dst);
317*4882a593Smuzhiyun dst = NULL;
318*4882a593Smuzhiyun }
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun /* Walk through the bind address list and try to get the
321*4882a593Smuzhiyun * best source address for a given destination.
322*4882a593Smuzhiyun */
323*4882a593Smuzhiyun rcu_read_lock();
324*4882a593Smuzhiyun list_for_each_entry_rcu(laddr, &bp->address_list, list) {
325*4882a593Smuzhiyun struct dst_entry *bdst;
326*4882a593Smuzhiyun __u8 bmatchlen;
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun if (!laddr->valid ||
329*4882a593Smuzhiyun laddr->state != SCTP_ADDR_SRC ||
330*4882a593Smuzhiyun laddr->a.sa.sa_family != AF_INET6 ||
331*4882a593Smuzhiyun scope > sctp_scope(&laddr->a))
332*4882a593Smuzhiyun continue;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun fl6->saddr = laddr->a.v6.sin6_addr;
335*4882a593Smuzhiyun fl6->fl6_sport = laddr->a.v6.sin6_port;
336*4882a593Smuzhiyun final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
337*4882a593Smuzhiyun bdst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun if (IS_ERR(bdst))
340*4882a593Smuzhiyun continue;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun if (ipv6_chk_addr(dev_net(bdst->dev),
343*4882a593Smuzhiyun &laddr->a.v6.sin6_addr, bdst->dev, 1)) {
344*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(dst))
345*4882a593Smuzhiyun dst_release(dst);
346*4882a593Smuzhiyun dst = bdst;
347*4882a593Smuzhiyun t->dst = dst;
348*4882a593Smuzhiyun memcpy(fl, &_fl, sizeof(_fl));
349*4882a593Smuzhiyun break;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
353*4882a593Smuzhiyun if (matchlen > bmatchlen) {
354*4882a593Smuzhiyun dst_release(bdst);
355*4882a593Smuzhiyun continue;
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(dst))
359*4882a593Smuzhiyun dst_release(dst);
360*4882a593Smuzhiyun dst = bdst;
361*4882a593Smuzhiyun matchlen = bmatchlen;
362*4882a593Smuzhiyun t->dst = dst;
363*4882a593Smuzhiyun memcpy(fl, &_fl, sizeof(_fl));
364*4882a593Smuzhiyun }
365*4882a593Smuzhiyun rcu_read_unlock();
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun out:
368*4882a593Smuzhiyun if (!IS_ERR_OR_NULL(dst)) {
369*4882a593Smuzhiyun struct rt6_info *rt;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun rt = (struct rt6_info *)dst;
372*4882a593Smuzhiyun t->dst_cookie = rt6_get_cookie(rt);
373*4882a593Smuzhiyun pr_debug("rt6_dst:%pI6/%d rt6_src:%pI6\n",
374*4882a593Smuzhiyun &rt->rt6i_dst.addr, rt->rt6i_dst.plen,
375*4882a593Smuzhiyun &fl->u.ip6.saddr);
376*4882a593Smuzhiyun } else {
377*4882a593Smuzhiyun t->dst = NULL;
378*4882a593Smuzhiyun pr_debug("no route\n");
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun /* Returns the number of consecutive initial bits that match in the 2 ipv6
383*4882a593Smuzhiyun * addresses.
384*4882a593Smuzhiyun */
sctp_v6_addr_match_len(union sctp_addr * s1,union sctp_addr * s2)385*4882a593Smuzhiyun static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
386*4882a593Smuzhiyun union sctp_addr *s2)
387*4882a593Smuzhiyun {
388*4882a593Smuzhiyun return ipv6_addr_diff(&s1->v6.sin6_addr, &s2->v6.sin6_addr);
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun /* Fills in the source address(saddr) based on the destination address(daddr)
392*4882a593Smuzhiyun * and asoc's bind address list.
393*4882a593Smuzhiyun */
sctp_v6_get_saddr(struct sctp_sock * sk,struct sctp_transport * t,struct flowi * fl)394*4882a593Smuzhiyun static void sctp_v6_get_saddr(struct sctp_sock *sk,
395*4882a593Smuzhiyun struct sctp_transport *t,
396*4882a593Smuzhiyun struct flowi *fl)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun struct flowi6 *fl6 = &fl->u.ip6;
399*4882a593Smuzhiyun union sctp_addr *saddr = &t->saddr;
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun pr_debug("%s: asoc:%p dst:%p\n", __func__, t->asoc, t->dst);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun if (t->dst) {
404*4882a593Smuzhiyun saddr->v6.sin6_family = AF_INET6;
405*4882a593Smuzhiyun saddr->v6.sin6_addr = fl6->saddr;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun /* Make a copy of all potential local addresses. */
sctp_v6_copy_addrlist(struct list_head * addrlist,struct net_device * dev)410*4882a593Smuzhiyun static void sctp_v6_copy_addrlist(struct list_head *addrlist,
411*4882a593Smuzhiyun struct net_device *dev)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun struct inet6_dev *in6_dev;
414*4882a593Smuzhiyun struct inet6_ifaddr *ifp;
415*4882a593Smuzhiyun struct sctp_sockaddr_entry *addr;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun rcu_read_lock();
418*4882a593Smuzhiyun if ((in6_dev = __in6_dev_get(dev)) == NULL) {
419*4882a593Smuzhiyun rcu_read_unlock();
420*4882a593Smuzhiyun return;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun read_lock_bh(&in6_dev->lock);
424*4882a593Smuzhiyun list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
425*4882a593Smuzhiyun /* Add the address to the local list. */
426*4882a593Smuzhiyun addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
427*4882a593Smuzhiyun if (addr) {
428*4882a593Smuzhiyun addr->a.v6.sin6_family = AF_INET6;
429*4882a593Smuzhiyun addr->a.v6.sin6_addr = ifp->addr;
430*4882a593Smuzhiyun addr->a.v6.sin6_scope_id = dev->ifindex;
431*4882a593Smuzhiyun addr->valid = 1;
432*4882a593Smuzhiyun INIT_LIST_HEAD(&addr->list);
433*4882a593Smuzhiyun list_add_tail(&addr->list, addrlist);
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun read_unlock_bh(&in6_dev->lock);
438*4882a593Smuzhiyun rcu_read_unlock();
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun /* Copy over any ip options */
sctp_v6_copy_ip_options(struct sock * sk,struct sock * newsk)442*4882a593Smuzhiyun static void sctp_v6_copy_ip_options(struct sock *sk, struct sock *newsk)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
445*4882a593Smuzhiyun struct ipv6_txoptions *opt;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun newnp = inet6_sk(newsk);
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun rcu_read_lock();
450*4882a593Smuzhiyun opt = rcu_dereference(np->opt);
451*4882a593Smuzhiyun if (opt) {
452*4882a593Smuzhiyun opt = ipv6_dup_options(newsk, opt);
453*4882a593Smuzhiyun if (!opt)
454*4882a593Smuzhiyun pr_err("%s: Failed to copy ip options\n", __func__);
455*4882a593Smuzhiyun }
456*4882a593Smuzhiyun RCU_INIT_POINTER(newnp->opt, opt);
457*4882a593Smuzhiyun rcu_read_unlock();
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun /* Account for the IP options */
sctp_v6_ip_options_len(struct sock * sk)461*4882a593Smuzhiyun static int sctp_v6_ip_options_len(struct sock *sk)
462*4882a593Smuzhiyun {
463*4882a593Smuzhiyun struct ipv6_pinfo *np = inet6_sk(sk);
464*4882a593Smuzhiyun struct ipv6_txoptions *opt;
465*4882a593Smuzhiyun int len = 0;
466*4882a593Smuzhiyun
467*4882a593Smuzhiyun rcu_read_lock();
468*4882a593Smuzhiyun opt = rcu_dereference(np->opt);
469*4882a593Smuzhiyun if (opt)
470*4882a593Smuzhiyun len = opt->opt_flen + opt->opt_nflen;
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun rcu_read_unlock();
473*4882a593Smuzhiyun return len;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun /* Initialize a sockaddr_storage from in incoming skb. */
sctp_v6_from_skb(union sctp_addr * addr,struct sk_buff * skb,int is_saddr)477*4882a593Smuzhiyun static void sctp_v6_from_skb(union sctp_addr *addr, struct sk_buff *skb,
478*4882a593Smuzhiyun int is_saddr)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun /* Always called on head skb, so this is safe */
481*4882a593Smuzhiyun struct sctphdr *sh = sctp_hdr(skb);
482*4882a593Smuzhiyun struct sockaddr_in6 *sa = &addr->v6;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun addr->v6.sin6_family = AF_INET6;
485*4882a593Smuzhiyun addr->v6.sin6_flowinfo = 0; /* FIXME */
486*4882a593Smuzhiyun addr->v6.sin6_scope_id = ((struct inet6_skb_parm *)skb->cb)->iif;
487*4882a593Smuzhiyun
488*4882a593Smuzhiyun if (is_saddr) {
489*4882a593Smuzhiyun sa->sin6_port = sh->source;
490*4882a593Smuzhiyun sa->sin6_addr = ipv6_hdr(skb)->saddr;
491*4882a593Smuzhiyun } else {
492*4882a593Smuzhiyun sa->sin6_port = sh->dest;
493*4882a593Smuzhiyun sa->sin6_addr = ipv6_hdr(skb)->daddr;
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun /* Initialize an sctp_addr from a socket. */
sctp_v6_from_sk(union sctp_addr * addr,struct sock * sk)498*4882a593Smuzhiyun static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun addr->v6.sin6_family = AF_INET6;
501*4882a593Smuzhiyun addr->v6.sin6_port = 0;
502*4882a593Smuzhiyun addr->v6.sin6_addr = sk->sk_v6_rcv_saddr;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun /* Initialize sk->sk_rcv_saddr from sctp_addr. */
sctp_v6_to_sk_saddr(union sctp_addr * addr,struct sock * sk)506*4882a593Smuzhiyun static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
507*4882a593Smuzhiyun {
508*4882a593Smuzhiyun if (addr->sa.sa_family == AF_INET) {
509*4882a593Smuzhiyun sk->sk_v6_rcv_saddr.s6_addr32[0] = 0;
510*4882a593Smuzhiyun sk->sk_v6_rcv_saddr.s6_addr32[1] = 0;
511*4882a593Smuzhiyun sk->sk_v6_rcv_saddr.s6_addr32[2] = htonl(0x0000ffff);
512*4882a593Smuzhiyun sk->sk_v6_rcv_saddr.s6_addr32[3] =
513*4882a593Smuzhiyun addr->v4.sin_addr.s_addr;
514*4882a593Smuzhiyun } else {
515*4882a593Smuzhiyun sk->sk_v6_rcv_saddr = addr->v6.sin6_addr;
516*4882a593Smuzhiyun }
517*4882a593Smuzhiyun }
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun /* Initialize sk->sk_daddr from sctp_addr. */
sctp_v6_to_sk_daddr(union sctp_addr * addr,struct sock * sk)520*4882a593Smuzhiyun static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun if (addr->sa.sa_family == AF_INET) {
523*4882a593Smuzhiyun sk->sk_v6_daddr.s6_addr32[0] = 0;
524*4882a593Smuzhiyun sk->sk_v6_daddr.s6_addr32[1] = 0;
525*4882a593Smuzhiyun sk->sk_v6_daddr.s6_addr32[2] = htonl(0x0000ffff);
526*4882a593Smuzhiyun sk->sk_v6_daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
527*4882a593Smuzhiyun } else {
528*4882a593Smuzhiyun sk->sk_v6_daddr = addr->v6.sin6_addr;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun /* Initialize a sctp_addr from an address parameter. */
sctp_v6_from_addr_param(union sctp_addr * addr,union sctp_addr_param * param,__be16 port,int iif)533*4882a593Smuzhiyun static bool sctp_v6_from_addr_param(union sctp_addr *addr,
534*4882a593Smuzhiyun union sctp_addr_param *param,
535*4882a593Smuzhiyun __be16 port, int iif)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun if (ntohs(param->v6.param_hdr.length) < sizeof(struct sctp_ipv6addr_param))
538*4882a593Smuzhiyun return false;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun addr->v6.sin6_family = AF_INET6;
541*4882a593Smuzhiyun addr->v6.sin6_port = port;
542*4882a593Smuzhiyun addr->v6.sin6_flowinfo = 0; /* BUG */
543*4882a593Smuzhiyun addr->v6.sin6_addr = param->v6.addr;
544*4882a593Smuzhiyun addr->v6.sin6_scope_id = iif;
545*4882a593Smuzhiyun
546*4882a593Smuzhiyun return true;
547*4882a593Smuzhiyun }
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun /* Initialize an address parameter from a sctp_addr and return the length
550*4882a593Smuzhiyun * of the address parameter.
551*4882a593Smuzhiyun */
sctp_v6_to_addr_param(const union sctp_addr * addr,union sctp_addr_param * param)552*4882a593Smuzhiyun static int sctp_v6_to_addr_param(const union sctp_addr *addr,
553*4882a593Smuzhiyun union sctp_addr_param *param)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun int length = sizeof(struct sctp_ipv6addr_param);
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS;
558*4882a593Smuzhiyun param->v6.param_hdr.length = htons(length);
559*4882a593Smuzhiyun param->v6.addr = addr->v6.sin6_addr;
560*4882a593Smuzhiyun
561*4882a593Smuzhiyun return length;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun /* Initialize a sctp_addr from struct in6_addr. */
sctp_v6_to_addr(union sctp_addr * addr,struct in6_addr * saddr,__be16 port)565*4882a593Smuzhiyun static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr,
566*4882a593Smuzhiyun __be16 port)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun addr->sa.sa_family = AF_INET6;
569*4882a593Smuzhiyun addr->v6.sin6_port = port;
570*4882a593Smuzhiyun addr->v6.sin6_flowinfo = 0;
571*4882a593Smuzhiyun addr->v6.sin6_addr = *saddr;
572*4882a593Smuzhiyun addr->v6.sin6_scope_id = 0;
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
__sctp_v6_cmp_addr(const union sctp_addr * addr1,const union sctp_addr * addr2)575*4882a593Smuzhiyun static int __sctp_v6_cmp_addr(const union sctp_addr *addr1,
576*4882a593Smuzhiyun const union sctp_addr *addr2)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun if (addr1->sa.sa_family != addr2->sa.sa_family) {
579*4882a593Smuzhiyun if (addr1->sa.sa_family == AF_INET &&
580*4882a593Smuzhiyun addr2->sa.sa_family == AF_INET6 &&
581*4882a593Smuzhiyun ipv6_addr_v4mapped(&addr2->v6.sin6_addr) &&
582*4882a593Smuzhiyun addr2->v6.sin6_addr.s6_addr32[3] ==
583*4882a593Smuzhiyun addr1->v4.sin_addr.s_addr)
584*4882a593Smuzhiyun return 1;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun if (addr2->sa.sa_family == AF_INET &&
587*4882a593Smuzhiyun addr1->sa.sa_family == AF_INET6 &&
588*4882a593Smuzhiyun ipv6_addr_v4mapped(&addr1->v6.sin6_addr) &&
589*4882a593Smuzhiyun addr1->v6.sin6_addr.s6_addr32[3] ==
590*4882a593Smuzhiyun addr2->v4.sin_addr.s_addr)
591*4882a593Smuzhiyun return 1;
592*4882a593Smuzhiyun
593*4882a593Smuzhiyun return 0;
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun if (!ipv6_addr_equal(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr))
597*4882a593Smuzhiyun return 0;
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun /* If this is a linklocal address, compare the scope_id. */
600*4882a593Smuzhiyun if ((ipv6_addr_type(&addr1->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) &&
601*4882a593Smuzhiyun addr1->v6.sin6_scope_id && addr2->v6.sin6_scope_id &&
602*4882a593Smuzhiyun addr1->v6.sin6_scope_id != addr2->v6.sin6_scope_id)
603*4882a593Smuzhiyun return 0;
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun return 1;
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun
608*4882a593Smuzhiyun /* Compare addresses exactly.
609*4882a593Smuzhiyun * v4-mapped-v6 is also in consideration.
610*4882a593Smuzhiyun */
sctp_v6_cmp_addr(const union sctp_addr * addr1,const union sctp_addr * addr2)611*4882a593Smuzhiyun static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
612*4882a593Smuzhiyun const union sctp_addr *addr2)
613*4882a593Smuzhiyun {
614*4882a593Smuzhiyun return __sctp_v6_cmp_addr(addr1, addr2) &&
615*4882a593Smuzhiyun addr1->v6.sin6_port == addr2->v6.sin6_port;
616*4882a593Smuzhiyun }
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun /* Initialize addr struct to INADDR_ANY. */
sctp_v6_inaddr_any(union sctp_addr * addr,__be16 port)619*4882a593Smuzhiyun static void sctp_v6_inaddr_any(union sctp_addr *addr, __be16 port)
620*4882a593Smuzhiyun {
621*4882a593Smuzhiyun memset(addr, 0x00, sizeof(union sctp_addr));
622*4882a593Smuzhiyun addr->v6.sin6_family = AF_INET6;
623*4882a593Smuzhiyun addr->v6.sin6_port = port;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun /* Is this a wildcard address? */
sctp_v6_is_any(const union sctp_addr * addr)627*4882a593Smuzhiyun static int sctp_v6_is_any(const union sctp_addr *addr)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun return ipv6_addr_any(&addr->v6.sin6_addr);
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun /* Should this be available for binding? */
sctp_v6_available(union sctp_addr * addr,struct sctp_sock * sp)633*4882a593Smuzhiyun static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun int type;
636*4882a593Smuzhiyun struct net *net = sock_net(&sp->inet.sk);
637*4882a593Smuzhiyun const struct in6_addr *in6 = (const struct in6_addr *)&addr->v6.sin6_addr;
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun type = ipv6_addr_type(in6);
640*4882a593Smuzhiyun if (IPV6_ADDR_ANY == type)
641*4882a593Smuzhiyun return 1;
642*4882a593Smuzhiyun if (type == IPV6_ADDR_MAPPED) {
643*4882a593Smuzhiyun if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
644*4882a593Smuzhiyun return 0;
645*4882a593Smuzhiyun sctp_v6_map_v4(addr);
646*4882a593Smuzhiyun return sctp_get_af_specific(AF_INET)->available(addr, sp);
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun if (!(type & IPV6_ADDR_UNICAST))
649*4882a593Smuzhiyun return 0;
650*4882a593Smuzhiyun
651*4882a593Smuzhiyun return ipv6_can_nonlocal_bind(net, &sp->inet) ||
652*4882a593Smuzhiyun ipv6_chk_addr(net, in6, NULL, 0);
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun
655*4882a593Smuzhiyun /* This function checks if the address is a valid address to be used for
656*4882a593Smuzhiyun * SCTP.
657*4882a593Smuzhiyun *
658*4882a593Smuzhiyun * Output:
659*4882a593Smuzhiyun * Return 0 - If the address is a non-unicast or an illegal address.
660*4882a593Smuzhiyun * Return 1 - If the address is a unicast.
661*4882a593Smuzhiyun */
sctp_v6_addr_valid(union sctp_addr * addr,struct sctp_sock * sp,const struct sk_buff * skb)662*4882a593Smuzhiyun static int sctp_v6_addr_valid(union sctp_addr *addr,
663*4882a593Smuzhiyun struct sctp_sock *sp,
664*4882a593Smuzhiyun const struct sk_buff *skb)
665*4882a593Smuzhiyun {
666*4882a593Smuzhiyun int ret = ipv6_addr_type(&addr->v6.sin6_addr);
667*4882a593Smuzhiyun
668*4882a593Smuzhiyun /* Support v4-mapped-v6 address. */
669*4882a593Smuzhiyun if (ret == IPV6_ADDR_MAPPED) {
670*4882a593Smuzhiyun /* Note: This routine is used in input, so v4-mapped-v6
671*4882a593Smuzhiyun * are disallowed here when there is no sctp_sock.
672*4882a593Smuzhiyun */
673*4882a593Smuzhiyun if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
674*4882a593Smuzhiyun return 0;
675*4882a593Smuzhiyun sctp_v6_map_v4(addr);
676*4882a593Smuzhiyun return sctp_get_af_specific(AF_INET)->addr_valid(addr, sp, skb);
677*4882a593Smuzhiyun }
678*4882a593Smuzhiyun
679*4882a593Smuzhiyun /* Is this a non-unicast address */
680*4882a593Smuzhiyun if (!(ret & IPV6_ADDR_UNICAST))
681*4882a593Smuzhiyun return 0;
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun return 1;
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun /* What is the scope of 'addr'? */
sctp_v6_scope(union sctp_addr * addr)687*4882a593Smuzhiyun static enum sctp_scope sctp_v6_scope(union sctp_addr *addr)
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun enum sctp_scope retval;
690*4882a593Smuzhiyun int v6scope;
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun /* The IPv6 scope is really a set of bit fields.
693*4882a593Smuzhiyun * See IFA_* in <net/if_inet6.h>. Map to a generic SCTP scope.
694*4882a593Smuzhiyun */
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun v6scope = ipv6_addr_scope(&addr->v6.sin6_addr);
697*4882a593Smuzhiyun switch (v6scope) {
698*4882a593Smuzhiyun case IFA_HOST:
699*4882a593Smuzhiyun retval = SCTP_SCOPE_LOOPBACK;
700*4882a593Smuzhiyun break;
701*4882a593Smuzhiyun case IFA_LINK:
702*4882a593Smuzhiyun retval = SCTP_SCOPE_LINK;
703*4882a593Smuzhiyun break;
704*4882a593Smuzhiyun case IFA_SITE:
705*4882a593Smuzhiyun retval = SCTP_SCOPE_PRIVATE;
706*4882a593Smuzhiyun break;
707*4882a593Smuzhiyun default:
708*4882a593Smuzhiyun retval = SCTP_SCOPE_GLOBAL;
709*4882a593Smuzhiyun break;
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun
712*4882a593Smuzhiyun return retval;
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun
715*4882a593Smuzhiyun /* Create and initialize a new sk for the socket to be returned by accept(). */
sctp_v6_create_accept_sk(struct sock * sk,struct sctp_association * asoc,bool kern)716*4882a593Smuzhiyun static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
717*4882a593Smuzhiyun struct sctp_association *asoc,
718*4882a593Smuzhiyun bool kern)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun struct sock *newsk;
721*4882a593Smuzhiyun struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
722*4882a593Smuzhiyun struct sctp6_sock *newsctp6sk;
723*4882a593Smuzhiyun
724*4882a593Smuzhiyun newsk = sk_alloc(sock_net(sk), PF_INET6, GFP_KERNEL, sk->sk_prot, kern);
725*4882a593Smuzhiyun if (!newsk)
726*4882a593Smuzhiyun goto out;
727*4882a593Smuzhiyun
728*4882a593Smuzhiyun sock_init_data(NULL, newsk);
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun sctp_copy_sock(newsk, sk, asoc);
731*4882a593Smuzhiyun sock_reset_flag(sk, SOCK_ZAPPED);
732*4882a593Smuzhiyun
733*4882a593Smuzhiyun newsctp6sk = (struct sctp6_sock *)newsk;
734*4882a593Smuzhiyun inet_sk(newsk)->pinet6 = &newsctp6sk->inet6;
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun sctp_sk(newsk)->v4mapped = sctp_sk(sk)->v4mapped;
737*4882a593Smuzhiyun
738*4882a593Smuzhiyun newnp = inet6_sk(newsk);
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun memcpy(newnp, np, sizeof(struct ipv6_pinfo));
741*4882a593Smuzhiyun newnp->ipv6_mc_list = NULL;
742*4882a593Smuzhiyun newnp->ipv6_ac_list = NULL;
743*4882a593Smuzhiyun newnp->ipv6_fl_list = NULL;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun sctp_v6_copy_ip_options(sk, newsk);
746*4882a593Smuzhiyun
747*4882a593Smuzhiyun /* Initialize sk's sport, dport, rcv_saddr and daddr for getsockname()
748*4882a593Smuzhiyun * and getpeername().
749*4882a593Smuzhiyun */
750*4882a593Smuzhiyun sctp_v6_to_sk_daddr(&asoc->peer.primary_addr, newsk);
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun newsk->sk_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun sk_refcnt_debug_inc(newsk);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun if (newsk->sk_prot->init(newsk)) {
757*4882a593Smuzhiyun sk_common_release(newsk);
758*4882a593Smuzhiyun newsk = NULL;
759*4882a593Smuzhiyun }
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun out:
762*4882a593Smuzhiyun return newsk;
763*4882a593Smuzhiyun }
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun /* Format a sockaddr for return to user space. This makes sure the return is
766*4882a593Smuzhiyun * AF_INET or AF_INET6 depending on the SCTP_I_WANT_MAPPED_V4_ADDR option.
767*4882a593Smuzhiyun */
sctp_v6_addr_to_user(struct sctp_sock * sp,union sctp_addr * addr)768*4882a593Smuzhiyun static int sctp_v6_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr)
769*4882a593Smuzhiyun {
770*4882a593Smuzhiyun if (sp->v4mapped) {
771*4882a593Smuzhiyun if (addr->sa.sa_family == AF_INET)
772*4882a593Smuzhiyun sctp_v4_map_v6(addr);
773*4882a593Smuzhiyun } else {
774*4882a593Smuzhiyun if (addr->sa.sa_family == AF_INET6 &&
775*4882a593Smuzhiyun ipv6_addr_v4mapped(&addr->v6.sin6_addr))
776*4882a593Smuzhiyun sctp_v6_map_v4(addr);
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun
779*4882a593Smuzhiyun if (addr->sa.sa_family == AF_INET) {
780*4882a593Smuzhiyun memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));
781*4882a593Smuzhiyun return sizeof(struct sockaddr_in);
782*4882a593Smuzhiyun }
783*4882a593Smuzhiyun return sizeof(struct sockaddr_in6);
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun /* Where did this skb come from? */
sctp_v6_skb_iif(const struct sk_buff * skb)787*4882a593Smuzhiyun static int sctp_v6_skb_iif(const struct sk_buff *skb)
788*4882a593Smuzhiyun {
789*4882a593Smuzhiyun return IP6CB(skb)->iif;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun /* Was this packet marked by Explicit Congestion Notification? */
sctp_v6_is_ce(const struct sk_buff * skb)793*4882a593Smuzhiyun static int sctp_v6_is_ce(const struct sk_buff *skb)
794*4882a593Smuzhiyun {
795*4882a593Smuzhiyun return *((__u32 *)(ipv6_hdr(skb))) & (__force __u32)htonl(1 << 20);
796*4882a593Smuzhiyun }
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun /* Dump the v6 addr to the seq file. */
sctp_v6_seq_dump_addr(struct seq_file * seq,union sctp_addr * addr)799*4882a593Smuzhiyun static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
800*4882a593Smuzhiyun {
801*4882a593Smuzhiyun seq_printf(seq, "%pI6 ", &addr->v6.sin6_addr);
802*4882a593Smuzhiyun }
803*4882a593Smuzhiyun
sctp_v6_ecn_capable(struct sock * sk)804*4882a593Smuzhiyun static void sctp_v6_ecn_capable(struct sock *sk)
805*4882a593Smuzhiyun {
806*4882a593Smuzhiyun inet6_sk(sk)->tclass |= INET_ECN_ECT_0;
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun
809*4882a593Smuzhiyun /* Initialize a PF_INET msgname from a ulpevent. */
sctp_inet6_event_msgname(struct sctp_ulpevent * event,char * msgname,int * addrlen)810*4882a593Smuzhiyun static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
811*4882a593Smuzhiyun char *msgname, int *addrlen)
812*4882a593Smuzhiyun {
813*4882a593Smuzhiyun union sctp_addr *addr;
814*4882a593Smuzhiyun struct sctp_association *asoc;
815*4882a593Smuzhiyun union sctp_addr *paddr;
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun if (!msgname)
818*4882a593Smuzhiyun return;
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun addr = (union sctp_addr *)msgname;
821*4882a593Smuzhiyun asoc = event->asoc;
822*4882a593Smuzhiyun paddr = &asoc->peer.primary_addr;
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun if (paddr->sa.sa_family == AF_INET) {
825*4882a593Smuzhiyun addr->v4.sin_family = AF_INET;
826*4882a593Smuzhiyun addr->v4.sin_port = htons(asoc->peer.port);
827*4882a593Smuzhiyun addr->v4.sin_addr = paddr->v4.sin_addr;
828*4882a593Smuzhiyun } else {
829*4882a593Smuzhiyun addr->v6.sin6_family = AF_INET6;
830*4882a593Smuzhiyun addr->v6.sin6_flowinfo = 0;
831*4882a593Smuzhiyun if (ipv6_addr_type(&paddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
832*4882a593Smuzhiyun addr->v6.sin6_scope_id = paddr->v6.sin6_scope_id;
833*4882a593Smuzhiyun else
834*4882a593Smuzhiyun addr->v6.sin6_scope_id = 0;
835*4882a593Smuzhiyun addr->v6.sin6_port = htons(asoc->peer.port);
836*4882a593Smuzhiyun addr->v6.sin6_addr = paddr->v6.sin6_addr;
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun
839*4882a593Smuzhiyun *addrlen = sctp_v6_addr_to_user(sctp_sk(asoc->base.sk), addr);
840*4882a593Smuzhiyun }
841*4882a593Smuzhiyun
842*4882a593Smuzhiyun /* Initialize a msg_name from an inbound skb. */
sctp_inet6_skb_msgname(struct sk_buff * skb,char * msgname,int * addr_len)843*4882a593Smuzhiyun static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
844*4882a593Smuzhiyun int *addr_len)
845*4882a593Smuzhiyun {
846*4882a593Smuzhiyun union sctp_addr *addr;
847*4882a593Smuzhiyun struct sctphdr *sh;
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun if (!msgname)
850*4882a593Smuzhiyun return;
851*4882a593Smuzhiyun
852*4882a593Smuzhiyun addr = (union sctp_addr *)msgname;
853*4882a593Smuzhiyun sh = sctp_hdr(skb);
854*4882a593Smuzhiyun
855*4882a593Smuzhiyun if (ip_hdr(skb)->version == 4) {
856*4882a593Smuzhiyun addr->v4.sin_family = AF_INET;
857*4882a593Smuzhiyun addr->v4.sin_port = sh->source;
858*4882a593Smuzhiyun addr->v4.sin_addr.s_addr = ip_hdr(skb)->saddr;
859*4882a593Smuzhiyun } else {
860*4882a593Smuzhiyun addr->v6.sin6_family = AF_INET6;
861*4882a593Smuzhiyun addr->v6.sin6_flowinfo = 0;
862*4882a593Smuzhiyun addr->v6.sin6_port = sh->source;
863*4882a593Smuzhiyun addr->v6.sin6_addr = ipv6_hdr(skb)->saddr;
864*4882a593Smuzhiyun if (ipv6_addr_type(&addr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
865*4882a593Smuzhiyun addr->v6.sin6_scope_id = sctp_v6_skb_iif(skb);
866*4882a593Smuzhiyun else
867*4882a593Smuzhiyun addr->v6.sin6_scope_id = 0;
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun *addr_len = sctp_v6_addr_to_user(sctp_sk(skb->sk), addr);
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun /* Do we support this AF? */
sctp_inet6_af_supported(sa_family_t family,struct sctp_sock * sp)874*4882a593Smuzhiyun static int sctp_inet6_af_supported(sa_family_t family, struct sctp_sock *sp)
875*4882a593Smuzhiyun {
876*4882a593Smuzhiyun switch (family) {
877*4882a593Smuzhiyun case AF_INET6:
878*4882a593Smuzhiyun return 1;
879*4882a593Smuzhiyun /* v4-mapped-v6 addresses */
880*4882a593Smuzhiyun case AF_INET:
881*4882a593Smuzhiyun if (!__ipv6_only_sock(sctp_opt2sk(sp)))
882*4882a593Smuzhiyun return 1;
883*4882a593Smuzhiyun fallthrough;
884*4882a593Smuzhiyun default:
885*4882a593Smuzhiyun return 0;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun
889*4882a593Smuzhiyun /* Address matching with wildcards allowed. This extra level
890*4882a593Smuzhiyun * of indirection lets us choose whether a PF_INET6 should
891*4882a593Smuzhiyun * disallow any v4 addresses if we so choose.
892*4882a593Smuzhiyun */
sctp_inet6_cmp_addr(const union sctp_addr * addr1,const union sctp_addr * addr2,struct sctp_sock * opt)893*4882a593Smuzhiyun static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
894*4882a593Smuzhiyun const union sctp_addr *addr2,
895*4882a593Smuzhiyun struct sctp_sock *opt)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun struct sock *sk = sctp_opt2sk(opt);
898*4882a593Smuzhiyun struct sctp_af *af1, *af2;
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun af1 = sctp_get_af_specific(addr1->sa.sa_family);
901*4882a593Smuzhiyun af2 = sctp_get_af_specific(addr2->sa.sa_family);
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun if (!af1 || !af2)
904*4882a593Smuzhiyun return 0;
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun /* If the socket is IPv6 only, v4 addrs will not match */
907*4882a593Smuzhiyun if (__ipv6_only_sock(sk) && af1 != af2)
908*4882a593Smuzhiyun return 0;
909*4882a593Smuzhiyun
910*4882a593Smuzhiyun /* Today, wildcard AF_INET/AF_INET6. */
911*4882a593Smuzhiyun if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2))
912*4882a593Smuzhiyun return 1;
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun if (addr1->sa.sa_family == AF_INET && addr2->sa.sa_family == AF_INET)
915*4882a593Smuzhiyun return addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr;
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun return __sctp_v6_cmp_addr(addr1, addr2);
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun
920*4882a593Smuzhiyun /* Verify that the provided sockaddr looks bindable. Common verification,
921*4882a593Smuzhiyun * has already been taken care of.
922*4882a593Smuzhiyun */
sctp_inet6_bind_verify(struct sctp_sock * opt,union sctp_addr * addr)923*4882a593Smuzhiyun static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
924*4882a593Smuzhiyun {
925*4882a593Smuzhiyun struct sctp_af *af;
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun /* ASSERT: address family has already been verified. */
928*4882a593Smuzhiyun if (addr->sa.sa_family != AF_INET6)
929*4882a593Smuzhiyun af = sctp_get_af_specific(addr->sa.sa_family);
930*4882a593Smuzhiyun else {
931*4882a593Smuzhiyun int type = ipv6_addr_type(&addr->v6.sin6_addr);
932*4882a593Smuzhiyun struct net_device *dev;
933*4882a593Smuzhiyun
934*4882a593Smuzhiyun if (type & IPV6_ADDR_LINKLOCAL) {
935*4882a593Smuzhiyun struct net *net;
936*4882a593Smuzhiyun if (!addr->v6.sin6_scope_id)
937*4882a593Smuzhiyun return 0;
938*4882a593Smuzhiyun net = sock_net(&opt->inet.sk);
939*4882a593Smuzhiyun rcu_read_lock();
940*4882a593Smuzhiyun dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id);
941*4882a593Smuzhiyun if (!dev || !(ipv6_can_nonlocal_bind(net, &opt->inet) ||
942*4882a593Smuzhiyun ipv6_chk_addr(net, &addr->v6.sin6_addr,
943*4882a593Smuzhiyun dev, 0))) {
944*4882a593Smuzhiyun rcu_read_unlock();
945*4882a593Smuzhiyun return 0;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun rcu_read_unlock();
948*4882a593Smuzhiyun }
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun af = opt->pf->af;
951*4882a593Smuzhiyun }
952*4882a593Smuzhiyun return af->available(addr, opt);
953*4882a593Smuzhiyun }
954*4882a593Smuzhiyun
955*4882a593Smuzhiyun /* Verify that the provided sockaddr looks sendable. Common verification,
956*4882a593Smuzhiyun * has already been taken care of.
957*4882a593Smuzhiyun */
sctp_inet6_send_verify(struct sctp_sock * opt,union sctp_addr * addr)958*4882a593Smuzhiyun static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun struct sctp_af *af = NULL;
961*4882a593Smuzhiyun
962*4882a593Smuzhiyun /* ASSERT: address family has already been verified. */
963*4882a593Smuzhiyun if (addr->sa.sa_family != AF_INET6)
964*4882a593Smuzhiyun af = sctp_get_af_specific(addr->sa.sa_family);
965*4882a593Smuzhiyun else {
966*4882a593Smuzhiyun int type = ipv6_addr_type(&addr->v6.sin6_addr);
967*4882a593Smuzhiyun struct net_device *dev;
968*4882a593Smuzhiyun
969*4882a593Smuzhiyun if (type & IPV6_ADDR_LINKLOCAL) {
970*4882a593Smuzhiyun if (!addr->v6.sin6_scope_id)
971*4882a593Smuzhiyun return 0;
972*4882a593Smuzhiyun rcu_read_lock();
973*4882a593Smuzhiyun dev = dev_get_by_index_rcu(sock_net(&opt->inet.sk),
974*4882a593Smuzhiyun addr->v6.sin6_scope_id);
975*4882a593Smuzhiyun rcu_read_unlock();
976*4882a593Smuzhiyun if (!dev)
977*4882a593Smuzhiyun return 0;
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun af = opt->pf->af;
980*4882a593Smuzhiyun }
981*4882a593Smuzhiyun
982*4882a593Smuzhiyun return af != NULL;
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun
985*4882a593Smuzhiyun /* Fill in Supported Address Type information for INIT and INIT-ACK
986*4882a593Smuzhiyun * chunks. Note: In the future, we may want to look at sock options
987*4882a593Smuzhiyun * to determine whether a PF_INET6 socket really wants to have IPV4
988*4882a593Smuzhiyun * addresses.
989*4882a593Smuzhiyun * Returns number of addresses supported.
990*4882a593Smuzhiyun */
sctp_inet6_supported_addrs(const struct sctp_sock * opt,__be16 * types)991*4882a593Smuzhiyun static int sctp_inet6_supported_addrs(const struct sctp_sock *opt,
992*4882a593Smuzhiyun __be16 *types)
993*4882a593Smuzhiyun {
994*4882a593Smuzhiyun types[0] = SCTP_PARAM_IPV6_ADDRESS;
995*4882a593Smuzhiyun if (!opt || !ipv6_only_sock(sctp_opt2sk(opt))) {
996*4882a593Smuzhiyun types[1] = SCTP_PARAM_IPV4_ADDRESS;
997*4882a593Smuzhiyun return 2;
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun return 1;
1000*4882a593Smuzhiyun }
1001*4882a593Smuzhiyun
1002*4882a593Smuzhiyun /* Handle SCTP_I_WANT_MAPPED_V4_ADDR for getpeername() and getsockname() */
sctp_getname(struct socket * sock,struct sockaddr * uaddr,int peer)1003*4882a593Smuzhiyun static int sctp_getname(struct socket *sock, struct sockaddr *uaddr,
1004*4882a593Smuzhiyun int peer)
1005*4882a593Smuzhiyun {
1006*4882a593Smuzhiyun int rc;
1007*4882a593Smuzhiyun
1008*4882a593Smuzhiyun rc = inet6_getname(sock, uaddr, peer);
1009*4882a593Smuzhiyun
1010*4882a593Smuzhiyun if (rc < 0)
1011*4882a593Smuzhiyun return rc;
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun rc = sctp_v6_addr_to_user(sctp_sk(sock->sk),
1014*4882a593Smuzhiyun (union sctp_addr *)uaddr);
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun return rc;
1017*4882a593Smuzhiyun }
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun static const struct proto_ops inet6_seqpacket_ops = {
1020*4882a593Smuzhiyun .family = PF_INET6,
1021*4882a593Smuzhiyun .owner = THIS_MODULE,
1022*4882a593Smuzhiyun .release = inet6_release,
1023*4882a593Smuzhiyun .bind = inet6_bind,
1024*4882a593Smuzhiyun .connect = sctp_inet_connect,
1025*4882a593Smuzhiyun .socketpair = sock_no_socketpair,
1026*4882a593Smuzhiyun .accept = inet_accept,
1027*4882a593Smuzhiyun .getname = sctp_getname,
1028*4882a593Smuzhiyun .poll = sctp_poll,
1029*4882a593Smuzhiyun .ioctl = inet6_ioctl,
1030*4882a593Smuzhiyun .gettstamp = sock_gettstamp,
1031*4882a593Smuzhiyun .listen = sctp_inet_listen,
1032*4882a593Smuzhiyun .shutdown = inet_shutdown,
1033*4882a593Smuzhiyun .setsockopt = sock_common_setsockopt,
1034*4882a593Smuzhiyun .getsockopt = sock_common_getsockopt,
1035*4882a593Smuzhiyun .sendmsg = inet_sendmsg,
1036*4882a593Smuzhiyun .recvmsg = inet_recvmsg,
1037*4882a593Smuzhiyun .mmap = sock_no_mmap,
1038*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
1039*4882a593Smuzhiyun .compat_ioctl = inet6_compat_ioctl,
1040*4882a593Smuzhiyun #endif
1041*4882a593Smuzhiyun };
1042*4882a593Smuzhiyun
1043*4882a593Smuzhiyun static struct inet_protosw sctpv6_seqpacket_protosw = {
1044*4882a593Smuzhiyun .type = SOCK_SEQPACKET,
1045*4882a593Smuzhiyun .protocol = IPPROTO_SCTP,
1046*4882a593Smuzhiyun .prot = &sctpv6_prot,
1047*4882a593Smuzhiyun .ops = &inet6_seqpacket_ops,
1048*4882a593Smuzhiyun .flags = SCTP_PROTOSW_FLAG
1049*4882a593Smuzhiyun };
1050*4882a593Smuzhiyun static struct inet_protosw sctpv6_stream_protosw = {
1051*4882a593Smuzhiyun .type = SOCK_STREAM,
1052*4882a593Smuzhiyun .protocol = IPPROTO_SCTP,
1053*4882a593Smuzhiyun .prot = &sctpv6_prot,
1054*4882a593Smuzhiyun .ops = &inet6_seqpacket_ops,
1055*4882a593Smuzhiyun .flags = SCTP_PROTOSW_FLAG,
1056*4882a593Smuzhiyun };
1057*4882a593Smuzhiyun
sctp6_rcv(struct sk_buff * skb)1058*4882a593Smuzhiyun static int sctp6_rcv(struct sk_buff *skb)
1059*4882a593Smuzhiyun {
1060*4882a593Smuzhiyun return sctp_rcv(skb) ? -1 : 0;
1061*4882a593Smuzhiyun }
1062*4882a593Smuzhiyun
1063*4882a593Smuzhiyun static const struct inet6_protocol sctpv6_protocol = {
1064*4882a593Smuzhiyun .handler = sctp6_rcv,
1065*4882a593Smuzhiyun .err_handler = sctp_v6_err,
1066*4882a593Smuzhiyun .flags = INET6_PROTO_NOPOLICY | INET6_PROTO_FINAL,
1067*4882a593Smuzhiyun };
1068*4882a593Smuzhiyun
1069*4882a593Smuzhiyun static struct sctp_af sctp_af_inet6 = {
1070*4882a593Smuzhiyun .sa_family = AF_INET6,
1071*4882a593Smuzhiyun .sctp_xmit = sctp_v6_xmit,
1072*4882a593Smuzhiyun .setsockopt = ipv6_setsockopt,
1073*4882a593Smuzhiyun .getsockopt = ipv6_getsockopt,
1074*4882a593Smuzhiyun .get_dst = sctp_v6_get_dst,
1075*4882a593Smuzhiyun .get_saddr = sctp_v6_get_saddr,
1076*4882a593Smuzhiyun .copy_addrlist = sctp_v6_copy_addrlist,
1077*4882a593Smuzhiyun .from_skb = sctp_v6_from_skb,
1078*4882a593Smuzhiyun .from_sk = sctp_v6_from_sk,
1079*4882a593Smuzhiyun .from_addr_param = sctp_v6_from_addr_param,
1080*4882a593Smuzhiyun .to_addr_param = sctp_v6_to_addr_param,
1081*4882a593Smuzhiyun .cmp_addr = sctp_v6_cmp_addr,
1082*4882a593Smuzhiyun .scope = sctp_v6_scope,
1083*4882a593Smuzhiyun .addr_valid = sctp_v6_addr_valid,
1084*4882a593Smuzhiyun .inaddr_any = sctp_v6_inaddr_any,
1085*4882a593Smuzhiyun .is_any = sctp_v6_is_any,
1086*4882a593Smuzhiyun .available = sctp_v6_available,
1087*4882a593Smuzhiyun .skb_iif = sctp_v6_skb_iif,
1088*4882a593Smuzhiyun .is_ce = sctp_v6_is_ce,
1089*4882a593Smuzhiyun .seq_dump_addr = sctp_v6_seq_dump_addr,
1090*4882a593Smuzhiyun .ecn_capable = sctp_v6_ecn_capable,
1091*4882a593Smuzhiyun .net_header_len = sizeof(struct ipv6hdr),
1092*4882a593Smuzhiyun .sockaddr_len = sizeof(struct sockaddr_in6),
1093*4882a593Smuzhiyun .ip_options_len = sctp_v6_ip_options_len,
1094*4882a593Smuzhiyun };
1095*4882a593Smuzhiyun
1096*4882a593Smuzhiyun static struct sctp_pf sctp_pf_inet6 = {
1097*4882a593Smuzhiyun .event_msgname = sctp_inet6_event_msgname,
1098*4882a593Smuzhiyun .skb_msgname = sctp_inet6_skb_msgname,
1099*4882a593Smuzhiyun .af_supported = sctp_inet6_af_supported,
1100*4882a593Smuzhiyun .cmp_addr = sctp_inet6_cmp_addr,
1101*4882a593Smuzhiyun .bind_verify = sctp_inet6_bind_verify,
1102*4882a593Smuzhiyun .send_verify = sctp_inet6_send_verify,
1103*4882a593Smuzhiyun .supported_addrs = sctp_inet6_supported_addrs,
1104*4882a593Smuzhiyun .create_accept_sk = sctp_v6_create_accept_sk,
1105*4882a593Smuzhiyun .addr_to_user = sctp_v6_addr_to_user,
1106*4882a593Smuzhiyun .to_sk_saddr = sctp_v6_to_sk_saddr,
1107*4882a593Smuzhiyun .to_sk_daddr = sctp_v6_to_sk_daddr,
1108*4882a593Smuzhiyun .copy_ip_options = sctp_v6_copy_ip_options,
1109*4882a593Smuzhiyun .af = &sctp_af_inet6,
1110*4882a593Smuzhiyun };
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun /* Initialize IPv6 support and register with socket layer. */
sctp_v6_pf_init(void)1113*4882a593Smuzhiyun void sctp_v6_pf_init(void)
1114*4882a593Smuzhiyun {
1115*4882a593Smuzhiyun /* Register the SCTP specific PF_INET6 functions. */
1116*4882a593Smuzhiyun sctp_register_pf(&sctp_pf_inet6, PF_INET6);
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun /* Register the SCTP specific AF_INET6 functions. */
1119*4882a593Smuzhiyun sctp_register_af(&sctp_af_inet6);
1120*4882a593Smuzhiyun }
1121*4882a593Smuzhiyun
sctp_v6_pf_exit(void)1122*4882a593Smuzhiyun void sctp_v6_pf_exit(void)
1123*4882a593Smuzhiyun {
1124*4882a593Smuzhiyun list_del(&sctp_af_inet6.list);
1125*4882a593Smuzhiyun }
1126*4882a593Smuzhiyun
1127*4882a593Smuzhiyun /* Initialize IPv6 support and register with socket layer. */
sctp_v6_protosw_init(void)1128*4882a593Smuzhiyun int sctp_v6_protosw_init(void)
1129*4882a593Smuzhiyun {
1130*4882a593Smuzhiyun int rc;
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyun rc = proto_register(&sctpv6_prot, 1);
1133*4882a593Smuzhiyun if (rc)
1134*4882a593Smuzhiyun return rc;
1135*4882a593Smuzhiyun
1136*4882a593Smuzhiyun /* Add SCTPv6(UDP and TCP style) to inetsw6 linked list. */
1137*4882a593Smuzhiyun inet6_register_protosw(&sctpv6_seqpacket_protosw);
1138*4882a593Smuzhiyun inet6_register_protosw(&sctpv6_stream_protosw);
1139*4882a593Smuzhiyun
1140*4882a593Smuzhiyun return 0;
1141*4882a593Smuzhiyun }
1142*4882a593Smuzhiyun
sctp_v6_protosw_exit(void)1143*4882a593Smuzhiyun void sctp_v6_protosw_exit(void)
1144*4882a593Smuzhiyun {
1145*4882a593Smuzhiyun inet6_unregister_protosw(&sctpv6_seqpacket_protosw);
1146*4882a593Smuzhiyun inet6_unregister_protosw(&sctpv6_stream_protosw);
1147*4882a593Smuzhiyun proto_unregister(&sctpv6_prot);
1148*4882a593Smuzhiyun }
1149*4882a593Smuzhiyun
1150*4882a593Smuzhiyun
1151*4882a593Smuzhiyun /* Register with inet6 layer. */
sctp_v6_add_protocol(void)1152*4882a593Smuzhiyun int sctp_v6_add_protocol(void)
1153*4882a593Smuzhiyun {
1154*4882a593Smuzhiyun /* Register notifier for inet6 address additions/deletions. */
1155*4882a593Smuzhiyun register_inet6addr_notifier(&sctp_inet6addr_notifier);
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun if (inet6_add_protocol(&sctpv6_protocol, IPPROTO_SCTP) < 0)
1158*4882a593Smuzhiyun return -EAGAIN;
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun return 0;
1161*4882a593Smuzhiyun }
1162*4882a593Smuzhiyun
1163*4882a593Smuzhiyun /* Unregister with inet6 layer. */
sctp_v6_del_protocol(void)1164*4882a593Smuzhiyun void sctp_v6_del_protocol(void)
1165*4882a593Smuzhiyun {
1166*4882a593Smuzhiyun inet6_del_protocol(&sctpv6_protocol, IPPROTO_SCTP);
1167*4882a593Smuzhiyun unregister_inet6addr_notifier(&sctp_inet6addr_notifier);
1168*4882a593Smuzhiyun }
1169