aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/appletalk
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/appletalk')
-rw-r--r--drivers/net/appletalk/ipddp.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index da64ba88d7f8..78cea5e80b1d 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -39,6 +39,7 @@
39static const char version[] = KERN_INFO "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n"; 39static const char version[] = KERN_INFO "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n";
40 40
41static struct ipddp_route *ipddp_route_list; 41static struct ipddp_route *ipddp_route_list;
42static DEFINE_SPINLOCK(ipddp_route_lock);
42 43
43#ifdef CONFIG_IPDDP_ENCAP 44#ifdef CONFIG_IPDDP_ENCAP
44static int ipddp_mode = IPDDP_ENCAP; 45static int ipddp_mode = IPDDP_ENCAP;
@@ -50,7 +51,7 @@ static int ipddp_mode = IPDDP_DECAP;
50static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev); 51static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev);
51static int ipddp_create(struct ipddp_route *new_rt); 52static int ipddp_create(struct ipddp_route *new_rt);
52static int ipddp_delete(struct ipddp_route *rt); 53static int ipddp_delete(struct ipddp_route *rt);
53static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt); 54static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt);
54static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); 55static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
55 56
56static const struct net_device_ops ipddp_netdev_ops = { 57static const struct net_device_ops ipddp_netdev_ops = {
@@ -71,6 +72,7 @@ static struct net_device * __init ipddp_init(void)
71 if (!dev) 72 if (!dev)
72 return ERR_PTR(-ENOMEM); 73 return ERR_PTR(-ENOMEM);
73 74
75 dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
74 strcpy(dev->name, "ipddp%d"); 76 strcpy(dev->name, "ipddp%d");
75 77
76 if (version_printed++ == 0) 78 if (version_printed++ == 0)
@@ -113,11 +115,13 @@ static struct net_device * __init ipddp_init(void)
113 */ 115 */
114static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev) 116static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
115{ 117{
116 __be32 paddr = ((struct rtable*)skb->dst)->rt_gateway; 118 __be32 paddr = skb_rtable(skb)->rt_gateway;
117 struct ddpehdr *ddp; 119 struct ddpehdr *ddp;
118 struct ipddp_route *rt; 120 struct ipddp_route *rt;
119 struct atalk_addr *our_addr; 121 struct atalk_addr *our_addr;
120 122
123 spin_lock(&ipddp_route_lock);
124
121 /* 125 /*
122 * Find appropriate route to use, based only on IP number. 126 * Find appropriate route to use, based only on IP number.
123 */ 127 */
@@ -126,8 +130,10 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
126 if(rt->ip == paddr) 130 if(rt->ip == paddr)
127 break; 131 break;
128 } 132 }
129 if(rt == NULL) 133 if(rt == NULL) {
134 spin_unlock(&ipddp_route_lock);
130 return 0; 135 return 0;
136 }
131 137
132 our_addr = atalk_find_dev_addr(rt->dev); 138 our_addr = atalk_find_dev_addr(rt->dev);
133 139
@@ -173,6 +179,8 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
173 if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0) 179 if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0)
174 dev_kfree_skb(skb); 180 dev_kfree_skb(skb);
175 181
182 spin_unlock(&ipddp_route_lock);
183
176 return 0; 184 return 0;
177} 185}
178 186
@@ -195,7 +203,9 @@ static int ipddp_create(struct ipddp_route *new_rt)
195 return -ENETUNREACH; 203 return -ENETUNREACH;
196 } 204 }
197 205
198 if (ipddp_find_route(rt)) { 206 spin_lock_bh(&ipddp_route_lock);
207 if (__ipddp_find_route(rt)) {
208 spin_unlock_bh(&ipddp_route_lock);
199 kfree(rt); 209 kfree(rt);
200 return -EEXIST; 210 return -EEXIST;
201 } 211 }
@@ -203,6 +213,8 @@ static int ipddp_create(struct ipddp_route *new_rt)
203 rt->next = ipddp_route_list; 213 rt->next = ipddp_route_list;
204 ipddp_route_list = rt; 214 ipddp_route_list = rt;
205 215
216 spin_unlock_bh(&ipddp_route_lock);
217
206 return 0; 218 return 0;
207} 219}
208 220
@@ -215,6 +227,7 @@ static int ipddp_delete(struct ipddp_route *rt)
215 struct ipddp_route **r = &ipddp_route_list; 227 struct ipddp_route **r = &ipddp_route_list;
216 struct ipddp_route *tmp; 228 struct ipddp_route *tmp;
217 229
230 spin_lock_bh(&ipddp_route_lock);
218 while((tmp = *r) != NULL) 231 while((tmp = *r) != NULL)
219 { 232 {
220 if(tmp->ip == rt->ip 233 if(tmp->ip == rt->ip
@@ -222,19 +235,21 @@ static int ipddp_delete(struct ipddp_route *rt)
222 && tmp->at.s_node == rt->at.s_node) 235 && tmp->at.s_node == rt->at.s_node)
223 { 236 {
224 *r = tmp->next; 237 *r = tmp->next;
238 spin_unlock_bh(&ipddp_route_lock);
225 kfree(tmp); 239 kfree(tmp);
226 return 0; 240 return 0;
227 } 241 }
228 r = &tmp->next; 242 r = &tmp->next;
229 } 243 }
230 244
245 spin_unlock_bh(&ipddp_route_lock);
231 return (-ENOENT); 246 return (-ENOENT);
232} 247}
233 248
234/* 249/*
235 * Find a routing entry, we only return a FULL match 250 * Find a routing entry, we only return a FULL match
236 */ 251 */
237static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt) 252static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt)
238{ 253{
239 struct ipddp_route *f; 254 struct ipddp_route *f;
240 255
@@ -252,7 +267,7 @@ static struct ipddp_route* ipddp_find_route(struct ipddp_route *rt)
252static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 267static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
253{ 268{
254 struct ipddp_route __user *rt = ifr->ifr_data; 269 struct ipddp_route __user *rt = ifr->ifr_data;
255 struct ipddp_route rcp; 270 struct ipddp_route rcp, rcp2, *rp;
256 271
257 if(!capable(CAP_NET_ADMIN)) 272 if(!capable(CAP_NET_ADMIN))
258 return -EPERM; 273 return -EPERM;
@@ -266,9 +281,19 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
266 return (ipddp_create(&rcp)); 281 return (ipddp_create(&rcp));
267 282
268 case SIOCFINDIPDDPRT: 283 case SIOCFINDIPDDPRT:
269 if(copy_to_user(rt, ipddp_find_route(&rcp), sizeof(struct ipddp_route))) 284 spin_lock_bh(&ipddp_route_lock);
270 return -EFAULT; 285 rp = __ipddp_find_route(&rcp);
271 return 0; 286 if (rp)
287 memcpy(&rcp2, rp, sizeof(rcp2));
288 spin_unlock_bh(&ipddp_route_lock);
289
290 if (rp) {
291 if (copy_to_user(rt, &rcp2,
292 sizeof(struct ipddp_route)))
293 return -EFAULT;
294 return 0;
295 } else
296 return -ENOENT;
272 297
273 case SIOCDELIPDDPRT: 298 case SIOCDELIPDDPRT:
274 return (ipddp_delete(&rcp)); 299 return (ipddp_delete(&rcp));