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 are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)if_loop.c 7.4 (Berkeley) 06/27/88 18 */ 19 20 /* 21 * Loopback interface driver for protocol testing and timing. 22 */ 23 24 #include "param.h" 25 #include "systm.h" 26 #include "mbuf.h" 27 #include "socket.h" 28 #include "errno.h" 29 #include "ioctl.h" 30 31 #include "../net/if.h" 32 #include "../net/netisr.h" 33 #include "../net/route.h" 34 35 #include "../machine/mtpr.h" 36 37 #ifdef INET 38 #include "../netinet/in.h" 39 #include "../netinet/in_systm.h" 40 #include "../netinet/in_var.h" 41 #include "../netinet/ip.h" 42 #endif 43 44 #ifdef NS 45 #include "../netns/ns.h" 46 #include "../netns/ns_if.h" 47 #endif 48 49 #define LOMTU (1024+512) 50 51 struct ifnet loif; 52 int looutput(), loioctl(); 53 54 loattach() 55 { 56 register struct ifnet *ifp = &loif; 57 58 ifp->if_name = "lo"; 59 ifp->if_mtu = LOMTU; 60 ifp->if_flags = IFF_LOOPBACK; 61 ifp->if_ioctl = loioctl; 62 ifp->if_output = looutput; 63 if_attach(ifp); 64 } 65 66 looutput(ifp, m0, dst) 67 struct ifnet *ifp; 68 register struct mbuf *m0; 69 struct sockaddr *dst; 70 { 71 int s; 72 register struct ifqueue *ifq; 73 struct mbuf *m; 74 75 /* 76 * Place interface pointer before the data 77 * for the receiving protocol. 78 */ 79 if (m0->m_off <= MMAXOFF && 80 m0->m_off >= MMINOFF + sizeof(struct ifnet *)) { 81 m0->m_off -= sizeof(struct ifnet *); 82 m0->m_len += sizeof(struct ifnet *); 83 } else { 84 MGET(m, M_DONTWAIT, MT_HEADER); 85 if (m == (struct mbuf *)0) 86 return (ENOBUFS); 87 m->m_off = MMINOFF; 88 m->m_len = sizeof(struct ifnet *); 89 m->m_next = m0; 90 m0 = m; 91 } 92 *(mtod(m0, struct ifnet **)) = ifp; 93 s = splimp(); 94 ifp->if_opackets++; 95 switch (dst->sa_family) { 96 97 #ifdef INET 98 case AF_INET: 99 ifq = &ipintrq; 100 if (IF_QFULL(ifq)) { 101 IF_DROP(ifq); 102 m_freem(m0); 103 splx(s); 104 return (ENOBUFS); 105 } 106 IF_ENQUEUE(ifq, m0); 107 schednetisr(NETISR_IP); 108 break; 109 #endif 110 #ifdef NS 111 case AF_NS: 112 ifq = &nsintrq; 113 if (IF_QFULL(ifq)) { 114 IF_DROP(ifq); 115 m_freem(m0); 116 splx(s); 117 return (ENOBUFS); 118 } 119 IF_ENQUEUE(ifq, m0); 120 schednetisr(NETISR_NS); 121 break; 122 #endif 123 default: 124 splx(s); 125 printf("lo%d: can't handle af%d\n", ifp->if_unit, 126 dst->sa_family); 127 m_freem(m0); 128 return (EAFNOSUPPORT); 129 } 130 ifp->if_ipackets++; 131 splx(s); 132 return (0); 133 } 134 135 /* 136 * Process an ioctl request. 137 */ 138 /* ARGSUSED */ 139 loioctl(ifp, cmd, data) 140 register struct ifnet *ifp; 141 int cmd; 142 caddr_t data; 143 { 144 int error = 0; 145 146 switch (cmd) { 147 148 case SIOCSIFADDR: 149 ifp->if_flags |= IFF_UP; 150 /* 151 * Everything else is done at a higher level. 152 */ 153 break; 154 155 default: 156 error = EINVAL; 157 } 158 return (error); 159 } 160