mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Socket: sending filedescriptors over UNIX sockets
This commit is contained in:
parent
62bca8e882
commit
d0425e8a54
@ -74,6 +74,9 @@ typedef struct birdsock {
|
||||
uint lifindex; /* local interface that received the datagram */
|
||||
/* laddr and lifindex are valid only if SKF_LADDR_RX flag is set to request it */
|
||||
|
||||
/* Filedescriptors to send/receive (UNIX) */
|
||||
int rxfd, txfd;
|
||||
|
||||
int af; /* System-dependend adress family (e.g. AF_INET) */
|
||||
int fd; /* System-dependent data */
|
||||
int index; /* Index in poll buffer */
|
||||
@ -143,6 +146,9 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shou
|
||||
#define SKF_HDRINCL 0x400 /* Used internally */
|
||||
#define SKF_PKTINFO 0x800 /* Used internally */
|
||||
|
||||
#define SKF_FD_RX 0x1000 /* Allow receiving filedescriptors (unix sockets) */
|
||||
#define SKF_FD_TX 0x2000 /* Allow sending filedescriptors (unix sockets) */
|
||||
|
||||
/*
|
||||
* Socket types SA SP DA DP IF TTL SendTo (?=may, -=must not, *=must)
|
||||
*/
|
||||
@ -157,6 +163,7 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shou
|
||||
#define SK_UNIX 9
|
||||
#define SK_SSH_ACTIVE 10 /* - - * * - ? - DA = host */
|
||||
#define SK_SSH 11
|
||||
#define SK_UNIX_MSG 12 /* Like SK_UNIX but using sendmsg and recvmsg */
|
||||
|
||||
/*
|
||||
* Socket subtypes
|
||||
|
@ -300,6 +300,43 @@ sk_prepare_cmsgs6(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
msg->msg_controllen = controllen;
|
||||
}
|
||||
|
||||
/*
|
||||
* UNIX packet control messages
|
||||
*/
|
||||
|
||||
#define CMSGU_SPACE_FD CMSG_SPACE(sizeof (int))
|
||||
|
||||
static inline void
|
||||
sk_prepare_cmsgs_unix(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
{
|
||||
if (s->txfd < 0)
|
||||
{
|
||||
msg->msg_control = NULL;
|
||||
msg->msg_controllen = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
msg->msg_control = cbuf;
|
||||
msg->msg_controllen = cbuflen;
|
||||
|
||||
struct cmsghdr *cm = CMSG_FIRSTHDR(msg);
|
||||
cm->cmsg_level = SOL_SOCKET;
|
||||
cm->cmsg_type = SCM_RIGHTS;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof s->txfd);
|
||||
memcpy(CMSG_DATA(cm), &s->txfd, sizeof s->txfd);
|
||||
|
||||
msg->msg_controllen = CMSGU_SPACE_FD;
|
||||
}
|
||||
|
||||
static inline void
|
||||
sk_process_cmsg_unix_fd(sock *s, struct cmsghdr *cm)
|
||||
{
|
||||
if (cm->cmsg_type == SCM_RIGHTS)
|
||||
memcpy(&s->rxfd, CMSG_DATA(cm), sizeof s->rxfd);
|
||||
else
|
||||
s->rxfd = -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Miscellaneous socket syscalls
|
||||
@ -1420,14 +1457,17 @@ sk_open_unix(sock *s, struct birdloop *loop, const char *name)
|
||||
}
|
||||
|
||||
|
||||
#define CMSG_RX_SPACE MAX(CMSG4_SPACE_PKTINFO+CMSG4_SPACE_TTL, \
|
||||
CMSG6_SPACE_PKTINFO+CMSG6_SPACE_TTL)
|
||||
#define CMSG_TX_SPACE MAX(CMSG4_SPACE_PKTINFO,CMSG6_SPACE_PKTINFO)
|
||||
#define CMSG_RX_SPACE MAX(CMSGU_SPACE_FD, \
|
||||
MAX(CMSG4_SPACE_PKTINFO+CMSG4_SPACE_TTL, \
|
||||
CMSG6_SPACE_PKTINFO+CMSG6_SPACE_TTL))
|
||||
#define CMSG_TX_SPACE MAX(MAX(CMSG4_SPACE_PKTINFO,CMSG6_SPACE_PKTINFO),CMSGU_SPACE_FD)
|
||||
|
||||
static void
|
||||
sk_prepare_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
||||
{
|
||||
if (sk_is_ipv4(s))
|
||||
if (s->type == SK_UNIX_MSG)
|
||||
sk_prepare_cmsgs_unix(s, msg, cbuf, cbuflen);
|
||||
else if (sk_is_ipv4(s))
|
||||
sk_prepare_cmsgs4(s, msg, cbuf, cbuflen);
|
||||
else
|
||||
sk_prepare_cmsgs6(s, msg, cbuf, cbuflen);
|
||||
@ -1455,6 +1495,11 @@ sk_process_cmsgs(sock *s, struct msghdr *msg)
|
||||
sk_process_cmsg6_pktinfo(s, cm);
|
||||
sk_process_cmsg6_ttl(s, cm);
|
||||
}
|
||||
|
||||
if ((cm->cmsg_level == SOL_SOCKET) && (s->type == SK_UNIX_MSG))
|
||||
{
|
||||
sk_process_cmsg_unix_fd(s, cm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1467,15 +1512,19 @@ sk_sendmsg(sock *s)
|
||||
sockaddr dst;
|
||||
int flags = 0;
|
||||
|
||||
sockaddr_fill(&dst, s->af, s->daddr, s->iface, s->dport);
|
||||
|
||||
struct msghdr msg = {
|
||||
.msg_name = &dst.sa,
|
||||
.msg_namelen = SA_LEN(dst),
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1
|
||||
};
|
||||
|
||||
if (s->type != SK_UNIX_MSG)
|
||||
{
|
||||
sockaddr_fill(&dst, s->af, s->daddr, s->iface, s->dport);
|
||||
|
||||
msg.msg_name = &dst.sa;
|
||||
msg.msg_namelen = SA_LEN(dst);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DONTROUTE_UNICAST
|
||||
/* FreeBSD silently changes TTL to 1 when MSG_DONTROUTE is used, therefore we
|
||||
cannot use it for other cases (e.g. when TTL security is used). */
|
||||
@ -1495,7 +1544,7 @@ sk_sendmsg(sock *s)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s->flags & SKF_PKTINFO)
|
||||
if (s->flags & (SKF_PKTINFO | SKF_FD_TX))
|
||||
sk_prepare_cmsgs(s, &msg, cmsg_buf, sizeof(cmsg_buf));
|
||||
|
||||
return sendmsg(s->fd, &msg, flags);
|
||||
@ -1602,6 +1651,7 @@ sk_maybe_write(sock *s)
|
||||
|
||||
case SK_UDP:
|
||||
case SK_IP:
|
||||
case SK_UNIX_MSG:
|
||||
{
|
||||
if (s->tbuf == s->tpos)
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user