diff options
Diffstat (limited to 'sys/netinet/in.c')
-rw-r--r-- | sys/netinet/in.c | 63 |
1 files changed, 29 insertions, 34 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 51bb470..7e9b1ed 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -56,10 +56,12 @@ __FBSDID("$FreeBSD$"); #include <net/route.h> #include <net/vnet.h> +#include <netinet/if_ether.h> #include <netinet/in.h> #include <netinet/in_var.h> #include <netinet/in_pcb.h> #include <netinet/ip_var.h> +#include <netinet/ip_carp.h> #include <netinet/igmp_var.h> #include <netinet/udp.h> #include <netinet/udp_var.h> @@ -69,17 +71,15 @@ static void in_len2mask(struct in_addr *, int); static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t, struct ifnet *, struct thread *); -static int in_addprefix(struct in_ifaddr *, int); -static int in_scrubprefix(struct in_ifaddr *, u_int); static void in_socktrim(struct sockaddr_in *); -static int in_ifinit(struct ifnet *, - struct in_ifaddr *, struct sockaddr_in *, int, int); +static int in_ifinit(struct ifnet *, struct in_ifaddr *, + struct sockaddr_in *, int, int, int); static void in_purgemaddrs(struct ifnet *); -static VNET_DEFINE(int, sameprefixcarponly); -#define V_sameprefixcarponly VNET(sameprefixcarponly) -SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, same_prefix_carp_only, CTLFLAG_RW, - &VNET_NAME(sameprefixcarponly), 0, +static VNET_DEFINE(int, nosameprefix); +#define V_nosameprefix VNET(nosameprefix) +SYSCTL_VNET_INT(_net_inet_ip, OID_AUTO, no_same_prefix, CTLFLAG_RW, + &VNET_NAME(nosameprefix), 0, "Refuse to create same prefixes on different interfaces"); VNET_DECLARE(struct inpcbinfo, ripcbinfo); @@ -517,7 +517,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, case SIOCSIFADDR: error = in_ifinit(ifp, ia, - (struct sockaddr_in *) &ifr->ifr_addr, 1, 0); + (struct sockaddr_in *) &ifr->ifr_addr, 1, 0, 0); if (error != 0 && iaIsNew) break; if (error == 0) { @@ -570,7 +570,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, } if (hostIsNew || maskIsNew) error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0, - maskIsNew); + maskIsNew, ifra->ifra_vhid); if (error != 0 && iaIsNew) break; @@ -609,6 +609,9 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, panic("in_control: unsupported ioctl"); } + if (ia->ia_ifa.ifa_carp) + (*carp_detach_p)(&ia->ia_ifa); + IF_ADDR_LOCK(ifp); /* Re-check that ia is still part of the list. */ TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { @@ -843,7 +846,7 @@ in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia, u_int flags) */ static int in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, - int scrub, int masksupplied) + int scrub, int masksupplied, int vhid) { register u_long i = ntohl(sin->sin_addr.s_addr); int flags = RTF_UP, error = 0; @@ -859,6 +862,15 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, ia, ia_hash); IN_IFADDR_WUNLOCK(); + if (vhid > 0) { + if (carp_attach_p != NULL) + error = (*carp_attach_p)(&ia->ia_ifa, vhid); + else + error = EPROTONOSUPPORT; + } + if (error) + return (error); + /* * Give the interface a chance to initialize * if this is its first address, @@ -885,11 +897,6 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, ia->ia_subnet = i & ia->ia_subnetmask; in_socktrim(&ia->ia_sockmask); /* - * XXX: carp(4) does not have interface route - */ - if (ifp->if_type == IFT_CARP) - return (0); - /* * Add route for the network. */ ia->ia_ifa.ifa_metric = ifp->if_metric; @@ -907,7 +914,7 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin, return (0); flags |= RTF_HOST; } - if ((error = in_addprefix(ia, flags)) != 0) + if (!vhid && (error = in_addprefix(ia, flags)) != 0) return (error); if (ia->ia_addr.sin_addr.s_addr == INADDR_ANY) @@ -920,7 +927,7 @@ 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)) { + if (V_useloopback && !vhid && !(ifp->if_flags & IFF_LOOPBACK)) { struct route ia_ro; bzero(&ia_ro, sizeof(ia_ro)); @@ -992,7 +999,7 @@ static void in_addralias_rtmsg(int cmd, struct in_addr *prefix, /* * Check if we have a route for the given prefix already or add one accordingly. */ -static int +int in_addprefix(struct in_ifaddr *target, int flags) { struct in_ifaddr *ia; @@ -1038,9 +1045,7 @@ in_addprefix(struct in_ifaddr *target, int flags) } else break; #endif - if (V_sameprefixcarponly && - target->ia_ifp->if_type != IFT_CARP && - ia->ia_ifp->if_type != IFT_CARP) { + if (V_nosameprefix) { IN_IFADDR_RUNLOCK(); return (EEXIST); } else { @@ -1061,14 +1066,12 @@ in_addprefix(struct in_ifaddr *target, int flags) return (error); } -extern void arp_ifscrub(struct ifnet *ifp, uint32_t addr); - /* * If there is no other address in the system that can serve a route to the * same prefix, remove the route. Hand over the route to the new address * otherwise. */ -static int +int in_scrubprefix(struct in_ifaddr *target, u_int flags) { struct in_ifaddr *ia; @@ -1156,13 +1159,8 @@ in_scrubprefix(struct in_ifaddr *target, u_int flags) * If we got a matching prefix address, move IFA_ROUTE and * the route itself to it. Make sure that routing daemons * get a heads-up. - * - * XXX: a special case for carp(4) interface - this should - * be more generally specified as an interface that - * doesn't support such action. */ - if ((ia->ia_flags & IFA_ROUTE) == 0 - && (ia->ia_ifp->if_type != IFT_CARP)) { + if ((ia->ia_flags & IFA_ROUTE) == 0) { ifa_ref(&ia->ia_ifa); IN_IFADDR_RUNLOCK(); error = rtinit(&(target->ia_ifa), (int)RTM_DELETE, @@ -1310,9 +1308,6 @@ in_purgemaddrs(struct ifnet *ifp) IN_MULTI_UNLOCK(); } -#include <net/if_dl.h> -#include <netinet/if_ether.h> - struct in_llentry { struct llentry base; struct sockaddr_in l3_addr4; |