diff options
author | ru <ru@FreeBSD.org> | 2005-11-04 15:42:01 +0000 |
---|---|---|
committer | ru <ru@FreeBSD.org> | 2005-11-04 15:42:01 +0000 |
commit | 8a9d6ba9030dfc2edcfe56d57ec03ce610b692de (patch) | |
tree | 97434496d40595a0ad1714675dfe4e1102bb43fc /sys/netgraph/ng_fec.c | |
parent | 52caee198230c71e8895ba3639f479f02035678a (diff) | |
download | FreeBSD-src-8a9d6ba9030dfc2edcfe56d57ec03ce610b692de.zip FreeBSD-src-8a9d6ba9030dfc2edcfe56d57ec03ce610b692de.tar.gz |
Bring some level of stability to this driver:
- Disallow bundle reconfiguration when virtual
interface is running; otherwise, removing a
port from a running configuration will cause
a panic in the start() method on the next packet
on an assumption that a bundle has an even
number of ports (2 or 4).
- Disallow bringing of virtual interface to a
running state when a bundle size is 0; otherwise,
adding and then removing the port will similarly
cause a panic.
- Add missing initialization of fec_ifstat when
adding a new port and fix media status reporting
when virtual interface isn't yet up (check for
fec_status of 1 rather than != 0).
Diffstat (limited to 'sys/netgraph/ng_fec.c')
-rw-r--r-- | sys/netgraph/ng_fec.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/sys/netgraph/ng_fec.c b/sys/netgraph/ng_fec.c index 55da28b..84b5db6 100644 --- a/sys/netgraph/ng_fec.c +++ b/sys/netgraph/ng_fec.c @@ -355,6 +355,13 @@ ng_fec_addport(struct ng_fec_private *priv, char *iface) b = &priv->fec_bundle; ifp = priv->ifp; + /* Only allow reconfiguration if not running. */ + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + printf("fec%d: can't add new iface; bundle is running\n", + priv->unit); + return (EINVAL); + } + /* Find the interface */ bifp = ifunit(iface); if (bifp == NULL) { @@ -443,6 +450,7 @@ ng_fec_addport(struct ng_fec_private *priv, char *iface) /* Add to the queue */ new->fec_if = bifp; + new->fec_ifstat = -1; TAILQ_INSERT_TAIL(&b->ng_fec_ports, new, fec_list); return(0); @@ -463,6 +471,13 @@ ng_fec_delport(struct ng_fec_private *priv, char *iface) b = &priv->fec_bundle; ifp = priv->ifp; + /* Only allow reconfiguration if not running. */ + if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + printf("fec%d: can't remove iface; bundle is running\n", + priv->unit); + return (EINVAL); + } + /* Find the interface */ bifp = ifunit(iface); if (bifp == NULL) { @@ -548,7 +563,7 @@ ng_fec_init(void *arg) ifp = priv->ifp; b = &priv->fec_bundle; - if (b->fec_ifcnt == 1 || b->fec_ifcnt == 3) { + if (b->fec_ifcnt != 2 && b->fec_ifcnt != FEC_BUNDLESIZ) { printf("fec%d: invalid bundle " "size: %d\n", priv->unit, b->fec_ifcnt); @@ -666,7 +681,7 @@ static void ng_fec_ifmedia_sts(struct ifnet *ifp, ifmr->ifm_status = IFM_AVALID; TAILQ_FOREACH(p, &b->ng_fec_ports, fec_list) { - if (p->fec_ifstat) { + if (p->fec_ifstat == 1) { ifmr->ifm_status |= IFM_ACTIVE; break; } @@ -711,7 +726,8 @@ ng_fec_ioctl(struct ifnet *ifp, u_long command, caddr_t data) if (ifr->ifr_flags & IFF_UP) { if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { /* Sanity. */ - if (b->fec_ifcnt == 1 || b->fec_ifcnt == 3) { + if (b->fec_ifcnt != 2 && + b->fec_ifcnt != FEC_BUNDLESIZ) { printf("fec%d: invalid bundle " "size: %d\n", priv->unit, b->fec_ifcnt); |