aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/sit.c
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-03-22 04:42:57 -0400
committerYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-04-02 21:05:59 -0400
commit3fcfa12904e83cc291cf2b7b05ff2530068920a4 (patch)
treeec1230028db764a9a6a169050bdcd2f7a8793e41 /net/ipv6/sit.c
parentfadf6bf06069138f8e97c9a963be38348ba2708b (diff)
[IPV6] SIT: Fix locking issues in PRL management.
To protect PRL list, use ipip6_lock. Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Diffstat (limited to 'net/ipv6/sit.c')
-rw-r--r--net/ipv6/sit.c49
1 files changed, 32 insertions, 17 deletions
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index 4786419ade0e..ee0cc2851691 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -198,7 +198,7 @@ failed:
198} 198}
199 199
200static struct ip_tunnel_prl_entry * 200static struct ip_tunnel_prl_entry *
201ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr) 201__ipip6_tunnel_locate_prl(struct ip_tunnel *t, __be32 addr)
202{ 202{
203 struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *)NULL; 203 struct ip_tunnel_prl_entry *p = (struct ip_tunnel_prl_entry *)NULL;
204 204
@@ -213,34 +213,46 @@ static int
213ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) 213ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg)
214{ 214{
215 struct ip_tunnel_prl_entry *p; 215 struct ip_tunnel_prl_entry *p;
216 int err = 0;
217
218 write_lock(&ipip6_lock);
216 219
217 for (p = t->prl; p; p = p->next) { 220 for (p = t->prl; p; p = p->next) {
218 if (p->entry.addr == a->addr) { 221 if (p->entry.addr == a->addr) {
219 if (chg) { 222 if (chg)
220 p->entry = *a; 223 goto update;
221 return 0; 224 err = -EEXIST;
222 } 225 goto out;
223 return -EEXIST;
224 } 226 }
225 } 227 }
226 228
227 if (chg) 229 if (chg) {
228 return -ENXIO; 230 err = -ENXIO;
231 goto out;
232 }
229 233
230 p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL); 234 p = kzalloc(sizeof(struct ip_tunnel_prl_entry), GFP_KERNEL);
231 if (!p) 235 if (!p) {
232 return -ENOBUFS; 236 err = -ENOBUFS;
237 goto out;
238 }
233 239
234 p->entry = *a;
235 p->next = t->prl; 240 p->next = t->prl;
236 t->prl = p; 241 t->prl = p;
237 return 0; 242update:
243 p->entry = *a;
244out:
245 write_unlock(&ipip6_lock);
246 return err;
238} 247}
239 248
240static int 249static int
241ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a) 250ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
242{ 251{
243 struct ip_tunnel_prl_entry *x, **p; 252 struct ip_tunnel_prl_entry *x, **p;
253 int err = 0;
254
255 write_lock(&ipip6_lock);
244 256
245 if (a) { 257 if (a) {
246 for (p = &t->prl; *p; p = &(*p)->next) { 258 for (p = &t->prl; *p; p = &(*p)->next) {
@@ -248,10 +260,10 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
248 x = *p; 260 x = *p;
249 *p = x->next; 261 *p = x->next;
250 kfree(x); 262 kfree(x);
251 return 0; 263 goto out;
252 } 264 }
253 } 265 }
254 return -ENXIO; 266 err = -ENXIO;
255 } else { 267 } else {
256 while (t->prl) { 268 while (t->prl) {
257 x = t->prl; 269 x = t->prl;
@@ -259,6 +271,8 @@ ipip6_tunnel_del_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a)
259 kfree(x); 271 kfree(x);
260 } 272 }
261 } 273 }
274out:
275 write_unlock(&ipip6_lock);
262 return 0; 276 return 0;
263} 277}
264 278
@@ -290,9 +304,11 @@ ipip6_onlink(struct in6_addr *addr, struct net_device *dev)
290static int 304static int
291isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) 305isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t)
292{ 306{
293 struct ip_tunnel_prl_entry *p = ipip6_tunnel_locate_prl(t, iph->saddr); 307 struct ip_tunnel_prl_entry *p;
294 int ok = 1; 308 int ok = 1;
295 309
310 read_lock(&ipip6_lock);
311 p = __ipip6_tunnel_locate_prl(t, iph->saddr);
296 if (p) { 312 if (p) {
297 if (p->entry.flags & PRL_DEFAULT) 313 if (p->entry.flags & PRL_DEFAULT)
298 skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT; 314 skb->ndisc_nodetype = NDISC_NODETYPE_DEFAULT;
@@ -307,6 +323,7 @@ isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t)
307 else 323 else
308 ok = 0; 324 ok = 0;
309 } 325 }
326 read_unlock(&ipip6_lock);
310 return ok; 327 return ok;
311} 328}
312 329
@@ -895,12 +912,10 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
895 if (!(t = netdev_priv(dev))) 912 if (!(t = netdev_priv(dev)))
896 goto done; 913 goto done;
897 914
898 ipip6_tunnel_unlink(t);
899 if (cmd == SIOCDELPRL) 915 if (cmd == SIOCDELPRL)
900 err = ipip6_tunnel_del_prl(t, &prl); 916 err = ipip6_tunnel_del_prl(t, &prl);
901 else 917 else
902 err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL); 918 err = ipip6_tunnel_add_prl(t, &prl, cmd == SIOCCHGPRL);
903 ipip6_tunnel_link(t);
904 netdev_state_change(dev); 919 netdev_state_change(dev);
905 break; 920 break;
906 921