Sender
int sock = cloexec_socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) { ...
}
if (connect(sock, (struct sockaddr *)&ctl_addr,
offsetof(struct sockaddr_un, sun_path) +
strlen(ctl_addr.sun_path)) < 0) { ...
}
/* Send message */
#if 0 // NetBSD hack
const ssize_t min = 856;
if (len < min) {
llog(ERROR_STREAM, logger, "bumping up buffer from %td to %td",
len, min);
len = min; /* this just writes pat of the string
* buffer */
}
#endif
if (write(sock, msg, len) != len) { ...
where cloexec* is:
int cloexec_socket(int domain, int type, int protocol)
{
#ifdef SOCK_CLOEXEC
return socket(domain, type|SOCK_CLOEXEC, protocol);
#else
receiver:
delete_ctl_socket(); /* preventative medicine */
ctl_fd = cloexec_socket(AF_UNIX, SOCK_STREAM, 0);
if (ctl_fd == -1) { ...
}
/* to keep control socket secure, use umask */
#ifdef PLUTO_GROUP_CTL
mode_t ou = umask(~(S_IRWXU | S_IRWXG));
#else
mode_t ou = umask(~S_IRWXU);
#endif
if (bind(ctl_fd, (struct sockaddr *)&ctl_addr,
offsetof(struct sockaddr_un, sun_path) +
strlen(ctl_addr.sun_path)) < 0) { ...
}
umask(ou);
#ifdef PLUTO_GROUP_CTL
// some code never enabled
#endif
/*
* 5 (five) is a haphazardly chosen limit for the backlog.
* Rumour has it that this is the max on BSD systems.
*/
if (listen(ctl_fd, 5) < 0) { ...
}
....
feed ctl_fd into libevent with EV_READ|EV_PERSIST
....
struct whack_message msg = {0};
ssize_t n = fd_read(whackfd, &msg, sizeof(msg));
// aka ssize_t s = read(fd->fd, buf, nbytes);
if (n <= 0) {
llog_errno(ERROR_STREAM, whack_logger, -(int)n,
"read() failed in whack_handle(): ");
return;
}
static uintmax_t msgnum;
ldbgf(DBG_TMI, whack_logger, "whack message %ju; size=%zd",
msgnum++, n);
| struct fd: newref @0x6fe4fb574c68(0->1) (whack_handle_cb() +617
programs/pluto/rcv_whack.c)
| fd_accept: new fd@0x6fe4fb574c68 (whack_handle_cb() +617
programs/pluto/rcv_whack.c)
| whack message 1; size=400
On Fri, 31 Oct 2025 at 04:06, RVP <[email protected]> wrote:
>
> On Thu, 30 Oct 2025, Andrew Cagney wrote:
>
> > I've what I thought was some stock (if somewhat old) code that used a
> > SOCK_STREAM for communication between a daemon and its control
> > program.
> >
>
> What domain? AF_LOCAL or AF_INET{,6}?
>
> > Because the messages were all below the socket's buffer size (8K
> > according to getsockopt()), my understanding is partial reads
> > shouldn't happen.
> >
>
> With SOCK_STREAM, partial reads can always happen. If you want whole-packet
> reads (< MTU size) you'll have to use SOCK_DGRAM or SOCK_SEQPACKET; or send
> the message size too, so that the server can loop until it gets the whole
> packet.
yea, might be time to update to SOCK_SEQPACKET
> Let's see your code.
>
> -RVP