Blame view
net/ipv6/anycast.c
11.5 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 |
/* * Anycast support for IPv6 |
1ab1457c4 [NET] IPV6: Fix w... |
3 |
* Linux INET6 implementation |
1da177e4c Linux-2.6.12-rc2 |
4 5 6 7 8 9 10 11 12 13 14 |
* * Authors: * David L Stevens (dlstevens@us.ibm.com) * * based heavily on net/ipv6/mcast.c * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ |
4fc268d24 [PATCH] capable/c... |
15 |
#include <linux/capability.h> |
1da177e4c Linux-2.6.12-rc2 |
16 17 18 19 20 21 22 |
#include <linux/module.h> #include <linux/errno.h> #include <linux/types.h> #include <linux/random.h> #include <linux/string.h> #include <linux/socket.h> #include <linux/sockios.h> |
1da177e4c Linux-2.6.12-rc2 |
23 24 25 26 27 28 29 30 |
#include <linux/net.h> #include <linux/in6.h> #include <linux/netdevice.h> #include <linux/if_arp.h> #include <linux/route.h> #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> |
5a0e3ad6a include cleanup: ... |
31 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
32 |
|
457c4cbc5 [NET]: Make /proc... |
33 |
#include <net/net_namespace.h> |
1da177e4c Linux-2.6.12-rc2 |
34 35 36 37 38 39 40 41 42 43 44 |
#include <net/sock.h> #include <net/snmp.h> #include <net/ipv6.h> #include <net/protocol.h> #include <net/if_inet6.h> #include <net/ndisc.h> #include <net/addrconf.h> #include <net/ip6_route.h> #include <net/checksum.h> |
b71d1d426 inet: constify ip... |
45 |
static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr); |
1da177e4c Linux-2.6.12-rc2 |
46 47 48 |
/* Big ac list lock for all the sockets */ static DEFINE_RWLOCK(ipv6_sk_ac_lock); |
1da177e4c Linux-2.6.12-rc2 |
49 50 51 52 |
/* * socket join an anycast group */ |
b71d1d426 inet: constify ip... |
53 |
int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) |
1da177e4c Linux-2.6.12-rc2 |
54 55 56 57 58 |
{ struct ipv6_pinfo *np = inet6_sk(sk); struct net_device *dev = NULL; struct inet6_dev *idev; struct ipv6_ac_socklist *pac; |
6ab57e7e7 [NETNS][IPV6] any... |
59 |
struct net *net = sock_net(sk); |
53b7997fd ipv6 netns: Make ... |
60 |
int ishost = !net->ipv6.devconf_all->forwarding; |
1da177e4c Linux-2.6.12-rc2 |
61 62 63 64 65 66 |
int err = 0; if (!capable(CAP_NET_ADMIN)) return -EPERM; if (ipv6_addr_is_multicast(addr)) return -EINVAL; |
6ab57e7e7 [NETNS][IPV6] any... |
67 |
if (ipv6_chk_addr(net, addr, NULL, 0)) |
1da177e4c Linux-2.6.12-rc2 |
68 69 70 71 72 73 |
return -EINVAL; pac = sock_kmalloc(sk, sizeof(struct ipv6_ac_socklist), GFP_KERNEL); if (pac == NULL) return -ENOMEM; pac->acl_next = NULL; |
4e3fd7a06 net: remove ipv6_... |
74 |
pac->acl_addr = *addr; |
1da177e4c Linux-2.6.12-rc2 |
75 |
|
bb69ae049 anycast: Some RCU... |
76 |
rcu_read_lock(); |
1da177e4c Linux-2.6.12-rc2 |
77 78 |
if (ifindex == 0) { struct rt6_info *rt; |
6ab57e7e7 [NETNS][IPV6] any... |
79 |
rt = rt6_lookup(net, addr, NULL, 0, 0); |
1da177e4c Linux-2.6.12-rc2 |
80 |
if (rt) { |
d19185428 ipv6: Kill rt6i_d... |
81 |
dev = rt->dst.dev; |
d8d1f30b9 net-next: remove ... |
82 |
dst_release(&rt->dst); |
1da177e4c Linux-2.6.12-rc2 |
83 84 |
} else if (ishost) { err = -EADDRNOTAVAIL; |
bb69ae049 anycast: Some RCU... |
85 |
goto error; |
1da177e4c Linux-2.6.12-rc2 |
86 87 |
} else { /* router, no matching interface: just pick one */ |
bb69ae049 anycast: Some RCU... |
88 89 |
dev = dev_get_by_flags_rcu(net, IFF_UP, IFF_UP | IFF_LOOPBACK); |
1da177e4c Linux-2.6.12-rc2 |
90 91 |
} } else |
bb69ae049 anycast: Some RCU... |
92 |
dev = dev_get_by_index_rcu(net, ifindex); |
1da177e4c Linux-2.6.12-rc2 |
93 94 95 |
if (dev == NULL) { err = -ENODEV; |
bb69ae049 anycast: Some RCU... |
96 |
goto error; |
1da177e4c Linux-2.6.12-rc2 |
97 |
} |
bb69ae049 anycast: Some RCU... |
98 |
idev = __in6_dev_get(dev); |
1da177e4c Linux-2.6.12-rc2 |
99 100 101 102 103 |
if (!idev) { if (ifindex) err = -ENODEV; else err = -EADDRNOTAVAIL; |
bb69ae049 anycast: Some RCU... |
104 |
goto error; |
1da177e4c Linux-2.6.12-rc2 |
105 106 107 |
} /* reset ishost, now that we have a specific device */ ishost = !idev->cnf.forwarding; |
1da177e4c Linux-2.6.12-rc2 |
108 109 110 111 112 113 114 115 |
pac->acl_ifindex = dev->ifindex; /* XXX * For hosts, allow link-local or matching prefix anycasts. * This obviates the need for propagating anycast routes while * still allowing some non-router anycast participation. */ |
52eeeb848 [IPV6]: Unify ip6... |
116 |
if (!ipv6_chk_prefix(addr, dev)) { |
1da177e4c Linux-2.6.12-rc2 |
117 118 119 |
if (ishost) err = -EADDRNOTAVAIL; if (err) |
bb69ae049 anycast: Some RCU... |
120 |
goto error; |
1da177e4c Linux-2.6.12-rc2 |
121 122 123 |
} err = ipv6_dev_ac_inc(dev, addr); |
bb69ae049 anycast: Some RCU... |
124 125 126 127 128 129 130 |
if (!err) { write_lock_bh(&ipv6_sk_ac_lock); pac->acl_next = np->ipv6_ac_list; np->ipv6_ac_list = pac; write_unlock_bh(&ipv6_sk_ac_lock); pac = NULL; } |
1da177e4c Linux-2.6.12-rc2 |
131 |
|
bb69ae049 anycast: Some RCU... |
132 133 134 135 |
error: rcu_read_unlock(); if (pac) sock_kfree_s(sk, pac, sizeof(*pac)); |
1da177e4c Linux-2.6.12-rc2 |
136 137 138 139 140 141 |
return err; } /* * socket leave an anycast group */ |
b71d1d426 inet: constify ip... |
142 |
int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) |
1da177e4c Linux-2.6.12-rc2 |
143 144 145 146 |
{ struct ipv6_pinfo *np = inet6_sk(sk); struct net_device *dev; struct ipv6_ac_socklist *pac, *prev_pac; |
6ab57e7e7 [NETNS][IPV6] any... |
147 |
struct net *net = sock_net(sk); |
1da177e4c Linux-2.6.12-rc2 |
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
write_lock_bh(&ipv6_sk_ac_lock); prev_pac = NULL; for (pac = np->ipv6_ac_list; pac; pac = pac->acl_next) { if ((ifindex == 0 || pac->acl_ifindex == ifindex) && ipv6_addr_equal(&pac->acl_addr, addr)) break; prev_pac = pac; } if (!pac) { write_unlock_bh(&ipv6_sk_ac_lock); return -ENOENT; } if (prev_pac) prev_pac->acl_next = pac->acl_next; else np->ipv6_ac_list = pac->acl_next; write_unlock_bh(&ipv6_sk_ac_lock); |
bb69ae049 anycast: Some RCU... |
167 168 169 |
rcu_read_lock(); dev = dev_get_by_index_rcu(net, pac->acl_ifindex); if (dev) |
1da177e4c Linux-2.6.12-rc2 |
170 |
ipv6_dev_ac_dec(dev, &pac->acl_addr); |
bb69ae049 anycast: Some RCU... |
171 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
172 173 174 175 176 177 178 179 180 |
sock_kfree_s(sk, pac, sizeof(*pac)); return 0; } void ipv6_sock_ac_close(struct sock *sk) { struct ipv6_pinfo *np = inet6_sk(sk); struct net_device *dev = NULL; struct ipv6_ac_socklist *pac; |
6ab57e7e7 [NETNS][IPV6] any... |
181 |
struct net *net = sock_net(sk); |
1da177e4c Linux-2.6.12-rc2 |
182 183 184 185 186 187 188 189 |
int prev_index; write_lock_bh(&ipv6_sk_ac_lock); pac = np->ipv6_ac_list; np->ipv6_ac_list = NULL; write_unlock_bh(&ipv6_sk_ac_lock); prev_index = 0; |
bb69ae049 anycast: Some RCU... |
190 |
rcu_read_lock(); |
1da177e4c Linux-2.6.12-rc2 |
191 192 193 194 |
while (pac) { struct ipv6_ac_socklist *next = pac->acl_next; if (pac->acl_ifindex != prev_index) { |
bb69ae049 anycast: Some RCU... |
195 |
dev = dev_get_by_index_rcu(net, pac->acl_ifindex); |
1da177e4c Linux-2.6.12-rc2 |
196 197 198 199 200 201 202 |
prev_index = pac->acl_ifindex; } if (dev) ipv6_dev_ac_dec(dev, &pac->acl_addr); sock_kfree_s(sk, pac, sizeof(*pac)); pac = next; } |
bb69ae049 anycast: Some RCU... |
203 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
} #if 0 /* The function is not used, which is funny. Apparently, author * supposed to use it to filter out datagrams inside udp/raw but forgot. * * It is OK, anycasts are not special comparing to delivery to unicasts. */ int inet6_ac_check(struct sock *sk, struct in6_addr *addr, int ifindex) { struct ipv6_ac_socklist *pac; struct ipv6_pinfo *np = inet6_sk(sk); int found; found = 0; read_lock(&ipv6_sk_ac_lock); for (pac=np->ipv6_ac_list; pac; pac=pac->acl_next) { if (ifindex && pac->acl_ifindex != ifindex) continue; found = ipv6_addr_equal(&pac->acl_addr, addr); if (found) break; } read_unlock(&ipv6_sk_ac_lock); return found; } #endif static void aca_put(struct ifacaddr6 *ac) { if (atomic_dec_and_test(&ac->aca_refcnt)) { in6_dev_put(ac->aca_idev); |
d8d1f30b9 net-next: remove ... |
239 |
dst_release(&ac->aca_rt->dst); |
1da177e4c Linux-2.6.12-rc2 |
240 241 242 243 244 245 246 |
kfree(ac); } } /* * device anycast group inc (add if not found) */ |
b71d1d426 inet: constify ip... |
247 |
int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr) |
1da177e4c Linux-2.6.12-rc2 |
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
{ struct ifacaddr6 *aca; struct inet6_dev *idev; struct rt6_info *rt; int err; idev = in6_dev_get(dev); if (idev == NULL) return -EINVAL; write_lock_bh(&idev->lock); if (idev->dead) { err = -ENODEV; goto out; } for (aca = idev->ac_list; aca; aca = aca->aca_next) { if (ipv6_addr_equal(&aca->aca_addr, addr)) { aca->aca_users++; err = 0; goto out; } } /* * not found: create a new one. */ |
0c600eda4 [IPV6]: Nearly co... |
276 |
aca = kzalloc(sizeof(struct ifacaddr6), GFP_ATOMIC); |
1da177e4c Linux-2.6.12-rc2 |
277 278 279 280 281 |
if (aca == NULL) { err = -ENOMEM; goto out; } |
8f0315190 ipv6: Make third ... |
282 |
rt = addrconf_dst_alloc(idev, addr, true); |
1da177e4c Linux-2.6.12-rc2 |
283 284 285 286 287 |
if (IS_ERR(rt)) { kfree(aca); err = PTR_ERR(rt); goto out; } |
4e3fd7a06 net: remove ipv6_... |
288 |
aca->aca_addr = *addr; |
1da177e4c Linux-2.6.12-rc2 |
289 290 291 292 293 294 295 296 297 298 299 |
aca->aca_idev = idev; aca->aca_rt = rt; aca->aca_users = 1; /* aca_tstamp should be updated upon changes */ aca->aca_cstamp = aca->aca_tstamp = jiffies; atomic_set(&aca->aca_refcnt, 2); spin_lock_init(&aca->aca_lock); aca->aca_next = idev->ac_list; idev->ac_list = aca; write_unlock_bh(&idev->lock); |
84f59370c [IPV6]: Fix refco... |
300 |
ip6_ins_rt(rt); |
1da177e4c Linux-2.6.12-rc2 |
301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
addrconf_join_solict(dev, &aca->aca_addr); aca_put(aca); return 0; out: write_unlock_bh(&idev->lock); in6_dev_put(idev); return err; } /* * device anycast group decrement */ |
b71d1d426 inet: constify ip... |
315 |
int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr) |
1da177e4c Linux-2.6.12-rc2 |
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
{ struct ifacaddr6 *aca, *prev_aca; write_lock_bh(&idev->lock); prev_aca = NULL; for (aca = idev->ac_list; aca; aca = aca->aca_next) { if (ipv6_addr_equal(&aca->aca_addr, addr)) break; prev_aca = aca; } if (!aca) { write_unlock_bh(&idev->lock); return -ENOENT; } if (--aca->aca_users > 0) { write_unlock_bh(&idev->lock); return 0; } if (prev_aca) prev_aca->aca_next = aca->aca_next; else idev->ac_list = aca->aca_next; write_unlock_bh(&idev->lock); addrconf_leave_solict(idev, &aca->aca_addr); |
d8d1f30b9 net-next: remove ... |
340 |
dst_hold(&aca->aca_rt->dst); |
84f59370c [IPV6]: Fix refco... |
341 |
ip6_del_rt(aca->aca_rt); |
1da177e4c Linux-2.6.12-rc2 |
342 343 344 345 |
aca_put(aca); return 0; } |
bb69ae049 anycast: Some RCU... |
346 |
/* called with rcu_read_lock() */ |
b71d1d426 inet: constify ip... |
347 |
static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr) |
1da177e4c Linux-2.6.12-rc2 |
348 |
{ |
bb69ae049 anycast: Some RCU... |
349 |
struct inet6_dev *idev = __in6_dev_get(dev); |
1da177e4c Linux-2.6.12-rc2 |
350 351 |
if (idev == NULL) return -ENODEV; |
bb69ae049 anycast: Some RCU... |
352 |
return __ipv6_dev_ac_dec(idev, addr); |
1da177e4c Linux-2.6.12-rc2 |
353 |
} |
1ab1457c4 [NET] IPV6: Fix w... |
354 |
|
1da177e4c Linux-2.6.12-rc2 |
355 356 |
/* * check if the interface has this anycast address |
bb69ae049 anycast: Some RCU... |
357 |
* called with rcu_read_lock() |
1da177e4c Linux-2.6.12-rc2 |
358 |
*/ |
b71d1d426 inet: constify ip... |
359 |
static int ipv6_chk_acast_dev(struct net_device *dev, const struct in6_addr *addr) |
1da177e4c Linux-2.6.12-rc2 |
360 361 362 |
{ struct inet6_dev *idev; struct ifacaddr6 *aca; |
bb69ae049 anycast: Some RCU... |
363 |
idev = __in6_dev_get(dev); |
1da177e4c Linux-2.6.12-rc2 |
364 365 366 367 368 369 |
if (idev) { read_lock_bh(&idev->lock); for (aca = idev->ac_list; aca; aca = aca->aca_next) if (ipv6_addr_equal(&aca->aca_addr, addr)) break; read_unlock_bh(&idev->lock); |
cfcabdcc2 [NET]: sparse war... |
370 |
return aca != NULL; |
1da177e4c Linux-2.6.12-rc2 |
371 372 373 374 375 376 377 |
} return 0; } /* * check if given interface (or any, if dev==0) has this anycast address */ |
6ab57e7e7 [NETNS][IPV6] any... |
378 |
int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, |
b71d1d426 inet: constify ip... |
379 |
const struct in6_addr *addr) |
1da177e4c Linux-2.6.12-rc2 |
380 |
{ |
7562f876c [NET]: Rework dev... |
381 |
int found = 0; |
c6d14c845 net: Introduce fo... |
382 |
rcu_read_lock(); |
bb69ae049 anycast: Some RCU... |
383 384 385 386 387 388 389 390 |
if (dev) found = ipv6_chk_acast_dev(dev, addr); else for_each_netdev_rcu(net, dev) if (ipv6_chk_acast_dev(dev, addr)) { found = 1; break; } |
c6d14c845 net: Introduce fo... |
391 |
rcu_read_unlock(); |
7562f876c [NET]: Rework dev... |
392 |
return found; |
1da177e4c Linux-2.6.12-rc2 |
393 394 395 396 397 |
} #ifdef CONFIG_PROC_FS struct ac6_iter_state { |
6ab57e7e7 [NETNS][IPV6] any... |
398 |
struct seq_net_private p; |
1da177e4c Linux-2.6.12-rc2 |
399 400 401 402 403 404 405 406 407 408 |
struct net_device *dev; struct inet6_dev *idev; }; #define ac6_seq_private(seq) ((struct ac6_iter_state *)(seq)->private) static inline struct ifacaddr6 *ac6_get_first(struct seq_file *seq) { struct ifacaddr6 *im = NULL; struct ac6_iter_state *state = ac6_seq_private(seq); |
6ab57e7e7 [NETNS][IPV6] any... |
409 |
struct net *net = seq_file_net(seq); |
1da177e4c Linux-2.6.12-rc2 |
410 |
|
7562f876c [NET]: Rework dev... |
411 |
state->idev = NULL; |
ce81b76a3 ipv6: use RCU to ... |
412 |
for_each_netdev_rcu(net, state->dev) { |
1da177e4c Linux-2.6.12-rc2 |
413 |
struct inet6_dev *idev; |
ce81b76a3 ipv6: use RCU to ... |
414 |
idev = __in6_dev_get(state->dev); |
1da177e4c Linux-2.6.12-rc2 |
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
if (!idev) continue; read_lock_bh(&idev->lock); im = idev->ac_list; if (im) { state->idev = idev; break; } read_unlock_bh(&idev->lock); } return im; } static struct ifacaddr6 *ac6_get_next(struct seq_file *seq, struct ifacaddr6 *im) { struct ac6_iter_state *state = ac6_seq_private(seq); im = im->aca_next; while (!im) { |
ce81b76a3 ipv6: use RCU to ... |
434 |
if (likely(state->idev != NULL)) |
1da177e4c Linux-2.6.12-rc2 |
435 |
read_unlock_bh(&state->idev->lock); |
ce81b76a3 ipv6: use RCU to ... |
436 437 |
state->dev = next_net_device_rcu(state->dev); |
1da177e4c Linux-2.6.12-rc2 |
438 439 440 441 |
if (!state->dev) { state->idev = NULL; break; } |
ce81b76a3 ipv6: use RCU to ... |
442 |
state->idev = __in6_dev_get(state->dev); |
1da177e4c Linux-2.6.12-rc2 |
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 |
if (!state->idev) continue; read_lock_bh(&state->idev->lock); im = state->idev->ac_list; } return im; } static struct ifacaddr6 *ac6_get_idx(struct seq_file *seq, loff_t pos) { struct ifacaddr6 *im = ac6_get_first(seq); if (im) while (pos && (im = ac6_get_next(seq, im)) != NULL) --pos; return pos ? NULL : im; } static void *ac6_seq_start(struct seq_file *seq, loff_t *pos) |
ce81b76a3 ipv6: use RCU to ... |
461 |
__acquires(RCU) |
1da177e4c Linux-2.6.12-rc2 |
462 |
{ |
ce81b76a3 ipv6: use RCU to ... |
463 |
rcu_read_lock(); |
1da177e4c Linux-2.6.12-rc2 |
464 465 466 467 468 |
return ac6_get_idx(seq, *pos); } static void *ac6_seq_next(struct seq_file *seq, void *v, loff_t *pos) { |
ce81b76a3 ipv6: use RCU to ... |
469 |
struct ifacaddr6 *im = ac6_get_next(seq, v); |
1da177e4c Linux-2.6.12-rc2 |
470 471 472 473 474 |
++*pos; return im; } static void ac6_seq_stop(struct seq_file *seq, void *v) |
ce81b76a3 ipv6: use RCU to ... |
475 |
__releases(RCU) |
1da177e4c Linux-2.6.12-rc2 |
476 477 |
{ struct ac6_iter_state *state = ac6_seq_private(seq); |
ce81b76a3 ipv6: use RCU to ... |
478 |
|
1da177e4c Linux-2.6.12-rc2 |
479 480 |
if (likely(state->idev != NULL)) { read_unlock_bh(&state->idev->lock); |
ce81b76a3 ipv6: use RCU to ... |
481 |
state->idev = NULL; |
1da177e4c Linux-2.6.12-rc2 |
482 |
} |
ce81b76a3 ipv6: use RCU to ... |
483 |
rcu_read_unlock(); |
1da177e4c Linux-2.6.12-rc2 |
484 485 486 487 488 489 |
} static int ac6_seq_show(struct seq_file *seq, void *v) { struct ifacaddr6 *im = (struct ifacaddr6 *)v; struct ac6_iter_state *state = ac6_seq_private(seq); |
4b7a4274c net: replace %#p6... |
490 491 |
seq_printf(seq, "%-4d %-15s %pi6 %5d ", |
1da177e4c Linux-2.6.12-rc2 |
492 |
state->dev->ifindex, state->dev->name, |
b071195de net: replace all ... |
493 |
&im->aca_addr, im->aca_users); |
1da177e4c Linux-2.6.12-rc2 |
494 495 |
return 0; } |
56b3d975b [NET]: Make all i... |
496 |
static const struct seq_operations ac6_seq_ops = { |
1da177e4c Linux-2.6.12-rc2 |
497 498 499 500 501 502 503 504 |
.start = ac6_seq_start, .next = ac6_seq_next, .stop = ac6_seq_stop, .show = ac6_seq_show, }; static int ac6_seq_open(struct inode *inode, struct file *file) { |
6ab57e7e7 [NETNS][IPV6] any... |
505 506 |
return seq_open_net(inode, file, &ac6_seq_ops, sizeof(struct ac6_iter_state)); |
1da177e4c Linux-2.6.12-rc2 |
507 |
} |
9a32144e9 [PATCH] mark stru... |
508 |
static const struct file_operations ac6_seq_fops = { |
1da177e4c Linux-2.6.12-rc2 |
509 510 511 512 |
.owner = THIS_MODULE, .open = ac6_seq_open, .read = seq_read, .llseek = seq_lseek, |
6ab57e7e7 [NETNS][IPV6] any... |
513 |
.release = seq_release_net, |
1da177e4c Linux-2.6.12-rc2 |
514 |
}; |
2c8c1e729 net: spread __net... |
515 |
int __net_init ac6_proc_init(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
516 |
{ |
6ab57e7e7 [NETNS][IPV6] any... |
517 |
if (!proc_net_fops_create(net, "anycast6", S_IRUGO, &ac6_seq_fops)) |
1da177e4c Linux-2.6.12-rc2 |
518 519 520 521 |
return -ENOMEM; return 0; } |
6ab57e7e7 [NETNS][IPV6] any... |
522 |
void ac6_proc_exit(struct net *net) |
1da177e4c Linux-2.6.12-rc2 |
523 |
{ |
6ab57e7e7 [NETNS][IPV6] any... |
524 |
proc_net_remove(net, "anycast6"); |
1da177e4c Linux-2.6.12-rc2 |
525 526 |
} #endif |