summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/net/if_llatbl.c4
-rw-r--r--sys/net/if_llatbl.h2
-rw-r--r--sys/net/if_var.h2
-rw-r--r--sys/net/route.c4
-rw-r--r--sys/net/route.h1
-rw-r--r--sys/net/rtsock.c22
-rw-r--r--sys/netinet/in.c52
-rw-r--r--sys/netinet6/in6.c16
8 files changed, 86 insertions, 17 deletions
diff --git a/sys/net/if_llatbl.c b/sys/net/if_llatbl.c
index 4991c81..5992f6d 100644
--- a/sys/net/if_llatbl.c
+++ b/sys/net/if_llatbl.c
@@ -274,7 +274,9 @@ lla_rt_output(struct rt_msghdr *rtm, struct rt_addrinfo *info)
#ifdef INET
if (dst->sa_family == AF_INET &&
((struct sockaddr_inarp *)dst)->sin_other != 0) {
- struct rtentry *rt = rtalloc1(dst, 0, 0);
+ struct rtentry *rt;
+ ((struct sockaddr_inarp *)dst)->sin_other = 0;
+ rt = rtalloc1(dst, 0, 0);
if (rt == NULL || !(rt->rt_flags & RTF_HOST)) {
log(LOG_INFO, "%s: RTM_ADD publish "
"(proxy only) is invalid\n",
diff --git a/sys/net/if_llatbl.h b/sys/net/if_llatbl.h
index f54c78a..21357eb 100644
--- a/sys/net/if_llatbl.h
+++ b/sys/net/if_llatbl.h
@@ -159,7 +159,7 @@ struct lltable {
const struct sockaddr *mask);
struct llentry * (*llt_lookup)(struct lltable *, u_int flags,
const struct sockaddr *l3addr);
- int (*llt_rtcheck)(struct ifnet *,
+ int (*llt_rtcheck)(struct ifnet *, u_int flags,
const struct sockaddr *);
int (*llt_dump)(struct lltable *,
struct sysctl_req *);
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 519e6aa..148d72c 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -710,6 +710,7 @@ struct ifaddr {
struct mtx ifa_mtx;
};
#define IFA_ROUTE RTF_UP /* route installed */
+#define IFA_RTSELF RTF_HOST /* loopback route to self installed */
/* for compatibility with other BSDs */
#define ifa_list ifa_link
@@ -843,6 +844,7 @@ void if_ref(struct ifnet *);
void if_rele(struct ifnet *);
int if_setlladdr(struct ifnet *, const u_char *, int);
void if_up(struct ifnet *);
+/*void ifinit(void);*/ /* declared in systm.h for main() */
int ifioctl(struct socket *, u_long, caddr_t, struct thread *);
int ifpromisc(struct ifnet *, int);
struct ifnet *ifunit(const char *);
diff --git a/sys/net/route.c b/sys/net/route.c
index 027772b..a938c9c 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -98,8 +98,6 @@ VNET_DEFINE(struct rtstat, rtstat);
#define V_rttrash VNET(rttrash)
#define V_rtstat VNET(rtstat)
-static void rt_maskedcopy(struct sockaddr *,
- struct sockaddr *, struct sockaddr *);
/* compare two sockaddr structures */
#define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
@@ -1322,7 +1320,7 @@ rt_setgate(struct rtentry *rt, struct sockaddr *dst, struct sockaddr *gate)
return (0);
}
-static void
+void
rt_maskedcopy(struct sockaddr *src, struct sockaddr *dst, struct sockaddr *netmask)
{
register u_char *cp1 = (u_char *)src;
diff --git a/sys/net/route.h b/sys/net/route.h
index 9a0bc63..a8ae867 100644
--- a/sys/net/route.h
+++ b/sys/net/route.h
@@ -384,6 +384,7 @@ void rt_missmsg(int, struct rt_addrinfo *, int, int);
void rt_newaddrmsg(int, struct ifaddr *, int, struct rtentry *);
void rt_newmaddrmsg(int, struct ifmultiaddr *);
int rt_setgate(struct rtentry *, struct sockaddr *, struct sockaddr *);
+void rt_maskedcopy(struct sockaddr *, struct sockaddr *, struct sockaddr *);
/*
* Note the following locking behavior:
diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c
index a0677ec..df4f9ae 100644
--- a/sys/net/rtsock.c
+++ b/sys/net/rtsock.c
@@ -60,6 +60,7 @@
#include <net/vnet.h>
#include <netinet/in.h>
+#include <netinet/if_ether.h>
#ifdef INET6
#include <netinet6/scope6_var.h>
#endif
@@ -622,6 +623,27 @@ route_output(struct mbuf *m, struct socket *so)
}
}
#endif
+ /*
+ * If performing proxied L2 entry insertion, and
+ * the actual PPP host entry is found, perform
+ * another search to retrieve the prefix route of
+ * the local end point of the PPP link.
+ */
+ if ((rtm->rtm_flags & RTF_ANNOUNCE) &&
+ (rt->rt_ifp->if_flags & IFF_POINTOPOINT)) {
+ struct sockaddr laddr;
+ rt_maskedcopy(rt->rt_ifa->ifa_addr,
+ &laddr,
+ rt->rt_ifa->ifa_netmask);
+ /*
+ * refactor rt and no lock operation necessary
+ */
+ rt = (struct rtentry *)rnh->rnh_matchaddr(&laddr, rnh);
+ if (rt == NULL) {
+ RADIX_NODE_HEAD_RUNLOCK(rnh);
+ senderr(ESRCH);
+ }
+ }
RT_LOCK(rt);
RT_ADDREF(rt);
RADIX_NODE_HEAD_RUNLOCK(rnh);
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 09f2f44..c5317e5 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -924,9 +924,25 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
/*
* add a loopback route to self
*/
- if (V_useloopback && !(ifp->if_flags & IFF_LOOPBACK))
- error = ifa_add_loopback_route((struct ifaddr *)ia,
+ if (V_useloopback && !(ifp->if_flags & IFF_LOOPBACK)) {
+ struct route ia_ro;
+
+ bzero(&ia_ro, sizeof(ia_ro));
+ *((struct sockaddr_in *)(&ia_ro.ro_dst)) = ia->ia_addr;
+ rtalloc_ign_fib(&ia_ro, 0, 0);
+ if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
+ (ia_ro.ro_rt->rt_ifp == V_loif)) {
+ RT_LOCK(ia_ro.ro_rt);
+ RT_ADDREF(ia_ro.ro_rt);
+ RTFREE_LOCKED(ia_ro.ro_rt);
+ } else
+ error = ifa_add_loopback_route((struct ifaddr *)ia,
(struct sockaddr *)&ia->ia_addr);
+ if (error == 0)
+ ia->ia_flags |= IFA_RTSELF;
+ if (ia_ro.ro_rt != NULL)
+ RTFREE(ia_ro.ro_rt);
+ }
return (error);
}
@@ -1043,7 +1059,7 @@ in_scrubprefix(struct in_ifaddr *target)
{
struct in_ifaddr *ia;
struct in_addr prefix, mask, p;
- int error;
+ int error = 0;
struct sockaddr_in prefix0, mask0;
/*
@@ -1057,9 +1073,28 @@ in_scrubprefix(struct in_ifaddr *target)
* deletion is unconditional.
*/
if ((target->ia_addr.sin_addr.s_addr != INADDR_ANY) &&
- !(target->ia_ifp->if_flags & IFF_LOOPBACK)) {
- error = ifa_del_loopback_route((struct ifaddr *)target,
+ !(target->ia_ifp->if_flags & IFF_LOOPBACK) &&
+ (target->ia_flags & IFA_RTSELF)) {
+ struct route ia_ro;
+ int freeit = 0;
+
+ bzero(&ia_ro, sizeof(ia_ro));
+ *((struct sockaddr_in *)(&ia_ro.ro_dst)) = target->ia_addr;
+ rtalloc_ign_fib(&ia_ro, 0, 0);
+ if ((ia_ro.ro_rt != NULL) && (ia_ro.ro_rt->rt_ifp != NULL) &&
+ (ia_ro.ro_rt->rt_ifp == V_loif)) {
+ RT_LOCK(ia_ro.ro_rt);
+ if (ia_ro.ro_rt->rt_refcnt <= 1)
+ freeit = 1;
+ else
+ RT_REMREF(ia_ro.ro_rt);
+ RTFREE_LOCKED(ia_ro.ro_rt);
+ }
+ if (freeit)
+ error = ifa_del_loopback_route((struct ifaddr *)target,
(struct sockaddr *)&target->ia_addr);
+ if (error == 0)
+ target->ia_flags &= ~IFA_RTSELF;
/* remove arp cache */
arp_ifscrub(target->ia_ifp, IA_SIN(target)->sin_addr.s_addr);
}
@@ -1317,7 +1352,7 @@ in_lltable_prefix_free(struct lltable *llt,
static int
-in_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
+in_lltable_rtcheck(struct ifnet *ifp, u_int flags, const struct sockaddr *l3addr)
{
struct rtentry *rt;
@@ -1326,7 +1361,8 @@ in_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
/* XXX rtalloc1 should take a const param */
rt = rtalloc1(__DECONST(struct sockaddr *, l3addr), 0, 0);
- if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) || rt->rt_ifp != ifp) {
+ if (rt == NULL || (rt->rt_flags & RTF_GATEWAY) ||
+ ((rt->rt_ifp != ifp) && !(flags & LLE_PUB))) {
#ifdef DIAGNOSTIC
log(LOG_INFO, "IPv4 address: \"%s\" is not on the network\n",
inet_ntoa(((const struct sockaddr_in *)l3addr)->sin_addr));
@@ -1378,7 +1414,7 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add
* verify this.
*/
if (!(flags & LLE_IFADDR) &&
- in_lltable_rtcheck(ifp, l3addr) != 0)
+ in_lltable_rtcheck(ifp, flags, l3addr) != 0)
goto done;
lle = in_lltable_new(l3addr, flags);
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 7254c4d..c839efd 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1200,8 +1200,12 @@ in6_purgeaddr(struct ifaddr *ifa)
* The check for the current setting of "nd6_useloopback"
* is not needed.
*/
- error = ifa_del_loopback_route((struct ifaddr *)ia,
- (struct sockaddr *)&ia->ia_addr);
+ if (ia->ia_flags & IFA_RTSELF) {
+ error = ifa_del_loopback_route((struct ifaddr *)ia,
+ (struct sockaddr *)&ia->ia_addr);
+ if (error == 0)
+ ia->ia_flags &= ~IFA_RTSELF;
+ }
/* stop DAD processing */
nd6_dad_stop(ifa);
@@ -1762,6 +1766,8 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
|| (ifp->if_flags & IFF_LOOPBACK))) {
error = ifa_add_loopback_route((struct ifaddr *)ia,
(struct sockaddr *)&ia->ia_addr);
+ if (error == 0)
+ ia->ia_flags |= IFA_RTSELF;
}
/* Add ownaddr as loopback rtentry, if necessary (ex. on p2p link). */
@@ -2347,7 +2353,9 @@ in6_lltable_prefix_free(struct lltable *llt,
}
static int
-in6_lltable_rtcheck(struct ifnet *ifp, const struct sockaddr *l3addr)
+in6_lltable_rtcheck(struct ifnet *ifp,
+ u_int flags,
+ const struct sockaddr *l3addr)
{
struct rtentry *rt;
char ip6buf[INET6_ADDRSTRLEN];
@@ -2415,7 +2423,7 @@ in6_lltable_lookup(struct lltable *llt, u_int flags,
* verify this.
*/
if (!(flags & LLE_IFADDR) &&
- in6_lltable_rtcheck(ifp, l3addr) != 0)
+ in6_lltable_rtcheck(ifp, flags, l3addr) != 0)
return NULL;
lle = in6_lltable_new(l3addr, flags);
OpenPOWER on IntegriCloud