]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
BPF: Add a DLPI interface
authorRoy Marples <roy@marples.name>
Tue, 19 May 2026 11:31:04 +0000 (12:31 +0100)
committerRoy Marples <roy@marples.name>
Tue, 19 May 2026 11:31:04 +0000 (12:31 +0100)
This works alongside the BSD interface.
We use the BSD interface for receiving and the DLPI interface
for sending.

configure
src/bpf-bsd.c
src/bpf-dlpi.c [new file with mode: 0644]
src/bpf-dlpi.h [new file with mode: 0644]
src/bpf.c
src/if-sun.c

index b92b139fd1307349d7866d6432b616575e357815..5c77cc6a995559c26d90351439283185ee364bf4 100755 (executable)
--- a/configure
+++ b/configure
@@ -515,6 +515,7 @@ solaris*|sunos*)
            >>$CONFIG_MK
        echo "DHCPCD_SRCS+=     if-sun.c" >>$CONFIG_MK
        echo "LDADD+=           -ldlpi -lkstat" >>$CONFIG_MK
+       BPF_OS="bpf-bsd.c bpf-dlpi.c"
        ;;
 *)
        echo "DHCPCD_SRCS+=     if-bsd.c" >>$CONFIG_MK
index 52503020731bc788671b604ed1c45172b9b56f76..1f1a63f8950d6225841d48c748ea6cc2dea90a4a 100644 (file)
@@ -38,6 +38,9 @@
 #include <string.h>
 
 #include "bpf.h"
+#ifdef __sun
+#include "bpf-dlpi.h"
+#endif
 #include "logerr.h"
 
 const char *bpf_name = "Berkeley Packet Filter";
@@ -123,6 +126,11 @@ bpf_open(const struct interface *ifp,
        if (bpf->bpf_buffer == NULL)
                goto eexit;
 
+#ifdef __sun
+       if (bpf_dlpi_open(bpf) == -1)
+               goto eexit;
+#endif
+
        return bpf;
 
 eexit:
@@ -251,6 +259,9 @@ bpf_writev(const struct bpf *bpf, struct iovec *iov, int iovcnt)
 void
 bpf_close(struct bpf *bpf)
 {
+#ifdef __sun
+       bpf_dlpi_close(bpf);
+#endif
        if (bpf->bpf_fd != -1)
                close(bpf->bpf_fd);
        free(bpf->bpf_buffer);
diff --git a/src/bpf-dlpi.c b/src/bpf-dlpi.c
new file mode 100644 (file)
index 0000000..27802c9
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * BPF DLPI interface
+ * SPDX-License-Identifier: BSD-2-Clause
+ * Copyright (c) 2006-2025 Roy Marples <roy@marples.name>
+ * All rights reserved
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <net/if.h>
+#include <netinet/if_ether.h>
+
+#include <errno.h>
+#include <libdlpi.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bpf.h"
+#include "bpf-dlpi.h"
+
+struct bpf_dlpi {
+       dlpi_handle_t bd_handle;
+       void *bd_buffer;
+       size_t bd_bufferlen;
+};
+
+int
+bpf_dlpi_open(struct bpf *bpf)
+{
+       const struct interface *ifp = bpf->bpf_ifp;
+       struct bpf_dlpi *bd;
+       int mtu;
+
+       bd = calloc(1, sizeof(*bd));
+       if (bd == NULL)
+               return -1;
+
+       if (dlpi_open(ifp->name, &bd->bd_handle, DLPI_RAW) != DLPI_SUCCESS) {
+               free(bd);
+               return -1;
+       }
+
+       bpf->bpf_handle = bd;
+
+       if (dlpi_bind(bd->bd_handle, DLPI_ANY_SAP, NULL) != DLPI_SUCCESS)
+               return -1;
+
+       mtu = ifp->mtu ? ifp->mtu : ETHERMTU;
+       bd->bd_bufferlen = bpf_frame_header_len(ifp) + (size_t)mtu;
+       bd->bd_buffer = malloc(bd->bd_bufferlen);
+       if (bpf->bpf_buffer == NULL)
+               return -1;
+
+       return 0;
+}
+
+ssize_t
+bpf_writev(const struct bpf *bpf, struct iovec *iov, int iovcnt)
+{
+       struct bpf_dlpi *bd = bpf->bpf_handle;
+       int i;
+       size_t len = 0;
+       uint8_t *bp = bd->bd_buffer;
+
+       for (i = 0; i < iovcnt; i++) {
+               /* This should be impossible. */
+               if (iov[i].iov_len > bd->bd_bufferlen - len) {
+                       errno = ENOBUFS;
+                       return -1;
+               }
+
+               memcpy(bp, iov[i].iov_base, iov[i].iov_len);
+               bp += iov[i].iov_len;
+               len += iov[i].iov_len;
+       }
+
+       i = dlpi_send(bd->bd_handle, NULL, 0, bd->bd_buffer, len, NULL);
+       return i == DLPI_SUCCESS ? (ssize_t)len : -1;
+}
+
+void
+bpf_dlpi_close(struct bpf *bpf)
+{
+       struct bpf_dlpi *bd = bpf->bpf_handle;
+
+       if (bd == NULL)
+               return;
+
+       dlpi_close(bd->bd_handle);
+       free(bd->bd_buffer);
+       free(bd);
+}
diff --git a/src/bpf-dlpi.h b/src/bpf-dlpi.h
new file mode 100644 (file)
index 0000000..dce8dce
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * BPF DLPI interface
+ * SPDX-License-Identifier: BSD-2-Clause
+ * Copyright (c) 2006-2025 Roy Marples <roy@marples.name>
+ * All rights reserved
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef BPF_DLPI_HEADER
+#define BPF_DLPI_HEADER
+
+struct bpf;
+
+int bpf_dlpi_open(struct bpf *);
+void bpf_dlpi_close(struct bpf *);
+#endif
index 19a0286a57556937834ddd41b35843a851ea7f12..78d9916674ac9d8e3c42c7decf7811b82ec949f5 100644 (file)
--- a/src/bpf.c
+++ b/src/bpf.c
@@ -138,7 +138,6 @@ bpf_frame_bcast(const struct interface *ifp, const void *frame)
        }
 }
 
-#ifndef __sun
 ssize_t
 bpf_send(const struct bpf *bpf, uint16_t protocol, const void *data, size_t len)
 {
@@ -164,7 +163,6 @@ bpf_send(const struct bpf *bpf, uint16_t protocol, const void *data, size_t len)
 
        return bpf_writev(bpf, iov, __arraycount(iov));
 }
-#endif
 
 #ifdef ARP
 #define BPF_CMP_HWADDR_LEN ((((HWADDR_LEN / 4) + 2) * 2) + 1)
index f46d4f34bd19986912ecafc628647c8b8dd38e68..0a9747692da6f8427314c97a9a98e801889b6d58 100644 (file)
  * SUCH DAMAGE.
  */
 
+/* Stop sunos headers including the system queue ... */
+#include "queue.h"
+
 #include <sys/ioctl.h>
 #include <sys/mac.h>
 #include <sys/pfmod.h>
 #include <sys/tihdr.h>
 #include <sys/utsname.h>
 
+#include <net/if.h>
 #include <net/if_dl.h>
 #include <net/if_types.h>
-#include <netinet/udp.h>
 #include <netinet/if_ether.h>
+#include <netinet/in.h>
+#include <netinet/udp.h>
 
 #include <assert.h>
 #include <errno.h>
@@ -1583,24 +1588,6 @@ if_initrt(struct dhcpcd_ctx *ctx, rb_tree_t *routes, int af)
 }
 
 #ifdef INET
-/* XXX We should fix this to write via the BPF interface. */
-ssize_t
-bpf_send(const struct bpf *bpf, uint16_t protocol, const void *data, size_t len)
-{
-       const struct interface *ifp = bpf->bpf_ifp;
-       dlpi_handle_t dh;
-       dlpi_info_t di;
-       int r;
-
-       if (dlpi_open(ifp->name, &dh, 0) != DLPI_SUCCESS)
-               return -1;
-       if ((r = dlpi_info(dh, &di, 0)) == DLPI_SUCCESS &&
-           (r = dlpi_bind(dh, protocol, NULL)) == DLPI_SUCCESS)
-               r = dlpi_send(dh, di.di_bcastaddr, ifp->hwlen, data, len, NULL);
-       dlpi_close(dh);
-       return r == DLPI_SUCCESS ? (ssize_t)len : -1;
-}
-
 int
 if_address(unsigned char cmd, const struct ipv4_addr *ia)
 {