Commit 70ced8bf authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents b3d4c027 6febb776
...@@ -191,7 +191,7 @@ struct ip_mc_list ...@@ -191,7 +191,7 @@ struct ip_mc_list
(IGMPV3_MASK((value) >> (nbmant), nbexp) + (nbexp)))) (IGMPV3_MASK((value) >> (nbmant), nbexp) + (nbexp))))
#define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value) #define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value)
#define IGMPV3_MRC(value) IGMPV3_EXP(0x8000, 12, 3, value) #define IGMPV3_MRC(value) IGMPV3_EXP(0x80, 4, 3, value)
extern int ip_check_mc(struct in_device *dev, u32 mc_addr, u32 src_addr, u16 proto); extern int ip_check_mc(struct in_device *dev, u32 mc_addr, u32 src_addr, u16 proto);
extern int igmp_rcv(struct sk_buff *); extern int igmp_rcv(struct sk_buff *);
...@@ -199,10 +199,12 @@ extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr); ...@@ -199,10 +199,12 @@ extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr); extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
extern void ip_mc_drop_socket(struct sock *sk); extern void ip_mc_drop_socket(struct sock *sk);
extern int ip_mc_source(int add, int omode, struct sock *sk, extern int ip_mc_source(int add, int omode, struct sock *sk,
struct ip_mreq_source *mreqs); struct ip_mreq_source *mreqs, int ifindex);
extern int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf); extern int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf,int ifindex);
extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf, extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
struct ip_msfilter *optval, int *optlen); struct ip_msfilter *optval, int *optlen);
extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
struct group_filter *optval, int *optlen);
extern int ip_mc_sf_allow(struct sock *sk, u32 local, u32 rmt, int dif); extern int ip_mc_sf_allow(struct sock *sk, u32 local, u32 rmt, int dif);
extern void ip_mr_init(void); extern void ip_mr_init(void);
extern void ip_mc_init_dev(struct in_device *); extern void ip_mc_init_dev(struct in_device *);
......
...@@ -140,6 +140,9 @@ struct net_proto_family { ...@@ -140,6 +140,9 @@ struct net_proto_family {
struct module *owner; struct module *owner;
}; };
extern int net_family_get(int family);
extern void net_family_put(int family);
struct iovec; struct iovec;
extern int sock_wake_async(struct socket *sk, int how, int band); extern int sock_wake_async(struct socket *sk, int how, int band);
......
...@@ -59,7 +59,7 @@ extern struct rt6_info *rt6_lookup(struct in6_addr *daddr, ...@@ -59,7 +59,7 @@ extern struct rt6_info *rt6_lookup(struct in6_addr *daddr,
struct in6_addr *saddr, struct in6_addr *saddr,
int oif, int flags); int oif, int flags);
extern struct rt6_info *ndisc_get_dummy_rt(void); extern struct rt6_info *ip6_dst_alloc(void);
/* /*
* support functions for ND * support functions for ND
......
...@@ -2582,6 +2582,16 @@ int register_netdevice(struct net_device *dev) ...@@ -2582,6 +2582,16 @@ int register_netdevice(struct net_device *dev)
if ((ret = kobject_register(&dev->kobj))) if ((ret = kobject_register(&dev->kobj)))
goto out_err; goto out_err;
/* Fix illegal SG+CSUM combinations. */
if ((dev->features & NETIF_F_SG) &&
!(dev->features & (NETIF_F_IP_CSUM |
NETIF_F_NO_CSUM |
NETIF_F_HW_CSUM))) {
printk("%s: Dropping NETIF_F_SG since no checksum feature.\n",
dev->name);
dev->features &= ~NETIF_F_SG;
}
/* /*
* nil rebuild_header routine, * nil rebuild_header routine,
* that should be never called and used as just bug trap. * that should be never called and used as just bug trap.
......
...@@ -589,8 +589,10 @@ static kmem_cache_t *sk_cachep; ...@@ -589,8 +589,10 @@ static kmem_cache_t *sk_cachep;
*/ */
struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab) struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
{ {
struct sock *sk; struct sock *sk = NULL;
if (!net_family_get(family))
goto out;
if (!slab) if (!slab)
slab = sk_cachep; slab = sk_cachep;
sk = kmem_cache_alloc(slab, priority); sk = kmem_cache_alloc(slab, priority);
...@@ -602,14 +604,16 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab) ...@@ -602,14 +604,16 @@ struct sock *sk_alloc(int family, int priority, int zero_it, kmem_cache_t *slab)
sock_lock_init(sk); sock_lock_init(sk);
} }
sk->slab = slab; sk->slab = slab;
} } else
net_family_put(family);
out:
return sk; return sk;
} }
void sk_free(struct sock *sk) void sk_free(struct sock *sk)
{ {
struct sk_filter *filter; struct sk_filter *filter;
const int family = sk->family;
if (sk->destruct) if (sk->destruct)
sk->destruct(sk); sk->destruct(sk);
...@@ -624,6 +628,7 @@ void sk_free(struct sock *sk) ...@@ -624,6 +628,7 @@ void sk_free(struct sock *sk)
printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc)); printk(KERN_DEBUG "sk_free: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
kmem_cache_free(sk->slab, sk); kmem_cache_free(sk->slab, sk);
net_family_put(family);
} }
void __init sk_init(void) void __init sk_init(void)
......
This diff is collapsed.
...@@ -1312,6 +1312,6 @@ void __init ip_init(void) ...@@ -1312,6 +1312,6 @@ void __init ip_init(void)
#ifdef CONFIG_IP_MULTICAST #ifdef CONFIG_IP_MULTICAST
proc_net_create("igmp", 0, ip_mc_procinfo); proc_net_create("igmp", 0, ip_mc_procinfo);
proc_net_create("mcfilter", 0, ip_mcf_procinfo);
#endif #endif
proc_net_create("mcfilter", 0, ip_mcf_procinfo);
} }
...@@ -631,7 +631,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt ...@@ -631,7 +631,7 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
kfree(msf); kfree(msf);
break; break;
} }
err = ip_mc_msfilter(sk, msf); err = ip_mc_msfilter(sk, msf, 0);
kfree(msf); kfree(msf);
break; break;
} }
...@@ -670,7 +670,142 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt ...@@ -670,7 +670,142 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
omode = MCAST_INCLUDE; omode = MCAST_INCLUDE;
add = 0; add = 0;
} }
err = ip_mc_source(add, omode, sk, &mreqs); err = ip_mc_source(add, omode, sk, &mreqs, 0);
break;
}
case MCAST_JOIN_GROUP:
case MCAST_LEAVE_GROUP:
{
struct group_req greq;
struct sockaddr_in *psin;
struct ip_mreqn mreq;
if (optlen < sizeof(struct group_req))
goto e_inval;
err = -EFAULT;
if(copy_from_user(&greq, optval, sizeof(greq)))
break;
psin = (struct sockaddr_in *)&greq.gr_group;
if (psin->sin_family != AF_INET)
goto e_inval;
memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr = psin->sin_addr;
mreq.imr_ifindex = greq.gr_interface;
if (optname == MCAST_JOIN_GROUP)
err = ip_mc_join_group(sk, &mreq);
else
err = ip_mc_leave_group(sk, &mreq);
break;
}
case MCAST_JOIN_SOURCE_GROUP:
case MCAST_LEAVE_SOURCE_GROUP:
case MCAST_BLOCK_SOURCE:
case MCAST_UNBLOCK_SOURCE:
{
struct group_source_req greqs;
struct ip_mreq_source mreqs;
struct sockaddr_in *psin;
int omode, add;
if (optlen != sizeof(struct group_source_req))
goto e_inval;
if (copy_from_user(&greqs, optval, sizeof(greqs))) {
err = -EFAULT;
break;
}
if (greqs.gsr_group.ss_family != AF_INET ||
greqs.gsr_source.ss_family != AF_INET) {
err = -EADDRNOTAVAIL;
break;
}
psin = (struct sockaddr_in *)&greqs.gsr_group;
mreqs.imr_multiaddr = psin->sin_addr.s_addr;
psin = (struct sockaddr_in *)&greqs.gsr_source;
mreqs.imr_sourceaddr = psin->sin_addr.s_addr;
mreqs.imr_interface = 0; /* use index for mc_source */
if (optname == MCAST_BLOCK_SOURCE) {
omode = MCAST_EXCLUDE;
add = 1;
} else if (optname == MCAST_UNBLOCK_SOURCE) {
omode = MCAST_EXCLUDE;
add = 0;
} else if (optname == MCAST_JOIN_SOURCE_GROUP) {
struct ip_mreqn mreq;
psin = (struct sockaddr_in *)&greqs.gsr_group;
mreq.imr_multiaddr = psin->sin_addr;
mreq.imr_address.s_addr = 0;
mreq.imr_ifindex = greqs.gsr_interface;
err = ip_mc_join_group(sk, &mreq);
if (err)
break;
omode = MCAST_INCLUDE;
add = 1;
} else /* MCAST_LEAVE_SOURCE_GROUP */ {
omode = MCAST_INCLUDE;
add = 0;
}
err = ip_mc_source(add, omode, sk, &mreqs,
greqs.gsr_interface);
break;
}
case MCAST_MSFILTER:
{
struct sockaddr_in *psin;
struct ip_msfilter *msf = 0;
struct group_filter *gsf = 0;
int msize, i, ifindex;
if (optlen < GROUP_FILTER_SIZE(0))
goto e_inval;
gsf = (struct group_filter *)kmalloc(optlen,GFP_KERNEL);
if (gsf == 0) {
err = -ENOBUFS;
break;
}
err = -EFAULT;
if (copy_from_user(gsf, optval, optlen)) {
goto mc_msf_out;
}
if (GROUP_FILTER_SIZE(gsf->gf_numsrc) < optlen) {
err = EINVAL;
goto mc_msf_out;
}
msize = IP_MSFILTER_SIZE(gsf->gf_numsrc);
msf = (struct ip_msfilter *)kmalloc(msize,GFP_KERNEL);
if (msf == 0) {
err = -ENOBUFS;
goto mc_msf_out;
}
ifindex = gsf->gf_interface;
psin = (struct sockaddr_in *)&gsf->gf_group;
if (psin->sin_family != AF_INET) {
err = -EADDRNOTAVAIL;
goto mc_msf_out;
}
msf->imsf_multiaddr = psin->sin_addr.s_addr;
msf->imsf_interface = 0;
msf->imsf_fmode = gsf->gf_fmode;
msf->imsf_numsrc = gsf->gf_numsrc;
err = -EADDRNOTAVAIL;
for (i=0; i<gsf->gf_numsrc; ++i) {
psin = (struct sockaddr_in *)&gsf->gf_slist[i];
if (psin->sin_family != AF_INET)
goto mc_msf_out;
msf->imsf_slist[i] = psin->sin_addr.s_addr;
}
kfree(gsf);
gsf = 0;
err = ip_mc_msfilter(sk, msf, ifindex);
mc_msf_out:
if (msf)
kfree(msf);
if (gsf)
kfree(gsf);
break; break;
} }
case IP_ROUTER_ALERT: case IP_ROUTER_ALERT:
...@@ -826,15 +961,37 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op ...@@ -826,15 +961,37 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
struct ip_msfilter msf; struct ip_msfilter msf;
int err; int err;
if (len < IP_MSFILTER_SIZE(0)) if (len < IP_MSFILTER_SIZE(0)) {
release_sock(sk);
return -EINVAL; return -EINVAL;
if (copy_from_user(&msf, optval, IP_MSFILTER_SIZE(0))) }
if (copy_from_user(&msf, optval, IP_MSFILTER_SIZE(0))) {
release_sock(sk);
return -EFAULT; return -EFAULT;
}
err = ip_mc_msfget(sk, &msf, err = ip_mc_msfget(sk, &msf,
(struct ip_msfilter *)optval, optlen); (struct ip_msfilter *)optval, optlen);
release_sock(sk); release_sock(sk);
return err; return err;
} }
case MCAST_MSFILTER:
{
struct group_filter gsf;
int err;
if (len < GROUP_FILTER_SIZE(0)) {
release_sock(sk);
return -EINVAL;
}
if (copy_from_user(&gsf, optval, GROUP_FILTER_SIZE(0))) {
release_sock(sk);
return -EFAULT;
}
err = ip_mc_gsfget(sk, &gsf,
(struct group_filter *)optval, optlen);
release_sock(sk);
return err;
}
case IP_PKTOPTIONS: case IP_PKTOPTIONS:
{ {
struct msghdr msg; struct msghdr msg;
......
...@@ -48,7 +48,7 @@ config IP_NF_IRC ...@@ -48,7 +48,7 @@ config IP_NF_IRC
<file:Documentation/modules.txt>. If unsure, say `Y'. <file:Documentation/modules.txt>. If unsure, say `Y'.
config IP_NF_TFTP config IP_NF_TFTP
tristate "TFTP prtocol support" tristate "TFTP protocol support"
depends on IP_NF_CONNTRACK depends on IP_NF_CONNTRACK
help help
TFTP connection tracking helper, this is required depending TFTP connection tracking helper, this is required depending
......
...@@ -120,6 +120,12 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *)) ...@@ -120,6 +120,12 @@ int ip6_ra_control(struct sock *sk, int sel, void (*destructor)(struct sock *))
return 0; return 0;
} }
extern int ip6_mc_source(int add, int omode, struct sock *sk,
struct group_source_req *pgsr);
extern int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf);
extern int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
struct group_filter *optval, int *optlen);
int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
int optlen) int optlen)
...@@ -393,12 +399,13 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, ...@@ -393,12 +399,13 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
break; break;
} }
psin6 = (struct sockaddr_in6 *)&greq.gr_group; psin6 = (struct sockaddr_in6 *)&greq.gr_group;
if (optname == IPV6_ADD_MEMBERSHIP) if (optname == MCAST_JOIN_GROUP)
retv = ipv6_sock_mc_join(sk, greq.gr_interface, retv = ipv6_sock_mc_join(sk, greq.gr_interface,
&psin6->sin6_addr); &psin6->sin6_addr);
else else
retv = ipv6_sock_mc_drop(sk, greq.gr_interface, retv = ipv6_sock_mc_drop(sk, greq.gr_interface,
&psin6->sin6_addr); &psin6->sin6_addr);
break;
} }
case MCAST_JOIN_SOURCE_GROUP: case MCAST_JOIN_SOURCE_GROUP:
case MCAST_LEAVE_SOURCE_GROUP: case MCAST_LEAVE_SOURCE_GROUP:
...@@ -414,7 +421,8 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval, ...@@ -414,7 +421,8 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
retv = -EFAULT; retv = -EFAULT;
break; break;
} }
if (greqs.gsr_group.ss_family != AF_INET6) { if (greqs.gsr_group.ss_family != AF_INET6 ||
greqs.gsr_source.ss_family != AF_INET6) {
retv = -EADDRNOTAVAIL; retv = -EADDRNOTAVAIL;
break; break;
} }
......
...@@ -768,7 +768,7 @@ static void mld_clear_delrec(struct inet6_dev *idev) ...@@ -768,7 +768,7 @@ static void mld_clear_delrec(struct inet6_dev *idev)
psf = pmc->mca_tomb; psf = pmc->mca_tomb;
pmc->mca_tomb = 0; pmc->mca_tomb = 0;
spin_unlock_bh(&pmc->mca_lock); spin_unlock_bh(&pmc->mca_lock);
for (psf=pmc->mca_tomb; psf; psf=psf_next) { for (; psf; psf=psf_next) {
psf_next = psf->sf_next; psf_next = psf->sf_next;
kfree(psf); kfree(psf);
} }
...@@ -1042,6 +1042,8 @@ int igmp6_event_query(struct sk_buff *skb) ...@@ -1042,6 +1042,8 @@ int igmp6_event_query(struct sk_buff *skb)
mld_clear_delrec(idev); mld_clear_delrec(idev);
} else if (len >= 28) { } else if (len >= 28) {
max_delay = MLDV2_MRC(ntohs(mlh2->mrc))*(HZ/10); max_delay = MLDV2_MRC(ntohs(mlh2->mrc))*(HZ/10);
if (!max_delay)
max_delay = 1;
idev->mc_maxdelay = max_delay; idev->mc_maxdelay = max_delay;
if (mlh2->qrv) if (mlh2->qrv)
idev->mc_qrv = mlh2->qrv; idev->mc_qrv = mlh2->qrv;
...@@ -2096,8 +2098,6 @@ static int ip6_mcf_read_proc(char *buffer, char **start, off_t offset, ...@@ -2096,8 +2098,6 @@ static int ip6_mcf_read_proc(char *buffer, char **start, off_t offset,
unsigned long icount, xcount, i; unsigned long icount, xcount, i;
spin_lock_bh(&imc->mca_lock); spin_lock_bh(&imc->mca_lock);
icount = imc->mca_sfcount[MCAST_INCLUDE];
xcount = imc->mca_sfcount[MCAST_EXCLUDE];
for (psf=imc->mca_sources; psf; psf=psf->sf_next) { for (psf=imc->mca_sources; psf; psf=psf->sf_next) {
if (first) { if (first) {
len += sprintf(buffer+len, "%3s %6s " len += sprintf(buffer+len, "%3s %6s "
...@@ -2130,36 +2130,6 @@ static int ip6_mcf_read_proc(char *buffer, char **start, off_t offset, ...@@ -2130,36 +2130,6 @@ static int ip6_mcf_read_proc(char *buffer, char **start, off_t offset,
in6_dev_put(idev); in6_dev_put(idev);
goto done; goto done;
} }
icount -= psf->sf_count[MCAST_INCLUDE];
xcount -= psf->sf_count[MCAST_EXCLUDE];
}
if (icount > 0 || xcount > 0) {
if (first) {
len += sprintf(buffer+len, "%3s %6s "
"%32s %32s %6s %6s\n", "Idx",
"Device", "Multicast Address",
"Source Address", "INC", "EXC");
first = 0;
}
len += sprintf(buffer+len,"%3d %6.6s ",
dev->ifindex, dev->name);
for (i=0; i<16; i++)
len += sprintf(buffer+len, "%02x",
imc->mca_addr.s6_addr[i]);
len += sprintf(buffer+len, " %32s %6lu %6lu\n",
"NONE", icount, xcount);
pos = begin+len;
if (pos < offset) {
len=0;
begin=pos;
}
if (pos > offset+length) {
spin_unlock_bh(&imc->mca_lock);
read_unlock_bh(&idev->lock);
in6_dev_put(idev);
goto done;
}
} }
spin_unlock_bh(&imc->mca_lock); spin_unlock_bh(&imc->mca_lock);
} }
......
...@@ -427,7 +427,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, ...@@ -427,7 +427,7 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh,
len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
rt = ndisc_get_dummy_rt(); rt = ip6_dst_alloc();
if (!rt) if (!rt)
return; return;
...@@ -524,7 +524,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, ...@@ -524,7 +524,7 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh,
saddr = &addr_buf; saddr = &addr_buf;
} }
rt = ndisc_get_dummy_rt(); rt = ip6_dst_alloc();
if (!rt) if (!rt)
return; return;
...@@ -595,7 +595,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, ...@@ -595,7 +595,7 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr,
int len; int len;
int err; int err;
rt = ndisc_get_dummy_rt(); rt = ip6_dst_alloc();
if (!rt) if (!rt)
return; return;
......
...@@ -130,12 +130,17 @@ struct fib6_node ip6_routing_table = { ...@@ -130,12 +130,17 @@ struct fib6_node ip6_routing_table = {
rwlock_t rt6_lock = RW_LOCK_UNLOCKED; rwlock_t rt6_lock = RW_LOCK_UNLOCKED;
/* Dummy rt for ndisc */ /* allocate dst with ip6_dst_ops */
struct rt6_info *ndisc_get_dummy_rt() static __inline__ struct rt6_info *__ip6_dst_alloc(void)
{ {
return dst_alloc(&ip6_dst_ops); return dst_alloc(&ip6_dst_ops);
} }
struct rt6_info *ip6_dst_alloc(void)
{
return __ip6_dst_alloc();
}
/* /*
* Route lookup. Any rt6_lock is implied. * Route lookup. Any rt6_lock is implied.
*/ */
...@@ -640,7 +645,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh) ...@@ -640,7 +645,7 @@ int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh)
if (rtmsg->rtmsg_metric == 0) if (rtmsg->rtmsg_metric == 0)
rtmsg->rtmsg_metric = IP6_RT_PRIO_USER; rtmsg->rtmsg_metric = IP6_RT_PRIO_USER;
rt = dst_alloc(&ip6_dst_ops); rt = __ip6_dst_alloc();
if (rt == NULL) if (rt == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -1035,9 +1040,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, ...@@ -1035,9 +1040,7 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr,
static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
{ {
struct rt6_info *rt; struct rt6_info *rt = __ip6_dst_alloc();
rt = dst_alloc(&ip6_dst_ops);
if (rt) { if (rt) {
rt->u.dst.input = ort->u.dst.input; rt->u.dst.input = ort->u.dst.input;
...@@ -1181,9 +1184,8 @@ int ip6_pkt_discard(struct sk_buff *skb) ...@@ -1181,9 +1184,8 @@ int ip6_pkt_discard(struct sk_buff *skb)
int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev) int ip6_rt_addr_add(struct in6_addr *addr, struct net_device *dev)
{ {
struct rt6_info *rt; struct rt6_info *rt = __ip6_dst_alloc();
rt = dst_alloc(&ip6_dst_ops);
if (rt == NULL) if (rt == NULL)
return -ENOMEM; return -ENOMEM;
......
...@@ -1052,6 +1052,7 @@ struct proto_ops netlink_ops = { ...@@ -1052,6 +1052,7 @@ struct proto_ops netlink_ops = {
struct net_proto_family netlink_family_ops = { struct net_proto_family netlink_family_ops = {
.family = PF_NETLINK, .family = PF_NETLINK,
.create = netlink_create, .create = netlink_create,
.owner = THIS_MODULE, /* for consistency 8) */
}; };
static int __init netlink_proto_init(void) static int __init netlink_proto_init(void)
...@@ -1065,6 +1066,11 @@ static int __init netlink_proto_init(void) ...@@ -1065,6 +1066,11 @@ static int __init netlink_proto_init(void)
sock_register(&netlink_family_ops); sock_register(&netlink_family_ops);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
create_proc_read_entry("net/netlink", 0, 0, netlink_read_proc, NULL); create_proc_read_entry("net/netlink", 0, 0, netlink_read_proc, NULL);
#endif
/* The netlink device handler may be needed early. */
rtnetlink_init();
#ifdef CONFIG_NETLINK_DEV
init_netlink();
#endif #endif
return 0; return 0;
} }
...@@ -1075,7 +1081,7 @@ static void __exit netlink_proto_exit(void) ...@@ -1075,7 +1081,7 @@ static void __exit netlink_proto_exit(void)
remove_proc_entry("net/netlink", NULL); remove_proc_entry("net/netlink", NULL);
} }
module_init(netlink_proto_init); subsys_initcall(netlink_proto_init);
module_exit(netlink_proto_exit); module_exit(netlink_proto_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -69,8 +69,6 @@ ...@@ -69,8 +69,6 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/wanrouter.h> #include <linux/wanrouter.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if_bridge.h> #include <linux/if_bridge.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/poll.h> #include <linux/poll.h>
...@@ -143,6 +141,36 @@ static struct file_operations socket_file_ops = { ...@@ -143,6 +141,36 @@ static struct file_operations socket_file_ops = {
static struct net_proto_family *net_families[NPROTO]; static struct net_proto_family *net_families[NPROTO];
static __inline__ void net_family_bug(int family)
{
printk(KERN_ERR "%d is not yet sock_registered!\n", family);
BUG();
}
int net_family_get(int family)
{
struct net_proto_family *prot = net_families[family];
int rc = 1;
barrier();
if (likely(prot != NULL))
rc = try_module_get(prot->owner);
else
net_family_bug(family);
return rc;
}
void net_family_put(int family)
{
struct net_proto_family *prot = net_families[family];
barrier();
if (likely(prot != NULL))
module_put(prot->owner);
else
net_family_bug(family);
}
#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT) #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
static atomic_t net_family_lockct = ATOMIC_INIT(0); static atomic_t net_family_lockct = ATOMIC_INIT(0);
static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED; static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED;
...@@ -511,7 +539,7 @@ void sock_release(struct socket *sock) ...@@ -511,7 +539,7 @@ void sock_release(struct socket *sock)
sock->ops->release(sock); sock->ops->release(sock);
sock->ops = NULL; sock->ops = NULL;
module_put(net_families[family]->owner); net_family_put(family);
} }
if (sock->fasync_list) if (sock->fasync_list)
...@@ -1064,7 +1092,7 @@ int sock_create(int family, int type, int protocol, struct socket **res) ...@@ -1064,7 +1092,7 @@ int sock_create(int family, int type, int protocol, struct socket **res)
sock->type = type; sock->type = type;
i = -EBUSY; i = -EBUSY;
if (!try_module_get(net_families[family]->owner)) if (!net_family_get(family))
goto out_release; goto out_release;
if ((i = net_families[family]->create(sock, protocol)) < 0) if ((i = net_families[family]->create(sock, protocol)) < 0)
...@@ -1953,17 +1981,6 @@ void __init sock_init(void) ...@@ -1953,17 +1981,6 @@ void __init sock_init(void)
* do_initcalls is run. * do_initcalls is run.
*/ */
/*
* The netlink device handler may be needed early.
*/
#ifdef CONFIG_NET
rtnetlink_init();
#endif
#ifdef CONFIG_NETLINK_DEV
init_netlink();
#endif
#ifdef CONFIG_NETFILTER #ifdef CONFIG_NETFILTER
netfilter_init(); netfilter_init();
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment