123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /* $OpenBSD: if_vether.c,v 1.24 2015/05/23 08:31:05 mpi Exp $ */
- /*
- * Copyright (c) 2009 Theo de Raadt
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- #include <sys/param.h>
- #include <sys/systm.h>
- #include <sys/mbuf.h>
- #include <sys/socket.h>
- #include <sys/sockio.h>
- #include <sys/ioctl.h>
- #include <net/if.h>
- #include <net/if_media.h>
- #include <netinet/in.h>
- #include <netinet/if_ether.h>
- #include "bpfilter.h"
- #if NBPFILTER > 0
- #include <net/bpf.h>
- #endif
- void vetherattach(int);
- int vetherioctl(struct ifnet *, u_long, caddr_t);
- void vetherstart(struct ifnet *);
- int vether_clone_create(struct if_clone *, int);
- int vether_clone_destroy(struct ifnet *);
- int vether_media_change(struct ifnet *);
- void vether_media_status(struct ifnet *, struct ifmediareq *);
- struct vether_softc {
- struct arpcom sc_ac;
- struct ifmedia sc_media;
- };
- struct if_clone vether_cloner =
- IF_CLONE_INITIALIZER("vether", vether_clone_create, vether_clone_destroy);
- int
- vether_media_change(struct ifnet *ifp)
- {
- return (0);
- }
- void
- vether_media_status(struct ifnet *ifp, struct ifmediareq *imr)
- {
- imr->ifm_active = IFM_ETHER | IFM_AUTO;
- imr->ifm_status = IFM_AVALID | IFM_ACTIVE;
- }
- void
- vetherattach(int nvether)
- {
- if_clone_attach(&vether_cloner);
- }
- int
- vether_clone_create(struct if_clone *ifc, int unit)
- {
- struct ifnet *ifp;
- struct vether_softc *sc;
- if ((sc = malloc(sizeof(*sc),
- M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
- return (ENOMEM);
- ifp = &sc->sc_ac.ac_if;
- snprintf(ifp->if_xname, sizeof ifp->if_xname, "vether%d", unit);
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ether_fakeaddr(ifp);
- ifp->if_softc = sc;
- ifp->if_ioctl = vetherioctl;
- ifp->if_start = vetherstart;
- IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
- IFQ_SET_READY(&ifp->if_snd);
- ifp->if_capabilities = IFCAP_VLAN_MTU;
- ifmedia_init(&sc->sc_media, 0, vether_media_change,
- vether_media_status);
- ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
- ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO);
- if_attach(ifp);
- ether_ifattach(ifp);
- return (0);
- }
- int
- vether_clone_destroy(struct ifnet *ifp)
- {
- struct vether_softc *sc = ifp->if_softc;
- ifmedia_delete_instance(&sc->sc_media, IFM_INST_ANY);
- ether_ifdetach(ifp);
- if_detach(ifp);
- free(sc, M_DEVBUF, sizeof(*sc));
- return (0);
- }
- /*
- * The bridge has magically already done all the work for us,
- * and we only need to discard the packets.
- */
- void
- vetherstart(struct ifnet *ifp)
- {
- struct mbuf *m;
- for (;;) {
- IFQ_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
- return;
- #if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
- #endif /* NBPFILTER > 0 */
- ifp->if_opackets++;
- m_freem(m);
- }
- }
- /* ARGSUSED */
- int
- vetherioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
- {
- struct vether_softc *sc = (struct vether_softc *)ifp->if_softc;
- struct ifaddr *ifa = (struct ifaddr *)data;
- struct ifreq *ifr = (struct ifreq *)data;
- int error = 0, link_state;
- switch (cmd) {
- case SIOCSIFADDR:
- ifp->if_flags |= IFF_UP;
- if (ifa->ifa_addr->sa_family == AF_INET)
- arp_ifinit(&sc->sc_ac, ifa);
- /* FALLTHROUGH */
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP) {
- ifp->if_flags |= IFF_RUNNING;
- link_state = LINK_STATE_UP;
- } else {
- ifp->if_flags &= ~IFF_RUNNING;
- link_state = LINK_STATE_DOWN;
- }
- if (ifp->if_link_state != link_state) {
- ifp->if_link_state = link_state;
- if_link_state_change(ifp);
- }
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- break;
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
- break;
- default:
- error = ether_ioctl(ifp, &sc->sc_ac, cmd, data);
- }
- return (error);
- }
|