mirror of
https://github.com/apache/nuttx.git
synced 2026-05-28 11:56:10 +08:00
net/netlink/netlink_route.c (mostly): This completes a minimal netlink implementation that will retrieve the ARP table.
net/netlink: Add basic hooks (only) to support the NETLINK_ROUTE protocol.
This commit is contained in:
+58
-17
@@ -48,6 +48,7 @@
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Netlink socket protocols *************************************************/
|
/* Netlink socket protocols *************************************************/
|
||||||
|
|
||||||
/* The AF_NETLINK family offers multiple protocol subsets. Each interfaces
|
/* The AF_NETLINK family offers multiple protocol subsets. Each interfaces
|
||||||
* to a different kernel component and has a different messaging subset. The
|
* to a different kernel component and has a different messaging subset. The
|
||||||
* subset is referenced by the protocol field in the socket call:
|
* subset is referenced by the protocol field in the socket call:
|
||||||
@@ -55,25 +56,36 @@
|
|||||||
* int socket(AF_NETLINK, SOCK_DGRAM or SOCK_RAW, protocol)
|
* int socket(AF_NETLINK, SOCK_DGRAM or SOCK_RAW, protocol)
|
||||||
*
|
*
|
||||||
* Ref. Wikipedia.org
|
* Ref. Wikipedia.org
|
||||||
|
*
|
||||||
|
* Namespace is Linux compatible.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NETLINK_ROUTE 0 /* Routing/device hook for user-space
|
#define NETLINK_ROUTE 0 /* Routing/device hook for user-space
|
||||||
* routing daemons */
|
* routing daemons (default) */
|
||||||
#define NETLINK_FIREWALL 1 /* Interface to receive packets from
|
#define NETLINK_USERSOCK 1 /* Reserved for user mode socket protocols */
|
||||||
* the firewall */
|
#define NETLINK_FIREWALL 2 /* Interface to receive packets from
|
||||||
#define NETLINK_NFLOG 2 /* netfilter/iptables ULOG */
|
* the firewall */
|
||||||
#define NETLINK_ARPD 3 /* Interface to manage the ARP table */
|
#define NETLINK_SOCK_DIAG 3 /* Socket monitoring */
|
||||||
#define NETLINK_AUDIT 4 /* Interface to auditing sub-system */
|
#define NETLINK_NFLOG 4 /* netfilter/iptables ULOG */
|
||||||
#define NETLINK_IP6_FW 5 /* Interface to transport packets from
|
#define NETLINK_XFRM 5 /* Interface to IPsec security databases
|
||||||
* netfilter to user-space. */
|
* for key-manager daemons using the Internet
|
||||||
#define NETLINK_ROUTE6 6
|
* Key Exchange protocol. */
|
||||||
#define NETLINK_TAPBASE 7
|
#define NETLINK_ISCSI 6 /* Open-iSCSI */
|
||||||
#define NETLINK_NETFILTER 8
|
#define NETLINK_AUDIT 7 /* Interface to auditing sub-system */
|
||||||
#define NETLINK_TCPDIAG 9
|
#define NETLINK_FIB_LOOKUP 8
|
||||||
#define NETLINK_XFRM 10 /* Interface to IPsec security databases
|
#define NETLINK_CONNECTOR 9
|
||||||
* for key-manager daemons using the Internet
|
#define NETLINK_NETFILTER 10 /* netfilter subsystem */
|
||||||
* Key Exchange protocol. */
|
#define NETLINK_IP6_FW 11 /* Interface to transport packets from
|
||||||
#define NETLINK_USERSOCK 11 /* Reserved for user mode socket protocols */
|
* netfilter to user-space. */
|
||||||
|
#define NETLINK_DNRTMSG 12 /* DECnet routing messages */
|
||||||
|
#define NETLINK_KOBJECT_UEVENT 13 /* Kernel messages to userspace */
|
||||||
|
#define NETLINK_GENERIC 14
|
||||||
|
/* NETLINK_DM (DM Events) */
|
||||||
|
#define NETLINK_SCSITRANSPORT 16 /* SCSI Transports */
|
||||||
|
#define NETLINK_ECRYPTFS 17
|
||||||
|
#define NETLINK_RDMA 18
|
||||||
|
#define NETLINK_CRYPTO 19 /* Crypto layer */
|
||||||
|
#define NETLINK_SMC 20 /* SMC monitoring */
|
||||||
|
|
||||||
/* NETLINK_ROUTE protocol message types *************************************/
|
/* NETLINK_ROUTE protocol message types *************************************/
|
||||||
/* Link layer:
|
/* Link layer:
|
||||||
@@ -218,6 +230,7 @@
|
|||||||
#define NLM_F_ACK_TLVS 0x0200 /* extended ACK TVLs were included */
|
#define NLM_F_ACK_TLVS 0x0200 /* extended ACK TVLs were included */
|
||||||
|
|
||||||
/* Definitions for struct rtattr ********************************************/
|
/* Definitions for struct rtattr ********************************************/
|
||||||
|
|
||||||
/* Macros to handle rtattributes */
|
/* Macros to handle rtattributes */
|
||||||
|
|
||||||
#define RTA_ALIGNTO 4
|
#define RTA_ALIGNTO 4
|
||||||
@@ -235,6 +248,7 @@
|
|||||||
#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
|
#define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
|
||||||
|
|
||||||
/* Definitions for struct ifaddrmsg ****************************************/
|
/* Definitions for struct ifaddrmsg ****************************************/
|
||||||
|
|
||||||
/* ifa_flags definitions: ifa_flags is a flag word of IFA_F_SECONDARY for
|
/* ifa_flags definitions: ifa_flags is a flag word of IFA_F_SECONDARY for
|
||||||
* secondary address (old alias interface), IFA_F_PERMANENT for a permanent
|
* secondary address (old alias interface), IFA_F_PERMANENT for a permanent
|
||||||
* address set by the user and other undocumented flags.
|
* address set by the user and other undocumented flags.
|
||||||
@@ -243,6 +257,17 @@
|
|||||||
#define IFA_F_SECONDARY 0x01
|
#define IFA_F_SECONDARY 0x01
|
||||||
#define IFA_F_PERMANENT 0x02
|
#define IFA_F_PERMANENT 0x02
|
||||||
|
|
||||||
|
/* Common message helper macros ********************************************/
|
||||||
|
|
||||||
|
#define NLMSG_MASK (sizeof(uint32_t) - 1)
|
||||||
|
#define NLMSG_ALIGN(n) (((n) + NLMSG_MASK) & ~NLMSG_MASK)
|
||||||
|
#define NLMSG_HDRLEN sizeof(struct nlmsghdr)
|
||||||
|
#define NLMSG_LENGTH(n) (NLMSG_HDRLEN + (n))
|
||||||
|
#define NLMSG_DATA(hdr) ((FAR void*)(((FAR char*)hdr) + NLMSG_HDRLEN)
|
||||||
|
#define NLMSG_NEXT(hdr,n) \
|
||||||
|
((n) -= NLMSG_ALIGN((hdr)->nlmsg_len), \
|
||||||
|
(FAR struct nlmsghdr*)(((FAR cha r*)(hdr)) + NLMSG_ALIGN((hdr)->nlmsg_len)))
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Type Definitions
|
* Public Type Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@@ -316,6 +341,22 @@ struct ifaddrmsg
|
|||||||
int16_t ifa_index; /* Unique interface index */
|
int16_t ifa_index; /* Unique interface index */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* RTM_NEWNEIGH, RTM_DELNEIGH, RTM_GETNEIGH
|
||||||
|
* Add, remove or receive information about a neighbor table entry (e.g.,
|
||||||
|
* an ARP entry). The message contains an ndmsg structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct ndmsg
|
||||||
|
{
|
||||||
|
uint8_t ndm_family;
|
||||||
|
uint8_t ndm_pad1;
|
||||||
|
uint16_t ndm_pad2;
|
||||||
|
int32_t ndm_ifindex;
|
||||||
|
uint16_t ndm_state;
|
||||||
|
uint8_t ndm_flags;
|
||||||
|
uint8_t ndm_type;
|
||||||
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
@@ -416,6 +416,31 @@ int arp_update(in_addr_t ipaddr, FAR uint8_t *ethaddr);
|
|||||||
|
|
||||||
void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr);
|
void arp_hdr_update(FAR uint16_t *pipaddr, FAR uint8_t *ethaddr);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arp_snapshot
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Take a snapshot of the current state of the ARP table.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* snapshot - Location to return the ARP table copy
|
||||||
|
* nentries - The size of the user provided 'dest' in entries, each of
|
||||||
|
* size sizeof(struct arp_entry_s)
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, the number of entries actually copied is returned. Unused
|
||||||
|
* entries are not returned.
|
||||||
|
*
|
||||||
|
* Assumptions
|
||||||
|
* The network is locked to assure exclusive access to the ARP table
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NETLINK_ROUTE
|
||||||
|
unsigned int arp_snapshot(FAR struct arp_entry_s *snapshot,
|
||||||
|
unsigned int nentries);
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: arp_dump
|
* Name: arp_dump
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -393,6 +393,56 @@ void arp_delete(in_addr_t ipaddr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: arp_snapshot
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Take a snapshot of the current state of the ARP table.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* snapshot - Location to return the ARP table copy
|
||||||
|
* nentries - The size of the user provided 'dest' in entries, each of
|
||||||
|
* size sizeof(struct arp_entry_s)
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* On success, the number of entries actually copied is returned. Unused
|
||||||
|
* entries are not returned.
|
||||||
|
*
|
||||||
|
* Assumptions
|
||||||
|
* The network is locked to assure exclusive access to the ARP table
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NETLINK_ROUTE
|
||||||
|
unsigned int arp_snapshot(FAR struct arp_entry_s *snapshot,
|
||||||
|
unsigned int nentries)
|
||||||
|
{
|
||||||
|
FAR struct arp_entry_s *tabptr;
|
||||||
|
clock_t now;
|
||||||
|
unsigned int ncopied;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Copy all non-empty, non-expired entries in the ARP table. */
|
||||||
|
|
||||||
|
for (i = 0, now = clock_systimer(), ncopied = 0;
|
||||||
|
nentries > ncopied && i < CONFIG_NET_ARPTAB_SIZE;
|
||||||
|
i++)
|
||||||
|
{
|
||||||
|
tabptr = &g_arptable[i];
|
||||||
|
if (tabptr->at_ipaddr == 0 &&
|
||||||
|
now - tabptr->at_time <= ARP_MAXAGE_TICK)
|
||||||
|
{
|
||||||
|
memcpy(&snapshot[ncopied], tabptr, sizeof(struct arp_entry_s));
|
||||||
|
ncopied++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not found */
|
||||||
|
|
||||||
|
return ncopied;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* CONFIG_NET_ARP */
|
#endif /* CONFIG_NET_ARP */
|
||||||
#endif /* CONFIG_NET */
|
#endif /* CONFIG_NET */
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -17,10 +17,19 @@ config NET_NETLINK
|
|||||||
|
|
||||||
if NET_NETLINK
|
if NET_NETLINK
|
||||||
|
|
||||||
config NET_NETLINK_CONNS
|
config NETLINK_CONNS
|
||||||
int "Number of netlink connections"
|
int "Number of netlink connections"
|
||||||
default 4
|
default 4
|
||||||
---help---
|
---help---
|
||||||
Maximum number of netlink connections (all tasks).
|
Maximum number of netlink connections (all tasks).
|
||||||
|
|
||||||
|
menu "Netlink Protocols"
|
||||||
|
|
||||||
|
config NETLINK_ROUTE
|
||||||
|
bool "Netlink Route protocol"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Support the NETLINK_ROUTE protocol option.
|
||||||
|
|
||||||
|
endmenu # Netlink Protocols
|
||||||
endif # NET_NETLINK
|
endif # NET_NETLINK
|
||||||
|
|||||||
@@ -37,7 +37,12 @@
|
|||||||
|
|
||||||
ifeq ($(CONFIG_NET_NETLINK),y)
|
ifeq ($(CONFIG_NET_NETLINK),y)
|
||||||
|
|
||||||
SOCK_CSRCS += netlink_sockif.c netlink_conn.c
|
SOCK_CSRCS += netlink_sockif.c
|
||||||
|
NET_CSRCS += netlink_conn.c
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_NETLINK_ROUTE),y)
|
||||||
|
NET_CSRCS += netlink_route.c
|
||||||
|
endif
|
||||||
|
|
||||||
# Include netlink build support
|
# Include netlink build support
|
||||||
|
|
||||||
|
|||||||
+91
-2
@@ -46,6 +46,8 @@
|
|||||||
#include <queue.h>
|
#include <queue.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
#include <netpacket/netlink.h>
|
||||||
|
|
||||||
#include "devif/devif.h"
|
#include "devif/devif.h"
|
||||||
#include "socket/socket.h"
|
#include "socket/socket.h"
|
||||||
|
|
||||||
@@ -59,6 +61,25 @@
|
|||||||
* Public Type Definitions
|
* Public Type Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* Netlink uses a two step, request-get, referenced by a user managed
|
||||||
|
* sequence number. This means that the requested data must be buffered
|
||||||
|
* until it is gotten by the client. This structure holds that buffered
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* REVISIT: There really should be a timestamp on this so that we can
|
||||||
|
* someday weed out un-claimed responses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct netlink_response_s
|
||||||
|
{
|
||||||
|
FAR struct netlink_response_s *flink;
|
||||||
|
FAR struct nlmsghdr msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SIZEOF_NETLINK_RESPONSE_S(n) (sizeof(struct netlink_response_s) + (n) - 1)
|
||||||
|
|
||||||
|
/* This "connection" structure describes the underlying state of the socket. */
|
||||||
|
|
||||||
struct netlink_conn_s
|
struct netlink_conn_s
|
||||||
{
|
{
|
||||||
/* Common prologue of all connection structures. */
|
/* Common prologue of all connection structures. */
|
||||||
@@ -74,7 +95,14 @@ struct netlink_conn_s
|
|||||||
|
|
||||||
/* Netlink-specific content follows */
|
/* Netlink-specific content follows */
|
||||||
|
|
||||||
|
uint32_t pid; /* Port ID (if bound) */
|
||||||
|
uint32_t groups; /* Multicast groups mask (if bound) */
|
||||||
uint8_t crefs; /* Reference counts on this instance */
|
uint8_t crefs; /* Reference counts on this instance */
|
||||||
|
uint8_t protocol; /* See NETLINK_* definitions */
|
||||||
|
|
||||||
|
/* Buffered response data */
|
||||||
|
|
||||||
|
FAR struct netlink_response_s *resplist;
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -95,6 +123,8 @@ EXTERN const struct sock_intf_s g_netlink_sockif;
|
|||||||
* Public Function Prototypes
|
* Public Function Prototypes
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct sockaddr_nl; /* Forward reference */
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: netlink_initialize()
|
* Name: netlink_initialize()
|
||||||
*
|
*
|
||||||
@@ -148,12 +178,71 @@ FAR struct netlink_conn_s *netlink_nextconn(FAR struct netlink_conn_s *conn);
|
|||||||
* Find a connection structure that is the appropriate connection for the
|
* Find a connection structure that is the appropriate connection for the
|
||||||
* provided netlink address
|
* provided netlink address
|
||||||
*
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR struct netlink_conn_s *netlink_active(FAR struct sockaddr_nl *addr);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netlink_add_response
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Add response data at the head of the pending response list.
|
||||||
|
*
|
||||||
* Assumptions:
|
* Assumptions:
|
||||||
|
* The caller has the network locked to prevent concurrent access to the
|
||||||
|
* socket.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
struct sockaddr_nl; /* Forward reference */
|
void netlink_add_response(FAR struct socket *psock,
|
||||||
FAR struct netlink_conn_s *netlink_active(FAR struct sockaddr_nl *addr);
|
FAR struct netlink_response_s *resp);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netlink_get_response
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Find the response matching the request. Remove it from the list of
|
||||||
|
* pending responses and return the response data.
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* The caller has the network locked to prevent concurrent access to the
|
||||||
|
* socket.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR struct netlink_response_s *
|
||||||
|
netlink_get_response(FAR struct socket *psock, FAR struct nlmsghdr *nlmsg);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netlink_route_sendto()
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform the sendto() operation for the NETLINK_ROUTE protocol.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NETLINK_ROUTE
|
||||||
|
ssize_t netlink_route_sendto(FAR struct socket *psock,
|
||||||
|
FAR const struct nlmsghdr *nlmsg,
|
||||||
|
size_t len, int flags,
|
||||||
|
FAR const struct sockaddr_nl *to,
|
||||||
|
socklen_t tolen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netlink_route_recvfrom()
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform the recvfrom() operation for the NETLINK_ROUTE protocol.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_NETLINK_ROUTE
|
||||||
|
ssize_t netlink_route_recvfrom(FAR struct socket *psock,
|
||||||
|
FAR struct nlmsghdr *nlmsg,
|
||||||
|
size_t len, int flags,
|
||||||
|
FAR struct sockaddr_nl *from);
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
/* The array containing all netlink connections. */
|
/* The array containing all netlink connections. */
|
||||||
|
|
||||||
static struct netlink_conn_s g_netlink_connections[CONFIG_NET_NETLINK_CONNS];
|
static struct netlink_conn_s g_netlink_connections[CONFIG_NETLINK_CONNS];
|
||||||
|
|
||||||
/* A list of all free netlink connections */
|
/* A list of all free netlink connections */
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ void netlink_initialize(void)
|
|||||||
dq_init(&g_active_netlink_connections);
|
dq_init(&g_active_netlink_connections);
|
||||||
nxsem_init(&g_free_sem, 0, 1);
|
nxsem_init(&g_free_sem, 0, 1);
|
||||||
|
|
||||||
for (i = 0; i < CONFIG_NET_NETLINK_CONNS; i++)
|
for (i = 0; i < CONFIG_NETLINK_CONNS; i++)
|
||||||
{
|
{
|
||||||
FAR struct netlink_conn_s *conn = &g_netlink_connections[i];
|
FAR struct netlink_conn_s *conn = &g_netlink_connections[i];
|
||||||
|
|
||||||
@@ -226,7 +226,7 @@ FAR struct netlink_conn_s *netlink_nextconn(FAR struct netlink_conn_s *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: netlink_active()
|
* Name: netlink_active
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Find a connection structure that is the appropriate connection for the
|
* Find a connection structure that is the appropriate connection for the
|
||||||
@@ -243,4 +243,89 @@ FAR struct netlink_conn_s *netlink_active(FAR struct sockaddr_nl *addr)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netlink_add_response
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Add response data at the head of the pending response list.
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* The caller has the network locked to prevent concurrent access to the
|
||||||
|
* socket.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void netlink_add_response(FAR struct socket *psock,
|
||||||
|
FAR struct netlink_response_s *resp)
|
||||||
|
{
|
||||||
|
FAR struct netlink_conn_s *conn;
|
||||||
|
|
||||||
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && resp != NULL);
|
||||||
|
|
||||||
|
conn = (FAR struct netlink_conn_s *)psock->s_conn;
|
||||||
|
resp->flink = conn->resplist;
|
||||||
|
conn->resplist = resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netlink_get_response
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Find the response matching the request. Remove it from the list of
|
||||||
|
* pending responses and return the response data.
|
||||||
|
*
|
||||||
|
* Assumptions:
|
||||||
|
* The caller has the network locked to prevent concurrent access to the
|
||||||
|
* socket.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR struct netlink_response_s *
|
||||||
|
netlink_get_response(FAR struct socket *psock, FAR struct nlmsghdr *nlmsg)
|
||||||
|
{
|
||||||
|
FAR struct netlink_conn_s *conn;
|
||||||
|
FAR struct netlink_response_s *curr;
|
||||||
|
FAR struct netlink_response_s *prev;
|
||||||
|
|
||||||
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && nlmsg != NULL);
|
||||||
|
|
||||||
|
conn = (FAR struct netlink_conn_s *)psock->s_conn;
|
||||||
|
|
||||||
|
/* Search the pending response data for this socket and find the entry
|
||||||
|
* with the matching sequence. Here is is assumed that the sequence
|
||||||
|
* number is unique and, hence, it is not necessary to verify other
|
||||||
|
* information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (prev = NULL, curr = conn->resplist;
|
||||||
|
curr != NULL;
|
||||||
|
prev = curr, curr = curr->flink)
|
||||||
|
{
|
||||||
|
/* Check for a matching sequence number */
|
||||||
|
|
||||||
|
if (curr->msg.nlmsg_seq == nlmsg->nlmsg_seq)
|
||||||
|
{
|
||||||
|
/* We have a match */
|
||||||
|
|
||||||
|
DEBUGASSERT(curr->msg.nlmsg_type == nlmsg->nlmsg_type);
|
||||||
|
|
||||||
|
/* Remove the entry from the list and return it */
|
||||||
|
|
||||||
|
if (prev != NULL)
|
||||||
|
{
|
||||||
|
prev->flink = curr->flink;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
conn->resplist = curr->flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
curr->flink = NULL;
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NET_NETLINK */
|
#endif /* CONFIG_NET_NETLINK */
|
||||||
|
|||||||
@@ -0,0 +1,262 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* net/netlink/netlink_route.c
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019 Gregory Nutt. All rights reserved.
|
||||||
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||||
|
* used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <netpacket/netlink.h>
|
||||||
|
|
||||||
|
#include <nuttx/kmalloc.h>
|
||||||
|
#include <nuttx/net/net.h>
|
||||||
|
#include <nuttx/net/arp.h>
|
||||||
|
|
||||||
|
#include "arp/arp.h"
|
||||||
|
#include "netlink/netlink.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_NETLINK_ROUTE
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define IFA_RTA(r) \
|
||||||
|
((FAR struct rtattr *)(((FAR char *)(r)) + \
|
||||||
|
NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
|
||||||
|
#define IFA_PAYLOAD(n) \
|
||||||
|
NLMSG_PAYLOAD(n, sizeof(struct ifaddrmsg))
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/* RTM_NEWNEIGH, RTM_DELNEIGH, RTM_GETNEIGH
|
||||||
|
* Add, remove or receive information about a neighbor table entry (e.g.,
|
||||||
|
* an ARP entry). The message contains an ndmsg structure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct nlroute_sendto_request_s
|
||||||
|
{
|
||||||
|
struct nlmsghdr hdr;
|
||||||
|
struct ndmsg msg;
|
||||||
|
uint8_t data[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SIZEOF_NLROUTE_SENDTO_REQUEST_S(n) \
|
||||||
|
(sizeof(struct nlroute_sendto_request_s) + (n) - 1)
|
||||||
|
|
||||||
|
struct nlroute_recvfrom_response_s
|
||||||
|
{
|
||||||
|
FAR struct netlink_reqdata_s *flink;
|
||||||
|
struct nlmsghdr hdr;
|
||||||
|
struct ndmsg msg;
|
||||||
|
struct rtattr attr;
|
||||||
|
uint8_t data[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SIZEOF_NLROUTE_RECVFROM_RESPONSE_S(n) \
|
||||||
|
(sizeof(struct nlroute_recvfrom_response_s) + (n) - 1)
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netlink_route_sendto()
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform the sendto() operation for the NETLINK_ROUTE protocol.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
ssize_t netlink_route_sendto(FAR struct socket *psock,
|
||||||
|
FAR const struct nlmsghdr *nlmsg,
|
||||||
|
size_t len, int flags,
|
||||||
|
FAR const struct sockaddr_nl *to,
|
||||||
|
socklen_t tolen)
|
||||||
|
{
|
||||||
|
FAR const struct nlroute_sendto_request_s *req;
|
||||||
|
|
||||||
|
DEBUGASSERT(psock != NULL && nlmsg != NULL &&
|
||||||
|
nlmsg->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||||
|
len >= sizeof(struct nlmsghdr) &&
|
||||||
|
len >= nlmsg->nlmsg_len && to != NULL &&
|
||||||
|
tolen >= sizeof(struct sockaddr_nl));
|
||||||
|
|
||||||
|
req = (FAR const struct nlroute_sendto_request_s *)nlmsg;
|
||||||
|
|
||||||
|
#ifdef CONFIG_NET_ARP
|
||||||
|
/* REVISIT: Currently, the only operation supported is retrieving the
|
||||||
|
* ARP table in its entirety.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (req->hdr.nlmsg_type == RTM_GETNEIGH && req->msg.ndm_family == AF_INET)
|
||||||
|
{
|
||||||
|
FAR struct nlroute_recvfrom_response_s *entry;
|
||||||
|
unsigned int ncopied;
|
||||||
|
size_t tabsize;
|
||||||
|
size_t paysize;
|
||||||
|
size_t entsize;
|
||||||
|
|
||||||
|
/* Preallocate memory to hold the maximum sized ARP table
|
||||||
|
* REVISIT: This is probably excessively large and could cause false
|
||||||
|
* memory out conditions. A better approach would be to actually count
|
||||||
|
* the number of valid entries in the ARP table.
|
||||||
|
*/
|
||||||
|
|
||||||
|
tabsize = CONFIG_NET_ARPTAB_SIZE * sizeof( struct arp_entry_s);
|
||||||
|
paysize = SIZEOF_NLROUTE_RECVFROM_RESPONSE_S(tabsize);
|
||||||
|
entsize = SIZEOF_NETLINK_RESPONSE_S(paysize);
|
||||||
|
|
||||||
|
entry = (FAR struct nlroute_recvfrom_response_s *)kmm_malloc(entsize);
|
||||||
|
if (entry == NULL)
|
||||||
|
{
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Populate the entry */
|
||||||
|
|
||||||
|
memcpy(&entry->hdr, &req->hdr, sizeof(struct nlmsghdr));
|
||||||
|
entry->hdr.nlmsg_len = paysize;
|
||||||
|
memcpy(&entry->msg, &req->msg, sizeof(struct ndmsg));
|
||||||
|
entry->attr.rta_len = tabsize;
|
||||||
|
entry->attr.rta_type = 0;
|
||||||
|
|
||||||
|
/* Lock the network so that the ARP table will be stable, then copy
|
||||||
|
* the ARP table into the allocated memory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
net_lock();
|
||||||
|
ncopied = arp_snapshot((FAR struct arp_entry_s *)entry->data,
|
||||||
|
CONFIG_NET_ARPTAB_SIZE);
|
||||||
|
net_unlock();
|
||||||
|
|
||||||
|
/* Now we have the real number of valid entries in the ARP table and
|
||||||
|
* we can trim the allocation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ncopied < CONFIG_NET_ARPTAB_SIZE)
|
||||||
|
{
|
||||||
|
FAR struct nlroute_recvfrom_response_s *newentry;
|
||||||
|
|
||||||
|
tabsize = ncopied * sizeof( struct arp_entry_s);
|
||||||
|
paysize = SIZEOF_NLROUTE_RECVFROM_RESPONSE_S(tabsize);
|
||||||
|
entsize = SIZEOF_NETLINK_RESPONSE_S(paysize);
|
||||||
|
|
||||||
|
newentry = (FAR struct nlroute_recvfrom_response_s *)
|
||||||
|
kmm_realloc(entry, entsize);
|
||||||
|
|
||||||
|
if (newentry != NULL)
|
||||||
|
{
|
||||||
|
entry = newentry;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry->hdr.nlmsg_len = paysize;
|
||||||
|
entry->attr.rta_len = tabsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, add the data to the list of pending responses */
|
||||||
|
|
||||||
|
netlink_add_response(psock, (FAR struct netlink_response_s *)entry);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
UNUSED(req);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* REVISIT: Not implemented */
|
||||||
|
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: netlink_route_recvfrom()
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Perform the recvfrom() operation for the NETLINK_ROUTE protocol.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
ssize_t netlink_route_recvfrom(FAR struct socket *psock,
|
||||||
|
FAR struct nlmsghdr *nlmsg,
|
||||||
|
size_t len, int flags,
|
||||||
|
FAR struct sockaddr_nl *from)
|
||||||
|
{
|
||||||
|
FAR struct nlroute_recvfrom_response_s *resp;
|
||||||
|
|
||||||
|
DEBUGASSERT(psock != NULL && nlmsg != NULL &&
|
||||||
|
nlmsg->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||||
|
len >= sizeof(struct nlmsghdr) &&
|
||||||
|
from != NULL);
|
||||||
|
|
||||||
|
/* Find the response to this message */
|
||||||
|
|
||||||
|
net_lock();
|
||||||
|
resp = (FAR struct nlroute_recvfrom_response_s *)
|
||||||
|
netlink_get_response(psock, nlmsg);
|
||||||
|
net_unlock();
|
||||||
|
|
||||||
|
if (resp == NULL)
|
||||||
|
{
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < resp->hdr.nlmsg_len)
|
||||||
|
{
|
||||||
|
kmm_free(resp);
|
||||||
|
return -EMSGSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(nlmsg, resp, resp->hdr.nlmsg_len);
|
||||||
|
|
||||||
|
/* Return address. REVISIT... this is just a guess. */
|
||||||
|
|
||||||
|
from->nl_family = resp->msg.ndm_family;
|
||||||
|
from->nl_pad = 0;
|
||||||
|
from->nl_pid = resp->hdr.nlmsg_pid;
|
||||||
|
from->nl_groups = resp->hdr.nlmsg_type;
|
||||||
|
|
||||||
|
return resp->hdr.nlmsg_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_NETLINK_ROUTE */
|
||||||
+186
-27
@@ -42,6 +42,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
@@ -120,8 +121,9 @@ const struct sock_intf_s g_netlink_sockif =
|
|||||||
* specific socket fields.
|
* specific socket fields.
|
||||||
*
|
*
|
||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* psock A pointer to a user allocated socket structure to be initialized.
|
* psock - A pointer to a user allocated socket structure to be
|
||||||
* protocol (see sys/socket.h)
|
* initialized.
|
||||||
|
* protocol - Netlink socket protocol (see sys/socket.h)
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* Zero (OK) is returned on success. Otherwise, a negated errno value is
|
* Zero (OK) is returned on success. Otherwise, a negated errno value is
|
||||||
@@ -133,19 +135,56 @@ static int netlink_setup(FAR struct socket *psock, int protocol)
|
|||||||
{
|
{
|
||||||
int domain = psock->s_domain;
|
int domain = psock->s_domain;
|
||||||
int type = psock->s_type;
|
int type = psock->s_type;
|
||||||
int ret;
|
|
||||||
|
/* Verify that the protocol is supported */
|
||||||
|
|
||||||
|
DEBUGASSERT((unsigned int)protocol <= UINT8_MAX);
|
||||||
|
|
||||||
|
switch (protocol)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NETLINK_ROUTE
|
||||||
|
case NETLINK_ROUTE:
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
return -EPROTONOSUPPORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify the socket type (domain should always be PF_NETLINK here) */
|
||||||
|
|
||||||
if (domain == PF_NETLINK && (type == SOCK_RAW || type == SOCK_DGRAM))
|
if (domain == PF_NETLINK && (type == SOCK_RAW || type == SOCK_DGRAM))
|
||||||
{
|
{
|
||||||
ret = OK;
|
/* Allocate the netlink socket connection structure and save it in the
|
||||||
}
|
* new socket instance.
|
||||||
else
|
*/
|
||||||
{
|
|
||||||
return -ENETDOWN;
|
FAR struct netlink_conn_s *conn = netlink_alloc();
|
||||||
|
if (conn == NULL)
|
||||||
|
{
|
||||||
|
/* Failed to reserve a connection structure */
|
||||||
|
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the connection instance */
|
||||||
|
|
||||||
|
conn->protocol = (uint8_t)protocol;
|
||||||
|
|
||||||
|
/* Set the reference count on the connection structure. This
|
||||||
|
* reference count will be incremented only if the socket is
|
||||||
|
* dup'ed
|
||||||
|
*/
|
||||||
|
|
||||||
|
conn->crefs = 1;
|
||||||
|
|
||||||
|
/* Attach the connection instance to the socket */
|
||||||
|
|
||||||
|
psock->s_conn = conn;
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
psock->s_conn = NULL;
|
return -EPROTONOSUPPORT;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -227,8 +266,22 @@ static void netlink_addref(FAR struct socket *psock)
|
|||||||
static int netlink_bind(FAR struct socket *psock,
|
static int netlink_bind(FAR struct socket *psock,
|
||||||
FAR const struct sockaddr *addr, socklen_t addrlen)
|
FAR const struct sockaddr *addr, socklen_t addrlen)
|
||||||
{
|
{
|
||||||
#warning Missing logic for NETLINK bind
|
FAR struct sockaddr_nl *nladdr;
|
||||||
return -EOPNOTSUPP;
|
FAR struct netlink_conn_s *conn;
|
||||||
|
|
||||||
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
|
||||||
|
addrlen >= sizeof(struct sockaddr_nl));
|
||||||
|
|
||||||
|
/* Save the address information in the connection structure */
|
||||||
|
|
||||||
|
nladdr = (FAR struct sockaddr_nl *)addr;
|
||||||
|
conn = (FAR struct netlink_conn_s *)psock->s_conn;
|
||||||
|
|
||||||
|
conn->pid = nladdr->nl_pid;
|
||||||
|
conn->groups = nladdr->nl_groups;
|
||||||
|
|
||||||
|
psock->s_flags |= _SF_BOUND;
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -257,8 +310,29 @@ static int netlink_getsockname(FAR struct socket *psock,
|
|||||||
FAR struct sockaddr *addr,
|
FAR struct sockaddr *addr,
|
||||||
FAR socklen_t *addrlen)
|
FAR socklen_t *addrlen)
|
||||||
{
|
{
|
||||||
#warning Missing logic for NETLINK getsockname
|
FAR struct sockaddr_nl *nladdr;
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && addr != NULL &&
|
||||||
|
addrlen != NULL && *addrlen >= sizeof(struct sockaddr_nl));
|
||||||
|
|
||||||
|
/* Return the address information in the address structure */
|
||||||
|
|
||||||
|
nladdr = (FAR struct sockaddr_nl *)addr;
|
||||||
|
memset(nladdr, 0, sizeof(struct sockaddr_nl));
|
||||||
|
|
||||||
|
nladdr->nl_family = AF_NETLINK;
|
||||||
|
|
||||||
|
if (_SS_ISBOUND(psock->s_flags))
|
||||||
|
{
|
||||||
|
FAR struct netlink_conn_s *conn;
|
||||||
|
|
||||||
|
conn = (FAR struct netlink_conn_s *)psock->s_conn;
|
||||||
|
nladdr->nl_pid = conn->pid;
|
||||||
|
nladdr->nl_groups = conn->groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
*addrlen = sizeof(struct sockaddr_nl);
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -449,12 +523,41 @@ static int netlink_poll(FAR struct socket *psock, FAR struct pollfd *fds,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t netlink_send(FAR struct socket *psock,
|
static ssize_t netlink_send(FAR struct socket *psock, FAR const void *buf,
|
||||||
FAR const void *buf,
|
size_t len, int flags)
|
||||||
size_t len, int flags)
|
|
||||||
{
|
{
|
||||||
#warning Missing logic for NETLINK send
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL);
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
/* The socket must be connected in order to use send */
|
||||||
|
|
||||||
|
if (_SS_ISBOUND(psock->s_flags))
|
||||||
|
{
|
||||||
|
FAR struct netlink_conn_s *conn;
|
||||||
|
struct sockaddr_nl nladdr;
|
||||||
|
|
||||||
|
/* Get the underlying connection structure */
|
||||||
|
|
||||||
|
conn = (FAR struct netlink_conn_s *)psock->s_conn;
|
||||||
|
|
||||||
|
/* Format the address */
|
||||||
|
|
||||||
|
nladdr.nl_family = AF_NETLINK;
|
||||||
|
nladdr.nl_pad = 0;
|
||||||
|
nladdr.nl_pid = conn->pid;
|
||||||
|
nladdr.nl_groups = conn->groups;
|
||||||
|
|
||||||
|
/* Then let sendto() perform the actual send operation */
|
||||||
|
|
||||||
|
return netlink_sendto(psock, buf, len, flags,
|
||||||
|
(FAR const struct sockaddr *)&nladdr,
|
||||||
|
sizeof(struct sockaddr_nl));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EDESTADDRREQ. Signifies that the socket is not connection-mode and no
|
||||||
|
* peer address is set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return -EDESTADDRREQ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -482,11 +585,40 @@ static ssize_t netlink_send(FAR struct socket *psock,
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t netlink_sendto(FAR struct socket *psock, FAR const void *buf,
|
static ssize_t netlink_sendto(FAR struct socket *psock, FAR const void *buf,
|
||||||
size_t len, int flags,
|
size_t len, int flags,
|
||||||
FAR const struct sockaddr *to, socklen_t tolen)
|
FAR const struct sockaddr *to, socklen_t tolen)
|
||||||
{
|
{
|
||||||
#warning Missing logic for NETLINK sendto
|
FAR struct netlink_conn_s *conn;
|
||||||
return -EOPNOTSUPP;
|
FAR struct nlmsghdr *nlmsg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL &&
|
||||||
|
to != NULL && tolen >= sizeof(struct nlmsghdr));
|
||||||
|
|
||||||
|
conn = (FAR struct netlink_conn_s *)psock->s_conn;
|
||||||
|
|
||||||
|
/* Get a reference to the netlink message */
|
||||||
|
|
||||||
|
nlmsg = (FAR struct nlmsghdr *)buf;
|
||||||
|
DEBUGASSERT(nlmsg->nlmsg_len >= sizeof(struct nlmsghdr) &&
|
||||||
|
tolen >= nlmsg->nlmsg_len);
|
||||||
|
|
||||||
|
switch (conn->protocol)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NETLINK_ROUTE
|
||||||
|
case NETLINK_ROUTE:
|
||||||
|
ret = netlink_route_sendto(psock, nlmsg, len, flags,
|
||||||
|
(FAR struct sockaddr_nl *)to,
|
||||||
|
tolen);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret= -EOPNOTSUPP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -516,8 +648,35 @@ static ssize_t netlink_recvfrom(FAR struct socket *psock, FAR void *buf,
|
|||||||
FAR struct sockaddr *from,
|
FAR struct sockaddr *from,
|
||||||
FAR socklen_t *fromlen)
|
FAR socklen_t *fromlen)
|
||||||
{
|
{
|
||||||
#warning Missing logic for NETLINK recvfrom
|
FAR struct netlink_conn_s *conn;
|
||||||
return -EOPNOTSUPP;
|
FAR struct nlmsghdr *nlmsg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
DEBUGASSERT(psock != NULL && psock->s_conn != NULL && buf != NULL &&
|
||||||
|
from != NULL && *fromlen >= sizeof(struct nlmsghdr));
|
||||||
|
|
||||||
|
conn = (FAR struct netlink_conn_s *)psock->s_conn;
|
||||||
|
|
||||||
|
/* Get a reference to the netlink message */
|
||||||
|
|
||||||
|
nlmsg = (FAR struct nlmsghdr *)buf;
|
||||||
|
|
||||||
|
switch (conn->protocol)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_NETLINK_ROUTE
|
||||||
|
case NETLINK_ROUTE:
|
||||||
|
ret = netlink_route_recvfrom(psock, nlmsg, len, flags,
|
||||||
|
(FAR struct sockaddr_nl *)from);
|
||||||
|
*fromlen = sizeof(struct sockaddr_nl);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
ret= -EOPNOTSUPP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -539,7 +698,7 @@ static ssize_t netlink_recvfrom(FAR struct socket *psock, FAR void *buf,
|
|||||||
static int netlink_close(FAR struct socket *psock)
|
static int netlink_close(FAR struct socket *psock)
|
||||||
{
|
{
|
||||||
FAR struct netlink_conn_s *conn = psock->s_conn;
|
FAR struct netlink_conn_s *conn = psock->s_conn;
|
||||||
int ret;
|
int ret = OK;
|
||||||
|
|
||||||
/* Perform some pre-close operations for the NETLINK socket type. */
|
/* Perform some pre-close operations for the NETLINK socket type. */
|
||||||
|
|
||||||
@@ -573,7 +732,7 @@ static int netlink_close(FAR struct socket *psock)
|
|||||||
conn->crefs--;
|
conn->crefs--;
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_NET_NETLINK */
|
#endif /* CONFIG_NET_NETLINK */
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ static int pkt_setup(FAR struct socket *psock, int protocol)
|
|||||||
* queried.
|
* queried.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* The set of socket cababilities is returned.
|
* The set of socket capabilities is returned.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ static void pkt_addref(FAR struct socket *psock)
|
|||||||
* addrlen Length of actual 'addr'
|
* addrlen Length of actual 'addr'
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
* 0 on success; a negated errno value on failue. See connect() for the
|
* 0 on success; a negated errno value on failure. See connect() for the
|
||||||
* list of appropriate errno values to be returned.
|
* list of appropriate errno values to be returned.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev,
|
|||||||
{
|
{
|
||||||
FAR struct sendto_s *pstate = (FAR struct sendto_s *)pvpriv;
|
FAR struct sendto_s *pstate = (FAR struct sendto_s *)pvpriv;
|
||||||
|
|
||||||
DEBUGASSERT(pstate != NULL && pstate->dev != NULL);
|
DEBUGASSERT(pstate != NULL && pstate->st_dev != NULL);
|
||||||
if (pstate != NULL)
|
if (pstate != NULL)
|
||||||
{
|
{
|
||||||
/* The TCP socket should be bound to a device. Make sure that the
|
/* The TCP socket should be bound to a device. Make sure that the
|
||||||
|
|||||||
Reference in New Issue
Block a user