Commit | Line | Data |
---|---|---|
8ae0e4b4 | 1 | /* |
21622db8 | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
8ae0e4b4 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
2e62d00d | 6 | * @(#)if_loop.c 7.2 (Berkeley) %G% |
8ae0e4b4 | 7 | */ |
0a486d2b BJ |
8 | |
9 | /* | |
10 | * Loopback interface driver for protocol testing and timing. | |
11 | */ | |
12 | ||
20666ad3 JB |
13 | #include "param.h" |
14 | #include "systm.h" | |
15 | #include "mbuf.h" | |
16 | #include "socket.h" | |
17 | #include "errno.h" | |
18 | #include "ioctl.h" | |
1cc8c949 | 19 | |
0a486d2b | 20 | #include "../net/if.h" |
fcfe450e | 21 | #include "../net/netisr.h" |
1cc8c949 SL |
22 | #include "../net/route.h" |
23 | ||
2e62d00d MK |
24 | #include "../machine/mtpr.h" |
25 | ||
dbc42650 MK |
26 | #ifdef INET |
27 | #include "../netinet/in.h" | |
28 | #include "../netinet/in_systm.h" | |
21622db8 | 29 | #include "../netinet/in_var.h" |
dbc42650 | 30 | #include "../netinet/ip.h" |
dbc42650 | 31 | #endif |
1cc8c949 | 32 | |
edecfd58 KS |
33 | #ifdef NS |
34 | #include "../netns/ns.h" | |
35 | #include "../netns/ns_if.h" | |
36 | #endif | |
37 | ||
56e0df97 | 38 | #define LOMTU (1024+512) |
0a486d2b BJ |
39 | |
40 | struct ifnet loif; | |
639a8848 | 41 | int looutput(), loioctl(); |
0a486d2b BJ |
42 | |
43 | loattach() | |
44 | { | |
45 | register struct ifnet *ifp = &loif; | |
46 | ||
b454c3ea | 47 | ifp->if_name = "lo"; |
0a486d2b | 48 | ifp->if_mtu = LOMTU; |
484ee22e | 49 | ifp->if_flags = IFF_LOOPBACK; |
639a8848 | 50 | ifp->if_ioctl = loioctl; |
0a486d2b | 51 | ifp->if_output = looutput; |
405c9168 | 52 | if_attach(ifp); |
0a486d2b BJ |
53 | } |
54 | ||
ee787340 | 55 | looutput(ifp, m0, dst) |
0a486d2b | 56 | struct ifnet *ifp; |
dbc42650 | 57 | register struct mbuf *m0; |
ee787340 | 58 | struct sockaddr *dst; |
0a486d2b | 59 | { |
dbc42650 | 60 | int s; |
1e977657 | 61 | register struct ifqueue *ifq; |
dbc42650 MK |
62 | struct mbuf *m; |
63 | ||
64 | /* | |
65 | * Place interface pointer before the data | |
66 | * for the receiving protocol. | |
67 | */ | |
68 | if (m0->m_off <= MMAXOFF && | |
69 | m0->m_off >= MMINOFF + sizeof(struct ifnet *)) { | |
70 | m0->m_off -= sizeof(struct ifnet *); | |
71 | m0->m_len += sizeof(struct ifnet *); | |
72 | } else { | |
73 | MGET(m, M_DONTWAIT, MT_HEADER); | |
74 | if (m == (struct mbuf *)0) | |
75 | return (ENOBUFS); | |
76 | m->m_off = MMINOFF; | |
77 | m->m_len = sizeof(struct ifnet *); | |
78 | m->m_next = m0; | |
79 | m0 = m; | |
80 | } | |
81 | *(mtod(m0, struct ifnet **)) = ifp; | |
82 | s = splimp(); | |
b454c3ea | 83 | ifp->if_opackets++; |
ee787340 | 84 | switch (dst->sa_family) { |
0a486d2b BJ |
85 | |
86 | #ifdef INET | |
ee787340 | 87 | case AF_INET: |
1e977657 BJ |
88 | ifq = &ipintrq; |
89 | if (IF_QFULL(ifq)) { | |
90 | IF_DROP(ifq); | |
ee787340 | 91 | m_freem(m0); |
1e977657 | 92 | splx(s); |
4c5902e0 | 93 | return (ENOBUFS); |
1e977657 BJ |
94 | } |
95 | IF_ENQUEUE(ifq, m0); | |
9c8692e9 | 96 | schednetisr(NETISR_IP); |
0a486d2b | 97 | break; |
edecfd58 KS |
98 | #endif |
99 | #ifdef NS | |
100 | case AF_NS: | |
101 | ifq = &nsintrq; | |
102 | if (IF_QFULL(ifq)) { | |
103 | IF_DROP(ifq); | |
104 | m_freem(m0); | |
105 | splx(s); | |
106 | return (ENOBUFS); | |
107 | } | |
108 | IF_ENQUEUE(ifq, m0); | |
109 | schednetisr(NETISR_NS); | |
110 | break; | |
0a486d2b | 111 | #endif |
0a486d2b BJ |
112 | default: |
113 | splx(s); | |
ee787340 SL |
114 | printf("lo%d: can't handle af%d\n", ifp->if_unit, |
115 | dst->sa_family); | |
116 | m_freem(m0); | |
4c5902e0 | 117 | return (EAFNOSUPPORT); |
0a486d2b | 118 | } |
b454c3ea | 119 | ifp->if_ipackets++; |
0a486d2b | 120 | splx(s); |
4c5902e0 | 121 | return (0); |
0a486d2b | 122 | } |
639a8848 SL |
123 | |
124 | /* | |
125 | * Process an ioctl request. | |
126 | */ | |
bba52753 | 127 | /* ARGSUSED */ |
639a8848 SL |
128 | loioctl(ifp, cmd, data) |
129 | register struct ifnet *ifp; | |
130 | int cmd; | |
131 | caddr_t data; | |
132 | { | |
bba52753 | 133 | int error = 0; |
639a8848 SL |
134 | |
135 | switch (cmd) { | |
136 | ||
137 | case SIOCSIFADDR: | |
bba52753 MK |
138 | ifp->if_flags |= IFF_UP; |
139 | /* | |
140 | * Everything else is done at a higher level. | |
141 | */ | |
639a8848 SL |
142 | break; |
143 | ||
144 | default: | |
145 | error = EINVAL; | |
146 | } | |
639a8848 SL |
147 | return (error); |
148 | } |