Pull RTM_CHANGE code out of route_output to make further changes easy

No functional change.
This commit is contained in:
ozaki-r 2016-10-26 06:49:10 +00:00
parent 1656c8e745
commit c0732db998

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtsock.c,v 1.197 2016/10/03 11:06:06 ozaki-r Exp $ */
/* $NetBSD: rtsock.c,v 1.198 2016/10/26 06:49:10 ozaki-r Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.197 2016/10/03 11:06:06 ozaki-r Exp $");
__KERNEL_RCSID(0, "$NetBSD: rtsock.c,v 1.198 2016/10/26 06:49:10 ozaki-r Exp $");
#ifdef _KERNEL_OPT
#include "opt_inet.h"
@ -593,6 +593,73 @@ out:
return ifa;
}
static int
route_output_change(struct rtentry *rt, struct rt_addrinfo *info,
struct rt_xmsghdr *rtm)
{
int error = 0;
struct ifnet *ifp, *new_ifp;
struct ifaddr *ifa, *new_ifa;
struct psref psref_ifa, psref_new_ifa, psref_ifp;
/*
* new gateway could require new ifaddr, ifp;
* flags may also be different; ifp may be specified
* by ll sockaddr when protocol address is ambiguous
*/
ifp = rt_getifp(info, &psref_ifp);
ifa = rt_getifa(info, &psref_ifa);
if (ifa == NULL) {
error = ENETUNREACH;
goto out;
}
if (info->rti_info[RTAX_GATEWAY]) {
error = rt_setgate(rt, info->rti_info[RTAX_GATEWAY]);
if (error != 0)
goto out;
}
if (info->rti_info[RTAX_TAG]) {
const struct sockaddr *tag;
tag = rt_settag(rt, info->rti_info[RTAX_TAG]);
if (tag == NULL) {
error = ENOBUFS;
goto out;
}
}
/* new gateway could require new ifaddr, ifp;
flags may also be different; ifp may be specified
by ll sockaddr when protocol address is ambiguous */
new_ifa = route_output_get_ifa(*info, rt, &new_ifp, &psref_new_ifa);
if (new_ifa != NULL) {
ifa_release(ifa, &psref_ifa);
ifa = new_ifa;
}
if (ifa) {
struct ifaddr *oifa = rt->rt_ifa;
if (oifa != ifa) {
if (oifa && oifa->ifa_rtrequest)
oifa->ifa_rtrequest(RTM_DELETE, rt, info);
rt_replace_ifa(rt, ifa);
rt->rt_ifp = new_ifp;
}
if (new_ifa == NULL)
ifa_release(ifa, &psref_ifa);
}
ifa_release(new_ifa, &psref_new_ifa);
if (new_ifp && rt->rt_ifp != new_ifp)
rt->rt_ifp = new_ifp;
rt_setmetrics(rtm->rtm_inits, rtm, rt);
if (rt->rt_flags != info->rti_flags)
rt->rt_flags = (info->rti_flags & ~PRESERVED_RTF)
| (rt->rt_flags & PRESERVED_RTF);
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, info);
out:
if_put(ifp, &psref_ifp);
return error;
}
/*ARGSUSED*/
int
COMPATNAME(route_output)(struct mbuf *m, struct socket *so)
@ -604,11 +671,8 @@ COMPATNAME(route_output)(struct mbuf *m, struct socket *so)
struct rtentry *saved_nrt = NULL;
struct rt_addrinfo info;
int len, error = 0;
struct ifnet *ifp = NULL;
struct ifaddr *ifa = NULL;
sa_family_t family;
struct sockaddr_dl sdl;
struct psref psref;
int bound = curlwp_bind();
#define senderr(e) do { error = e; goto flush;} while (/*CONSTCOND*/ 0)
@ -818,70 +882,11 @@ COMPATNAME(route_output)(struct mbuf *m, struct socket *so)
}
break;
case RTM_CHANGE: {
struct ifnet *_ifp;
struct ifaddr *_ifa;
struct psref _psref, psref_ifp;
/*
* new gateway could require new ifaddr, ifp;
* flags may also be different; ifp may be specified
* by ll sockaddr when protocol address is ambiguous
*/
_ifp = rt_getifp(&info, &psref_ifp);
ifa = rt_getifa(&info, &psref);
if (ifa == NULL) {
if_put(_ifp, &psref_ifp);
senderr(ENETUNREACH);
}
if (info.rti_info[RTAX_GATEWAY]) {
error = rt_setgate(rt,
info.rti_info[RTAX_GATEWAY]);
if (error != 0) {
if_put(_ifp, &psref_ifp);
senderr(error);
}
}
if (info.rti_info[RTAX_TAG]) {
const struct sockaddr *tag;
tag = rt_settag(rt, info.rti_info[RTAX_TAG]);
if (tag == NULL) {
if_put(_ifp, &psref_ifp);
senderr(ENOBUFS);
}
}
/* new gateway could require new ifaddr, ifp;
flags may also be different; ifp may be specified
by ll sockaddr when protocol address is ambiguous */
_ifa = route_output_get_ifa(info, rt, &ifp, &_psref);
if (_ifa != NULL) {
ifa_release(ifa, &psref);
ifa = _ifa;
}
if (ifa) {
struct ifaddr *oifa = rt->rt_ifa;
if (oifa != ifa) {
if (oifa && oifa->ifa_rtrequest) {
oifa->ifa_rtrequest(RTM_DELETE,
rt, &info);
}
rt_replace_ifa(rt, ifa);
rt->rt_ifp = ifp;
}
if (_ifa == NULL)
ifa_release(ifa, &psref);
}
ifa_release(_ifa, &_psref);
if (ifp && rt->rt_ifp != ifp)
rt->rt_ifp = ifp;
rt_setmetrics(rtm->rtm_inits, rtm, rt);
if (rt->rt_flags != info.rti_flags)
rt->rt_flags = (info.rti_flags & ~PRESERVED_RTF)
| (rt->rt_flags & PRESERVED_RTF);
if (rt->rt_ifa && rt->rt_ifa->ifa_rtrequest)
rt->rt_ifa->ifa_rtrequest(RTM_ADD, rt, &info);
if_put(_ifp, &psref_ifp);
case RTM_CHANGE:
error = route_output_change(rt, &info, rtm);
if (error != 0)
goto flush;
/*FALLTHROUGH*/
}
case RTM_LOCK:
rt->rt_rmx.rmx_locks &= ~(rtm->rtm_inits);
rt->rt_rmx.rmx_locks |=