diff --git a/include/sys/socket.h b/include/sys/socket.h index f7df0ce45ae..aa633ec7a47 100644 --- a/include/sys/socket.h +++ b/include/sys/socket.h @@ -202,6 +202,9 @@ */ #define SO_BINDTODEVICE 17 /* Bind this socket to a specific network device. */ +#define SO_PEERCRED 18 /* Return the credentials of the peer process + * connected to this socket. + */ /* The options are unsupported but included for compatibility * and portability @@ -330,6 +333,13 @@ struct cmsghdr int cmsg_type; /* Protocol-specific type */ }; +struct ucred +{ + pid_t pid; + uid_t uid; + gid_t gid; +}; + /**************************************************************************** * Inline Functions ****************************************************************************/ diff --git a/net/local/local.h b/net/local/local.h index 47235a318da..075254f0484 100644 --- a/net/local/local.h +++ b/net/local/local.h @@ -129,6 +129,7 @@ struct local_conn_s uint16_t lc_cfpcount; /* Control file pointer counter */ FAR struct file * lc_cfps[LOCAL_NCONTROLFDS]; /* Socket message control filep */ + struct ucred lc_cred; /* The credentials of connection instance */ #endif /* CONFIG_NET_LOCAL_SCM */ mutex_t lc_sendlock; /* Make sending multi-thread safe */ diff --git a/net/local/local_conn.c b/net/local/local_conn.c index 0abba63b588..efaac03a7d0 100644 --- a/net/local/local_conn.c +++ b/net/local/local_conn.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -129,6 +130,12 @@ FAR struct local_conn_s *local_alloc(void) nxmutex_init(&conn->lc_sendlock); +#ifdef CONFIG_NET_LOCAL_SCM + conn->lc_cred.pid = getpid(); + conn->lc_cred.uid = getuid(); + conn->lc_cred.gid = getgid(); +#endif + /* Add the connection structure to the list of listeners */ net_lock(); diff --git a/net/local/local_sockif.c b/net/local/local_sockif.c index a34776f348b..4d639e3f3a3 100644 --- a/net/local/local_sockif.c +++ b/net/local/local_sockif.c @@ -72,6 +72,12 @@ static int local_close(FAR struct socket *psock); static int local_ioctl(FAR struct socket *psock, int cmd, unsigned long arg); static int local_socketpair(FAR struct socket *psocks[2]); +#ifdef CONFIG_NET_SOCKOPTS +static int local_getsockopt(FAR struct socket *psock, int level, + int option, FAR void *value, FAR socklen_t *value_len); +static int local_setsockopt(FAR struct socket *psock, int level, + int option, FAR const void *value, socklen_t value_len); +#endif /**************************************************************************** * Public Data @@ -94,6 +100,10 @@ const struct sock_intf_s g_local_sockif = local_close, /* si_close */ local_ioctl, /* si_ioctl */ local_socketpair /* si_socketpair */ +#ifdef CONFIG_NET_SOCKOPTS + , local_getsockopt /* si_getsockopt */ + , local_setsockopt /* si_setsockopt */ +#endif }; /**************************************************************************** @@ -434,6 +444,88 @@ static int local_getpeername(FAR struct socket *psock, return local_getsockname(psock, addr, addrlen); } +#ifdef CONFIG_NET_SOCKOPTS + +/**************************************************************************** + * Name: local_getsockopt + * + * Description: + * local_getsockopt() retrieve the value for the option specified by the + * 'option' argument at the protocol level specified by the 'level' + * argument. If the size of the option value is greater than 'value_len', + * the value stored in the object pointed to by the 'value' argument will + * be silently truncated. Otherwise, the length pointed to by the + * 'value_len' argument will be modified to indicate the actual length + * of the 'value'. + * + * The 'level' argument specifies the protocol level of the option. To + * retrieve options at the socket level, specify the level argument as + * SOL_SOCKET. + * + * See a complete list of values for the 'option' argument. + * + * Input Parameters: + * psock Socket structure of the socket to query + * level Protocol level to set the option + * option identifies the option to get + * value Points to the argument value + * value_len The length of the argument value + * + ****************************************************************************/ + +static int local_getsockopt(FAR struct socket *psock, int level, int option, + FAR void *value, FAR socklen_t *value_len) +{ + DEBUGASSERT(psock != NULL && psock->s_conn != NULL && + psock->s_domain == PF_LOCAL); + +#ifdef CONFIG_NET_LOCAL_SCM + if (level == SOL_SOCKET && option == SO_PEERCRED) + { + FAR struct local_conn_s *conn = psock->s_conn; + if (*value_len != sizeof(struct ucred)) + { + return -EINVAL; + } + + memcpy(value, &conn->lc_peer->lc_cred, sizeof(struct ucred)); + return OK; + } +#endif + + return -ENOPROTOOPT; +} + +/**************************************************************************** + * Name: local_setsockopt + * + * Description: + * local_setsockopt() sets the option specified by the 'option' argument, + * at the protocol level specified by the 'level' argument, to the value + * pointed to by the 'value' argument for the usrsock connection. + * + * The 'level' argument specifies the protocol level of the option. To set + * options at the socket level, specify the level argument as SOL_SOCKET. + * + * See a complete list of values for the 'option' argument. + * + * Input Parameters: + * psock Socket structure of the socket to query + * level Protocol level to set the option + * option identifies the option to set + * value Points to the argument value + * value_len The length of the argument value + * + ****************************************************************************/ + +static int local_setsockopt(FAR struct socket *psock, int level, int option, + FAR const void *value, socklen_t value_len) +{ + return -ENOPROTOOPT; +} + +#endif + /**************************************************************************** * Name: local_listen *