1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)if_loop.c 7.13 (Berkeley) 4/26/91 34 * $Id: if_loop.c,v 1.7 1993/11/23 08:16:55 deraadt Exp $ 35 */ 36 37 /* 38 * Loopback interface driver for protocol testing and timing. 39 */ 40 41 #include "param.h" 42 #include "systm.h" 43 #include "mbuf.h" 44 #include "socket.h" 45 #include "errno.h" 46 #include "ioctl.h" 47 #include "protosw.h" 48 49 #include "loop.h" 50 51 #include "../net/if.h" 52 #include "../net/if_types.h" 53 #include "../net/netisr.h" 54 #include "../net/route.h" 55 56 #include "machine/mtpr.h" 57 58 #ifdef INET 59 #include "../netinet/in.h" 60 #include "../netinet/in_systm.h" 61 #include "../netinet/in_var.h" 62 #include "../netinet/ip.h" 63 #endif 64 65 #ifdef NS 66 #include "../netns/ns.h" 67 #include "../netns/ns_if.h" 68 #endif 69 70 #ifdef ISO 71 #include "../netiso/iso.h" 72 #include "../netiso/iso_var.h" 73 #endif 74 75 #include "bpfilter.h" 76 #if NBPFILTER > 0 77 #include <sys/time.h> 78 #include <net/bpf.h> 79 static caddr_t lo_bpf; 80 #endif 81 82 #define LOMTU (1024+512) 83 84 struct ifnet loif[NLOOP]; 85 int looutput(), loioctl(); 86 87 void 88 loopattach() 89 { 90 register int i; 91 register struct ifnet *ifp; 92 93 for (i = 0; i < NLOOP; i++) 94 { 95 ifp = &loif[i]; 96 ifp->if_unit = i; 97 ifp->if_name = "lo"; 98 ifp->if_mtu = LOMTU; 99 ifp->if_flags = IFF_LOOPBACK; 100 ifp->if_ioctl = loioctl; 101 ifp->if_output = looutput; 102 ifp->if_type = IFT_LOOP; 103 ifp->if_hdrlen = 0; 104 ifp->if_addrlen = 0; 105 if_attach(ifp); 106 #if NBPFILTER > 0 107 bpfattach(&lo_bpf, ifp, DLT_NULL, sizeof(u_int)); 108 #endif 109 } 110 } 111 112 looutput(ifp, m, dst, rt) 113 struct ifnet *ifp; 114 register struct mbuf *m; 115 struct sockaddr *dst; 116 register struct rtentry *rt; 117 { 118 int s, isr; 119 register struct ifqueue *ifq = 0; 120 121 if ((m->m_flags & M_PKTHDR) == 0) 122 panic("looutput no HDR"); 123 #if NBPFILTER > 0 124 if (lo_bpf) { 125 /* 126 * We need to prepend the address family as 127 * a four byte field. Cons up a dummy header 128 * to pacify bpf. This is safe because bpf 129 * will only read from the mbuf (i.e., it won't 130 * try to free it or keep a pointer to it). 131 */ 132 struct mbuf m0; 133 u_int af = dst->sa_family; 134 135 m0.m_next = m; 136 m0.m_len = 4; 137 m0.m_data = (char *)⁡ 138 139 bpf_mtap(lo_bpf, &m0); 140 } 141 #endif 142 m->m_pkthdr.rcvif = ifp; 143 144 if (rt && rt->rt_flags & RTF_REJECT) { 145 m_freem(m); 146 return (rt->rt_flags & RTF_HOST ? EHOSTUNREACH : ENETUNREACH); 147 } 148 ifp->if_opackets++; 149 ifp->if_obytes += m->m_pkthdr.len; 150 switch (dst->sa_family) { 151 152 #ifdef INET 153 case AF_INET: 154 ifq = &ipintrq; 155 isr = NETISR_IP; 156 break; 157 #endif 158 #ifdef NS 159 case AF_NS: 160 ifq = &nsintrq; 161 isr = NETISR_NS; 162 break; 163 #endif 164 #ifdef ISO 165 case AF_ISO: 166 ifq = &clnlintrq; 167 isr = NETISR_ISO; 168 break; 169 #endif 170 default: 171 printf("lo%d: can't handle af%d\n", ifp->if_unit, 172 dst->sa_family); 173 m_freem(m); 174 return (EAFNOSUPPORT); 175 } 176 s = splimp(); 177 if (IF_QFULL(ifq)) { 178 IF_DROP(ifq); 179 m_freem(m); 180 splx(s); 181 return (ENOBUFS); 182 } 183 IF_ENQUEUE(ifq, m); 184 schednetisr(isr); 185 ifp->if_ipackets++; 186 ifp->if_ibytes += m->m_pkthdr.len; 187 splx(s); 188 return (0); 189 } 190 191 /* ARGSUSED */ 192 lortrequest(cmd, rt, sa) 193 struct rtentry *rt; 194 struct sockaddr *sa; 195 { 196 if (rt) 197 rt->rt_rmx.rmx_mtu = LOMTU; 198 } 199 200 /* 201 * Process an ioctl request. 202 */ 203 /* ARGSUSED */ 204 loioctl(ifp, cmd, data) 205 register struct ifnet *ifp; 206 int cmd; 207 caddr_t data; 208 { 209 register struct ifaddr *ifa; 210 int error = 0; 211 212 switch (cmd) { 213 214 case SIOCSIFADDR: 215 ifp->if_flags |= IFF_UP; 216 ifa = (struct ifaddr *)data; 217 if (ifa != 0 && ifa->ifa_addr->sa_family == AF_ISO) 218 ifa->ifa_rtrequest = lortrequest; 219 /* 220 * Everything else is done at a higher level. 221 */ 222 break; 223 224 default: 225 error = EINVAL; 226 } 227 return (error); 228 } 229