better support for multiple IPv4 addresses on a single interface.

- consider non-primary (2nd and beyond) IPv4 address as "local", and prevent
  outgoing ARP.
- for routing entries generated by ARP, make sure to set rt->rt_ifa equal to
  rt_key, to help IPv4 source address selection for traffic to myself.
PR 13311.

caveats/TODOs:
- interface routes ("connected routes" in cisco terminlogy) is tied with the
  primary (1st) IPv4 address on the interface.  should be fixed with updates
  to rt_ifinit().
- source address selection for offlink locations.  1st address tend to be used
  with the current code
  (you can configure it right by setting rt->rt_ifa accordingly).
This commit is contained in:
itojun 2001-07-04 02:29:58 +00:00
parent 89ea4732df
commit 0fec95079e
2 changed files with 50 additions and 6 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_arp.c,v 1.75 2001/06/11 06:19:50 tron Exp $ */
/* $NetBSD: if_arp.c,v 1.76 2001/07/04 02:29:58 itojun Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@ -380,6 +380,8 @@ arp_rtrequest(req, rt, info)
size_t allocsize;
struct mbuf *mold;
int s;
struct in_ifaddr *ia;
struct ifaddr *ifa;
if (!arpinit_done) {
arpinit_done = 1;
@ -491,8 +493,11 @@ arp_rtrequest(req, rt, info)
la->la_rt = rt;
rt->rt_flags |= RTF_LLINFO;
LIST_INSERT_HEAD(&llinfo_arp, la, la_list);
if (in_hosteq(SIN(rt_key(rt))->sin_addr,
(IA_SIN(rt->rt_ifa))->sin_addr)) {
INADDR_TO_IA(SIN(rt_key(rt))->sin_addr, ia);
while (ia && ia->ia_ifp != rt->rt_ifp)
NEXT_IA_WITH_SAME_ADDR(ia);
if (ia) {
/*
* This test used to be
* if (loif.if_flags & IFF_UP)
@ -503,6 +508,12 @@ arp_rtrequest(req, rt, info)
* packets they send. It is now necessary to clear
* "useloopback" and remove the route to force
* traffic out to the hardware.
*
* In 4.4BSD, the above "if" statement checked
* rt->rt_ifa against rt_key(rt). It was changed
* to the current form so that we can provide a
* better support for multiple IPv4 addresses on a
* interface.
*/
rt->rt_expire = 0;
Bcopy(LLADDR(rt->rt_ifp->if_sadl),
@ -513,6 +524,17 @@ arp_rtrequest(req, rt, info)
if (useloopback)
rt->rt_ifp = &loif[0];
#endif
/*
* make sure to set rt->rt_ifa to the interface
* address we are using, otherwise we will have trouble
* with source address selection.
*/
ifa = &ia->ia_ifa;
if (ifa != rt->rt_ifa) {
IFAFREE(rt->rt_ifa);
IFAREF(ifa);
rt->rt_ifa = ifa;
}
}
break;

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_ieee1394arp.c,v 1.4 2001/06/12 15:17:28 wiz Exp $ */
/* $NetBSD: if_ieee1394arp.c,v 1.5 2001/07/04 02:29:59 itojun Exp $ */
/*
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -160,6 +160,8 @@ ieee1394arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
sizeof(struct ieee1394_hwaddr), AF_LINK };
struct mbuf *mold;
int s;
struct in_ifaddr *ia;
struct ifaddr *ifa;
if (!arpinit_done) {
/*
@ -233,8 +235,11 @@ ieee1394arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
la->la_rt = rt;
rt->rt_flags |= RTF_LLINFO;
LIST_INSERT_HEAD(&llinfo_arp, la, la_list);
if (in_hosteq(SIN(rt_key(rt))->sin_addr,
(IA_SIN(rt->rt_ifa))->sin_addr)) {
INADDR_TO_IA(SIN(rt_key(rt))->sin_addr, ia);
while (ia && ia->ia_ifp != rt->rt_ifp)
NEXT_IA_WITH_SAME_ADDR(ia);
if (ia) {
/*
* This test used to be
* if (loif.if_flags & IFF_UP)
@ -245,6 +250,12 @@ ieee1394arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
* packets they send. It is now necessary to clear
* "useloopback" and remove the route to force
* traffic out to the hardware.
*
* In 4.4BSD, the above "if" statement checked
* rt->rt_ifa against rt_key(rt). It was changed
* to the current form so that we can provide a
* better support for multiple IPv4 address on a
* interface.
*/
rt->rt_expire = 0;
memcpy(LLADDR(SDL(gate)),
@ -254,6 +265,17 @@ ieee1394arp_rtrequest(int req, struct rtentry *rt, struct rt_addrinfo *info)
if (useloopback)
rt->rt_ifp = &loif[0];
#endif
/*
* make sure to set rt->rt_ifa to the interface
* address we are using, otherwise we will have trouble
* with source address selection.
*/
ifa = &ia->ia_ifa;
if (ifa != rt->rt_ifa) {
IFAFREE(rt->rt_ifa);
IFAREF(ifa);
rt->rt_ifa = ifa;
}
}
break;