diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/if_ether.c | 31 | ||||
-rw-r--r-- | sys/netinet/in.c | 11 | ||||
-rw-r--r-- | sys/netinet/in.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_carp.c | 107 | ||||
-rw-r--r-- | sys/netinet/ip_divert.c | 15 | ||||
-rw-r--r-- | sys/netinet/ip_fw.h | 22 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 20 | ||||
-rw-r--r-- | sys/netinet/ip_ipsec.c | 24 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 60 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 2 |
10 files changed, 178 insertions, 117 deletions
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c index 78d2f43..3a9d262 100644 --- a/sys/netinet/if_ether.c +++ b/sys/netinet/if_ether.c @@ -80,6 +80,8 @@ SYSCTL_DECL(_net_link_ether); static SYSCTL_NODE(_net_link_ether, PF_INET, inet, CTLFLAG_RW, 0, ""); static SYSCTL_NODE(_net_link_ether, PF_ARP, arp, CTLFLAG_RW, 0, ""); +static VNET_DEFINE(int, arp_carp_mac) = 0; /* default to disabled */ + /* timer values */ static VNET_DEFINE(int, arpt_keep) = (20*60); /* once resolved, good for 20 * minutes */ @@ -98,12 +100,16 @@ VNET_PCPUSTAT_SYSUNINIT(arpstat); static VNET_DEFINE(int, arp_maxhold) = 1; +#define V_arp_carp_mac VNET(arp_carp_mac) #define V_arpt_keep VNET(arpt_keep) #define V_arpt_down VNET(arpt_down) #define V_arp_maxtries VNET(arp_maxtries) #define V_arp_proxyall VNET(arp_proxyall) #define V_arp_maxhold VNET(arp_maxhold) +SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, carp_mac, CTLFLAG_RW, + &VNET_NAME(arp_carp_mac), 0, + "Send CARP mac with replies to CARP ips"); SYSCTL_VNET_INT(_net_link_ether_inet, OID_AUTO, max_age, CTLFLAG_RW, &VNET_NAME(arpt_keep), 0, "ARP entry lifetime in seconds"); @@ -909,6 +915,29 @@ reply: /* default behaviour; never reply by broadcast. */ m->m_flags &= ~(M_BCAST|M_MCAST); } +#ifdef DEV_CARP + if (V_arp_carp_mac && carp_match) { + struct ether_header *eh = (struct ether_header *) sa.sa_data; + short type = htons(ETHERTYPE_ARP); + + ah->ar_hrd = htons(ARPHRD_ETHER); + + (void)memcpy(&eh->ether_type, &type, + sizeof(eh->ether_type)); + (void)memcpy(eh->ether_dhost, ar_tha(ah), + sizeof (eh->ether_dhost)); + (void)memcpy(eh->ether_shost, enaddr, + sizeof(eh->ether_shost)); + + sa.sa_family = pseudo_AF_HDRCMPLT; + sa.sa_len = sizeof(sa); + } else { +#endif + sa.sa_family = AF_ARP; + sa.sa_len = 2; +#ifdef DEV_CARP + } +#endif (void)memcpy(ar_tpa(ah), ar_spa(ah), ah->ar_pln); (void)memcpy(ar_spa(ah), &itaddr, ah->ar_pln); ah->ar_op = htons(ARPOP_REPLY); @@ -916,8 +945,6 @@ reply: m->m_len = sizeof(*ah) + (2 * ah->ar_pln) + (2 * ah->ar_hln); m->m_pkthdr.len = m->m_len; m->m_pkthdr.rcvif = NULL; - sa.sa_family = AF_ARP; - sa.sa_len = 2; m_clrprotoflags(m); /* Avoid confusing lower layers. */ (*ifp->if_output)(ifp, m, &sa, NULL); ARPSTAT_INC(txreplies); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index b61b4b6..fde54be 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -315,6 +315,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, * Security checks before we get involved in any work. */ switch (cmd) { + case SIOCORDERIFADDR: case SIOCAIFADDR: if (td != NULL) { error = priv_check(td, PRIV_NET_ADDIFADDR); @@ -374,6 +375,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, error = 0; switch (cmd) { + case SIOCORDERIFADDR: case SIOCAIFADDR: case SIOCDIFADDR: if (ifra->ifra_addr.sin_family == AF_INET) { @@ -399,10 +401,17 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp, goto out; } } - if (cmd == SIOCDIFADDR && ia == NULL) { + if ((cmd == SIOCDIFADDR || cmd == SIOCORDERIFADDR) && ia == NULL) { error = EADDRNOTAVAIL; goto out; } + if (cmd == SIOCORDERIFADDR && ia != NULL) { + IF_ADDR_WLOCK(ifp); + TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); + TAILQ_INSERT_AFTER(&ifp->if_addrhead, TAILQ_FIRST(&ifp->if_addrhead), &ia->ia_ifa, ifa_link); + IF_ADDR_WUNLOCK(ifp); + goto out; + } if (ia == NULL) { ia = (struct in_ifaddr *) malloc(sizeof *ia, M_IFADDR, M_NOWAIT | diff --git a/sys/netinet/in.h b/sys/netinet/in.h index fa4cebe..5ec7ed7 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -702,7 +702,8 @@ int getsourcefilter(int, uint32_t, struct sockaddr *, socklen_t, #define IPCTL_FASTFORWARDING 14 /* use fast IP forwarding code */ #define IPCTL_KEEPFAITH 15 /* FAITH IPv4->IPv6 translater ctl */ #define IPCTL_GIF_TTL 16 /* default TTL for gif encap packet */ -#define IPCTL_MAXID 17 +#define IPCTL_IPSEC_INUSE 17 +#define IPCTL_MAXID 18 #endif /* __BSD_VISIBLE */ diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index c5fea16..f85a322 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -115,7 +115,6 @@ struct carp_softc { int sc_sendad_success; #define CARP_SENDAD_MIN_SUCCESS 3 - int sc_init_counter; uint64_t sc_counter; /* authentication */ @@ -143,7 +142,7 @@ struct carp_if { struct ip6_moptions cif_im6o; #endif struct ifnet *cif_ifp; - struct mtx cif_mtx; + struct rwlock cif_mtx; }; #define CARP_INET 0 @@ -247,18 +246,19 @@ SYSCTL_VNET_PCPUSTAT(_net_inet_carp, OID_AUTO, stats, struct carpstats, #define CARP_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) #define CARP_LOCK(sc) mtx_lock(&(sc)->sc_mtx) #define CARP_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) -#define CIF_LOCK_INIT(cif) mtx_init(&(cif)->cif_mtx, "carp_if", \ - NULL, MTX_DEF) -#define CIF_LOCK_DESTROY(cif) mtx_destroy(&(cif)->cif_mtx) -#define CIF_LOCK_ASSERT(cif) mtx_assert(&(cif)->cif_mtx, MA_OWNED) -#define CIF_LOCK(cif) mtx_lock(&(cif)->cif_mtx) -#define CIF_UNLOCK(cif) mtx_unlock(&(cif)->cif_mtx) +#define CIF_LOCK_INIT(cif) rw_init(&(cif)->cif_mtx, "carp_if") +#define CIF_LOCK_DESTROY(cif) rw_destroy(&(cif)->cif_mtx) +#define CIF_LOCK_ASSERT(cif) rw_assert(&(cif)->cif_mtx, MA_OWNED) +#define CIF_RLOCK(cif) rw_rlock(&(cif)->cif_mtx) +#define CIF_RUNLOCK(cif) rw_runlock(&(cif)->cif_mtx) +#define CIF_WLOCK(cif) rw_wlock(&(cif)->cif_mtx) +#define CIF_WUNLOCK(cif) rw_wunlock(&(cif)->cif_mtx) #define CIF_FREE(cif) do { \ CIF_LOCK_ASSERT(cif); \ if (TAILQ_EMPTY(&(cif)->cif_vrs)) \ carp_free_if(cif); \ else \ - CIF_UNLOCK(cif); \ + CIF_WUNLOCK(cif); \ } while (0) #define CARP_LOG(...) do { \ @@ -579,7 +579,6 @@ carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af) struct ifnet *ifp = m->m_pkthdr.rcvif; struct ifaddr *ifa; struct carp_softc *sc; - uint64_t tmp_counter; struct timeval sc_tv, ch_tv; /* verify that the VHID is valid on the receiving interface */ @@ -619,14 +618,20 @@ carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af) goto out; } - tmp_counter = ntohl(ch->carp_counter[0]); - tmp_counter = tmp_counter<<32; - tmp_counter += ntohl(ch->carp_counter[1]); - - /* XXX Replay protection goes here */ - - sc->sc_init_counter = 0; - sc->sc_counter = tmp_counter; + if (!bcmp(&sc->sc_counter, ch->carp_counter, + sizeof(ch->carp_counter))) { + /* Do not log duplicates from non simplex interfaces */ + if (sc->sc_carpdev->if_flags & IFF_SIMPLEX) { + CARPSTATS_INC(carps_badauth); + ifp->if_ierrors++; + CARP_UNLOCK(sc); + CARP_LOG("%s, replay or network loop detected.\n", + ifp->if_xname); + } else + CARP_UNLOCK(sc); + m_freem(m); + return; + } sc_tv.tv_sec = sc->sc_advbase; sc_tv.tv_usec = DEMOTE_ADVSKEW(sc) * 1000000 / 256; @@ -700,13 +705,12 @@ carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch) { struct m_tag *mtag; - if (sc->sc_init_counter) { + if (!sc->sc_counter) { /* this could also be seconds since unix epoch */ sc->sc_counter = arc4random(); sc->sc_counter = sc->sc_counter << 32; sc->sc_counter += arc4random(); - } else - sc->sc_counter++; + } ch->carp_counter[0] = htonl((sc->sc_counter>>32)&0xffffffff); ch->carp_counter[1] = htonl(sc->sc_counter&0xffffffff); @@ -772,7 +776,8 @@ carp_send_ad_error(struct carp_softc *sc, int error) char msg[sizeof(fmt) + IFNAMSIZ]; sprintf(msg, fmt, error, sc->sc_carpdev->if_xname); - carp_demote_adj(V_carp_senderr_adj, msg); + if (V_carp_senderr_adj > 0) + carp_demote_adj(V_carp_senderr_adj, msg); } sc->sc_sendad_success = 0; } else { @@ -782,7 +787,8 @@ carp_send_ad_error(struct carp_softc *sc, int error) char msg[sizeof(fmt) + IFNAMSIZ]; sprintf(msg, fmt, sc->sc_carpdev->if_xname); - carp_demote_adj(-V_carp_senderr_adj, msg); + if (V_carp_senderr_adj > 0) + carp_demote_adj(-V_carp_senderr_adj, msg); sc->sc_sendad_errors = 0; } else sc->sc_sendad_errors = 0; @@ -1117,18 +1123,17 @@ carp_forus(struct ifnet *ifp, u_char *dhost) if (ena[0] || ena[1] || ena[2] != 0x5e || ena[3] || ena[4] != 1) return (0); - CIF_LOCK(ifp->if_carp); + CIF_RLOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) { - CARP_LOCK(sc); - if (sc->sc_state == MASTER && !bcmp(dhost, LLADDR(&sc->sc_addr), - ETHER_ADDR_LEN)) { - CARP_UNLOCK(sc); - CIF_UNLOCK(ifp->if_carp); + //CARP_LOCK(sc); + if (sc->sc_state == MASTER && ena[5] == sc->sc_vhid) { + //CARP_UNLOCK(sc); + CIF_RUNLOCK(ifp->if_carp); return (1); } - CARP_UNLOCK(sc); + //CARP_UNLOCK(sc); } - CIF_UNLOCK(ifp->if_carp); + CIF_RUNLOCK(ifp->if_carp); return (0); } @@ -1485,9 +1490,9 @@ carp_alloc(struct ifnet *ifp) sc = malloc(sizeof(*sc), M_CARP, M_WAITOK|M_ZERO); + sc->sc_counter = 0; sc->sc_advbase = CARP_DFLTINTV; sc->sc_vhid = -1; /* required setting */ - sc->sc_init_counter = 1; sc->sc_state = INIT; sc->sc_ifasiz = sizeof(struct ifaddr *); @@ -1503,9 +1508,9 @@ carp_alloc(struct ifnet *ifp) #endif callout_init_mtx(&sc->sc_ad_tmo, &sc->sc_mtx, CALLOUT_RETURNUNLOCKED); - CIF_LOCK(cif); + CIF_WLOCK(cif); TAILQ_INSERT_TAIL(&cif->cif_vrs, sc, sc_list); - CIF_UNLOCK(cif); + CIF_WUNLOCK(cif); mtx_lock(&carp_mtx); LIST_INSERT_HEAD(&carp_list, sc, sc_next); @@ -1669,11 +1674,11 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td) } if (ifp->if_carp) { - CIF_LOCK(ifp->if_carp); + CIF_RLOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == carpr.carpr_vhid) break; - CIF_UNLOCK(ifp->if_carp); + CIF_RUNLOCK(ifp->if_carp); } if (sc == NULL) { sc = carp_alloc(ifp); @@ -1747,11 +1752,11 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td) priveleged = (priv_check(td, PRIV_NETINET_CARP) == 0); if (carpr.carpr_vhid != 0) { - CIF_LOCK(ifp->if_carp); + CIF_RLOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == carpr.carpr_vhid) break; - CIF_UNLOCK(ifp->if_carp); + CIF_RUNLOCK(ifp->if_carp); if (sc == NULL) { error = ENOENT; break; @@ -1762,12 +1767,12 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td) int i, count; count = 0; - CIF_LOCK(ifp->if_carp); + CIF_RLOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) count++; if (count > carpr.carpr_count) { - CIF_UNLOCK(ifp->if_carp); + CIF_RUNLOCK(ifp->if_carp); error = EMSGSIZE; break; } @@ -1779,12 +1784,12 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td) error = copyout(&carpr, ifr->ifr_data + (i * sizeof(carpr)), sizeof(carpr)); if (error) { - CIF_UNLOCK(ifp->if_carp); + CIF_RUNLOCK(ifp->if_carp); break; } i++; } - CIF_UNLOCK(ifp->if_carp); + CIF_RUNLOCK(ifp->if_carp); } break; } @@ -1833,12 +1838,12 @@ carp_attach(struct ifaddr *ifa, int vhid) return (EPROTOTYPE); } - CIF_LOCK(cif); + CIF_WLOCK(cif); IFNET_FOREACH_CARP(ifp, sc) if (sc->sc_vhid == vhid) break; if (sc == NULL) { - CIF_UNLOCK(cif); + CIF_WUNLOCK(cif); return (ENOENT); } @@ -1846,7 +1851,7 @@ carp_attach(struct ifaddr *ifa, int vhid) if (ifa->ifa_carp->sc_vhid != vhid) carp_detach_locked(ifa); else { - CIF_UNLOCK(cif); + CIF_WUNLOCK(cif); return (0); } } @@ -1891,7 +1896,7 @@ carp_attach(struct ifaddr *ifa, int vhid) carp_sc_state(sc); CARP_UNLOCK(sc); - CIF_UNLOCK(cif); + CIF_WUNLOCK(cif); return (0); } @@ -1902,7 +1907,7 @@ carp_detach(struct ifaddr *ifa) struct ifnet *ifp = ifa->ifa_ifp; struct carp_if *cif = ifp->if_carp; - CIF_LOCK(cif); + CIF_WLOCK(cif); carp_detach_locked(ifa); CIF_FREE(cif); } @@ -1984,13 +1989,13 @@ carp_linkstate(struct ifnet *ifp) { struct carp_softc *sc; - CIF_LOCK(ifp->if_carp); + CIF_RLOCK(ifp->if_carp); IFNET_FOREACH_CARP(ifp, sc) { CARP_LOCK(sc); carp_sc_state(sc); CARP_UNLOCK(sc); } - CIF_UNLOCK(ifp->if_carp); + CIF_RUNLOCK(ifp->if_carp); } static void @@ -2025,9 +2030,11 @@ carp_sc_state(struct carp_softc *sc) static void carp_demote_adj(int adj, char *reason) { + if (adj == 0) + return; atomic_add_int(&V_carp_demotion, adj); CARP_LOG("demoted by %d to %d (%s)\n", adj, V_carp_demotion, reason); - taskqueue_enqueue(taskqueue_swi, &carp_sendall_task); + taskqueue_enqueue(taskqueue_thread, &carp_sendall_task); } static int diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index e698035..b74d60d 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -267,8 +267,7 @@ divert_packet(struct mbuf *m, int incoming) * this iface name will come along for the ride. * (see div_output for the other half of this.) */ - strlcpy(divsrc.sin_zero, m->m_pkthdr.rcvif->if_xname, - sizeof(divsrc.sin_zero)); + *((u_short *)divsrc.sin_zero) = m->m_pkthdr.rcvif->if_index; } /* Put packet on socket queue, if any */ @@ -342,7 +341,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, /* Loopback avoidance and state recovery */ if (sin) { - int i; + u_short idx; /* set the starting point. We provide a non-zero slot, * but a non_matching chain_id to skip that info and use @@ -350,7 +349,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, */ dt->slot = 1; /* dummy, chain_id is invalid */ dt->chain_id = 0; - dt->rulenum = sin->sin_port+1; /* host format ? */ + dt->rulenum = sin->sin_port; /* host format ? */ dt->rule_id = 0; /* * Find receive interface with the given name, stuffed @@ -358,10 +357,9 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, * The name is user supplied data so don't trust its size * or that it is zero terminated. */ - for (i = 0; i < sizeof(sin->sin_zero) && sin->sin_zero[i]; i++) - ; - if ( i > 0 && i < sizeof(sin->sin_zero)) - m->m_pkthdr.rcvif = ifunit(sin->sin_zero); + idx = *((u_short *)sin->sin_zero); + if ( idx > 0 ) + m->m_pkthdr.rcvif = ifnet_byindex(idx); } /* Reinject packet into the system as incoming or outgoing */ @@ -832,5 +830,4 @@ static moduledata_t ipdivertmod = { }; DECLARE_MODULE(ipdivert, ipdivertmod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY); -MODULE_DEPEND(ipdivert, ipfw, 2, 2, 2); MODULE_VERSION(ipdivert, 1); diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index dae8cc0..188057d 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -65,7 +65,8 @@ /* IP_FW3 header/opcodes */ typedef struct _ip_fw3_opheader { uint16_t opcode; /* Operation opcode */ - uint16_t reserved[3]; /* Align to 64-bit boundary */ + uint16_t ctxid; + uint16_t reserved[2]; /* Align to 64-bit boundary */ } ip_fw3_opheader; @@ -74,6 +75,14 @@ typedef struct _ip_fw3_opheader { #define IP_FW_TABLE_XDEL 87 /* delete entry */ #define IP_FW_TABLE_XGETSIZE 88 /* get table size */ #define IP_FW_TABLE_XLIST 89 /* list table contents */ +#define IP_FW_TABLE_XLISTENTRY 90 /* list one table entry contents */ +#define IP_FW_TABLE_XZEROENTRY 91 /* zero one table entry stats */ +#define IP_FW_CTX_GET 92 +#define IP_FW_CTX_ADD 93 +#define IP_FW_CTX_DEL 94 +#define IP_FW_CTX_SET 95 +#define IP_FW_CTX_ADDMEMBER 96 +#define IP_FW_CTX_DELMEMBER 97 /* * The kernel representation of ipfw rules is made of a list of @@ -600,11 +609,16 @@ struct _ipfw_dyn_rule { #define IPFW_TABLE_CIDR 1 /* Table for holding IPv4/IPv6 prefixes */ #define IPFW_TABLE_INTERFACE 2 /* Table for holding interface names */ -#define IPFW_TABLE_MAXTYPE 2 /* Maximum valid number */ +#define IPFW_TABLE_MIX 3 /* Table for holding IPv4/mac entries */ +#define IPFW_TABLE_MAC 4 /* Table for holding mac entries */ +#define IPFW_TABLE_MAXTYPE 5 /* Maximum valid number */ typedef struct _ipfw_table_entry { in_addr_t addr; /* network address */ u_int32_t value; /* value */ + uint64_t mac_addr; + uint64_t bytes; + uint64_t packets; u_int16_t tbl; /* table number */ u_int8_t masklen; /* mask length */ } ipfw_table_entry; @@ -616,6 +630,10 @@ typedef struct _ipfw_table_xentry { uint16_t tbl; /* table number */ uint16_t flags; /* record flags */ uint32_t value; /* value */ + uint32_t timestamp; + uint64_t mac_addr; + uint64_t bytes; + uint64_t packets; union { /* Longest field needs to be aligned by 4-byte boundary */ struct in6_addr addr6; /* IPv6 address */ diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 2dc080f..0d6ade9 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -97,6 +97,11 @@ SYSCTL_VNET_INT(_net_inet_ip, IPCTL_FORWARDING, forwarding, CTLFLAG_RW, &VNET_NAME(ipforwarding), 0, "Enable IP forwarding between interfaces"); +VNET_DEFINE(int, ipipsec_in_use); +SYSCTL_VNET_INT(_net_inet_ip, IPCTL_IPSEC_INUSE, ipsec_in_use, CTLFLAG_RW, + &VNET_NAME(ipipsec_in_use), 0, + "Enable IPSec processing of packets"); + static VNET_DEFINE(int, ipsendredirects) = 1; /* XXX */ #define V_ipsendredirects VNET(ipsendredirects) SYSCTL_VNET_INT(_net_inet_ip, IPCTL_SENDREDIRECTS, redirect, CTLFLAG_RW, @@ -297,6 +302,9 @@ ip_init(void) if ((i = pfil_head_register(&V_inet_pfil_hook)) != 0) printf("%s: WARNING: unable to register pfil hook, " "error %d\n", __func__, i); + else + pfil_head_export_sysctl(&V_inet_pfil_hook, + SYSCTL_STATIC_CHILDREN(_net_inet_ip)); /* Skip initialization of globals for non-default instances. */ if (!IS_DEFAULT_VNET(curvnet)) @@ -468,7 +476,7 @@ tooshort: /* * Bypass packet filtering for packets previously handled by IPsec. */ - if (ip_ipsec_filtertunnel(m)) + if (V_ipipsec_in_use && ip_ipsec_filtertunnel(m)) goto passin; #endif /* IPSEC */ @@ -499,8 +507,7 @@ tooshort: goto ours; } if (m->m_flags & M_IP_NEXTHOP) { - dchg = (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL); - if (dchg != 0) { + if (m_tag_find(m, PACKET_TAG_IPFORWARD, NULL) != NULL) { /* * Directly ship the packet on. This allows * forwarding packets originally destined to us @@ -675,7 +682,7 @@ passin: m_freem(m); } else { #ifdef IPSEC - if (ip_ipsec_fwd(m)) + if (V_ipipsec_in_use && ip_ipsec_fwd(m)) goto bad; #endif /* IPSEC */ ip_forward(m, dchg); @@ -722,7 +729,7 @@ ours: * note that we do not visit this with protocols with pcb layer * code - like udp/tcp/raw ip. */ - if (ip_ipsec_input(m)) + if (V_ipipsec_in_use && ip_ipsec_input(m)) goto bad; #endif /* IPSEC */ @@ -1521,7 +1528,8 @@ ip_forward(struct mbuf *m, int srcrt) * If IPsec is configured for this path, * override any possibly mtu value set by ip_output. */ - mtu = ip_ipsec_mtu(mcopy, mtu); + if (V_ipipsec_in_use) + mtu = ip_ipsec_mtu(mcopy, mtu); #endif /* IPSEC */ /* * If the MTU was set before make sure we are below the diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c index 1550018..098e78a 100644 --- a/sys/netinet/ip_ipsec.c +++ b/sys/netinet/ip_ipsec.c @@ -113,19 +113,11 @@ int ip_ipsec_fwd(struct mbuf *m) { #ifdef IPSEC - struct m_tag *mtag; - struct tdb_ident *tdbi; struct secpolicy *sp; int error; - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)(mtag + 1); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); - } else { - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } + sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, + IP_FORWARDING, &error); if (sp == NULL) { /* NB: can happen if error */ /*XXX error stat???*/ DPRINTF(("ip_input: no SP for forwarding\n")); /*XXX*/ @@ -157,8 +149,6 @@ ip_ipsec_input(struct mbuf *m) { #ifdef IPSEC struct ip *ip = mtod(m, struct ip *); - struct m_tag *mtag; - struct tdb_ident *tdbi; struct secpolicy *sp; int error; /* @@ -173,14 +163,8 @@ ip_ipsec_input(struct mbuf *m) * set during AH, ESP, etc. input handling, before the * packet is returned to the ip input queue for delivery. */ - mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL); - if (mtag != NULL) { - tdbi = (struct tdb_ident *)(mtag + 1); - sp = ipsec_getpolicy(tdbi, IPSEC_DIR_INBOUND); - } else { - sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, - IP_FORWARDING, &error); - } + sp = ipsec_getpolicybyaddr(m, IPSEC_DIR_INBOUND, + IP_FORWARDING, &error); if (sp != NULL) { /* * Check security policy against packet attributes. diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 954785d..aee6834 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -123,7 +123,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct ifnet *ifp = NULL; /* keep compiler happy */ struct mbuf *m0; int hlen = sizeof (struct ip); - int mtu; + int mtu = 0; int n; /* scratchpad */ int error = 0; struct sockaddr_in *dst; @@ -136,9 +136,8 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct in_addr odst; struct m_tag *fwd_tag = NULL; int have_ia_ref; -#ifdef IPSEC - int no_route_but_check_spd = 0; -#endif + int no_route_but_check = 0; + M_ASSERTPKTHDR(m); if (inp != NULL) { @@ -292,10 +291,11 @@ again: * There is no route for this packet, but it is * possible that a matching SPD entry exists. */ - no_route_but_check_spd = 1; mtu = 0; /* Silence GCC warning. */ - goto sendit; #endif + no_route_but_check = 1; + goto sendit; + IPSTAT_INC(ips_noroute); error = EHOSTUNREACH; goto bad; @@ -482,37 +482,45 @@ again: sendit: #ifdef IPSEC - switch(ip_ipsec_output(&m, inp, &flags, &error)) { - case 1: - goto bad; - case -1: - goto done; - case 0: - default: - break; /* Continue with packet processing. */ - } - /* - * Check if there was a route for this packet; return error if not. - */ - if (no_route_but_check_spd) { - IPSTAT_INC(ips_noroute); - error = EHOSTUNREACH; - goto bad; + if (V_ipipsec_in_use) { + switch(ip_ipsec_output(&m, inp, &flags, &error)) { + case 1: + goto bad; + case -1: + goto done; + case 0: + default: + break; /* Continue with packet processing. */ + } + /* Update variables that are affected by ipsec4_output(). */ + ip = mtod(m, struct ip *); + hlen = ip->ip_hl << 2; } - /* Update variables that are affected by ipsec4_output(). */ - ip = mtod(m, struct ip *); - hlen = ip->ip_hl << 2; #endif /* IPSEC */ /* Jump over all PFIL processing if hooks are not active. */ - if (!PFIL_HOOKED(&V_inet_pfil_hook)) + if (!PFIL_HOOKED(&V_inet_pfil_hook)) { + if (no_route_but_check) { + IPSTAT_INC(ips_noroute); + error = EHOSTUNREACH; + goto bad; + } goto passout; + } + + if (ifp == NULL) + ifp = V_loif; /* Run through list of hooks for output packets. */ odst.s_addr = ip->ip_dst.s_addr; error = pfil_run_hooks(&V_inet_pfil_hook, &m, ifp, PFIL_OUT, inp); if (error != 0 || m == NULL) goto done; + if (no_route_but_check) { + IPSTAT_INC(ips_noroute); + error = EHOSTUNREACH; + goto bad; + } ip = mtod(m, struct ip *); diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index b2251ac..de08849 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -176,6 +176,7 @@ struct sockopt; VNET_DECLARE(u_short, ip_id); /* ip packet ctr, for ids */ VNET_DECLARE(int, ip_defttl); /* default IP ttl */ VNET_DECLARE(int, ipforwarding); /* ip forwarding */ +VNET_DECLARE(int, ipipsec_in_use); #ifdef IPSTEALTH VNET_DECLARE(int, ipstealth); /* stealth forwarding */ #endif @@ -191,6 +192,7 @@ extern struct pr_usrreqs rip_usrreqs; #define V_ip_id VNET(ip_id) #define V_ip_defttl VNET(ip_defttl) #define V_ipforwarding VNET(ipforwarding) +#define V_ipipsec_in_use VNET(ipipsec_in_use) #ifdef IPSTEALTH #define V_ipstealth VNET(ipstealth) #endif |