summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArchie Cobbs <archie@FreeBSD.org>2000-04-19 21:28:03 +0000
committerArchie Cobbs <archie@FreeBSD.org>2000-04-19 21:28:03 +0000
commitae6c5a5c27ce72711801651af6ad056c9491bff0 (patch)
tree309062987d9341eada8cea804cd03b03fa55e7aa
parent8750a3a8c1fc609b0dc8be1f4d586cbb2e6c947b (diff)
Notes
-rw-r--r--sys/modules/netgraph/iface/Makefile26
-rw-r--r--sys/modules/netgraph/iface/ng_iface.883
-rw-r--r--sys/netgraph/ng_iface.c387
-rw-r--r--sys/netgraph/ng_iface.h8
4 files changed, 269 insertions, 235 deletions
diff --git a/sys/modules/netgraph/iface/Makefile b/sys/modules/netgraph/iface/Makefile
index cc5cc1ec310f..23a067d168ed 100644
--- a/sys/modules/netgraph/iface/Makefile
+++ b/sys/modules/netgraph/iface/Makefile
@@ -2,32 +2,8 @@
# $Whistle: Makefile,v 1.2 1999/01/19 19:39:21 archie Exp $
KMOD= ng_iface
-SRCS= ng_iface.c opt_inet.h opt_atalk.h opt_ipx.h
+SRCS= ng_iface.c
MAN8= ng_iface.8
KMODDEPS= netgraph
-IFACE_INET?= 1 # 0/1 - requires INET configured in kernel
-IFACE_NETATALK?= 0 # 0/1 - requires NETATALK configured in kernel
-IFACE_IPX?= 0 # 0/1 - requires IPX configured in kernel
-
-CFLAGS+= ${PROTOS}
-
-opt_inet.h:
- touch opt_inet.h
-.if ${IFACE_INET} > 0
- echo "#define INET 1" > opt_inet.h
-.endif
-
-opt_atalk.h:
- touch opt_atalk.h
-.if ${IFACE_NETATALK} > 0
- echo "#define NETATALK ${IFACE_NETATALK}" > opt_atalk.h
-.endif
-
-opt_ipx.h:
- touch opt_ipx.h
-.if ${IFACE_IPX} > 0
- echo "#define IPX ${IFACE_IPX}" > opt_ipx.h
-.endif
-
.include <bsd.kmod.mk>
diff --git a/sys/modules/netgraph/iface/ng_iface.8 b/sys/modules/netgraph/iface/ng_iface.8
index 40c6f8812b1e..d56ead9d1e85 100644
--- a/sys/modules/netgraph/iface/ng_iface.8
+++ b/sys/modules/netgraph/iface/ng_iface.8
@@ -47,39 +47,55 @@
An
.Nm iface
node is both a netgraph node and a system networking interface. When an
-.Nm
-node is created, a new point-to-point interface appears which is accessible via
+.Nm iface
+node is created, a new interface appears which is accessible via
.Xr ifconfig 8 .
-The new interfaces are named
+.Nm Iface
+node interfaces are named
.Dv ng0 ,
.Dv ng1 ,
-etc. The node is assigned the same name as its interface, unless the name
+etc.
+When a node is shutdown, the corresponding interface is removed
+and the interface name becomes available for reuse by future
+.Nm iface
+nodes; new nodes always take the first unused interface.
+The node itself is assigned the same name as its interface, unless the name
already exists, in which case the node remains unnamed.
.Pp
An
-.Nm
+.Nm iface
node has a single hook corresponding to each supported protocol.
Packets transmitted via the interface flow out the corresponding
protocol-specific hook.
Similarly, packets received on a hook appear on the interface as
-packets received in the corresponding protocol.
-.Pp
-The currently supported protocols are IP, IPX, AppleTalk, and NS.
-In the KLD module, only support for IP is compiled in by default.
+packets received into the corresponding protocol stack.
+The currently supported protocols are IP, IPv6, AppleTalk, IPX, ATM,
+NATM, and NS.
.Pp
An
-.Nm
-node supports the Berkeley Packet Filter (BPF).
+.Nm iface
+node be configured as a point-to-point interface or a broadcast interface.
+The configuration can only be changed when the interface is down.
+The default mode is point-to-point.
+.Pp
+.Nm Iface
+nodes support the Berkeley Packet Filter (BPF).
.Sh HOOKS
This node type supports the following hooks:
.Pp
.Bl -tag -width foobar
.It Dv inet
Transmission and reception of IP packets.
-.It Dv ipx
-Transmission and reception of IPX packets.
+.It Dv inet6
+Transmission and reception of IPv6 packets.
.It Dv atalk
Transmission and reception of AppleTalk packets.
+.It Dv ipx
+Transmission and reception of IPX packets.
+.It Dv atm
+Transmission and reception of ATM packets.
+.It Dv natm
+Transmission and reception of NATM packets.
.It Dv ns
Transmission and reception of NS packets.
.El
@@ -94,11 +110,12 @@ struct ng_iface_ifname {
char ngif_name[NG_IFACE_IFACE_NAME_MAX + 1];
};
.Ed
-.It Dv NGM_IFACE_GET_IFADDRS
-Returns the list of addresses associated with this interface.
-The list is returned in the same format as the
-.Dv SIOCGIFCONF
-.Fn ioctl .
+.It Dv NGM_IFACE_POINT2POINT
+Set the interface to point-to-point mode.
+The interface must not currently be up.
+.It Dv NGM_IFACE_BROADCAST
+Set the interface to broadcast mode.
+The interface must not currently be up.
.It Dv NGM_CISCO_GET_IPADDR
This message is defined by the
.Xr ng_cisco 8
@@ -107,28 +124,30 @@ node type; see
for a description.
.El
.Sh SHUTDOWN
-Because it is currently not possible to remove a system networking
-interface in
-.Fx ,
-.Nm
-nodes are
-.Em persistent.
-That is, once created they are never destroyed.
-The receipt of a
+This node shuts down upon receipt of a
.Dv NGM_SHUTDOWN
-control message disconnects all hooks but does not remove the node.
+control message. The associated interface is removed and becomes available
+for use by future
+.Nm iface
+nodes.
+.Pp
+Unlike most other node types, an
+.Nm iface
+node does
+.Em not
+go away when all hooks have been disconnected; rather, and explicit
+.Dv NGM_SHUTDOWN
+control message is required.
.Sh SEE ALSO
.Xr bpf 4 ,
.Xr netgraph 4 ,
.Xr ifconfig 8 ,
.Xr ng_cisco 8 ,
-.Xr ng_ppp 8 ,
-.Xr ng_rfc1490 8 ,
-.Xr ngctl 8 .
+.Xr ngctl 8
.Sh HISTORY
The
-.Nm
+.Nm iface
node type was implemented in
.Fx 4.0 .
-.Sh AUTHORS
+.Sh AUTHOR
.An Archie Cobbs Aq archie@whistle.com
diff --git a/sys/netgraph/ng_iface.c b/sys/netgraph/ng_iface.c
index 0139f9de417e..d22aa2a7d3f4 100644
--- a/sys/netgraph/ng_iface.c
+++ b/sys/netgraph/ng_iface.c
@@ -45,16 +45,12 @@
* a hook for each protocol (IP, AppleTalk, IPX, etc). Packets
* are simply relayed between the interface and the hooks.
*
- * Interfaces are named ng0, ng1, .... FreeBSD does not support
- * the removal of interfaces, so iface nodes are persistent.
+ * Interfaces are named ng0, ng1, etc. New nodes take the
+ * first available interface name.
*
* This node also includes Berkeley packet filter support.
*/
-#include "opt_inet.h"
-#include "opt_atalk.h"
-#include "opt_ipx.h"
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/errno.h>
@@ -65,102 +61,46 @@
#include <sys/sockio.h>
#include <sys/socket.h>
#include <sys/syslog.h>
+#include <sys/libkern.h>
#include <net/if.h>
#include <net/if_types.h>
-#include <net/netisr.h>
+#include <net/intrq.h>
+#include <net/bpf.h>
#include <netinet/in.h>
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
+#include <netgraph/ng_parse.h>
#include <netgraph/ng_iface.h>
#include <netgraph/ng_cisco.h>
-#ifdef INET
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/in_var.h>
-#endif
-
-#ifdef NETATALK
-#include <netatalk/at.h>
-#include <netatalk/at_var.h>
-#endif
-
-#ifdef IPX
-#include <netipx/ipx.h>
-#include <netipx/ipx_if.h>
-#endif
-
-#ifdef NS
-#include <netns/ns.h>
-#include <netns/ns_if.h>
-#endif
-
-#include <net/bpf.h>
-
/* This struct describes one address family */
struct iffam {
- char *hookname; /* Name for hook */
- u_char af; /* Family number */
- u_char netisr; /* or NETISR_NONE */
- union {
- void *_dummy; /* avoid warning */
- struct ifqueue *inq; /* if netisr */
- void (*input)(struct mbuf *m); /* if direct input */
- } u;
+ sa_family_t family; /* Address family */
+ const char *hookname; /* Name for hook */
};
typedef const struct iffam *iffam_p;
-#define NETISR_NONE 0xff
-
-/* List of address families supported by our interface. Each address
- family has a way to input packets to it, either by calling a function
- directly (such as ip_input()) or by adding the packet to a queue and
- setting a NETISR bit. */
+/* List of address families supported by our interface */
const static struct iffam gFamilies[] = {
-#ifdef INET
- {
- NG_IFACE_HOOK_INET,
- AF_INET,
- NETISR_NONE,
- { ip_input }
- },
-#endif
-#ifdef NETATALK
- {
- NG_IFACE_HOOK_ATALK,
- AF_APPLETALK,
- NETISR_ATALK,
- { &atintrq2 }
- },
-#endif
-#ifdef IPX
- {
- NG_IFACE_HOOK_IPX,
- AF_IPX,
- NETISR_IPX,
- { &ipxintrq }
- },
-#endif
-#ifdef NS
- {
- NG_IFACE_HOOK_NS,
- AF_NS,
- NETISR_NS,
- { &nsintrq }
- },
-#endif
+ { AF_INET, NG_IFACE_HOOK_INET },
+ { AF_INET6, NG_IFACE_HOOK_INET6 },
+ { AF_APPLETALK, NG_IFACE_HOOK_ATALK },
+ { AF_IPX, NG_IFACE_HOOK_IPX },
+ { AF_ATM, NG_IFACE_HOOK_ATM },
+ { AF_NATM, NG_IFACE_HOOK_NATM },
+ { AF_NS, NG_IFACE_HOOK_NS },
};
#define NUM_FAMILIES (sizeof(gFamilies) / sizeof(*gFamilies))
/* Node private data */
struct ng_iface_private {
- struct ifnet *ifp; /* This interface */
+ struct ifnet *ifp; /* Our interface */
+ int unit; /* Interface unit number */
node_p node; /* Our netgraph node */
hook_p hooks[NUM_FAMILIES]; /* Hook for each address family */
- struct private *next; /* When hung on the free list */
};
typedef struct ng_iface_private *priv_p;
@@ -168,8 +108,9 @@ typedef struct ng_iface_private *priv_p;
static void ng_iface_start(struct ifnet *ifp);
static int ng_iface_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
static int ng_iface_output(struct ifnet *ifp, struct mbuf *m0,
- struct sockaddr *dst, struct rtentry *rt0);
-static void ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, u_int af);
+ struct sockaddr *dst, struct rtentry *rt0);
+static void ng_iface_bpftap(struct ifnet *ifp,
+ struct mbuf *m, sa_family_t family);
#ifdef DEBUG
static void ng_iface_print_ioctl(struct ifnet *ifp, int cmd, caddr_t data);
#endif
@@ -183,11 +124,61 @@ static ng_rcvdata_t ng_iface_rcvdata;
static ng_disconnect_t ng_iface_disconnect;
/* Helper stuff */
-static iffam_p get_iffam_from_af(int af);
+static iffam_p get_iffam_from_af(sa_family_t family);
static iffam_p get_iffam_from_hook(priv_p priv, hook_p hook);
static iffam_p get_iffam_from_name(const char *name);
static hook_p *get_hook_from_iffam(priv_p priv, iffam_p iffam);
+/* Parse type for struct ng_iface_ifname */
+static const struct ng_parse_fixedstring_info ng_iface_ifname_info = {
+ NG_IFACE_IFACE_NAME_MAX + 1
+};
+static const struct ng_parse_type ng_iface_ifname_type = {
+ &ng_parse_fixedstring_type,
+ &ng_iface_ifname_info
+};
+
+/* Parse type for struct ng_cisco_ipaddr */
+static const struct ng_parse_struct_info
+ ng_cisco_ipaddr_type_info = NG_CISCO_IPADDR_TYPE_INFO;
+static const struct ng_parse_type ng_cisco_ipaddr_type = {
+ &ng_parse_struct_type,
+ &ng_cisco_ipaddr_type_info
+};
+
+/* List of commands and how to convert arguments to/from ASCII */
+static const struct ng_cmdlist ng_iface_cmds[] = {
+ {
+ NGM_IFACE_COOKIE,
+ NGM_IFACE_GET_IFNAME,
+ "getifname",
+ NULL,
+ &ng_iface_ifname_type
+ },
+ {
+ NGM_IFACE_COOKIE,
+ NGM_IFACE_POINT2POINT,
+ "point2point",
+ NULL,
+ NULL
+ },
+ {
+ NGM_IFACE_COOKIE,
+ NGM_IFACE_BROADCAST,
+ "broadcast",
+ NULL,
+ NULL
+ },
+ {
+ NGM_CISCO_COOKIE,
+ NGM_CISCO_GET_IPADDR,
+ "getipaddr",
+ NULL,
+ &ng_cisco_ipaddr_type
+ },
+ { 0 }
+};
+
/* Node type descriptor */
static struct ng_type typestruct = {
NG_VERSION,
@@ -202,12 +193,16 @@ static struct ng_type typestruct = {
ng_iface_rcvdata,
ng_iface_rcvdata,
ng_iface_disconnect,
- NULL
+ ng_iface_cmds
};
NETGRAPH_INIT(iface, &typestruct);
-static char ng_iface_ifname[] = NG_IFACE_IFACE_NAME;
-static int ng_iface_next_unit;
+/* We keep a bitmap indicating which unit numbers are free.
+ One means the unit number is free, zero means it's taken. */
+static int *ng_iface_units = NULL;
+static int ng_iface_units_len = 0;
+
+#define UNITS_BITSPERWORD (sizeof(*ng_iface_units) * NBBY)
/************************************************************************
HELPER STUFF
@@ -217,14 +212,14 @@ static int ng_iface_next_unit;
* Get the family descriptor from the family ID
*/
static __inline__ iffam_p
-get_iffam_from_af(int af)
+get_iffam_from_af(sa_family_t family)
{
iffam_p iffam;
int k;
for (k = 0; k < NUM_FAMILIES; k++) {
iffam = &gFamilies[k];
- if (iffam->af == af)
+ if (iffam->family == family)
return (iffam);
}
return (NULL);
@@ -271,6 +266,63 @@ get_iffam_from_name(const char *name)
return (NULL);
}
+/*
+ * Find the first free unit number for a new interface.
+ * Increase the size of the unit bitmap as necessary.
+ */
+static __inline__ int
+ng_iface_get_unit(int *unit)
+{
+ int index, bit;
+
+ for (index = 0; index < ng_iface_units_len
+ && ng_iface_units[index] == 0; index++);
+ if (index == ng_iface_units_len) { /* extend array */
+ int i, *newarray, newlen;
+
+ newlen = (2 * ng_iface_units_len) + 4;
+ MALLOC(newarray, int *, newlen * sizeof(*ng_iface_units),
+ M_NETGRAPH, M_WAITOK);
+ if (newarray == NULL)
+ return (ENOMEM);
+ bcopy(ng_iface_units, newarray,
+ ng_iface_units_len * sizeof(*ng_iface_units));
+ for (i = ng_iface_units_len; i < newlen; i++)
+ newarray[i] = ~0;
+ if (ng_iface_units != NULL)
+ FREE(ng_iface_units, M_NETGRAPH);
+ ng_iface_units = newarray;
+ ng_iface_units_len = newlen;
+ }
+ bit = ffs(ng_iface_units[index]) - 1;
+ KASSERT(bit >= 0 && bit <= UNITS_BITSPERWORD - 1,
+ ("%s: word=%d bit=%d", __FUNCTION__, ng_iface_units[index], bit));
+ ng_iface_units[index] &= ~(1 << bit);
+ *unit = (index * UNITS_BITSPERWORD) + bit;
+ return (0);
+}
+
+/*
+ * Free a no longer needed unit number.
+ */
+static __inline__ void
+ng_iface_free_unit(int unit)
+{
+ int index, bit;
+
+ index = unit / UNITS_BITSPERWORD;
+ bit = unit % UNITS_BITSPERWORD;
+ KASSERT(index < ng_iface_units_len,
+ ("%s: unit=%d len=%d", __FUNCTION__, unit, ng_iface_units_len));
+ KASSERT((ng_iface_units[index] & (1 << bit)) == 0,
+ ("%s: unit=%d is free", __FUNCTION__, unit));
+ ng_iface_units[index] |= (1 << bit);
+ /*
+ * XXX We could think about reducing the size of ng_iface_units[]
+ * XXX here if the last portion is all ones
+ */
+}
+
/************************************************************************
INTERFACE STUFF
************************************************************************/
@@ -362,6 +414,16 @@ ng_iface_output(struct ifnet *ifp, struct mbuf *m,
return (ENETDOWN);
}
+ /* BPF writes need to be handled specially */
+ if (dst->sa_family == AF_UNSPEC) {
+ if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL)
+ return (ENOBUFS);
+ dst->sa_family = (sa_family_t)*mtod(m, int32_t *);
+ m->m_data += 4;
+ m->m_len -= 4;
+ m->m_pkthdr.len -= 4;
+ }
+
/* Berkeley packet filter */
ng_iface_bpftap(ifp, m, dst->sa_family);
@@ -369,7 +431,7 @@ ng_iface_output(struct ifnet *ifp, struct mbuf *m,
if (iffam == NULL) {
m_freem(m);
log(LOG_WARNING, "%s%d: can't handle af%d\n",
- ifp->if_name, ifp->if_unit, dst->sa_family);
+ ifp->if_name, ifp->if_unit, (int)dst->sa_family);
return (EAFNOSUPPORT);
}
@@ -402,23 +464,18 @@ ng_iface_start(struct ifnet *ifp)
* Note the phoney mbuf; this is OK because BPF treats it read-only.
*/
static void
-ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, u_int af)
+ng_iface_bpftap(struct ifnet *ifp, struct mbuf *m, sa_family_t family)
{
- struct mbuf m2;
-
- if (ifp->if_bpf) {
- if (af == AF_UNSPEC) {
- af = *(mtod(m, int *));
- m->m_len -= sizeof(int);
- m->m_pkthdr.len -= sizeof(int);
- m->m_data += sizeof(int);
- }
- if (!ifp->if_bpf)
- return;
- m2.m_next = m;
- m2.m_len = 4;
- m2.m_data = (char *) &af;
- bpf_mtap(ifp, &m2);
+ int32_t family4 = (int32_t)family;
+ struct mbuf m0;
+
+ KASSERT(family != AF_UNSPEC, ("%s: family=AF_UNSPEC", __FUNCTION__));
+ if (ifp->if_bpf != NULL) {
+ bzero(&m0, sizeof(m0));
+ m0.m_next = m;
+ m0.m_len = sizeof(family4);
+ m0.m_data = (char *)&family4;
+ bpf_mtap(ifp, &m0);
}
}
@@ -489,10 +546,18 @@ ng_iface_constructor(node_p *nodep)
ifp->if_softc = priv;
priv->ifp = ifp;
- /* Call generic node constructor */
- if ((error = ng_make_node_common(&typestruct, nodep))) {
+ /* Get an interface unit number */
+ if ((error = ng_iface_get_unit(&priv->unit)) != 0) {
+ FREE(ifp, M_NETGRAPH);
FREE(priv, M_NETGRAPH);
+ return (error);
+ }
+
+ /* Call generic node constructor */
+ if ((error = ng_make_node_common(&typestruct, nodep)) != 0) {
+ ng_iface_free_unit(priv->unit);
FREE(ifp, M_NETGRAPH);
+ FREE(priv, M_NETGRAPH);
return (error);
}
node = *nodep;
@@ -502,15 +567,15 @@ ng_iface_constructor(node_p *nodep)
priv->node = node;
/* Initialize interface structure */
- ifp->if_name = ng_iface_ifname;
- ifp->if_unit = ng_iface_next_unit++;
+ ifp->if_name = NG_IFACE_IFACE_NAME;
+ ifp->if_unit = priv->unit;
ifp->if_output = ng_iface_output;
ifp->if_start = ng_iface_start;
ifp->if_ioctl = ng_iface_ioctl;
ifp->if_watchdog = NULL;
ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
ifp->if_mtu = NG_IFACE_MTU_DEFAULT;
- ifp->if_flags = (IFF_SIMPLEX | IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST);
+ ifp->if_flags = (IFF_SIMPLEX|IFF_POINTOPOINT|IFF_NOARP|IFF_MULTICAST);
ifp->if_type = IFT_PROPVIRTUAL; /* XXX */
ifp->if_addrlen = 0; /* XXX */
ifp->if_hdrlen = 0; /* XXX */
@@ -519,8 +584,9 @@ ng_iface_constructor(node_p *nodep)
/* Give this node the same name as the interface (if possible) */
bzero(ifname, sizeof(ifname));
- sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
- (void) ng_name_node(node, ifname);
+ snprintf(ifname, sizeof(ifname), "%s%d", ifp->if_name, ifp->if_unit);
+ if (ng_name_node(node, ifname) != 0)
+ log(LOG_WARNING, "%s: can't acquire netgraph name\n", ifname);
/* Attach the interface */
if_attach(ifp);
@@ -572,46 +638,32 @@ ng_iface_rcvmsg(node_p node, struct ng_mesg *msg,
error = ENOMEM;
break;
}
- arg = (struct ng_iface_ifname *) resp->data;
- sprintf(arg->ngif_name,
+ arg = (struct ng_iface_ifname *)resp->data;
+ snprintf(arg->ngif_name, sizeof(arg->ngif_name),
"%s%d", ifp->if_name, ifp->if_unit);
break;
}
- case NGM_IFACE_GET_IFADDRS:
+ case NGM_IFACE_POINT2POINT:
+ case NGM_IFACE_BROADCAST:
{
- struct ifaddr *ifa;
- caddr_t ptr;
- int buflen;
-#define SA_SIZE(s) ((s)->sa_len<sizeof(*(s))? sizeof(*(s)):(s)->sa_len)
+ /* Deny request if interface is UP */
+ if ((ifp->if_flags & IFF_UP) != 0)
+ return (EBUSY);
- /* Determine size of response and allocate it */
- buflen = 0;
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link)
- buflen += SA_SIZE(ifa->ifa_addr);
- NG_MKRESPONSE(resp, msg, buflen, M_NOWAIT);
- if (resp == NULL) {
- error = ENOMEM;
+ /* Change flags */
+ switch (msg->header.cmd) {
+ case NGM_IFACE_POINT2POINT:
+ ifp->if_flags |= IFF_POINTOPOINT;
+ ifp->if_flags &= ~IFF_BROADCAST;
+ break;
+ case NGM_IFACE_BROADCAST:
+ ifp->if_flags &= ~IFF_POINTOPOINT;
+ ifp->if_flags |= IFF_BROADCAST;
break;
- }
-
- /* Add addresses */
- ptr = resp->data;
- TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- const int len = SA_SIZE(ifa->ifa_addr);
-
- if (buflen < len) {
- log(LOG_ERR, "%s%d: len changed?\n",
- ifp->if_name, ifp->if_unit);
- break;
- }
- bcopy(ifa->ifa_addr, ptr, len);
- ptr += len;
- buflen -= len;
}
break;
-#undef SA_SIZE
}
default:
@@ -627,20 +679,19 @@ ng_iface_rcvmsg(node_p node, struct ng_mesg *msg,
/* Return the first configured IP address */
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
- struct in_addr *ips;
+ struct ng_cisco_ipaddr *ips;
if (ifa->ifa_addr->sa_family != AF_INET)
continue;
- NG_MKRESPONSE(resp, msg,
- 2 * sizeof(*ips), M_NOWAIT);
+ NG_MKRESPONSE(resp, msg, sizeof(ips), M_NOWAIT);
if (resp == NULL) {
error = ENOMEM;
break;
}
- ips = (struct in_addr *) resp->data;
- ips[0] = ((struct sockaddr_in *)
+ ips = (struct ng_cisco_ipaddr *)resp->data;
+ ips->ipaddr = ((struct sockaddr_in *)
ifa->ifa_addr)->sin_addr;
- ips[1] = ((struct sockaddr_in *)
+ ips->netmask = ((struct sockaddr_in *)
ifa->ifa_netmask)->sin_addr;
break;
}
@@ -676,7 +727,6 @@ ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
const priv_p priv = hook->node->private;
const iffam_p iffam = get_iffam_from_hook(priv, hook);
struct ifnet *const ifp = priv->ifp;
- int s, error = 0;
/* Sanity checks */
KASSERT(iffam != NULL, ("%s: iffam", __FUNCTION__));
@@ -696,53 +746,38 @@ ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
m->m_pkthdr.rcvif = ifp;
/* Berkeley packet filter */
- ng_iface_bpftap(ifp, m, iffam->af);
+ ng_iface_bpftap(ifp, m, iffam->family);
/* Ignore any meta-data */
NG_FREE_META(meta);
- /* Send packet, either by NETISR or use a direct input function */
- switch (iffam->netisr) {
- case NETISR_NONE:
- (*iffam->u.input)(m);
- break;
- default:
- s = splimp();
- schednetisr(iffam->netisr);
- if (IF_QFULL(iffam->u.inq)) {
- IF_DROP(iffam->u.inq);
- m_freem(m);
- error = ENOBUFS;
- } else
- IF_ENQUEUE(iffam->u.inq, m);
- splx(s);
- break;
- }
-
- /* Done */
- return (error);
+ /* Send packet */
+ return family_enqueue(iffam->family, m);
}
/*
- * Because the BSD networking code doesn't support the removal of
- * networking interfaces, iface nodes (once created) are persistent.
- * So this method breaks all connections and marks the interface
- * down, but does not remove the node.
+ * Shutdown and remove the node and its associated interface.
*/
static int
ng_iface_rmnode(node_p node)
{
const priv_p priv = node->private;
- struct ifnet *const ifp = priv->ifp;
ng_cutlinks(node);
- node->flags &= ~NG_INVALID;
- ifp->if_flags &= ~(IFF_UP | IFF_RUNNING | IFF_OACTIVE);
+ ng_unname(node);
+ bpfdetach(priv->ifp);
+ if_detach(priv->ifp);
+ priv->ifp = NULL;
+ ng_iface_free_unit(priv->unit);
+ FREE(priv, M_NETGRAPH);
+ node->private = NULL;
+ ng_unref(node);
return (0);
}
/*
- * Hook disconnection
+ * Hook disconnection. Note that we do *not* shutdown when all
+ * hooks have been disconnected.
*/
static int
ng_iface_disconnect(hook_p hook)
diff --git a/sys/netgraph/ng_iface.h b/sys/netgraph/ng_iface.h
index 946f06e751c8..e856c9403044 100644
--- a/sys/netgraph/ng_iface.h
+++ b/sys/netgraph/ng_iface.h
@@ -45,7 +45,7 @@
/* Node type name and magic cookie */
#define NG_IFACE_NODE_TYPE "iface"
-#define NGM_IFACE_COOKIE 858821772
+#define NGM_IFACE_COOKIE 858821773
/* Interface base name */
#define NG_IFACE_IFACE_NAME "ng"
@@ -53,8 +53,11 @@
/* My hook names */
#define NG_IFACE_HOOK_INET "inet"
+#define NG_IFACE_HOOK_INET6 "inet6"
#define NG_IFACE_HOOK_ATALK "atalk" /* AppleTalk phase 2 */
#define NG_IFACE_HOOK_IPX "ipx"
+#define NG_IFACE_HOOK_ATM "atm"
+#define NG_IFACE_HOOK_NATM "natm"
#define NG_IFACE_HOOK_NS "ns"
/* MTU bounds */
@@ -65,7 +68,8 @@
/* Netgraph commands */
enum {
NGM_IFACE_GET_IFNAME = 1, /* returns struct ng_iface_ifname */
- NGM_IFACE_GET_IFADDRS, /* returns list of addresses */
+ NGM_IFACE_POINT2POINT,
+ NGM_IFACE_BROADCAST,
};
struct ng_iface_ifname {