diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-08-25 09:12:35 +0000 |
commit | c7fc24dc4420057f103afe8fc64524ebc25c5d37 (patch) | |
tree | 3682407a599b8f9f03fc096298134cafba1c9b2f /net/ipv6/ipv6_sockglue.c | |
parent | 1d793fade8b063fde3cf275bf1a5c2d381292cd9 (diff) |
o Merge with Linux 2.1.116.
o New Newport console code.
o New G364 console code.
Diffstat (limited to 'net/ipv6/ipv6_sockglue.c')
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 83 |
1 files changed, 63 insertions, 20 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index ebd3365cd..b31c07c00 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -7,7 +7,7 @@ * * Based on linux/net/ipv4/ip_sockglue.c * - * $Id: ipv6_sockglue.c,v 1.19 1998/04/30 16:24:26 freitag Exp $ + * $Id: ipv6_sockglue.c,v 1.22 1998/07/15 05:05:39 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -67,6 +67,45 @@ static struct notifier_block ipv6_dev_notf = { 0 }; +struct ip6_ra_chain *ip6_ra_chain; + +int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) +{ + struct ip6_ra_chain *ra, *new_ra, **rap; + + /* RA packet may be delivered ONLY to IPPROTO_RAW socket */ + if (sk->type != SOCK_RAW || sk->num != IPPROTO_RAW) + return -EINVAL; + + new_ra = (sel>=0) ? kmalloc(sizeof(*new_ra), GFP_KERNEL) : NULL; + + for (rap = &ip6_ra_chain; (ra=*rap) != NULL; rap = &ra->next) { + if (ra->sk == sk) { + if (sel>=0) { + if (new_ra) + kfree(new_ra); + return -EADDRINUSE; + } + *rap = ra->next; + if (ra->destructor) + ra->destructor(sk); + kfree(ra); + return 0; + } + } + if (new_ra == NULL) + return -ENOBUFS; + new_ra->sk = sk; + new_ra->sel = sel; + new_ra->destructor = destructor; + start_bh_atomic(); + new_ra->next = ra; + *rap = new_ra; + end_bh_atomic(); + return 0; +} + + int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen) { @@ -74,6 +113,9 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, int val, err; int retv = -ENOPROTOOPT; + if(level==SOL_IP && sk->type != SOCK_RAW) + return udp_prot.setsockopt(sk, level, optname, optval, optlen); + if(level!=SOL_IPV6) goto out; @@ -110,7 +152,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, sk->prot = &tcp_prot; tp->af_specific = &ipv4_specific; sk->socket->ops = &inet_stream_ops; - sk->family = AF_INET; + sk->family = PF_INET; } else { sk->prot = &udp_prot; sk->socket->ops = &inet_dgram_ops; @@ -197,7 +239,11 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr); else retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr); + break; } + case IPV6_ROUTER_ALERT: + retv = ip6_ra_control(sk, val, NULL); + break; }; out: @@ -207,7 +253,11 @@ out: int ipv6_getsockopt(struct sock *sk, int level, int optname, char *optval, int *optlen) { - return 0; + if(level==SOL_IP && sk->type != SOCK_RAW) + return udp_prot.getsockopt(sk, level, optname, optval, optlen); + if(level!=SOL_IPV6) + return -ENOPROTOOPT; + return -EINVAL; } #if defined(MODULE) && defined(CONFIG_SYSCTL) @@ -220,31 +270,24 @@ extern void ipv6_sysctl_register(void); extern void ipv6_sysctl_unregister(void); #endif -__initfunc(void ipv6_init(void)) +__initfunc(void ipv6_packet_init(void)) { dev_add_pack(&ipv6_packet_type); +} -#if defined(MODULE) && defined(CONFIG_SYSCTL) - ipv6_sysctl_register(); -#endif - +__initfunc(void ipv6_netdev_notif_init(void)) +{ register_netdevice_notifier(&ipv6_dev_notf); - - ip6_route_init(); } #ifdef MODULE -void ipv6_cleanup(void) +void ipv6_packet_cleanup(void) { - unregister_netdevice_notifier(&ipv6_dev_notf); dev_remove_pack(&ipv6_packet_type); -#ifdef CONFIG_SYSCTL - ipv6_sysctl_unregister(); -#endif - ip6_route_cleanup(); - icmpv6_cleanup(); - addrconf_cleanup(); } -#endif - +void ipv6_netdev_notif_cleanup(void) +{ + unregister_netdevice_notifier(&ipv6_dev_notf); +} +#endif |