Commit 18c01243 authored by David S. Miller's avatar David S. Miller

Merge bk://kernel.bkbits.net/acme/ipx-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 7f1648a6 975dc0dc
...@@ -5,8 +5,7 @@ ...@@ -5,8 +5,7 @@
#define IPX_NODE_LEN 6 #define IPX_NODE_LEN 6
#define IPX_MTU 576 #define IPX_MTU 576
struct sockaddr_ipx struct sockaddr_ipx {
{
sa_family_t sipx_family; sa_family_t sipx_family;
__u16 sipx_port; __u16 sipx_port;
__u32 sipx_network; __u32 sipx_network;
...@@ -18,7 +17,6 @@ struct sockaddr_ipx ...@@ -18,7 +17,6 @@ struct sockaddr_ipx
/* /*
* So we can fit the extra info for SIOCSIFADDR into the address nicely * So we can fit the extra info for SIOCSIFADDR into the address nicely
*/ */
#define sipx_special sipx_port #define sipx_special sipx_port
#define sipx_action sipx_zero #define sipx_action sipx_zero
#define IPX_DLTITF 0 #define IPX_DLTITF 0
...@@ -56,8 +54,7 @@ struct ipx_config_data { ...@@ -56,8 +54,7 @@ struct ipx_config_data {
* OLD Route Definition for backward compatibility. * OLD Route Definition for backward compatibility.
*/ */
struct ipx_route_def struct ipx_route_def {
{
__u32 ipx_network; __u32 ipx_network;
__u32 ipx_router_network; __u32 ipx_router_network;
#define IPX_ROUTE_NO_ROUTER 0 #define IPX_ROUTE_NO_ROUTER 0
...@@ -71,7 +68,7 @@ struct ipx_route_def ...@@ -71,7 +68,7 @@ struct ipx_route_def
}; };
#define SIOCAIPXITFCRT (SIOCPROTOPRIVATE) #define SIOCAIPXITFCRT (SIOCPROTOPRIVATE)
#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE+1) #define SIOCAIPXPRISLT (SIOCPROTOPRIVATE + 1)
#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE+2) #define SIOCIPXCFGDATA (SIOCPROTOPRIVATE + 2)
#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE+3) #define SIOCIPXNCPCONN (SIOCPROTOPRIVATE + 3)
#endif /* def _IPX_H_ */ #endif /* _IPX_H_ */
...@@ -296,6 +296,19 @@ static inline void list_splice_init(struct list_head *list, ...@@ -296,6 +296,19 @@ static inline void list_splice_init(struct list_head *list,
pos = list_entry(pos->member.next, typeof(*pos), member), \ pos = list_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next)) prefetch(pos->member.next))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/** /**
* list_for_each_rcu - iterate over an rcu-protected list * list_for_each_rcu - iterate over an rcu-protected list
* @pos: the &struct list_head to use as a loop counter. * @pos: the &struct list_head to use as a loop counter.
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <net/datalink.h> #include <net/datalink.h>
#include <linux/ipx.h> #include <linux/ipx.h>
#include <linux/list.h>
struct ipx_address { struct ipx_address {
__u32 net; __u32 net;
...@@ -66,7 +67,7 @@ struct ipx_interface { ...@@ -66,7 +67,7 @@ struct ipx_interface {
unsigned char if_internal; unsigned char if_internal;
unsigned char if_primary; unsigned char if_primary;
struct ipx_interface *if_next; struct list_head node; /* node in ipx_interfaces list */
}; };
struct ipx_route { struct ipx_route {
...@@ -74,7 +75,7 @@ struct ipx_route { ...@@ -74,7 +75,7 @@ struct ipx_route {
struct ipx_interface *ir_intrfc; struct ipx_interface *ir_intrfc;
unsigned char ir_routed; unsigned char ir_routed;
unsigned char ir_router_node[IPX_NODE_LEN]; unsigned char ir_router_node[IPX_NODE_LEN];
struct ipx_route *ir_next; struct list_head node; /* node in ipx_routes list */
atomic_t refcnt; atomic_t refcnt;
}; };
...@@ -97,8 +98,10 @@ struct ipx_opt { ...@@ -97,8 +98,10 @@ struct ipx_opt {
unsigned char node[IPX_NODE_LEN]; unsigned char node[IPX_NODE_LEN];
#endif #endif
unsigned short type; unsigned short type;
/* To handle special ncp connection-handling sockets for mars_nwe, /*
* the connection number must be stored in the socket. */ * To handle special ncp connection-handling sockets for mars_nwe,
* the connection number must be stored in the socket.
*/
unsigned short ipx_ncp_conn; unsigned short ipx_ncp_conn;
}; };
...@@ -108,10 +111,11 @@ struct ipx_opt { ...@@ -108,10 +111,11 @@ struct ipx_opt {
#define IPX_MIN_EPHEMERAL_SOCKET 0x4000 #define IPX_MIN_EPHEMERAL_SOCKET 0x4000
#define IPX_MAX_EPHEMERAL_SOCKET 0x7fff #define IPX_MAX_EPHEMERAL_SOCKET 0x7fff
extern struct ipx_route *ipx_routes; extern struct list_head ipx_routes;
extern rwlock_t ipx_routes_lock; extern rwlock_t ipx_routes_lock;
extern struct ipx_interface *ipx_interfaces; extern struct list_head ipx_interfaces;
extern struct ipx_interface *ipx_interfaces_head(void);
extern spinlock_t ipx_interfaces_lock; extern spinlock_t ipx_interfaces_lock;
extern struct ipx_interface *ipx_primary_net; extern struct ipx_interface *ipx_primary_net;
...@@ -121,4 +125,4 @@ extern void ipx_proc_exit(void); ...@@ -121,4 +125,4 @@ extern void ipx_proc_exit(void);
extern const char *ipx_frame_name(unsigned short); extern const char *ipx_frame_name(unsigned short);
extern const char *ipx_device_name(struct ipx_interface *intrfc); extern const char *ipx_device_name(struct ipx_interface *intrfc);
#endif /* def _NET_INET_IPX_H_ */ #endif /* _NET_INET_IPX_H_ */
...@@ -81,10 +81,10 @@ static struct datalink_proto *pSNAP_datalink; ...@@ -81,10 +81,10 @@ static struct datalink_proto *pSNAP_datalink;
static struct proto_ops ipx_dgram_ops; static struct proto_ops ipx_dgram_ops;
struct ipx_route *ipx_routes; LIST_HEAD(ipx_routes);
rwlock_t ipx_routes_lock = RW_LOCK_UNLOCKED; rwlock_t ipx_routes_lock = RW_LOCK_UNLOCKED;
struct ipx_interface *ipx_interfaces; LIST_HEAD(ipx_interfaces);
spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED; spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED;
struct ipx_interface *ipx_primary_net; struct ipx_interface *ipx_primary_net;
...@@ -95,11 +95,21 @@ static struct ipx_interface *ipx_internal_net; ...@@ -95,11 +95,21 @@ static struct ipx_interface *ipx_internal_net;
atomic_t ipx_sock_nr; atomic_t ipx_sock_nr;
#endif #endif
struct ipx_interface *ipx_interfaces_head(void)
{
struct ipx_interface *rc = NULL;
if (!list_empty(&ipx_interfaces))
rc = list_entry(ipx_interfaces.next,
struct ipx_interface, node);
return rc;
}
static void ipxcfg_set_auto_select(char val) static void ipxcfg_set_auto_select(char val)
{ {
ipxcfg_auto_select_primary = val; ipxcfg_auto_select_primary = val;
if (val && !ipx_primary_net) if (val && !ipx_primary_net)
ipx_primary_net = ipx_interfaces; ipx_primary_net = ipx_interfaces_head();
} }
static int ipxcfg_get_config_data(struct ipx_config_data *arg) static int ipxcfg_get_config_data(struct ipx_config_data *arg)
...@@ -197,17 +207,21 @@ static struct ipx_route *ipxrtr_lookup(__u32 net); ...@@ -197,17 +207,21 @@ static struct ipx_route *ipxrtr_lookup(__u32 net);
static void ipxitf_clear_primary_net(void) static void ipxitf_clear_primary_net(void)
{ {
ipx_primary_net = ipxcfg_auto_select_primary ? ipx_interfaces : NULL; ipx_primary_net = NULL;
if (ipxcfg_auto_select_primary)
ipx_primary_net = ipx_interfaces_head();
} }
static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev, static struct ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
unsigned short datalink) unsigned short datalink)
{ {
struct ipx_interface *i = ipx_interfaces; struct ipx_interface *i;
while (i && (i->if_dev != dev || i->if_dlink_type != datalink))
i = i->if_next;
list_for_each_entry(i, &ipx_interfaces, node)
if (i->if_dev == dev && i->if_dlink_type == datalink)
goto out;
i = NULL;
out:
return i; return i;
} }
...@@ -229,16 +243,20 @@ static struct ipx_interface *ipxitf_find_using_net(__u32 net) ...@@ -229,16 +243,20 @@ static struct ipx_interface *ipxitf_find_using_net(__u32 net)
struct ipx_interface *i; struct ipx_interface *i;
spin_lock_bh(&ipx_interfaces_lock); spin_lock_bh(&ipx_interfaces_lock);
if (net) if (net) {
for (i = ipx_interfaces; i && i->if_netnum != net; list_for_each_entry(i, &ipx_interfaces, node)
i = i->if_next) if (i->if_netnum == net)
; goto hold;
else i = NULL;
goto unlock;
}
i = ipx_primary_net; i = ipx_primary_net;
if (i) if (i)
hold:
ipxitf_hold(i); ipxitf_hold(i);
unlock:
spin_unlock_bh(&ipx_interfaces_lock); spin_unlock_bh(&ipx_interfaces_lock);
return i; return i;
} }
...@@ -342,15 +360,7 @@ static void __ipxitf_down(struct ipx_interface *intrfc) ...@@ -342,15 +360,7 @@ static void __ipxitf_down(struct ipx_interface *intrfc)
spin_unlock_bh(&intrfc->if_sklist_lock); spin_unlock_bh(&intrfc->if_sklist_lock);
/* remove this interface from list */ /* remove this interface from list */
if (intrfc == ipx_interfaces) list_del(&intrfc->node);
ipx_interfaces = intrfc->if_next;
else {
struct ipx_interface *i = ipx_interfaces;
while (i && i->if_next != intrfc)
i = i->if_next;
if (i && i->if_next == intrfc)
i->if_next = intrfc->if_next;
}
/* remove this interface from *special* networks */ /* remove this interface from *special* networks */
if (intrfc == ipx_primary_net) if (intrfc == ipx_primary_net)
...@@ -380,16 +390,13 @@ static int ipxitf_device_event(struct notifier_block *notifier, ...@@ -380,16 +390,13 @@ static int ipxitf_device_event(struct notifier_block *notifier,
goto out; goto out;
spin_lock_bh(&ipx_interfaces_lock); spin_lock_bh(&ipx_interfaces_lock);
for (i = ipx_interfaces; i;) { list_for_each_entry_safe(i, tmp, &ipx_interfaces, node)
tmp = i->if_next;
if (i->if_dev == dev) { if (i->if_dev == dev) {
if (event == NETDEV_UP) if (event == NETDEV_UP)
ipxitf_hold(i); ipxitf_hold(i);
else else
__ipxitf_put(i); __ipxitf_put(i);
} }
i = tmp;
}
spin_unlock_bh(&ipx_interfaces_lock); spin_unlock_bh(&ipx_interfaces_lock);
out: out:
return NOTIFY_DONE; return NOTIFY_DONE;
...@@ -872,7 +879,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) ...@@ -872,7 +879,7 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum; IPX_SKB_CB(skb)->last_hop.netnum = intrfc->if_netnum;
/* xmit on all other interfaces... */ /* xmit on all other interfaces... */
spin_lock_bh(&ipx_interfaces_lock); spin_lock_bh(&ipx_interfaces_lock);
for (ifcs = ipx_interfaces; ifcs; ifcs = ifcs->if_next) { list_for_each_entry(ifcs, &ipx_interfaces, node) {
/* Except unconfigured interfaces */ /* Except unconfigured interfaces */
if (!ifcs->if_netnum) if (!ifcs->if_netnum)
continue; continue;
...@@ -902,16 +909,8 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb) ...@@ -902,16 +909,8 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
static void ipxitf_insert(struct ipx_interface *intrfc) static void ipxitf_insert(struct ipx_interface *intrfc)
{ {
intrfc->if_next = NULL;
spin_lock_bh(&ipx_interfaces_lock); spin_lock_bh(&ipx_interfaces_lock);
if (!ipx_interfaces) list_add_tail(&intrfc->node, &ipx_interfaces);
ipx_interfaces = intrfc;
else {
struct ipx_interface *i = ipx_interfaces;
while (i->if_next)
i = i->if_next;
i->if_next = intrfc;
}
spin_unlock_bh(&ipx_interfaces_lock); spin_unlock_bh(&ipx_interfaces_lock);
if (ipxcfg_auto_select_primary && !ipx_primary_net) if (ipxcfg_auto_select_primary && !ipx_primary_net)
...@@ -1278,12 +1277,14 @@ static struct ipx_route *ipxrtr_lookup(__u32 net) ...@@ -1278,12 +1277,14 @@ static struct ipx_route *ipxrtr_lookup(__u32 net)
struct ipx_route *r; struct ipx_route *r;
read_lock_bh(&ipx_routes_lock); read_lock_bh(&ipx_routes_lock);
for (r = ipx_routes; r && r->ir_net != net; r = r->ir_next) list_for_each_entry(r, &ipx_routes, node)
; if (r->ir_net == net) {
if (r)
ipxrtr_hold(r); ipxrtr_hold(r);
goto unlock;
}
r = NULL;
unlock:
read_unlock_bh(&ipx_routes_lock); read_unlock_bh(&ipx_routes_lock);
return r; return r;
} }
...@@ -1306,8 +1307,7 @@ static int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc, ...@@ -1306,8 +1307,7 @@ static int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc,
atomic_set(&rt->refcnt, 1); atomic_set(&rt->refcnt, 1);
ipxrtr_hold(rt); ipxrtr_hold(rt);
write_lock_bh(&ipx_routes_lock); write_lock_bh(&ipx_routes_lock);
rt->ir_next = ipx_routes; list_add(&rt->node, &ipx_routes);
ipx_routes = rt;
write_unlock_bh(&ipx_routes_lock); write_unlock_bh(&ipx_routes_lock);
} else { } else {
rc = -EEXIST; rc = -EEXIST;
...@@ -1334,15 +1334,13 @@ static int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc, ...@@ -1334,15 +1334,13 @@ static int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc,
static void ipxrtr_del_routes(struct ipx_interface *intrfc) static void ipxrtr_del_routes(struct ipx_interface *intrfc)
{ {
struct ipx_route **r, *tmp; struct ipx_route *r, *tmp;
write_lock_bh(&ipx_routes_lock); write_lock_bh(&ipx_routes_lock);
for (r = &ipx_routes; (tmp = *r) != NULL;) { list_for_each_entry_safe(r, tmp, &ipx_routes, node)
if (tmp->ir_intrfc == intrfc) { if (r->ir_intrfc == intrfc) {
*r = tmp->ir_next; list_del(&r->node);
ipxrtr_put(tmp); ipxrtr_put(r);
} else
r = &(tmp->ir_next);
} }
write_unlock_bh(&ipx_routes_lock); write_unlock_bh(&ipx_routes_lock);
} }
...@@ -1364,26 +1362,21 @@ static int ipxrtr_create(struct ipx_route_definition *rd) ...@@ -1364,26 +1362,21 @@ static int ipxrtr_create(struct ipx_route_definition *rd)
static int ipxrtr_delete(long net) static int ipxrtr_delete(long net)
{ {
struct ipx_route **r; struct ipx_route *r, *tmp;
struct ipx_route *tmp;
int rc; int rc;
write_lock_bh(&ipx_routes_lock); write_lock_bh(&ipx_routes_lock);
for (r = &ipx_routes; (tmp = *r) != NULL;) { list_for_each_entry_safe(r, tmp, &ipx_routes, node)
if (tmp->ir_net == net) { if (r->ir_net == net) {
/* Directly connected; can't lose route */ /* Directly connected; can't lose route */
rc = -EPERM; rc = -EPERM;
if (!tmp->ir_routed) if (!r->ir_routed)
goto out; goto out;
list_del(&r->node);
*r = tmp->ir_next; ipxrtr_put(r);
ipxrtr_put(tmp);
rc = 0; rc = 0;
goto out; goto out;
} }
r = &(tmp->ir_next);
}
rc = -ENOENT; rc = -ENOENT;
out: out:
write_unlock_bh(&ipx_routes_lock); write_unlock_bh(&ipx_routes_lock);
......
...@@ -17,12 +17,23 @@ static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos) ...@@ -17,12 +17,23 @@ static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos)
{ {
struct ipx_interface *i; struct ipx_interface *i;
for (i = ipx_interfaces; pos && i; i = i->if_next) list_for_each_entry(i, &ipx_interfaces, node)
--pos; if (!pos--)
goto out;
i = NULL;
out:
return i; return i;
} }
static struct ipx_interface *ipx_interfaces_next(struct ipx_interface *i)
{
struct ipx_interface *rc = NULL;
if (i->node.next != &ipx_interfaces)
rc = list_entry(i->node.next, struct ipx_interface, node);
return rc;
}
static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos) static void *ipx_seq_interface_start(struct seq_file *seq, loff_t *pos)
{ {
loff_t l = *pos; loff_t l = *pos;
...@@ -36,15 +47,10 @@ static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -36,15 +47,10 @@ static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos)
struct ipx_interface *i; struct ipx_interface *i;
++*pos; ++*pos;
if (v == (void *)1) { if (v == (void *)1)
i = NULL; i = ipx_interfaces_head();
if (ipx_interfaces) else
i = ipx_interfaces; i = ipx_interfaces_next(v);
goto out;
}
i = v;
i = i->if_next;
out:
return i; return i;
} }
...@@ -83,13 +89,33 @@ static int ipx_seq_interface_show(struct seq_file *seq, void *v) ...@@ -83,13 +89,33 @@ static int ipx_seq_interface_show(struct seq_file *seq, void *v)
return 0; return 0;
} }
static struct ipx_route *ipx_routes_head(void)
{
struct ipx_route *rc = NULL;
if (!list_empty(&ipx_routes))
rc = list_entry(ipx_routes.next, struct ipx_route, node);
return rc;
}
static struct ipx_route *ipx_routes_next(struct ipx_route *r)
{
struct ipx_route *rc = NULL;
if (r->node.next != &ipx_routes)
rc = list_entry(r->node.next, struct ipx_route, node);
return rc;
}
static __inline__ struct ipx_route *ipx_get_route_idx(loff_t pos) static __inline__ struct ipx_route *ipx_get_route_idx(loff_t pos)
{ {
struct ipx_route *r; struct ipx_route *r;
for (r = ipx_routes; pos && r; r = r->ir_next) list_for_each_entry(r, &ipx_routes, node)
--pos; if (!pos--)
goto out;
r = NULL;
out:
return r; return r;
} }
...@@ -105,15 +131,10 @@ static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -105,15 +131,10 @@ static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos)
struct ipx_route *r; struct ipx_route *r;
++*pos; ++*pos;
if (v == (void *)1) { if (v == (void *)1)
r = NULL; r = ipx_routes_head();
if (ipx_routes) else
r = ipx_routes; r = ipx_routes_next(v);
goto out;
}
r = v;
r = r->ir_next;
out:
return r; return r;
} }
...@@ -149,7 +170,9 @@ static __inline__ struct sock *ipx_get_socket_idx(loff_t pos) ...@@ -149,7 +170,9 @@ static __inline__ struct sock *ipx_get_socket_idx(loff_t pos)
struct sock *s = NULL; struct sock *s = NULL;
struct ipx_interface *i; struct ipx_interface *i;
for (i = ipx_interfaces; pos && i; i = i->if_next) { list_for_each_entry(i, &ipx_interfaces, node) {
if (!pos)
break;
spin_lock_bh(&i->if_sklist_lock); spin_lock_bh(&i->if_sklist_lock);
for (s = i->if_sklist; pos && s; s = s->next) for (s = i->if_sklist; pos && s; s = s->next)
--pos; --pos;
...@@ -181,11 +204,12 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -181,11 +204,12 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
++*pos; ++*pos;
if (v == (void *)1) { if (v == (void *)1) {
sk = NULL; sk = NULL;
if (!ipx_interfaces) i = ipx_interfaces_head();
if (!i)
goto out; goto out;
sk = ipx_interfaces->if_sklist; sk = i->if_sklist;
if (sk) if (sk)
spin_lock_bh(&ipx_interfaces->if_sklist_lock); spin_lock_bh(&i->if_sklist_lock);
goto out; goto out;
} }
sk = v; sk = v;
...@@ -198,9 +222,9 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -198,9 +222,9 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
spin_unlock_bh(&i->if_sklist_lock); spin_unlock_bh(&i->if_sklist_lock);
sk = NULL; sk = NULL;
for (;;) { for (;;) {
if (!i->if_next) i = ipx_interfaces_next(i);
if (!i)
break; break;
i = i->if_next;
spin_lock_bh(&i->if_sklist_lock); spin_lock_bh(&i->if_sklist_lock);
if (i->if_sklist) { if (i->if_sklist) {
sk = i->if_sklist; sk = i->if_sklist;
......
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