--- /fw-bsd/src/sys/netinet6/ip6_var.h +++ /fw-bsd/src/sys/netinet6/ip6_var.h @@ -278,20 +278,22 @@ */ }; #endif #ifdef _KERNEL /* flags passed to ip6_output as last parameter */ #define IPV6_UNSPECSRC 0x01 /* allow :: as the source address */ #define IPV6_FORWARDING 0x02 /* most of IPv6 header exists */ #define IPV6_MINMTU 0x04 /* use minimum MTU (IPV6_USE_MIN_MTU) */ +#define M_FASTFWD6_OURS M_PROTO1 /* changed dst to local */ + #ifdef __NO_STRICT_ALIGNMENT #define IP6_HDR_ALIGNED_P(ip) 1 #else #define IP6_HDR_ALIGNED_P(ip) ((((intptr_t) (ip)) & 3) == 0) #endif VNET_DECLARE(struct ip6stat, ip6stat); /* statistics */ VNET_DECLARE(int, ip6_defhlim); /* default hop limit */ VNET_DECLARE(int, ip6_defmcasthlim); /* default multicast hop limit */ VNET_DECLARE(int, ip6_forwarding); /* act as router? */ --- /fw-bsd/src/sys/netinet/ipfw/ip_fw_pfil.c +++ /fw-bsd/src/sys/netinet/ipfw/ip_fw_pfil.c @@ -140,49 +140,73 @@ *m0 = args.m; KASSERT(*m0 != NULL || ipfw == IP_FW_DENY, ("%s: m0 is NULL", __func__)); /* breaking out of the switch means drop */ ret = 0; /* default return value for pass */ switch (ipfw) { case IP_FW_PASS: /* next_hop may be set by ipfw_chk */ - if (args.next_hop == NULL) + if (args.next_hop == NULL && args.next_hop6 == NULL) break; /* pass */ #ifndef IPFIREWALL_FORWARD ret = EACCES; #else { struct m_tag *fwd_tag; - /* Incoming packets should not be tagged so we do not + /* + * Incoming packets should not be tagged so we do not * m_tag_find. Outgoing packets may be tagged, so we * reuse the tag if present. */ - fwd_tag = (dir == DIR_IN) ? NULL : - m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL); - if (fwd_tag != NULL) { - m_tag_unlink(*m0, fwd_tag); - } else { - fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, - sizeof(struct sockaddr_in), M_NOWAIT); - if (fwd_tag == NULL) { - ret = EACCES; - break; /* i.e. drop */ - } + if (args.next_hop) { + fwd_tag = (dir == DIR_IN) ? NULL : + m_tag_find(*m0, PACKET_TAG_IPFORWARD, NULL); + if (fwd_tag != NULL) { + m_tag_unlink(*m0, fwd_tag); + } else { + fwd_tag = m_tag_get(PACKET_TAG_IPFORWARD, + sizeof(struct sockaddr_in), M_NOWAIT); + if (fwd_tag == NULL) { + ret = EACCES; + break; /* i.e. drop */ + } + } + bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in)); + m_tag_prepend(*m0, fwd_tag); + + if (in_localip(args.next_hop->sin_addr)) + (*m0)->m_flags |= M_FASTFWD_OURS; + } else { /* next_hop6 is not null. */ +#ifdef INET6 + fwd_tag = (dir == DIR_IN) ? NULL : + m_tag_find(*m0, PACKET_TAG_IP6FORWARD, NULL); + if (fwd_tag != NULL) + m_tag_unlink(*m0, fwd_tag); + else { + fwd_tag = m_tag_get(PACKET_TAG_IP6FORWARD, + sizeof(struct sockaddr_in6), M_NOWAIT); + if (fwd_tag == NULL) { + ret = EACCES; + break; /* i.e. drop */ + } + } + bcopy(args.next_hop6, (fwd_tag+1), + sizeof(struct sockaddr_in6)); + m_tag_prepend(*m0, fwd_tag); + + if (in6_localaddr(&args.next_hop6->sin6_addr)) + (*m0)->m_flags |= M_FASTFWD_OURS; +#endif } - bcopy(args.next_hop, (fwd_tag+1), sizeof(struct sockaddr_in)); - m_tag_prepend(*m0, fwd_tag); - - if (in_localip(args.next_hop->sin_addr)) - (*m0)->m_flags |= M_FASTFWD_OURS; } #endif break; case IP_FW_DENY: ret = EACCES; break; /* i.e. drop */ case IP_FW_DUMMYNET: ret = EACCES; --- /fw-bsd/src/sys/net/if_loop.c +++ /fw-bsd/src/sys/net/if_loop.c @@ -229,21 +229,23 @@ } #endif if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { m_freem(m); return (rt->rt_flags & RTF_BLACKHOLE ? 0 : rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); } ifp->if_opackets++; + IFX_DATA(ifp, opackets)++; ifp->if_obytes += m->m_pkthdr.len; + IFX_DATA(ifp, obytes) += m->m_pkthdr.len; /* BPF writes need to be handled specially. */ if (dst->sa_family == AF_UNSPEC) { bcopy(dst->sa_data, &af, sizeof(af)); dst->sa_family = af; } #if 1 /* XXX */ switch (dst->sa_family) { case AF_INET: @@ -357,21 +359,23 @@ case AF_APPLETALK: isr = NETISR_ATALK2; break; #endif default: printf("if_simloop: can't handle af=%d\n", af); m_freem(m); return (EAFNOSUPPORT); } ifp->if_ipackets++; + IFX_DATA(ifp, ipackets)++; ifp->if_ibytes += m->m_pkthdr.len; + IFX_DATA(ifp, ibytes) += m->m_pkthdr.len; netisr_queue(isr, m); /* mbuf is free'd on failure. */ return (0); } /* ARGSUSED */ static void lortrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) { RT_LOCK_ASSERT(rt); --- /fw-bsd/src/sys/net/if_bridge.c +++ /fw-bsd/src/sys/net/if_bridge.c @@ -93,20 +93,21 @@ #include #include #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include @@ -217,20 +218,21 @@ uint32_t sc_iflist_xcnt; /* refcount for sc_iflist */ LIST_HEAD(, bridge_iflist) sc_iflist; /* member interface list */ LIST_HEAD(, bridge_rtnode) *sc_rthash; /* our forwarding table */ LIST_HEAD(, bridge_rtnode) sc_rtlist; /* list version of above */ uint32_t sc_rthash_key; /* key for hash */ LIST_HEAD(, bridge_iflist) sc_spanlist; /* span ports list */ struct bstp_state sc_stp; /* STP state */ uint32_t sc_brtexceeded; /* # of cache drops */ struct ifnet *sc_ifaddr; /* member mac copied from */ u_char sc_defaddr[6]; /* Default MAC address */ + struct sysctl_ctx_list sc_sysctl_ctx; }; static struct mtx bridge_list_mtx; eventhandler_tag bridge_detach_cookie = NULL; int bridge_rtable_prune_period = BRIDGE_RTABLE_PRUNE_PERIOD; uma_zone_t bridge_rtnode_zone; static int bridge_clone_create(struct if_clone *, int, caddr_t); @@ -317,29 +319,33 @@ static int bridge_ioctl_sifprio(struct bridge_softc *, void *); static int bridge_ioctl_sifcost(struct bridge_softc *, void *); static int bridge_ioctl_sifmaxaddr(struct bridge_softc *, void *); static int bridge_ioctl_addspan(struct bridge_softc *, void *); static int bridge_ioctl_delspan(struct bridge_softc *, void *); static int bridge_ioctl_gbparam(struct bridge_softc *, void *); static int bridge_ioctl_grte(struct bridge_softc *, void *); static int bridge_ioctl_gifsstp(struct bridge_softc *, void *); static int bridge_ioctl_sproto(struct bridge_softc *, void *); static int bridge_ioctl_stxhc(struct bridge_softc *, void *); +static int bridge_ioctl_maclookup(struct bridge_softc *, void *); + static int bridge_pfil(struct mbuf **, struct ifnet *, struct ifnet *, int); static int bridge_ip_checkbasic(struct mbuf **mp); #ifdef INET6 static int bridge_ip6_checkbasic(struct mbuf **mp); #endif /* INET6 */ static int bridge_fragment(struct ifnet *, struct mbuf *, struct ether_header *, int, struct llc *); +static int sysctl_list_macs(SYSCTL_HANDLER_ARGS); + /* The default bridge vlan is 1 (IEEE 802.1Q-2003 Table 9-2) */ #define VLANTAGOF(_m) \ (_m->m_flags & M_VLANTAG) ? EVL_VLANOFTAG(_m->m_pkthdr.ether_vtag) : 1 static struct bstp_cb_ops bridge_ops = { .bcb_state = bridge_state_change, .bcb_rtage = bridge_rtable_expire }; SYSCTL_DECL(_net_link); @@ -458,20 +464,22 @@ { bridge_ioctl_sproto, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER }, { bridge_ioctl_stxhc, sizeof(struct ifbrparam), BC_F_COPYIN|BC_F_SUSER }, { bridge_ioctl_sifmaxaddr, sizeof(struct ifbreq), BC_F_COPYIN|BC_F_SUSER }, + { bridge_ioctl_maclookup, sizeof(struct ifbmaclookup), + BC_F_COPYIN|BC_F_COPYOUT }, }; const int bridge_control_table_size = sizeof(bridge_control_table) / sizeof(bridge_control_table[0]); LIST_HEAD(, bridge_softc) bridge_list; IFC_SIMPLE_DECLARE(bridge, 0); static int bridge_modevent(module_t mod, int type, void *data) @@ -553,20 +561,21 @@ /* * bridge_clone_create: * * Create a new bridge instance. */ static int bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params) { struct bridge_softc *sc, *sc2; struct ifnet *bifp, *ifp; + struct sysctl_oid *oid; int retry; sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); ifp = sc->sc_ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { free(sc, M_DEVBUF); return (ENOSPC); } BRIDGE_LOCK_INIT(sc); @@ -614,20 +623,28 @@ } mtx_unlock(&bridge_list_mtx); } bstp_attach(&sc->sc_stp, &bridge_ops); ether_ifattach(ifp, sc->sc_defaddr); /* Now undo some of the damage... */ ifp->if_baudrate = 0; ifp->if_type = IFT_BRIDGE; + sysctl_ctx_init(&sc->sc_sysctl_ctx); + oid = SYSCTL_ADD_NODE(&sc->sc_sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_net_link_bridge), OID_AUTO, ifp->if_xname, + CTLFLAG_RD, NULL, ""); + SYSCTL_ADD_PROC(&sc->sc_sysctl_ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "list_macs", CTLFLAG_RD|CTLTYPE_STRING, sc, 0, + sysctl_list_macs, "A", "list MACs learned by the bridge"); + mtx_lock(&bridge_list_mtx); LIST_INSERT_HEAD(&bridge_list, sc, sc_list); mtx_unlock(&bridge_list_mtx); return (0); } /* * bridge_clone_destroy: * @@ -659,20 +676,22 @@ LIST_REMOVE(sc, sc_list); mtx_unlock(&bridge_list_mtx); bstp_detach(&sc->sc_stp); ether_ifdetach(ifp); if_free_type(ifp, IFT_ETHER); /* Tear down the routing table. */ bridge_rtable_fini(sc); + sysctl_ctx_free(&sc->sc_sysctl_ctx); + BRIDGE_LOCK_DESTROY(sc); free(sc, M_DEVBUF); } /* * bridge_ioctl: * * Handle a control request from the operator. */ static int @@ -682,20 +701,21 @@ struct ifreq *ifr = (struct ifreq *)data; struct bridge_iflist *bif; struct thread *td = curthread; union { struct ifbreq ifbreq; struct ifbifconf ifbifconf; struct ifbareq ifbareq; struct ifbaconf ifbaconf; struct ifbrparam ifbrparam; struct ifbropreq ifbropreq; + struct ifbmaclookup ifbmaclookup; } args; struct ifdrv *ifd = (struct ifdrv *) data; const struct bridge_control *bc; int error = 0; switch (cmd) { case SIOCADDMULTI: case SIOCDELMULTI: break; @@ -1651,20 +1671,73 @@ return (bstp_set_protocol(&sc->sc_stp, param->ifbrp_proto)); } static int bridge_ioctl_stxhc(struct bridge_softc *sc, void *arg) { struct ifbrparam *param = arg; return (bstp_set_holdcount(&sc->sc_stp, param->ifbrp_txhc)); +} + +static int +bridge_ioctl_maclookup(struct bridge_softc *sc, void *arg) +{ + struct ifbmaclookup *lookup = arg; + struct bridge_rtnode *node; + + node = bridge_rtnode_lookup(sc, lookup->ifbm_ether, lookup->ifbm_vlan); + if (node == NULL) + return (ENOENT); + + strlcpy(lookup->ifbm_ifsname, node->brt_ifp->if_xname, IFNAMSIZ); + + return (0); +} + +static int +sysctl_list_macs(SYSCTL_HANDLER_ARGS) +{ + struct bridge_softc *sc = arg1; + struct bridge_rtnode *node; + struct sbuf s; + int error; + + error = 0; + sbuf_new(&s, NULL, PAGE_SIZE, SBUF_FIXEDLEN); + + BRIDGE_LOCK(sc); + LIST_FOREACH(node, &sc->sc_rtlist, brt_list) { + sbuf_printf(&s, "%6D on interface %s", node->brt_addr, ":", + node->brt_ifp->if_xname); + + if (node->brt_vlan != 0) + sbuf_printf(&s, " (vlan %d)", node->brt_vlan); + + sbuf_printf(&s, "\n"); + + if (sbuf_overflowed(&s)) { + error = ENOMEM; + break; + } + } + BRIDGE_UNLOCK(sc); + + if (error) + return (error); + + sbuf_finish(&s); + error = SYSCTL_OUT(req, sbuf_data(&s), sbuf_len(&s)); + sbuf_delete(&s); + + return (error); } /* * bridge_ifdetach: * * Detach an interface from a bridge. Called when a member * interface is detaching. */ static void bridge_ifdetach(void *arg __unused, struct ifnet *ifp) --- /fw-bsd/src/sys/net/rtsock.c +++ /fw-bsd/src/sys/net/rtsock.c @@ -45,24 +45,26 @@ #include #include #include #include #include #include #include #include #include +#include #include #include #include #include +#include #include #include #include #include #include #include #ifdef INET6 #include #endif @@ -995,20 +997,24 @@ case RTM_IFINFO: len = sizeof(struct if_msghdr); break; case RTM_IFANNOUNCE: case RTM_IEEE80211: len = sizeof(struct if_announcemsghdr); break; + case RTM_IFVLAN: + len = sizeof(struct ifvlan_msghdr); + break; + default: len = sizeof(struct rt_msghdr); } if (len > MCLBYTES) panic("rt_msg1"); m = m_gethdr(M_DONTWAIT, MT_DATA); if (m && len > MHLEN) { MCLGET(m, M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); @@ -1341,20 +1347,45 @@ */ void rt_ifannouncemsg(struct ifnet *ifp, int what) { struct mbuf *m; struct rt_addrinfo info; m = rt_makeifannouncemsg(ifp, RTM_IFANNOUNCE, what, &info); if (m != NULL) rt_dispatch(m, NULL); +} + +/* + * This is called to generate routing socket messages indicating + * a change in vlan interface configuration. + */ +void +rt_ifvlanmsg(struct ifnet *ifp, struct vlanreq *vlr) +{ + struct ifvlan_msghdr *ifvmh; + struct mbuf *m; + struct rt_addrinfo info; + + if (route_cb.any_count == 0) + return; + bzero((caddr_t)&info, sizeof(info)); + m = rt_msg1(RTM_IFVLAN, &info); + if (m == NULL) + return; + ifvmh = mtod(m, struct ifvlan_msghdr *); + ifvmh->ifvmh_index = ifp->if_index; + strlcpy(ifvmh->ifvmh_name, ifp->if_xname, sizeof(ifvmh->ifvmh_name)); + strlcpy(ifvmh->ifvmh_parent, vlr->vlr_parent, sizeof(ifvmh->ifvmh_parent)); + ifvmh->ifvmh_tag = vlr->vlr_tag; + rt_dispatch(m, NULL); } static void rt_dispatch(struct mbuf *m, const struct sockaddr *sa) { struct m_tag *tag; /* * Preserve the family from the sockaddr, if any, in an m_tag for * use when injecting the mbuf into the routing socket buffer from --- /fw-bsd/src/sys/net/if_gre.h +++ /fw-bsd/src/sys/net/if_gre.h @@ -33,34 +33,41 @@ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef _NET_IF_GRE_H #define _NET_IF_GRE_H +#include #include #ifdef _KERNEL #include +#endif /* _KERNEL */ + +#include +#include +#include /* * Version of the WCCP, need to be configured manually since * header for version 2 is the same but IP payload is prepended * with additional 4-bytes field. */ typedef enum { WCCP_V1 = 0, WCCP_V2 } wccp_ver_t; +#ifdef _KERNEL struct gre_softc { struct ifnet *sc_ifp; LIST_ENTRY(gre_softc) sc_list; int gre_unit; int gre_flags; u_int gre_fibnum; /* use this fib for envelopes */ struct in_addr g_src; /* source address of gre packets */ struct in_addr g_dst; /* destination address of gre packets */ struct route route; /* routing entry that determines, where a encapsulated packet should go */ @@ -70,20 +77,21 @@ int called; /* infinite recursion preventer */ uint32_t key; /* key included in outgoing GRE packets */ /* zero means none */ wccp_ver_t wccp_ver; /* version of the WCCP */ }; #define GRE2IFP(sc) ((sc)->sc_ifp) +#endif /* _KERNEL */ struct gre_h { u_int16_t flags; /* GRE flags */ u_int16_t ptype; /* protocol type of payload typically Ether protocol type*/ uint32_t options[0]; /* optional options */ /* * from here on: fields are optional, presence indicated by flags * u_int_16 checksum checksum (one-complements of GRE header @@ -160,22 +168,20 @@ struct ip mi; struct mobile_h mh; } __packed; #define MOB_H_SIZ_S (sizeof(struct mobile_h) - sizeof(u_int32_t)) #define MOB_H_SIZ_L (sizeof(struct mobile_h)) #define MOB_H_SBIT 0x0080 #define GRE_TTL 30 - -#endif /* _KERNEL */ /* * ioctls needed to manipulate the interface */ #define GRESADDRS _IOW('i', 101, struct ifreq) #define GRESADDRD _IOW('i', 102, struct ifreq) #define GREGADDRS _IOWR('i', 103, struct ifreq) #define GREGADDRD _IOWR('i', 104, struct ifreq) #define GRESPROTO _IOW('i' , 105, struct ifreq) --- /fw-bsd/src/sys/netinet/ipfw/ip_fw_sockopt.c +++ /fw-bsd/src/sys/netinet/ipfw/ip_fw_sockopt.c @@ -713,20 +713,30 @@ case O_FORWARD_IP: #ifdef IPFIREWALL_FORWARD if (cmdlen != F_INSN_SIZE(ipfw_insn_sa)) goto bad_size; goto check_action; #else return EINVAL; #endif +#ifdef INET6 + case O_FORWARD_IP6: +#ifdef IPFIREWALL_FORWARD + if (cmdlen != F_INSN_SIZE(ipfw_insn_sa6)) + goto bad_size; + goto check_action; +#else + return (EINVAL); +#endif +#endif case O_DIVERT: case O_TEE: if (ip_divert_ptr == NULL) return EINVAL; else goto check_size; case O_NETGRAPH: case O_NGTEE: if (ng_ipfw_input_p == NULL) return EINVAL; --- /fw-bsd/src/sys/net/route.h +++ /fw-bsd/src/sys/net/route.h @@ -251,20 +251,21 @@ #define RTM_OLDADD 0x9 /* caused by SIOCADDRT */ #define RTM_OLDDEL 0xa /* caused by SIOCDELRT */ #define RTM_RESOLVE 0xb /* req to resolve dst to LL addr */ #define RTM_NEWADDR 0xc /* address being added to iface */ #define RTM_DELADDR 0xd /* address being removed from iface */ #define RTM_IFINFO 0xe /* iface going up/down etc. */ #define RTM_NEWMADDR 0xf /* mcast group membership being added to if */ #define RTM_DELMADDR 0x10 /* mcast group membership being deleted */ #define RTM_IFANNOUNCE 0x11 /* iface arrival/departure */ #define RTM_IEEE80211 0x12 /* IEEE80211 wireless event */ +#define RTM_IFVLAN 0x20 /* SV: vlan configuration change */ /* * Bitmask values for rtm_inits and rmx_locks. */ #define RTV_MTU 0x1 /* init or lock _mtu */ #define RTV_HOPCOUNT 0x2 /* init or lock _hopcount */ #define RTV_EXPIRE 0x4 /* init or lock _expire */ #define RTV_RPIPE 0x8 /* init or lock _recvpipe */ #define RTV_SPIPE 0x10 /* init or lock _sendpipe */ #define RTV_SSTHRESH 0x20 /* init or lock _ssthresh */ @@ -372,24 +373,26 @@ _rt = 0; /* signal that it went away */ \ } else { \ RT_REMREF(_rt); \ /* note that _rt is still valid */ \ } \ } while (0) struct radix_node_head *rt_tables_get_rnh(int, int); struct ifmultiaddr; +struct vlanreq; void rt_ieee80211msg(struct ifnet *, int, void *, size_t); void rt_ifannouncemsg(struct ifnet *, int); void rt_ifmsg(struct ifnet *); +void rt_ifvlanmsg(struct ifnet *, struct vlanreq *); 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: * * rtalloc_ign() and rtalloc() return ro->ro_rt unlocked --- /fw-bsd/src/sys/net/bpf.c +++ /fw-bsd/src/sys/net/bpf.c @@ -42,20 +42,21 @@ #include "opt_netgraph.h" #include #include #include #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include @@ -1829,20 +1830,77 @@ #ifdef MAC if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) #endif catchpacket(d, (u_char *)m, pktlen, slen, bpf_append_mbuf, &tv); } BPFD_UNLOCK(d); } BPFIF_UNLOCK(bp); } + +/* + * Incoming linkage from device drivers, when packets are in a packet strip + */ +void +bpf_fasttap(struct bpf_if *bp, struct pkt_strip *pkt_strip_p) +{ + struct timeval tv; + struct fcd tempFcd; + struct bpf_d *d; + int i; + u_int slen; + int gottime; + + gottime = 0; + + BPFIF_LOCK(bp); + LIST_FOREACH(d, &bp->bif_dlist, bd_next) { + if (BPF_CHECK_DIRECTION(d, pkt_strip_p->rx_interface, bp->bif_ifp)) + continue; + BPFD_LOCK(d); + + /* + * Iterate over all the packets in the strip, checking each one + * against the current bpf descriptor. This means each + * descriptor only needs to be locked and unlocked once per + * strip rather than once per packet. + */ + for (i = pkt_strip_p->start; i != pkt_strip_p->end; i++) { + tempFcd = pkt_strip_p->pkt[i]; + + ++d->bd_rcount; + + /* Check the packet against the descriptor. */ + slen = bpf_filter(d->bd_rfilter, tempFcd.data, + tempFcd.fcInfo.field.dataLength, + tempFcd.fcInfo.field.dataLength); + if (slen != 0) { + d->bd_fcount++; + if (!gottime) { + microtime(&tv); + gottime = 1; + } +#ifdef MAC + if (mac_bpfdesc_check_receive(d, bp->bif_ifp) == 0) +#endif + catchpacket(d, tempFcd.data, + tempFcd.fcInfo.field.dataLength, + slen, bpf_append_bytes, &tv); + } + } + + BPFD_UNLOCK(d); + } + BPFIF_UNLOCK(bp); +} + /* * Incoming linkage from device drivers, when packet is in * an mbuf chain and to be prepended by a contiguous header. */ void bpf_mtap2(struct bpf_if *bp, void *data, u_int dlen, struct mbuf *m) { struct mbuf mb; struct bpf_d *d; --- /fw-bsd/src/sys/netinet/ip_fw.h +++ /fw-bsd/src/sys/netinet/ip_fw.h @@ -144,20 +144,21 @@ O_ACCEPT, /* none */ O_DENY, /* none */ O_REJECT, /* arg1=icmp arg (same as deny) */ O_COUNT, /* none */ O_SKIPTO, /* arg1=next rule number */ O_PIPE, /* arg1=pipe number */ O_QUEUE, /* arg1=queue number */ O_DIVERT, /* arg1=port number */ O_TEE, /* arg1=port number */ O_FORWARD_IP, /* fwd sockaddr */ + O_FORWARD_IP6, /* fwd ipv6 sockaddr */ O_FORWARD_MAC, /* fwd mac */ O_NAT, /* nope */ O_REASS, /* none */ /* * More opcodes. */ O_IPSEC, /* has ipsec history */ O_IP_SRC_LOOKUP, /* arg1=table number, u32=value */ O_IP_DST_LOOKUP, /* arg1=table number, u32=value */ @@ -279,20 +280,28 @@ struct in_addr mask; } ipfw_insn_ip; /* * This is used to forward to a given address (ip). */ typedef struct _ipfw_insn_sa { ipfw_insn o; struct sockaddr_in sa; } ipfw_insn_sa; + +/* + * This is used to forward to a given address (ipv6). + */ +typedef struct _ipfw_insn_sa6 { + ipfw_insn o; + struct sockaddr_in6 sa; +} ipfw_insn_sa6; /* * This is used for MAC addr-mask pairs. */ typedef struct _ipfw_insn_mac { ipfw_insn o; u_char addr[12]; /* dst[6] + src[6] */ u_char mask[12]; /* dst[6] + src[6] */ } ipfw_insn_mac; --- /fw-bsd/src/sys/net/if_mib.h +++ /fw-bsd/src/sys/net/if_mib.h @@ -36,32 +36,68 @@ char ifmd_name[IFNAMSIZ]; /* name of interface */ int ifmd_pcount; /* number of promiscuous listeners */ int ifmd_flags; /* interface flags */ int ifmd_snd_len; /* instantaneous length of send queue */ int ifmd_snd_maxlen; /* maximum length of send queue */ int ifmd_snd_drops; /* number of drops in send queue */ int ifmd_filler[4]; /* for future expansion */ struct if_data ifmd_data; /* generic information and statistics */ }; +struct ifxmibdata { + char ifmd_name[IFNAMSIZ]; /* name of interface */ + int ifmd_pcount; /* number of promiscuous listeners */ + int ifmd_flags; /* interface flags */ + int ifmd_snd_len; /* instantaneous length of send queue */ + int ifmd_snd_maxlen; /* maximum length of send queue */ + int ifmd_snd_drops; /* number of drops in send queue */ + struct timeval ifmd_lastchange; /* last change in the stack*/ + int ifmd_filler[2]; /* for future expansion */ + struct if_data ifmd_data; /* generic information and statistics */ + struct ifx_data ifxmd_data; /* generic 64bit statistics */ + struct rmon_data rmonmd_data; /* generic RMON statistics */ + struct sv_hw_stats hw_stats; /* Statistics counters collected by the MAC */ +}; + +#ifdef COMPAT_IA32 +struct ifxmibdata32 { + char ifmd_name[IFNAMSIZ]; /* name of interface */ + int ifmd_pcount; /* number of promiscuous listeners */ + int ifmd_flags; /* interface flags */ + int ifmd_snd_len; /* instantaneous length of send queue */ + int ifmd_snd_maxlen; /* maximum length of send queue */ + int ifmd_snd_drops; /* number of drops in send queue */ + struct timeval32 ifmd_lastchange; /* last change in the stack*/ + int ifmd_filler[2]; /* for future expansion */ + struct if_data32 ifmd_data; /* generic information and statistics */ + struct ifx_data32 ifxmd_data; /* generic 64bit statistics */ + struct rmon_data32 rmonmd_data; /* generic RMON statistics */ + struct sv_hw_stats hw_stats; /* Statistics counters collected by the MAC */ +} __packed; +#endif + /* * sysctl MIB tags at the net.link.generic level */ #define IFMIB_SYSTEM 1 /* non-interface-specific */ #define IFMIB_IFDATA 2 /* per-interface data table */ /* * MIB tags for the various net.link.generic.ifdata tables */ #define IFDATA_GENERAL 1 /* generic stats for all kinds of ifaces */ +#define IFDATA_GENERAL64BIT 4 /* generic 64bit stats for all kinds + of interfaces */ +#define IFDATA_SETNONCOUNTERS 5 /* set all the non counter vars for + an interface */ /* * MIB tags at the net.link.generic.system level */ #define IFMIB_IFCOUNT 1 /* number of interfaces configured */ /* * MIB tags as the net.link level * All of the other values are IFT_* names defined in if_types.h. */ @@ -131,21 +167,24 @@ /* Driver writers! Add your chipsets here! */ enum { dot3ChipSetAMD7990 = 1, dot3ChipSetAMD79900 = 2, dot3ChipSetAMD79C940 = 3 }; enum { dot3ChipSetIntel82586 = 1, dot3ChipSetIntel82596 = 2, - dot3ChipSetIntel82557 = 3 + dot3ChipSetIntel82557 = 3, + dot3ChipSetIntel82546 = 4, + /* this is a catch-all for hardware that hasn't been added */ + dot3ChipSetIntelUnknown = 5 }; enum { dot3ChipSetNational8390 = 1, dot3ChipSetNationalSonic = 2 }; enum { dot3ChipSetFujitsu86950 = 1 }; --- /fw-bsd/src/sys/net/if_bridgevar.h +++ /fw-bsd/src/sys/net/if_bridgevar.h @@ -108,20 +108,21 @@ #define BRDGSIFCOST 22 /* set if path cost (ifbreq) */ #define BRDGADDS 23 /* add bridge span member (ifbreq) */ #define BRDGDELS 24 /* delete bridge span member (ifbreq) */ #define BRDGPARAM 25 /* get bridge STP params (ifbropreq) */ #define BRDGGRTE 26 /* get cache drops (ifbrparam) */ #define BRDGGIFSSTP 27 /* get member STP params list * (ifbpstpconf) */ #define BRDGSPROTO 28 /* set protocol (ifbrparam) */ #define BRDGSTXHC 29 /* set tx hold count (ifbrparam) */ #define BRDGSIFAMAX 30 /* set max interface addrs (ifbreq) */ +#define BRDGMACLOOKUP 31 /* lookup learned ifx for MAC (ifbmaclookup) */ /* * Generic bridge control request. */ struct ifbreq { char ifbr_ifsname[IFNAMSIZ]; /* member if name */ uint32_t ifbr_ifsflags; /* member if flags */ uint32_t ifbr_stpflags; /* member if STP flags */ uint32_t ifbr_path_cost; /* member if STP cost */ uint8_t ifbr_portno; /* member if port number */ @@ -258,20 +259,31 @@ * Bridge STP ports list structure. */ struct ifbpstpconf { uint32_t ifbpstp_len; /* buffer size */ union { caddr_t ifbpstpu_buf; struct ifbpstpreq *ifbpstpu_req; } ifbpstp_ifbpstpu; #define ifbpstp_buf ifbpstp_ifbpstpu.ifbpstpu_buf #define ifbpstp_req ifbpstp_ifbpstpu.ifbpstpu_req +}; + +struct ifbmaclookup { + /* interface on which mac was learned */ + char ifbm_ifsname[IFNAMSIZ]; + + /* mac to look up */ + uint8_t ifbm_ether[ETHER_ADDR_LEN]; + + /* vlan to match (or 0 to ignore vlan) */ + uint16_t ifbm_vlan; }; #ifdef _KERNEL #define BRIDGE_LOCK_INIT(_sc) do { \ mtx_init(&(_sc)->sc_mtx, "if_bridge", NULL, MTX_DEF); \ cv_init(&(_sc)->sc_cv, "if_bridge_cv"); \ } while (0) #define BRIDGE_LOCK_DESTROY(_sc) do { \ mtx_destroy(&(_sc)->sc_mtx); \ --- /fw-bsd/src/sys/net/bpf.h +++ /fw-bsd/src/sys/net/bpf.h @@ -920,28 +920,32 @@ */ struct bpf_if { LIST_ENTRY(bpf_if) bif_next; /* list of all interfaces */ LIST_HEAD(, bpf_d) bif_dlist; /* descriptor list */ u_int bif_dlt; /* link layer type */ u_int bif_hdrlen; /* length of header (with padding) */ struct ifnet *bif_ifp; /* corresponding interface */ struct mtx bif_mtx; /* mutex for interface */ }; +struct pkt_strip; + void bpf_bufheld(struct bpf_d *d); int bpf_validate(const struct bpf_insn *, int); void bpf_tap(struct bpf_if *, u_char *, u_int); void bpf_mtap(struct bpf_if *, struct mbuf *); void bpf_mtap2(struct bpf_if *, void *, u_int, struct mbuf *); void bpfattach(struct ifnet *, u_int, u_int); void bpfattach2(struct ifnet *, u_int, u_int, struct bpf_if **); void bpfdetach(struct ifnet *); +void bpf_fasttap(struct bpf_if *, struct pkt_strip *); + void bpfilterattach(int); u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int); static __inline int bpf_peers_present(struct bpf_if *bpf) { if (!LIST_EMPTY(&bpf->bif_dlist)) return (1); @@ -955,20 +959,25 @@ #define BPF_MTAP(_ifp,_m) do { \ if (bpf_peers_present((_ifp)->if_bpf)) { \ M_ASSERTVALID(_m); \ bpf_mtap((_ifp)->if_bpf, (_m)); \ } \ } while (0) #define BPF_MTAP2(_ifp,_data,_dlen,_m) do { \ if (bpf_peers_present((_ifp)->if_bpf)) { \ M_ASSERTVALID(_m); \ bpf_mtap2((_ifp)->if_bpf,(_data),(_dlen),(_m)); \ + } \ +} while (0) +#define BPF_FASTTAP(_ifp,_pkt_strip_p) do { \ + if (bpf_peers_present((_ifp)->if_bpf)) { \ + bpf_fasttap((_ifp)->if_bpf, (_pkt_strip_p)); \ } \ } while (0) #endif /* * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). */ #define BPF_MEMWORDS 16 #endif /* _NET_BPF_H_ */ --- /fw-bsd/src/sys/net/ethernet.h +++ /fw-bsd/src/sys/net/ethernet.h @@ -65,20 +65,24 @@ /* * Structure of a 48-bit Ethernet address. */ struct ether_addr { u_char octet[ETHER_ADDR_LEN]; } __packed; #define ETHER_IS_MULTICAST(addr) (*(addr) & 0x01) /* is address mcast/bcast? */ +/* Is address broadcast? Inspired by netgraph/ng_bridge.c */ +#define ETHER_IS_BROADCAST(addr) (((const u_int32_t *)(addr))[0] == 0xffffffff \ + && ((const u_int16_t *)(addr))[2] == 0xffff) + /* * NOTE: 0x0000-0x05DC (0..1500) are generally IEEE 802.3 length fields. * However, there are some conflicts. */ #define ETHERTYPE_8023 0x0004 /* IEEE 802.3 packet */ /* 0x0101 .. 0x1FF Experimental */ #define ETHERTYPE_PUP 0x0200 /* Xerox PUP protocol - see 0A00 */ #define ETHERTYPE_PUPAT 0x0200 /* PUP Address Translation - see 0A01 */ #define ETHERTYPE_SPRITE 0x0500 /* ??? */ --- /fw-bsd/src/sys/netinet6/ip6_input.c +++ /fw-bsd/src/sys/netinet6/ip6_input.c @@ -698,20 +698,34 @@ ip6_sprintf(ip6bufs, &ip6->ip6_src), ip6_sprintf(ip6bufd, &ip6->ip6_dst))); if (ia6 != NULL && free_ia6 != 0) ifa_free(&ia6->ia_ifa); goto bad; } } /* + * Check for ipfw "forward" action. + */ + if (m->m_flags & M_FASTFWD6_OURS) { + /* + * Firewall or NAT changed destination to local. + * We expect ip_len and ip_off to be in host byte order. + */ + m->m_flags &= ~M_FASTFWD6_OURS; + ours = 1; + deliverifp = m->m_pkthdr.rcvif; + goto hbhcheck; + } + + /* * FAITH (Firewall Aided Internet Translator) */ if (V_ip6_keepfaith) { if (rin6.ro_rt && rin6.ro_rt->rt_ifp && rin6.ro_rt->rt_ifp->if_type == IFT_FAITH) { /* XXX do we need more sanity checks? */ ours = 1; deliverifp = rin6.ro_rt->rt_ifp; /* faith */ goto hbhcheck; } @@ -1224,56 +1238,76 @@ if ((inp->inp_socket->so_options & SO_TIMESTAMP) != 0) { struct timeval tv; microtime(&tv); *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), SCM_TIMESTAMP, SOL_SOCKET); if (*mp) mp = &(*mp)->m_next; } #endif - - if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) { - if (v4only != NULL) - *v4only = 1; - return (mp); - } - + /* + * This may be called with an IPv4 packet, for the IPv4-mapped IPv6 + * addressing. Therefore, only PKTINFO and HOPLIMIT need to be support + * for both protocols. + */ #define IS2292(inp, x, y) (((inp)->inp_flags & IN6P_RFC2292) ? (x) : (y)) /* RFC 2292 sec. 5 */ if ((inp->inp_flags & IN6P_PKTINFO) != 0) { struct in6_pktinfo pi6; - bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr)); - in6_clearscope(&pi6.ipi6_addr); /* XXX */ + if ((ip6->ip6_vfc & IPV6_VERSION_MASK) == IPV6_VERSION) { + bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, + sizeof(struct in6_addr)); + in6_clearscope(&pi6.ipi6_addr); /* XXX */ + } else { + struct ip *ip4 = mtod(m, struct ip *); + /* Convert to IPv4 mapped address format. */ + pi6.ipi6_addr.s6_addr32[0] = 0; + pi6.ipi6_addr.s6_addr32[1] = 0; + pi6.ipi6_addr.s6_addr32[2] = IPV6_ADDR_INT32_SMP; + pi6.ipi6_addr.s6_addr32[3] = ip4->ip_dst.s_addr; + } pi6.ipi6_ifindex = (m && m->m_pkthdr.rcvif) ? m->m_pkthdr.rcvif->if_index : 0; *mp = sbcreatecontrol((caddr_t) &pi6, sizeof(struct in6_pktinfo), IS2292(inp, IPV6_2292PKTINFO, IPV6_PKTINFO), IPPROTO_IPV6); if (*mp) mp = &(*mp)->m_next; } + if ((ip6->ip6_vfc & IPV6_VERSION_MASK) == IPV6_VERSION) + hlim = ip6->ip6_hlim & 0xff; + else { + struct ip *ip4 = mtod(m, struct ip *); + hlim = ip4->ip_ttl; + } + *mp = sbcreatecontrol((caddr_t) &hlim, sizeof(int), IS2292(inp, IPV6_2292HOPLIMIT, IPV6_HOPLIMIT), IPPROTO_IPV6); if (*mp) mp = &(*mp)->m_next; } - if (v4only != NULL) - *v4only = 0; + if (v4only != NULL) { + if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) + *v4only = 1; + else + *v4only = 0; + } + return (mp); } void ip6_savecontrol(struct inpcb *in6p, struct mbuf *m, struct mbuf **mp) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); int v4only = 0; mp = ip6_savecontrol_v4(in6p, m, mp, &v4only); --- /fw-bsd/src/sys/net/if.c +++ /fw-bsd/src/sys/net/if.c @@ -423,21 +423,23 @@ * Allocate a struct ifnet and an index for an interface. A layer 2 * common structure will also be allocated if an allocation routine is * registered for the passed type. */ struct ifnet * if_alloc(u_char type) { struct ifnet *ifp; u_short idx; - ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK|M_ZERO); + ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK | M_ZERO); + ifp->if_data.ifi_svmib = malloc(sizeof(struct sv_mib_data), + M_IFADDR, M_WAITOK | M_ZERO); IFNET_WLOCK(); if (ifindex_alloc_locked(&idx) != 0) { IFNET_WUNLOCK(); free(ifp, M_IFNET); return (NULL); } ifnet_setbyindex_locked(idx, IFNET_HOLD); IFNET_WUNLOCK(); ifp->if_index = idx; ifp->if_type = type; @@ -493,20 +495,21 @@ ifp->if_alloctype); #ifdef MAC mac_ifnet_destroy(ifp); #endif /* MAC */ if (ifp->if_description != NULL) free(ifp->if_description, M_IFDESCR); IF_AFDATA_DESTROY(ifp); IF_ADDR_LOCK_DESTROY(ifp); ifq_delete(&ifp->if_snd); + free(ifp->if_data.ifi_svmib, M_IFNET); free(ifp, M_IFNET); } /* * This version should only be called by intefaces that switch their type * after calling if_alloc(). if_free_type() will go away again now that we * have if_alloctype to cache the original allocation type. For now, assert * that they match, since we require that in practice. */ void @@ -612,20 +615,23 @@ ifp->if_xname); #ifdef VIMAGE ifp->if_vnet = curvnet; if (ifp->if_home_vnet == NULL) ifp->if_home_vnet = curvnet; #endif if_addgroup(ifp, IFG_ALL); + /* initialize 64-bit & RMON structs */ + IFX_DATA(ifp, linkTrapEnable) = 1; + getmicrotime(&ifp->if_lastchange); ifp->if_data.ifi_epoch = time_uptime; ifp->if_data.ifi_datalen = sizeof(struct if_data); KASSERT((ifp->if_transmit == NULL && ifp->if_qflush == NULL) || (ifp->if_transmit != NULL && ifp->if_qflush != NULL), ("transmit and qflush must both either be set or both be NULL")); if (ifp->if_transmit == NULL) { ifp->if_transmit = if_transmit; ifp->if_qflush = if_qflush; @@ -2252,21 +2258,20 @@ /* * XXX: Locking. Nothing else seems to lock if_flags, * and there are numerous other races with the * ifunit() checks not being atomic with namespace * changes (renames, vmoves, if_attach, etc). */ ifp->if_flags |= IFF_RENAMING; /* Announce the departure of the interface. */ - rt_ifannouncemsg(ifp, IFAN_DEPARTURE); EVENTHANDLER_INVOKE(ifnet_departure_event, ifp); log(LOG_INFO, "%s: changing name to '%s'\n", ifp->if_xname, new_name); strlcpy(ifp->if_xname, new_name, sizeof(ifp->if_xname)); ifa = ifp->if_addr; IFA_LOCK(ifa); sdl = (struct sockaddr_dl *)ifa->ifa_addr; namelen = strlen(new_name); @@ -2283,21 +2288,21 @@ bcopy(new_name, sdl->sdl_data, namelen); sdl->sdl_nlen = namelen; sdl = (struct sockaddr_dl *)ifa->ifa_netmask; bzero(sdl->sdl_data, onamelen); while (namelen != 0) sdl->sdl_data[--namelen] = 0xff; IFA_UNLOCK(ifa); EVENTHANDLER_INVOKE(ifnet_arrival_event, ifp); /* Announce the return of the interface. */ - rt_ifannouncemsg(ifp, IFAN_ARRIVAL); + rt_ifannouncemsg(ifp, IFAN_RENAME); ifp->if_flags &= ~IFF_RENAMING; break; #ifdef VIMAGE case SIOCSIFVNET: error = priv_check(td, PRIV_NET_SETIFVNET); if (error) return (error); error = if_vmove_loan(td, ifp, ifr->ifr_name, ifr->ifr_jid); @@ -3384,22 +3389,31 @@ IF_LOCK(ifq); if (_IF_QFULL(ifq)) { _IF_DROP(ifq); IF_UNLOCK(ifq); m_freem(m); return (0); } if (ifp != NULL) { ifp->if_obytes += m->m_pkthdr.len + adjust; - if (m->m_flags & (M_BCAST|M_MCAST)) + IFX_DATA(ifp, obytes) += m->m_pkthdr.len + adjust; + + if (m->m_flags & (M_BCAST|M_MCAST)) { ifp->if_omcasts++; + + if (m->m_flags & M_BCAST) + IFX_DATA(ifp, obcasts)++; + else + IFX_DATA(ifp, omcasts)++; + } + active = ifp->if_drv_flags & IFF_DRV_OACTIVE; } _IF_ENQUEUE(ifq, m); IF_UNLOCK(ifq); if (ifp != NULL && !active) (*(ifp)->if_start)(ifp); return (1); } void --- /fw-bsd/src/sys/net/if_media.h +++ /fw-bsd/src/sys/net/if_media.h @@ -283,20 +283,22 @@ #define IFM_GMASK 0x0ff00000 /* Global options */ /* Ethernet flow control mask */ #define IFM_ETH_FMASK (IFM_FLOW | IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE) /* * Status bits */ #define IFM_AVALID 0x00000001 /* Active bit valid */ #define IFM_ACTIVE 0x00000002 /* Interface attached to working net */ +#define IFM_LINK_PARTNER 0x00010000 /* Interface detected a link partner */ +#define IFM_BYPASS 0x00020000 /* Interface is in bypass state */ /* Mask of "status valid" bits, for ifconfig(8). */ #define IFM_STATUS_VALID IFM_AVALID /* List of "status valid" bits, for ifconfig(8). */ #define IFM_STATUS_VALID_LIST { \ IFM_AVALID, \ 0 \ } --- /fw-bsd/src/sys/netinet6/udp6_usrreq.c +++ /fw-bsd/src/sys/netinet6/udp6_usrreq.c @@ -60,20 +60,21 @@ * SUCH DAMAGE. * * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 */ #include __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_ipfw.h" #include "opt_ipsec.h" #include #include #include #include #include #include #include #include @@ -170,20 +171,23 @@ { struct mbuf *m = *mp; struct ifnet *ifp; struct ip6_hdr *ip6; struct udphdr *uh; struct inpcb *inp; struct udpcb *up; int off = *offp; int plen, ulen; struct sockaddr_in6 fromsa; +#ifdef IPFIREWALL_FORWARD + struct m_tag *fwd_tag; +#endif ifp = m->m_pkthdr.rcvif; ip6 = mtod(m, struct ip6_hdr *); if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) { /* XXX send icmp6 host/port unreach? */ m_freem(m); return (IPPROTO_DONE); } @@ -359,22 +363,55 @@ * Engage the tunneling protocol. */ (*up->u_tun_func)(m, off, last); } INP_RUNLOCK(last); return (IPPROTO_DONE); } /* * Locate pcb for datagram. */ - inp = in6_pcblookup_hash(&V_udbinfo, &ip6->ip6_src, uh->uh_sport, - &ip6->ip6_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif); +#ifdef IPFIREWALL_FORWARD + /* Grab info from PACKET_TAG_IP6FORWARD tag prepended to the chain. */ + fwd_tag = m_tag_find(m, PACKET_TAG_IP6FORWARD, NULL); + + if (fwd_tag != NULL) { + struct sockaddr_in6 *next_hop = + (struct sockaddr_in6 *)(fwd_tag + 1); + /* + * Transparently forwarded. Pretend to be the destination. + * Already got one like this? + */ + inp = in6_pcblookup_hash(&udbinfo, &ip6->ip6_src, + uh->uh_sport, &next_hop->sin6_addr, + uh->uh_dport, 1, m->m_pkthdr.rcvif); + + if (!inp) { + /* No, then it's new. */ + if (!next_hop->sin6_port) + inp = in6_pcblookup_hash(&udbinfo, + &ip6->ip6_src, uh->uh_sport, + &next_hop->sin6_addr, uh->uh_dport, + 1, m->m_pkthdr.rcvif); + else + inp = in6_pcblookup_hash(&udbinfo, + &ip6->ip6_src, uh->uh_sport, + &next_hop->sin6_addr, + ntohs(next_hop->sin6_port), + 1, m->m_pkthdr.rcvif); + } + /* Remove the tag from the packet. We don't need it anymore. */ + m_tag_delete(m, fwd_tag); + } else +#endif /* IPFIREWALL_FORWARD */ + inp = in6_pcblookup_hash(&V_udbinfo, &ip6->ip6_src, uh->uh_sport, + &ip6->ip6_dst, uh->uh_dport, 1, m->m_pkthdr.rcvif); if (inp == NULL) { if (udp_log_in_vain) { char ip6bufs[INET6_ADDRSTRLEN]; char ip6bufd[INET6_ADDRSTRLEN]; log(LOG_INFO, "Connection attempt to UDP [%s]:%d from [%s]:%d\n", ip6_sprintf(ip6bufd, &ip6->ip6_dst), ntohs(uh->uh_dport), ip6_sprintf(ip6bufs, &ip6->ip6_src), --- /fw-bsd/src/sys/net/if.h +++ /fw-bsd/src/sys/net/if.h @@ -29,21 +29,23 @@ * @(#)if.h 8.1 (Berkeley) 6/10/93 * $FreeBSD$ */ #ifndef _NET_IF_H_ #define _NET_IF_H_ #include #ifdef _KERNEL +#include #include +#include #endif #if __BSD_VISIBLE /* * does not depend on on most other systems. This * helps userland compatibility. (struct timeval ifi_lastchange) */ #ifndef _KERNEL #include #endif @@ -69,20 +71,147 @@ struct if_clonereq { int ifcr_total; /* total cloners (out) */ int ifcr_count; /* room for this many in user buffer */ char *ifcr_buffer; /* buffer for cloner names */ }; /* * Structure describing information about an interface * which may be of interest to management entities. */ +#define IF_ALIAS_LENGTH 64 +struct ifx_data { + u_int64_t ifi_ipackets; /* packets received on a interface */ + u_int64_t ifi_opackets; /* packets sent on a interface */ + u_int64_t ifi_ibytes; /* total number of octets received */ + u_int64_t ifi_obytes; /* total number of octets sent */ + u_int64_t ifi_imcasts; /* packets received via multicast */ + u_int64_t ifi_omcasts; /* packets sent via multicast */ + u_int64_t ifi_ibcasts; /* packets received via broadcast */ + u_int64_t ifi_obcasts; /* packets sent via braodcast */ + char ifi_alias[IF_ALIAS_LENGTH+1]; /* if alias string */ + u_int8_t ifi_linkTrapEnable; /* send trap flag */ +}; +#ifdef COMPAT_IA32 +struct ifx_data32 { + u_int64_t ifi_ipackets; /* packets received on a interface */ + u_int64_t ifi_opackets; /* packets sent on a interface */ + u_int64_t ifi_ibytes; /* total number of octets received */ + u_int64_t ifi_obytes; /* total number of octets sent */ + u_int64_t ifi_imcasts; /* packets received via multicast */ + u_int64_t ifi_omcasts; /* packets sent via multicast */ + u_int64_t ifi_ibcasts; /* packets received via broadcast */ + u_int64_t ifi_obcasts; /* packets sent via braodcast */ + char ifi_alias[IF_ALIAS_LENGTH+1]; /* if alias string */ + u_int8_t ifi_linkTrapEnable; /* send trap flag */ + u_int16_t pad; +} __packed; +#endif + +/* RMON Statistics as per RFC 1757 */ +struct rmon_data { + u_long etherStatsOctets; + u_long etherStatsDropEvents; + u_long etherStatsCRCAlignErrors; + u_long etherStatsUndersizePkts; + u_long etherStatsOversizePkts; + u_long etherStatsFragments; + u_long etherStatsJabbers; + u_long etherStatsCollisions; + u_long etherStatsPkts64Octets; + u_long etherStatsPkts65to127Octets; + u_long etherStatsPkts128to255Octets; + u_long etherStatsPkts256to511Octets; + u_long etherStatsPkts512to1023Octets; + u_long etherStatsPkts1024to1518Octets; + /* This doesn't belong here, but ifmib_iso_8802_3 doesn't include it for + * some reason */ + u_long etherStatsdot3StatsSymbolErrors; +}; +#ifdef COMPAT_IA32 +struct rmon_data32 { + u_int32_t etherStatsOctets; + u_int32_t etherStatsDropEvents; + u_int32_t etherStatsCRCAlignErrors; + u_int32_t etherStatsUndersizePkts; + u_int32_t etherStatsOversizePkts; + u_int32_t etherStatsFragments; + u_int32_t etherStatsJabbers; + u_int32_t etherStatsCollisions; + u_int32_t etherStatsPkts64Octets; + u_int32_t etherStatsPkts65to127Octets; + u_int32_t etherStatsPkts128to255Octets; + u_int32_t etherStatsPkts256to511Octets; + u_int32_t etherStatsPkts512to1023Octets; + u_int32_t etherStatsPkts1024to1518Octets; + /* This doesn't belong here, but ifmib_iso_8802_3 doesn't include it for + * some reason */ + u_int32_t etherStatsdot3StatsSymbolErrors; +} __packed; +#endif +struct lg_port_data { + + void (*lg_mode_enable) /* enable link cluster mode */ + (struct ifnet *); + void (*lg_mode_disable) /* disable link cluster mode */ + (struct ifnet *); + void (*lg_transmitter_enable) /* enable transmitter */ + (struct ifnet *); + void (*lg_transmitter_disable) /* disable transmitter */ + (struct ifnet *); +}; + +#define IF_DATA_AUX_MAGIC 987654321; + +struct ifx_aux_data +{ + int magic; + int last_tick; /* device polling tick */ +}; + +/* Statistics counters collected by the MAC */ +struct sv_hw_stats { + uint64_t hw_xonrxc; + uint64_t hw_xontxc; + uint64_t hw_xoffrxc; + uint64_t hw_xofftxc; +}; + +/* modeFlag and desiredModeFlag definitions */ +#define FP_FASTMODE 0x00000001 +#define FP_FULLDROP 0x00000002 + +#define GET_IF_FP(ifp) \ + (&((ifp)->if_data.ifi_svmib->fp_data)) + +#define fastpath_supported(ifp) (GET_IF_FP(ifp)->adapter_tx_fast_path != NULL) + +#define in_fast_mode(if_fp) \ + ((if_fp)->mode_flags & FP_FASTMODE) + +#define GET_IF_FP_INDEX(ifp) \ + ((ifp)->if_fp_index) + +#define IF_FP_INDEX(ifp) \ + ((ifp)->if_fp_index) + +#ifdef _KERNEL +struct sv_mib_data { + struct ifx_data ifmib; /* ifMib statistics */ + struct rmon_data rmon; /* rmon statistics */ + struct lg_port_data lg_port;/* link cluster data */ + struct ifx_aux_data aux_data; + struct if_fastpath fp_data;/* fast path data */ + struct sv_hw_stats hw_stats; /* mac stat counters */ +}; +#endif + struct if_data { /* generic interface information */ u_char ifi_type; /* ethernet, tokenring, etc */ u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */ u_char ifi_addrlen; /* media address length */ u_char ifi_hdrlen; /* media header length */ u_char ifi_link_state; /* current link state */ u_char ifi_spare_char1; /* spare byte */ u_char ifi_spare_char2; /* spare byte */ u_char ifi_datalen; /* length of this data struct */ @@ -97,22 +226,61 @@ u_long ifi_collisions; /* collisions on csma interfaces */ u_long ifi_ibytes; /* total number of octets received */ u_long ifi_obytes; /* total number of octets sent */ u_long ifi_imcasts; /* packets received via multicast */ u_long ifi_omcasts; /* packets sent via multicast */ u_long ifi_iqdrops; /* dropped on input, this interface */ u_long ifi_noproto; /* destined for unsupported protocol */ u_long ifi_hwassist; /* HW offload capabilities, see IFCAP */ time_t ifi_epoch; /* uptime at attach or stat reset */ struct timeval ifi_lastchange; /* time of last administrative change */ + struct sv_mib_data *ifi_svmib; /* SV mib and general catch-all */ }; - +#ifdef COMPAT_IA32 + +#include +#include + +struct if_data32 { + /* generic interface information */ + u_char ifi_type; /* ethernet, tokenring, etc */ + u_char ifi_physical; /* e.g., AUI, Thinnet, 10base-T, etc */ + u_char ifi_addrlen; /* media address length */ + u_char ifi_hdrlen; /* media header length */ + u_char ifi_link_state; /* current link state */ + u_char ifi_recvquota; /* polling quota for receive intrs */ + u_char ifi_xmitquota; /* polling quota for xmit intrs */ + u_char ifi_datalen; /* length of this data struct */ + u_int32_t ifi_mtu; /* maximum transmission unit */ + u_int32_t ifi_metric; /* routing metric (external only) */ + u_int32_t ifi_baudrate; /* linespeed */ + /* volatile statistics */ + u_int32_t ifi_ipackets; /* packets received on interface */ + u_int32_t ifi_ierrors; /* input errors on interface */ + u_int32_t ifi_opackets; /* packets sent on interface */ + u_int32_t ifi_oerrors; /* output errors on interface */ + u_int32_t ifi_collisions; /* collisions on csma interfaces */ + u_int32_t ifi_ibytes; /* total number of octets received */ + u_int32_t ifi_obytes; /* total number of octets sent */ + u_int32_t ifi_imcasts; /* packets received via multicast */ + u_int32_t ifi_omcasts; /* packets sent via multicast */ + u_int32_t ifi_iqdrops; /* dropped on input, this interface */ + u_int32_t ifi_noproto; /* destined for unsupported protocol */ + u_int32_t ifi_hwassist; /* HW offload capabilities */ + u_int32_t ifi_epoch; /* uptime at attach or stat reset */ +#ifdef __alpha__ + u_int ifi_timepad; /* time_t is int, not long on alpha */ +#endif + struct timeval32 ifi_lastchange; /* time of last administrative change */ + u_int32_t ifi_svmib; /* SV mib and general catch-all */ +} __packed; +#endif /*- * Interface flags are of two types: network stack owned flags, and driver * owned flags. Historically, these values were stored in the same ifnet * flags field, but with the advent of fine-grained locking, they have been * broken out such that the network stack is responsible for synchronizing * the stack-owned fields, and the device driver the device-owned fields. * Both halves can perform lockless reads of the other half's field, subject * to accepting the involved races. * * Both sets of flags come from the same number space, and should not be @@ -144,20 +312,23 @@ #define IFF_LINK1 0x2000 /* per link layer defined bit */ #define IFF_LINK2 0x4000 /* per link layer defined bit */ #define IFF_ALTPHYS IFF_LINK2 /* use alternate physical connection */ #define IFF_MULTICAST 0x8000 /* (i) supports multicast */ /* 0x10000 */ #define IFF_PPROMISC 0x20000 /* (n) user-requested promisc mode */ #define IFF_MONITOR 0x40000 /* (n) user-requested monitor mode */ #define IFF_STATICARP 0x80000 /* (n) static ARP */ #define IFF_DYING 0x200000 /* (n) interface is winding down */ #define IFF_RENAMING 0x400000 /* (n) interface is being renamed */ +#define IFF_POLLSAFE 0x20000000 /* SV: not called from interrupt */ +#define IFF_RMONCAPABLE 0x40000000 /* SV: RMON capable hardware flag */ + /* * Old names for driver flags so that user space tools can continue to use * the old (portable) names. */ #ifndef _KERNEL #define IFF_RUNNING IFF_DRV_RUNNING #define IFF_OACTIVE IFF_DRV_OACTIVE #endif @@ -277,20 +448,21 @@ u_short ifan_msglen; /* to skip over non-understood messages */ u_char ifan_version; /* future binary compatibility */ u_char ifan_type; /* message type */ u_short ifan_index; /* index for associated ifp */ char ifan_name[IFNAMSIZ]; /* if name, e.g. "en0" */ u_short ifan_what; /* what type of announcement */ }; #define IFAN_ARRIVAL 0 /* interface arrival */ #define IFAN_DEPARTURE 1 /* interface departure */ +#define IFAN_RENAME 2 /* interface rename */ /* * Buffer with length to be used in SIOCGIFDESCR/SIOCSIFDESCR requests */ struct ifreq_buffer { size_t length; void *buffer; }; /* @@ -325,21 +497,40 @@ #define ifr_jid ifr_ifru.ifru_jid /* jail/vnet */ #define ifr_metric ifr_ifru.ifru_metric /* metric */ #define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ #define ifr_phys ifr_ifru.ifru_phys /* physical wire */ #define ifr_media ifr_ifru.ifru_media /* physical media */ #define ifr_data ifr_ifru.ifru_data /* for use by interface */ #define ifr_reqcap ifr_ifru.ifru_cap[0] /* requested capabilities */ #define ifr_curcap ifr_ifru.ifru_cap[1] /* current capabilities */ #define ifr_index ifr_ifru.ifru_index /* interface index */ }; - +#ifdef COMPAT_IA32 + +struct ifreq32 { + char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + short ifru_flags[2]; + short ifru_index; + int ifru_metric; + int ifru_mtu; + int ifru_phys; + int ifru_media; + u_int32_t ifru_data; + int ifru_cap[2]; + } ifr_ifru; +} __packed; + +#endif #define _SIZEOF_ADDR_IFREQ(ifr) \ ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \ (sizeof(struct ifreq) - sizeof(struct sockaddr) + \ (ifr).ifr_addr.sa_len) : sizeof(struct ifreq)) struct ifaliasreq { char ifra_name[IFNAMSIZ]; /* if name, e.g. "en0" */ struct sockaddr ifra_addr; struct sockaddr ifra_broadaddr; struct sockaddr ifra_mask; @@ -348,28 +539,40 @@ struct ifmediareq { char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */ int ifm_current; /* current media options */ int ifm_mask; /* don't care mask */ int ifm_status; /* media status */ int ifm_active; /* active options */ int ifm_count; /* # entries in ifm_ulist array */ int *ifm_ulist; /* media words */ }; +#ifdef COMPAT_IA32 +struct ifmediareq32 { + char ifm_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + int ifm_current; /* current media options */ + int ifm_mask; /* don't care mask */ + int ifm_status; /* media status */ + int ifm_active; /* active options */ + int ifm_count; /* # entries in ifm_ulist array */ + u_int32_t ifm_ulist; /* media words */ +}; +#endif + struct ifdrv { char ifd_name[IFNAMSIZ]; /* if name, e.g. "en0" */ unsigned long ifd_cmd; size_t ifd_len; void *ifd_data; }; -/* +/* * Structure used to retrieve aux status data from interfaces. * Kernel suppliers to this interface should respect the formatting * needed by ifconfig(8): each line starts with a TAB and ends with * a newline. The canonical example to copy and paste is in if_tun.c. */ #define IFSTATMAX 800 /* 10 lines of text */ struct ifstat { char ifs_name[IFNAMSIZ]; /* if name, e.g. "en0" */ char ascii[IFSTATMAX + 1]; --- /fw-bsd/src/sys/net/if_lagg.c +++ /fw-bsd/src/sys/net/if_lagg.c --- /fw-bsd/src/sys/net/if_mib.c +++ /fw-bsd/src/sys/net/if_mib.c @@ -73,33 +73,67 @@ static int sysctl_ifdata(SYSCTL_HANDLER_ARGS) /* XXX bad syntax! */ { int *name = (int *)arg1; int error; u_int namelen = arg2; struct ifnet *ifp; struct ifmibdata ifmd; size_t dlen; char *dbuf; + struct ifxmibdata ifxmd; if (namelen != 2) return EINVAL; if (name[0] <= 0) return (ENOENT); ifp = ifnet_byindex_ref(name[0]); if (ifp == NULL) return (ENOENT); switch(name[1]) { + + case IFDATA_GENERAL64BIT: + strlcpy(ifxmd.ifmd_name, ifp->if_xname, sizeof(ifxmd.ifmd_name)); + +#define COPY(fld) ifxmd.ifmd_##fld = ifp->if_##fld + COPY(pcount); + COPY(flags); + COPY(data); +#undef COPY + ifxmd.ifxmd_data = ifp->if_data.ifi_svmib->ifmib; + ifxmd.rmonmd_data = ifp->if_data.ifi_svmib->rmon; + ifxmd.hw_stats = ifp->if_data.ifi_svmib->hw_stats; + ifxmd.ifmd_snd_len = ifp->if_snd.ifq_len; + ifxmd.ifmd_snd_maxlen = ifp->if_snd.ifq_maxlen; + ifxmd.ifmd_snd_drops = ifp->if_snd.ifq_drops; + + error = SYSCTL_OUT(req, &ifxmd, sizeof ifxmd); + if (error || !req->newptr) + return error; + + error = SYSCTL_IN(req, &ifxmd, sizeof ifxmd); + if (error) + return error; + +#define COPY(fld) ifp->if_##fld = ifmd.ifmd_##fld + COPY(data); +#undef COPY + ifp->if_data.ifi_svmib->ifmib = ifxmd.ifxmd_data; + ifp->if_data.ifi_svmib->rmon = ifxmd.rmonmd_data; + + ifp->if_snd.ifq_maxlen = ifxmd.ifmd_snd_maxlen; + ifp->if_snd.ifq_drops = ifxmd.ifmd_snd_drops; + break; case IFDATA_GENERAL: bzero(&ifmd, sizeof(ifmd)); strlcpy(ifmd.ifmd_name, ifp->if_xname, sizeof(ifmd.ifmd_name)); #define COPY(fld) ifmd.ifmd_##fld = ifp->if_##fld COPY(pcount); COPY(data); #undef COPY ifmd.ifmd_flags = ifp->if_flags | ifp->if_drv_flags; --- /fw-bsd/src/sys/netinet/ipfw/ip_fw_log.c +++ /fw-bsd/src/sys/netinet/ipfw/ip_fw_log.c @@ -283,20 +283,35 @@ dummyaddr.s_addr = sa->sa.sin_addr.s_addr; len = snprintf(SNPARGS(action2, 0), "Forward to %s", inet_ntoa(dummyaddr)); if (sa->sa.sin_port) snprintf(SNPARGS(action2, len), ":%d", sa->sa.sin_port); } break; +#ifdef INET6 + case O_FORWARD_IP6: { + char buf[INET6_ADDRSTRLEN]; + ipfw_insn_sa6 *sa = (ipfw_insn_sa6 *)cmd; + int len; + + len = snprintf(SNPARGS(action2, 0), "Forward to %s", + ip6_sprintf(buf, &sa->sa.sin6_addr)); + + if (sa->sa.sin6_port) + snprintf(SNPARGS(action2, len), ",%d", + sa->sa.sin6_port); + } + break; +#endif case O_NETGRAPH: snprintf(SNPARGS(action2, 0), "Netgraph %d", cmd->arg1); break; case O_NGTEE: snprintf(SNPARGS(action2, 0), "Ngtee %d", cmd->arg1); break; case O_NAT: action = "Nat"; --- /fw-bsd/src/sys/net/if_var.h +++ /fw-bsd/src/sys/net/if_var.h @@ -65,35 +65,37 @@ struct mbuf; struct thread; struct rtentry; struct rt_addrinfo; struct socket; struct ether_header; struct carp_if; struct ifvlantrunk; struct route; struct vnet; +struct netdump_methods; #endif #include /* get TAILQ macros */ #ifdef _KERNEL #include #include #include #include #endif /* _KERNEL */ +#include #include #define IF_DUNIT_NONE -1 #include TAILQ_HEAD(ifnethead, ifnet); /* we use TAILQs so that the order of */ TAILQ_HEAD(ifaddrhead, ifaddr); /* instantiation is preserved in the list */ TAILQ_HEAD(ifprefixhead, ifprefix); TAILQ_HEAD(ifmultihead, ifmultiaddr); @@ -192,28 +194,31 @@ struct task if_linktask; /* task for link change events */ struct mtx if_addr_mtx; /* mutex to protect address lists */ LIST_ENTRY(ifnet) if_clones; /* interfaces of a cloner */ TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */ /* protected by if_addr_mtx */ void *if_pf_kif; void *if_lagg; /* lagg glue */ u_char if_alloctype; /* if_type at time of allocation */ + fp_index_t if_fp_index; /* fastpath index this iface is assigned to */ + /* * Spare fields are added so that we can modify sensitive data * structures without changing the kernel binary interface, and must * be used with care where binary compatibility is required. */ char if_cspare[3]; char *if_description; /* interface description */ - void *if_pspare[7]; + struct netdump_methods *if_ndumpfuncs; /* netdump virtual methods */ + void *if_pspare[6]; int if_ispare[4]; }; typedef void if_init_f_t(void *); /* * XXX These aliases are terribly dangerous because they could apply * to anything. */ #define if_mtu if_data.ifi_mtu @@ -237,20 +242,35 @@ #define if_iqdrops if_data.ifi_iqdrops #define if_noproto if_data.ifi_noproto #define if_lastchange if_data.ifi_lastchange /* for compatibility with other BSDs */ #define if_addrlist if_addrhead #define if_list if_link #define if_name(ifp) ((ifp)->if_xname) /* + * ifXTable counters + */ + +#define IFX_DATA(ifp, counter) \ + ((ifp->if_data.ifi_svmib)->ifmib.ifi_##counter) +#define RMON_DATA(ifp, counter) \ + ((ifp->if_data.ifi_svmib)->rmon.etherStats##counter) +#define LG_DATA(ifp, function) \ + ((ifp->if_data.ifi_svmib)->lg_port.lg_##function) +#define AUX_DATA(ifp, x) \ + ((ifp->if_data.ifi_svmib)->aux_data.x) +#define HW_STATS_DATA(ifp, counter) \ + ((ifp->if_data.ifi_svmib)->hw_stats.hw_##counter) + +/* * Locks for address lists on the network interface. */ #define IF_ADDR_LOCK_INIT(if) mtx_init(&(if)->if_addr_mtx, \ "if_addr_mtx", NULL, MTX_DEF) #define IF_ADDR_LOCK_DESTROY(if) mtx_destroy(&(if)->if_addr_mtx) #define IF_ADDR_LOCK(if) mtx_lock(&(if)->if_addr_mtx) #define IF_ADDR_UNLOCK(if) mtx_unlock(&(if)->if_addr_mtx) #define IF_ADDR_LOCK_ASSERT(if) mtx_assert(&(if)->if_addr_mtx, MA_OWNED) /* @@ -497,22 +517,28 @@ #define IFQ_HANDOFF_ADJ(ifp, m, adj, err) \ do { \ int len; \ short mflags; \ \ len = (m)->m_pkthdr.len; \ mflags = (m)->m_flags; \ IFQ_ENQUEUE(&(ifp)->if_snd, m, err); \ if ((err) == 0) { \ (ifp)->if_obytes += len + (adj); \ - if (mflags & M_MCAST) \ + IFX_DATA((ifp), obytes) += len + (adj); \ + if (mflags & (M_MCAST|M_BCAST)) { \ (ifp)->if_omcasts++; \ + if (mflags & M_BCAST) \ + IFX_DATA((ifp), obcasts)++; \ + else \ + IFX_DATA((ifp), omcasts)++; \ + } \ if (((ifp)->if_drv_flags & IFF_DRV_OACTIVE) == 0) \ if_start(ifp); \ } \ } while (0) #define IFQ_HANDOFF(ifp, m, err) \ IFQ_HANDOFF_ADJ(ifp, m, 0, err) #define IFQ_DRV_DEQUEUE(ifq, m) \ do { \ @@ -876,29 +902,38 @@ struct ifaddr *ifa_ifwithbroadaddr(struct sockaddr *); struct ifaddr *ifa_ifwithdstaddr(struct sockaddr *); struct ifaddr *ifa_ifwithnet(struct sockaddr *, int); struct ifaddr *ifa_ifwithroute(int, struct sockaddr *, struct sockaddr *); struct ifaddr *ifa_ifwithroute_fib(int, struct sockaddr *, struct sockaddr *, u_int); struct ifaddr *ifaof_ifpforaddr(struct sockaddr *, struct ifnet *); int if_simloop(struct ifnet *ifp, struct mbuf *m, int af, int hlen); +void if_initIfXStruct(struct ifnet *); typedef void *if_com_alloc_t(u_char type, struct ifnet *ifp); typedef void if_com_free_t(void *com, u_char type); void if_register_com_alloc(u_char type, if_com_alloc_t *a, if_com_free_t *f); void if_deregister_com_alloc(u_char type); #define IF_LLADDR(ifp) \ LLADDR((struct sockaddr_dl *)((ifp)->if_addr->ifa_addr)) -#ifdef DEVICE_POLLING -enum poll_cmd { POLL_ONLY, POLL_AND_CHECK_STATUS }; +/* + * Keep enum poll_cmd and poll_handler_t specification unconditional from + * DEVICE_POLLING because other modules may be needing them as well + * (where the most notable one is netdump). + */ +enum poll_cmd { POLL_ONLY, POLL_AND_CHECK_STATUS, POLL_ENABLE_NOTIFY }; typedef int poll_handler_t(struct ifnet *ifp, enum poll_cmd cmd, int count); + +#ifdef DEVICE_POLLING int ether_poll_register(poll_handler_t *h, struct ifnet *ifp); +int ether_poll_register_locked(poll_handler_t *h, struct ifnet *ifp); int ether_poll_deregister(struct ifnet *ifp); +int ether_poll_deregister_locked(struct ifnet *ifp); #endif /* DEVICE_POLLING */ #endif /* _KERNEL */ #endif /* !_NET_IF_VAR_H_ */ --- /fw-bsd/src/sys/netinet/tcp_input.c +++ /fw-bsd/src/sys/netinet/tcp_input.c @@ -501,28 +501,68 @@ findpcb: #ifdef INVARIANTS if (ti_locked == TI_RLOCKED) INP_INFO_RLOCK_ASSERT(&V_tcbinfo); else if (ti_locked == TI_WLOCKED) INP_INFO_WLOCK_ASSERT(&V_tcbinfo); else panic("%s: findpcb ti_locked %d\n", __func__, ti_locked); #endif + if (isipv6) { +#ifdef INET6 +#ifdef IPFIREWALL_FORWARD + fwd_tag = m_tag_find(m, PACKET_TAG_IP6FORWARD, NULL); + if (fwd_tag != NULL) { + struct sockaddr_in6 *next_hop6; + + next_hop6 = (struct sockaddr_in6 *)(fwd_tag + 1); + /* + * Transparently forwarded. Pretend to be the + * destination. Already got one like this? + */ + inp = in6_pcblookup_hash(&V_tcbinfo, + &ip6->ip6_src, th->th_sport, + &ip6->ip6_dst, th->th_dport, + 0, m->m_pkthdr.rcvif); + if (!inp) { + /* It's new. Try to find the ambushing socket. */ + inp = in6_pcblookup_hash(&V_tcbinfo, + &ip6->ip6_src, th->th_sport, + &next_hop6->sin6_addr, + next_hop6->sin6_port ? + ntohs(next_hop6->sin6_port) : + th->th_dport, + INPLOOKUP_WILDCARD, + m->m_pkthdr.rcvif); + } + /* Remove the tag from the packet. We don't need it anymore. */ + m_tag_delete(m, fwd_tag); + } else +#endif /* IPFIREWALL_FORWARD */ + { + inp = in6_pcblookup_hash(&V_tcbinfo, + &ip6->ip6_src, th->th_sport, + &ip6->ip6_dst, th->th_dport, + INPLOOKUP_WILDCARD, + m->m_pkthdr.rcvif); + } +#endif /* INET6 */ + } #ifdef IPFIREWALL_FORWARD /* * Grab info from PACKET_TAG_IPFORWARD tag prepended to the chain. */ fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL); - if (fwd_tag != NULL && isipv6 == 0) { /* IPv6 support is not yet */ + if (fwd_tag != NULL) { struct sockaddr_in *next_hop; next_hop = (struct sockaddr_in *)(fwd_tag+1); /* * Transparently forwarded. Pretend to be the destination. * already got one like this? */ inp = in_pcblookup_hash(&V_tcbinfo, ip->ip_src, th->th_sport, ip->ip_dst, th->th_dport, @@ -536,34 +576,25 @@ ntohs(next_hop->sin_port) : th->th_dport, INPLOOKUP_WILDCARD, m->m_pkthdr.rcvif); } /* Remove the tag from the packet. We don't need it anymore. */ m_tag_delete(m, fwd_tag); } else #endif /* IPFIREWALL_FORWARD */ { - if (isipv6) { -#ifdef INET6 - inp = in6_pcblookup_hash(&V_tcbinfo, - &ip6->ip6_src, th->th_sport, - &ip6->ip6_dst, th->th_dport, - INPLOOKUP_WILDCARD, - m->m_pkthdr.rcvif); -#endif - } else - inp = in_pcblookup_hash(&V_tcbinfo, - ip->ip_src, th->th_sport, - ip->ip_dst, th->th_dport, - INPLOOKUP_WILDCARD, - m->m_pkthdr.rcvif); + inp = in_pcblookup_hash(&V_tcbinfo, + ip->ip_src, th->th_sport, + ip->ip_dst, th->th_dport, + INPLOOKUP_WILDCARD, + m->m_pkthdr.rcvif); } /* * If the INPCB does not exist then all data in the incoming * segment is discarded and an appropriate RST is sent back. * XXX MRT Send RST using which routing table? */ if (inp == NULL) { /* * Log communication attempts to ports that are not --- /fw-bsd/src/sys/netinet/ipfw/ip_dn_glue.c +++ /fw-bsd/src/sys/netinet/ipfw/ip_dn_glue.c @@ -96,21 +96,21 @@ /* hash table of queues onto this flow_set */ int rq_size ; /* number of slots */ int rq_elements ; /* active elements */ struct dn_flow_queue7 **rq; /* array of rq_size entries */ u_int32_t last_expired ; /* do not expire too frequently */ int backlogged ; /* #active queues for this flowset */ /* RED parameters */ -#define SCALE_RED 16 +#define SCALE_RED 12 #define SCALE(x) ( (x) << SCALE_RED ) #define SCALE_VAL(x) ( (x) >> SCALE_RED ) #define SCALE_MUL(x,y) ( ( (x) * (y) ) >> SCALE_RED ) int w_q ; /* queue weight (scaled) */ int max_th ; /* maximum threshold for queue (scaled) */ int min_th ; /* minimum threshold for queue (scaled) */ int max_p ; /* maximum value for p_b (scaled) */ u_int c_1 ; /* max_p/(max_th-min_th) (scaled) */ u_int c_2 ; /* max_p*min_th/(max_th-min_th) (scaled) */ u_int c_3 ; /* for GRED, (1-max_p)/max_th (scaled) */ --- /fw-bsd/src/sys/net/if_vlan_var.h +++ /fw-bsd/src/sys/net/if_vlan_var.h @@ -82,20 +82,35 @@ /* * Configuration structure for SIOCSETVLAN and SIOCGETVLAN ioctls. */ struct vlanreq { char vlr_parent[IFNAMSIZ]; u_short vlr_tag; }; #define SIOCSETVLAN SIOCSIFGENERIC #define SIOCGETVLAN SIOCGIFGENERIC +/* + * SV: Message format announcing a configuration change in a vlan interface. + */ +struct ifvlan_msghdr { + u_short ifvmh_msglen; /* to skip over non-understood messages */ + u_char ifvmh_version; /* future binary compatibility */ + u_char ifvmh_type; /* message type */ + u_short ifvmh_index; /* index for associated ifp */ + char ifvmh_name[IFNAMSIZ]; /* if name, e.g. "vlan0" */ + struct vlanreq ifvmh_vlr; /* the new configuration */ +}; + +#define ifvmh_parent ifvmh_vlr.vlr_parent +#define ifvmh_tag ifvmh_vlr.vlr_tag + #ifdef _KERNEL /* * Drivers that are capable of adding and removing the VLAN header * in hardware indicate they support this by marking IFCAP_VLAN_HWTAGGING * in if_capabilities. Drivers for hardware that is capable * of handling larger MTU's that may include a software-appended * VLAN header w/o lowering the normal MTU should mark IFCAP_VLAN_MTU * in if_capabilities; this notifies the VLAN code it can leave the * MTU on the vlan interface at the normal setting. */ --- /fw-bsd/src/sys/netinet/ip_dummynet.h +++ /fw-bsd/src/sys/netinet/ip_dummynet.h @@ -142,21 +142,21 @@ uint32_t sched_nr; /* the scheduler we attach to */ /* generic scheduler parameters. Leave them at -1 if unset. * Now we use 0: weight, 1: lmax, 2: priority */ int par[4]; /* RED/GRED parameters. * weight and probabilities are in the range 0..1 represented * in fixed point arithmetic with SCALE_RED decimal bits. */ -#define SCALE_RED 16 +#define SCALE_RED 12 #define SCALE(x) ( (x) << SCALE_RED ) #define SCALE_VAL(x) ( (x) >> SCALE_RED ) #define SCALE_MUL(x,y) ( ( (x) * (y) ) >> SCALE_RED ) int w_q ; /* queue weight (scaled) */ int max_th ; /* maximum threshold for queue (scaled) */ int min_th ; /* minimum threshold for queue (scaled) */ int max_p ; /* maximum value for p_b (scaled) */ }; --- /fw-bsd/src/sys/netinet/in.c +++ /fw-bsd/src/sys/netinet/in.c @@ -145,21 +145,22 @@ * Determine whether an IP address is in a reserved set of addresses * that may not be forwarded, or whether datagrams to that destination * may be forwarded. */ int in_canforward(struct in_addr in) { register u_long i = ntohl(in.s_addr); register u_long net; - if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) || IN_LINKLOCAL(i)) + /* reqst00242442: backed out to unbreak ppus on 14k and 24k */ + if (IN_EXPERIMENTAL(i) || IN_MULTICAST(i) /*|| IN_LINKLOCAL(i)*/) return (0); if (IN_CLASSA(i)) { net = i & IN_CLASSA_NET; if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT)) return (0); } return (1); } /* --- /fw-bsd/src/sys/net/if_vlan.c +++ /fw-bsd/src/sys/net/if_vlan.c @@ -57,20 +57,21 @@ #include #include #include #include #include #include #include #include #include +#include #include #define VLANNAME "vlan" #define VLAN_DEF_HWIDTH 4 #define VLAN_IFFLAGS (IFF_BROADCAST | IFF_MULTICAST) #define UP_AND_RUNNING(ifp) \ ((ifp)->if_flags & IFF_UP && (ifp)->if_drv_flags & IFF_DRV_RUNNING) LIST_HEAD(ifvlanhead, ifvlan); @@ -946,23 +947,24 @@ ifp->if_oerrors++; continue; } } /* * Send it, precisely as ether_output() would have. * We are already running at splimp. */ error = (p->if_transmit)(p, m); - if (!error) + if (!error) { ifp->if_opackets++; - else + IFX_DATA(ifp, opackets)++; + } else ifp->if_oerrors++; } } static void vlan_input(struct ifnet *ifp, struct mbuf *m) { struct ifvlantrunk *trunk = ifp->if_vlantrunk; struct ifvlan *ifv; uint16_t tag; @@ -1023,20 +1025,21 @@ if (ifv == NULL || !UP_AND_RUNNING(ifv->ifv_ifp)) { TRUNK_RUNLOCK(trunk); m_freem(m); ifp->if_noproto++; return; } TRUNK_RUNLOCK(trunk); m->m_pkthdr.rcvif = ifv->ifv_ifp; ifv->ifv_ifp->if_ipackets++; + IFX_DATA(ifv->ifv_ifp, ipackets)++; /* Pass it back through the parent's input routine. */ (*ifp->if_input)(ifv->ifv_ifp, m); } static int vlan_config(struct ifvlan *ifv, struct ifnet *p, uint16_t tag) { struct ifvlantrunk *trunk; struct ifnet *ifp; @@ -1461,41 +1464,44 @@ if (ifp->if_vnet != ifp->if_home_vnet) { error = EPERM; break; } #endif error = copyin(ifr->ifr_data, &vlr, sizeof(vlr)); if (error) break; if (vlr.vlr_parent[0] == '\0') { vlan_unconfig(ifp); + rt_ifvlanmsg(ifp, &vlr); break; } p = ifunit(vlr.vlr_parent); if (p == 0) { error = ENOENT; break; } /* * Don't let the caller set up a VLAN tag with * anything except VLID bits. + + rt_ifvlanmsg(ifp, &vlr); break; case SIOCGETVLAN: #ifdef VIMAGE if (ifp->if_vnet != ifp->if_home_vnet) { error = EPERM; break; } #endif bzero(&vlr, sizeof(vlr)); --- /fw-bsd/src/sys/net/if_ethersubr.c +++ /fw-bsd/src/sys/net/if_ethersubr.c @@ -129,23 +129,20 @@ static int ether_resolvemulti(struct ifnet *, struct sockaddr **, struct sockaddr *); #ifdef VIMAGE static void ether_reassign(struct ifnet *, struct vnet *, char *); #endif /* XXX: should be in an arp support file, not here */ MALLOC_DEFINE(M_ARPCOM, "arpcom", "802.* interface internals"); -#define ETHER_IS_BROADCAST(addr) \ - (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0) - #define senderr(e) do { error = (e); goto bad;} while (0) #if defined(INET) || defined(INET6) int ether_ipfw_chk(struct mbuf **m0, struct ifnet *dst, int shared); static VNET_DEFINE(int, ether_ipfw); #define V_ether_ipfw VNET(ether_ipfw) #endif @@ -607,24 +604,27 @@ #ifdef DIAGNOSTIC if (m->m_pkthdr.rcvif != ifp) { if_printf(ifp, "Warning, frame marked as received on %s\n", m->m_pkthdr.rcvif->if_xname); } #endif CURVNET_SET_QUIET(ifp->if_vnet); if (ETHER_IS_MULTICAST(eh->ether_dhost)) { - if (ETHER_IS_BROADCAST(eh->ether_dhost)) + if (ETHER_IS_BROADCAST(eh->ether_dhost)) { m->m_flags |= M_BCAST; - else + IFX_DATA(ifp, ibcasts)++; + } else { m->m_flags |= M_MCAST; + IFX_DATA(ifp, imcasts)++; + } ifp->if_imcasts++; } #ifdef MAC /* * Tag the mbuf with an appropriate MAC label before any other * consumers can get to it. */ mac_ifnet_create_mbuf(ifp, m); #endif @@ -638,20 +638,21 @@ * If the CRC is still on the packet, trim it off. We do this once * and once only in case we are re-entered. Nothing else on the * Ethernet receive path expects to see the FCS. */ if (m->m_flags & M_HASFCS) { m_adj(m, -ETHER_CRC_LEN); m->m_flags &= ~M_HASFCS; } ifp->if_ibytes += m->m_pkthdr.len; + IFX_DATA(ifp, ibytes) += m->m_pkthdr.len; /* Allow monitor mode to claim this frame, after stats are updated. */ if (ifp->if_flags & IFF_MONITOR) { m_freem(m); CURVNET_RESTORE(); return; } /* Handle input from a lagg(4) port */ if (ifp->if_type == IFT_IEEE8023ADLAG) { --- /fw-bsd/src/sys/netinet/ipfw/ip_fw_private.h +++ /fw-bsd/src/sys/netinet/ipfw/ip_fw_private.h @@ -79,38 +79,40 @@ /* * Arguments for calling ipfw_chk() and dummynet_io(). We put them * all into a structure because this way it is easier and more * efficient to pass variables around and extend the interface. */ struct ip_fw_args { struct mbuf *m; /* the mbuf chain */ struct ifnet *oif; /* output interface */ struct sockaddr_in *next_hop; /* forward address */ + struct sockaddr_in6 *next_hop6; /* * On return, it points to the matching rule. * On entry, rule.slot > 0 means the info is valid and * contains the the starting rule for an ipfw search. * If chain_id == chain->id && slot >0 then jump to that slot. * Otherwise, we locate the first rule >= rulenum:rule_id */ struct ipfw_rule_ref rule; /* match/restart info */ + struct sockaddr_in6 hopstore6; }; MALLOC_DECLARE(M_IPFW); /* * Hooks sometime need to know the direction of the packet * (divert, dummynet, netgraph, ...) * We use a generic definition here, with bit0-1 indicating the * direction, bit 2 indicating layer2 or 3, bit 3-4 indicating the * specific protocol --- /fw-bsd/src/sys/netinet/ip_input.c +++ /fw-bsd/src/sys/netinet/ip_input.c @@ -653,26 +653,31 @@ if (IA_SIN(ia)->sin_addr.s_addr == INADDR_ANY) { ifa_ref(ifa); IF_ADDR_UNLOCK(ifp); goto ours; } #endif } IF_ADDR_UNLOCK(ifp); ia = NULL; } + /* RFC 3927 2.7: Do not forward datagrams for 169.254.0.0/16. */ + /* reqst00242442: backed out to unbreak ppus on 14k and 24k */ +#if 0 if (IN_LINKLOCAL(ntohl(ip->ip_dst.s_addr))) { IPSTAT_INC(ips_cantforward); m_freem(m); return; } +#endif + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { if (V_ip_mrouter) { /* * If we are acting as a multicast router, all * incoming multicast packets are passed to the * kernel-level multicast forwarding function. * The packet is returned (relatively) intact; if * ip_mforward() returns a non-zero value, the packet * must be discarded, else it may be accepted below. */ --- /fw-bsd/src/sys/netinet/in.h +++ /fw-bsd/src/sys/netinet/in.h @@ -480,20 +480,23 @@ /* IPv4 Source Filter Multicast API [RFC3678] */ #define IP_ADD_SOURCE_MEMBERSHIP 70 /* join a source-specific group */ #define IP_DROP_SOURCE_MEMBERSHIP 71 /* drop a single source */ #define IP_BLOCK_SOURCE 72 /* block a source */ #define IP_UNBLOCK_SOURCE 73 /* unblock a source */ /* The following option is private; do not use it from user applications. */ #define IP_MSFILTER 74 /* set/get filter list */ +#define IP_RECVDSTPORT 78 /* receive IP dst port w/ dgram */ +#define IP_RECVSRCIF 79 /* receive src ethernet if */ + /* Protocol Independent Multicast API [RFC3678] */ #define MCAST_JOIN_GROUP 80 /* join an any-source group */ #define MCAST_LEAVE_GROUP 81 /* leave all sources for group */ #define MCAST_JOIN_SOURCE_GROUP 82 /* join a source-specific group */ #define MCAST_LEAVE_SOURCE_GROUP 83 /* leave a single source */ #define MCAST_BLOCK_SOURCE 84 /* block a source */ #define MCAST_UNBLOCK_SOURCE 85 /* unblock a source */ /* * Defaults and limits for options --- /fw-bsd/src/sys/netinet/ipfw/ip_fw2.c +++ /fw-bsd/src/sys/netinet/ipfw/ip_fw2.c @@ -2072,20 +2072,35 @@ args->next_hop = &args->hopstore; } else { args->next_hop = sa; } } retval = IP_FW_PASS; l = 0; /* exit inner loop */ done = 1; /* exit outer loop */ break; +#ifdef INET6 + case O_FORWARD_IP6: + if (args->eh) /* not valid on layer2 pkts */ + break; + if (!q || dyn_dir == MATCH_FORWARD) { + struct sockaddr_in6 *sa; + sa = &(((ipfw_insn_sa6 *)cmd)->sa); + args->next_hop6 = sa; + } + retval = IP_FW_PASS; + l = 0; /* exit inner loop */ + done = 1; /* exit outer loop */ + break; +#endif + case O_NETGRAPH: case O_NGTEE: set_match(args, f_pos, chain); args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ? tablearg : cmd->arg1; if (V_fw_one_pass) args->rule.info |= IPFW_ONEPASS; retval = (cmd->opcode == O_NETGRAPH) ? IP_FW_NETGRAPH : IP_FW_NGTEE; l = 0; /* exit inner loop */