diff options
Diffstat (limited to 'net/sctp/ipv6.c')
-rw-r--r-- | net/sctp/ipv6.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 3c3e560087ca..d8d36dee5ab6 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -78,8 +78,44 @@ | |||
78 | 78 | ||
79 | #include <asm/uaccess.h> | 79 | #include <asm/uaccess.h> |
80 | 80 | ||
81 | /* Event handler for inet6 address addition/deletion events. */ | ||
82 | int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, | ||
83 | void *ptr) | ||
84 | { | ||
85 | struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; | ||
86 | struct sctp_sockaddr_entry *addr; | ||
87 | struct list_head *pos, *temp; | ||
88 | |||
89 | switch (ev) { | ||
90 | case NETDEV_UP: | ||
91 | addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); | ||
92 | if (addr) { | ||
93 | addr->a.v6.sin6_family = AF_INET6; | ||
94 | addr->a.v6.sin6_port = 0; | ||
95 | memcpy(&addr->a.v6.sin6_addr, &ifa->addr, | ||
96 | sizeof(struct in6_addr)); | ||
97 | addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; | ||
98 | list_add_tail(&addr->list, &sctp_local_addr_list); | ||
99 | } | ||
100 | break; | ||
101 | case NETDEV_DOWN: | ||
102 | list_for_each_safe(pos, temp, &sctp_local_addr_list) { | ||
103 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); | ||
104 | if (ipv6_addr_equal(&addr->a.v6.sin6_addr, &ifa->addr)) { | ||
105 | list_del(pos); | ||
106 | kfree(addr); | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | break; | ||
112 | } | ||
113 | |||
114 | return NOTIFY_DONE; | ||
115 | } | ||
116 | |||
81 | static struct notifier_block sctp_inet6addr_notifier = { | 117 | static struct notifier_block sctp_inet6addr_notifier = { |
82 | .notifier_call = sctp_inetaddr_event, | 118 | .notifier_call = sctp_inet6addr_event, |
83 | }; | 119 | }; |
84 | 120 | ||
85 | /* ICMP error handler. */ | 121 | /* ICMP error handler. */ |