X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fdecnet%2Fdn_dev.c;h=a26ff9f44576fffb0c20dd7725a463c291db989e;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=11b0f0c6d45ce9e5a23d7ca1fc4fdd63436ad4ef;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 11b0f0c6d..a26ff9f44 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c @@ -25,6 +25,7 @@ */ #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -62,11 +64,11 @@ extern struct neigh_table dn_neigh_table; /* * 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); @@ -247,21 +249,6 @@ static struct dn_dev_sysctl_table { }, {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; @@ -314,52 +301,6 @@ static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms) } } -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 __user *buffer, @@ -454,6 +395,21 @@ static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms * #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; @@ -483,14 +439,14 @@ static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr **ifap, int de *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); + blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1); if (destroy) { dn_dev_free_ifa(ifa1); @@ -514,7 +470,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) } 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); @@ -525,7 +481,7 @@ static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa) dn_db->ifa_list = ifa; rtmsg_ifa(RTM_NEWADDR, ifa); - notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); + blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa); return 0; } @@ -605,7 +561,7 @@ int dn_dev_ioctl(unsigned int cmd, void __user *arg) switch(cmd) { case SIOCGIFADDR: - *((dn_address *)sdn->sdn_nodeaddr) = ifa->ifa_local; + *((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local; goto rarok; case SIOCSIFADDR: @@ -635,6 +591,52 @@ rarok: 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; @@ -661,7 +663,7 @@ static int dn_dev_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a 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))) + (rta[IFA_LABEL-1] && rtattr_strcmp(rta[IFA_LABEL-1], ifa->ifa_label))) continue; dn_dev_del_ifa(dn_db, ifap, 1); @@ -704,7 +706,7 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a 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); + rtattr_strlcpy(ifa->ifa_label, rta[IFA_LABEL-1], IFNAMSIZ); else memcpy(ifa->ifa_label, dev->name, IFNAMSIZ); @@ -715,13 +717,13 @@ static int dn_dev_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *a } static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa, - u32 pid, u32 seq, int event) + 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)); + nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags); ifm = NLMSG_DATA(nlh); ifm->ifa_family = AF_DECnet; @@ -751,16 +753,16 @@ static void rtmsg_ifa(int event, struct dn_ifaddr *ifa) skb = alloc_skb(size, GFP_KERNEL); if (!skb) { - netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, ENOBUFS); + netlink_set_err(rtnl, 0, RTNLGRP_DECnet_IFADDR, ENOBUFS); return; } - if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event) < 0) { + if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) { kfree_skb(skb); - netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, EINVAL); + netlink_set_err(rtnl, 0, RTNLGRP_DECnet_IFADDR, EINVAL); return; } - NETLINK_CB(skb).dst_groups = RTMGRP_DECnet_IFADDR; - netlink_broadcast(rtnl, skb, 0, RTMGRP_DECnet_IFADDR, GFP_KERNEL); + NETLINK_CB(skb).dst_group = RTNLGRP_DECnet_IFADDR; + netlink_broadcast(rtnl, skb, 0, RTNLGRP_DECnet_IFADDR, GFP_KERNEL); } static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) @@ -789,7 +791,8 @@ static int dn_dev_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) if (dn_dev_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, - RTM_NEWADDR) <= 0) + RTM_NEWADDR, + NLM_F_MULTI) <= 0) goto done; } } @@ -801,7 +804,7 @@ done: 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; @@ -827,7 +830,7 @@ out: * 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; @@ -850,7 +853,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa) { 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) @@ -879,7 +882,7 @@ static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa) 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; @@ -923,7 +926,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) size_t size; unsigned char *ptr; unsigned char *i1, *i2; - unsigned short *pktlen; + __le16 *pktlen; char *src; if (mtu2blksize(dev) < (26 + 7)) @@ -952,11 +955,11 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) 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++; @@ -971,7 +974,7 @@ static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa) 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; @@ -1013,7 +1016,7 @@ static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa) 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; @@ -1108,6 +1111,7 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err) 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); @@ -1146,7 +1150,7 @@ struct dn_dev *dn_dev_create(struct net_device *dev, int *err) 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; @@ -1169,7 +1173,7 @@ void dn_dev_up(struct net_device *dev) 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; } @@ -1215,6 +1219,7 @@ static void dn_dev_delete(struct net_device *dev) 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); @@ -1280,67 +1285,14 @@ void dn_dev_devices_on(void) 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); + return blocking_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; -} -#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) { @@ -1433,8 +1385,8 @@ static int dn_dev_seq_show(struct seq_file *seq, void *v) 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; } @@ -1461,28 +1413,28 @@ static struct file_operations dn_dev_seq_fops = { #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_dev_rtm_newaddr, }, + [RTM_DELADDR - RTM_BASE] = { .doit = dn_dev_rtm_deladdr, }, + [RTM_GETADDR - RTM_BASE] = { .dumpit = dn_dev_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_NEWRULE - RTM_BASE] = { .doit = dn_fib_rtm_newrule, }, + [RTM_DELRULE - RTM_BASE] = { .doit = dn_fib_rtm_delrule, }, + [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) @@ -1500,9 +1452,6 @@ 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; @@ -1521,10 +1470,6 @@ void __exit dn_dev_cleanup(void) { rtnetlink_links[PF_DECnet] = NULL; -#ifdef CONFIG_DECNET_SIOCGIFCONF - unregister_gifconf(PF_DECnet); -#endif /* CONFIG_DECNET_SIOCGIFCONF */ - #ifdef CONFIG_SYSCTL { int i;