Socket sendmsg() porting question

21 views
Skip to first unread message

Lundberg, Johannes

unread,
Aug 3, 2016, 12:54:58 PM8/3/16
to
Hi

I'm porting a project to fbsd and I have problem with this part that works
in linux but not fbsd when fd = -1.

https://github.com/Cloudef/wlc/blob/master/src/session/fd.c#L80-L108

I get "invalid argument" from sendmsg() when setting CMSG_LEN(0).

Anyone have a clue how to correctly do this on fbsd?

Thanks!

Johannes

--
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
秘密保持について:この電子メールは、名宛人に送信したものであり、秘匿特権の対象となる情報を含んでいます。
もし、名宛人以外の方が受信された場合、このメールの破棄、およびこのメールに関する一切の開示、
複写、配布、その他の利用、または記載内容に基づくいかなる行動もされないようお願い申し上げます。
---
CONFIDENTIALITY NOTE: The information in this email is confidential
and intended solely for the addressee.
Disclosure, copying, distribution or any other action of use of this
email by person other than intended recipient, is prohibited.
If you are not the intended recipient and have received this email in
error, please destroy the original message.
_______________________________________________
freebsd...@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-curre...@freebsd.org"

Alan Somers

unread,
Aug 3, 2016, 1:12:48 PM8/3/16
to
On Wed, Aug 3, 2016 at 10:54 AM, Lundberg, Johannes
<joha...@brilliantservice.co.jp> wrote:
> Hi
>
> I'm porting a project to fbsd and I have problem with this part that works
> in linux but not fbsd when fd = -1.
>
> https://github.com/Cloudef/wlc/blob/master/src/session/fd.c#L80-L108
>
> I get "invalid argument" from sendmsg() when setting CMSG_LEN(0).
>
> Anyone have a clue how to correctly do this on fbsd?
>
> Thanks!
>
> Johannes
>

It sounds like you're trying to send an empty cmsg. The error may
happen because your msg_controllen field is inconsistent with your
cmsg_len field. You're setting msg_controllen as if there were a full
cmsg, but then cmsg_len says that there is no cmsg. Or maybe the
error is because (just guessing) FreeBSD doesn't allow sending empty
or undefined cmsgs. Notice that cmsg_level and cmsg_type are
undefined in the case where fd == -1. POSIX doesn't say whether
sendmsg supports empty cmsgs, but why bother? You could just use send
instead of sendmsg if you're not sending a file descriptor.

-Alan

Lundberg, Johannes

unread,
Aug 3, 2016, 1:19:05 PM8/3/16
to
​Hi Alan

Thanks for the reply.

Can I still use the same receiving function for sendmsg/send and tell what
kind of message is coming?
How would I tell if there is an fd attached or not?

Even if I set cmsg_level and cmsg_type it won't let me send it. The problem
is having a zero length attachment on freebsd....
I can't send -1 as fd because that errors to invalid file descriptor.


On Wed, Aug 3, 2016 at 10:12 AM, Alan Somers <aso...@freebsd.org> wrote:

> On Wed, Aug 3, 2016 at 10:54 AM, Lundberg, Johannes
> <joha...@brilliantservice.co.jp> wrote:
> > Hi
> >
> > I'm porting a project to fbsd and I have problem with this part that
> works
> > in linux but not fbsd when fd = -1.
> >
> > https://github.com/Cloudef/wlc/blob/master/src/session/fd.c#L80-L108
> >
> > I get "invalid argument" from sendmsg() when setting CMSG_LEN(0).
> >
> > Anyone have a clue how to correctly do this on fbsd?
> >
> > Thanks!
> >
> > Johannes
> >
>
> It sounds like you're trying to send an empty cmsg. The error may
> happen because your msg_controllen field is inconsistent with your
> cmsg_len field. You're setting msg_controllen as if there were a full
> cmsg, but then cmsg_len says that there is no cmsg. Or maybe the
> error is because (just guessing) FreeBSD doesn't allow sending empty
> or undefined cmsgs. Notice that cmsg_level and cmsg_type are
> undefined in the case where fd == -1. POSIX doesn't say whether
> sendmsg supports empty cmsgs, but why bother? You could just use send
> instead of sendmsg if you're not sending a file descriptor.
>
> -Alan
>

--

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
秘密保持について:この電子メールは、名宛人に送信したものであり、秘匿特権の対象となる情報を含んでいます。
もし、名宛人以外の方が受信された場合、このメールの破棄、およびこのメールに関する一切の開示、
複写、配布、その他の利用、または記載内容に基づくいかなる行動もされないようお願い申し上げます。
---
CONFIDENTIALITY NOTE: The information in this email is confidential
and intended solely for the addressee.
Disclosure, copying, distribution or any other action of use of this
email by person other than intended recipient, is prohibited.
If you are not the intended recipient and have received this email in
error, please destroy the original message.

Julian Elischer

unread,
Aug 4, 2016, 3:15:21 AM8/4/16
to
I think it's a standards interpretation thing.

what data do you send WITH the message? I assume you have some in-band
data as well.

if you have no FD, just use "sendto()."

the other end will still be able to do a recvmesg() but will discover
no added info.

Ed Schouten

unread,
Aug 4, 2016, 3:15:41 AM8/4/16
to
2016-08-03 19:18 GMT+02:00 Lundberg, Johannes <joha...@brilliantservice.co.jp>:
> Even if I set cmsg_level and cmsg_type it won't let me send it. The problem
> is having a zero length attachment on freebsd....
> I can't send -1 as fd because that errors to invalid file descriptor.

Well, it makes sense. If you're attaching a message to a sendmsg()
call, it should have contents that make sense. Also, msg_controllen
should correspond with the actual space consumed by the message. Not a
single byte more. Change the logic to one of the following two.

Solution 1: Simply set msg_controllen to zero entirely, so there is no
message attached when sending.

struct cmsghdr *cmsg = CMSG_FIRSTHDR(&message);
if (fd >= 0) {
message.msg_controllen = CMSG_SPACE(sizeof(fd));
cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
} else {
message.msg_controllen = 0;
}

Solution 2: Send a SCM_RIGHTS message that contains no file descriptors.

struct cmsghdr *cmsg = CMSG_FIRSTHDR(&message);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
if (fd >= 0) {
message.msg_controllen = CMSG_SPACE(sizeof(fd));
cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
} else {
message.msg_controllen = CMSG_SPACE(0);
cmsg->cmsg_len = CMSG_LEN(0);
}

Also worth mentioning:

char control[CMSG_SPACE(sizeof(int))];

That line is incorrect. The reason for this is that it may not be
sufficiently aligned. You have to make sure that the control message
buffer is aligned to at least 'struct cmsghdr', as CMSG_FIRSTHDR()
will do nothing more than return the buffer directly. Change that line
to one of the following two:

#include <stdalign.h>
alignas(struct cmsghdr) char control[CMSG_SPACE(sizeof(int))];

Or:

union {
struct cmsghdr a;
char b[CMSG_SPACE(sizeof(int))];
} control;

Best regards,
--
Ed Schouten <e...@nuxi.nl>
Nuxi, 's-Hertogenbosch, the Netherlands
KvK-nr.: 62051717
Reply all
Reply to author
Forward
0 new messages