cleanup
[linux-2.4.21-pre4.git] / net / ipv6 / af_inet6.c
1 /*
2  *      PF_INET6 socket protocol family
3  *      Linux INET6 implementation 
4  *
5  *      Authors:
6  *      Pedro Roque             <roque@di.fc.ul.pt>     
7  *
8  *      Adapted from linux/net/ipv4/af_inet.c
9  *
10  *      $Id: af_inet6.c,v 1.1.1.1 2005/04/11 02:51:13 jack Exp $
11  *
12  *      Fixes:
13  *      piggy, Karl Knutson     :       Socket protocol table
14  *      Hideaki YOSHIFUJI       :       sin6_scope_id support
15  *      Arnaldo Melo            :       check proc_net_create return, cleanups
16  *
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.
21  */
22
23
24 #include <linux/module.h>
25 #include <linux/config.h>
26 #include <linux/errno.h>
27 #include <linux/types.h>
28 #include <linux/socket.h>
29 #include <linux/in.h>
30 #include <linux/kernel.h>
31 #include <linux/major.h>
32 #include <linux/sched.h>
33 #include <linux/timer.h>
34 #include <linux/string.h>
35 #include <linux/sockios.h>
36 #include <linux/net.h>
37 #include <linux/fcntl.h>
38 #include <linux/mm.h>
39 #include <linux/interrupt.h>
40 #include <linux/proc_fs.h>
41 #include <linux/stat.h>
42 #include <linux/init.h>
43 #include <linux/version.h>
44
45 #include <linux/inet.h>
46 #include <linux/netdevice.h>
47 #include <linux/icmpv6.h>
48 #include <linux/brlock.h>
49 #include <linux/smp_lock.h>
50
51 #include <net/ip.h>
52 #include <net/ipv6.h>
53 #include <net/udp.h>
54 #include <net/tcp.h>
55 #include <net/ipip.h>
56 #include <net/protocol.h>
57 #include <net/inet_common.h>
58 #include <net/transp_v6.h>
59 #include <net/ip6_route.h>
60 #include <net/addrconf.h>
61
62 #include <asm/uaccess.h>
63 #include <asm/system.h>
64
65 #ifdef MODULE
66 static int unloadable = 0; /* XX: Turn to one when all is ok within the
67                               module for allowing unload */
68 #endif
69
70 #if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
71 MODULE_AUTHOR("Cast of dozens");
72 MODULE_DESCRIPTION("IPv6 protocol stack for Linux");
73 MODULE_PARM(unloadable, "i");
74 #endif
75
76 /* IPv6 procfs goodies... */
77
78 #ifdef CONFIG_PROC_FS
79 extern int raw6_get_info(char *, char **, off_t, int);
80 extern int tcp6_get_info(char *, char **, off_t, int);
81 extern int udp6_get_info(char *, char **, off_t, int);
82 extern int afinet6_get_info(char *, char **, off_t, int);
83 extern int afinet6_get_snmp(char *, char **, off_t, int);
84 #endif
85
86 #ifdef CONFIG_SYSCTL
87 extern void ipv6_sysctl_register(void);
88 extern void ipv6_sysctl_unregister(void);
89 #endif
90
91 int sysctl_ipv6_bindv6only;
92
93 #ifdef INET_REFCNT_DEBUG
94 atomic_t inet6_sock_nr;
95 #endif
96
97 /* The inetsw table contains everything that inet_create needs to
98  * build a new socket.
99  */
100 struct list_head inetsw6[SOCK_MAX];
101
102 static void inet6_sock_destruct(struct sock *sk)
103 {
104         inet_sock_destruct(sk);
105
106 #ifdef INET_REFCNT_DEBUG
107         atomic_dec(&inet6_sock_nr);
108 #endif
109         MOD_DEC_USE_COUNT;
110 }
111
112 static int inet6_create(struct socket *sock, int protocol)
113 {
114         struct sock *sk;
115         struct list_head *p;
116         struct inet_protosw *answer;
117
118         sk = sk_alloc(PF_INET6, GFP_KERNEL, 1);
119         if (sk == NULL) 
120                 goto do_oom;
121
122         /* Look for the requested type/protocol pair. */
123         answer = NULL;
124         br_read_lock_bh(BR_NETPROTO_LOCK);
125         list_for_each(p, &inetsw6[sock->type]) {
126                 answer = list_entry(p, struct inet_protosw, list);
127
128                 /* Check the non-wild match. */
129                 if (protocol == answer->protocol) {
130                         if (protocol != IPPROTO_IP)
131                                 break;
132                 } else {
133                         /* Check for the two wild cases. */
134                         if (IPPROTO_IP == protocol) {
135                                 protocol = answer->protocol;
136                                 break;
137                         }
138                         if (IPPROTO_IP == answer->protocol)
139                                 break;
140                 }
141                 answer = NULL;
142         }
143         br_read_unlock_bh(BR_NETPROTO_LOCK);
144
145         if (!answer)
146                 goto free_and_badtype;
147         if (answer->capability > 0 && !capable(answer->capability))
148                 goto free_and_badperm;
149         if (!protocol)
150                 goto free_and_noproto;
151
152         sock->ops = answer->ops;
153         sock_init_data(sock, sk);
154
155         sk->prot = answer->prot;
156         sk->no_check = answer->no_check;
157         if (INET_PROTOSW_REUSE & answer->flags)
158                 sk->reuse = 1;
159
160         if (SOCK_RAW == sock->type) {
161                 sk->num = protocol;
162                 if (IPPROTO_RAW == protocol)
163                         sk->protinfo.af_inet.hdrincl = 1;
164         }
165
166         sk->destruct            = inet6_sock_destruct;
167         sk->zapped              = 0;
168         sk->family              = PF_INET6;
169         sk->protocol            = protocol;
170
171         sk->backlog_rcv         = answer->prot->backlog_rcv;
172
173         sk->net_pinfo.af_inet6.hop_limit  = -1;
174         sk->net_pinfo.af_inet6.mcast_hops = -1;
175         sk->net_pinfo.af_inet6.mc_loop    = 1;
176         sk->net_pinfo.af_inet6.pmtudisc   = IPV6_PMTUDISC_WANT;
177
178         sk->net_pinfo.af_inet6.ipv6only = sysctl_ipv6_bindv6only;
179         
180         /* Init the ipv4 part of the socket since we can have sockets
181          * using v6 API for ipv4.
182          */
183         sk->protinfo.af_inet.ttl        = 64;
184
185         sk->protinfo.af_inet.mc_loop    = 1;
186         sk->protinfo.af_inet.mc_ttl     = 1;
187         sk->protinfo.af_inet.mc_index   = 0;
188         sk->protinfo.af_inet.mc_list    = NULL;
189
190         if (ipv4_config.no_pmtu_disc)
191                 sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT;
192         else
193                 sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_WANT;
194
195
196 #ifdef INET_REFCNT_DEBUG
197         atomic_inc(&inet6_sock_nr);
198         atomic_inc(&inet_sock_nr);
199 #endif
200         MOD_INC_USE_COUNT;
201
202         if (sk->num) {
203                 /* It assumes that any protocol which allows
204                  * the user to assign a number at socket
205                  * creation time automatically shares.
206                  */
207                 sk->sport = ntohs(sk->num);
208                 sk->prot->hash(sk);
209         }
210         if (sk->prot->init) {
211                 int err = sk->prot->init(sk);
212                 if (err != 0) {
213                         MOD_DEC_USE_COUNT;
214                         inet_sock_release(sk);
215                         return err;
216                 }
217         }
218         return 0;
219
220 free_and_badtype:
221         sk_free(sk);
222         return -ESOCKTNOSUPPORT;
223 free_and_badperm:
224         sk_free(sk);
225         return -EPERM;
226 free_and_noproto:
227         sk_free(sk);
228         return -EPROTONOSUPPORT;
229 do_oom:
230         return -ENOBUFS;
231 }
232
233
234 /* bind for INET6 API */
235 static int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
236 {
237         struct sockaddr_in6 *addr=(struct sockaddr_in6 *)uaddr;
238         struct sock *sk = sock->sk;
239         __u32 v4addr = 0;
240         unsigned short snum;
241         int addr_type = 0;
242
243         /* If the socket has its own bind function then use it. */
244         if(sk->prot->bind)
245                 return sk->prot->bind(sk, uaddr, addr_len);
246
247         if (addr_len < SIN6_LEN_RFC2133)
248                 return -EINVAL;
249         addr_type = ipv6_addr_type(&addr->sin6_addr);
250         if ((addr_type & IPV6_ADDR_MULTICAST) && sock->type == SOCK_STREAM)
251                 return -EINVAL;
252
253         /* Check if the address belongs to the host. */
254         if (addr_type == IPV6_ADDR_MAPPED) {
255                 v4addr = addr->sin6_addr.s6_addr32[3];
256                 if (inet_addr_type(v4addr) != RTN_LOCAL)
257                         return -EADDRNOTAVAIL;
258         } else {
259                 if (addr_type != IPV6_ADDR_ANY) {
260                         /* ipv4 addr of the socket is invalid.  Only the
261                          * unpecified and mapped address have a v4 equivalent.
262                          */
263                         v4addr = LOOPBACK4_IPV6;
264                         if (!(addr_type & IPV6_ADDR_MULTICAST)) {
265                                 if (!ipv6_chk_addr(&addr->sin6_addr, NULL))
266                                         return -EADDRNOTAVAIL;
267                         }
268                 }
269         }
270
271         snum = ntohs(addr->sin6_port);
272         if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
273                 return -EACCES;
274
275         lock_sock(sk);
276
277         /* Check these errors (active socket, double bind). */
278         if ((sk->state != TCP_CLOSE)                    ||
279             (sk->num != 0)) {
280                 release_sock(sk);
281                 return -EINVAL;
282         }
283
284         if (addr_type & IPV6_ADDR_LINKLOCAL) {
285                 if (addr_len >= sizeof(struct sockaddr_in6) &&
286                     addr->sin6_scope_id) {
287                         /* Override any existing binding, if another one
288                          * is supplied by user.
289                          */
290                         sk->bound_dev_if = addr->sin6_scope_id;
291                 }
292
293                 /* Binding to link-local address requires an interface */
294                 if (sk->bound_dev_if == 0) {
295                         release_sock(sk);
296                         return -EINVAL;
297                 }
298         }
299
300         sk->rcv_saddr = v4addr;
301         sk->saddr = v4addr;
302
303         ipv6_addr_copy(&sk->net_pinfo.af_inet6.rcv_saddr, &addr->sin6_addr);
304                 
305         if (!(addr_type & IPV6_ADDR_MULTICAST))
306                 ipv6_addr_copy(&sk->net_pinfo.af_inet6.saddr, &addr->sin6_addr);
307
308         /* Make sure we are allowed to bind here. */
309         if (sk->prot->get_port(sk, snum) != 0) {
310                 sk->rcv_saddr = 0;
311                 sk->saddr = 0;
312                 memset(&sk->net_pinfo.af_inet6.rcv_saddr, 0, sizeof(struct in6_addr));
313                 memset(&sk->net_pinfo.af_inet6.saddr, 0, sizeof(struct in6_addr));
314
315                 release_sock(sk);
316                 return -EADDRINUSE;
317         }
318
319         if (addr_type != IPV6_ADDR_ANY)
320                 sk->userlocks |= SOCK_BINDADDR_LOCK;
321         if (snum)
322                 sk->userlocks |= SOCK_BINDPORT_LOCK;
323         sk->sport = ntohs(sk->num);
324         sk->dport = 0;
325         sk->daddr = 0;
326         release_sock(sk);
327
328         return 0;
329 }
330
331 static int inet6_release(struct socket *sock)
332 {
333         struct sock *sk = sock->sk;
334
335         if (sk == NULL)
336                 return -EINVAL;
337
338         /* Free mc lists */
339         ipv6_sock_mc_close(sk);
340
341         return inet_release(sock);
342 }
343
344 int inet6_destroy_sock(struct sock *sk)
345 {
346         struct sk_buff *skb;
347         struct ipv6_txoptions *opt;
348
349         /*
350          *      Release destination entry
351          */
352
353         sk_dst_reset(sk);
354
355         /* Release rx options */
356
357         if ((skb = xchg(&sk->net_pinfo.af_inet6.pktoptions, NULL)) != NULL)
358                 kfree_skb(skb);
359
360         /* Free flowlabels */
361         fl6_free_socklist(sk);
362
363         /* Free tx options */
364
365         if ((opt = xchg(&sk->net_pinfo.af_inet6.opt, NULL)) != NULL)
366                 sock_kfree_s(sk, opt, opt->tot_len);
367
368         return 0;
369 }
370
371 /*
372  *      This does both peername and sockname.
373  */
374  
375 static int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
376                  int *uaddr_len, int peer)
377 {
378         struct sockaddr_in6 *sin=(struct sockaddr_in6 *)uaddr;
379         struct sock *sk = sock->sk;
380   
381         sin->sin6_family = AF_INET6;
382         sin->sin6_flowinfo = 0;
383         sin->sin6_scope_id = 0;
384         if (peer) {
385                 if (!sk->dport)
386                         return -ENOTCONN;
387                 if (((1<<sk->state)&(TCPF_CLOSE|TCPF_SYN_SENT)) && peer == 1)
388                         return -ENOTCONN;
389                 sin->sin6_port = sk->dport;
390                 memcpy(&sin->sin6_addr, &sk->net_pinfo.af_inet6.daddr,
391                        sizeof(struct in6_addr));
392                 if (sk->net_pinfo.af_inet6.sndflow)
393                         sin->sin6_flowinfo = sk->net_pinfo.af_inet6.flow_label;
394         } else {
395                 if (ipv6_addr_type(&sk->net_pinfo.af_inet6.rcv_saddr) == IPV6_ADDR_ANY)
396                         memcpy(&sin->sin6_addr, 
397                                &sk->net_pinfo.af_inet6.saddr,
398                                sizeof(struct in6_addr));
399                 else
400                         memcpy(&sin->sin6_addr, 
401                                &sk->net_pinfo.af_inet6.rcv_saddr,
402                                sizeof(struct in6_addr));
403
404                 sin->sin6_port = sk->sport;
405         }
406         if (ipv6_addr_type(&sin->sin6_addr) & IPV6_ADDR_LINKLOCAL)
407                 sin->sin6_scope_id = sk->bound_dev_if;
408         *uaddr_len = sizeof(*sin);
409         return(0);
410 }
411
412 static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
413 {
414         struct sock *sk = sock->sk;
415         int err = -EINVAL;
416         int pid;
417
418         switch(cmd) 
419         {
420         case FIOSETOWN:
421         case SIOCSPGRP:
422                 if (get_user(pid, (int *) arg))
423                         return -EFAULT;
424                 /* see sock_no_fcntl */
425                 if (current->pid != pid && current->pgrp != -pid && 
426                     !capable(CAP_NET_ADMIN))
427                         return -EPERM;
428                 sk->proc = pid;
429                 return(0);
430         case FIOGETOWN:
431         case SIOCGPGRP:
432                 return put_user(sk->proc,(int *)arg);
433         case SIOCGSTAMP:
434                 if(sk->stamp.tv_sec==0)
435                         return -ENOENT;
436                 err = copy_to_user((void *)arg, &sk->stamp,
437                                    sizeof(struct timeval));
438                 if (err)
439                         return -EFAULT;
440                 return 0;
441
442         case SIOCADDRT:
443         case SIOCDELRT:
444           
445                 return(ipv6_route_ioctl(cmd,(void *)arg));
446
447         case SIOCSIFADDR:
448                 return addrconf_add_ifaddr((void *) arg);
449         case SIOCDIFADDR:
450                 return addrconf_del_ifaddr((void *) arg);
451         case SIOCSIFDSTADDR:
452                 return addrconf_set_dstaddr((void *) arg);
453         default:
454                 if ((cmd >= SIOCDEVPRIVATE) &&
455                     (cmd <= (SIOCDEVPRIVATE + 15)))
456                         return(dev_ioctl(cmd,(void *) arg));
457                 
458                 if(sk->prot->ioctl==0 || (err=sk->prot->ioctl(sk, cmd, arg))==-ENOIOCTLCMD)
459                         return(dev_ioctl(cmd,(void *) arg));            
460                 return err;
461         }
462         /*NOTREACHED*/
463         return(0);
464 }
465
466 struct proto_ops inet6_stream_ops = {
467         family:         PF_INET6,
468
469         release:        inet6_release,
470         bind:           inet6_bind,
471         connect:        inet_stream_connect,            /* ok           */
472         socketpair:     sock_no_socketpair,             /* a do nothing */
473         accept:         inet_accept,                    /* ok           */
474         getname:        inet6_getname, 
475         poll:           tcp_poll,                       /* ok           */
476         ioctl:          inet6_ioctl,                    /* must change  */
477         listen:         inet_listen,                    /* ok           */
478         shutdown:       inet_shutdown,                  /* ok           */
479         setsockopt:     inet_setsockopt,                /* ok           */
480         getsockopt:     inet_getsockopt,                /* ok           */
481         sendmsg:        inet_sendmsg,                   /* ok           */
482         recvmsg:        inet_recvmsg,                   /* ok           */
483         mmap:           sock_no_mmap,
484         sendpage:       tcp_sendpage
485 };
486
487 struct proto_ops inet6_dgram_ops = {
488         family:         PF_INET6,
489
490         release:        inet6_release,
491         bind:           inet6_bind,
492         connect:        inet_dgram_connect,             /* ok           */
493         socketpair:     sock_no_socketpair,             /* a do nothing */
494         accept:         sock_no_accept,                 /* a do nothing */
495         getname:        inet6_getname, 
496         poll:           datagram_poll,                  /* ok           */
497         ioctl:          inet6_ioctl,                    /* must change  */
498         listen:         sock_no_listen,                 /* ok           */
499         shutdown:       inet_shutdown,                  /* ok           */
500         setsockopt:     inet_setsockopt,                /* ok           */
501         getsockopt:     inet_getsockopt,                /* ok           */
502         sendmsg:        inet_sendmsg,                   /* ok           */
503         recvmsg:        inet_recvmsg,                   /* ok           */
504         mmap:           sock_no_mmap,
505         sendpage:       sock_no_sendpage,
506 };
507
508 struct net_proto_family inet6_family_ops = {
509         PF_INET6,
510         inet6_create
511 };
512
513 #ifdef MODULE
514 int ipv6_unload(void)
515 {
516         if (!unloadable) return 1;
517         /* We keep internally 3 raw sockets */
518         return atomic_read(&(__this_module.uc.usecount)) - 3;
519 }
520 #endif
521
522 #if defined(MODULE) && defined(CONFIG_SYSCTL)
523 extern void ipv6_sysctl_register(void);
524 extern void ipv6_sysctl_unregister(void);
525 #endif
526
527 static struct inet_protosw rawv6_protosw = {
528         type:        SOCK_RAW,
529         protocol:    IPPROTO_IP,        /* wild card */
530         prot:        &rawv6_prot,
531         ops:         &inet6_dgram_ops,
532         capability:  CAP_NET_RAW,
533         no_check:    UDP_CSUM_DEFAULT,
534         flags:       INET_PROTOSW_REUSE,
535 };
536
537 #define INETSW6_ARRAY_LEN (sizeof(inetsw6_array) / sizeof(struct inet_protosw))
538
539 void
540 inet6_register_protosw(struct inet_protosw *p)
541 {
542         struct list_head *lh;
543         struct inet_protosw *answer;
544         int protocol = p->protocol;
545
546         br_write_lock_bh(BR_NETPROTO_LOCK);
547
548         if (p->type > SOCK_MAX)
549                 goto out_illegal;
550
551         /* If we are trying to override a permanent protocol, bail. */
552         answer = NULL;
553         list_for_each(lh, &inetsw6[p->type]) {
554                 answer = list_entry(lh, struct inet_protosw, list);
555
556                 /* Check only the non-wild match. */
557                 if (protocol == answer->protocol &&
558                     (INET_PROTOSW_PERMANENT & answer->flags))
559                         break;
560
561                 answer = NULL;
562         }
563         if (answer)
564                 goto out_permanent;
565
566         /* Add to the BEGINNING so that we override any existing
567          * entry.  This means that when we remove this entry, the
568          * system automatically returns to the old behavior.
569          */
570         list_add(&p->list, &inetsw6[p->type]);
571 out:
572         br_write_unlock_bh(BR_NETPROTO_LOCK);
573         return;
574
575 out_permanent:
576         printk(KERN_ERR "Attempt to override permanent protocol %d.\n",
577                protocol);
578         goto out;
579
580 out_illegal:
581         printk(KERN_ERR
582                "Ignoring attempt to register illegal socket type %d.\n",
583                p->type);
584         goto out;
585 }
586
587 void
588 inet6_unregister_protosw(struct inet_protosw *p)
589 {
590         inet_unregister_protosw(p);
591 }
592
593 static int __init inet6_init(void)
594 {
595         struct sk_buff *dummy_skb;
596         struct list_head *r;
597         int err;
598
599 #ifdef MODULE
600         if (!mod_member_present(&__this_module, can_unload))
601           return -EINVAL;
602
603         __this_module.can_unload = &ipv6_unload;
604 #endif
605
606         printk(KERN_INFO "IPv6 v0.8 for NET4.0\n");
607
608         if (sizeof(struct inet6_skb_parm) > sizeof(dummy_skb->cb))
609         {
610                 printk(KERN_CRIT "inet6_proto_init: size fault\n");
611                 return -EINVAL;
612         }
613
614         /* Register the socket-side information for inet6_create.  */
615         for(r = &inetsw6[0]; r < &inetsw6[SOCK_MAX]; ++r)
616                 INIT_LIST_HEAD(r);
617
618         /* We MUST register RAW sockets before we create the ICMP6,
619          * IGMP6, or NDISC control sockets.
620          */
621         inet6_register_protosw(&rawv6_protosw);
622
623         /*
624          *      ipngwg API draft makes clear that the correct semantics
625          *      for TCP and UDP is to consider one TCP and UDP instance
626          *      in a host availiable by both INET and INET6 APIs and
627          *      able to communicate via both network protocols.
628          */
629
630 #if defined(MODULE) && defined(CONFIG_SYSCTL)
631         ipv6_sysctl_register();
632 #endif
633         err = icmpv6_init(&inet6_family_ops);
634         if (err)
635                 goto icmp_fail;
636         err = ndisc_init(&inet6_family_ops);
637         if (err)
638                 goto ndisc_fail;
639         err = igmp6_init(&inet6_family_ops);
640         if (err)
641                 goto igmp_fail;
642         /* Create /proc/foo6 entries. */
643 #ifdef CONFIG_PROC_FS
644         err = -ENOMEM;
645         if (!proc_net_create("raw6", 0, raw6_get_info))
646                 goto proc_raw6_fail;
647         if (!proc_net_create("tcp6", 0, tcp6_get_info))
648                 goto proc_tcp6_fail;
649         if (!proc_net_create("udp6", 0, udp6_get_info))
650                 goto proc_udp6_fail;
651         if (!proc_net_create("sockstat6", 0, afinet6_get_info))
652                 goto proc_sockstat6_fail;
653         if (!proc_net_create("snmp6", 0, afinet6_get_snmp))
654                 goto proc_snmp6_fail;
655 #endif
656         ipv6_netdev_notif_init();
657         ipv6_packet_init();
658         ip6_route_init();
659         ip6_flowlabel_init();
660         addrconf_init();
661         sit_init();
662
663         /* Init v6 transport protocols. */
664         udpv6_init();
665         tcpv6_init();
666
667         /* Now the userspace is allowed to create INET6 sockets. */
668         (void) sock_register(&inet6_family_ops);
669         
670         return 0;
671
672 #ifdef CONFIG_PROC_FS
673 proc_snmp6_fail:
674         proc_net_remove("sockstat6");
675 proc_sockstat6_fail:
676         proc_net_remove("udp6");
677 proc_udp6_fail:
678         proc_net_remove("tcp6");
679 proc_tcp6_fail:
680         proc_net_remove("raw6");
681 proc_raw6_fail:
682         igmp6_cleanup();
683 #endif
684 igmp_fail:
685         ndisc_cleanup();
686 ndisc_fail:
687         icmpv6_cleanup();
688 icmp_fail:
689 #if defined(MODULE) && defined(CONFIG_SYSCTL)
690         ipv6_sysctl_unregister();
691 #endif
692         return err;
693 }
694 module_init(inet6_init);
695
696
697 #ifdef MODULE
698 static void inet6_exit(void)
699 {
700         /* First of all disallow new sockets creation. */
701         sock_unregister(PF_INET6);
702 #ifdef CONFIG_PROC_FS
703         proc_net_remove("raw6");
704         proc_net_remove("tcp6");
705         proc_net_remove("udp6");
706         proc_net_remove("sockstat6");
707         proc_net_remove("snmp6");
708 #endif
709         /* Cleanup code parts. */
710         sit_cleanup();
711         ipv6_netdev_notif_cleanup();
712         ip6_flowlabel_cleanup();
713         addrconf_cleanup();
714         ip6_route_cleanup();
715         ipv6_packet_cleanup();
716         igmp6_cleanup();
717         ndisc_cleanup();
718         icmpv6_cleanup();
719 #ifdef CONFIG_SYSCTL
720         ipv6_sysctl_unregister();       
721 #endif
722 }
723 module_exit(inet6_exit);
724 #endif /* MODULE */
725 MODULE_LICENSE("GPL");