Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,9 @@ EOF
echo "yes"
echo "SANITIZEADDRESS= yes" >>$CONFIG_MK
echo "CPPFLAGS+= -DASAN" >>$CONFIG_MK
echo "CFLAGS+= -fsanitize=address" >>$CONFIG_MK
echo "CFLAGS+= -fsanitize=address,undefined" >>$CONFIG_MK
echo "CFLAGS+= -fno-omit-frame-pointer" >>$CONFIG_MK
echo "LDFLAGS+= -fsanitize=address" >>$CONFIG_MK
echo "LDFLAGS+= -fsanitize=address,undefined" >>$CONFIG_MK
else
echo "no"
fi
Expand Down Expand Up @@ -591,6 +591,30 @@ fi
rm -rf _inet_ntoa.* _inet_ntoa
$abort && exit 1

if [ -z "$LINK_SRC" ]; then
printf "Testing for route ..."
cat << EOF >_route.c
#include <net/route.h>
int main(void) {
#ifdef RTM_IFINFO
return 0;
#endif
}
EOF
if $XCC _route.c -o _route 2>&3; then
LINK_SRC="route.c"
echo "yes"
else
echo "no"
fi
rm -rf _route.* _route
fi
if [ -z "$LINK_SRC" ]; then
echo "no mechanism for detecting interface departures found" >&2
exit 1
fi
echo "LINK_SRC= $LINK_SRC" >>$CONFIG_MK

if [ -z "$SETPROCTITLE" ]; then
printf "Testing for setproctitle ... "
cat << EOF >_setproctitle.c
Expand Down Expand Up @@ -742,7 +766,5 @@ echo " LIBDIR = $LIBDIR"
echo " DATADIR = $DATADIR"
echo " RUNDIR = $RUNDIR"
echo " MANDIR = $MANDIR"
if [ "$PRIVSEP" = yes ]; then
echo " PRIVSEPUSER = $PRIVSEP_USER"
fi
echo " DHCPSD_USER = $DHCPSD_USER"
echo
9 changes: 5 additions & 4 deletions src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ PROG= dhcpsd
SRCS= dhcpsd.c common.c eloop.c if.c logerr.c
SRCS+= bpf.c dhcp.c dhcp_lease.c
SRCS+= if_none.c if_ether.c
SRCS+= service.c unpriv.c
SRCS+= service.c priv.c unpriv.c
SRCS+= plugin.c
OBJS+= ${SRCS:.c=.o}
SRCS+= ${LINK_SRC}
OBJS+= ${SRCS:.c=.o}

PVENDOR_SRCS= ${VENDOR_SRCS:vendor/%=${TOP}/vendor/%}
OBJS+= ${PVENDOR_SRCS:.c=.o}
OBJS+= ${PVENDOR_SRCS:.c=.o}

PCOMPAT_SRCS= ${COMPAT_SRCS:compat/%=${TOP}/compat/%}
OBJS+= ${PCOMPAT_SRCS:.c=.o}
OBJS+= ${PCOMPAT_SRCS:.c=.o}

CFLAGS?= -O2
SUBDIRS= plugins
Expand Down
7 changes: 3 additions & 4 deletions src/bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ bpf_open(const struct interface *ifp, int (*filter)(const struct bpf *),
#else
struct bpf_version pv = { .bv_major = 0, .bv_minor = 0 };
struct ifreq ifr = { .ifr_flags = 0 };
#if 0
#if 1
int ibuf_len = 0;
#endif
Comment on lines +400 to 402
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e

printf 'bpf_open call sites and nearby flags:\n\n'
rg -nP -C3 '\bbpf_open\s*\(' src

printf '\nCurrent allocation guard in src/bpf.c:\n\n'
sed -n '505,518p' src/bpf.c

Repository: NetworkConfiguration/dhcpsd

Length of output: 1385


🏁 Script executed:

#!/bin/bash

# 1. Check POSIX flag values in standard headers
echo "=== POSIX O_* flag definitions ===" 
grep -rn "define O_RDONLY\|define O_WRONLY\|define O_RDWR\|define O_ACCMODE" /usr/include --include="*.h" 2>/dev/null | head -20

echo ""
echo "=== All bpf_open call sites ===" 
rg -n '\bbpf_open\s*\(' src

echo ""
echo "=== Context: src/bpf.c lines 395-410 (around line 400) ===" 
sed -n '395,410p' src/bpf.c

echo ""
echo "=== Context: src/bpf.c lines 505-520 (allocation guard) ===" 
sed -n '505,520p' src/bpf.c

echo ""
echo "=== Check for bpf_read definition and usage ===" 
grep -n "^bpf_read" src/bpf.c | head -5
rg -n 'bpf_read\s*\(' src --max-count=10

Repository: NetworkConfiguration/dhcpsd

Length of output: 1372


🏁 Script executed:

#!/bin/bash

echo "=== All invocations of bpf_read() ===" 
rg -n '\bbpf_read\s*\(' src

echo ""
echo "=== bpf_read function body (lines 534-560) ===" 
sed -n '534,560p' src/bpf.c

echo ""
echo "=== Check lines 530-584 context mentioned in review ===" 
sed -n '530,545p' src/bpf.c

echo ""
echo "=== Verify POSIX flag semantics via C headers ===" 
cat > /tmp/check_flags.c << 'EOF'
`#include` <fcntl.h>
`#include` <stdio.h>
int main() {
    printf("O_RDONLY=%d\nO_WRONLY=%d\nO_RDWR=%d\nO_ACCMODE=%d\n",
           O_RDONLY, O_WRONLY, O_RDWR, O_ACCMODE);
    printf("\nO_RDONLY & (O_RDONLY | O_RDWR) = %d\n", O_RDONLY & (O_RDONLY | O_RDWR));
    printf("O_RDWR & (O_RDONLY | O_RDWR) = %d\n", O_RDWR & (O_RDONLY | O_RDWR));
    printf("(O_RDONLY & O_ACCMODE) != O_WRONLY: %d\n", (O_RDONLY & O_ACCMODE) != O_WRONLY);
    printf("(O_RDWR & O_ACCMODE) != O_WRONLY: %d\n", (O_RDWR & O_ACCMODE) != O_WRONLY);
    printf("(O_WRONLY & O_ACCMODE) != O_WRONLY: %d\n", (O_WRONLY & O_ACCMODE) != O_WRONLY);
    return 0;
}
EOF
gcc /tmp/check_flags.c -o /tmp/check_flags && /tmp/check_flags

Repository: NetworkConfiguration/dhcpsd

Length of output: 1549


🏁 Script executed:

#!/bin/bash

echo "=== Check if bpf_read is exported or used elsewhere ===" 
rg -n 'bpf_read' src --type c --type h

echo ""
echo "=== Verify the flags semantics with known values ===" 
python3 << 'EOF'
# POSIX standard values
O_RDONLY = 0
O_WRONLY = 1
O_RDWR = 2
O_ACCMODE = 3

print("POSIX flag values:")
print(f"  O_RDONLY = {O_RDONLY}")
print(f"  O_WRONLY = {O_WRONLY}")
print(f"  O_RDWR = {O_RDWR}")
print(f"  O_ACCMODE = {O_ACCMODE}")

print("\nCurrent guard: if (flags & (O_RDONLY | O_WRONLY))")
print(f"  With O_RDONLY: {O_RDONLY} & ({O_RDONLY} | {O_RDWR}) = {O_RDONLY & (O_RDONLY | O_RDWR)} (False - FAILS TO ALLOCATE)")
print(f"  With O_WRONLY: {O_WRONLY} & ({O_RDONLY} | {O_RDWR}) = {O_WRONLY & (O_RDONLY | O_RDWR)} (False - expected)")
print(f"  With O_RDWR:   {O_RDWR} & ({O_RDONLY} | {O_RDWR}) = {O_RDWR & (O_RDONLY | O_RDWR)} (True - correct)")

print("\nProposed fix: if ((flags & O_ACCMODE) != O_WRONLY)")
print(f"  With O_RDONLY: ({O_RDONLY} & {O_ACCMODE}) != {O_WRONLY} = {(O_RDONLY & O_ACCMODE) != O_WRONLY} (True - correct)")
print(f"  With O_WRONLY: ({O_WRONLY} & {O_ACCMODE}) != {O_WRONLY} = {(O_WRONLY & O_ACCMODE) != O_WRONLY} (False - correct)")
print(f"  With O_RDWR:   ({O_RDWR} & {O_ACCMODE}) != {O_WRONLY} = {(O_RDWR & O_ACCMODE) != O_WRONLY} (True - correct)")
EOF

echo ""
echo "=== Check bpf_read at line 543 for buffer access ===" 
sed -n '540,545p' src/bpf.c

Repository: NetworkConfiguration/dhcpsd

Length of output: 1023


Allocate the BPF read buffer by access mode, not O_RDONLY | O_RDWR.

Re-enabling bpf_read() makes this path depend on bpf->bpf_buffer, but the allocation check uses flags & (O_RDONLY | O_RDWR). Since O_RDONLY is 0, this condition evaluates to flags & 2, which fails for read-only opens and leaves bpf_buffer as NULL and bpf_size as 0. A read-only open to bpf_read() will then call read(bpf->bpf_fd, NULL, 0) at line 543, causing undefined behavior.

Proposed fix
-	if (flags & (O_RDONLY | O_RDWR)) {
+	if ((flags & O_ACCMODE) != O_WRONLY) {
 		/* Get the required BPF buffer length from the kernel. */
 		if (ioctl(bpf->bpf_fd, BIOCGBLEN, &ibuf_len) == -1)
 			goto eexit;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bpf.c` around lines 400 - 402, The allocation check for bpf->bpf_buffer
must test the open access mode correctly instead of using flags & (O_RDONLY |
O_RDWR) (O_RDONLY == 0), so modify the allocation logic (in the bpf open/init
path that sets bpf->bpf_buffer and bpf_size) to inspect (flags & O_ACCMODE) and
allocate when the mode is O_RDONLY or O_RDWR (or equivalent read-capable modes);
update the condition that gates buffer allocation to use (flags & O_ACCMODE) ==
O_RDONLY || (flags & O_ACCMODE) == O_RDWR (or test for read-capable flag),
ensure bpf_size > 0 when allocating, and keep bpf_read() usage consistent so
read(bpf->bpf_fd, bpf->bpf_buffer, bpf_size) never happens with a NULL buffer or
zero size.

unsigned int imm;
Expand Down Expand Up @@ -506,7 +506,6 @@ bpf_open(const struct interface *ifp, int (*filter)(const struct bpf *),
#ifdef __linux__
UNUSED(flags);
#else
#if 0
if (flags & (O_RDONLY | O_RDWR)) {
/* Get the required BPF buffer length from the kernel. */
if (ioctl(bpf->bpf_fd, BIOCGBLEN, &ibuf_len) == -1)
Expand All @@ -517,7 +516,6 @@ bpf_open(const struct interface *ifp, int (*filter)(const struct bpf *),
if (bpf->bpf_buffer == NULL)
goto eexit;
}
#endif
#endif

return bpf;
Expand Down Expand Up @@ -568,7 +566,8 @@ bpf_read(struct bpf *bpf, void *data, size_t len)
bytes = (ssize_t)len;
else
bytes = (ssize_t)packet.bh_caplen;
memcpy(data, payload, (size_t)bytes);
if (data)
memcpy(data, payload, (size_t)bytes);
next:
bpf->bpf_pos += BPF_WORDALIGN(
packet.bh_hdrlen + packet.bh_caplen);
Expand Down
15 changes: 14 additions & 1 deletion src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,20 @@ inet_ntocidr(struct in_addr *addr)
return cidr;
}

size_t
int
sa_is_link(const struct sockaddr *sa)
{
#ifdef AF_LINK
return sa->sa_family == AF_LINK ? 1 : 0;
#elif defined(AF_PACKET)
return sa->sa_family == AF_PACKET ? 1 : 0;
#else
errno = EAFNOSUPPORT;
return -1;
#endif
}

socklen_t
sa_len(const struct sockaddr *sa)
{
#ifdef BSD
Expand Down
3 changes: 2 additions & 1 deletion src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ uint8_t inet_ntocidr(struct in_addr *);

struct sockaddr;

size_t sa_len(const struct sockaddr *);
int sa_is_link(const struct sockaddr *);
socklen_t sa_len(const struct sockaddr *);
int sa_cmp(const struct sockaddr *, const struct sockaddr *);
#define ss_len(ss) sa_len((const struct sockaddr *)(ss))
int sa_pton(struct sockaddr *, const char *restrict);
Expand Down
112 changes: 43 additions & 69 deletions src/dhcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@

#include <fcntl.h>

#include "src/priv.h"

#ifdef AF_LINK
#include <net/if_dl.h>
#endif
Expand Down Expand Up @@ -110,8 +112,8 @@ static void dhcp_set_expire_timeout(struct dhcp_ctx *ctx);
static void dhcp_handlebootp(struct interface *ifp, struct bootp *bootp,
size_t len, uint32_t flags);

static inline int
dhcp_cookiecmp(struct bootp *bootp)
int
dhcp_cookiecmp(const struct bootp *bootp)
{
uint32_t cookie = htonl(MAGIC_COOKIE);

Expand Down Expand Up @@ -259,7 +261,7 @@ dhcp_findoption(const struct bootp *bootp, size_t len, uint8_t opt)
return NULL;
}

static void
static ssize_t
dhcp_outputudp(const struct interface *ifp, const size_t len)
{
const struct dhcp_ctx *ctx = ifp->if_ctx->ctx_dhcp;
Expand All @@ -272,22 +274,28 @@ dhcp_outputudp(const struct interface *ifp, const size_t len)
.sin_len = sizeof(sin),
#endif
};
ssize_t nbytes;

#ifdef HAVE_CASPER
if (cap_connect(ctx->dhcp_ctx->ctx_capnet, ctx->dhcp_capfd,
(struct sockaddr *)&sin, sizeof(sin)) == -1)
(struct sockaddr *)&sin, sizeof(sin)) == -1) {
logerr("%s: cap_connect", __func__);
else if (send(ctx->dhcp_capfd, bootp, len, 0) == -1)
return -1;
}
nbytes = send(ctx->dhcp_capfd, bootp, len, 0);
if (nbytes == -1)
logerr("%s: send", __func__);
#else
if (sendto(ctx->dhcp_fd, bootp, len, 0, (struct sockaddr *)&sin,
sizeof(sin)) == -1)
nbytes = sendto(ctx->dhcp_fd, bootp, len, 0, (struct sockaddr *)&sin,
sizeof(sin));
if (nbytes == -1)
logerr("%s: sendto", __func__);
#endif
return nbytes;
}

static void
dhcp_outputipudp(const struct interface *ifp, const struct in_addr *src,
static ssize_t
dhcp_outputipudp(struct interface *ifp, const struct in_addr *src,
const size_t len)
{
const struct dhcp_ctx *ctx = ifp->if_ctx->ctx_dhcp;
Expand Down Expand Up @@ -328,6 +336,7 @@ dhcp_outputipudp(const struct interface *ifp, const struct in_addr *src,
.iov_len = len,
},
};
ssize_t nbytes;

if (dhcp_cookiecmp(bootp) == 0 &&
((opt = dhcp_findoption(bootp, len, DHO_MESSAGETYPE)) != NULL) &&
Expand Down Expand Up @@ -360,9 +369,10 @@ dhcp_outputipudp(const struct interface *ifp, const struct in_addr *src,
in_cksum(&udp, sizeof(udp), &sum);
udp.uh_sum = in_cksum(bootp, len, &sum);

if (ifp->if_output(ifp, ifp->if_bpf->bpf_fd, iov, ARRAYCOUNT(iov)) ==
-1)
logerr("%s: if_output: %s", __func__, ifp->if_name);
nbytes = priv_sendbpf(ifp, iov, ARRAYCOUNT(iov));
if (nbytes == -1)
logerr("%s: priv_sendbpf: %s", __func__, ifp->if_name);
return nbytes;
}

static const char *
Expand Down Expand Up @@ -837,12 +847,12 @@ dhcp_addoptions(struct bootp *bootp, uint8_t **p, const uint8_t *e,
return 0;
}

static void
dhcp_output(const struct interface *ifp, const struct dhcp_lease *lease,
static ssize_t
dhcp_output(struct interface *ifp, const struct dhcp_lease *lease,
const uint8_t type, const char *msg, const struct bootp *req, size_t reqlen)
{
struct dhcp_ctx *ctx = ifp->if_ctx->ctx_dhcp;
struct bootp *bootp = ctx->dhcp_bootp;
struct bootp *bootp;
const struct dhcp_pool *pool;
struct in_addr addr;
uint8_t *p, *e;
Expand All @@ -852,6 +862,18 @@ dhcp_output(const struct interface *ifp, const struct dhcp_lease *lease,
const uint8_t *opt;
int err;

len = (size_t)ifp->if_mtu - sizeof(struct udphdr) - sizeof(struct ip);
if (len > ctx->dhcp_bootplen) {
void *n = realloc(ctx->dhcp_bootp, len);
if (n == NULL) {
logerr("%s: realloc", __func__);
return -1;
}
ctx->dhcp_bootp = n;
ctx->dhcp_bootplen = len;
}
Comment on lines +864 to +873
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate MTU to prevent short-buffer overflow.

len = (size_t)ifp->if_mtu - sizeof(struct udphdr) - sizeof(struct ip) is unchecked. For ifp->if_mtu values that are 0 (uninitialized, plausible under -w before the interface is fully configured) or <= 28, the subtraction wraps and produces a huge size_t, causing realloc to fail and the function to error out — recoverable. However, for MTUs in the narrow range of ~29..~327, the realloc succeeds with a buffer smaller than sizeof(struct bootp), and the very next memset(bootp, 0, sizeof(*bootp)) at line 877 overflows the heap. Clamp to a sensible floor.

🐛 Proposed fix
-	len = (size_t)ifp->if_mtu - sizeof(struct udphdr) - sizeof(struct ip);
+	if (ifp->if_mtu <= 0 ||
+	    (size_t)ifp->if_mtu <= sizeof(struct udphdr) + sizeof(struct ip)) {
+		logerrx("%s: interface mtu too small: %d",
+		    ifp->if_name, ifp->if_mtu);
+		return -1;
+	}
+	len = (size_t)ifp->if_mtu - sizeof(struct udphdr) - sizeof(struct ip);
+	if (len < sizeof(struct bootp))
+		len = sizeof(struct bootp);
 	if (len > ctx->dhcp_bootplen) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
len = (size_t)ifp->if_mtu - sizeof(struct udphdr) - sizeof(struct ip);
if (len > ctx->dhcp_bootplen) {
void *n = realloc(ctx->dhcp_bootp, len);
if (n == NULL) {
logerr("%s: realloc", __func__);
return -1;
}
ctx->dhcp_bootp = n;
ctx->dhcp_bootplen = len;
}
if (ifp->if_mtu <= 0 ||
(size_t)ifp->if_mtu <= sizeof(struct udphdr) + sizeof(struct ip)) {
logerrx("%s: interface mtu too small: %d",
ifp->if_name, ifp->if_mtu);
return -1;
}
len = (size_t)ifp->if_mtu - sizeof(struct udphdr) - sizeof(struct ip);
if (len < sizeof(struct bootp))
len = sizeof(struct bootp);
if (len > ctx->dhcp_bootplen) {
void *n = realloc(ctx->dhcp_bootp, len);
if (n == NULL) {
logerr("%s: realloc", __func__);
return -1;
}
ctx->dhcp_bootp = n;
ctx->dhcp_bootplen = len;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/dhcp.c` around lines 865 - 874, The calculation of len from ifp->if_mtu
can underflow or produce a buffer smaller than struct bootp causing a subsequent
memset overflow; before using ifp->if_mtu, validate and clamp it: compute
min_payload = sizeof(struct bootp) and required_mtu = min_payload +
sizeof(struct udphdr) + sizeof(struct ip), then if ifp->if_mtu is 0 or less than
required_mtu treat it as required_mtu (or skip realloc and keep existing
ctx->dhcp_bootplen if larger), set len = ifp->if_mtu - sizeof(struct udphdr) -
sizeof(struct ip) only after clamping, and ensure the resulting len >=
sizeof(struct bootp) before calling realloc on ctx->dhcp_bootp and updating
ctx->dhcp_bootplen to prevent heap overflow from the subsequent memset of the
bootp structure.


bootp = ctx->dhcp_bootp;
memset(bootp, 0, sizeof(*bootp));
bootp->op = BOOTREPLY;
bootp->flags = htons(ntohs(req->flags) & BROADCAST_FLAG);
Expand Down Expand Up @@ -909,7 +931,7 @@ dhcp_output(const struct interface *ifp, const struct dhcp_lease *lease,
ifp->if_name);
else {
logerr("%s: dhcp_addoptions", ifp->if_name);
return;
return -1;
}
}

Expand All @@ -928,10 +950,9 @@ dhcp_output(const struct interface *ifp, const struct dhcp_lease *lease,
bootp->xid, inet_ntoa(addr));
if (bootp->giaddr != INADDR_ANY ||
(bootp->ciaddr != INADDR_ANY && type != DHCP_NAK))
dhcp_outputudp(ifp, len);
else
dhcp_outputipudp(ifp, &pool->dp_addr, len);
return;
return dhcp_outputudp(ifp, len);

return dhcp_outputipudp(ifp, &pool->dp_addr, len);
}

static void
Expand Down Expand Up @@ -1644,7 +1665,7 @@ dhcp_readudp0(struct dhcp_ctx *ctx, int fd, unsigned short events)
if (ifp == NULL) {
/* This is a common situation for me when my tap
* interfaces come and go. */
#if 0
#if 1
logwarnx("dhcp: interface not found 0x%x %s", bootp->xid,
inet_ntoa(from.sin_addr));
#endif
Expand Down Expand Up @@ -1709,54 +1730,6 @@ dhcp_expire_leases(struct dhcp_ctx *ctx)
dhcp_set_expire_timeout(ctx);
}

int
dhcp_openbpf(struct interface *ifp)
{
struct ctx *ctx = ifp->if_ctx;
struct dhcp_ctx *dhcp_ctx = ctx->ctx_dhcp;
struct ifreq ifr = { .ifr_mtu = 0 };
size_t buflen;
#ifdef HAVE_CASPER
cap_rights_t rights;
#endif

/* Ensure our bootp write buffer is as big as the MTU */
strlcpy(ifr.ifr_name, ifp->if_name, sizeof(ifr.ifr_name));
if (ioctl(ctx->ctx_pf_inet_fd, SIOCGIFMTU, &ifr, sizeof(ifr)) == -1) {
logerr("%s SIOCGIFMTU", __func__);
return -1;
}
buflen = (size_t)ifr.ifr_mtu - sizeof(struct udphdr) -
sizeof(struct ip);
if (buflen > dhcp_ctx->dhcp_bootplen) {
void *n = realloc(dhcp_ctx->dhcp_bootp, buflen);
if (n == NULL) {
logerr("%s: realloc", __func__);
return -1;
}
dhcp_ctx->dhcp_bootp = n;
dhcp_ctx->dhcp_bootplen = buflen;
}

/*
* We only write to BPF, we don't read as we get the
* same data from the UDP socket even for unconfigured clients.
*/
ifp->if_bpf = bpf_open(ifp, bpf_bootp, O_WRONLY);
if (ifp->if_bpf == NULL)
return -1;

#ifdef HAVE_CASPER
cap_rights_init(&rights, CAP_WRITE);
if (caph_rights_limit(ifp->if_bpf->bpf_fd, &rights) == -1) {
logerr("%s: caph_rights_limit", __func__);
return -1;
}
#endif

return 0;
}

static int
dhcp_open(void)
{
Expand Down Expand Up @@ -1814,6 +1787,7 @@ dhcp_open(void)
goto errexit;
}

logdebugx("dhcp: listening on port %d", BOOTPS);
return s;

errexit:
Expand Down
7 changes: 4 additions & 3 deletions src/dhcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,15 @@ struct bootp {
#define DHCP_TTL 128
#define DHCP_LEASE_TIME 3600

struct interface;

struct dhcp_pool {
struct in_addr dp_addr;
struct in_addr dp_mask;
struct in_addr dp_from;
struct in_addr dp_to;
uint32_t dp_lease_time;
struct interface *dp_ifp;
};

#define DHCP_CLIENTID_LEN 1 + 255 /* first byte is length */
Expand Down Expand Up @@ -213,11 +216,8 @@ struct dhcp_ctx {
#endif
};

struct interface;

struct dhcp_ctx *dhcp_new(struct ctx *);
void dhcp_free(struct dhcp_ctx *);
int dhcp_openbpf(struct interface *);
void dhcp_expire_leases(struct dhcp_ctx *ctx);

struct dhcp_lease *dhcp_alloclease(void);
Expand All @@ -226,6 +226,7 @@ struct dhcp_lease *dhcp_newleaseaddr(struct dhcp_ctx *,
const struct dhcp_lease *);

/* For plugins to interogate the DHCP message */
int dhcp_cookiecmp(const struct bootp *);
const uint8_t *dhcp_findoption(const struct bootp *, size_t, uint8_t);

const char *dhcp_ftoa(uint32_t);
Expand Down
Loading
Loading