1 1.10 thorpej /* $NetBSD: if_canloop.c,v 1.10 2022/09/03 02:48:00 thorpej Exp $ */ 2 1.2 bouyer 3 1.2 bouyer /*- 4 1.2 bouyer * Copyright (c) 2017 The NetBSD Foundation, Inc. 5 1.2 bouyer * All rights reserved. 6 1.2 bouyer * 7 1.2 bouyer * This code is derived from software contributed to The NetBSD Foundation 8 1.2 bouyer * by Manuel Bouyer. 9 1.2 bouyer * 10 1.2 bouyer * Redistribution and use in source and binary forms, with or without 11 1.2 bouyer * modification, are permitted provided that the following conditions 12 1.2 bouyer * are met: 13 1.2 bouyer * 1. Redistributions of source code must retain the above copyright 14 1.2 bouyer * notice, this list of conditions and the following disclaimer. 15 1.2 bouyer * 2. Redistributions in binary form must reproduce the above copyright 16 1.2 bouyer * notice, this list of conditions and the following disclaimer in the 17 1.2 bouyer * documentation and/or other materials provided with the distribution. 18 1.2 bouyer * 19 1.2 bouyer * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.2 bouyer * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.2 bouyer * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.2 bouyer * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.2 bouyer * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.2 bouyer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.2 bouyer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.2 bouyer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.2 bouyer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.2 bouyer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.2 bouyer * POSSIBILITY OF SUCH DAMAGE. 30 1.2 bouyer */ 31 1.2 bouyer 32 1.2 bouyer 33 1.2 bouyer /* 34 1.2 bouyer * Loopback interface driver for the CAN protocol 35 1.2 bouyer */ 36 1.2 bouyer 37 1.2 bouyer #include <sys/cdefs.h> 38 1.10 thorpej __KERNEL_RCSID(0, "$NetBSD: if_canloop.c,v 1.10 2022/09/03 02:48:00 thorpej Exp $"); 39 1.2 bouyer 40 1.2 bouyer #ifdef _KERNEL_OPT 41 1.2 bouyer #include "opt_can.h" 42 1.2 bouyer #include "opt_net_mpsafe.h" 43 1.2 bouyer #endif 44 1.2 bouyer 45 1.2 bouyer #include <sys/param.h> 46 1.2 bouyer #include <sys/systm.h> 47 1.2 bouyer #include <sys/kernel.h> 48 1.2 bouyer #include <sys/mbuf.h> 49 1.2 bouyer #include <sys/socket.h> 50 1.2 bouyer #include <sys/errno.h> 51 1.2 bouyer #include <sys/ioctl.h> 52 1.2 bouyer #include <sys/time.h> 53 1.2 bouyer #include <sys/device.h> 54 1.2 bouyer #include <sys/module.h> 55 1.2 bouyer 56 1.2 bouyer #include <sys/cpu.h> 57 1.2 bouyer 58 1.2 bouyer #include <net/if.h> 59 1.2 bouyer #include <net/if_types.h> 60 1.2 bouyer 61 1.2 bouyer #ifdef CAN 62 1.2 bouyer #include <netcan/can.h> 63 1.10 thorpej #include <netcan/can_var.h> 64 1.2 bouyer #endif 65 1.2 bouyer 66 1.2 bouyer void canloopattach(int); 67 1.2 bouyer void canloopinit(void); 68 1.2 bouyer static int canloop_clone_create(struct if_clone *, int); 69 1.2 bouyer static int canloop_clone_destroy(struct ifnet *); 70 1.2 bouyer static int canloop_ioctl(struct ifnet *, u_long, void *); 71 1.2 bouyer static void canloop_ifstart(struct ifnet *); 72 1.2 bouyer 73 1.2 bouyer static int canloop_count; 74 1.2 bouyer 75 1.2 bouyer static struct if_clone canloop_cloner = 76 1.2 bouyer IF_CLONE_INITIALIZER("canlo", canloop_clone_create, canloop_clone_destroy); 77 1.2 bouyer 78 1.2 bouyer void 79 1.2 bouyer canloopattach(int n) 80 1.2 bouyer { 81 1.2 bouyer 82 1.2 bouyer /* 83 1.2 bouyer * Nothing to do here, initialization is handled by the 84 1.2 bouyer * module initialization code in canloopinit() below). 85 1.2 bouyer */ 86 1.2 bouyer } 87 1.2 bouyer 88 1.2 bouyer void 89 1.2 bouyer canloopinit(void) 90 1.2 bouyer { 91 1.2 bouyer 92 1.2 bouyer canloop_count = 0; 93 1.2 bouyer if_clone_attach(&canloop_cloner); 94 1.2 bouyer } 95 1.2 bouyer 96 1.2 bouyer static int 97 1.2 bouyer canloopdetach(void) 98 1.2 bouyer { 99 1.2 bouyer if (canloop_count > 0) 100 1.2 bouyer return EBUSY; 101 1.2 bouyer if_clone_detach(&canloop_cloner); 102 1.2 bouyer return 0; 103 1.2 bouyer } 104 1.2 bouyer 105 1.2 bouyer static int 106 1.2 bouyer canloop_clone_create(struct if_clone *ifc, int unit) 107 1.2 bouyer { 108 1.2 bouyer struct ifnet *ifp; 109 1.2 bouyer 110 1.2 bouyer ifp = if_alloc(IFT_OTHER); 111 1.2 bouyer 112 1.2 bouyer if_initname(ifp, ifc->ifc_name, unit); 113 1.2 bouyer 114 1.4 ozaki ifp->if_flags = IFF_LOOPBACK; 115 1.5 ozaki #ifdef NET_MPSAFE 116 1.3 ozaki ifp->if_extflags = IFEF_MPSAFE; 117 1.5 ozaki #endif 118 1.2 bouyer ifp->if_ioctl = canloop_ioctl; 119 1.2 bouyer ifp->if_start = canloop_ifstart; 120 1.2 bouyer can_ifattach(ifp); 121 1.2 bouyer #ifdef MBUFTRACE 122 1.2 bouyer ifp->if_mowner = malloc(sizeof(struct mowner), M_DEVBUF, 123 1.2 bouyer M_WAITOK | M_ZERO); 124 1.2 bouyer strlcpy(ifp->if_mowner->mo_name, ifp->if_xname, 125 1.2 bouyer sizeof(ifp->if_mowner->mo_name)); 126 1.2 bouyer MOWNER_ATTACH(ifp->if_mowner); 127 1.2 bouyer #endif 128 1.2 bouyer canloop_count++; 129 1.4 ozaki ifp->if_flags |= IFF_RUNNING; 130 1.2 bouyer 131 1.2 bouyer return (0); 132 1.2 bouyer } 133 1.2 bouyer 134 1.2 bouyer static int 135 1.2 bouyer canloop_clone_destroy(struct ifnet *ifp) 136 1.2 bouyer { 137 1.2 bouyer 138 1.4 ozaki ifp->if_flags &= ~IFF_RUNNING; 139 1.4 ozaki 140 1.2 bouyer #ifdef MBUFTRACE 141 1.2 bouyer MOWNER_DETACH(ifp->if_mowner); 142 1.2 bouyer free(ifp->if_mowner, M_DEVBUF); 143 1.2 bouyer #endif 144 1.2 bouyer 145 1.2 bouyer can_ifdetach(ifp); 146 1.2 bouyer 147 1.2 bouyer if_free(ifp); 148 1.2 bouyer canloop_count--; 149 1.2 bouyer KASSERT(canloop_count >= 0); 150 1.2 bouyer return (0); 151 1.2 bouyer } 152 1.2 bouyer 153 1.2 bouyer static void 154 1.2 bouyer canloop_ifstart(struct ifnet *ifp) 155 1.2 bouyer { 156 1.2 bouyer size_t pktlen; 157 1.2 bouyer struct mbuf *m; 158 1.2 bouyer 159 1.2 bouyer KERNEL_LOCK(1, NULL); 160 1.2 bouyer while (true) { 161 1.2 bouyer IF_DEQUEUE(&ifp->if_snd, m); 162 1.2 bouyer if (m == NULL) 163 1.2 bouyer break; 164 1.2 bouyer MCLAIM(m, ifp->if_mowner); 165 1.2 bouyer 166 1.2 bouyer if ((m->m_flags & M_PKTHDR) == 0) 167 1.2 bouyer panic("canloop_output: no header mbuf"); 168 1.2 bouyer m_set_rcvif(m, ifp); 169 1.2 bouyer if (ifp->if_flags & IFF_LOOPBACK) 170 1.2 bouyer can_bpf_mtap(ifp, m, 0); 171 1.2 bouyer 172 1.2 bouyer pktlen = m->m_pkthdr.len; 173 1.9 thorpej if_statadd2(ifp, if_opackets, 1, if_obytes, pktlen); 174 1.2 bouyer 175 1.2 bouyer #ifdef CAN 176 1.2 bouyer can_mbuf_tag_clean(m); 177 1.2 bouyer can_input(ifp, m); 178 1.2 bouyer #else 179 1.2 bouyer printf("%s: can't handle CAN packet\n", ifp->if_xname); 180 1.2 bouyer m_freem(m); 181 1.2 bouyer #endif 182 1.2 bouyer } 183 1.2 bouyer 184 1.2 bouyer KERNEL_UNLOCK_ONE(NULL); 185 1.2 bouyer } 186 1.2 bouyer 187 1.2 bouyer /* 188 1.2 bouyer * Process an ioctl request. 189 1.2 bouyer */ 190 1.2 bouyer /* ARGSUSED */ 191 1.2 bouyer static int 192 1.2 bouyer canloop_ioctl(struct ifnet *ifp, u_long cmd, void *data) 193 1.2 bouyer { 194 1.2 bouyer struct ifreq *ifr = data; 195 1.2 bouyer int error = 0; 196 1.2 bouyer 197 1.2 bouyer switch (cmd) { 198 1.2 bouyer 199 1.2 bouyer case SIOCINITIFADDR: 200 1.2 bouyer error = EAFNOSUPPORT; 201 1.2 bouyer break; 202 1.2 bouyer 203 1.2 bouyer case SIOCSIFMTU: 204 1.2 bouyer if ((unsigned)ifr->ifr_mtu != sizeof(struct can_frame)) 205 1.2 bouyer error = EINVAL; 206 1.2 bouyer break; 207 1.2 bouyer 208 1.2 bouyer case SIOCADDMULTI: 209 1.2 bouyer case SIOCDELMULTI: 210 1.2 bouyer error = EAFNOSUPPORT; 211 1.2 bouyer break; 212 1.2 bouyer 213 1.2 bouyer default: 214 1.2 bouyer error = ifioctl_common(ifp, cmd, data); 215 1.2 bouyer } 216 1.2 bouyer return (error); 217 1.2 bouyer } 218 1.2 bouyer 219 1.2 bouyer /* 220 1.2 bouyer * Module infrastructure 221 1.2 bouyer */ 222 1.2 bouyer #include "../net/if_module.h" 223 1.2 bouyer 224 1.8 pgoyette IF_MODULE(MODULE_CLASS_DRIVER, canloop, NULL) 225