summaryrefslogtreecommitdiffstats
path: root/sys/net
diff options
context:
space:
mode:
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/bpf.c14
-rw-r--r--sys/net/if_atm.h42
-rw-r--r--sys/net/if_atmsubr.c483
3 files changed, 409 insertions, 130 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 136edf0..c65bbff 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -37,7 +37,7 @@
*
* @(#)bpf.c 8.2 (Berkeley) 3/28/94
*
- * $Id: bpf.c,v 1.38 1998/02/20 13:46:57 bde Exp $
+ * $Id: bpf.c,v 1.39 1998/06/07 17:12:01 dfr Exp $
*/
#include "bpfilter.h"
@@ -197,6 +197,18 @@ bpf_movein(uio, linktype, mp, sockp, datlen)
hlen = 0;
break;
+#ifdef __FreeBSD__
+ case DLT_ATM_RFC1483:
+ /*
+ * en atm driver requires 4-byte atm pseudo header.
+ * though it isn't standard, vpi:vci needs to be
+ * specified anyway.
+ */
+ sockp->sa_family = AF_UNSPEC;
+ hlen = 12; /* XXX 4(ATM_PH) + 3(LLC) + 5(SNAP) */
+ break;
+#endif
+
default:
return (EIO);
}
diff --git a/sys/net/if_atm.h b/sys/net/if_atm.h
index 1d7cd8e..f1e2d8b 100644
--- a/sys/net/if_atm.h
+++ b/sys/net/if_atm.h
@@ -42,6 +42,14 @@
#endif
#endif /* freebsd doesn't define _KERNEL */
+#ifndef NO_ATM_PVCEXT
+/*
+ * ATM_PVCEXT enables PVC extention: VP/VC shaping
+ * and PVC shadow interfaces.
+ */
+#define ATM_PVCEXT /* enable pvc extention */
+#endif
+
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__bsdi__)
#define RTALLOC1(A,B) rtalloc1((A),(B))
#elif defined(__FreeBSD__)
@@ -51,7 +59,6 @@
/*
* pseudo header for packet transmission
*/
-
struct atm_pseudohdr {
u_int8_t atm_ph[4]; /* flags+VPI+VCI1(msb)+VCI2(lsb) */
};
@@ -67,6 +74,9 @@ struct atm_pseudohdr {
#define ATM_PH_AAL5 0x01 /* use AAL5? (0 == aal0) */
#define ATM_PH_LLCSNAP 0x02 /* use the LLC SNAP encoding (iff aal5) */
+#ifdef ATM_PVCEXT
+#define ATM_PH_INERNAL 0x20 /* reserve for kernel internal use */
+#endif
#define ATM_PH_DRIVER7 0x40 /* reserve for driver's use */
#define ATM_PH_DRIVER8 0x80 /* reserve for driver's use */
@@ -85,6 +95,29 @@ struct atm_pseudoioctl {
#define SIOCATMENA _IOWR('a', 123, struct atm_pseudoioctl) /* enable */
#define SIOCATMDIS _IOWR('a', 124, struct atm_pseudoioctl) /* disable */
+#ifdef ATM_PVCEXT
+
+/* structure to control PVC transmitter */
+struct pvctxreq {
+ /* first entry must be compatible with struct ifreq */
+ char pvc_ifname[IFNAMSIZ]; /* if name, e.g. "en0" */
+ struct atm_pseudohdr pvc_aph; /* (flags) + vpi:vci */
+ struct atm_pseudohdr pvc_joint; /* for vp shaping: another vc
+ to share the shaper */
+ int pvc_pcr; /* peak cell rate (shaper value) */
+};
+
+/* use ifioctl for now */
+#define SIOCSPVCTX _IOWR('i', 95, struct pvctxreq)
+#define SIOCGPVCTX _IOWR('i', 96, struct pvctxreq)
+#define SIOCSPVCSIF _IOWR('i', 97, struct ifreq)
+#define SIOCGPVCSIF _IOWR('i', 98, struct ifreq)
+
+#ifdef _KERNEL
+#define ATM_PH_PVCSIF ATM_PH_INERNAL /* pvc shadow interface */
+#endif
+#endif /* ATM_PVCEXT */
+
/*
* XXX forget all the garbage in if_llc.h and do it the easy way
*/
@@ -109,3 +142,10 @@ void atm_input __P((struct ifnet *, struct atm_pseudohdr *,
int atm_output __P((struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *));
#endif
+#ifdef ATM_PVCEXT
+char *shadow2if __P((char *));
+#ifdef _KERNEL
+struct ifnet *pvc_attach __P((struct ifnet *));
+int pvc_setaph __P((struct ifnet *, struct atm_pseudohdr *));
+#endif
+#endif
diff --git a/sys/net/if_atmsubr.c b/sys/net/if_atmsubr.c
index 7df2626..a41bfaf 100644
--- a/sys/net/if_atmsubr.c
+++ b/sys/net/if_atmsubr.c
@@ -43,6 +43,9 @@
#include <sys/systm.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/malloc.h>
+#include <sys/errno.h>
#include <net/if.h>
#include <net/netisr.h>
@@ -54,25 +57,16 @@
#include <netinet/in.h>
#include <netinet/if_atm.h>
#include <netinet/if_ether.h> /* XXX: for ETHERTYPE_* */
-#ifdef INET
+#if defined(INET) || defined(INET6)
#include <netinet/in_var.h>
#endif
#ifdef NATM
#include <netnatm/natm.h>
#endif
-#include "bpfilter.h"
-#if NBPFILTER > 0
-/*
- * bpf support.
- * the code is derived from if_loop.c.
- * bpf support should belong to the driver but it's easier to implement
- * it here since we can call bpf_mtap before atm_output adds a pseudo
- * header to the mbuf.
- * --kjc
- */
-#include <net/bpf.h>
-#endif /* NBPFILTER > 0 */
+#ifndef ETHERTYPE_IPV6
+#define ETHERTYPE_IPV6 0x86dd
+#endif
#define senderr(e) { error = (e); goto bad;}
@@ -104,11 +98,11 @@ atm_output(ifp, m0, dst, rt0)
register struct mbuf *m = m0;
register struct rtentry *rt;
struct atmllc *atmllc;
+ struct atmllc *llc_hdr = NULL;
u_int32_t atm_flags;
if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
senderr(ENETDOWN);
- getmicrotime(&ifp->if_lastchange);
/*
* check route
@@ -142,8 +136,9 @@ atm_output(ifp, m0, dst, rt0)
*/
if (dst) {
switch (dst->sa_family) {
-#ifdef INET
+#if defined(INET) || defined(INET6)
case AF_INET:
+ case AF_INET6:
if (!atmresolve(rt, m, dst, &atmdst)) {
m = NULL;
/* XXX: atmresolve already free'd it */
@@ -151,10 +146,23 @@ atm_output(ifp, m0, dst, rt0)
/* XXX: put ATMARP stuff here */
/* XXX: watch who frees m on failure */
}
- etype = htons(ETHERTYPE_IP);
+ if (dst->sa_family == AF_INET6)
+ etype = htons(ETHERTYPE_IPV6);
+ else
+ etype = htons(ETHERTYPE_IP);
break;
-#endif
-
+#endif /* INET || INET6 */
+
+ case AF_UNSPEC:
+ /*
+ * XXX: bpfwrite or output from a pvc shadow if.
+ * assuming dst contains 12 bytes (atm pseudo
+ * header (4) + LLC/SNAP (8))
+ */
+ bcopy(dst->sa_data, &atmdst, sizeof(atmdst));
+ llc_hdr = (struct atmllc *)(dst->sa_data + sizeof(atmdst));
+ break;
+
default:
#if defined(__NetBSD__) || defined(__OpenBSD__)
printf("%s: can't handle af%d\n", ifp->if_xname,
@@ -166,40 +174,6 @@ atm_output(ifp, m0, dst, rt0)
senderr(EAFNOSUPPORT);
}
-#if NBPFILTER > 0
- /* BPF write needs to be handled specially */
- if (dst && dst->sa_family == AF_UNSPEC) {
- dst->sa_family = *(mtod(m, int *));
- m->m_len -= sizeof(int);
- m->m_pkthdr.len -= sizeof(int);
- m->m_data += sizeof(int);
- }
-
- if (ifp->if_bpf) {
- /*
- * We need to prepend the address family as
- * a four byte field. Cons up a dummy header
- * to pacify bpf. This is safe because bpf
- * will only read from the mbuf (i.e., it won't
- * try to free it or keep a pointer a to it).
- */
- struct mbuf m1;
- u_int af = dst->sa_family;
-
- m1.m_next = m;
- m1.m_len = 4;
- m1.m_data = (char *)&af;
-
- s = splimp();
-#if defined(__NetBSD__) || defined(__OpenBSD__)
- bpf_mtap(&ifp->if_bpf, &m0);
-#elif defined(__FreeBSD__)
- bpf_mtap(ifp, &m1);
-#endif
- splx(s);
- }
-#endif /* NBPFILTER > 0 */
-
/*
* must add atm_pseudohdr to data
*/
@@ -213,10 +187,14 @@ atm_output(ifp, m0, dst, rt0)
*ad = atmdst;
if (atm_flags & ATM_PH_LLCSNAP) {
atmllc = (struct atmllc *)(ad + 1);
- bcopy(ATMLLC_HDR, atmllc->llchdr,
- sizeof(atmllc->llchdr));
- ATM_LLC_SETTYPE(atmllc, etype);
+ if (llc_hdr == NULL) {
+ bcopy(ATMLLC_HDR, atmllc->llchdr,
+ sizeof(atmllc->llchdr));
+ ATM_LLC_SETTYPE(atmllc, etype);
/* note: already in network order */
+ }
+ else
+ bcopy(llc_hdr, atmllc, sizeof(struct atmllc));
}
}
@@ -224,7 +202,6 @@ atm_output(ifp, m0, dst, rt0)
* Queue message on interface, and start output if interface
* not yet active.
*/
-
s = splimp();
if (IF_QFULL(&ifp->if_snd)) {
IF_DROP(&ifp->if_snd);
@@ -263,82 +240,76 @@ atm_input(ifp, ah, m, rxhand)
m_freem(m);
return;
}
- getmicrotime(&ifp->if_lastchange);
ifp->if_ibytes += m->m_pkthdr.len;
-#if NBPFILTER > 0
- if (ifp->if_bpf) {
+#ifdef ATM_PVCEXT
+ if (ATM_PH_FLAGS(ah) & ATM_PH_PVCSIF) {
/*
- * We need to prepend the address family as
- * a four byte field. Cons up a dummy header
- * to pacify bpf. This is safe because bpf
- * will only read from the mbuf (i.e., it won't
- * try to free it or keep a pointer to it).
+ * when PVC shadow interface is used, pointer to
+ * the shadow interface is passed as rxhand.
+ * override the receive interface of the packet.
*/
- struct mbuf m0;
- u_int af = AF_INET;
-
- m0.m_next = m;
- m0.m_len = 4;
- m0.m_data = (char *)&af;
-
-#if defined(__NetBSD__) || defined(__OpenBSD__)
- bpf_mtap(&ifp->if_bpf, &m0);
-#elif defined(__FreeBSD__)
- bpf_mtap(ifp, &m0);
-#endif
+ m->m_pkthdr.rcvif = (struct ifnet *)rxhand;
+ rxhand = NULL;
}
-#endif /* NBPFILTER > 0 */
+#endif /* ATM_PVCEXT */
if (rxhand) {
#ifdef NATM
- struct natmpcb *npcb = rxhand;
- s = splimp(); /* in case 2 atm cards @ diff lvls */
- npcb->npcb_inq++; /* count # in queue */
- splx(s);
- schednetisr(NETISR_NATM);
- inq = &natmintrq;
- m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
+ struct natmpcb *npcb = rxhand;
+ s = splimp(); /* in case 2 atm cards @ diff lvls */
+ npcb->npcb_inq++; /* count # in queue */
+ splx(s);
+ schednetisr(NETISR_NATM);
+ inq = &natmintrq;
+ m->m_pkthdr.rcvif = rxhand; /* XXX: overload */
#else
- printf("atm_input: NATM detected but not configured in kernel\n");
- m_freem(m);
- return;
+ printf("atm_input: NATM detected but not configured in kernel\n");
+ m_freem(m);
+ return;
#endif
} else {
- /*
- * handle LLC/SNAP header, if present
- */
- if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
- struct atmllc *alc;
- if (m->m_len < sizeof(*alc) && (m = m_pullup(m, sizeof(*alc))) == 0)
- return; /* failed */
- alc = mtod(m, struct atmllc *);
- if (bcmp(alc, ATMLLC_HDR, 6)) {
+ /*
+ * handle LLC/SNAP header, if present
+ */
+ if (ATM_PH_FLAGS(ah) & ATM_PH_LLCSNAP) {
+ struct atmllc *alc;
+ if (m->m_len < sizeof(*alc) &&
+ (m = m_pullup(m, sizeof(*alc))) == 0)
+ return; /* failed */
+ alc = mtod(m, struct atmllc *);
+ if (bcmp(alc, ATMLLC_HDR, 6)) {
#if defined(__NetBSD__) || defined(__OpenBSD__)
- printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
- ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
+ printf("%s: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
+ ifp->if_xname, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
#elif defined(__FreeBSD__) || defined(__bsdi__)
- printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
- ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
+ printf("%s%d: recv'd invalid LLC/SNAP frame [vp=%d,vc=%d]\n",
+ ifp->if_name, ifp->if_unit, ATM_PH_VPI(ah), ATM_PH_VCI(ah));
#endif
- m_freem(m);
- return;
- }
- etype = ATM_LLC_TYPE(alc);
- m_adj(m, sizeof(*alc));
- }
-
- switch (etype) {
+ m_freem(m);
+ return;
+ }
+ etype = ATM_LLC_TYPE(alc);
+ m_adj(m, sizeof(*alc));
+ }
+
+ switch (etype) {
#ifdef INET
- case ETHERTYPE_IP:
- schednetisr(NETISR_IP);
- inq = &ipintrq;
- break;
+ case ETHERTYPE_IP:
+ schednetisr(NETISR_IP);
+ inq = &ipintrq;
+ break;
+#endif
+#ifdef INET6
+ case ETHERTYPE_IPV6:
+ schednetisr(NETISR_IPV6);
+ inq = &ip6intrq;
+ break;
#endif
- default:
- m_freem(m);
- return;
- }
+ default:
+ m_freem(m);
+ return;
+ }
}
s = splimp();
@@ -369,18 +340,12 @@ atm_ifattach(ifp)
#if defined(__NetBSD__) || defined(__OpenBSD__)
for (ifa = ifp->if_addrlist.tqh_first; ifa != 0;
ifa = ifa->ifa_list.tqe_next)
-#elif defined(__FreeBSD__) && ((__FreeBSD__ > 2) || defined(_NET_IF_VAR_H_))
-/*
- * for FreeBSD-3.0. 3.0-SNAP-970124 still sets -D__FreeBSD__=2!
- * XXX -- for now, use newly-introduced "net/if_var.h" as an identifier.
- * need a better way to identify 3.0. -- kjc
- */
+#elif defined(__FreeBSD__) && (__FreeBSD__ > 2)
for (ifa = ifp->if_addrhead.tqh_first; ifa;
ifa = ifa->ifa_link.tqe_next)
#elif defined(__FreeBSD__) || defined(__bsdi__)
for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
#endif
-
if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
sdl->sdl_family == AF_LINK) {
sdl->sdl_type = IFT_ATM;
@@ -390,11 +355,273 @@ atm_ifattach(ifp)
#endif
break;
}
-#if NBPFILTER > 0
+
+}
+
+#ifdef ATM_PVCEXT
+/*
+ * ATM PVC shadow interface: a trick to assign a shadow interface
+ * to a PVC.
+ * with shadow interface, each PVC looks like an individual
+ * Point-to-Point interface.
+ * as oposed to the NBMA model, a shadow interface is inherently
+ * multicast capable (no LANE/MARS required).
+ */
+struct pvcsif {
+ struct ifnet sif_shadow; /* shadow ifnet structure per pvc */
+ struct atm_pseudohdr sif_aph; /* flags + vpi:vci */
+ struct ifnet *sif_ifp; /* pointer to the genuine interface */
+};
+
+static int pvc_output __P((struct ifnet *, struct mbuf *,
+ struct sockaddr *, struct rtentry *));
+static int pvc_ioctl __P((struct ifnet *, u_long, caddr_t));
+
+/*
+ * create and attach per pvc shadow interface
+ * (currently detach is not supported)
+ */
+static int pvc_number = 0;
+
+struct ifnet *
+pvc_attach(ifp)
+ struct ifnet *ifp;
+{
+ struct pvcsif *pvcsif;
+ struct ifnet *shadow;
+ struct ifaddr *ifa;
+ struct sockaddr_dl *sdl;
+ int s;
+
+ MALLOC(pvcsif, struct pvcsif *, sizeof(struct pvcsif),
+ M_DEVBUF, M_WAITOK);
+ bzero(pvcsif, sizeof(struct pvcsif));
+
+ pvcsif->sif_ifp = ifp;
+ shadow = &pvcsif->sif_shadow;
+
+ shadow->if_name = "pvc";
+ shadow->if_unit = pvc_number++;
+ shadow->if_flags = ifp->if_flags | (IFF_POINTOPOINT | IFF_MULTICAST);
+ shadow->if_ioctl = pvc_ioctl;
+ shadow->if_output = pvc_output;
+ shadow->if_start = NULL;
+ shadow->if_mtu = ifp->if_mtu;
+ shadow->if_type = ifp->if_type;
+ shadow->if_addrlen = ifp->if_addrlen;
+ shadow->if_hdrlen = ifp->if_hdrlen;
+ shadow->if_softc = pvcsif;
+ shadow->if_snd.ifq_maxlen = 50; /* dummy */
+
+ s = splimp();
+ if_attach(shadow);
+
#if defined(__NetBSD__) || defined(__OpenBSD__)
- bpfattach(&ifp->if_bpf, ifp, DLT_NULL, sizeof(u_int));
-#elif defined(__FreeBSD__)
- bpfattach(ifp, DLT_NULL, sizeof(u_int));
+ for (ifa = shadow->if_addrlist.tqh_first; ifa != 0;
+ ifa = ifa->ifa_list.tqe_next)
+#elif defined(__FreeBSD__) && (__FreeBSD__ > 2)
+ for (ifa = shadow->if_addrhead.tqh_first; ifa;
+ ifa = ifa->ifa_link.tqe_next)
+#elif defined(__FreeBSD__) || defined(__bsdi__)
+ for (ifa = shadow->if_addrlist; ifa; ifa = ifa->ifa_next)
+#endif
+ if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
+ sdl->sdl_family == AF_LINK) {
+ sdl->sdl_type = IFT_ATM;
+ sdl->sdl_alen = shadow->if_addrlen;
+ break;
+ }
+ splx(s);
+
+ return (shadow);
+}
+
+/*
+ * pvc_output relays the packet to atm_output along with vpi:vci info.
+ */
+static int
+pvc_output(shadow, m, dst, rt)
+ struct ifnet *shadow;
+ struct mbuf *m;
+ struct sockaddr *dst;
+ struct rtentry *rt;
+{
+ struct pvcsif *pvcsif;
+ struct sockaddr dst_addr;
+ struct atmllc *atmllc;
+ u_int16_t etype = 0;
+ int error = 0;
+
+ if ((shadow->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+ senderr(ENETDOWN);
+
+ pvcsif = shadow->if_softc;
+ if (ATM_PH_VCI(&pvcsif->sif_aph) == 0)
+ senderr(ENETDOWN);
+
+ /*
+ * create a dummy sockaddr: (using bpfwrite interface)
+ * put atm pseudo header and llc/snap into sa_data (12 bytes)
+ * and mark it as AF_UNSPEC.
+ */
+ if (dst) {
+ switch (dst->sa_family) {
+#if defined(INET) || defined(INET6)
+ case AF_INET:
+ case AF_INET6:
+ if (dst->sa_family == AF_INET6)
+ etype = htons(ETHERTYPE_IPV6);
+ else
+ etype = htons(ETHERTYPE_IP);
+ break;
+#endif
+
+ default:
+ printf("%s%d: can't handle af%d\n", shadow->if_name,
+ shadow->if_unit, dst->sa_family);
+ senderr(EAFNOSUPPORT);
+ }
+ }
+
+ dst_addr.sa_family = AF_UNSPEC;
+ bcopy(&pvcsif->sif_aph, dst_addr.sa_data,
+ sizeof(struct atm_pseudohdr));
+ atmllc = (struct atmllc *)
+ (dst_addr.sa_data + sizeof(struct atm_pseudohdr));
+ bcopy(ATMLLC_HDR, atmllc->llchdr, sizeof(atmllc->llchdr));
+ ATM_LLC_SETTYPE(atmllc, etype); /* note: already in network order */
+
+ return atm_output(pvcsif->sif_ifp, m, &dst_addr, rt);
+
+bad:
+ if (m)
+ m_freem(m);
+ return (error);
+}
+
+static int
+pvc_ioctl(shadow, cmd, data)
+ struct ifnet *shadow;
+ u_long cmd;
+ caddr_t data;
+{
+ struct ifnet *ifp;
+ struct pvcsif *pvcsif;
+ struct ifreq *ifr = (struct ifreq *) data;
+ void (*ifa_rtrequest)(int, struct rtentry *, struct sockaddr *) = NULL;
+ int error = 0;
+
+ pvcsif = (struct pvcsif *)shadow->if_softc;
+ ifp = pvcsif->sif_ifp;
+ if (ifp == 0 || ifp->if_ioctl == 0)
+ return (EOPNOTSUPP);
+
+ /*
+ * pre process
+ */
+ switch (cmd) {
+ case SIOCGPVCSIF:
+ sprintf(ifr->ifr_name, "%s%d", ifp->if_name, ifp->if_unit);
+ return (0);
+
+ case SIOCGPVCTX:
+ do {
+ struct pvctxreq *pvcreq = (struct pvctxreq *)data;
+
+ sprintf(pvcreq->pvc_ifname, "%s%d",
+ ifp->if_name, ifp->if_unit);
+ pvcreq->pvc_aph = pvcsif->sif_aph;
+ } while (0);
+ break;
+
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (ifr == 0)
+ return (EAFNOSUPPORT); /* XXX */
+ switch (ifr->ifr_addr.sa_family) {
+#ifdef INET
+ case AF_INET:
+ return (0);
#endif
-#endif /* NBPFILTER > 0 */
+#ifdef INET6
+ case AF_INET6:
+ return (0);
+#endif
+ default:
+ return (EAFNOSUPPORT);
+ }
+ break;
+ case SIOCSIFADDR:
+ if (ifp->if_flags & IFF_UP) {
+ /* real if is already up */
+ shadow->if_flags = ifp->if_flags |
+ (IFF_POINTOPOINT|IFF_MULTICAST);
+ return (0);
+ }
+ /*
+ * XXX: save the rtrequest field since the atm driver
+ * overwrites this field.
+ */
+ ifa_rtrequest = ((struct ifaddr *)data)->ifa_rtrequest;
+ break;
+
+ case SIOCSIFFLAGS:
+ if ((shadow->if_flags & IFF_UP) == 0) {
+ /*
+ * interface down. don't pass this to
+ * the real interface.
+ */
+ return (0);
+ }
+ if (shadow->if_flags & IFF_UP) {
+ /*
+ * interface up. if the real if is already up,
+ * nothing to do.
+ */
+ if (ifp->if_flags & IFF_UP) {
+ shadow->if_flags = ifp->if_flags |
+ (IFF_POINTOPOINT|IFF_MULTICAST);
+ return (0);
+ }
+ }
+ break;
+ }
+
+ /*
+ * pass the ioctl to the genuine interface
+ */
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
+
+ /*
+ * post process
+ */
+ switch (cmd) {
+ case SIOCSIFMTU:
+ shadow->if_mtu = ifp->if_mtu;
+ break;
+ case SIOCSIFADDR:
+ /* restore rtrequest */
+ ((struct ifaddr *)data)->ifa_rtrequest = ifa_rtrequest;
+ /* fall into... */
+ case SIOCSIFFLAGS:
+ /* update if_flags */
+ shadow->if_flags = ifp->if_flags
+ | (IFF_POINTOPOINT|IFF_MULTICAST);
+ break;
+ }
+
+ return (error);
}
+
+int pvc_setaph(shadow, aph)
+ struct ifnet *shadow;
+ struct atm_pseudohdr *aph;
+{
+ struct pvcsif *pvcsif;
+
+ pvcsif = shadow->if_softc;
+ bcopy(aph, &pvcsif->sif_aph, sizeof(struct atm_pseudohdr));
+ return (0);
+}
+
+#endif /* ATM_PVCEXT */
OpenPOWER on IntegriCloud