From 34aeeb024c9b59b22c8a57d63aaaae2c56460319 Mon Sep 17 00:00:00 2001 From: meijian Date: Tue, 9 Apr 2024 21:07:57 +0800 Subject: [PATCH] net/netlink: Add RTM route support Signed-off-by: meijian --- net/netlink/netlink.h | 20 ++++ net/netlink/netlink_route.c | 167 +++++++++++++++++++++++++++------- net/route/net_add_fileroute.c | 5 + net/route/net_add_ramroute.c | 5 + net/route/net_del_fileroute.c | 5 + net/route/net_del_ramroute.c | 20 ++-- 6 files changed, 183 insertions(+), 39 deletions(-) diff --git a/net/netlink/netlink.h b/net/netlink/netlink.h index 9e8fc9e584..474a898c16 100644 --- a/net/netlink/netlink.h +++ b/net/netlink/netlink.h @@ -46,6 +46,7 @@ #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) #endif #ifdef CONFIG_NET_NETLINK @@ -512,6 +513,25 @@ 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: nla_next * diff --git a/net/netlink/netlink_route.c b/net/netlink/netlink_route.c index 0f4bdc2e18..e91241a1d0 100644 --- a/net/netlink/netlink_route.c +++ b/net/netlink/netlink_route.c @@ -663,15 +663,14 @@ static int netlink_get_nbtable(NETLINK_HANDLE handle, ****************************************************************************/ #if defined(CONFIG_NET_IPv4) && !defined(CONFIG_NETLINK_DISABLE_GETROUTE) -static int netlink_ipv4_route(FAR struct net_route_ipv4_s *route, - FAR void *arg) +static FAR struct netlink_response_s * +netlink_get_ipv4_route(FAR const struct net_route_ipv4_s *route, int type, + FAR const struct nlroute_sendto_request_s *req) { FAR struct getroute_recvfrom_ipv4resplist_s *alloc; FAR struct getroute_recvfrom_ipv4response_s *resp; - FAR struct nlroute_info_s *info; - DEBUGASSERT(route != NULL && arg != NULL); - info = (FAR struct nlroute_info_s *)arg; + DEBUGASSERT(route != NULL); /* Allocate the response */ @@ -679,19 +678,19 @@ static int netlink_ipv4_route(FAR struct net_route_ipv4_s *route, kmm_zalloc(sizeof(struct getroute_recvfrom_ipv4resplist_s)); if (alloc == NULL) { - return -ENOMEM; + return NULL; } /* Format the response */ resp = &alloc->payload; resp->hdr.nlmsg_len = sizeof(struct getroute_recvfrom_ipv4response_s); - resp->hdr.nlmsg_type = RTM_NEWROUTE; - resp->hdr.nlmsg_flags = info->req->hdr.nlmsg_flags; - resp->hdr.nlmsg_seq = info->req->hdr.nlmsg_seq; - resp->hdr.nlmsg_pid = info->req->hdr.nlmsg_pid; + resp->hdr.nlmsg_type = type; + resp->hdr.nlmsg_flags = req ? req->hdr.nlmsg_flags : 0; + resp->hdr.nlmsg_seq = req ? req->hdr.nlmsg_seq : 0; + resp->hdr.nlmsg_pid = req ? req->hdr.nlmsg_pid : 0; - resp->rte.rtm_family = info->req->gen.rtgen_family; + resp->rte.rtm_family = AF_INET; resp->rte.rtm_table = RT_TABLE_MAIN; resp->rte.rtm_protocol = RTPROT_STATIC; resp->rte.rtm_scope = RT_SCOPE_SITE; @@ -708,15 +707,39 @@ static int netlink_ipv4_route(FAR struct net_route_ipv4_s *route, resp->gateway.attr.rta_type = RTA_GATEWAY; resp->gateway.addr = route->router; + return (FAR struct netlink_response_s *)alloc; +} + +/**************************************************************************** + * Name: netlink_ipv4route_callback + * + * Input Parameters: + * route - The entry of IPV4 routing table. + * arg - The netlink info of request. + * + ****************************************************************************/ + +static int netlink_ipv4route_callback(FAR struct net_route_ipv4_s *route, + FAR void *arg) +{ + FAR struct nlroute_info_s *info = arg; + FAR struct netlink_response_s *resp; + + resp = netlink_get_ipv4_route(route, RTM_NEWROUTE, info->req); + if (resp == NULL) + { + return -ENOENT; + } + /* Finally, add the response to the list of pending responses */ - netlink_add_response(info->handle, (FAR struct netlink_response_s *)alloc); + netlink_add_response(info->handle, resp); return OK; } #endif /**************************************************************************** - * Name: netlink_get_ipv4route + * Name: netlink_list_ipv4_route * * Description: * Dump a list of all network devices of the specified type. @@ -724,7 +747,7 @@ static int netlink_ipv4_route(FAR struct net_route_ipv4_s *route, ****************************************************************************/ #if defined(CONFIG_NET_IPv4) && !defined(CONFIG_NETLINK_DISABLE_GETROUTE) -static int netlink_get_ipv4route(NETLINK_HANDLE handle, +static int netlink_list_ipv4_route(NETLINK_HANDLE handle, FAR const struct nlroute_sendto_request_s *req) { struct nlroute_info_s info; @@ -735,7 +758,7 @@ static int netlink_get_ipv4route(NETLINK_HANDLE handle, info.handle = handle; info.req = req; - ret = net_foreachroute_ipv4(netlink_ipv4_route, &info); + ret = net_foreachroute_ipv4(netlink_ipv4route_callback, &info); if (ret < 0) { return ret; @@ -748,7 +771,7 @@ static int netlink_get_ipv4route(NETLINK_HANDLE handle, #endif /**************************************************************************** - * Name: netlink_ipv6_route + * Name: netlink_get_ipv6_route * * Description: * Dump a list of all network devices of the specified type. @@ -756,15 +779,14 @@ static int netlink_get_ipv4route(NETLINK_HANDLE handle, ****************************************************************************/ #if defined(CONFIG_NET_IPv6) && !defined(CONFIG_NETLINK_DISABLE_GETROUTE) -static int netlink_ipv6_route(FAR struct net_route_ipv6_s *route, - FAR void *arg) +static FAR struct netlink_response_s * +netlink_get_ipv6_route(FAR const struct net_route_ipv6_s *route, int type, + FAR const struct nlroute_sendto_request_s *req) { FAR struct getroute_recvfrom_ipv6resplist_s *alloc; FAR struct getroute_recvfrom_ipv6response_s *resp; - FAR struct nlroute_info_s *info; - DEBUGASSERT(route != NULL && arg != NULL); - info = (FAR struct nlroute_info_s *)arg; + DEBUGASSERT(route != NULL); /* Allocate the response */ @@ -772,19 +794,19 @@ static int netlink_ipv6_route(FAR struct net_route_ipv6_s *route, kmm_zalloc(sizeof(struct getroute_recvfrom_ipv6resplist_s)); if (alloc == NULL) { - return -ENOMEM; + return NULL; } /* Format the response */ resp = &alloc->payload; resp->hdr.nlmsg_len = sizeof(struct getroute_recvfrom_ipv6response_s); - resp->hdr.nlmsg_type = RTM_NEWROUTE; - resp->hdr.nlmsg_flags = info->req->hdr.nlmsg_flags; - resp->hdr.nlmsg_seq = info->req->hdr.nlmsg_seq; - resp->hdr.nlmsg_pid = info->req->hdr.nlmsg_pid; + resp->hdr.nlmsg_type = type; + resp->hdr.nlmsg_flags = req ? req->hdr.nlmsg_flags : 0; + resp->hdr.nlmsg_seq = req ? req->hdr.nlmsg_seq : 0; + resp->hdr.nlmsg_pid = req ? req->hdr.nlmsg_pid : 0; - resp->rte.rtm_family = info->req->gen.rtgen_family; + resp->rte.rtm_family = AF_INET6; resp->rte.rtm_table = RT_TABLE_MAIN; resp->rte.rtm_protocol = RTPROT_STATIC; resp->rte.rtm_scope = RT_SCOPE_SITE; @@ -801,9 +823,37 @@ static int netlink_ipv6_route(FAR struct net_route_ipv6_s *route, resp->gateway.attr.rta_type = RTA_GATEWAY; net_ipv6addr_copy(resp->gateway.addr, route->router); + return (FAR struct netlink_response_s *)alloc; +} + +/**************************************************************************** + * Name: netlink_ipv6route_callback + * + * Description: + * Response netlink message from ipv6 route list. + * + * Input Parameters: + * route - The entry of IPV6 routing table. + * arg - The netlink info of request. + * + ****************************************************************************/ + +static int netlink_ipv6route_callback(FAR struct net_route_ipv6_s *route, + FAR void *arg) +{ + FAR struct nlroute_info_s *info = arg; + FAR struct netlink_response_s *resp; + + resp = netlink_get_ipv6_route(route, RTM_NEWROUTE, info->req); + if (resp == NULL) + { + return -ENOENT; + } + /* Finally, add the response to the list of pending responses */ - netlink_add_response(info->handle, (FAR struct netlink_response_s *)alloc); + netlink_add_response(info->handle, resp); + return OK; } #endif @@ -817,7 +867,7 @@ static int netlink_ipv6_route(FAR struct net_route_ipv6_s *route, ****************************************************************************/ #if defined(CONFIG_NET_IPv6) && !defined(CONFIG_NETLINK_DISABLE_GETROUTE) -static int netlink_get_ipv6route(NETLINK_HANDLE handle, +static int netlink_list_ipv6_route(NETLINK_HANDLE handle, FAR const struct nlroute_sendto_request_s *req) { struct nlroute_info_s info; @@ -828,7 +878,7 @@ static int netlink_get_ipv6route(NETLINK_HANDLE handle, info.handle = handle; info.req = req; - ret = net_foreachroute_ipv6(netlink_ipv6_route, &info); + ret = net_foreachroute_ipv6(netlink_ipv6route_callback, &info); if (ret < 0) { return ret; @@ -1211,14 +1261,14 @@ ssize_t netlink_route_sendto(NETLINK_HANDLE handle, #ifdef CONFIG_NET_IPv4 if (req->gen.rtgen_family == AF_INET) { - ret = netlink_get_ipv4route(handle, req); + ret = netlink_list_ipv4_route(handle, req); } else #endif #ifdef CONFIG_NET_IPv6 if (req->gen.rtgen_family == AF_INET6) { - ret = netlink_get_ipv6route(handle, req); + ret = netlink_list_ipv6_route(handle, req); } else #endif @@ -1388,4 +1438,57 @@ void netlink_device_notify_ipaddr(FAR struct net_driver_s *dev, } #endif +/**************************************************************************** + * 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 + * + ****************************************************************************/ + +#ifndef CONFIG_NETLINK_DISABLE_GETROUTE +void netlink_route_notify(FAR const void *route, int type, int domain) +{ + FAR struct netlink_response_s *resp; + int group; + + DEBUGASSERT(route != NULL); + +#ifdef CONFIG_NET_IPv4 + if (domain == AF_INET) + { + resp = netlink_get_ipv4_route((FAR struct net_route_ipv4_s *)route, + type, NULL); + group = RTNLGRP_IPV4_ROUTE; + } + else +#endif +#ifdef CONFIG_NET_IPv6 + if (domain == AF_INET6) + { + resp = netlink_get_ipv6_route((FAR struct net_route_ipv6_s *)route, + type, NULL); + group = RTNLGRP_IPV6_ROUTE; + } + else +#endif + { + nwarn("netlink_route_notify unknown type %d domain %d\n", + type, domain); + return; + } + + if (resp != NULL) + { + netlink_add_broadcast(group, resp); + netlink_add_terminator(NULL, NULL, group); + } +} +#endif + #endif /* CONFIG_NETLINK_ROUTE */ diff --git a/net/route/net_add_fileroute.c b/net/route/net_add_fileroute.c index 6c846c6c6f..51593ac47a 100644 --- a/net/route/net_add_fileroute.c +++ b/net/route/net_add_fileroute.c @@ -33,6 +33,7 @@ #include #include +#include "netlink/netlink.h" #include "route/fileroute.h" #include "route/route.h" @@ -84,6 +85,8 @@ int net_addroute_ipv4(in_addr_t target, in_addr_t netmask, in_addr_t router) nwritten = net_writeroute_ipv4(&fshandle, &route); net_closeroute_ipv4(&fshandle); + + netlink_route_notify(&route, RTM_NEWROUTE, AF_INET); return nwritten >= 0 ? 0 : (int)nwritten; } #endif @@ -118,6 +121,8 @@ int net_addroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask, nwritten = net_writeroute_ipv6(&fshandle, &route); net_closeroute_ipv6(&fshandle); + + netlink_route_notify(&route, RTM_NEWROUTE, AF_INET6); return nwritten >= 0 ? 0 : (int)nwritten; } #endif diff --git a/net/route/net_add_ramroute.c b/net/route/net_add_ramroute.c index 05adde4625..5f1907839d 100644 --- a/net/route/net_add_ramroute.c +++ b/net/route/net_add_ramroute.c @@ -34,6 +34,7 @@ #include +#include "netlink/netlink.h" #include "route/ramroute.h" #include "route/route.h" @@ -86,6 +87,8 @@ int net_addroute_ipv4(in_addr_t target, in_addr_t netmask, in_addr_t router) ramroute_ipv4_addlast((FAR struct net_route_ipv4_entry_s *)route, &g_ipv4_routes); net_unlock(); + + netlink_route_notify(route, RTM_NEWROUTE, AF_INET); return OK; } #endif @@ -121,6 +124,8 @@ int net_addroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask, ramroute_ipv6_addlast((FAR struct net_route_ipv6_entry_s *)route, &g_ipv6_routes); net_unlock(); + + netlink_route_notify(route, RTM_NEWROUTE, AF_INET6); return OK; } #endif diff --git a/net/route/net_del_fileroute.c b/net/route/net_del_fileroute.c index dff88fe7df..5c232ec030 100644 --- a/net/route/net_del_fileroute.c +++ b/net/route/net_del_fileroute.c @@ -36,6 +36,7 @@ #include #include +#include "netlink/netlink.h" #include "route/fileroute.h" #include "route/cacheroute.h" #include "route/route.h" @@ -313,6 +314,8 @@ int net_delroute_ipv4(in_addr_t target, in_addr_t netmask) filesize = (nentries - 1) * sizeof(struct net_route_ipv4_s); ret = file_truncate(&fshandle, filesize); + netlink_route_notify(&match, RTM_DELROUTE, AF_INET); + errout_with_fshandle: net_closeroute_ipv4(&fshandle); @@ -464,6 +467,8 @@ int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask) filesize = (nentries - 1) * sizeof(struct net_route_ipv6_s); ret = file_truncate(&fshandle, filesize); + netlink_route_notify(&match, RTM_DELROUTE, AF_INET6); + errout_with_fshandle: net_closeroute_ipv6(&fshandle); diff --git a/net/route/net_del_ramroute.c b/net/route/net_del_ramroute.c index 5914dd46d2..71e8b067b7 100644 --- a/net/route/net_del_ramroute.c +++ b/net/route/net_del_ramroute.c @@ -32,6 +32,7 @@ #include #include +#include "netlink/netlink.h" #include "route/ramroute.h" #include "route/route.h" @@ -64,10 +65,10 @@ struct route_match_ipv6_s ****************************************************************************/ /**************************************************************************** - * Name: net_match_ipv4 + * Name: net_del_ipv4route * * Description: - * Return 1 if the route is available + * Return 1 if the route is available, and delete the match route * * Input Parameters: * route - The next route to examine @@ -79,7 +80,8 @@ struct route_match_ipv6_s ****************************************************************************/ #ifdef CONFIG_ROUTE_IPv4_RAMROUTE -static int net_match_ipv4(FAR struct net_route_ipv4_s *route, FAR void *arg) +static int net_del_ipv4route(FAR struct net_route_ipv4_s *route, + FAR void *arg) { FAR struct route_match_ipv4_s *match = (FAR struct route_match_ipv4_s *)arg; @@ -109,6 +111,8 @@ static int net_match_ipv4(FAR struct net_route_ipv4_s *route, FAR void *arg) ramroute_ipv4_remfirst(&g_ipv4_routes); } + netlink_route_notify(route, RTM_DELROUTE, AF_INET); + /* And free the routing table entry by adding it to the free list */ net_freeroute_ipv4(route); @@ -126,8 +130,8 @@ static int net_match_ipv4(FAR struct net_route_ipv4_s *route, FAR void *arg) #endif #ifdef CONFIG_ROUTE_IPv6_RAMROUTE -static int net_match_ipv6( - FAR struct net_route_ipv6_s *route, FAR void *arg) +static int net_del_ipv6route(FAR struct net_route_ipv6_s *route, + FAR void *arg) { FAR struct route_match_ipv6_s *match = (FAR struct route_match_ipv6_s *)arg; @@ -165,6 +169,8 @@ static int net_match_ipv6( ramroute_ipv6_remfirst(&g_ipv6_routes); } + netlink_route_notify(route, RTM_DELROUTE, AF_INET6); + /* And free the routing table entry by adding it to the free list */ net_freeroute_ipv6(route); @@ -211,7 +217,7 @@ int net_delroute_ipv4(in_addr_t target, in_addr_t netmask) /* Then remove the entry from the routing table */ - return net_foreachroute_ipv4(net_match_ipv4, &match) ? OK : -ENOENT; + return net_foreachroute_ipv4(net_del_ipv4route, &match) ? OK : -ENOENT; } #endif @@ -228,7 +234,7 @@ int net_delroute_ipv6(net_ipv6addr_t target, net_ipv6addr_t netmask) /* Then remove the entry from the routing table */ - return net_foreachroute_ipv6(net_match_ipv6, &match) ? OK : -ENOENT; + return net_foreachroute_ipv6(net_del_ipv6route, &match) ? OK : -ENOENT; } #endif