Remove building with NOCRYPTO option
[minix3.git] / minix / net / lwip / loopif.c
blobdb21db09ac50f6558627a8c4cfca24e322d9d313
1 /* LWIP service - loopif.c - loopback interfaces */
2 /*
3 * There is always at least one loopback device. This device is used also to
4 * loop back packets sent on other interfaces to the local interface address.
5 * Therefore, not all packets on the loopback device have a source or
6 * destination address corresponding to the loopback device.
7 */
9 #include "lwip.h"
12 * As a safety measure, if lwIP somehow gets stuck in a loop replying to its
13 * own packets on a loopback interface, stop with immediately feeding packets
14 * back into lwIP after this many packets. The remaining packets will still be
15 * delivered, but not before the main message loop has had a chance to run.
17 #define LOOPIF_LIMIT 65536
20 * The MTU is restricted to 65531 bytes, because we need space for a 4-byte
21 * header to identify the original interface of the packet.
23 #define LOOPIF_MAX_MTU (UINT16_MAX - sizeof(uint32_t)) /* maximum MTU */
24 #define LOOPIF_DEF_MTU LOOPIF_MAX_MTU /* default MTU */
26 #define NR_LOOPIF 2 /* number of loopback devices */
28 struct loopif {
29 struct ifdev loopif_ifdev; /* interface device, MUST be first */
30 struct pbuf *loopif_head; /* head of pending loopback packets */
31 struct pbuf **loopif_tailp; /* tail ptr-ptr of pending packets */
32 TAILQ_ENTRY(loopif) loopif_next; /* next in free list */
33 } loopif_array[NR_LOOPIF];
35 static TAILQ_HEAD(, loopif) loopif_freelist; /* free loop interfaces list */
36 static TAILQ_HEAD(, loopif) loopif_activelist; /* active loop interfaces */
38 #define loopif_get_netif(loopif) (ifdev_get_netif(&(loopif)->loopif_ifdev))
40 static unsigned int loopif_cksum_flags;
42 static int loopif_create(const char *name);
44 static const struct ifdev_ops loopif_ops;
47 * Initialize the loopback interface module.
49 void
50 loopif_init(void)
52 unsigned int slot;
54 /* Initialize the lists of loopback interfaces. */
55 TAILQ_INIT(&loopif_freelist);
56 TAILQ_INIT(&loopif_activelist);
58 for (slot = 0; slot < __arraycount(loopif_array); slot++)
59 TAILQ_INSERT_TAIL(&loopif_freelist, &loopif_array[slot],
60 loopif_next);
63 * The default is to perform no checksumming on loopback interfaces,
64 * except for ICMP messages because otherwise we would need additional
65 * changes in the code receiving those. In fact, for future
66 * compatibility, disable only those flags that we manage ourselves.
68 loopif_cksum_flags = NETIF_CHECKSUM_ENABLE_ALL &
69 ~(NETIF_CHECKSUM_GEN_IP | NETIF_CHECKSUM_CHECK_IP |
70 NETIF_CHECKSUM_GEN_UDP | NETIF_CHECKSUM_CHECK_UDP |
71 NETIF_CHECKSUM_GEN_TCP | NETIF_CHECKSUM_CHECK_TCP);
73 /* Tell the ifdev module that users may create more loopif devices. */
74 ifdev_register("lo", loopif_create);
78 * Polling function, invoked after each message loop iteration. Forward any
79 * packets received on the output side of the loopback device during this
80 * loop iteration, to the input side of the device.
82 static void
83 loopif_poll(struct ifdev * ifdev)
85 struct loopif *loopif = (struct loopif *)ifdev;
86 struct pbuf *pbuf, **pnext;
87 struct ifdev *oifdev;
88 struct netif *netif;
89 uint32_t oifindex;
90 unsigned int count;
91 static int warned = FALSE;
93 count = 0;
95 while ((pbuf = loopif->loopif_head) != NULL) {
97 * Prevent endless loops. Keep in mind that packets may be
98 * added to the queue as part of processing packets from the
99 * queue here, so the queue itself will never reach this
100 * length. As such the limit can (and must) be fairly high.
102 * In any case, if this warning is shown, that basically means
103 * that a bug in lwIP has been triggered. There should be no
104 * such bugs, so if there are, they should be fixed in lwIP.
106 if (count++ == LOOPIF_LIMIT) {
107 if (!warned) {
108 printf("LWIP: excess loopback traffic, "
109 "throttling output\n");
110 warned = TRUE;
113 break;
116 pnext = pchain_end(pbuf);
118 if ((loopif->loopif_head = *pnext) == NULL)
119 loopif->loopif_tailp = &loopif->loopif_head;
120 *pnext = NULL;
123 * Get the original interface for the packet, which if non-zero
124 * must also be used to pass the packet back to. The interface
125 * should still exist in all cases, but better safe than sorry.
127 memcpy(&oifindex, pbuf->payload, sizeof(oifindex));
129 util_pbuf_header(pbuf, -(int)sizeof(oifindex));
131 if (oifindex != 0 &&
132 (oifdev = ifdev_get_by_index(oifindex)) != NULL)
133 netif = ifdev_get_netif(oifdev);
134 else
135 netif = NULL;
138 * Loopback devices hand packets to BPF on output only. Doing
139 * so on input as well would duplicate all captured packets.
141 ifdev_input(ifdev, pbuf, netif, FALSE /*to_bpf*/);
146 * Process a packet as output on a loopback interface. Packets cannot be
147 * passed back into lwIP right away, nor can the original packets be passed
148 * back into lwIP. Therefore, make a copy of the packet, and pass it back to
149 * lwIP at the end of the current message loop iteration.
151 static err_t
152 loopif_output(struct ifdev * ifdev, struct pbuf * pbuf, struct netif * netif)
154 struct loopif *loopif = (struct loopif *)ifdev;
155 struct ifdev *oifdev;
156 struct pbuf *pcopy;
157 uint32_t oifindex;
159 /* Reject oversized packets immediately. This should not happen. */
160 if (pbuf->tot_len > UINT16_MAX - sizeof(oifindex)) {
161 printf("LWIP: attempt to send oversized loopback packet\n");
163 return ERR_MEM;
167 * If the service is low on memory, this is a likely place where
168 * allocation failures will occur. Thus, do not print anything here.
169 * The user can diagnose such problems with interface statistics.
171 pcopy = pchain_alloc(PBUF_RAW, sizeof(oifindex) + pbuf->tot_len);
172 if (pcopy == NULL) {
173 ifdev_output_drop(ifdev);
175 return ERR_MEM;
179 * If the packet was purposely diverted from a non-loopback interface
180 * to this interface, we have to remember the original interface, so
181 * that we can pass back the packet to that interface as well. If we
182 * don't, packets to link-local addresses assigned to non-loopback
183 * interfaces will not be processed correctly.
185 if (netif != NULL) {
186 oifdev = netif_get_ifdev(netif);
187 oifindex = ifdev_get_index(oifdev);
188 } else
189 oifindex = 0;
191 assert(pcopy->len >= sizeof(oifindex));
193 memcpy(pcopy->payload, &oifindex, sizeof(oifindex));
195 util_pbuf_header(pcopy, -(int)sizeof(oifindex));
197 if (pbuf_copy(pcopy, pbuf) != ERR_OK)
198 panic("unexpected pbuf copy failure");
200 pcopy->flags |= pbuf->flags & (PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST);
202 util_pbuf_header(pcopy, sizeof(oifindex));
204 *loopif->loopif_tailp = pcopy;
205 loopif->loopif_tailp = pchain_end(pcopy);
207 return ERR_OK;
211 * Initialization function for a loopback-type netif interface, called from
212 * lwIP at interface creation time.
214 static err_t
215 loopif_init_netif(struct ifdev * ifdev, struct netif * netif)
218 netif->name[0] = 'l';
219 netif->name[1] = 'o';
222 * FIXME: unfortunately, lwIP does not allow one to enable multicast on
223 * an interface without also enabling multicast management traffic
224 * (that is, IGMP and MLD). Thus, for now, joining multicast groups
225 * and assigning local IPv6 addresses will incur such traffic even on
226 * loopback interfaces. For now this is preferable over not supporting
227 * multicast on loopback interfaces at all.
229 netif->flags |= NETIF_FLAG_IGMP | NETIF_FLAG_MLD6;
231 NETIF_SET_CHECKSUM_CTRL(netif, loopif_cksum_flags);
233 return ERR_OK;
237 * Create a new loopback device.
239 static int
240 loopif_create(const char * name)
242 struct loopif *loopif;
244 /* Find a free loopback interface slot, if available. */
245 if (TAILQ_EMPTY(&loopif_freelist))
246 return ENOBUFS;
248 loopif = TAILQ_FIRST(&loopif_freelist);
249 TAILQ_REMOVE(&loopif_freelist, loopif, loopif_next);
251 /* Initialize the loopif structure. */
252 TAILQ_INSERT_HEAD(&loopif_activelist, loopif, loopif_next);
254 loopif->loopif_head = NULL;
255 loopif->loopif_tailp = &loopif->loopif_head;
258 * For simplicity and efficiency, we do not prepend the address family
259 * (IPv4/IPv6) to the packet for BPF, which means our loopback devices
260 * are of type DLT_RAW rather than (NetBSD's) DLT_NULL.
262 ifdev_add(&loopif->loopif_ifdev, name, IFF_LOOPBACK | IFF_MULTICAST,
263 IFT_LOOP, 0 /*hdrlen*/, 0 /*addrlen*/, DLT_RAW, LOOPIF_MAX_MTU,
264 0 /*nd6flags*/, &loopif_ops);
266 ifdev_update_link(&loopif->loopif_ifdev, LINK_STATE_UP);
268 return OK;
272 * Destroy an existing loopback device.
274 static int
275 loopif_destroy(struct ifdev * ifdev)
277 struct loopif *loopif = (struct loopif *)ifdev;
278 struct pbuf *pbuf, **pnext;
279 int r;
282 * The ifdev module may refuse to remove this interface if it is the
283 * loopback interface used to loop back packets for other interfaces.
285 if ((r = ifdev_remove(&loopif->loopif_ifdev)) != OK)
286 return r;
289 * Clean up. The loopback queue can be non-empty only if we have been
290 * throttling in case of a feedback loop.
292 while ((pbuf = loopif->loopif_head) != NULL) {
293 pnext = pchain_end(pbuf);
295 if ((loopif->loopif_head = *pnext) == NULL)
296 loopif->loopif_tailp = &loopif->loopif_head;
297 *pnext = NULL;
299 pbuf_free(pbuf);
302 TAILQ_REMOVE(&loopif_activelist, loopif, loopif_next);
304 TAILQ_INSERT_HEAD(&loopif_freelist, loopif, loopif_next);
306 return OK;
310 * Set NetBSD-style interface flags (IFF_) for a loopback interface.
312 static int
313 loopif_set_ifflags(struct ifdev * ifdev, unsigned int ifflags)
315 struct loopif *loopif = (struct loopif *)ifdev;
318 * Only the IFF_UP flag may be set and cleared. We adjust the
319 * IFF_RUNNING flag immediately based on this flag. This is a bit
320 * dangerous, but the caller takes this possibility into account.
322 if ((ifflags & ~IFF_UP) != 0)
323 return EINVAL;
325 if (ifflags & IFF_UP)
326 ifdev_update_ifflags(&loopif->loopif_ifdev,
327 ifdev_get_ifflags(&loopif->loopif_ifdev) | IFF_RUNNING);
328 else
329 ifdev_update_ifflags(&loopif->loopif_ifdev,
330 ifdev_get_ifflags(&loopif->loopif_ifdev) & ~IFF_RUNNING);
332 return OK;
336 * Set the Maximum Transmission Unit for this interface. Return TRUE if the
337 * new value is acceptable, in which case the caller will do the rest. Return
338 * FALSE otherwise.
340 static int
341 loopif_set_mtu(struct ifdev * ifdev __unused, unsigned int mtu)
344 return (mtu <= LOOPIF_MAX_MTU);
347 static const struct ifdev_ops loopif_ops = {
348 .iop_init = loopif_init_netif,
349 .iop_input = ip_input,
350 .iop_output = loopif_output,
351 .iop_poll = loopif_poll,
352 .iop_set_ifflags = loopif_set_ifflags,
353 .iop_set_mtu = loopif_set_mtu,
354 .iop_destroy = loopif_destroy,
358 * Set and/or retrieve a per-protocol loopback checksumming option through
359 * sysctl(7).
361 ssize_t
362 loopif_cksum(struct rmib_call * call, struct rmib_node * node __unused,
363 struct rmib_oldp * oldp, struct rmib_newp * newp)
365 struct loopif *loopif;
366 unsigned int flags;
367 int r, val;
370 * The third name field is the protocol. We ignore the domain (the
371 * second field), thus sharing settings between PF_INET and PF_INET6.
372 * This is necessary because lwIP does not support TCP/UDP checksumming
373 * flags on a per-domain basis.
375 switch (call->call_oname[2]) {
376 case IPPROTO_IP:
377 flags = NETIF_CHECKSUM_GEN_IP | NETIF_CHECKSUM_CHECK_IP;
378 break;
379 case IPPROTO_UDP:
380 flags = NETIF_CHECKSUM_GEN_UDP | NETIF_CHECKSUM_CHECK_UDP;
381 break;
382 case IPPROTO_TCP:
383 flags = NETIF_CHECKSUM_GEN_TCP | NETIF_CHECKSUM_CHECK_TCP;
384 break;
385 default:
386 return EINVAL;
389 /* Copy out the old (current) checksumming option. */
390 if (oldp != NULL) {
391 val = !!(loopif_cksum_flags & flags);
393 if ((r = rmib_copyout(oldp, 0, &val, sizeof(val))) < 0)
394 return r;
397 if (newp != NULL) {
398 if ((r = rmib_copyin(newp, &val, sizeof(val))) != OK)
399 return r;
401 if (val)
402 loopif_cksum_flags |= flags;
403 else
404 loopif_cksum_flags &= ~flags;
407 * Apply the new checksum flags to all loopback interfaces.
408 * Technically, this may result in dropped packets when
409 * enabling checksumming on a throttled loopif, but that is a
410 * case so rare and unimportant that we ignore it.
412 TAILQ_FOREACH(loopif, &loopif_activelist, loopif_next) {
413 NETIF_SET_CHECKSUM_CTRL(loopif_get_netif(loopif),
414 loopif_cksum_flags);
418 /* Return the length of the node. */
419 return sizeof(val);