4141
4242#ifndef NDA_RTA
4343# define NDA_RTA (r ) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
44- #endif
44+ #endif
45+
46+ /* Used to request refresh of addresses or routes just once,
47+ * when multiple changes might be announced. */
48+ enum async_states {
49+ STATE_NEWADDR = (1 << 0 ),
50+ STATE_NEWROUTE = (1 << 1 ),
51+ };
4552
4653
4754static struct iovec iov ;
4855static u32 netlink_pid ;
4956
50- static void nl_async (struct nlmsghdr * h );
57+ static unsigned nl_async (struct nlmsghdr * h , unsigned state );
5158
5259char * netlink_init (void )
5360{
@@ -159,6 +166,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
159166 ssize_t len ;
160167 static unsigned int seq = 0 ;
161168 int callback_ok = 1 ;
169+ unsigned state = 0 ;
162170
163171 struct {
164172 struct nlmsghdr nlh ;
@@ -207,7 +215,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
207215 if (h -> nlmsg_pid != netlink_pid || h -> nlmsg_type == NLMSG_ERROR )
208216 {
209217 /* May be multicast arriving async */
210- nl_async (h );
218+ state = nl_async (h , state );
211219 }
212220 else if (h -> nlmsg_seq != seq )
213221 {
@@ -346,29 +354,30 @@ void netlink_multicast(void)
346354 ssize_t len ;
347355 struct nlmsghdr * h ;
348356 int flags ;
357+ unsigned state = 0 ;
349358
350359 /* don't risk blocking reading netlink messages here. */
351360 if ((flags = fcntl (daemon -> netlinkfd , F_GETFL )) == -1 ||
352361 fcntl (daemon -> netlinkfd , F_SETFL , flags | O_NONBLOCK ) == -1 )
353362 return ;
354363
355- if ((len = netlink_recv ()) != -1 )
364+ while ((len = netlink_recv ()) != -1 )
356365 for (h = (struct nlmsghdr * )iov .iov_base ; NLMSG_OK (h , (size_t )len ); h = NLMSG_NEXT (h , len ))
357- nl_async (h );
366+ state = nl_async (h , state );
358367
359368 /* restore non-blocking status */
360369 fcntl (daemon -> netlinkfd , F_SETFL , flags );
361370}
362371
363- static void nl_async (struct nlmsghdr * h )
372+ static unsigned nl_async (struct nlmsghdr * h , unsigned state )
364373{
365374 if (h -> nlmsg_type == NLMSG_ERROR )
366375 {
367376 struct nlmsgerr * err = NLMSG_DATA (h );
368377 if (err -> error != 0 )
369378 my_syslog (LOG_ERR , _ ("netlink returns error: %s" ), strerror (- (err -> error )));
370379 }
371- else if (h -> nlmsg_pid == 0 && h -> nlmsg_type == RTM_NEWROUTE )
380+ else if (h -> nlmsg_pid == 0 && h -> nlmsg_type == RTM_NEWROUTE && ( state & STATE_NEWROUTE ) == 0 )
372381 {
373382 /* We arrange to receive netlink multicast messages whenever the network route is added.
374383 If this happens and we still have a DNS packet in the buffer, we re-send it.
@@ -380,10 +389,17 @@ static void nl_async(struct nlmsghdr *h)
380389 if (rtm -> rtm_type == RTN_UNICAST && rtm -> rtm_scope == RT_SCOPE_LINK &&
381390 (rtm -> rtm_table == RT_TABLE_MAIN ||
382391 rtm -> rtm_table == RT_TABLE_LOCAL ))
383- queue_event (EVENT_NEWROUTE );
392+ {
393+ queue_event (EVENT_NEWROUTE );
394+ state |= STATE_NEWROUTE ;
395+ }
396+ }
397+ else if ((state & STATE_NEWADDR )== 0 && (h -> nlmsg_type == RTM_NEWADDR || h -> nlmsg_type == RTM_DELADDR ))
398+ {
399+ queue_event (EVENT_NEWADDR );
400+ state |= STATE_NEWADDR ;
384401 }
385- else if (h -> nlmsg_type == RTM_NEWADDR || h -> nlmsg_type == RTM_DELADDR )
386- queue_event (EVENT_NEWADDR );
402+ return state ;
387403}
388404#endif
389405
0 commit comments