@@ -1378,11 +1378,29 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind
13781378 return 1 ;
13791379}
13801380
1381+ static int allocate_sfd_socket (union mysockaddr * addr , char * intname , unsigned int ifindex )
1382+ {
1383+ int fd ;
1384+ int opt = 1 ;
1385+
1386+ if ((fd = socket (addr -> sa .sa_family , SOCK_DGRAM , 0 )) == -1 )
1387+ return -1 ;
1388+
1389+ if ((addr -> sa .sa_family == AF_INET6 && setsockopt (fd , IPPROTO_IPV6 , IPV6_V6ONLY , & opt , sizeof (opt )) == -1 ) ||
1390+ !local_bind (fd , addr , intname , ifindex , 0 ) || !fix_fd (fd ))
1391+ {
1392+ int errsave = errno ; /* save error from bind/setsockopt. */
1393+ close (fd );
1394+ errno = errsave ;
1395+ return -1 ;
1396+ }
1397+ return fd ;
1398+ }
1399+
13811400static struct serverfd * allocate_sfd (union mysockaddr * addr , char * intname , unsigned int ifindex )
13821401{
13831402 struct serverfd * sfd ;
1384- int errsave ;
1385- int opt = 1 ;
1403+ int singlefd = 1 ;
13861404
13871405 /* when using random ports, servers which would otherwise use
13881406 the INADDR_ANY/port0 socket have sfd set to NULL, this is
@@ -1391,13 +1409,15 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname, unsi
13911409 {
13921410 errno = 0 ;
13931411
1394- if (addr -> sa .sa_family == AF_INET &&
1395- addr -> in .sin_port == htons (0 ))
1396- return NULL ;
1397-
1398- if (addr -> sa .sa_family == AF_INET6 &&
1399- addr -> in6 .sin6_port == htons (0 ))
1400- return NULL ;
1412+ if ((addr -> sa .sa_family == AF_INET &&
1413+ addr -> in .sin_port == htons (0 )) ||
1414+ (addr -> sa .sa_family == AF_INET6 &&
1415+ addr -> in6 .sin6_port == htons (0 )))
1416+ {
1417+ if (intname [0 ] == 0 )
1418+ return NULL ;
1419+ singlefd = 0 ;
1420+ }
14011421 }
14021422
14031423 /* may have a suitable one already */
@@ -1411,21 +1431,16 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname, unsi
14111431 errno = ENOMEM ; /* in case malloc fails. */
14121432 if (!(sfd = whine_malloc (sizeof (struct serverfd ))))
14131433 return NULL ;
1414-
1415- if ((sfd -> fd = socket (addr -> sa .sa_family , SOCK_DGRAM , 0 )) == -1 )
1416- {
1417- free (sfd );
1418- return NULL ;
1419- }
14201434
1421- if ((addr -> sa .sa_family == AF_INET6 && setsockopt (sfd -> fd , IPPROTO_IPV6 , IPV6_V6ONLY , & opt , sizeof (opt )) == -1 ) ||
1422- !local_bind (sfd -> fd , addr , intname , ifindex , 0 ) || !fix_fd (sfd -> fd ))
1423- {
1424- errsave = errno ; /* save error from bind/setsockopt. */
1425- close (sfd -> fd );
1426- free (sfd );
1427- errno = errsave ;
1428- return NULL ;
1435+ sfd -> fd = -1 ;
1436+ if (singlefd )
1437+ {
1438+ sfd -> fd = allocate_sfd_socket (addr , intname , ifindex );
1439+ if (sfd -> fd == -1 )
1440+ {
1441+ free (sfd );
1442+ return NULL ;
1443+ }
14291444 }
14301445
14311446 safe_strncpy (sfd -> interface , intname , sizeof (sfd -> interface ));
@@ -1607,6 +1622,27 @@ void add_update_server(int flags,
16071622 }
16081623}
16091624
1625+ static void free_sfd (struct serverfd * sfd )
1626+ {
1627+ int i ;
1628+ struct randfd_list * rl ;
1629+
1630+ /* If any random socket refers to this serverfd, invalidate the reference.
1631+ NULL is valid value in randfd.sfd, cannot use that. */
1632+ for (i = 0 ; i < RANDOM_SOCKS ; i ++ )
1633+ if (daemon -> randomsocks [i ].refcount != 0 && daemon -> randomsocks [i ].sfd == sfd )
1634+ daemon -> randomsocks [i ].sfd = SERVERFD_INVALID ;
1635+ for (rl = daemon -> rfl_poll ; rl ; rl = rl -> next )
1636+ /* Invalidate sfd pointer so it is no longer reused.
1637+ * Pending answers might be still received and processed. */
1638+ if (rl -> rfd -> sfd == sfd )
1639+ rl -> rfd -> sfd = SERVERFD_INVALID ;
1640+
1641+ if (sfd -> fd != -1 )
1642+ close (sfd -> fd );
1643+ free (sfd );
1644+ }
1645+
16101646void check_servers (void )
16111647{
16121648 struct irec * iface ;
@@ -1747,8 +1783,7 @@ void check_servers(void)
17471783 if (!sfd -> used )
17481784 {
17491785 * up = sfd -> next ;
1750- close (sfd -> fd );
1751- free (sfd );
1786+ free_sfd (sfd );
17521787 }
17531788 else
17541789 up = & sfd -> next ;
0 commit comments