diff options
Diffstat (limited to 'pfinet/linux-src/net/ipv6/raw_ipv6.c')
-rw-r--r-- | pfinet/linux-src/net/ipv6/raw_ipv6.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/pfinet/linux-src/net/ipv6/raw_ipv6.c b/pfinet/linux-src/net/ipv6/raw_ipv6.c index 95856ea7..9980b3ad 100644 --- a/pfinet/linux-src/net/ipv6/raw_ipv6.c +++ b/pfinet/linux-src/net/ipv6/raw_ipv6.c @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/raw.c * - * $Id: raw_ipv6.c,v 1.1 2007/10/08 21:12:31 stesie Exp $ + * $Id: raw_ipv6.c,v 1.2 2007/10/13 01:43:00 stesie Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -128,6 +128,25 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) return(-EADDRNOTAVAIL); } else { if (addr_type != IPV6_ADDR_ANY) { + if (addr_type & IPV6_ADDR_LINKLOCAL) { + if (addr_len >= sizeof(struct sockaddr_in6) && + addr->sin6_scope_id) { + /* Override any existing binding, + * if another one is supplied by user. + */ + sk->bound_dev_if = + addr->sin6_scope_id; + } + + /* Binding to link-local address requires + an interface */ + if (!sk->bound_dev_if) + return(-EINVAL); + + if (!dev_get_by_index(sk->bound_dev_if)) + return(-ENODEV); + } + /* ipv4 addr of the socket is invalid. Only the * unpecified and mapped address have a v4 equivalent. */ @@ -252,6 +271,10 @@ int rawv6_recvmsg(struct sock *sk, struct msghdr *msg, int len, memcpy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr, sizeof(struct in6_addr)); sin6->sin6_flowinfo = 0; + sin6->sin6_scope_id = 0; + if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) + sin6->sin6_scope_id = + ((struct inet6_skb_parm *) skb->cb)->iif; } if (sk->net_pinfo.af_inet6.rxopt.all) @@ -391,6 +414,11 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, int len) if (sk->state == TCP_ESTABLISHED && !ipv6_addr_cmp(daddr, &sk->net_pinfo.af_inet6.daddr)) daddr = &sk->net_pinfo.af_inet6.daddr; + + if (addr_len >= sizeof(struct sockaddr_in6) && + sin6->sin6_scope_id && + ipv6_addr_type(daddr)&IPV6_ADDR_LINKLOCAL) + fl.oif = sin6->sin6_scope_id; } else { if (sk->state != TCP_ESTABLISHED) return(-EINVAL); |