xref: /csrg-svn/sys/net/if_loop.c (revision 23174)
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