3 * Linux INET6 implementation
6 * Pedro Roque <roque@di.fc.ul.pt>
8 * Adapted from linux/net/ipv4/raw.c
10 * $Id: raw.c,v 1.51 2002/02/01 22:01:04 davem Exp $
13 * Hideaki YOSHIFUJI : sin6_scope_id support
14 * YOSHIFUJI,H.@USAGI : raw checksum (RFC2292(bis) compliance)
15 * Kazunori MIYAZAWA @USAGI: change process style to use ip6_append_data
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version
20 * 2 of the License, or (at your option) any later version.
23 #include <linux/errno.h>
24 #include <linux/types.h>
25 #include <linux/socket.h>
26 #include <linux/sockios.h>
27 #include <linux/sched.h>
28 #include <linux/net.h>
29 #include <linux/in6.h>
30 #include <linux/netdevice.h>
31 #include <linux/if_arp.h>
32 #include <linux/icmpv6.h>
33 #include <linux/netfilter.h>
34 #include <linux/netfilter_ipv6.h>
35 #include <asm/uaccess.h>
36 #include <asm/ioctls.h>
42 #include <net/ndisc.h>
43 #include <net/protocol.h>
44 #include <net/ip6_route.h>
45 #include <net/addrconf.h>
46 #include <net/transp_v6.h>
48 #include <net/inet_common.h>
50 #include <net/rawv6.h>
53 #include <linux/proc_fs.h>
54 #include <linux/seq_file.h>
56 struct hlist_head raw_v6_htable
[RAWV6_HTABLE_SIZE
];
57 rwlock_t raw_v6_lock
= RW_LOCK_UNLOCKED
;
59 static void raw_v6_hash(struct sock
*sk
)
61 struct hlist_head
*list
= &raw_v6_htable
[inet_sk(sk
)->num
&
62 (RAWV6_HTABLE_SIZE
- 1)];
64 write_lock_bh(&raw_v6_lock
);
65 sk_add_node(sk
, list
);
66 sock_prot_inc_use(sk
->sk_prot
);
67 write_unlock_bh(&raw_v6_lock
);
70 static void raw_v6_unhash(struct sock
*sk
)
72 write_lock_bh(&raw_v6_lock
);
73 if (sk_del_node_init(sk
))
74 sock_prot_dec_use(sk
->sk_prot
);
75 write_unlock_bh(&raw_v6_lock
);
79 /* Grumble... icmp and ip_input want to get at this... */
80 struct sock
*__raw_v6_lookup(struct sock
*sk
, unsigned short num
,
81 struct in6_addr
*loc_addr
, struct in6_addr
*rmt_addr
)
83 struct hlist_node
*node
;
84 int addr_type
= ipv6_addr_type(loc_addr
);
86 sk_for_each_from(sk
, node
)
87 if (inet_sk(sk
)->num
== num
) {
88 struct ipv6_pinfo
*np
= inet6_sk(sk
);
90 if (!ipv6_addr_any(&np
->daddr
) &&
91 ipv6_addr_cmp(&np
->daddr
, rmt_addr
))
94 if (!ipv6_addr_any(&np
->rcv_saddr
)) {
95 if (!ipv6_addr_cmp(&np
->rcv_saddr
, loc_addr
))
97 if ((addr_type
& IPV6_ADDR_MULTICAST
) &&
98 inet6_mc_check(sk
, loc_addr
, rmt_addr
))
113 static __inline__
int icmpv6_filter(struct sock
*sk
, struct sk_buff
*skb
)
115 struct icmp6hdr
*icmph
;
116 struct raw6_opt
*opt
= raw6_sk(sk
);
118 if (pskb_may_pull(skb
, sizeof(struct icmp6hdr
))) {
119 __u32
*data
= &opt
->filter
.data
[0];
122 icmph
= (struct icmp6hdr
*) skb
->data
;
123 bit_nr
= icmph
->icmp6_type
;
125 return (data
[bit_nr
>> 5] & (1 << (bit_nr
& 31))) != 0;
131 * demultiplex raw sockets.
132 * (should consider queueing the skb in the sock receive_queue
133 * without calling rawv6.c)
135 * Caller owns SKB so we must make clones.
137 void ipv6_raw_deliver(struct sk_buff
*skb
, int nexthdr
)
139 struct in6_addr
*saddr
;
140 struct in6_addr
*daddr
;
144 saddr
= &skb
->nh
.ipv6h
->saddr
;
147 hash
= nexthdr
& (MAX_INET_PROTOS
- 1);
149 read_lock(&raw_v6_lock
);
150 sk
= sk_head(&raw_v6_htable
[hash
]);
153 * The first socket found will be delivered after
154 * delivery to transport protocols.
160 sk
= __raw_v6_lookup(sk
, nexthdr
, daddr
, saddr
);
163 if (nexthdr
!= IPPROTO_ICMPV6
|| !icmpv6_filter(sk
, skb
)) {
164 struct sk_buff
*clone
= skb_clone(skb
, GFP_ATOMIC
);
166 /* Not releasing hash table! */
168 rawv6_rcv(sk
, clone
);
170 sk
= __raw_v6_lookup(sk_next(sk
), nexthdr
, daddr
, saddr
);
173 read_unlock(&raw_v6_lock
);
176 /* This cleans up af_inet6 a bit. -DaveM */
177 static int rawv6_bind(struct sock
*sk
, struct sockaddr
*uaddr
, int addr_len
)
179 struct inet_opt
*inet
= inet_sk(sk
);
180 struct ipv6_pinfo
*np
= inet6_sk(sk
);
181 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*) uaddr
;
186 if (addr_len
< SIN6_LEN_RFC2133
)
188 addr_type
= ipv6_addr_type(&addr
->sin6_addr
);
190 /* Raw sockets are IPv6 only */
191 if (addr_type
== IPV6_ADDR_MAPPED
)
192 return(-EADDRNOTAVAIL
);
197 if (sk
->sk_state
!= TCP_CLOSE
)
200 if (addr_type
& IPV6_ADDR_LINKLOCAL
) {
201 if (addr_len
>= sizeof(struct sockaddr_in6
) &&
202 addr
->sin6_scope_id
) {
203 /* Override any existing binding, if another one
204 * is supplied by user.
206 sk
->sk_bound_dev_if
= addr
->sin6_scope_id
;
209 /* Binding to link-local address requires an interface */
210 if (!sk
->sk_bound_dev_if
)
214 /* Check if the address belongs to the host. */
215 if (addr_type
!= IPV6_ADDR_ANY
) {
216 /* ipv4 addr of the socket is invalid. Only the
217 * unpecified and mapped address have a v4 equivalent.
219 v4addr
= LOOPBACK4_IPV6
;
220 if (!(addr_type
& IPV6_ADDR_MULTICAST
)) {
221 err
= -EADDRNOTAVAIL
;
222 if (!ipv6_chk_addr(&addr
->sin6_addr
, NULL
))
227 inet
->rcv_saddr
= inet
->saddr
= v4addr
;
228 ipv6_addr_copy(&np
->rcv_saddr
, &addr
->sin6_addr
);
229 if (!(addr_type
& IPV6_ADDR_MULTICAST
))
230 ipv6_addr_copy(&np
->saddr
, &addr
->sin6_addr
);
237 void rawv6_err(struct sock
*sk
, struct sk_buff
*skb
,
238 struct inet6_skb_parm
*opt
,
239 int type
, int code
, int offset
, u32 info
)
241 struct inet_opt
*inet
= inet_sk(sk
);
242 struct ipv6_pinfo
*np
= inet6_sk(sk
);
246 /* Report error on raw socket, if:
247 1. User requested recverr.
248 2. Socket is connected (otherwise the error indication
249 is useless without recverr and error is hard.
251 if (!np
->recverr
&& sk
->sk_state
!= TCP_ESTABLISHED
)
254 harderr
= icmpv6_err_convert(type
, code
, &err
);
255 if (type
== ICMPV6_PKT_TOOBIG
)
256 harderr
= (np
->pmtudisc
== IPV6_PMTUDISC_DO
);
259 u8
*payload
= skb
->data
;
262 ipv6_icmp_error(sk
, skb
, err
, 0, ntohl(info
), payload
);
265 if (np
->recverr
|| harderr
) {
267 sk
->sk_error_report(sk
);
271 static inline int rawv6_rcv_skb(struct sock
* sk
, struct sk_buff
* skb
)
273 if (sk
->sk_filter
&& skb
->ip_summed
!= CHECKSUM_UNNECESSARY
) {
274 if ((unsigned short)csum_fold(skb_checksum(skb
, 0, skb
->len
, skb
->csum
))) {
275 /* FIXME: increment a raw6 drops counter here */
279 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
282 /* Charge it to the socket. */
283 if (sock_queue_rcv_skb(sk
,skb
)<0) {
284 /* FIXME: increment a raw6 drops counter here */
293 * This is next to useless...
294 * if we demultiplex in network layer we don't need the extra call
295 * just to queue the skb...
296 * maybe we could have the network decide uppon a hint if it
297 * should call raw_rcv for demultiplexing
299 int rawv6_rcv(struct sock
*sk
, struct sk_buff
*skb
)
301 struct inet_opt
*inet
= inet_sk(sk
);
302 struct raw6_opt
*raw_opt
= raw6_sk(sk
);
304 if (!xfrm6_policy_check(sk
, XFRM_POLICY_IN
, skb
)) {
309 if (!raw_opt
->checksum
)
310 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
312 if (skb
->ip_summed
!= CHECKSUM_UNNECESSARY
) {
313 if (skb
->ip_summed
== CHECKSUM_HW
) {
314 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
315 if (csum_ipv6_magic(&skb
->nh
.ipv6h
->saddr
,
316 &skb
->nh
.ipv6h
->daddr
,
317 skb
->len
, inet
->num
, skb
->csum
)) {
318 NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG
"raw v6 hw csum failure.\n"));
319 skb
->ip_summed
= CHECKSUM_NONE
;
322 if (skb
->ip_summed
== CHECKSUM_NONE
)
323 skb
->csum
= ~csum_ipv6_magic(&skb
->nh
.ipv6h
->saddr
,
324 &skb
->nh
.ipv6h
->daddr
,
325 skb
->len
, inet
->num
, 0);
329 if (skb
->ip_summed
!= CHECKSUM_UNNECESSARY
&&
330 (unsigned short)csum_fold(skb_checksum(skb
, 0, skb
->len
, skb
->csum
))) {
331 /* FIXME: increment a raw6 drops counter here */
335 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
338 rawv6_rcv_skb(sk
, skb
);
344 * This should be easy, if there is something there
345 * we return it, otherwise we block.
348 static int rawv6_recvmsg(struct kiocb
*iocb
, struct sock
*sk
, struct msghdr
*msg
, int len
,
349 int noblock
, int flags
, int *addr_len
)
351 struct ipv6_pinfo
*np
= inet6_sk(sk
);
352 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)msg
->msg_name
;
360 *addr_len
=sizeof(*sin6
);
362 if (flags
& MSG_ERRQUEUE
)
363 return ipv6_recv_error(sk
, msg
, len
);
365 skb
= skb_recv_datagram(sk
, flags
, noblock
, &err
);
372 msg
->msg_flags
|= MSG_TRUNC
;
375 if (skb
->ip_summed
==CHECKSUM_UNNECESSARY
) {
376 err
= skb_copy_datagram_iovec(skb
, 0, msg
->msg_iov
, copied
);
377 } else if (msg
->msg_flags
&MSG_TRUNC
) {
378 if ((unsigned short)csum_fold(skb_checksum(skb
, 0, skb
->len
, skb
->csum
)))
380 err
= skb_copy_datagram_iovec(skb
, 0, msg
->msg_iov
, copied
);
382 err
= skb_copy_and_csum_datagram_iovec(skb
, 0, msg
->msg_iov
);
389 /* Copy the address. */
391 sin6
->sin6_family
= AF_INET6
;
392 ipv6_addr_copy(&sin6
->sin6_addr
, &skb
->nh
.ipv6h
->saddr
);
393 sin6
->sin6_flowinfo
= 0;
394 sin6
->sin6_scope_id
= 0;
395 if (ipv6_addr_type(&sin6
->sin6_addr
) & IPV6_ADDR_LINKLOCAL
) {
396 struct inet6_skb_parm
*opt
= (struct inet6_skb_parm
*) skb
->cb
;
397 sin6
->sin6_scope_id
= opt
->iif
;
401 sock_recv_timestamp(msg
, sk
, skb
);
404 datagram_recv_ctl(sk
, msg
, skb
);
408 skb_free_datagram(sk
, skb
);
414 if (flags
&MSG_PEEK
) {
416 spin_lock_irq(&sk
->sk_receive_queue
.lock
);
417 if (skb
== skb_peek(&sk
->sk_receive_queue
)) {
418 __skb_unlink(skb
, &sk
->sk_receive_queue
);
421 spin_unlock_irq(&sk
->sk_receive_queue
.lock
);
426 /* Error for blocking case is chosen to masquerade
427 as some normal condition.
429 err
= (flags
&MSG_DONTWAIT
) ? -EAGAIN
: -EHOSTUNREACH
;
430 /* FIXME: increment a raw6 drops counter here */
434 static int rawv6_push_pending_frames(struct sock
*sk
, struct flowi
*fl
, struct raw6_opt
*opt
, int len
)
440 if ((skb
= skb_peek(&sk
->sk_write_queue
)) == NULL
)
443 if (opt
->offset
+ 1 < len
)
444 csum
= (u16
*)(skb
->h
.raw
+ opt
->offset
);
450 if (skb_queue_len(&sk
->sk_write_queue
) == 1) {
452 * Only one fragment on the socket.
454 /* should be check HW csum miyazawa */
455 *csum
= csum_ipv6_magic(&fl
->fl6_src
,
457 len
, fl
->proto
, skb
->csum
);
461 skb_queue_walk(&sk
->sk_write_queue
, skb
) {
462 tmp_csum
= csum_add(tmp_csum
, skb
->csum
);
465 tmp_csum
= csum_ipv6_magic(&fl
->fl6_src
,
467 len
, fl
->proto
, tmp_csum
);
472 ip6_push_pending_frames(sk
);
477 static int rawv6_send_hdrinc(struct sock
*sk
, void *from
, int length
,
478 struct flowi
*fl
, struct rt6_info
*rt
,
481 struct inet_opt
*inet
= inet_sk(sk
);
487 if (length
> rt
->u
.dst
.dev
->mtu
) {
488 ipv6_local_error(sk
, EMSGSIZE
, fl
, rt
->u
.dst
.dev
->mtu
);
494 hh_len
= LL_RESERVED_SPACE(rt
->u
.dst
.dev
);
496 skb
= sock_alloc_send_skb(sk
, length
+hh_len
+15,
497 flags
&MSG_DONTWAIT
, &err
);
500 skb_reserve(skb
, hh_len
);
502 skb
->priority
= sk
->sk_priority
;
503 skb
->dst
= dst_clone(&rt
->u
.dst
);
505 skb
->nh
.ipv6h
= iph
= (struct ipv6hdr
*)skb_put(skb
, length
);
507 skb
->ip_summed
= CHECKSUM_NONE
;
509 skb
->h
.raw
= skb
->nh
.raw
;
510 err
= memcpy_fromiovecend((void *)iph
, from
, 0, length
);
514 err
= NF_HOOK(PF_INET6
, NF_IP6_LOCAL_OUT
, skb
, NULL
, rt
->u
.dst
.dev
,
517 err
= inet
->recverr
? net_xmit_errno(err
) : 0;
527 IP6_INC_STATS(Ip6OutDiscards
);
530 static int rawv6_sendmsg(struct kiocb
*iocb
, struct sock
*sk
, struct msghdr
*msg
, int len
)
532 struct ipv6_txoptions opt_space
;
533 struct sockaddr_in6
* sin6
= (struct sockaddr_in6
*) msg
->msg_name
;
534 struct in6_addr
*daddr
;
535 struct inet_opt
*inet
= inet_sk(sk
);
536 struct ipv6_pinfo
*np
= inet6_sk(sk
);
537 struct raw6_opt
*raw_opt
= raw6_sk(sk
);
538 struct ipv6_txoptions
*opt
= NULL
;
539 struct ip6_flowlabel
*flowlabel
= NULL
;
540 struct dst_entry
*dst
= NULL
;
542 int addr_len
= msg
->msg_namelen
;
547 /* Rough check on arithmetic overflow,
548 better check is made in ip6_build_xmit
553 /* Mirror BSD error message compatibility */
554 if (msg
->msg_flags
& MSG_OOB
)
558 * Get and verify the address.
560 memset(&fl
, 0, sizeof(fl
));
563 if (addr_len
< SIN6_LEN_RFC2133
)
566 if (sin6
->sin6_family
&& sin6
->sin6_family
!= AF_INET6
)
569 /* port is the proto value [0..255] carried in nexthdr */
570 proto
= ntohs(sin6
->sin6_port
);
574 else if (proto
!= inet
->num
)
580 daddr
= &sin6
->sin6_addr
;
582 fl
.fl6_flowlabel
= sin6
->sin6_flowinfo
&IPV6_FLOWINFO_MASK
;
583 if (fl
.fl6_flowlabel
&IPV6_FLOWLABEL_MASK
) {
584 flowlabel
= fl6_sock_lookup(sk
, fl
.fl6_flowlabel
);
585 if (flowlabel
== NULL
)
587 daddr
= &flowlabel
->dst
;
592 * Otherwise it will be difficult to maintain
595 if (sk
->sk_state
== TCP_ESTABLISHED
&&
596 !ipv6_addr_cmp(daddr
, &np
->daddr
))
599 if (addr_len
>= sizeof(struct sockaddr_in6
) &&
600 sin6
->sin6_scope_id
&&
601 ipv6_addr_type(daddr
)&IPV6_ADDR_LINKLOCAL
)
602 fl
.oif
= sin6
->sin6_scope_id
;
604 if (sk
->sk_state
!= TCP_ESTABLISHED
)
609 fl
.fl6_flowlabel
= np
->flow_label
;
612 if (ipv6_addr_any(daddr
)) {
614 * unspecfied destination address
615 * treated as error... is this correct ?
617 fl6_sock_release(flowlabel
);
622 fl
.oif
= sk
->sk_bound_dev_if
;
624 if (msg
->msg_controllen
) {
626 memset(opt
, 0, sizeof(struct ipv6_txoptions
));
628 err
= datagram_send_ctl(msg
, &fl
, opt
, &hlimit
);
630 fl6_sock_release(flowlabel
);
633 if ((fl
.fl6_flowlabel
&IPV6_FLOWLABEL_MASK
) && !flowlabel
) {
634 flowlabel
= fl6_sock_lookup(sk
, fl
.fl6_flowlabel
);
635 if (flowlabel
== NULL
)
638 if (!(opt
->opt_nflen
|opt
->opt_flen
))
644 opt
= fl6_merge_options(&opt_space
, flowlabel
, opt
);
647 ipv6_addr_copy(&fl
.fl6_dst
, daddr
);
648 if (ipv6_addr_any(&fl
.fl6_src
) && !ipv6_addr_any(&np
->saddr
))
649 ipv6_addr_copy(&fl
.fl6_src
, &np
->saddr
);
651 /* merge ip6_build_xmit from ip6_output */
652 if (opt
&& opt
->srcrt
) {
653 struct rt0_hdr
*rt0
= (struct rt0_hdr
*) opt
->srcrt
;
654 ipv6_addr_copy(&fl
.fl6_dst
, rt0
->addr
);
657 if (!fl
.oif
&& ipv6_addr_is_multicast(&fl
.fl6_dst
))
658 fl
.oif
= np
->mcast_oif
;
660 err
= ip6_dst_lookup(sk
, &dst
, &fl
);
665 if (ipv6_addr_is_multicast(&fl
.fl6_dst
))
666 hlimit
= np
->mcast_hops
;
668 hlimit
= np
->hop_limit
;
670 hlimit
= dst_metric(dst
, RTAX_HOPLIMIT
);
673 if (msg
->msg_flags
&MSG_CONFIRM
)
678 err
= rawv6_send_hdrinc(sk
, msg
->msg_iov
, len
, &fl
, (struct rt6_info
*)dst
, msg
->msg_flags
);
681 err
= ip6_append_data(sk
, ip_generic_getfrag
, msg
->msg_iov
, len
, 0,
682 hlimit
, opt
, &fl
, (struct rt6_info
*)dst
, msg
->msg_flags
);
685 ip6_flush_pending_frames(sk
);
686 else if (!(msg
->msg_flags
& MSG_MORE
)) {
687 if (raw_opt
->checksum
) {
688 err
= rawv6_push_pending_frames(sk
, &fl
, raw_opt
, len
);
690 err
= ip6_push_pending_frames(sk
);
695 ip6_dst_store(sk
, dst
,
696 !ipv6_addr_cmp(&fl
.fl6_dst
, &np
->daddr
) ?
699 err
= np
->recverr
? net_xmit_errno(err
) : 0;
703 fl6_sock_release(flowlabel
);
704 return err
<0?err
:len
;
707 if (!(msg
->msg_flags
& MSG_PROBE
) || len
)
708 goto back_from_confirm
;
713 static int rawv6_seticmpfilter(struct sock
*sk
, int level
, int optname
,
714 char *optval
, int optlen
)
718 if (optlen
> sizeof(struct icmp6_filter
))
719 optlen
= sizeof(struct icmp6_filter
);
720 if (copy_from_user(&raw6_sk(sk
)->filter
, optval
, optlen
))
730 static int rawv6_geticmpfilter(struct sock
*sk
, int level
, int optname
,
731 char *optval
, int *optlen
)
737 if (get_user(len
, optlen
))
741 if (len
> sizeof(struct icmp6_filter
))
742 len
= sizeof(struct icmp6_filter
);
743 if (put_user(len
, optlen
))
745 if (copy_to_user(optval
, &raw6_sk(sk
)->filter
, len
))
756 static int rawv6_setsockopt(struct sock
*sk
, int level
, int optname
,
757 char *optval
, int optlen
)
759 struct raw6_opt
*opt
= raw6_sk(sk
);
767 if (inet_sk(sk
)->num
!= IPPROTO_ICMPV6
)
769 return rawv6_seticmpfilter(sk
, level
, optname
, optval
,
772 if (optname
== IPV6_CHECKSUM
)
775 return ipv6_setsockopt(sk
, level
, optname
, optval
,
779 if (get_user(val
, (int *)optval
))
784 /* You may get strange result with a positive odd offset;
785 RFC2292bis agrees with me. */
786 if (val
> 0 && (val
&1))
799 return(-ENOPROTOOPT
);
803 static int rawv6_getsockopt(struct sock
*sk
, int level
, int optname
,
804 char *optval
, int *optlen
)
806 struct raw6_opt
*opt
= raw6_sk(sk
);
814 if (inet_sk(sk
)->num
!= IPPROTO_ICMPV6
)
816 return rawv6_geticmpfilter(sk
, level
, optname
, optval
,
819 if (optname
== IPV6_CHECKSUM
)
822 return ipv6_getsockopt(sk
, level
, optname
, optval
,
826 if (get_user(len
,optlen
))
831 if (opt
->checksum
== 0)
840 len
= min_t(unsigned int, sizeof(int), len
);
842 if (put_user(len
, optlen
))
844 if (copy_to_user(optval
,&val
,len
))
849 static int rawv6_ioctl(struct sock
*sk
, int cmd
, unsigned long arg
)
854 int amount
= atomic_read(&sk
->sk_wmem_alloc
);
855 return put_user(amount
, (int *)arg
);
862 spin_lock_irq(&sk
->sk_receive_queue
.lock
);
863 skb
= skb_peek(&sk
->sk_receive_queue
);
865 amount
= skb
->tail
- skb
->h
.raw
;
866 spin_unlock_irq(&sk
->sk_receive_queue
.lock
);
867 return put_user(amount
, (int *)arg
);
875 static void rawv6_close(struct sock
*sk
, long timeout
)
877 if (inet_sk(sk
)->num
== IPPROTO_RAW
)
878 ip6_ra_control(sk
, -1, NULL
);
880 inet_sock_release(sk
);
883 static int rawv6_init_sk(struct sock
*sk
)
885 if (inet_sk(sk
)->num
== IPPROTO_ICMPV6
) {
886 struct raw6_opt
*opt
= raw6_sk(sk
);
893 struct proto rawv6_prot
= {
895 .close
= rawv6_close
,
896 .connect
= udpv6_connect
,
897 .disconnect
= udp_disconnect
,
898 .ioctl
= rawv6_ioctl
,
899 .init
= rawv6_init_sk
,
900 .destroy
= inet6_destroy_sock
,
901 .setsockopt
= rawv6_setsockopt
,
902 .getsockopt
= rawv6_getsockopt
,
903 .sendmsg
= rawv6_sendmsg
,
904 .recvmsg
= rawv6_recvmsg
,
906 .backlog_rcv
= rawv6_rcv_skb
,
908 .unhash
= raw_v6_unhash
,
911 #ifdef CONFIG_PROC_FS
912 struct raw6_iter_state
{
916 #define raw6_seq_private(seq) ((struct raw6_iter_state *)&seq->private)
918 static struct sock
*raw6_get_first(struct seq_file
*seq
)
921 struct hlist_node
*node
;
922 struct raw6_iter_state
* state
= raw6_seq_private(seq
);
924 for (state
->bucket
= 0; state
->bucket
< RAWV6_HTABLE_SIZE
; ++state
->bucket
)
925 sk_for_each(sk
, node
, &raw_v6_htable
[state
->bucket
])
926 if (sk
->sk_family
== PF_INET6
)
933 static struct sock
*raw6_get_next(struct seq_file
*seq
, struct sock
*sk
)
935 struct raw6_iter_state
* state
= raw6_seq_private(seq
);
941 } while (sk
&& sk
->sk_family
!= PF_INET6
);
943 if (!sk
&& ++state
->bucket
< RAWV6_HTABLE_SIZE
) {
944 sk
= sk_head(&raw_v6_htable
[state
->bucket
]);
950 static struct sock
*raw6_get_idx(struct seq_file
*seq
, loff_t pos
)
952 struct sock
*sk
= raw6_get_first(seq
);
954 while (pos
&& (sk
= raw6_get_next(seq
, sk
)) != NULL
)
956 return pos
? NULL
: sk
;
959 static void *raw6_seq_start(struct seq_file
*seq
, loff_t
*pos
)
961 read_lock(&raw_v6_lock
);
962 return *pos
? raw6_get_idx(seq
, *pos
) : (void *)1;
965 static void *raw6_seq_next(struct seq_file
*seq
, void *v
, loff_t
*pos
)
970 sk
= raw6_get_first(seq
);
972 sk
= raw6_get_next(seq
, v
);
977 static void raw6_seq_stop(struct seq_file
*seq
, void *v
)
979 read_unlock(&raw_v6_lock
);
982 static void raw6_sock_seq_show(struct seq_file
*seq
, struct sock
*sp
, int i
)
984 struct ipv6_pinfo
*np
= inet6_sk(sp
);
985 struct in6_addr
*dest
, *src
;
989 src
= &np
->rcv_saddr
;
991 srcp
= inet_sk(sp
)->num
;
993 "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
994 "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p\n",
996 src
->s6_addr32
[0], src
->s6_addr32
[1],
997 src
->s6_addr32
[2], src
->s6_addr32
[3], srcp
,
998 dest
->s6_addr32
[0], dest
->s6_addr32
[1],
999 dest
->s6_addr32
[2], dest
->s6_addr32
[3], destp
,
1001 atomic_read(&sp
->sk_wmem_alloc
),
1002 atomic_read(&sp
->sk_rmem_alloc
),
1006 atomic_read(&sp
->sk_refcnt
), sp
);
1009 static int raw6_seq_show(struct seq_file
*seq
, void *v
)
1016 "st tx_queue rx_queue tr tm->when retrnsmt"
1017 " uid timeout inode\n");
1019 raw6_sock_seq_show(seq
, v
, raw6_seq_private(seq
)->bucket
);
1023 static struct seq_operations raw6_seq_ops
= {
1024 .start
= raw6_seq_start
,
1025 .next
= raw6_seq_next
,
1026 .stop
= raw6_seq_stop
,
1027 .show
= raw6_seq_show
,
1030 static int raw6_seq_open(struct inode
*inode
, struct file
*file
)
1032 struct seq_file
*seq
;
1034 struct raw6_iter_state
*s
= kmalloc(sizeof(*s
), GFP_KERNEL
);
1037 rc
= seq_open(file
, &raw6_seq_ops
);
1040 seq
= file
->private_data
;
1042 memset(s
, 0, sizeof(*s
));
1050 static struct file_operations raw6_seq_fops
= {
1051 .owner
= THIS_MODULE
,
1052 .open
= raw6_seq_open
,
1054 .llseek
= seq_lseek
,
1055 .release
= seq_release_private
,
1058 int __init
raw6_proc_init(void)
1060 struct proc_dir_entry
*p
= create_proc_entry("raw6", S_IRUGO
, proc_net
);
1064 p
->proc_fops
= &raw6_seq_fops
;
1069 void raw6_proc_exit(void)
1071 proc_net_remove("raw6");
1073 #endif /* CONFIG_PROC_FS */