1 /* 2 * Copyright (c) 1982 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)if_loop.c 6.6 (Berkeley) 06/08/85 7 */ 8 9 /* 10 * Loopback interface driver for protocol testing and timing. 11 */ 12 13 #include "param.h" 14 #include "systm.h" 15 #include "mbuf.h" 16 #include "socket.h" 17 #include "errno.h" 18 #include "ioctl.h" 19 20 #include "../net/if.h" 21 #include "../net/netisr.h" 22 #include "../net/route.h" 23 24 #include "in.h" 25 #include "in_systm.h" 26 #include "ip.h" 27 #include "ip_var.h" 28 29 #ifdef vax 30 #include "../vax/mtpr.h" 31 #endif 32 33 #ifdef NS 34 #include "../netns/ns.h" 35 #include "../netns/ns_if.h" 36 #endif 37 38 #define LOMTU (1024+512) 39 40 struct ifnet loif; 41 int looutput(), loioctl(); 42 43 loattach() 44 { 45 register struct ifnet *ifp = &loif; 46 register struct sockaddr_in *sin; 47 48 ifp->if_name = "lo"; 49 ifp->if_mtu = LOMTU; 50 ifp->if_ioctl = loioctl; 51 ifp->if_output = looutput; 52 if_attach(ifp); 53 } 54 55 looutput(ifp, m0, dst) 56 struct ifnet *ifp; 57 struct mbuf *m0; 58 struct sockaddr *dst; 59 { 60 int s = splimp(); 61 register struct ifqueue *ifq; 62 63 ifp->if_opackets++; 64 switch (dst->sa_family) { 65 66 #ifdef INET 67 case AF_INET: 68 ifq = &ipintrq; 69 if (IF_QFULL(ifq)) { 70 IF_DROP(ifq); 71 m_freem(m0); 72 splx(s); 73 return (ENOBUFS); 74 } 75 IF_ENQUEUE(ifq, m0); 76 schednetisr(NETISR_IP); 77 break; 78 #endif 79 #ifdef NS 80 case AF_NS: 81 ifq = &nsintrq; 82 if (IF_QFULL(ifq)) { 83 IF_DROP(ifq); 84 m_freem(m0); 85 splx(s); 86 return (ENOBUFS); 87 } 88 IF_ENQUEUE(ifq, m0); 89 schednetisr(NETISR_NS); 90 break; 91 #endif 92 default: 93 splx(s); 94 printf("lo%d: can't handle af%d\n", ifp->if_unit, 95 dst->sa_family); 96 m_freem(m0); 97 return (EAFNOSUPPORT); 98 } 99 ifp->if_ipackets++; 100 splx(s); 101 return (0); 102 } 103 104 /* 105 * Process an ioctl request. 106 */ 107 /* ARGSUSED */ 108 loioctl(ifp, cmd, data) 109 register struct ifnet *ifp; 110 int cmd; 111 caddr_t data; 112 { 113 int error = 0; 114 115 switch (cmd) { 116 117 case SIOCSIFADDR: 118 ifp->if_flags |= IFF_UP; 119 /* 120 * Everything else is done at a higher level. 121 */ 122 break; 123 124 default: 125 error = EINVAL; 126 } 127 return (error); 128 } 129