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