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

From: Guy Yur <guyyur_at_gmail.com>
Date: Sat, 14 Jan 2023 20:46:00 UTC
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.

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