version 1.145, 2015/06/08 08:21:49 |
version 1.146, 2015/07/17 02:21:08 |
Line 355 rtcache(struct route *ro) |
|
Line 355 rtcache(struct route *ro) |
|
} |
} |
|
|
/* |
/* |
* Packet routing routines. |
* Packet routing routines. If success, refcnt of a returned rtentry |
|
* will be incremented. The caller has to rtfree it by itself. |
*/ |
*/ |
struct rtentry * |
struct rtentry * |
rtalloc1(const struct sockaddr *dst, int report) |
rtalloc1(const struct sockaddr *dst, int report) |
Line 378 rtalloc1(const struct sockaddr *dst, int |
|
Line 379 rtalloc1(const struct sockaddr *dst, int |
|
} |
} |
KASSERT(newrt != NULL); |
KASSERT(newrt != NULL); |
rt = newrt; |
rt = newrt; |
|
rt->rt_refcnt++; |
if (rt->rt_flags & RTF_XRESOLVE) { |
if (rt->rt_flags & RTF_XRESOLVE) { |
msgtype = RTM_RESOLVE; |
msgtype = RTM_RESOLVE; |
goto miss; |
goto miss; |
|
|
} |
} |
|
|
/* |
/* |
* Delete a route and generate a message |
* Delete a route and generate a message. |
|
* It doesn't free a passed rt. |
*/ |
*/ |
static int |
static int |
rtdeletemsg(struct rtentry *rt) |
rtdeletemsg(struct rtentry *rt) |
{ |
{ |
int error; |
int error; |
struct rt_addrinfo info; |
struct rt_addrinfo info; |
|
struct rtentry *retrt; |
|
|
/* |
/* |
* Request the new route so that the entry is not actually |
* Request the new route so that the entry is not actually |
Line 551 rtdeletemsg(struct rtentry *rt) |
|
Line 555 rtdeletemsg(struct rtentry *rt) |
|
info.rti_info[RTAX_NETMASK] = rt_mask(rt); |
info.rti_info[RTAX_NETMASK] = rt_mask(rt); |
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; |
info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; |
info.rti_flags = rt->rt_flags; |
info.rti_flags = rt->rt_flags; |
error = rtrequest1(RTM_DELETE, &info, &rt); |
error = rtrequest1(RTM_DELETE, &info, &retrt); |
|
|
rt_missmsg(RTM_DELETE, &info, info.rti_flags, error); |
rt_missmsg(RTM_DELETE, &info, info.rti_flags, error); |
|
|
/* Adjust the refcount */ |
if (error == 0) |
if (error == 0 && rt->rt_refcnt <= 0) { |
rtfree(retrt); |
rt->rt_refcnt++; |
|
rtfree(rt); |
|
} |
|
return error; |
return error; |
} |
} |
|
|
Line 617 ifa_ifwithroute(int flags, const struct |
|
Line 618 ifa_ifwithroute(int flags, const struct |
|
struct rtentry *rt = rtalloc1(dst, 0); |
struct rtentry *rt = rtalloc1(dst, 0); |
if (rt == NULL) |
if (rt == NULL) |
return NULL; |
return NULL; |
rt->rt_refcnt--; |
ifa = rt->rt_ifa; |
if ((ifa = rt->rt_ifa) == NULL) |
rtfree(rt); |
|
if (ifa == NULL) |
return NULL; |
return NULL; |
} |
} |
if (ifa->ifa_addr->sa_family != dst->sa_family) { |
if (ifa->ifa_addr->sa_family != dst->sa_family) { |
Line 630 ifa_ifwithroute(int flags, const struct |
|
Line 632 ifa_ifwithroute(int flags, const struct |
|
return ifa; |
return ifa; |
} |
} |
|
|
|
/* |
|
* If it suceeds and ret_nrt isn't NULL, refcnt of ret_nrt is incremented. |
|
* The caller has to rtfree it by itself. |
|
*/ |
int |
int |
rtrequest(int req, const struct sockaddr *dst, const struct sockaddr *gateway, |
rtrequest(int req, const struct sockaddr *dst, const struct sockaddr *gateway, |
const struct sockaddr *netmask, int flags, struct rtentry **ret_nrt) |
const struct sockaddr *netmask, int flags, struct rtentry **ret_nrt) |
Line 644 rtrequest(int req, const struct sockaddr |
|
Line 650 rtrequest(int req, const struct sockaddr |
|
return rtrequest1(req, &info, ret_nrt); |
return rtrequest1(req, &info, ret_nrt); |
} |
} |
|
|
|
/* |
|
* It's a utility function to add/remove a route to/from the routing table |
|
* and tell user processes the addition/removal on success. |
|
*/ |
|
int |
|
rtrequest_newmsg(const int req, const struct sockaddr *dst, |
|
const struct sockaddr *gateway, const struct sockaddr *netmask, |
|
const int flags) |
|
{ |
|
int error; |
|
struct rtentry *ret_nrt = NULL; |
|
|
|
KASSERT(req == RTM_ADD || req == RTM_DELETE); |
|
|
|
error = rtrequest(req, dst, gateway, netmask, flags, &ret_nrt); |
|
if (error != 0) |
|
return error; |
|
|
|
KASSERT(ret_nrt != NULL); |
|
|
|
rt_newmsg(req, ret_nrt); /* tell user process */ |
|
rtfree(ret_nrt); |
|
|
|
return 0; |
|
} |
|
|
int |
int |
rt_getifa(struct rt_addrinfo *info) |
rt_getifa(struct rt_addrinfo *info) |
{ |
{ |
Line 688 rt_getifa(struct rt_addrinfo *info) |
|
Line 720 rt_getifa(struct rt_addrinfo *info) |
|
return 0; |
return 0; |
} |
} |
|
|
|
/* |
|
* If it suceeds and ret_nrt isn't NULL, refcnt of ret_nrt is incremented. |
|
* The caller has to rtfree it by itself. |
|
*/ |
int |
int |
rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) |
rtrequest1(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt) |
{ |
{ |
Line 743 rtrequest1(int req, struct rt_addrinfo * |
|
Line 779 rtrequest1(int req, struct rt_addrinfo * |
|
ifa->ifa_rtrequest(RTM_DELETE, rt, info); |
ifa->ifa_rtrequest(RTM_DELETE, rt, info); |
} |
} |
rttrash++; |
rttrash++; |
if (ret_nrt) |
if (ret_nrt) { |
*ret_nrt = rt; |
*ret_nrt = rt; |
else if (rt->rt_refcnt <= 0) { |
rt->rt_refcnt++; |
|
} else if (rt->rt_refcnt <= 0) { |
|
/* Adjust the refcount */ |
rt->rt_refcnt++; |
rt->rt_refcnt++; |
rtfree(rt); |
rtfree(rt); |
} |
} |
Line 974 rtinit(struct ifaddr *ifa, int cmd, int |
|
Line 1012 rtinit(struct ifaddr *ifa, int cmd, int |
|
rt_maskedcopy(odst, dst, ifa->ifa_netmask); |
rt_maskedcopy(odst, dst, ifa->ifa_netmask); |
} |
} |
if ((rt = rtalloc1(dst, 0)) != NULL) { |
if ((rt = rtalloc1(dst, 0)) != NULL) { |
rt->rt_refcnt--; |
if (rt->rt_ifa != ifa) { |
if (rt->rt_ifa != ifa) |
rtfree(rt); |
return (flags & RTF_HOST) ? EHOSTUNREACH |
return (flags & RTF_HOST) ? EHOSTUNREACH |
: ENETUNREACH; |
: ENETUNREACH; |
|
} |
|
rtfree(rt); |
} |
} |
} |
} |
memset(&info, 0, sizeof(info)); |
memset(&info, 0, sizeof(info)); |
Line 996 rtinit(struct ifaddr *ifa, int cmd, int |
|
Line 1036 rtinit(struct ifaddr *ifa, int cmd, int |
|
error = rtrequest1((cmd == RTM_LLINFO_UPD) ? RTM_GET : cmd, &info, |
error = rtrequest1((cmd == RTM_LLINFO_UPD) ? RTM_GET : cmd, &info, |
&nrt); |
&nrt); |
if (error != 0 || (rt = nrt) == NULL) |
if (error != 0 || (rt = nrt) == NULL) |
; |
return error; |
else switch (cmd) { |
|
|
switch (cmd) { |
case RTM_DELETE: |
case RTM_DELETE: |
rt_newmsg(cmd, nrt); |
rt_newmsg(cmd, rt); |
if (rt->rt_refcnt <= 0) { |
rtfree(rt); |
rt->rt_refcnt++; |
|
rtfree(rt); |
|
} |
|
break; |
break; |
case RTM_LLINFO_UPD: |
case RTM_LLINFO_UPD: |
rt->rt_refcnt--; |
|
RT_DPRINTF("%s: updating%s\n", __func__, |
RT_DPRINTF("%s: updating%s\n", __func__, |
((rt->rt_flags & RTF_LLINFO) == 0) ? " (no llinfo)" : ""); |
((rt->rt_flags & RTF_LLINFO) == 0) ? " (no llinfo)" : ""); |
|
|
Line 1023 rtinit(struct ifaddr *ifa, int cmd, int |
|
Line 1060 rtinit(struct ifaddr *ifa, int cmd, int |
|
|
|
if (cmd == RTM_LLINFO_UPD && ifa->ifa_rtrequest != NULL) |
if (cmd == RTM_LLINFO_UPD && ifa->ifa_rtrequest != NULL) |
ifa->ifa_rtrequest(RTM_LLINFO_UPD, rt, &info); |
ifa->ifa_rtrequest(RTM_LLINFO_UPD, rt, &info); |
rt_newmsg(RTM_CHANGE, nrt); |
rt_newmsg(RTM_CHANGE, rt); |
|
rtfree(rt); |
break; |
break; |
case RTM_ADD: |
case RTM_ADD: |
rt->rt_refcnt--; |
|
if (rt->rt_ifa != ifa) { |
if (rt->rt_ifa != ifa) { |
printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, |
printf("rtinit: wrong ifa (%p) was (%p)\n", ifa, |
rt->rt_ifa); |
rt->rt_ifa); |
Line 1039 rtinit(struct ifaddr *ifa, int cmd, int |
|
Line 1076 rtinit(struct ifaddr *ifa, int cmd, int |
|
if (ifa->ifa_rtrequest != NULL) |
if (ifa->ifa_rtrequest != NULL) |
ifa->ifa_rtrequest(RTM_ADD, rt, &info); |
ifa->ifa_rtrequest(RTM_ADD, rt, &info); |
} |
} |
rt_newmsg(cmd, nrt); |
rt_newmsg(cmd, rt); |
|
rtfree(rt); |
break; |
break; |
} |
} |
return error; |
return error; |
Line 1085 rt_ifa_localrequest(int cmd, struct ifad |
|
Line 1123 rt_ifa_localrequest(int cmd, struct ifad |
|
rt_replace_ifa(nrt, ifa); |
rt_replace_ifa(nrt, ifa); |
|
|
rt_newaddrmsg(cmd, ifa, e, nrt); |
rt_newaddrmsg(cmd, ifa, e, nrt); |
if (nrt) { |
if (nrt != NULL) |
if (cmd == RTM_DELETE) { |
rtfree(nrt); |
if (nrt->rt_refcnt <= 0) { |
|
/* XXX: we should free the entry ourselves. */ |
|
nrt->rt_refcnt++; |
|
rtfree(nrt); |
|
} |
|
} else { |
|
/* the cmd must be RTM_ADD here */ |
|
nrt->rt_refcnt--; |
|
} |
|
} |
|
return e; |
return e; |
} |
} |
|
|
Line 1120 rt_ifa_addlocal(struct ifaddr *ifa) |
|
Line 1149 rt_ifa_addlocal(struct ifaddr *ifa) |
|
rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL); |
rt_newaddrmsg(RTM_NEWADDR, ifa, 0, NULL); |
} |
} |
if (rt != NULL) |
if (rt != NULL) |
rt->rt_refcnt--; |
rtfree(rt); |
return e; |
return e; |
} |
} |
|
|
Line 1161 rt_ifa_remlocal(struct ifaddr *ifa, stru |
|
Line 1190 rt_ifa_remlocal(struct ifaddr *ifa, stru |
|
} else |
} else |
rt_newaddrmsg(RTM_DELADDR, ifa, 0, NULL); |
rt_newaddrmsg(RTM_DELADDR, ifa, 0, NULL); |
if (rt != NULL) |
if (rt != NULL) |
rt->rt_refcnt--; |
rtfree(rt); |
return e; |
return e; |
} |
} |
|
|