1 /* $NetBSD: if_vether.c,v 1.1 2020/09/27 13:31:04 roy Exp $ */ 2 /* $OpenBSD: if_vether.c,v 1.27 2016/04/13 11:41:15 mpi Exp $ */ 3 4 /* 5 * Copyright (c) 2009 Theo de Raadt 6 * Copyright (c) 2020 Roy Marples 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/cdefs.h> 22 __KERNEL_RCSID(0, "$NetBSD: if_vether.c,v 1.1 2020/09/27 13:31:04 roy Exp $"); 23 24 #include <sys/cprng.h> 25 #include <sys/kmem.h> 26 #include <sys/mbuf.h> 27 28 #include <net/if.h> 29 #include <net/if_ether.h> 30 #include <net/bpf.h> 31 32 void vetherattach(int); 33 static int vether_ioctl(struct ifnet *, u_long, void *); 34 static void vether_start(struct ifnet *); 35 static int vether_clone_create(struct if_clone *, int); 36 static int vether_clone_destroy(struct ifnet *); 37 38 static void vether_stop(struct ifnet *, int); 39 static int vether_init(struct ifnet *); 40 41 struct vether_softc { 42 struct ethercom sc_ec; 43 }; 44 45 struct if_clone vether_cloner = 46 IF_CLONE_INITIALIZER("vether", vether_clone_create, vether_clone_destroy); 47 48 void 49 vetherattach(int nvether) 50 { 51 52 if_clone_attach(&vether_cloner); 53 } 54 55 static int 56 vether_clone_create(struct if_clone *ifc, int unit) 57 { 58 struct ifnet *ifp; 59 struct vether_softc *sc; 60 uint8_t enaddr[ETHER_ADDR_LEN] = 61 { 0xf2, 0x0b, 0xa4, 0xff, 0xff, 0xff }; 62 63 sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); 64 ifp = &sc->sc_ec.ec_if; 65 if_initname(ifp, ifc->ifc_name, unit); 66 ifp->if_softc = sc; 67 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 68 #ifdef NET_MPSAFE 69 ifp->if_extflags = IFEF_MPSAFE; 70 #endif 71 ifp->if_ioctl = vether_ioctl; 72 ifp->if_start = vether_start; 73 ifp->if_stop = vether_stop; 74 ifp->if_init = vether_init; 75 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); 76 IFQ_SET_READY(&ifp->if_snd); 77 78 sc->sc_ec.ec_capabilities = ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU; 79 80 /* 81 * In order to obtain unique initial Ethernet address on a host, 82 * do some randomisation. It's not meant for anything but avoiding 83 * hard-coding an address. 84 */ 85 cprng_fast(&enaddr[3], 3); 86 87 /* Those steps are mandatory for an Ethernet driver. */ 88 if_initialize(ifp); 89 ether_ifattach(ifp, enaddr); 90 if_register(ifp); 91 92 return 0; 93 } 94 95 static int 96 vether_clone_destroy(struct ifnet *ifp) 97 { 98 struct vether_softc *sc = ifp->if_softc; 99 100 ether_ifdetach(ifp); 101 if_detach(ifp); 102 kmem_free(sc, sizeof(*sc)); 103 return 0; 104 } 105 106 static int 107 vether_init(struct ifnet *ifp) 108 { 109 110 ifp->if_flags |= IFF_RUNNING; 111 if_link_state_change(ifp, LINK_STATE_UP); 112 vether_start(ifp); 113 return 0; 114 } 115 116 /* 117 * The bridge has magically already done all the work for us, 118 * and we only need to discard the packets. 119 */ 120 static void 121 vether_start(struct ifnet *ifp) 122 { 123 struct mbuf *m; 124 125 for (;;) { 126 IFQ_DEQUEUE(&ifp->if_snd, m); 127 if (m == NULL) 128 break; 129 bpf_mtap(ifp, m, BPF_D_OUT); 130 m_freem(m); 131 if_statinc(ifp, if_opackets); 132 } 133 } 134 135 static void 136 vether_stop(struct ifnet *ifp, __unused int disable) 137 { 138 139 ifp->if_flags &= ~IFF_RUNNING; 140 if_link_state_change(ifp, LINK_STATE_DOWN); 141 } 142 143 static int 144 vether_ioctl(struct ifnet *ifp, unsigned long cmd, void *data) 145 { 146 int error = 0; 147 148 switch (cmd) { 149 case SIOCADDMULTI: 150 case SIOCDELMULTI: 151 break; 152 153 default: 154 error = ether_ioctl(ifp, cmd, data); 155 } 156 return error; 157 } 158