Pull routing header handling out of ip6_output
No functional change.
This commit is contained in:
parent
2ad0a3feca
commit
29a46075c0
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: ip6_output.c,v 1.176 2016/11/07 01:05:39 ozaki-r Exp $ */
|
/* $NetBSD: ip6_output.c,v 1.177 2016/11/07 01:55:17 ozaki-r Exp $ */
|
||||||
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
|
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -62,7 +62,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.176 2016/11/07 01:05:39 ozaki-r Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.177 2016/11/07 01:55:17 ozaki-r Exp $");
|
||||||
|
|
||||||
#ifdef _KERNEL_OPT
|
#ifdef _KERNEL_OPT
|
||||||
#include "opt_inet.h"
|
#include "opt_inet.h"
|
||||||
@ -136,11 +136,50 @@ static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
|
|||||||
static int ip6_getpmtu(struct rtentry *, struct ifnet *, u_long *, int *);
|
static int ip6_getpmtu(struct rtentry *, struct ifnet *, u_long *, int *);
|
||||||
static int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *, int);
|
static int copypktopts(struct ip6_pktopts *, struct ip6_pktopts *, int);
|
||||||
static int ip6_ifaddrvalid(const struct in6_addr *);
|
static int ip6_ifaddrvalid(const struct in6_addr *);
|
||||||
|
static int ip6_handle_rthdr(struct ip6_rthdr *, struct ip6_hdr *);
|
||||||
|
|
||||||
#ifdef RFC2292
|
#ifdef RFC2292
|
||||||
static int ip6_pcbopts(struct ip6_pktopts **, struct socket *, struct sockopt *);
|
static int ip6_pcbopts(struct ip6_pktopts **, struct socket *, struct sockopt *);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
ip6_handle_rthdr(struct ip6_rthdr *rh, struct ip6_hdr *ip6)
|
||||||
|
{
|
||||||
|
struct ip6_rthdr0 *rh0;
|
||||||
|
struct in6_addr *addr;
|
||||||
|
struct sockaddr_in6 sa;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
switch (rh->ip6r_type) {
|
||||||
|
case IPV6_RTHDR_TYPE_0:
|
||||||
|
rh0 = (struct ip6_rthdr0 *)rh;
|
||||||
|
addr = (struct in6_addr *)(rh0 + 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* construct a sockaddr_in6 form of the first hop.
|
||||||
|
*
|
||||||
|
* XXX we may not have enough information about its scope zone;
|
||||||
|
* there is no standard API to pass the information from the
|
||||||
|
* application.
|
||||||
|
*/
|
||||||
|
sockaddr_in6_init(&sa, addr, 0, 0, 0);
|
||||||
|
error = sa6_embedscope(&sa, ip6_use_defzone);
|
||||||
|
if (error != 0)
|
||||||
|
break;
|
||||||
|
(void)memmove(&addr[0], &addr[1],
|
||||||
|
sizeof(struct in6_addr) * (rh0->ip6r0_segleft - 1));
|
||||||
|
addr[rh0->ip6r0_segleft - 1] = ip6->ip6_dst;
|
||||||
|
ip6->ip6_dst = sa.sin6_addr;
|
||||||
|
/* XXX */
|
||||||
|
in6_clearscope(addr + rh0->ip6r0_segleft - 1);
|
||||||
|
break;
|
||||||
|
default: /* is it possible? */
|
||||||
|
error = EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IP6 output. The packet in mbuf chain m contains a skeletal IP6
|
* IP6 output. The packet in mbuf chain m contains a skeletal IP6
|
||||||
* header (with pri, len, nxt, hlim, src, dst).
|
* header (with pri, len, nxt, hlim, src, dst).
|
||||||
@ -375,45 +414,14 @@ ip6_output(
|
|||||||
*/
|
*/
|
||||||
if (exthdrs.ip6e_rthdr) {
|
if (exthdrs.ip6e_rthdr) {
|
||||||
struct ip6_rthdr *rh;
|
struct ip6_rthdr *rh;
|
||||||
struct ip6_rthdr0 *rh0;
|
|
||||||
struct in6_addr *addr;
|
|
||||||
struct sockaddr_in6 sa;
|
|
||||||
|
|
||||||
rh = (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,
|
rh = (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,
|
||||||
struct ip6_rthdr *));
|
struct ip6_rthdr *));
|
||||||
finaldst = ip6->ip6_dst;
|
finaldst = ip6->ip6_dst; /* need to save for pmtu */
|
||||||
switch (rh->ip6r_type) {
|
|
||||||
case IPV6_RTHDR_TYPE_0:
|
|
||||||
rh0 = (struct ip6_rthdr0 *)rh;
|
|
||||||
addr = (struct in6_addr *)(rh0 + 1);
|
|
||||||
|
|
||||||
/*
|
error = ip6_handle_rthdr(rh, ip6);
|
||||||
* construct a sockaddr_in6 form of
|
if (error != 0)
|
||||||
* the first hop.
|
goto bad;
|
||||||
*
|
|
||||||
* XXX: we may not have enough
|
|
||||||
* information about its scope zone;
|
|
||||||
* there is no standard API to pass
|
|
||||||
* the information from the
|
|
||||||
* application.
|
|
||||||
*/
|
|
||||||
sockaddr_in6_init(&sa, addr, 0, 0, 0);
|
|
||||||
if ((error = sa6_embedscope(&sa,
|
|
||||||
ip6_use_defzone)) != 0) {
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
ip6->ip6_dst = sa.sin6_addr;
|
|
||||||
(void)memmove(&addr[0], &addr[1],
|
|
||||||
sizeof(struct in6_addr) *
|
|
||||||
(rh0->ip6r0_segleft - 1));
|
|
||||||
addr[rh0->ip6r0_segleft - 1] = finaldst;
|
|
||||||
/* XXX */
|
|
||||||
in6_clearscope(addr + rh0->ip6r0_segleft - 1);
|
|
||||||
break;
|
|
||||||
default: /* is it possible? */
|
|
||||||
error = EINVAL;
|
|
||||||
goto bad;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Source address validation */
|
/* Source address validation */
|
||||||
|
Loading…
Reference in New Issue
Block a user