Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/bouyer-socketcan]: src/external/bsd/dhcpcd/dist/src 1965961



details:   https://anonhg.NetBSD.org/src/rev/1af24a426ff3
branches:  bouyer-socketcan
changeset: 820869:1af24a426ff3
user:      roy <roy%NetBSD.org@localhost>
date:      Fri Apr 14 09:56:33 2017 +0000

description:
1965961

diffstat:

 external/bsd/dhcpcd/dist/src/bpf.c        |   670 +++++++
 external/bsd/dhcpcd/dist/src/dhcpcd.c     |  1975 +++++++++++++++++++++
 external/bsd/dhcpcd/dist/src/if-options.c |  2615 +++++++++++++++++++++++++++++
 3 files changed, 5260 insertions(+), 0 deletions(-)

diffs (truncated from 5272 to 300 lines):

diff -r 398bfc126fb4 -r 1af24a426ff3 external/bsd/dhcpcd/dist/src/bpf.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/external/bsd/dhcpcd/dist/src/bpf.c        Fri Apr 14 09:56:33 2017 +0000
@@ -0,0 +1,670 @@
+/*
+ * dhcpcd: BPF arp and bootp filtering
+ * Copyright (c) 2006-2017 Roy Marples <roy%marples.name@localhost>
+ * 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/ioctl.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#ifdef __linux__
+/* Special BPF snowflake. */
+#include <linux/filter.h>
+#define        bpf_insn                sock_filter
+#else
+#include <net/bpf.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "common.h"
+#include "arp.h"
+#include "bpf.h"
+#include "dhcp.h"
+#include "if.h"
+#include "logerr.h"
+
+#define        ARP_ADDRS_MAX   3
+
+/* BPF helper macros */
+#ifdef __linux__
+#define        BPF_WHOLEPACKET         0x7fffffff /* work around buggy LPF filters */
+#else
+#define        BPF_WHOLEPACKET         ~0U
+#endif
+
+/* Macros to update the BPF structure */
+#define        BPF_SET_STMT(insn, c, v) {                              \
+       (insn)->code = (c);                                     \
+       (insn)->jt = 0;                                         \
+       (insn)->jf = 0;                                         \
+       (insn)->k = (uint32_t)(v);                              \
+};
+
+#define        BPF_SET_JUMP(insn, c, v, t, f) {                        \
+       (insn)->code = (c);                                     \
+       (insn)->jt = (t);                                       \
+       (insn)->jf = (f);                                       \
+       (insn)->k = (uint32_t)(v);                              \
+};
+
+size_t
+bpf_frame_header_len(const struct interface *ifp)
+{
+
+       switch(ifp->family) {
+       case ARPHRD_ETHER:
+               return sizeof(struct ether_header);
+       default:
+               return 0;
+       }
+}
+
+#ifndef __linux__
+/* Linux is a special snowflake for opening, attaching and reading BPF.
+ * See if-linux.c for the Linux specific BPF functions. */
+
+const char *bpf_name = "Berkley Packet Filter";
+
+int
+bpf_open(struct interface *ifp, int (*filter)(struct interface *, int))
+{
+       struct ipv4_state *state;
+       int fd = -1;
+       struct ifreq ifr;
+       int ibuf_len = 0;
+       size_t buf_len;
+       struct bpf_version pv;
+#ifdef BIOCIMMEDIATE
+       int flags;
+#endif
+#ifndef O_CLOEXEC
+       int fd_opts;
+#endif
+
+#ifdef _PATH_BPF
+       fd = open(_PATH_BPF, O_RDWR | O_NONBLOCK
+#ifdef O_CLOEXEC
+               | O_CLOEXEC
+#endif
+       );
+#else
+       char device[32];
+       int n = 0;
+
+       do {
+               snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+               fd = open(device, O_RDWR | O_NONBLOCK
+#ifdef O_CLOEXEC
+                               | O_CLOEXEC
+#endif
+               );
+       } while (fd == -1 && errno == EBUSY);
+#endif
+
+       if (fd == -1)
+               return -1;
+
+#ifndef O_CLOEXEC
+       if ((fd_opts = fcntl(fd, F_GETFD)) == -1 ||
+           fcntl(fd, F_SETFD, fd_opts | FD_CLOEXEC) == -1) {
+               close(fd);
+               return -1;
+       }
+#endif
+
+       memset(&pv, 0, sizeof(pv));
+       if (ioctl(fd, BIOCVERSION, &pv) == -1)
+               goto eexit;
+       if (pv.bv_major != BPF_MAJOR_VERSION ||
+           pv.bv_minor < BPF_MINOR_VERSION) {
+               logerrx("BPF version mismatch - recompile");
+               goto eexit;
+       }
+
+       if (filter(ifp, fd) != 0)
+               goto eexit;
+
+       memset(&ifr, 0, sizeof(ifr));
+       strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
+       if (ioctl(fd, BIOCSETIF, &ifr) == -1)
+               goto eexit;
+
+       /* Get the required BPF buffer length from the kernel. */
+       if (ioctl(fd, BIOCGBLEN, &ibuf_len) == -1)
+               goto eexit;
+       buf_len = (size_t)ibuf_len;
+       state = IPV4_STATE(ifp);
+       if (state->buffer_size != buf_len) {
+               void *nb;
+
+               if ((nb = realloc(state->buffer, buf_len)) == NULL)
+                       goto eexit;
+               state->buffer = nb;
+               state->buffer_size = buf_len;
+       }
+
+#ifdef BIOCIMMEDIATE
+       flags = 1;
+       if (ioctl(fd, BIOCIMMEDIATE, &flags) == -1)
+               goto eexit;
+#endif
+
+       return fd;
+
+eexit:
+       close(fd);
+       return -1;
+}
+
+/* BPF requires that we read the entire buffer.
+ * So we pass the buffer in the API so we can loop on >1 packet. */
+ssize_t
+bpf_read(struct interface *ifp, int fd, void *data, size_t len, int *flags)
+{
+       ssize_t fl = (ssize_t)bpf_frame_header_len(ifp);
+       ssize_t bytes;
+       struct ipv4_state *state = IPV4_STATE(ifp);
+
+       struct bpf_hdr packet;
+       const char *payload;
+
+       *flags = 0;
+       for (;;) {
+               if (state->buffer_len == 0) {
+                       bytes = read(fd, state->buffer, state->buffer_size);
+#if defined(__sun)
+                       /* After 2^31 bytes, the kernel offset overflows.
+                        * To work around this bug, lseek 0. */
+                       if (bytes == -1 && errno == EINVAL) {
+                               lseek(fd, 0, SEEK_SET);
+                               continue;
+                       }
+#endif
+                       if (bytes == -1 || bytes == 0)
+                               return bytes;
+                       state->buffer_len = (size_t)bytes;
+                       state->buffer_pos = 0;
+               }
+               bytes = -1;
+               memcpy(&packet, state->buffer + state->buffer_pos,
+                   sizeof(packet));
+               if (state->buffer_pos + packet.bh_caplen + packet.bh_hdrlen >
+                   state->buffer_len)
+                       goto next; /* Packet beyond buffer, drop. */
+               payload = state->buffer + state->buffer_pos +
+                   packet.bh_hdrlen + fl;
+               bytes = (ssize_t)packet.bh_caplen - fl;
+               if ((size_t)bytes > len)
+                       bytes = (ssize_t)len;
+               memcpy(data, payload, (size_t)bytes);
+next:
+               state->buffer_pos += BPF_WORDALIGN(packet.bh_hdrlen +
+                   packet.bh_caplen);
+               if (state->buffer_pos >= state->buffer_len) {
+                       state->buffer_len = state->buffer_pos = 0;
+                       *flags |= BPF_EOF;
+               }
+               if (bytes != -1)
+                       return bytes;
+       }
+
+       return bytes;
+}
+
+int
+bpf_attach(int fd, void *filter, unsigned int filter_len)
+{
+       struct bpf_program pf;
+
+       /* Install the filter. */
+       memset(&pf, 0, sizeof(pf));
+       pf.bf_insns = filter;
+       pf.bf_len = filter_len;
+       return ioctl(fd, BIOCSETF, &pf);
+}
+#endif
+
+#ifndef __sun
+/* SunOS is special too - sending via BPF goes nowhere. */
+ssize_t
+bpf_send(const struct interface *ifp, int fd, uint16_t protocol,
+    const void *data, size_t len)
+{
+       struct iovec iov[2];
+       struct ether_header eh;
+
+       switch(ifp->family) {
+       case ARPHRD_ETHER:
+               memset(&eh.ether_dhost, 0xff, sizeof(eh.ether_dhost));
+               memcpy(&eh.ether_shost, ifp->hwaddr, sizeof(eh.ether_shost));
+               eh.ether_type = htons(protocol);
+               iov[0].iov_base = &eh;
+               iov[0].iov_len = sizeof(eh);
+               break;
+       default:
+               iov[0].iov_base = NULL;
+               iov[0].iov_len = 0;
+               break;
+       }
+       iov[1].iov_base = UNCONST(data);
+       iov[1].iov_len = len;
+       return writev(fd, iov, 2);
+}
+#endif
+
+int
+bpf_close(struct interface *ifp, int fd)
+{
+       struct ipv4_state *state = IPV4_STATE(ifp);
+
+       /* Rewind the buffer on closing. */
+       state->buffer_len = state->buffer_pos = 0;
+       return close(fd);
+}



Home | Main Index | Thread Index | Old Index