return ndev;
}
-static struct inet6_dev * ipv6_find_idev(struct net_device *dev)
+struct inet6_dev * ipv6_find_idev(struct net_device *dev)
{
struct inet6_dev *idev;
struct inet6_dev *idev = ifp->idev;
struct in6_addr addr, *tmpaddr;
unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp;
+ unsigned long regen_advance;
int tmp_plen;
int ret = 0;
int max_addresses;
tmp_tstamp = ifp->tstamp;
spin_unlock_bh(&ifp->lock);
+ regen_advance = idev->cnf.regen_max_retry *
+ idev->cnf.dad_transmits *
+ idev->nd_parms->retrans_time / HZ;
write_unlock(&idev->lock);
+ /* A temporary address is created only if this calculated Preferred
+ * Lifetime is greater than REGEN_ADVANCE time units. In particular,
+ * an implementation must not create a temporary address with a zero
+ * Preferred Lifetime.
+ */
+ if (tmp_prefered_lft <= regen_advance) {
+ in6_ifa_put(ifp);
+ in6_dev_put(idev);
+ ret = -1;
+ goto out;
+ }
+
addr_flags = IFA_F_TEMPORARY;
/* set in addrconf_prefix_rcv() */
if (ifp->flags & IFA_F_OPTIMISTIC)
read_lock_bh(&addrconf_hash_lock);
for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
- if (dev_net(ifp->idev->dev) != net)
+ if (!net_eq(dev_net(ifp->idev->dev), net))
continue;
if (ipv6_addr_equal(&ifp->addr, addr) &&
!(ifp->flags&IFA_F_TENTATIVE)) {
u8 hash = ipv6_addr_hash(addr);
for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
- if (dev_net(ifp->idev->dev) != net)
+ if (!net_eq(dev_net(ifp->idev->dev), net))
continue;
if (ipv6_addr_equal(&ifp->addr, addr)) {
if (dev == NULL || ifp->idev->dev == dev)
return ifp != NULL;
}
+int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev)
+{
+ struct inet6_dev *idev;
+ struct inet6_ifaddr *ifa;
+ int onlink;
+
+ onlink = 0;
+ rcu_read_lock();
+ idev = __in6_dev_get(dev);
+ if (idev) {
+ read_lock_bh(&idev->lock);
+ for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) {
+ onlink = ipv6_prefix_equal(addr, &ifa->addr,
+ ifa->prefix_len);
+ if (onlink)
+ break;
+ }
+ read_unlock_bh(&idev->lock);
+ }
+ rcu_read_unlock();
+ return onlink;
+}
+
+EXPORT_SYMBOL(ipv6_chk_prefix);
+
struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, struct in6_addr *addr,
struct net_device *dev, int strict)
{
read_lock_bh(&addrconf_hash_lock);
for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) {
- if (dev_net(ifp->idev->dev) != net)
+ if (!net_eq(dev_net(ifp->idev->dev), net))
continue;
if (ipv6_addr_equal(&ifp->addr, addr)) {
if (dev == NULL || ifp->idev->dev == dev ||
* lifetimes of an existing temporary address
* when processing a Prefix Information Option.
*/
+ if (ifp != ift->ifpub)
+ continue;
+
spin_lock(&ift->lock);
flags = ift->flags;
if (ift->valid_lft > valid_lft &&
{
struct inet6_ifaddr *ifa = NULL;
struct if6_iter_state *state = seq->private;
- struct net *net = state->p.net;
+ struct net *net = seq_file_net(seq);
for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) {
ifa = inet6_addr_lst[state->bucket];
- while (ifa && dev_net(ifa->idev->dev) != net)
+ while (ifa && !net_eq(dev_net(ifa->idev->dev), net))
ifa = ifa->lst_next;
if (ifa)
break;
static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa)
{
struct if6_iter_state *state = seq->private;
- struct net *net = state->p.net;
+ struct net *net = seq_file_net(seq);
ifa = ifa->lst_next;
try_again:
if (ifa) {
- if (dev_net(ifa->idev->dev) != net) {
+ if (!net_eq(dev_net(ifa->idev->dev), net)) {
ifa = ifa->lst_next;
goto try_again;
}
u8 hash = ipv6_addr_hash(addr);
read_lock_bh(&addrconf_hash_lock);
for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) {
- if (dev_net(ifp->idev->dev) != net)
+ if (!net_eq(dev_net(ifp->idev->dev), net))
continue;
if (ipv6_addr_cmp(&ifp->addr, addr) == 0 &&
(ifp->flags & IFA_F_HOMEADDRESS)) {
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
array[DEVCONF_OPTIMISTIC_DAD] = cnf->optimistic_dad;
#endif
+#ifdef CONFIG_IPV6_MROUTE
+ array[DEVCONF_MC_FORWARDING] = cnf->mc_forwarding;
+#endif
}
static inline size_t inet6_if_nlmsg_size(void)
static struct addrconf_sysctl_table
{
struct ctl_table_header *sysctl_header;
- ctl_table addrconf_vars[__NET_IPV6_MAX];
+ ctl_table addrconf_vars[DEVCONF_MAX+1];
char *dev_name;
} addrconf_sysctl __read_mostly = {
.sysctl_header = NULL,
.proc_handler = &proc_dointvec,
},
+#endif
+#ifdef CONFIG_IPV6_MROUTE
+ {
+ .ctl_name = CTL_UNNUMBERED,
+ .procname = "mc_forwarding",
+ .data = &ipv6_devconf.mc_forwarding,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
#endif
{
.ctl_name = 0, /* sentinel */