patch-2.2.17 linux/net/appletalk/ddp.c
Next file: linux/net/bridge/br.c
Previous file: linux/net/appletalk/aarp.c
Back to the patch index
Back to the overall index
- Lines: 388
- Date:
Mon Sep 4 18:39:28 2000
- Orig file:
v2.2.16/net/appletalk/ddp.c
- Orig date:
Mon Sep 4 18:37:22 2000
diff -u --recursive --new-file v2.2.16/net/appletalk/ddp.c linux/net/appletalk/ddp.c
@@ -37,6 +37,8 @@
* port assignment. we lose a
* valid localtalk port as a
* result.
+ * Arnaldo Melo : fix minor skb handling bug
+ * in atalk_rcv
*
*
* This program is free software; you can redistribute it and/or
@@ -129,18 +131,23 @@
extern inline void atalk_remove_socket(struct sock *sk)
{
+ SOCKHASH_LOCK();
sklist_remove_socket(&atalk_socket_list,sk);
+ SOCKHASH_UNLOCK();
}
extern inline void atalk_insert_socket(struct sock *sk)
{
+ SOCKHASH_LOCK();
sklist_insert_socket(&atalk_socket_list,sk);
+ SOCKHASH_UNLOCK();
}
static struct sock *atalk_search_socket(struct sockaddr_at *to, struct atalk_iface *atif)
{
struct sock *s;
+ SOCKHASH_LOCK();
for(s = atalk_socket_list; s != NULL; s = s->next)
{
if(to->sat_port != s->protinfo.af_at.src_port)
@@ -172,6 +179,7 @@
break;
}
}
+ SOCKHASH_UNLOCK();
return (s);
}
@@ -183,6 +191,8 @@
{
struct sock *s;
+ SOCKHASH_LOCK();
+
for(s = atalk_socket_list; s != NULL; s = s->next)
{
if(s->protinfo.af_at.src_net != sat->sat_addr.s_net)
@@ -203,12 +213,15 @@
break;
}
+ SOCKHASH_UNLOCK();
return (s);
}
extern inline void atalk_destroy_socket(struct sock *sk)
{
+ SOCKHASH_LOCK();
sklist_destroy_socket(&atalk_socket_list, sk);
+ SOCKHASH_UNLOCK();
MOD_DEC_USE_COUNT;
}
@@ -227,6 +240,7 @@
*/
len += sprintf(buffer,"Type local_addr remote_addr tx_queue rx_queue st uid\n");
+ SOCKHASH_LOCK();
for(s = atalk_socket_list; s != NULL; s = s->next)
{
len += sprintf(buffer+len,"%02X ", s->type);
@@ -256,6 +270,8 @@
break;
}
+ SOCKHASH_UNLOCK();
+
/* The data in question runs from begin to begin+len */
*start = buffer + (offset - begin); /* Start of wanted data */
len -= (offset - begin); /* Remove unwanted header data from length */
@@ -288,6 +304,7 @@
struct atalk_iface **iface = &atalk_iface_list;
struct atalk_iface *tmp;
+ SOCKHASH_LOCK();
while((tmp = *iface) != NULL)
{
if(tmp->dev == dev)
@@ -300,14 +317,13 @@
else
iface = &tmp->next;
}
-
+ SOCKHASH_UNLOCK();
}
static struct atalk_iface *atif_add_device(struct device *dev, struct at_addr *sa)
{
struct atalk_iface *iface = (struct atalk_iface *)
kmalloc(sizeof(*iface), GFP_KERNEL);
- unsigned long flags;
if(iface==NULL)
return (NULL);
@@ -316,11 +332,11 @@
dev->atalk_ptr=iface;
iface->address= *sa;
iface->status=0;
- save_flags(flags);
- cli();
+
+ SOCKHASH_LOCK();
iface->next=atalk_iface_list;
atalk_iface_list=iface;
- restore_flags(flags);
+ SOCKHASH_UNLOCK();
MOD_INC_USE_COUNT;
@@ -487,20 +503,29 @@
* Return a point-to-point interface only if
* there is no non-ptp interface available.
*/
+ SOCKHASH_LOCK();
for(iface=atalk_iface_list; iface != NULL; iface=iface->next)
{
if(!fiface && !(iface->dev->flags & IFF_LOOPBACK))
fiface=iface;
- if(!(iface->dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)))
+ if(!(iface->dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) {
+ SOCKHASH_UNLOCK();
return (&iface->address);
+ }
}
- if(fiface)
+ if(fiface) {
+ SOCKHASH_UNLOCK();
return (&fiface->address);
- if(atalk_iface_list != NULL)
+ }
+ if(atalk_iface_list != NULL) {
+ SOCKHASH_UNLOCK();
return (&atalk_iface_list->address);
- else
+ }
+ else {
+ SOCKHASH_UNLOCK();
return (NULL);
+ }
}
/*
@@ -527,21 +552,27 @@
{
struct atalk_iface *iface;
+ SOCKHASH_LOCK();
for(iface=atalk_iface_list; iface != NULL; iface=iface->next)
{
if((node==ATADDR_BCAST || node==ATADDR_ANYNODE
|| iface->address.s_node==node)
&& iface->address.s_net==net
- && !(iface->status & ATIF_PROBE))
+ && !(iface->status & ATIF_PROBE)) {
+ SOCKHASH_UNLOCK();
return (iface);
+ }
/* XXXX.0 -- net.0 returns the iface associated with net */
if ((node==ATADDR_ANYNODE) && (net != ATADDR_ANYNET) &&
(ntohs(iface->nets.nr_firstnet) <= ntohs(net)) &&
- (ntohs(net) <= ntohs(iface->nets.nr_lastnet)))
+ (ntohs(net) <= ntohs(iface->nets.nr_lastnet))) {
+ SOCKHASH_UNLOCK();
return (iface);
+ }
}
+ SOCKHASH_UNLOCK();
return (NULL);
}
@@ -561,6 +592,7 @@
struct atalk_route *r;
struct atalk_route *net_route = NULL;
+ SOCKHASH_LOCK();
for(r=atalk_router_list; r != NULL; r=r->next)
{
if(!(r->flags & RTF_UP))
@@ -573,8 +605,10 @@
* if this host route is for the target,
* the we're done
*/
- if (r->target.s_node == target->s_node)
+ if (r->target.s_node == target->s_node) {
+ SOCKHASH_UNLOCK();
return (r);
+ }
}
else
{
@@ -591,12 +625,17 @@
* if we found a network route but not a direct host
* route, then return it
*/
- if (net_route != NULL)
+ if (net_route != NULL) {
+ SOCKHASH_UNLOCK();
return (net_route);
+ }
- if(atrtr_default.dev)
+ if(atrtr_default.dev) {
+ SOCKHASH_UNLOCK();
return (&atrtr_default);
+ }
+ SOCKHASH_UNLOCK();
return (NULL);
}
@@ -637,9 +676,6 @@
struct sockaddr_at *ga=(struct sockaddr_at *)&r->rt_gateway;
struct atalk_route *rt;
struct atalk_iface *iface, *riface;
- unsigned long flags;
-
- save_flags(flags);
/*
* Fixme: Raise/Lower a routing change semaphore for these
@@ -657,6 +693,7 @@
/*
* Now walk the routing table and make our decisions.
*/
+ SOCKHASH_LOCK();
for(rt=atalk_router_list; rt!=NULL; rt=rt->next)
{
if(r->rt_flags != rt->flags)
@@ -685,17 +722,21 @@
riface = iface;
}
- if(riface == NULL)
+ if(riface == NULL) {
+ SOCKHASH_UNLOCK();
return (-ENETUNREACH);
+ }
devhint = riface->dev;
}
if(rt == NULL)
{
- rt = (struct atalk_route *)kmalloc(sizeof(struct atalk_route), GFP_KERNEL);
- if(rt == NULL)
+ rt = (struct atalk_route *)kmalloc(sizeof(struct atalk_route), GFP_ATOMIC);
+ if(rt == NULL) {
+ SOCKHASH_UNLOCK();
return (-ENOBUFS);
- cli();
+ }
+
rt->next = atalk_router_list;
atalk_router_list = rt;
}
@@ -708,8 +749,7 @@
rt->flags = r->rt_flags;
rt->gateway = ga->sat_addr;
- restore_flags(flags);
-
+ SOCKHASH_UNLOCK();
return (0);
}
@@ -720,7 +760,8 @@
{
struct atalk_route **r = &atalk_router_list;
struct atalk_route *tmp;
-
+
+ SOCKHASH_LOCK();
while((tmp = *r) != NULL)
{
if(tmp->target.s_net == addr->s_net
@@ -729,11 +770,13 @@
{
*r = tmp->next;
kfree_s(tmp, sizeof(struct atalk_route));
+ SOCKHASH_UNLOCK();
return (0);
}
r = &tmp->next;
}
-
+
+ SOCKHASH_UNLOCK();
return (-ENOENT);
}
@@ -746,6 +789,7 @@
struct atalk_route **r = &atalk_router_list;
struct atalk_route *tmp;
+ SOCKHASH_LOCK();
while((tmp = *r) != NULL)
{
if(tmp->dev == dev)
@@ -756,6 +800,7 @@
else
r = &tmp->next;
}
+ SOCKHASH_UNLOCK();
if(atrtr_default.dev == dev)
atrtr_set_default(NULL);
@@ -1061,6 +1106,7 @@
off_t begin=0;
len += sprintf(buffer,"Interface Address Networks Status\n");
+ SOCKHASH_LOCK();
for(iface = atalk_iface_list; iface != NULL; iface = iface->next)
{
len += sprintf(buffer+len,"%-16s %04X:%02X %04X-%04X %d\n",
@@ -1076,6 +1122,8 @@
if(pos > offset + length)
break;
}
+ SOCKHASH_UNLOCK();
+
*start = buffer + (offset - begin);
len -= (offset - begin);
if(len > length)
@@ -1102,6 +1150,7 @@
rt->dev->name);
}
+ SOCKHASH_LOCK();
for(rt = atalk_router_list; rt != NULL; rt = rt->next)
{
len += sprintf(buffer+len,"%04X:%02X %04X:%02X %-4d %s\n",
@@ -1117,6 +1166,7 @@
if(pos > offset + length)
break;
}
+ SOCKHASH_UNLOCK();
*start = buffer + (offset - begin);
len -= (offset - begin);
@@ -1238,12 +1288,16 @@
*/
static int atalk_pick_port(struct sockaddr_at *sat)
{
+ SOCKHASH_LOCK();
for(sat->sat_port = ATPORT_RESERVED; sat->sat_port < ATPORT_LAST; sat->sat_port++)
{
if(atalk_find_socket(sat) == NULL)
+ {
+ SOCKHASH_UNLOCK();
return sat->sat_port;
+ }
}
-
+ SOCKHASH_UNLOCK();
return (-EBUSY);
}
@@ -1583,8 +1637,14 @@
* Note. ddp-> becomes invalid at the realloc.
*/
if(skb_headroom(skb) < 22)
+ {
/* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */
- skb = skb_realloc_headroom(skb, 32);
+ struct sk_buff *nskb = skb_realloc_headroom(skb, 32);
+ kfree_skb(skb);
+ if (!nskb)
+ return 0;
+ skb=nskb;
+ }
else
skb = skb_unshare(skb, GFP_ATOMIC);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)