| /**************************************************************************** |
| * net/netlink/netlink.h |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance with the |
| * License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations |
| * under the License. |
| * |
| ****************************************************************************/ |
| |
| #ifndef __NET_NETLINK_NETLINK_H |
| #define __NET_NETLINK_NETLINK_H |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| |
| #include <sys/types.h> |
| #include <poll.h> |
| |
| #include <netpacket/netlink.h> |
| #include <nuttx/queue.h> |
| #include <nuttx/net/icmpv6.h> |
| #include <nuttx/net/netlink.h> |
| #include <nuttx/semaphore.h> |
| #include <nuttx/wqueue.h> |
| |
| #include "devif/devif.h" |
| #include "socket/socket.h" |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| #ifndef CONFIG_NETLINK_ROUTE |
| # define netlink_device_notify(dev) |
| # define netlink_device_notify_ipaddr(dev, type, domain, addr, preflen) |
| # define netlink_route_notify(route, type, domain) |
| # define netlink_neigh_notify(neigh, type, domain) |
| # define netlink_ipv6_prefix_notify(dev, type, pinfo) |
| #endif |
| |
| #ifdef CONFIG_NET_NETLINK |
| |
| /* nla_for_each_attr - iterate over a stream of attributes |
| * pos: loop counter, set to current attribute |
| * head: head of attribute stream |
| * len: length of attribute stream |
| * rem: initialized to len, holds bytes currently remaining in stream |
| */ |
| |
| #define nla_for_each_attr(pos, head, len, rem) \ |
| for (pos = head, rem = len; nla_ok(pos, rem); \ |
| pos = nla_next(pos, &(rem))) |
| |
| /* Always use this macro, this allows later putting the |
| * message into a separate section or such for things |
| * like translation or listing all possible messages. |
| * Currently string formatting is not supported (due |
| * to the lack of an output buffer.) |
| */ |
| |
| #define nl_set_err_msg_attr(extack, attr, msg) \ |
| do \ |
| { \ |
| static const char __msg[] = (msg); \ |
| FAR struct netlink_ext_ack *__extack = (extack); \ |
| if (__extack) \ |
| { \ |
| __extack->_msg = __msg; \ |
| __extack->bad_attr = (attr); \ |
| } \ |
| } \ |
| while (0) |
| |
| /* nla_data - head of payload |
| * nla: netlink attribute |
| */ |
| |
| #define nla_data(nla) ((FAR void *)((FAR char *)(nla) + NLA_HDRLEN)) |
| |
| /* nla_len - length of payload |
| * nla: netlink attribute |
| */ |
| |
| #define nla_len(nla) ((nla)->nla_len - NLA_HDRLEN) |
| |
| /* nla_type - attribute type |
| * nla: netlink attribute |
| */ |
| |
| #define nla_type(nla) ((nla)->nla_type & NLA_TYPE_MASK) |
| |
| /* nla_ok - check if the netlink attribute fits into the remaining bytes |
| * nla: netlink attribute |
| * remaining: number of bytes remaining in attribute stream |
| */ |
| |
| #define nla_ok(nla, remaining) \ |
| ((remaining) >= sizeof(*(nla)) && \ |
| (nla)->nla_len >= sizeof(*(nla)) && \ |
| (nla)->nla_len <= (remaining)) |
| |
| /* nlmsg_msg_size - length of netlink message not including padding |
| * payload: length of message payload |
| */ |
| |
| #define nlmsg_msg_size(payload) (NLMSG_HDRLEN + (payload)) |
| |
| /* nlmsg_len - length of message payload |
| * nlh: netlink message header |
| */ |
| |
| #define nlmsg_len(nlh) ((nlh)->nlmsg_len - NLMSG_HDRLEN) |
| |
| /* nlmsg_attrlen - length of attributes data |
| * nlh: netlink message header |
| * hdrlen: length of family specific header |
| */ |
| |
| #define nlmsg_attrlen(nlh, hdrlen) (nlmsg_len(nlh) - NLMSG_ALIGN(hdrlen)) |
| |
| /* nlmsg_data - head of message payload |
| * nlh: netlink message header |
| */ |
| |
| #define nlmsg_data(nlh) ((FAR void *)((FAR char *)(nlh) + NLMSG_HDRLEN)) |
| |
| /* nla_get_in_addr - return payload of IPv4 address attribute |
| * nla: IPv4 address netlink attribute |
| */ |
| |
| #define nla_get_in_addr(nla) (*(FAR uint32_t *)nla_data(nla)) |
| |
| /* nlmsg_attrdata - head of attributes data |
| * nlh: netlink message header |
| * hdrlen: length of family specific header |
| */ |
| |
| #define nlmsg_attrdata(nlh, hdrlen) \ |
| ((FAR struct nlattr *)((FAR char *)nlmsg_data(nlh) + NLMSG_ALIGN(hdrlen))) |
| |
| /* nlmsg_parse - parse attributes of a netlink message |
| * nlh: netlink message header |
| * hdrlen: length of family specific header |
| * tb: destination array with maxtype+1 elements |
| * maxtype: maximum attribute type to be expected |
| * policy: validation policy |
| * extack: extended ACK report struct |
| * |
| * See nla_parse() |
| */ |
| |
| #define nlmsg_parse(nlh, hdrlen, tb, maxtype, policy, extack) \ |
| ((nlh)->nlmsg_len < nlmsg_msg_size(hdrlen) ? -EINVAL : \ |
| nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen), \ |
| nlmsg_attrlen(nlh, hdrlen), policy, extack)) |
| |
| /* this can be increased when necessary - don't expose to userland */ |
| |
| #define NETLINK_MAX_COOKIE_LEN 20 |
| |
| /**************************************************************************** |
| * Public Type Definitions |
| ****************************************************************************/ |
| |
| /* This connection structure describes the underlying state of the socket. */ |
| |
| struct netlink_conn_s |
| { |
| /* Common prologue of all connection structures. */ |
| |
| struct socket_conn_s sconn; |
| |
| /* NetLink-specific content follows */ |
| |
| uint32_t pid; /* Port ID (if bound) */ |
| uint32_t groups; /* Multicast groups mask (if bound) */ |
| uint32_t dst_pid; /* Destination port ID */ |
| uint32_t dst_groups; /* Destination multicast groups mask */ |
| uint8_t crefs; /* Reference counts on this instance */ |
| |
| /* poll() support */ |
| |
| int key; /* used to cancel notifications */ |
| FAR struct pollfd *fds; /* Used to wakeup poll() */ |
| |
| /* Queued response data */ |
| |
| sq_queue_t resplist; /* Singly linked list of responses */ |
| }; |
| |
| /* Standard attribute types to specify validation policy */ |
| |
| enum |
| { |
| NLA_UNSPEC, |
| NLA_U8, |
| NLA_U16, |
| NLA_U32, |
| NLA_U64, |
| NLA_STRING, |
| NLA_FLAG, |
| NLA_MSECS, |
| NLA_NESTED, |
| NLA_NESTED_COMPAT, |
| NLA_NUL_STRING, |
| NLA_BINARY, |
| NLA_S8, |
| NLA_S16, |
| NLA_S32, |
| NLA_S64, |
| NLA_BITFIELD32, |
| NLA_TYPE_MAX = NLA_BITFIELD32, |
| }; |
| |
| /* struct netlink_ext_ack - netlink extended ACK report struct |
| * _msg: message string to report - don't access directly, use |
| * nl_set_err_msg_attr |
| * bad_attr: attribute with error |
| * cookie: cookie data to return to userspace (for success) |
| * cookie_len: actual cookie data length |
| */ |
| |
| struct netlink_ext_ack |
| { |
| FAR const char *_msg; |
| FAR const struct nlattr *bad_attr; |
| uint8_t cookie[NETLINK_MAX_COOKIE_LEN]; |
| uint8_t cookie_len; |
| }; |
| |
| /* struct nla_policy - attribute validation policy |
| * type: Type of attribute or NLA_UNSPEC |
| * len: Type specific length of payload |
| * |
| * Policies are defined as arrays of this struct, the array must be |
| * accessible by attribute type up to the highest identifier to be expected. |
| * |
| * Meaning of `len' field: |
| * NLA_STRING Maximum length of string |
| * NLA_NUL_STRING Maximum length of string (excluding NUL) |
| * NLA_FLAG Unused |
| * NLA_BINARY Maximum length of attribute payload |
| * NLA_NESTED Don't use `len' field -- length verification is |
| * done by checking len of nested header (or empty) |
| * NLA_NESTED_COMPAT Minimum length of structure payload |
| * NLA_U8, NLA_U16, |
| * NLA_U32, NLA_U64, |
| * NLA_S8, NLA_S16, |
| * NLA_S32, NLA_S64, |
| * NLA_MSECS Leaving the length field zero will verify the |
| * given type fits, using it verifies minimum length |
| * just like "All other" |
| * NLA_BITFIELD32 A 32-bit bitmap/bitselector attribute |
| * All other Minimum length of attribute payload |
| * |
| * Example: |
| * static const struct nla_policy my_policy[ATTR_MAX + 1] = { |
| * [ATTR_FOO] = { .type = NLA_U16 }, |
| * [ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ }, |
| * [ATTR_BAZ] = { .len = sizeof(struct mystruct) }, |
| * [ATTR_GOO] = { .type = NLA_BITFIELD32, .validation_data = |
| * &myvalidflags }, |
| * }; |
| */ |
| |
| struct nla_policy |
| { |
| uint16_t type; |
| uint16_t len; |
| FAR void *validation_data; |
| }; |
| |
| /**************************************************************************** |
| * Public Data |
| ****************************************************************************/ |
| |
| #ifdef __cplusplus |
| # define EXTERN extern "C" |
| extern "C" |
| { |
| #else |
| # define EXTERN extern |
| #endif |
| |
| EXTERN const struct sock_intf_s g_netlink_sockif; |
| |
| /**************************************************************************** |
| * Name: netlink_initialize() |
| * |
| * Description: |
| * Initialize the NetLink connection structures. Called once and only |
| * from the networking layer. |
| * |
| ****************************************************************************/ |
| |
| void netlink_initialize(void); |
| |
| /**************************************************************************** |
| * Name: netlink_alloc() |
| * |
| * Description: |
| * Allocate a new, uninitialized NetLink connection structure. This is |
| * normally something done by the implementation of the socket() API |
| * |
| ****************************************************************************/ |
| |
| FAR struct netlink_conn_s *netlink_alloc(void); |
| |
| /**************************************************************************** |
| * Name: netlink_free() |
| * |
| * Description: |
| * Free a NetLink connection structure that is no longer in use. This |
| * should be done by the implementation of close(). |
| * |
| ****************************************************************************/ |
| |
| void netlink_free(FAR struct netlink_conn_s *conn); |
| |
| /**************************************************************************** |
| * Name: netlink_nextconn() |
| * |
| * Description: |
| * Traverse the list of allocated NetLink connections |
| * |
| * Assumptions: |
| * This function is called from NetLink device logic. |
| * |
| ****************************************************************************/ |
| |
| FAR struct netlink_conn_s *netlink_nextconn(FAR struct netlink_conn_s *conn); |
| |
| /**************************************************************************** |
| * Name: netlink_notifier_setup |
| * |
| * Description: |
| * Set up to perform a callback to the worker function the Netlink |
| * response data is received. The worker function will execute on the low |
| * priority worker thread. |
| * |
| * Input Parameters: |
| * worker - The worker function to execute on the low priority work |
| * queue when Netlink response data is available. |
| * conn - The Netlink connection where the response is expected. |
| * arg - A user-defined argument that will be available to the worker |
| * function when it runs. |
| * |
| * Returned Value: |
| * Zero (OK) is returned if the notification was successfully set up. |
| * A negated error value is returned if an unexpected error occurred |
| * and no notification will occur. |
| * |
| ****************************************************************************/ |
| |
| int netlink_notifier_setup(worker_t worker, FAR struct netlink_conn_s *conn, |
| FAR void *arg); |
| |
| /**************************************************************************** |
| * Name: netlink_notifier_teardown |
| * |
| * Description: |
| * Eliminate a Netlink response notification previously setup by |
| * netlink_notifier_setup(). This function should only be called if the |
| * notification should be aborted prior to the notification. The |
| * notification will automatically be torn down after the notification. |
| * |
| * Input Parameters: |
| * conn - Teardown the notification for this Netlink connection. |
| * |
| ****************************************************************************/ |
| |
| void netlink_notifier_teardown(FAR struct netlink_conn_s *conn); |
| |
| /**************************************************************************** |
| * Name: netlink_notifier_signal |
| * |
| * Description: |
| * New Netlink response data is available. Execute worker thread |
| * functions for all threads that wait for response data. |
| * |
| * Input Parameters: |
| * conn - The Netlink connection where the response was just buffered. |
| * |
| * Returned Value: |
| * None. |
| * |
| ****************************************************************************/ |
| |
| void netlink_notifier_signal(FAR struct netlink_conn_s *conn); |
| |
| /**************************************************************************** |
| * Name: netlink_add_terminator |
| * |
| * Description: |
| * Add one NLMSG_DONE response to handle. |
| * |
| * Input Parameters: |
| * handle - The handle previously provided to the sendto() implementation |
| * for the protocol. This is an opaque reference to the Netlink |
| * socket state structure. |
| * req - The request message header. |
| * group - The broadcast group index, 0 for normal response. |
| * |
| * Returned Value: |
| * Zero (OK) is returned if the terminator was successfully added to the |
| * response list. |
| * A negated error value is returned if an unexpected error occurred. |
| * |
| ****************************************************************************/ |
| |
| int netlink_add_terminator(NETLINK_HANDLE handle, |
| FAR const struct nlmsghdr *req, int group); |
| |
| /**************************************************************************** |
| * Name: netlink_tryget_response |
| * |
| * Description: |
| * Return the next response from the head of the pending response list. |
| * Responses are returned one-at-a-time in FIFO order. |
| * |
| * Note: The network will be momentarily locked to support exclusive |
| * access to the pending response list. |
| * |
| * Returned Value: |
| * The next response from the head of the pending response list is |
| * returned. NULL will be returned if the pending response list is |
| * empty |
| * |
| ****************************************************************************/ |
| |
| FAR struct netlink_response_s * |
| netlink_tryget_response(FAR struct netlink_conn_s *conn); |
| |
| /**************************************************************************** |
| * Name: netlink_get_response |
| * |
| * Description: |
| * Return the next response from the head of the pending response list. |
| * Responses are returned one-at-a-time in FIFO order. |
| * |
| * Note: The network will be momentarily locked to support exclusive |
| * access to the pending response list. |
| * |
| * Returned Value: |
| * The next response from the head of the pending response list is |
| * returned. This function will block until a response is received if |
| * the pending response list is empty. NULL will be returned only in the |
| * event of a failure. |
| * |
| ****************************************************************************/ |
| |
| FAR struct netlink_response_s * |
| netlink_get_response(FAR struct netlink_conn_s *conn); |
| |
| /**************************************************************************** |
| * Name: netlink_check_response |
| * |
| * Description: |
| * Return true is a response is pending now. |
| * |
| * Returned Value: |
| * True: A response is available; False; No response is available. |
| * |
| ****************************************************************************/ |
| |
| bool netlink_check_response(FAR struct netlink_conn_s *conn); |
| |
| /**************************************************************************** |
| * Name: netlink_route_sendto() |
| * |
| * Description: |
| * Perform the sendto() operation for the NETLINK_ROUTE protocol. |
| * |
| ****************************************************************************/ |
| |
| #ifdef CONFIG_NETLINK_ROUTE |
| ssize_t netlink_route_sendto(NETLINK_HANDLE handle, |
| FAR const struct nlmsghdr *nlmsg, |
| size_t len, int flags, |
| FAR const struct sockaddr_nl *to, |
| socklen_t tolen); |
| |
| /**************************************************************************** |
| * Name: netlink_device_notify() |
| * |
| * Description: |
| * Perform the route broadcast for the NETLINK_ROUTE protocol. |
| * |
| ****************************************************************************/ |
| |
| void netlink_device_notify(FAR struct net_driver_s *dev); |
| |
| /**************************************************************************** |
| * Name: netlink_device_notify_ipaddr() |
| * |
| * Description: |
| * Perform the route broadcast for the NETLINK_ROUTE protocol. |
| * |
| ****************************************************************************/ |
| |
| void netlink_device_notify_ipaddr(FAR struct net_driver_s *dev, |
| int type, int domain, |
| FAR const void *addr, uint8_t preflen); |
| |
| /**************************************************************************** |
| * Name: netlink_route_notify |
| * |
| * Description: |
| * Perform the route broadcast for the NETLINK_NETFILTER protocol. |
| * |
| * Input Parameters: |
| * route - The route entry |
| * type - The type of the message, RTM_*ROUTE |
| * domain - The domain of the message |
| * |
| ****************************************************************************/ |
| |
| #if defined CONFIG_NETLINK_DISABLE_GETROUTE |
| # define netlink_route_notify(route, type, domain) |
| #else |
| void netlink_route_notify(FAR const void *route, int type, int domain); |
| #endif |
| |
| /**************************************************************************** |
| * Name: netlink_neigh_notify() |
| * |
| * Description: |
| * Perform the neigh broadcast for the NETLINK_ROUTE protocol. |
| * |
| * Input Parameters: |
| * neigh - The ARP entry or neighbour entry |
| * type - The type of the message, RTM_*NEIGH |
| * domain - The domain of the message |
| * |
| ****************************************************************************/ |
| |
| #if defined(CONFIG_NETLINK_DISABLE_GETNEIGH) |
| # define netlink_neigh_notify(neigh, type, domain) |
| #else |
| void netlink_neigh_notify(FAR const void *neigh, int type, int domain); |
| #endif |
| |
| /**************************************************************************** |
| * Name: netlink_ipv6_prefix_notify() |
| * |
| * Description: |
| * Perform the RA prefix for the NETLINK_ROUTE protocol. |
| * |
| ****************************************************************************/ |
| |
| #if defined(CONFIG_NETLINK_DISABLE_NEWPREFIX) || !defined(CONFIG_NET_IPv6) |
| # define netlink_ipv6_prefix_notify(dev, type, pinfo) |
| #else |
| void netlink_ipv6_prefix_notify(FAR struct net_driver_s *dev, int type, |
| FAR const struct icmpv6_prefixinfo_s *pinfo); |
| #endif |
| |
| /**************************************************************************** |
| * Name: nla_next |
| * |
| * Description: |
| * Next netlink attribute in attribute stream. |
| * |
| * Input Parameters: |
| * nla - netlink attribute. |
| * remaining - number of bytes remaining in attribute stream. |
| * |
| * Returned Value: |
| * Returns the next netlink attribute in the attribute stream and |
| * decrements remaining by the size of the current attribute. |
| * |
| ****************************************************************************/ |
| |
| FAR struct nlattr *nla_next(FAR const struct nlattr *nla, |
| FAR int *remaining); |
| |
| /**************************************************************************** |
| * Name: nla_parse |
| * |
| * Description: |
| * Parse the nested netlink attribute. |
| * |
| ****************************************************************************/ |
| |
| int nla_parse(FAR struct nlattr **tb, int maxtype, |
| FAR const struct nlattr *head, |
| int len, FAR const struct nla_policy *policy, |
| FAR struct netlink_ext_ack *extack); |
| #endif /* CONFIG_NETLINK_ROUTE */ |
| |
| /**************************************************************************** |
| * Name: netlink_netfilter_sendto |
| * |
| * Description: |
| * Perform the sendto() operation for the NETLINK_NETFILTER protocol. |
| * |
| ****************************************************************************/ |
| |
| #ifdef CONFIG_NETLINK_NETFILTER |
| ssize_t netlink_netfilter_sendto(NETLINK_HANDLE handle, |
| FAR const struct nlmsghdr *nlmsg, |
| size_t len, int flags, |
| FAR const struct sockaddr_nl *to, |
| socklen_t tolen); |
| |
| /**************************************************************************** |
| * Name: netlink_conntrack_notify |
| * |
| * Description: |
| * Perform the conntrack broadcast for the NETLINK_NETFILTER protocol. |
| * |
| * Input Parameters: |
| * type - The type of the message, IPCTNL_MSG_CT_* |
| * domain - The domain of the message |
| * nat_entry - The NAT entry |
| * |
| ****************************************************************************/ |
| |
| void netlink_conntrack_notify(uint8_t type, uint8_t domain, |
| FAR const void *nat_entry); |
| |
| #endif /* CONFIG_NETLINK_NETFILTER */ |
| |
| #undef EXTERN |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* CONFIG_NET_NETLINK */ |
| #endif /* __NET_NETLINK_NETLINK_H */ |