#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/net.h>
-#include <linux/sched.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
#include <asm/uaccess.h>
+/* Event handler for inet6 address addition/deletion events. */
+static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
+ void *ptr)
+{
+ struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr;
+ struct sctp_sockaddr_entry *addr;
+ struct list_head *pos, *temp;
+
+ switch (ev) {
+ case NETDEV_UP:
+ addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+ if (addr) {
+ addr->a.v6.sin6_family = AF_INET6;
+ addr->a.v6.sin6_port = 0;
+ memcpy(&addr->a.v6.sin6_addr, &ifa->addr,
+ sizeof(struct in6_addr));
+ addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
+ list_add_tail(&addr->list, &sctp_local_addr_list);
+ }
+ break;
+ case NETDEV_DOWN:
+ list_for_each_safe(pos, temp, &sctp_local_addr_list) {
+ addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+ if (ipv6_addr_equal(&addr->a.v6.sin6_addr, &ifa->addr)) {
+ list_del(pos);
+ kfree(addr);
+ break;
+ }
+ }
+
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
static struct notifier_block sctp_inet6addr_notifier = {
- .notifier_call = sctp_inetaddr_event,
+ .notifier_call = sctp_inet6addr_event,
};
/* ICMP error handler. */
/* Fill in the dest address from the route entry passed with the skb
* and the source address from the transport.
*/
- ipv6_addr_copy(&fl.fl6_dst, &transport->ipaddr_h.v6.sin6_addr);
+ ipv6_addr_copy(&fl.fl6_dst, &transport->ipaddr.v6.sin6_addr);
ipv6_addr_copy(&fl.fl6_src, &transport->saddr.v6.sin6_addr);
fl.fl6_flowlabel = np->flow_label;
fl.oif = transport->saddr.v6.sin6_scope_id;
else
fl.oif = sk->sk_bound_dev_if;
- fl.fl_ip_sport = inet_sk(sk)->sport;
- fl.fl_ip_dport = transport->ipaddr_h.v6.sin6_port;
if (np->opt && np->opt->srcrt) {
struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt;
ipv6_addr_copy(&fl.fl6_dst, &daddr->v6.sin6_addr);
if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
fl.oif = daddr->v6.sin6_scope_id;
-
+
SCTP_DEBUG_PRINTK("%s: DST=" NIP6_FMT " ",
__FUNCTION__, NIP6(fl.fl6_dst));
static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
{
addr->v6.sin6_family = AF_INET6;
- addr->v6.sin6_port = inet_sk(sk)->num;
+ addr->v6.sin6_port = 0;
addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr;
}
}
/* Initialize addr struct to INADDR_ANY. */
-static void sctp_v6_inaddr_any(union sctp_addr *addr, unsigned short port)
+static void sctp_v6_inaddr_any(union sctp_addr *addr, __be16 port)
{
memset(addr, 0x00, sizeof(union sctp_addr));
addr->v6.sin6_family = AF_INET6;
* Returns number of addresses supported.
*/
static int sctp_inet6_supported_addrs(const struct sctp_sock *opt,
- __u16 *types)
+ __be16 *types)
{
types[0] = SCTP_PARAM_IPV4_ADDRESS;
types[1] = SCTP_PARAM_IPV6_ADDRESS;