xref: /csrg-svn/sys/net/if_loop.c (revision 17058)
1 /*	if_loop.c	6.2	84/08/29	*/
2 
3 /*
4  * Loopback interface driver for protocol testing and timing.
5  */
6 
7 #include "param.h"
8 #include "systm.h"
9 #include "mbuf.h"
10 #include "socket.h"
11 #include "errno.h"
12 #include "ioctl.h"
13 
14 #include "../net/if.h"
15 #include "../net/netisr.h"
16 #include "../net/route.h"
17 
18 #include "in.h"
19 #include "in_systm.h"
20 #include "ip.h"
21 #include "ip_var.h"
22 
23 #ifdef vax
24 #include "../vax/mtpr.h"
25 #endif
26 
27 #define	LONET	127
28 #define	LOHOST	1			/* can't be 0, that's broadcast */
29 #define	LOMTU	(1024+512)
30 
31 struct	ifnet loif;
32 int	looutput(), loioctl();
33 
34 loattach()
35 {
36 	register struct ifnet *ifp = &loif;
37 	register struct sockaddr_in *sin;
38 
39 	ifp->if_name = "lo";
40 	ifp->if_mtu = LOMTU;
41 	ifp->if_net = LONET;
42 	ifp->if_host[0] = LOHOST;
43 	sin = (struct sockaddr_in *)&ifp->if_addr;
44 	sin->sin_family = AF_INET;
45 	sin->sin_addr = if_makeaddr(LONET, LOHOST);
46 	ifp->if_flags = IFF_UP | IFF_RUNNING;
47 	ifp->if_ioctl = loioctl;
48 	ifp->if_output = looutput;
49 	if_attach(ifp);
50 	if_rtinit(ifp, RTF_UP);
51 }
52 
53 looutput(ifp, m0, dst)
54 	struct ifnet *ifp;
55 	struct mbuf *m0;
56 	struct sockaddr *dst;
57 {
58 	int s = splimp();
59 	register struct ifqueue *ifq;
60 
61 	ifp->if_opackets++;
62 	switch (dst->sa_family) {
63 
64 #ifdef INET
65 	case AF_INET:
66 		ifq = &ipintrq;
67 		if (IF_QFULL(ifq)) {
68 			IF_DROP(ifq);
69 			m_freem(m0);
70 			splx(s);
71 			return (ENOBUFS);
72 		}
73 		IF_ENQUEUE(ifq, m0);
74 		schednetisr(NETISR_IP);
75 		break;
76 #endif
77 	default:
78 		splx(s);
79 		printf("lo%d: can't handle af%d\n", ifp->if_unit,
80 			dst->sa_family);
81 		m_freem(m0);
82 		return (EAFNOSUPPORT);
83 	}
84 	ifp->if_ipackets++;
85 	splx(s);
86 	return (0);
87 }
88 
89 /*
90  * Process an ioctl request.
91  */
92 loioctl(ifp, cmd, data)
93 	register struct ifnet *ifp;
94 	int cmd;
95 	caddr_t data;
96 {
97 	struct ifreq *ifr = (struct ifreq *)data;
98 	struct sockaddr_in *sin;
99 	int s = splimp(), error = 0;
100 
101 	switch (cmd) {
102 
103 	case SIOCSIFADDR:
104 		if (ifp->if_flags & IFF_RUNNING)
105 			if_rtinit(ifp, -1);	/* delete previous route */
106 		ifp->if_addr = ifr->ifr_addr;
107 		sin = (struct sockaddr_in *)&ifp->if_addr;
108 		ifp->if_net = in_netof(sin->sin_addr);
109 		ifp->if_host[0] = in_lnaof(sin->sin_addr);
110 		if_rtinit(ifp, RTF_UP);
111 		break;
112 
113 	default:
114 		error = EINVAL;
115 	}
116 	splx(s);
117 	return (error);
118 }
119