Networking: Add logic for binding Unix domain sockets

This commit is contained in:
Gregory Nutt 2015-01-25 08:33:39 -06:00
parent 3b64518049
commit ffc02f30b0
3 changed files with 163 additions and 13 deletions

View File

@ -56,12 +56,21 @@
/****************************************************************************
* Public Type Definitions
****************************************************************************/
/* Local, Unix domain socket types */
enum local_type_e
{
LOCAL_TYPE_UNNAMED = 0, /* A Unix socket that is not bound to any name */
LOCAL_TYPE_PATHNAME, /* lc_path holds a null terminated string */
LOCAL_TYPE_ABSTRACT /* lc_path is length zero */
};
/* Representation of a local connection */
struct local_conn_s
{
uint8_t lc_crefs; /* Reference counts on this instance */
uint8_t lc_type; /* See enum local_type_e */
int16_t lc_fd; /* File descriptor of underlying pipe */
char lc_path[UNIX_PATH_MAX]; /* Path assigned by bind() */
};
@ -129,7 +138,7 @@ void local_free(FAR struct local_conn_s *conn);
****************************************************************************/
int local_bind(FAR struct local_conn_s *conn,
FAR const struct sockaddr *addr);
FAR const struct sockaddr *addr, socklen_t addrlen);
/****************************************************************************
* Name: local_connect

View File

@ -40,10 +40,12 @@
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_LOCAL)
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include "local/local.h"
/****************************************************************************
@ -81,7 +83,17 @@
FAR struct local_conn_s *local_alloc(void)
{
return (FAR struct local_conn_s *)malloc(sizeof(struct local_conn_s));
FAR struct local_conn_s *conn =
(FAR struct local_conn_s *)kmm_zalloc(sizeof(struct local_conn_s));
if (conn)
{
/* Make sure that the pipe is marked closed */
conn->lc_fd = -1;
}
return conn;
}
/****************************************************************************
@ -99,4 +111,56 @@ void local_free(FAR struct local_conn_s *conn)
free(conn);
}
/****************************************************************************
* Name: local_bind
*
* Description:
* This function implements the low-level parts of the standard local
* bind()operation.
*
****************************************************************************/
int local_bind(FAR struct local_conn_s *conn,
FAR const struct sockaddr *addr, socklen_t addrlen)
{
FAR const struct sockaddr_un *unaddr =
(FAR const struct sockaddr_un *)addr;
int namelen;
DEBUGASSERT(conn && unaddr && unaddr->sun_family == AF_LOCAL &&
addrlen >= sizeof(sa_family_t));
if (addrlen == sizeof(sa_family_t))
{
/* No sun_path... This is an un-named Unix domain socket */
conn->lc_type = LOCAL_TYPE_UNNAMED;
}
else
{
namelen = strnlen(unaddr->sun_path, UNIX_PATH_MAX-1);
if (namelen <= 0)
{
/* Zero-length sun_path... This is an abstract Unix domain socket */
conn->lc_type = LOCAL_TYPE_ABSTRACT;
conn->lc_path[0] = '\0';
}
else
{
/* This is an normal, pathname Unix domain socket */
conn->lc_type = LOCAL_TYPE_PATHNAME;
/* Copy the path into the connection structure */
(void)strncpy(conn->lc_path, unaddr->sun_path, UNIX_PATH_MAX-1);
conn->lc_path[UNIX_PATH_MAX-1] = '\0';
}
}
return OK;
}
#endif /* CONFIG_NET && CONFIG_NET_LOCAL */

View File

@ -1,7 +1,7 @@
/****************************************************************************
* net/socket/bind.c
*
* Copyright (C) 2007-2009, 2012, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2012, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -42,6 +42,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <errno.h>
#include <string.h>
#include <debug.h>
@ -58,6 +59,7 @@
#include "tcp/tcp.h"
#include "udp/udp.h"
#include "pkt/pkt.h"
#include "local/local.h"
/****************************************************************************
* Private Functions
@ -116,8 +118,8 @@ static int pkt_bind(FAR struct pkt_conn_s *conn,
*
* Description:
* bind() gives the socket 'psock' the local address 'addr'. 'addr' is
* 'addrlen' bytes long. Traditionally, this is called "assigning a name to
* a socket." When a socket is created with socket, it exists in a name
* 'addrlen' bytes long. Traditionally, this is called "assigning a name
* to a socket." When a socket is created with socket, it exists in a name
* space (address family) but has no name assigned.
*
* Parameters:
@ -175,6 +177,12 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
break;
#endif
#ifdef CONFIG_NET_LOCAL
case AF_LOCAL:
minlen = sizeof(sa_family_t);
break;
#endif
#ifdef CONFIG_NET_PKT
case AF_PACKET:
minlen = sizeof(struct sockaddr_ll);
@ -204,18 +212,87 @@ int psock_bind(FAR struct socket *psock, const struct sockaddr *addr,
break;
#endif
#ifdef CONFIG_NET_TCP
/* Bind a stream socket which may either be TCP/IP or a local, Unix
* domain socket.
*/
#if defined(CONFIG_NET_TCP) || defined(CONFIG_NET_LOCAL)
case SOCK_STREAM:
ret = tcp_bind(psock->s_conn, addr);
psock->s_flags |= _SF_BOUND;
break;
{
#ifdef CONFIG_NET_LOCAL
#ifdef CONFIG_NET_TCP
/* Is this a Unix domain socket? */
if (psock->s_domain == PF_LOCAL)
#endif
{
/* Bind the Unix domain connection structure */
ret = local_bind(psock->s_conn, addr, addrlen);
}
#endif /* CONFIG_NET_LOCAL */
#ifdef CONFIG_NET_TCP
#ifdef CONFIG_NET_LOCAL
else
#endif
{
/* Bind the TCP/IP connection structure */
ret = tcp_bind(psock->s_conn, addr);
}
#endif /* CONFIG_NET_TCP */
/* Mark the socket bound */
if (ret >= 0)
{
psock->s_flags |= _SF_BOUND;
}
}
break;
#endif /* CONFIG_NET_TCP || CONFIG_NET_LOCAL */
/* Bind a datagram socket which may either be TCP/IP or a local, Unix
* domain socket.
*/
#if defined(CONFIG_NET_UDP) || defined(CONFIG_NET_LOCAL)
case SOCK_DGRAM:
{
#ifdef CONFIG_NET_LOCAL
#ifdef CONFIG_NET_UDP
/* Is this a Unix domain socket? */
if (psock->s_domain == PF_LOCAL)
#endif
{
/* Bind the Unix domain connection structure */
ret = local_bind(psock->s_conn, addr, addrlen);
}
#endif /* CONFIG_NET_LOCAL */
#ifdef CONFIG_NET_UDP
case SOCK_DGRAM:
ret = udp_bind(psock->s_conn, addr);
break;
#ifdef CONFIG_NET_LOCAL
else
#endif
{
/* Bind the UDPP/IP connection structure */
ret = udp_bind(psock->s_conn, addr);
}
#endif /* CONFIG_NET_UDP */
/* Mark the socket bound */
if (ret >= 0)
{
psock->s_flags |= _SF_BOUND;
}
}
break;
#endif /* CONFIG_NET_UDP || CONFIG_NET_LOCAL */
default:
err = EBADF;