@@ -44,6 +44,11 @@ KHASH_INIT(ucs_netlink_rt_cache, khint32_t, ucs_netlink_rt_rules_t, 1,
4444 kh_int_hash_func , kh_int_hash_equal );
4545static khash_t (ucs_netlink_rt_cache ) ucs_netlink_routing_table_cache ;
4646
47+ static inline int ucs_netlink_is_msg_done (const struct nlmsghdr * nlh )
48+ {
49+ return (nlh -> nlmsg_type == NLMSG_DONE );
50+ }
51+
4752static ucs_status_t ucs_netlink_socket_init (int * fd_p , int protocol )
4853{
4954 struct sockaddr_nl sa = {.nl_family = AF_NETLINK };
@@ -78,7 +83,7 @@ ucs_netlink_parse_msg(const void *msg, size_t msg_len,
7883 const struct nlmsghdr * nlh = (const struct nlmsghdr * )msg ;
7984
8085 while ((status == UCS_INPROGRESS ) && NLMSG_OK (nlh , msg_len ) &&
81- (nlh -> nlmsg_type != NLMSG_DONE )) {
86+ ! ucs_netlink_is_msg_done (nlh )) {
8287 if (nlh -> nlmsg_type == NLMSG_ERROR ) {
8388 struct nlmsgerr * err = (struct nlmsgerr * )NLMSG_DATA (nlh );
8489 ucs_error ("received error response from netlink err=%d: %s\n" ,
@@ -100,9 +105,10 @@ ucs_netlink_send_request(int protocol, unsigned short nlmsg_type,
100105 ucs_netlink_parse_cb_t parse_cb , void * arg )
101106{
102107 struct nlmsghdr nlh = {0 };
103- char * recv_msg = NULL ;
104- size_t recv_msg_len = 0 ;
105108 int netlink_fd = -1 ;
109+ size_t recv_msg_len ;
110+ char * recv_msg ;
111+ int msg_done ;
106112 ucs_status_t status ;
107113 struct iovec iov [2 ];
108114 size_t bytes_sent ;
@@ -131,33 +137,38 @@ ucs_netlink_send_request(int protocol, unsigned short nlmsg_type,
131137 }
132138
133139 /* get message size */
134- status = ucs_socket_recv_nb (netlink_fd , NULL , MSG_PEEK | MSG_TRUNC ,
135- & recv_msg_len );
136- if (status != UCS_OK ) {
137- ucs_error ("failed to get netlink message size %d (%s)" ,
138- status , ucs_status_string (status ));
139- goto out ;
140- }
140+ do {
141+ recv_msg_len = 0 ;
142+ status = ucs_socket_recv_nb (netlink_fd , NULL , MSG_PEEK | MSG_TRUNC ,
143+ & recv_msg_len );
144+ if (status != UCS_OK ) {
145+ ucs_error ("failed to get netlink message size %d (%s)" ,
146+ status , ucs_status_string (status ));
147+ goto out ;
148+ }
141149
142- recv_msg = ucs_malloc (recv_msg_len , "netlink recv message" );
143- if (recv_msg == NULL ) {
144- ucs_error ("failed to allocate a buffer for netlink receive message of "
145- " size %zu" , recv_msg_len );
146- goto out ;
147- }
150+ recv_msg = ucs_malloc (recv_msg_len , "netlink recv message" );
151+ if (recv_msg == NULL ) {
152+ ucs_error ("failed to allocate a buffer for netlink receive message"
153+ " of size %zu" , recv_msg_len );
154+ goto out ;
155+ }
148156
149- status = ucs_socket_recv (netlink_fd , recv_msg , recv_msg_len );
150- if (status != UCS_OK ) {
151- ucs_error ("failed to receive netlink message on fd=%d: %s" ,
152- netlink_fd , ucs_status_string (status ));
153- goto out ;
154- }
157+ status = ucs_socket_recv (netlink_fd , recv_msg , recv_msg_len );
158+ if (status != UCS_OK ) {
159+ ucs_error ("failed to receive netlink message on fd=%d: %s" ,
160+ netlink_fd , ucs_status_string (status ));
161+ ucs_free (recv_msg );
162+ goto out ;
163+ }
155164
156- status = ucs_netlink_parse_msg (recv_msg , recv_msg_len , parse_cb , arg );
165+ status = ucs_netlink_parse_msg (recv_msg , recv_msg_len , parse_cb , arg );
166+ msg_done = ucs_netlink_is_msg_done ((const struct nlmsghdr * )recv_msg );
167+ ucs_free (recv_msg );
168+ } while ((nlmsg_flags & NLM_F_DUMP ) && !msg_done );
157169
158170out :
159171 ucs_close_fd (& netlink_fd );
160- ucs_free (recv_msg );
161172 return status ;
162173}
163174
@@ -262,8 +273,8 @@ int ucs_netlink_route_exists(int if_index, const struct sockaddr *sa_remote)
262273 ucs_netlink_route_info_t info ;
263274
264275 UCS_INIT_ONCE (& init_once ) {
276+ rtm .rtm_table = RT_TABLE_UNSPEC ; /* fetch all the tables */
265277 rtm .rtm_family = AF_INET ;
266- rtm .rtm_table = RT_TABLE_MAIN ;
267278 ucs_netlink_send_request (NETLINK_ROUTE , RTM_GETROUTE , NLM_F_DUMP , & rtm ,
268279 sizeof (rtm ), ucs_netlink_parse_rt_entry_cb ,
269280 NULL );
0 commit comments