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 @@
#define IPX_NODE_LEN 6
#define IPX_MTU 576
struct sockaddr_ipx
{
struct sockaddr_ipx {
sa_family_t sipx_family;
__u16 sipx_port;
__u32 sipx_network;
......@@ -16,9 +15,8 @@ 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_action sipx_zero
#define IPX_DLTITF 0
......@@ -56,14 +54,13 @@ struct ipx_config_data {
* OLD Route Definition for backward compatibility.
*/
struct ipx_route_def
{
__u32 ipx_network;
__u32 ipx_router_network;
struct ipx_route_def {
__u32 ipx_network;
__u32 ipx_router_network;
#define IPX_ROUTE_NO_ROUTER 0
unsigned char ipx_router_node[IPX_NODE_LEN];
unsigned char ipx_device[16];
unsigned short ipx_flags;
unsigned char ipx_router_node[IPX_NODE_LEN];
unsigned char ipx_device[16];
unsigned short ipx_flags;
#define IPX_RT_SNAP 8
#define IPX_RT_8022 4
#define IPX_RT_BLUEBOOK 2
......@@ -71,7 +68,7 @@ struct ipx_route_def
};
#define SIOCAIPXITFCRT (SIOCPROTOPRIVATE)
#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE+1)
#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE+2)
#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE+3)
#endif /* def _IPX_H_ */
#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE + 1)
#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE + 2)
#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE + 3)
#endif /* _IPX_H_ */
......@@ -296,6 +296,19 @@ static inline void list_splice_init(struct list_head *list,
pos = list_entry(pos->member.next, typeof(*pos), member), \
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
* @pos: the &struct list_head to use as a loop counter.
......
......@@ -12,6 +12,7 @@
#include <linux/netdevice.h>
#include <net/datalink.h>
#include <linux/ipx.h>
#include <linux/list.h>
struct ipx_address {
__u32 net;
......@@ -25,11 +26,11 @@ struct ipx_address {
#define IPX_MAX_PPROP_HOPS 8
struct ipxhdr {
__u16 ipx_checksum __attribute__ ((packed));
__u16 ipx_checksum __attribute__ ((packed));
#define IPX_NO_CHECKSUM 0xFFFF
__u16 ipx_pktsize __attribute__ ((packed));
__u8 ipx_tctrl;
__u8 ipx_type;
__u16 ipx_pktsize __attribute__ ((packed));
__u8 ipx_tctrl;
__u8 ipx_type;
#define IPX_TYPE_UNKNOWN 0x00
#define IPX_TYPE_RIP 0x01 /* may also be 0 */
#define IPX_TYPE_SAP 0x04 /* may also be 0 */
......@@ -47,42 +48,42 @@ static __inline__ struct ipxhdr *ipx_hdr(struct sk_buff *skb)
struct ipx_interface {
/* IPX address */
__u32 if_netnum;
unsigned char if_node[IPX_NODE_LEN];
atomic_t refcnt;
__u32 if_netnum;
unsigned char if_node[IPX_NODE_LEN];
atomic_t refcnt;
/* physical device info */
struct net_device *if_dev;
struct datalink_proto *if_dlink;
unsigned short if_dlink_type;
unsigned short if_dlink_type;
/* socket support */
unsigned short if_sknum;
struct sock *if_sklist;
spinlock_t if_sklist_lock;
unsigned short if_sknum;
struct sock *if_sklist;
spinlock_t if_sklist_lock;
/* administrative overhead */
int if_ipx_offset;
unsigned char if_internal;
unsigned char if_primary;
int if_ipx_offset;
unsigned char if_internal;
unsigned char if_primary;
struct ipx_interface *if_next;
struct list_head node; /* node in ipx_interfaces list */
};
struct ipx_route {
__u32 ir_net;
__u32 ir_net;
struct ipx_interface *ir_intrfc;
unsigned char ir_routed;
unsigned char ir_router_node[IPX_NODE_LEN];
struct ipx_route *ir_next;
atomic_t refcnt;
unsigned char ir_routed;
unsigned char ir_router_node[IPX_NODE_LEN];
struct list_head node; /* node in ipx_routes list */
atomic_t refcnt;
};
#ifdef __KERNEL__
struct ipx_cb {
u8 ipx_tctrl;
u32 ipx_dest_net;
u32 ipx_source_net;
u8 ipx_tctrl;
u32 ipx_dest_net;
u32 ipx_source_net;
struct {
u32 netnum;
int index;
......@@ -92,14 +93,16 @@ struct ipx_cb {
struct ipx_opt {
struct ipx_address dest_addr;
struct ipx_interface *intrfc;
unsigned short port;
unsigned short port;
#ifdef CONFIG_IPX_INTERN
unsigned char node[IPX_NODE_LEN];
unsigned char node[IPX_NODE_LEN];
#endif
unsigned short type;
/* 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 type;
/*
* To handle special ncp connection-handling sockets for mars_nwe,
* the connection number must be stored in the socket.
*/
unsigned short ipx_ncp_conn;
};
#define ipx_sk(__sk) ((struct ipx_opt *)(__sk)->protinfo)
......@@ -108,10 +111,11 @@ struct ipx_opt {
#define IPX_MIN_EPHEMERAL_SOCKET 0x4000
#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 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 struct ipx_interface *ipx_primary_net;
......@@ -121,4 +125,4 @@ extern void ipx_proc_exit(void);
extern const char *ipx_frame_name(unsigned short);
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;
static struct proto_ops ipx_dgram_ops;
struct ipx_route *ipx_routes;
LIST_HEAD(ipx_routes);
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;
struct ipx_interface *ipx_primary_net;
......@@ -95,11 +95,21 @@ static struct ipx_interface *ipx_internal_net;
atomic_t ipx_sock_nr;
#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)
{
ipxcfg_auto_select_primary = val;
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)
......@@ -197,17 +207,21 @@ static struct ipx_route *ipxrtr_lookup(__u32 net);
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,
unsigned short datalink)
{
struct ipx_interface *i = ipx_interfaces;
while (i && (i->if_dev != dev || i->if_dlink_type != datalink))
i = i->if_next;
struct ipx_interface *i;
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;
}
......@@ -229,16 +243,20 @@ static struct ipx_interface *ipxitf_find_using_net(__u32 net)
struct ipx_interface *i;
spin_lock_bh(&ipx_interfaces_lock);
if (net)
for (i = ipx_interfaces; i && i->if_netnum != net;
i = i->if_next)
;
else
i = ipx_primary_net;
if (net) {
list_for_each_entry(i, &ipx_interfaces, node)
if (i->if_netnum == net)
goto hold;
i = NULL;
goto unlock;
}
i = ipx_primary_net;
if (i)
hold:
ipxitf_hold(i);
unlock:
spin_unlock_bh(&ipx_interfaces_lock);
return i;
}
......@@ -342,15 +360,7 @@ static void __ipxitf_down(struct ipx_interface *intrfc)
spin_unlock_bh(&intrfc->if_sklist_lock);
/* remove this interface from list */
if (intrfc == ipx_interfaces)
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;
}
list_del(&intrfc->node);
/* remove this interface from *special* networks */
if (intrfc == ipx_primary_net)
......@@ -380,16 +390,13 @@ static int ipxitf_device_event(struct notifier_block *notifier,
goto out;
spin_lock_bh(&ipx_interfaces_lock);
for (i = ipx_interfaces; i;) {
tmp = i->if_next;
list_for_each_entry_safe(i, tmp, &ipx_interfaces, node)
if (i->if_dev == dev) {
if (event == NETDEV_UP)
ipxitf_hold(i);
else
__ipxitf_put(i);
}
i = tmp;
}
spin_unlock_bh(&ipx_interfaces_lock);
out:
return NOTIFY_DONE;
......@@ -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;
/* xmit on all other interfaces... */
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 */
if (!ifcs->if_netnum)
continue;
......@@ -902,16 +909,8 @@ static int ipxitf_pprop(struct ipx_interface *intrfc, struct sk_buff *skb)
static void ipxitf_insert(struct ipx_interface *intrfc)
{
intrfc->if_next = NULL;
spin_lock_bh(&ipx_interfaces_lock);
if (!ipx_interfaces)
ipx_interfaces = intrfc;
else {
struct ipx_interface *i = ipx_interfaces;
while (i->if_next)
i = i->if_next;
i->if_next = intrfc;
}
list_add_tail(&intrfc->node, &ipx_interfaces);
spin_unlock_bh(&ipx_interfaces_lock);
if (ipxcfg_auto_select_primary && !ipx_primary_net)
......@@ -1278,12 +1277,14 @@ static struct ipx_route *ipxrtr_lookup(__u32 net)
struct ipx_route *r;
read_lock_bh(&ipx_routes_lock);
for (r = ipx_routes; r && r->ir_net != net; r = r->ir_next)
;
if (r)
ipxrtr_hold(r);
list_for_each_entry(r, &ipx_routes, node)
if (r->ir_net == net) {
ipxrtr_hold(r);
goto unlock;
}
r = NULL;
unlock:
read_unlock_bh(&ipx_routes_lock);
return r;
}
......@@ -1306,8 +1307,7 @@ static int ipxrtr_add_route(__u32 network, struct ipx_interface *intrfc,
atomic_set(&rt->refcnt, 1);
ipxrtr_hold(rt);
write_lock_bh(&ipx_routes_lock);
rt->ir_next = ipx_routes;
ipx_routes = rt;
list_add(&rt->node, &ipx_routes);
write_unlock_bh(&ipx_routes_lock);
} else {
rc = -EEXIST;
......@@ -1334,16 +1334,14 @@ static int ipxrtr_add_route(__u32 network, 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);
for (r = &ipx_routes; (tmp = *r) != NULL;) {
if (tmp->ir_intrfc == intrfc) {
*r = tmp->ir_next;
ipxrtr_put(tmp);
} else
r = &(tmp->ir_next);
}
list_for_each_entry_safe(r, tmp, &ipx_routes, node)
if (r->ir_intrfc == intrfc) {
list_del(&r->node);
ipxrtr_put(r);
}
write_unlock_bh(&ipx_routes_lock);
}
......@@ -1364,26 +1362,21 @@ static int ipxrtr_create(struct ipx_route_definition *rd)
static int ipxrtr_delete(long net)
{
struct ipx_route **r;
struct ipx_route *tmp;
struct ipx_route *r, *tmp;
int rc;
write_lock_bh(&ipx_routes_lock);
for (r = &ipx_routes; (tmp = *r) != NULL;) {
if (tmp->ir_net == net) {
list_for_each_entry_safe(r, tmp, &ipx_routes, node)
if (r->ir_net == net) {
/* Directly connected; can't lose route */
rc = -EPERM;
if (!tmp->ir_routed)
if (!r->ir_routed)
goto out;
*r = tmp->ir_next;
ipxrtr_put(tmp);
list_del(&r->node);
ipxrtr_put(r);
rc = 0;
goto out;
}
r = &(tmp->ir_next);
}
rc = -ENOENT;
out:
write_unlock_bh(&ipx_routes_lock);
......
......@@ -17,12 +17,23 @@ static __inline__ struct ipx_interface *ipx_get_interface_idx(loff_t pos)
{
struct ipx_interface *i;
for (i = ipx_interfaces; pos && i; i = i->if_next)
--pos;
list_for_each_entry(i, &ipx_interfaces, node)
if (!pos--)
goto out;
i = NULL;
out:
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)
{
loff_t l = *pos;
......@@ -36,15 +47,10 @@ static void *ipx_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos)
struct ipx_interface *i;
++*pos;
if (v == (void *)1) {
i = NULL;
if (ipx_interfaces)
i = ipx_interfaces;
goto out;
}
i = v;
i = i->if_next;
out:
if (v == (void *)1)
i = ipx_interfaces_head();
else
i = ipx_interfaces_next(v);
return i;
}
......@@ -83,13 +89,33 @@ static int ipx_seq_interface_show(struct seq_file *seq, void *v)
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)
{
struct ipx_route *r;
for (r = ipx_routes; pos && r; r = r->ir_next)
--pos;
list_for_each_entry(r, &ipx_routes, node)
if (!pos--)
goto out;
r = NULL;
out:
return r;
}
......@@ -105,15 +131,10 @@ static void *ipx_seq_route_next(struct seq_file *seq, void *v, loff_t *pos)
struct ipx_route *r;
++*pos;
if (v == (void *)1) {
r = NULL;
if (ipx_routes)
r = ipx_routes;
goto out;
}
r = v;
r = r->ir_next;
out:
if (v == (void *)1)
r = ipx_routes_head();
else
r = ipx_routes_next(v);
return r;
}
......@@ -149,7 +170,9 @@ static __inline__ struct sock *ipx_get_socket_idx(loff_t pos)
struct sock *s = NULL;
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);
for (s = i->if_sklist; pos && s; s = s->next)
--pos;
......@@ -181,11 +204,12 @@ static void *ipx_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos)
++*pos;
if (v == (void *)1) {
sk = NULL;
if (!ipx_interfaces)
i = ipx_interfaces_head();
if (!i)
goto out;
sk = ipx_interfaces->if_sklist;
sk = i->if_sklist;
if (sk)
spin_lock_bh(&ipx_interfaces->if_sklist_lock);
spin_lock_bh(&i->if_sklist_lock);
goto out;
}
sk = v;
......@@ -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);
sk = NULL;
for (;;) {
if (!i->if_next)
i = ipx_interfaces_next(i);
if (!i)
break;
i = i->if_next;
spin_lock_bh(&i->if_sklist_lock);
if (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