Re: close(2) on a PF_ROUTE socket returns -1 and sets errno to EOPNOTSUPP

From: Alexander V. Chernikov <melifaro_at_ipfw.ru>
Date: Sun, 15 Jan 2023 13:50:48 UTC

> On 14 Jan 2023, at 20:46, Guy Yur <guyyur@gmail.com> wrote:
> 
> Hi,
> 
> close(2) on a PF_ROUTE socket returns -1 and sets errno to EOPNOTSUPP.
> I am testing 14.0-CURRENT (main branch) built today.
> On 13.1-RELEASE-p5 close returns 0.
> 
> The problem looks to be related to 36b10ac2cd18a535cac20ccf51e3fc6c408671e8.
> 
> The commit removed rts_disconnect and initialization for .pru_disconnect.
> After the change, .pr_disconnect is not initialized in rtsock.c
> so now it is set to pr_disconnect_notsupp.
> This causes flow of:
>   soclose()
>   sodisconnect()
>   so->so_proto->pr_disconnect()
>   pr_disconnect_notsupp()
>   return EOPNOTSUPP
> On 13.1 it called the raw socket disconnect which returned ENOTCONN.
> 
> Noticed in dhcpcd error: if_route (ADD): Operation not supported
> dhcpcd with privsep called write() which failed with EEXIST (expected since
> route already existed) and then close() which overwrote the errno to
> EOPNOTSUPP and the parent process received back EOPNOTSUPP instead of EEXIST.
Thank you for the report!
I’ve created https://reviews.freebsd.org/D38059 to address the issue.
> 
> 
> 
> Simple test program (prints error on head, no error on 13.1):
> 
> #include <sys/types.h>
> #include <sys/time.h>
> #include <sys/socket.h>
> #include <net/if.h>
> #include <net/route.h>
> #include <unistd.h>
> #include <err.h>
> 
> int main(int argc, char *argv[])
> {
>   int s = socket(PF_ROUTE, SOCK_RAW, 0);
>   if (s == -1)
>     err(1, "socket()");
>   if (close(s) == -1)
>     err(1, "close()");
>   return 0;
> }
> 
> 
> Regards,
> Guy Yur