* devices. All mtu based now.
*/
-#include <linux/config.h>
+#include <linux/capability.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/timer.h>
#include <linux/string.h>
+#include <linux/if_addr.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
#include <linux/sysctl.h>
#include <linux/notifier.h>
#include <asm/uaccess.h>
+#include <asm/system.h>
#include <net/neighbour.h>
#include <net/dst.h>
#include <net/flow.h>
+#include <net/fib_rules.h>
+#include <net/netlink.h>
#include <net/dn.h>
#include <net/dn_dev.h>
#include <net/dn_route.h>
/*
* decnet_address is kept in network order.
*/
-dn_address decnet_address = 0;
+__le16 decnet_address = 0;
-static rwlock_t dndev_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(dndev_lock);
static struct net_device *decnet_default_device;
-static struct notifier_block *dnaddr_chain;
+static BLOCKING_NOTIFIER_HEAD(dnaddr_chain);
static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
static void dn_dev_delete(struct net_device *dev);
-static void rtmsg_ifa(int event, struct dn_ifaddr *ifa);
+static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa);
static int dn_eth_up(struct net_device *);
static void dn_eth_down(struct net_device *);
static int max_priority[] = { 127 }; /* From DECnet spec */
static int dn_forwarding_proc(ctl_table *, int, struct file *,
- void *, size_t *);
-static int dn_forwarding_sysctl(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen,
- void **context);
+ void __user *, size_t *, loff_t *);
+static int dn_forwarding_sysctl(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen);
static struct dn_dev_sysctl_table {
struct ctl_table_header *sysctl_header;
}, {0}}
};
-static inline __u16 mtu2blksize(struct net_device *dev)
-{
- u32 blksize = dev->mtu;
- if (blksize > 0xffff)
- blksize = 0xffff;
-
- if (dev->type == ARPHRD_ETHER ||
- dev->type == ARPHRD_PPP ||
- dev->type == ARPHRD_IPGRE ||
- dev->type == ARPHRD_LOOPBACK)
- blksize -= 2;
-
- return (__u16)blksize;
-}
-
static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
{
struct dn_dev_sysctl_table *t;
int i;
- t = kmalloc(sizeof(*t), GFP_KERNEL);
+ t = kmemdup(&dn_dev_sysctl, sizeof(*t), GFP_KERNEL);
if (t == NULL)
return;
- memcpy(t, &dn_dev_sysctl, sizeof(*t));
-
for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) {
long offset = (long)t->dn_dev_vars[i].data;
t->dn_dev_vars[i].data = ((char *)parms) + offset;
}
}
-struct net_device *dn_dev_get_default(void)
-{
- struct net_device *dev;
- read_lock(&dndev_lock);
- dev = decnet_default_device;
- if (dev) {
- if (dev->dn_ptr)
- dev_hold(dev);
- else
- dev = NULL;
- }
- read_unlock(&dndev_lock);
- return dev;
-}
-
-int dn_dev_set_default(struct net_device *dev, int force)
-{
- struct net_device *old = NULL;
- int rv = -EBUSY;
- if (!dev->dn_ptr)
- return -ENODEV;
- write_lock(&dndev_lock);
- if (force || decnet_default_device == NULL) {
- old = decnet_default_device;
- decnet_default_device = dev;
- rv = 0;
- }
- write_unlock(&dndev_lock);
- if (old)
- dev_put(dev);
- return rv;
-}
-
-static void dn_dev_check_default(struct net_device *dev)
-{
- write_lock(&dndev_lock);
- if (dev == decnet_default_device) {
- decnet_default_device = NULL;
- } else {
- dev = NULL;
- }
- write_unlock(&dndev_lock);
- if (dev)
- dev_put(dev);
-}
-
static int dn_forwarding_proc(ctl_table *table, int write,
struct file *filep,
- void *buffer, size_t *lenp)
+ void __user *buffer,
+ size_t *lenp, loff_t *ppos)
{
#ifdef CONFIG_DECNET_ROUTER
struct net_device *dev = table->extra1;
dn_db = dev->dn_ptr;
old = dn_db->parms.forwarding;
- err = proc_dointvec(table, write, filep, buffer, lenp);
+ err = proc_dointvec(table, write, filep, buffer, lenp, ppos);
if ((err >= 0) && write) {
if (dn_db->parms.forwarding < 0)
#endif
}
-static int dn_forwarding_sysctl(ctl_table *table, int *name, int nlen,
- void *oldval, size_t *oldlenp,
- void *newval, size_t newlen,
- void **context)
+static int dn_forwarding_sysctl(ctl_table *table, int __user *name, int nlen,
+ void __user *oldval, size_t __user *oldlenp,
+ void __user *newval, size_t newlen)
{
#ifdef CONFIG_DECNET_ROUTER
struct net_device *dev = table->extra1;
if (newlen != sizeof(int))
return -EINVAL;
- if (get_user(value, (int *)newval))
+ if (get_user(value, (int __user *)newval))
return -EFAULT;
if (value < 0)
return -EINVAL;
#endif /* CONFIG_SYSCTL */
+static inline __u16 mtu2blksize(struct net_device *dev)
+{
+ u32 blksize = dev->mtu;
+ if (blksize > 0xffff)
+ blksize = 0xffff;
+
+ if (dev->type == ARPHRD_ETHER ||
+ dev->type == ARPHRD_PPP ||
+ dev->type == ARPHRD_IPGRE ||
+ dev->type == ARPHRD_LOOPBACK)
+ blksize -= 2;
+
+ return (__u16)blksize;
+}
+
static struct dn_ifaddr *dn_dev_alloc_ifa(void)
{
struct dn_ifaddr *ifa;
- ifa = kmalloc(sizeof(*ifa), GFP_KERNEL);
-
- if (ifa) {
- memset(ifa, 0, sizeof(*ifa));
- }
+ ifa = kzalloc(sizeof(*ifa), GFP_KERNEL);
return ifa;
}
*ifap = ifa1->ifa_next;
if (dn_db->dev->type == ARPHRD_ETHER) {
- if (ifa1->ifa_local != dn_htons(dn_eth2dn(dev->dev_addr))) {
+ if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) {
dn_dn2eth(mac_addr, ifa1->ifa_local);
dev_mc_delete(dev, mac_addr, ETH_ALEN, 0);
}
}
- rtmsg_ifa(RTM_DELADDR, ifa1);
- notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
+ dn_ifaddr_notify(RTM_DELADDR, ifa1);
+ blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
if (destroy) {
dn_dev_free_ifa(ifa1);
}
if (dev->type == ARPHRD_ETHER) {
- if (ifa->ifa_local != dn_htons(dn_eth2dn(dev->dev_addr))) {
+ if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) {
dn_dn2eth(mac_addr, ifa->ifa_local);
dev_mc_add(dev, mac_addr, ETH_ALEN, 0);
dev_mc_upload(dev);
ifa->ifa_next = dn_db->ifa_list;
dn_db->ifa_list = ifa;
- rtmsg_ifa(RTM_NEWADDR, ifa);
- notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
+ dn_ifaddr_notify(RTM_NEWADDR, ifa);
+ blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
return 0;
}
}
-int dn_dev_ioctl(unsigned int cmd, void *arg)
+int dn_dev_ioctl(unsigned int cmd, void __user *arg)
{
char buffer[DN_IFREQ_SIZE];
struct ifreq *ifr = (struct ifreq *)buffer;
switch(cmd) {
case SIOCGIFADDR:
- *((dn_address *)sdn->sdn_nodeaddr) = ifa->ifa_local;
+ *((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local;
goto rarok;
case SIOCSIFADDR:
goto done;
}
+struct net_device *dn_dev_get_default(void)
+{
+ struct net_device *dev;
+ read_lock(&dndev_lock);
+ dev = decnet_default_device;
+ if (dev) {
+ if (dev->dn_ptr)
+ dev_hold(dev);
+ else
+ dev = NULL;
+ }
+ read_unlock(&dndev_lock);
+ return dev;
+}
+
+int dn_dev_set_default(struct net_device *dev, int force)
+{
+ struct net_device *old = NULL;
+ int rv = -EBUSY;
+ if (!dev->dn_ptr)
+ return -ENODEV;
+ write_lock(&dndev_lock);
+ if (force || decnet_default_device == NULL) {
+ old = decnet_default_device;
+ decnet_default_device = dev;
+ rv = 0;
+ }
+ write_unlock(&dndev_lock);
+ if (old)
+ dev_put(old);
+ return rv;
+}
+
+static void dn_dev_check_default(struct net_device *dev)
+{
+ write_lock(&dndev_lock);
+ if (dev == decnet_default_device) {
+ decnet_default_device = NULL;
+ } else {
+ dev = NULL;
+ }
+ write_unlock(&dndev_lock);
+ if (dev)
+ dev_put(dev);
+}
+
static struct dn_dev *dn_dev_by_index(int ifindex)
{
struct net_device *dev;
return dn_dev;
}
-static int dn_dev_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static struct nla_policy dn_ifa_policy[IFA_MAX+1] __read_mostly = {
+ [IFA_ADDRESS] = { .type = NLA_U16 },
+ [IFA_LOCAL] = { .type = NLA_U16 },
+ [IFA_LABEL] = { .type = NLA_STRING,
+ .len = IFNAMSIZ - 1 },
+};
+
+static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct rtattr **rta = arg;
+ struct nlattr *tb[IFA_MAX+1];
struct dn_dev *dn_db;
- struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+ struct ifaddrmsg *ifm;
struct dn_ifaddr *ifa, **ifap;
+ int err = -EADDRNOTAVAIL;
+
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
+ if (err < 0)
+ goto errout;
+ ifm = nlmsg_data(nlh);
if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL)
- return -EADDRNOTAVAIL;
+ goto errout;
- for(ifap = &dn_db->ifa_list; (ifa=*ifap) != NULL; ifap = &ifa->ifa_next) {
- void *tmp = rta[IFA_LOCAL-1];
- if ((tmp && memcmp(RTA_DATA(tmp), &ifa->ifa_local, 2)) ||
- (rta[IFA_LABEL-1] && strcmp(RTA_DATA(rta[IFA_LABEL-1]), ifa->ifa_label)))
+ for (ifap = &dn_db->ifa_list; (ifa = *ifap); ifap = &ifa->ifa_next) {
+ if (tb[IFA_LOCAL] &&
+ nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2))
+ continue;
+
+ if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
continue;
dn_dev_del_ifa(dn_db, ifap, 1);
return 0;
}
- return -EADDRNOTAVAIL;
+errout:
+ return err;
}
-static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
{
- struct rtattr **rta = arg;
+ struct nlattr *tb[IFA_MAX+1];
struct net_device *dev;
struct dn_dev *dn_db;
- struct ifaddrmsg *ifm = NLMSG_DATA(nlh);
+ struct ifaddrmsg *ifm;
struct dn_ifaddr *ifa;
- int rv;
+ int err;
- if (rta[IFA_LOCAL-1] == NULL)
+ err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, dn_ifa_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[IFA_LOCAL] == NULL)
return -EINVAL;
+ ifm = nlmsg_data(nlh);
if ((dev = __dev_get_by_index(ifm->ifa_index)) == NULL)
return -ENODEV;
if ((ifa = dn_dev_alloc_ifa()) == NULL)
return -ENOBUFS;
- if (!rta[IFA_ADDRESS - 1])
- rta[IFA_ADDRESS - 1] = rta[IFA_LOCAL - 1];
- memcpy(&ifa->ifa_local, RTA_DATA(rta[IFA_LOCAL-1]), 2);
- memcpy(&ifa->ifa_address, RTA_DATA(rta[IFA_ADDRESS-1]), 2);
+ if (tb[IFA_ADDRESS] == NULL)
+ tb[IFA_ADDRESS] = tb[IFA_LOCAL];
+
+ ifa->ifa_local = nla_get_le16(tb[IFA_LOCAL]);
+ ifa->ifa_address = nla_get_le16(tb[IFA_ADDRESS]);
ifa->ifa_flags = ifm->ifa_flags;
ifa->ifa_scope = ifm->ifa_scope;
ifa->ifa_dev = dn_db;
- if (rta[IFA_LABEL-1])
- memcpy(ifa->ifa_label, RTA_DATA(rta[IFA_LABEL-1]), IFNAMSIZ);
+
+ if (tb[IFA_LABEL])
+ nla_strlcpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
else
memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
- rv = dn_dev_insert_ifa(dn_db, ifa);
- if (rv)
+ err = dn_dev_insert_ifa(dn_db, ifa);
+ if (err)
dn_dev_free_ifa(ifa);
- return rv;
+
+ return err;
+}
+
+static inline size_t dn_ifaddr_nlmsg_size(void)
+{
+ return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
+ + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
+ + nla_total_size(2) /* IFA_ADDRESS */
+ + nla_total_size(2); /* IFA_LOCAL */
}
-static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
- u32 pid, u32 seq, int event)
+static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
+ u32 pid, u32 seq, int event, unsigned int flags)
{
struct ifaddrmsg *ifm;
struct nlmsghdr *nlh;
- unsigned char *b = skb->tail;
- nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
- ifm = NLMSG_DATA(nlh);
+ nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
+ if (nlh == NULL)
+ return -ENOBUFS;
+ ifm = nlmsg_data(nlh);
ifm->ifa_family = AF_DECnet;
ifm->ifa_prefixlen = 16;
ifm->ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
ifm->ifa_scope = ifa->ifa_scope;
ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
+
if (ifa->ifa_address)
- RTA_PUT(skb, IFA_ADDRESS, 2, &ifa->ifa_address);
+ NLA_PUT_LE16(skb, IFA_ADDRESS, ifa->ifa_address);
if (ifa->ifa_local)
- RTA_PUT(skb, IFA_LOCAL, 2, &ifa->ifa_local);
+ NLA_PUT_LE16(skb, IFA_LOCAL, ifa->ifa_local);
if (ifa->ifa_label[0])
- RTA_PUT(skb, IFA_LABEL, IFNAMSIZ, &ifa->ifa_label);
- nlh->nlmsg_len = skb->tail - b;
- return skb->len;
+ NLA_PUT_STRING(skb, IFA_LABEL, ifa->ifa_label);
+
+ return nlmsg_end(skb, nlh);
-nlmsg_failure:
-rtattr_failure:
- skb_trim(skb, b - skb->data);
- return -1;
+nla_put_failure:
+ return nlmsg_cancel(skb, nlh);
}
-static void rtmsg_ifa(int event, struct dn_ifaddr *ifa)
+static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
{
struct sk_buff *skb;
- int size = NLMSG_SPACE(sizeof(struct ifaddrmsg)+128);
+ int err = -ENOBUFS;
- skb = alloc_skb(size, GFP_KERNEL);
- if (!skb) {
- netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, ENOBUFS);
- return;
- }
- if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
- kfree_skb(skb);
- netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, EINVAL);
- return;
- }
- NETLINK_CB(skb).dst_groups = RTMGRP_DECnet_IFADDR;
- netlink_broadcast(rtnl, skb, 0, RTMGRP_DECnet_IFADDR, GFP_KERNEL);
+ skb = alloc_skb(dn_ifaddr_nlmsg_size(), GFP_KERNEL);
+ if (skb == NULL)
+ goto errout;
+
+ err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
+ /* failure implies BUG in dn_ifaddr_nlmsg_size() */
+ BUG_ON(err < 0);
+
+ err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
+errout:
+ if (err < 0)
+ rtnl_set_sk_err(RTNLGRP_DECnet_IFADDR, err);
}
-static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
{
- int idx, dn_idx;
- int s_idx, s_dn_idx;
+ int idx, dn_idx = 0, skip_ndevs, skip_naddr;
struct net_device *dev;
struct dn_dev *dn_db;
struct dn_ifaddr *ifa;
- s_idx = cb->args[0];
- s_dn_idx = dn_idx = cb->args[1];
+ skip_ndevs = cb->args[0];
+ skip_naddr = cb->args[1];
+
read_lock(&dev_base_lock);
- for(dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
- if (idx < s_idx)
+ for (dev = dev_base, idx = 0; dev; dev = dev->next, idx++) {
+ if (idx < skip_ndevs)
continue;
- if (idx > s_idx)
- s_dn_idx = 0;
+ else if (idx > skip_ndevs) {
+ /* Only skip over addresses for first dev dumped
+ * in this iteration (idx == skip_ndevs) */
+ skip_naddr = 0;
+ }
+
if ((dn_db = dev->dn_ptr) == NULL)
continue;
- for(ifa = dn_db->ifa_list, dn_idx = 0; ifa; ifa = ifa->ifa_next, dn_idx++) {
- if (dn_idx < s_dn_idx)
+ for (ifa = dn_db->ifa_list, dn_idx = 0; ifa;
+ ifa = ifa->ifa_next, dn_idx++) {
+ if (dn_idx < skip_naddr)
continue;
- if (dn_dev_fill_ifaddr(skb, ifa,
- NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq,
- RTM_NEWADDR) <= 0)
+ if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
+ cb->nlh->nlmsg_seq, RTM_NEWADDR,
+ NLM_F_MULTI) < 0)
goto done;
}
}
done:
read_unlock(&dev_base_lock);
+
cb->args[0] = idx;
cb->args[1] = dn_idx;
return skb->len;
}
-static int dn_dev_get_first(struct net_device *dev, dn_address *addr)
+static int dn_dev_get_first(struct net_device *dev, __le16 *addr)
{
struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
struct dn_ifaddr *ifa;
* a sensible default. Eventually the routing code will take care of all the
* nasties for us I hope.
*/
-int dn_dev_bind_default(dn_address *addr)
+int dn_dev_bind_default(__le16 *addr)
{
struct net_device *dev;
int rv;
{
struct endnode_hello_message *msg;
struct sk_buff *skb = NULL;
- unsigned short int *pktlen;
+ __le16 *pktlen;
struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
msg->datalen = 0x02;
memset(msg->data, 0xAA, 2);
- pktlen = (unsigned short *)skb_push(skb,2);
+ pktlen = (__le16 *)skb_push(skb,2);
*pktlen = dn_htons(skb->len - 2);
skb->nh.raw = skb->data;
size_t size;
unsigned char *ptr;
unsigned char *i1, *i2;
- unsigned short *pktlen;
+ __le16 *pktlen;
char *src;
if (mtu2blksize(dev) < (26 + 7))
ptr += ETH_ALEN;
*ptr++ = dn_db->parms.forwarding == 1 ?
DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
- *((unsigned short *)ptr) = dn_htons(mtu2blksize(dev));
+ *((__le16 *)ptr) = dn_htons(mtu2blksize(dev));
ptr += 2;
*ptr++ = dn_db->parms.priority; /* Priority */
*ptr++ = 0; /* Area: Reserved */
- *((unsigned short *)ptr) = dn_htons((unsigned short)dn_db->parms.t3);
+ *((__le16 *)ptr) = dn_htons((unsigned short)dn_db->parms.t3);
ptr += 2;
*ptr++ = 0; /* MPD: Reserved */
i1 = ptr++;
skb_trim(skb, (27 + *i2));
- pktlen = (unsigned short *)skb_push(skb, 2);
+ pktlen = (__le16 *)skb_push(skb, 2);
*pktlen = dn_htons(skb->len - 2);
skb->nh.raw = skb->data;
ptr = skb_put(skb, 2 + 4 + tdlen);
*ptr++ = DN_RT_PKT_HELO;
- *((dn_address *)ptr) = ifa->ifa_local;
+ *((__le16 *)ptr) = ifa->ifa_local;
ptr += 2;
*ptr++ = tdlen;
return NULL;
*err = -ENOBUFS;
- if ((dn_db = kmalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)
+ if ((dn_db = kzalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)
return NULL;
- memset(dn_db, 0, sizeof(struct dn_dev));
memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
+ smp_wmb();
dev->dn_ptr = dn_db;
dn_db->dev = dev;
init_timer(&dn_db->timer);
dn_db->uptime = jiffies;
+
+ dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
+ if (!dn_db->neigh_parms) {
+ dev->dn_ptr = NULL;
+ kfree(dn_db);
+ return NULL;
+ }
+
if (dn_db->parms.up) {
if (dn_db->parms.up(dev) < 0) {
+ neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
dev->dn_ptr = NULL;
kfree(dn_db);
return NULL;
}
}
- dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
-
dn_dev_sysctl_register(dev, &dn_db->parms);
dn_dev_set_timer(dev);
void dn_dev_up(struct net_device *dev)
{
struct dn_ifaddr *ifa;
- dn_address addr = decnet_address;
+ __le16 addr = decnet_address;
int maybe_default = 0;
struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
if (dev->type == ARPHRD_ETHER) {
if (memcmp(dev->dev_addr, dn_hiord, 4) != 0)
return;
- addr = dn_htons(dn_eth2dn(dev->dev_addr));
+ addr = dn_eth2dn(dev->dev_addr);
maybe_default = 1;
}
dev->dn_ptr = NULL;
neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
+ neigh_ifdown(&dn_neigh_table, dev);
if (dn_db->router)
neigh_release(dn_db->router);
int register_dnaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_register(&dnaddr_chain, nb);
+ return blocking_notifier_chain_register(&dnaddr_chain, nb);
}
int unregister_dnaddr_notifier(struct notifier_block *nb)
{
- return notifier_chain_unregister(&dnaddr_chain, nb);
-}
-
-#ifdef CONFIG_DECNET_SIOCGIFCONF
-/*
- * Now we support multiple addresses per interface.
- * Since we don't want to break existing code, you have to enable
- * it as a compile time option. Probably you should use the
- * rtnetlink interface instead.
- */
-int dnet_gifconf(struct net_device *dev, char __user *buf, int len)
-{
- struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr;
- struct dn_ifaddr *ifa;
- char buffer[DN_IFREQ_SIZE];
- struct ifreq *ifr = (struct ifreq *)buffer;
- struct sockaddr_dn *addr = (struct sockaddr_dn *)&ifr->ifr_addr;
- int done = 0;
-
- if ((dn_db == NULL) || ((ifa = dn_db->ifa_list) == NULL))
- return 0;
-
- for(; ifa; ifa = ifa->ifa_next) {
- if (!buf) {
- done += sizeof(DN_IFREQ_SIZE);
- continue;
- }
- if (len < DN_IFREQ_SIZE)
- return done;
- memset(buffer, 0, DN_IFREQ_SIZE);
-
- if (ifa->ifa_label)
- strcpy(ifr->ifr_name, ifa->ifa_label);
- else
- strcpy(ifr->ifr_name, dev->name);
-
- addr->sdn_family = AF_DECnet;
- addr->sdn_add.a_len = 2;
- memcpy(addr->sdn_add.a_addr, &ifa->ifa_local,
- sizeof(dn_address));
-
- if (copy_to_user(buf, buffer, DN_IFREQ_SIZE)) {
- done = -EFAULT;
- break;
- }
-
- buf += DN_IFREQ_SIZE;
- len -= DN_IFREQ_SIZE;
- done += DN_IFREQ_SIZE;
- }
-
- return done;
+ return blocking_notifier_chain_unregister(&dnaddr_chain, nb);
}
-#endif /* CONFIG_DECNET_SIOCGIFCONF */
-
#ifdef CONFIG_PROC_FS
static inline struct net_device *dn_dev_get_next(struct seq_file *seq, struct net_device *dev)
mtu2blksize(dev),
dn_db->parms.priority,
dn_db->parms.state, dn_db->parms.name,
- dn_db->router ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->router->primary_key), router_buf) : "",
- dn_db->peer ? dn_addr2asc(dn_ntohs(*(dn_address *)dn_db->peer->primary_key), peer_buf) : "");
+ dn_db->router ? dn_addr2asc(dn_ntohs(*(__le16 *)dn_db->router->primary_key), router_buf) : "",
+ dn_db->peer ? dn_addr2asc(dn_ntohs(*(__le16 *)dn_db->peer->primary_key), peer_buf) : "");
}
return 0;
}
#endif /* CONFIG_PROC_FS */
-static struct rtnetlink_link dnet_rtnetlink_table[RTM_MAX-RTM_BASE+1] =
+static struct rtnetlink_link dnet_rtnetlink_table[RTM_NR_MSGTYPES] =
{
- [4] = { .doit = dn_dev_rtm_newaddr, },
- [5] = { .doit = dn_dev_rtm_deladdr, },
- [6] = { .dumpit = dn_dev_dump_ifaddr, },
-
+ [RTM_NEWADDR - RTM_BASE] = { .doit = dn_nl_newaddr, },
+ [RTM_DELADDR - RTM_BASE] = { .doit = dn_nl_deladdr, },
+ [RTM_GETADDR - RTM_BASE] = { .dumpit = dn_nl_dump_ifaddr, },
#ifdef CONFIG_DECNET_ROUTER
- [8] = { .doit = dn_fib_rtm_newroute, },
- [9] = { .doit = dn_fib_rtm_delroute, },
- [10] = { .doit = dn_cache_getroute, .dumpit = dn_fib_dump, },
- [16] = { .doit = dn_fib_rtm_newrule, },
- [17] = { .doit = dn_fib_rtm_delrule, },
- [18] = { .dumpit = dn_fib_dump_rules, },
+ [RTM_NEWROUTE - RTM_BASE] = { .doit = dn_fib_rtm_newroute, },
+ [RTM_DELROUTE - RTM_BASE] = { .doit = dn_fib_rtm_delroute, },
+ [RTM_GETROUTE - RTM_BASE] = { .doit = dn_cache_getroute,
+ .dumpit = dn_fib_dump, },
+ [RTM_GETRULE - RTM_BASE] = { .dumpit = dn_fib_dump_rules, },
#else
- [10] = { .doit = dn_cache_getroute, .dumpit = dn_cache_dump, },
+ [RTM_GETROUTE - RTM_BASE] = { .doit = dn_cache_getroute,
+ .dumpit = dn_cache_dump, },
#endif
};
static int __initdata addr[2];
-static int __initdata num;
-module_param_array(addr, int, num, 0444);
+module_param_array(addr, int, NULL, 0444);
MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
void __init dn_dev_init(void)
decnet_address = dn_htons((addr[0] << 10) | addr[1]);
dn_dev_devices_on();
-#ifdef CONFIG_DECNET_SIOCGIFCONF
- register_gifconf(PF_DECnet, dnet_gifconf);
-#endif /* CONFIG_DECNET_SIOCGIFCONF */
rtnetlink_links[PF_DECnet] = dnet_rtnetlink_table;
{
rtnetlink_links[PF_DECnet] = NULL;
-#ifdef CONFIG_DECNET_SIOCGIFCONF
- unregister_gifconf(PF_DECnet);
-#endif /* CONFIG_DECNET_SIOCGIFCONF */
-
#ifdef CONFIG_SYSCTL
{
int i;