#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
+#include <linux/capability.h>
#include <linux/delay.h>
#include <linux/notifier.h>
#include <linux/string.h>
#ifdef CONFIG_IPV6_PRIVACY
#include <linux/random.h>
-#include <linux/crypto.h>
-#include <linux/scatterlist.h>
#endif
#include <asm/uaccess.h>
static void ipv6_regen_rndid(unsigned long data);
static int desync_factor = MAX_DESYNC_FACTOR * HZ;
-static struct crypto_tfm *md5_tfm;
-static DEFINE_SPINLOCK(md5_tfm_lock);
#endif
static int ipv6_count_addresses(struct inet6_dev *idev);
.max_desync_factor = MAX_DESYNC_FACTOR,
#endif
.max_addresses = IPV6_MAX_ADDRESSES,
+ .accept_ra_defrtr = 1,
+ .accept_ra_pinfo = 1,
+#ifdef CONFIG_IPV6_ROUTER_PREF
+ .accept_ra_rtr_pref = 1,
+ .rtr_probe_interval = 60 * HZ,
+#endif
};
static struct ipv6_devconf ipv6_devconf_dflt = {
.max_desync_factor = MAX_DESYNC_FACTOR,
#endif
.max_addresses = IPV6_MAX_ADDRESSES,
+ .accept_ra_defrtr = 1,
+ .accept_ra_pinfo = 1,
+#ifdef CONFIG_IPV6_ROUTER_PREF
+ .accept_ra_rtr_pref = 1,
+ .rtr_probe_interval = 60 * HZ,
+#endif
};
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
in6_dev_hold(ndev);
#ifdef CONFIG_IPV6_PRIVACY
- get_random_bytes(ndev->rndid, sizeof(ndev->rndid));
- get_random_bytes(ndev->entropy, sizeof(ndev->entropy));
init_timer(&ndev->regen_timer);
ndev->regen_timer.function = ipv6_regen_rndid;
ndev->regen_timer.data = (unsigned long) ndev;
int addr_type;
unsigned int attrs;
int matchlen;
- unsigned int scope;
+ int scope;
unsigned int rule;
};
__ipv6_dev_ac_dec(ifp->idev, &addr);
}
+static int addrconf_ifid_eui48(u8 *eui, struct net_device *dev)
+{
+ if (dev->addr_len != ETH_ALEN)
+ return -1;
+ memcpy(eui, dev->dev_addr, 3);
+ memcpy(eui + 5, dev->dev_addr + 3, 3);
+
+ /*
+ * The zSeries OSA network cards can be shared among various
+ * OS instances, but the OSA cards have only one MAC address.
+ * This leads to duplicate address conflicts in conjunction
+ * with IPv6 if more than one instance uses the same card.
+ *
+ * The driver for these cards can deliver a unique 16-bit
+ * identifier for each instance sharing the same card. It is
+ * placed instead of 0xFFFE in the interface identifier. The
+ * "u" bit of the interface identifier is not inverted in this
+ * case. Hence the resulting interface identifier has local
+ * scope according to RFC2373.
+ */
+ if (dev->dev_id) {
+ eui[3] = (dev->dev_id >> 8) & 0xFF;
+ eui[4] = dev->dev_id & 0xFF;
+ } else {
+ eui[3] = 0xFF;
+ eui[4] = 0xFE;
+ eui[0] ^= 2;
+ }
+ return 0;
+}
+
+static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev)
+{
+ /* XXX: inherit EUI-64 from other interface -- yoshfuji */
+ if (dev->addr_len != ARCNET_ALEN)
+ return -1;
+ memset(eui, 0, 7);
+ eui[7] = *(u8*)dev->dev_addr;
+ return 0;
+}
+
+static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev)
+{
+ if (dev->addr_len != INFINIBAND_ALEN)
+ return -1;
+ memcpy(eui, dev->dev_addr + 12, 8);
+ eui[0] |= 2;
+ return 0;
+}
+
static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
{
switch (dev->type) {
case ARPHRD_ETHER:
case ARPHRD_FDDI:
case ARPHRD_IEEE802_TR:
- if (dev->addr_len != ETH_ALEN)
- return -1;
- memcpy(eui, dev->dev_addr, 3);
- memcpy(eui + 5, dev->dev_addr + 3, 3);
-
- /*
- * The zSeries OSA network cards can be shared among various
- * OS instances, but the OSA cards have only one MAC address.
- * This leads to duplicate address conflicts in conjunction
- * with IPv6 if more than one instance uses the same card.
- *
- * The driver for these cards can deliver a unique 16-bit
- * identifier for each instance sharing the same card. It is
- * placed instead of 0xFFFE in the interface identifier. The
- * "u" bit of the interface identifier is not inverted in this
- * case. Hence the resulting interface identifier has local
- * scope according to RFC2373.
- */
- if (dev->dev_id) {
- eui[3] = (dev->dev_id >> 8) & 0xFF;
- eui[4] = dev->dev_id & 0xFF;
- } else {
- eui[3] = 0xFF;
- eui[4] = 0xFE;
- eui[0] ^= 2;
- }
- return 0;
+ return addrconf_ifid_eui48(eui, dev);
case ARPHRD_ARCNET:
- /* XXX: inherit EUI-64 from other interface -- yoshfuji */
- if (dev->addr_len != ARCNET_ALEN)
- return -1;
- memset(eui, 0, 7);
- eui[7] = *(u8*)dev->dev_addr;
- return 0;
+ return addrconf_ifid_arcnet(eui, dev);
case ARPHRD_INFINIBAND:
- if (dev->addr_len != INFINIBAND_ALEN)
- return -1;
- memcpy(eui, dev->dev_addr + 12, 8);
- eui[0] |= 2;
- return 0;
+ return addrconf_ifid_infiniband(eui, dev);
}
return -1;
}
/* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */
static int __ipv6_regen_rndid(struct inet6_dev *idev)
{
- struct net_device *dev;
- struct scatterlist sg[2];
-
- sg_set_buf(&sg[0], idev->entropy, 8);
- sg_set_buf(&sg[1], idev->work_eui64, 8);
-
- dev = idev->dev;
-
- if (ipv6_generate_eui64(idev->work_eui64, dev)) {
- printk(KERN_INFO
- "__ipv6_regen_rndid(idev=%p): cannot get EUI64 identifier; use random bytes.\n",
- idev);
- get_random_bytes(idev->work_eui64, sizeof(idev->work_eui64));
- }
regen:
- spin_lock(&md5_tfm_lock);
- if (unlikely(md5_tfm == NULL)) {
- spin_unlock(&md5_tfm_lock);
- return -1;
- }
- crypto_digest_init(md5_tfm);
- crypto_digest_update(md5_tfm, sg, 2);
- crypto_digest_final(md5_tfm, idev->work_digest);
- spin_unlock(&md5_tfm_lock);
-
- memcpy(idev->rndid, &idev->work_digest[0], 8);
+ get_random_bytes(idev->rndid, sizeof(idev->rndid));
idev->rndid[0] &= ~0x02;
- memcpy(idev->entropy, &idev->work_digest[8], 8);
/*
* <draft-ietf-ipngwg-temp-addresses-v2-00.txt>:
return;
}
ip6_tnl_add_linklocal(idev);
- addrconf_add_mroute(dev);
}
static int addrconf_notify(struct notifier_block *this, unsigned long event,
dev->name);
break;
}
+
+ if (idev)
+ idev->if_flags |= IF_READY;
} else {
if (!netif_carrier_ok(dev)) {
/* device is still not ready. */
{
struct inet6_ifaddr *ifp = (struct inet6_ifaddr *)v;
seq_printf(seq,
- "%04x%04x%04x%04x%04x%04x%04x%04x %02x %02x %02x %02x %8s\n",
+ NIP6_SEQFMT " %02x %02x %02x %02x %8s\n",
NIP6(ifp->addr),
ifp->idev->dev->ifindex,
ifp->prefix_len,
array[DEVCONF_MAX_DESYNC_FACTOR] = cnf->max_desync_factor;
#endif
array[DEVCONF_MAX_ADDRESSES] = cnf->max_addresses;
+ array[DEVCONF_ACCEPT_RA_DEFRTR] = cnf->accept_ra_defrtr;
+ array[DEVCONF_ACCEPT_RA_PINFO] = cnf->accept_ra_pinfo;
+#ifdef CONFIG_IPV6_ROUTER_PREF
+ array[DEVCONF_ACCEPT_RA_RTR_PREF] = cnf->accept_ra_rtr_pref;
+ array[DEVCONF_RTR_PROBE_INTERVAL] = cnf->rtr_probe_interval;
+#endif
}
static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
switch (event) {
case RTM_NEWADDR:
- dst_hold(&ifp->rt->u.dst);
- if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL))
- dst_release(&ifp->rt->u.dst);
+ ip6_ins_rt(ifp->rt, NULL, NULL, NULL);
if (ifp->idev->cnf.forwarding)
addrconf_join_anycast(ifp);
break;
dst_hold(&ifp->rt->u.dst);
if (ip6_del_rt(ifp->rt, NULL, NULL, NULL))
dst_free(&ifp->rt->u.dst);
- else
- dst_release(&ifp->rt->u.dst);
break;
}
}
.mode = 0644,
.proc_handler = &proc_dointvec,
},
+ {
+ .ctl_name = NET_IPV6_ACCEPT_RA_DEFRTR,
+ .procname = "accept_ra_defrtr",
+ .data = &ipv6_devconf.accept_ra_defrtr,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV6_ACCEPT_RA_PINFO,
+ .procname = "accept_ra_pinfo",
+ .data = &ipv6_devconf.accept_ra_pinfo,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+#ifdef CONFIG_IPV6_ROUTER_PREF
+ {
+ .ctl_name = NET_IPV6_ACCEPT_RA_RTR_PREF,
+ .procname = "accept_ra_rtr_pref",
+ .data = &ipv6_devconf.accept_ra_rtr_pref,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ {
+ .ctl_name = NET_IPV6_RTR_PROBE_INTERVAL,
+ .procname = "router_probe_interval",
+ .data = &ipv6_devconf.rtr_probe_interval,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec_jiffies,
+ .strategy = &sysctl_jiffies,
+ },
+#endif
{
.ctl_name = 0, /* sentinel */
}
register_netdevice_notifier(&ipv6_dev_notf);
-#ifdef CONFIG_IPV6_PRIVACY
- md5_tfm = crypto_alloc_tfm("md5", 0);
- if (unlikely(md5_tfm == NULL))
- printk(KERN_WARNING
- "failed to load transform for md5\n");
-#endif
-
addrconf_verify(0);
rtnetlink_links[PF_INET6] = inet6_rtnetlink_table;
#ifdef CONFIG_SYSCTL
rtnl_unlock();
-#ifdef CONFIG_IPV6_PRIVACY
- crypto_free_tfm(md5_tfm);
- md5_tfm = NULL;
-#endif
-
#ifdef CONFIG_PROC_FS
proc_net_remove("if_inet6");
#endif