61#include <sys/kernel.h>
63#include <sys/malloc.h>
67#include <sys/random.h>
68#include <sys/rmlock.h>
69#include <sys/sockio.h>
70#include <sys/socket.h>
71#include <sys/sysctl.h>
72#include <sys/syslog.h>
73#include <sys/libkern.h>
76#include <net/if_var.h>
77#include <net/if_types.h>
79#include <net/netisr.h>
83#include <netinet/in.h>
90#ifdef NG_SEPARATE_MALLOC
93#define M_NETGRAPH_IFACE M_NETGRAPH
96static SYSCTL_NODE(_net_graph, OID_AUTO, iface, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
97 "Point to point netgraph interface");
99#define V_ng_iface_max_nest VNET(ng_iface_max_nest)
100SYSCTL_INT(_net_graph_iface, OID_AUTO, max_nesting, CTLFLAG_VNET | CTLFLAG_RW,
101 &VNET_NAME(ng_iface_max_nest), 0,
"Max nested tunnels");
115#define NUM_FAMILIES nitems(gFamilies)
127#define PRIV_RLOCK(priv, t) rm_rlock(&priv->lock, t)
128#define PRIV_RUNLOCK(priv, t) rm_runlock(&priv->lock, t)
129#define PRIV_WLOCK(priv) rm_wlock(&priv->lock)
130#define PRIV_WUNLOCK(priv) rm_wunlock(&priv->lock)
136 const struct sockaddr *dst,
struct route *ro);
138 struct mbuf *m, sa_family_t family);
142static void ng_iface_print_ioctl(
struct ifnet *
ifp,
int cmd, caddr_t
data);
209#define V_ng_iface_unit VNET(ng_iface_unit)
241 if (
priv->hooks[k] == hook)
283 struct ifreq *
const ifr = (
struct ifreq *)
data;
287 ng_iface_print_ioctl(ifp, command,
data);
292 ifp->if_flags |= IFF_UP;
293 ifp->if_drv_flags |= IFF_DRV_RUNNING;
294 ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE);
305 if (ifr->ifr_flags & IFF_UP) {
306 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
307 ifp->if_drv_flags &= ~(IFF_DRV_OACTIVE);
308 ifp->if_drv_flags |= IFF_DRV_RUNNING;
311 if (ifp->if_drv_flags & IFF_DRV_RUNNING)
312 ifp->if_drv_flags &= ~(IFF_DRV_RUNNING |
323 ifp->if_mtu = ifr->ifr_mtu;
350 const struct sockaddr *dst,
struct route *ro)
356 if (!((ifp->if_flags & IFF_UP) &&
357 (ifp->if_drv_flags & IFF_DRV_RUNNING))) {
371 if (dst->sa_family == AF_UNSPEC)
372 bcopy(dst->sa_data, &af,
sizeof(af));
374 af = RO_GET_FAMILY(ro, dst);
379 if (ALTQ_IS_ENABLED(&ifp->if_snd)) {
380 M_PREPEND(m,
sizeof(sa_family_t), M_NOWAIT);
382 if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
385 *(sa_family_t *)m->m_data = af;
386 error = (ifp->if_transmit)(ifp, m);
402 KASSERT(ALTQ_IS_ENABLED(&ifp->if_snd), (
"%s without ALTQ", __func__));
405 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
408 sa = *mtod(m, sa_family_t *);
409 m_adj(m,
sizeof(sa_family_t));
421 KASSERT(family != AF_UNSPEC, (
"%s: family=AF_UNSPEC", __func__));
422 if (bpf_peers_present(ifp->if_bpf)) {
423 int32_t family4 = (int32_t)family;
424 bpf_mtap2(ifp->if_bpf, &family4,
sizeof(family4), m);
436 struct rm_priotracker priv_tracker;
446 log(LOG_WARNING,
"%s: can't handle af%d\n", ifp->if_xname, sa);
447 return (EAFNOSUPPORT);
451 len = m->m_pkthdr.len;
470 if_inc_counter(ifp, IFCOUNTER_OBYTES, len);
471 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
483ng_iface_print_ioctl(
struct ifnet *ifp,
int command, caddr_t
data)
487 switch (command & IOC_DIRMASK) {
503 log(LOG_DEBUG,
"%s: %s('%c', %d, char[%d])\n",
508 IOCPARM_LEN(command));
527 ifp = if_alloc(IFT_PROPVIRTUAL);
533 rm_init(&
priv->lock,
"ng_iface private rmlock");
536 ifp->if_softc =
priv;
552 ifp->if_flags = (IFF_SIMPLEX|IFF_POINTOPOINT|IFF_NOARP|IFF_MULTICAST);
553 ifp->if_type = IFT_PROPVIRTUAL;
556 ifp->if_baudrate = 64000;
559 IFQ_SET_READY(&ifp->if_snd);
563 log(LOG_WARNING,
"%s: can't acquire netgraph name\n",
568 bpfattach(ifp, DLT_NULL,
sizeof(u_int32_t));
585 return (EPFNOSUPPORT);
588 if (*hookptr != NULL) {
606 struct ifnet *
const ifp =
priv->ifp;
621 strlcpy(resp->
data, ifp->if_xname, IFNAMSIZ);
628 if ((ifp->if_flags & IFF_UP) != 0)
634 ifp->if_flags |= IFF_POINTOPOINT;
635 ifp->if_flags &= ~IFF_BROADCAST;
638 ifp->if_flags &= ~IFF_POINTOPOINT;
639 ifp->if_flags |= IFF_BROADCAST;
651 *((uint32_t *)resp->
data) =
priv->ifp->if_index;
662 if_link_state_change(ifp, LINK_STATE_UP);
665 if_link_state_change(ifp, LINK_STATE_DOWN);
688 struct ifnet *
const ifp =
priv->ifp;
689 struct epoch_tracker et;
696 KASSERT(
iffam != NULL, (
"%s: iffam", __func__));
698 if ((ifp->if_flags & IFF_UP) == 0) {
704 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
705 if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len);
708 m->m_pkthdr.rcvif = ifp;
727 return (EAFNOSUPPORT);
729 random_harvest_queue(m,
sizeof(*m), RANDOM_NET_NG);
730 M_SETFIB(m, ifp->if_fib);
731 CURVNET_SET(ifp->if_vnet);
733 netisr_dispatch(isr, m);
751 CURVNET_SET_QUIET(
priv->ifp->if_vnet);
752 bpfdetach(
priv->ifp);
753 if_detach(
priv->ifp);
758 rm_destroy(&
priv->lock);
776 panic(
"%s", __func__);
#define NG_OUTBOUND_THREAD_UNREF()
#define NG_HOOK_NODE(hook)
#define NG_HOOK_SET_TO_INBOUND(hook)
#define NG_HOOK_UNREF(hook)
#define NG_HOOK_HI_STACK(hook)
int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook)
int ng_disconnect_t(hook_p hook)
#define NG_NODE_SET_PRIVATE(node, val)
#define NG_RESPOND_MSG(error, here, item, resp)
#define NG_NODE_UNREF(node)
#define NG_OUTBOUND_THREAD_REF()
#define NG_SEND_DATA_ONLY(error, hook, m)
#define NG_HOOK_REF(hook)
int ng_rcvdata_t(hook_p hook, item_p item)
int ng_shutdown_t(node_p node)
#define NG_FREE_ITEM(item)
int ng_name_node(node_p node, const char *name)
int ng_constructor_t(node_p node)
#define NGI_GET_MSG(i, m)
#define NG_NODE_PRIVATE(node)
int ng_newhook_t(node_p node, hook_p hook, const char *name)
MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node")
const struct iffam * iffam_p
static iffam_p get_iffam_from_af(sa_family_t family)
static int ng_iface_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
#define V_ng_iface_max_nest
static const struct iffam gFamilies[]
VNET_DEFINE_STATIC(int, ng_iface_max_nest)
static const struct ng_cmdlist ng_iface_cmds[]
#define PRIV_RLOCK(priv, t)
static ng_shutdown_t ng_iface_shutdown
static hook_p * get_hook_from_iffam(priv_p priv, iffam_p iffam)
static int ng_iface_send(struct ifnet *ifp, struct mbuf *m, sa_family_t sa)
static int ng_iface_mod_event(module_t, int, void *)
static void ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, sa_family_t family)
static ng_rcvmsg_t ng_iface_rcvmsg
static ng_disconnect_t ng_iface_disconnect
struct ng_iface_private * priv_p
static iffam_p get_iffam_from_hook(priv_p priv, hook_p hook)
static ng_newhook_t ng_iface_newhook
static struct ng_type typestruct
static int ng_iface_output(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst, struct route *ro)
static ng_constructor_t ng_iface_constructor
VNET_SYSUNINIT(vnet_ng_iface_uninit, SI_SUB_INIT_IF, SI_ORDER_ANY, vnet_ng_iface_uninit, NULL)
#define PRIV_WUNLOCK(priv)
static void vnet_ng_iface_init(const void *unused)
SYSCTL_INT(_net_graph_iface, OID_AUTO, max_nesting, CTLFLAG_VNET|CTLFLAG_RW, &VNET_NAME(ng_iface_max_nest), 0, "Max nested tunnels")
#define PRIV_RUNLOCK(priv, t)
static SYSCTL_NODE(_net_graph, OID_AUTO, iface, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "Point to point netgraph interface")
static void vnet_ng_iface_uninit(const void *unused)
static ng_rcvdata_t ng_iface_rcvdata
NETGRAPH_INIT(iface, &typestruct)
VNET_SYSINIT(vnet_ng_iface_init, SI_SUB_PSEUDO, SI_ORDER_ANY, vnet_ng_iface_init, NULL)
static void ng_iface_start(struct ifnet *ifp)
static iffam_p get_iffam_from_name(const char *name)
#define NG_IFACE_HOOK_INET6
#define NG_IFACE_MTU_DEFAULT
#define NG_IFACE_NODE_TYPE
#define NG_IFACE_HOOK_INET
#define NG_IFACE_IFACE_NAME
#define NG_MKRESPONSE(rsp, msg, len, how)
const struct ng_parse_type ng_parse_string_type
const struct ng_parse_type ng_parse_uint32_type
hook_p hooks[NUM_FAMILIES]
struct ng_mesg::ng_msghdr header