From: Dave Hart Date: Thu, 11 Nov 2010 19:20:40 +0000 (+0000) Subject: [Bug 1683] Non-localhost on loopback exempted from nic rules. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1dbc07ab270202beae7252d88e5b2bccf19dc08b;p=thirdparty%2Fntp.git [Bug 1683] Non-localhost on loopback exempted from nic rules. bk: 4cdc42081Lx7FRbNxl5ht0MVQzLkEQ --- diff --git a/ChangeLog b/ChangeLog index c0c245e6a7..7bdf9004a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +--- + +* [Bug 1683] Non-localhost on loopback exempted from nic rules. + --- (4.2.6p3-RC9) 2010/11/10 Released by Harlan Stenn diff --git a/include/ntp.h b/include/ntp.h index 11285f47bd..898ce07c90 100644 --- a/include/ntp.h +++ b/include/ntp.h @@ -185,7 +185,7 @@ struct interface { char name[32]; /* name of interface */ u_short family; /* Address family */ u_short phase; /* phase in update cycle */ - int flags; /* interface flags */ + u_int32 flags; /* interface flags */ int last_ttl; /* last TTL specified */ u_int32 addr_refid; /* IPv4 addr or IPv6 hash */ int num_mcast; /* No. of IP addresses in multicast socket */ diff --git a/include/ntp_io.h b/include/ntp_io.h index 692d4440fc..7d88314ea8 100644 --- a/include/ntp_io.h +++ b/include/ntp_io.h @@ -81,7 +81,7 @@ typedef enum { isc_boolean_t get_broadcastclient_flag(void); -isc_boolean_t is_ip_address(const char *, isc_netaddr_t *); +extern int is_ip_address(const char *, sockaddr_u *); extern void sau_from_netaddr(sockaddr_u *, const isc_netaddr_t *); extern void add_nic_rule(nic_rule_match match_type, const char *if_name, int prefixlen, nic_rule_action action); diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c index e6fb56c24a..2bbc0b5c4a 100644 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@ -2160,8 +2160,8 @@ config_access( int * curr_flag; sockaddr_u addr_sock; sockaddr_u addr_mask; - int flags; - int mflags; + u_short flags; + u_short mflags; int restrict_default; const char * signd_warning = #ifdef HAVE_NTP_SIGND @@ -2430,12 +2430,13 @@ config_nic_rules( ) { nic_rule_node * curr_node; - isc_netaddr_t netaddr; + sockaddr_u addr; nic_rule_match match_type; nic_rule_action action; char * if_name; char * pchSlash; int prefixlen; + int addrbits; curr_node = queue_head(ptree->nic_rules); @@ -2482,16 +2483,16 @@ config_nic_rules( pchSlash = strchr(if_name, '/'); if (pchSlash != NULL) *pchSlash = '\0'; - if (is_ip_address(if_name, &netaddr)) { + if (is_ip_address(if_name, &addr)) { match_type = MATCH_IFADDR; if (pchSlash != NULL) { sscanf(pchSlash + 1, "%d", &prefixlen); + addrbits = 8 * + SIZEOF_INADDR(AF(&addr)); prefixlen = max(-1, prefixlen); - prefixlen = min(prefixlen, - (AF_INET6 == netaddr.family) - ? 128 - : 32); + prefixlen = min(prefixlen, + addrbits); } } else { match_type = MATCH_IFNAME; @@ -4317,7 +4318,7 @@ get_multiple_netnums( struct addrinfo hints; struct addrinfo *ptr; int retval; - isc_netaddr_t ipaddr; + sockaddr_u ipaddr; memset(&hints, 0, sizeof(hints)); @@ -4329,7 +4330,7 @@ get_multiple_netnums( lookup = nameornum; if (is_ip_address(nameornum, &ipaddr)) { hints.ai_flags = AI_NUMERICHOST; - hints.ai_family = ipaddr.family; + hints.ai_family = AF(&ipaddr); if ('[' == nameornum[0]) { lookup = lookbuf; strncpy(lookbuf, &nameornum[1], @@ -4387,8 +4388,9 @@ get_multiple_netnums( if (!retval) { freeaddrinfo(ptr); return -1; - } else + } else { return 0; + } } *res = ptr; diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index b8674fc51f..84cecbc909 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -76,7 +76,7 @@ struct nic_rule_tag { nic_rule_action action; nic_rule_match match_type; char * if_name; - isc_netaddr_t netaddr; + sockaddr_u addr; int prefixlen; }; @@ -186,8 +186,7 @@ static void remove_interface(struct interface *); static struct interface *create_interface(u_short, struct interface *); static int move_fd (SOCKET); -static int is_wildcard_addr (sockaddr_u *); -static int is_wildcard_netaddr (const isc_netaddr_t *); +static int is_wildcard_addr (const sockaddr_u *); /* * Multicast functions @@ -250,7 +249,9 @@ static void remove_asyncio_reader (struct asyncio_reader *); static void init_async_notifications (void); -static int create_sockets (u_short); +static int addr_eqprefix (const sockaddr_u *, const sockaddr_u *, + int); +static int create_sockets (u_short); static SOCKET open_socket (sockaddr_u *, int, int, struct interface *); static char * fdbits (int, fd_set *); static void set_reuseaddr (int); @@ -285,8 +286,7 @@ static void create_wildcards (u_short); #ifdef DEBUG static const char * action_text (nic_rule_action); #endif -static nic_rule_action interface_action(char *, isc_netaddr_t *, - isc_uint32_t); +static nic_rule_action interface_action(char *, sockaddr_u *, u_int32); static void convert_isc_if (isc_interface_t *, struct interface *, u_short); static void calc_addr_distance(sockaddr_u *, @@ -706,16 +706,44 @@ remove_asyncio_reader( } #endif /* !defined(HAVE_IO_COMPLETION_PORT) && defined(HAS_ROUTING_SOCKET) */ + +/* compare two sockaddr prefixes */ +static int +addr_eqprefix( + const sockaddr_u * a, + const sockaddr_u * b, + int prefixlen + ) +{ + isc_netaddr_t isc_a; + isc_netaddr_t isc_b; + isc_sockaddr_t isc_sa; + + memset(&isc_sa, 0, sizeof(isc_sa)); + memcpy(&isc_sa.type.sa, &a->sa, + min(sizeof(isc_sa.type), sizeof(a))); + isc_netaddr_fromsockaddr(&isc_a, &isc_sa); + + memset(&isc_sa, 0, sizeof(isc_sa)); + memcpy(&isc_sa.type.sa, &b->sa, + min(sizeof(isc_sa.type), sizeof(b))); + isc_netaddr_fromsockaddr(&isc_b, &isc_sa); + + return (int)isc_netaddr_eqprefix(&isc_a, &isc_b, + (u_int)prefixlen); +} + + /* * Code to tell if we have an IP address * If we have then return the sockaddr structure * and set the return value * see the bind9/getaddresses.c for details */ -isc_boolean_t +int is_ip_address( const char * host, - isc_netaddr_t * addr + sockaddr_u * addr ) { struct in_addr in4; @@ -726,6 +754,8 @@ is_ip_address( NTP_REQUIRE(host != NULL); NTP_REQUIRE(addr != NULL); + memset(addr, 0, sizeof(*addr)); + /* * Try IPv4, then IPv6. In order to handle the extended format * for IPv6 scoped addresses (address%scope_ID), we'll use a local @@ -736,8 +766,10 @@ is_ip_address( * terminating NULL character. */ if (inet_pton(AF_INET, host, &in4) == 1) { - isc_netaddr_fromin(addr, &in4); - return (ISC_TRUE); + AF(addr) = AF_INET; + SET_ADDR4N(addr, in4.s_addr); + + return TRUE; } else if (sizeof(tmpbuf) > strlen(host)) { if ('[' == host[0]) { strncpy(tmpbuf, &host[1], sizeof(tmpbuf)); @@ -751,14 +783,16 @@ is_ip_address( *pch = '\0'; if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) { - isc_netaddr_fromin6(addr, &in6); - return (ISC_TRUE); + AF(addr) = AF_INET6; + SET_ADDR6N(addr, in6); + + return TRUE; } } /* * If we got here it was not an IP address */ - return (ISC_FALSE); + return FALSE; } @@ -930,7 +964,6 @@ create_wildcards( { int v4wild, v6wild; sockaddr_u wildaddr; - isc_netaddr_t wnaddr; nic_rule_action action; struct interface * wildif; @@ -953,11 +986,8 @@ create_wildcards( SET_ADDR4(&wildaddr, INADDR_ANY); SET_PORT(&wildaddr, port); - /* make an libisc-friendly copy */ - isc_netaddr_fromin(&wnaddr, &wildaddr.sa4.sin_addr); - /* check for interface/nic rules affecting the wildcard */ - action = interface_action(NULL, &wnaddr, 0); + action = interface_action(NULL, &wildaddr, 0); v4wild = (ACTION_IGNORE != action); } if (v4wild) { @@ -1010,11 +1040,8 @@ create_wildcards( SET_PORT(&wildaddr, port); SET_SCOPE(&wildaddr, 0); - /* make an libisc-friendly copy */ - isc_netaddr_fromin(&wnaddr, &wildaddr.sa4.sin_addr); - /* check for interface/nic rules affecting the wildcard */ - action = interface_action(NULL, &wnaddr, 0); + action = interface_action(NULL, &wildaddr, 0); v6wild = (ACTION_IGNORE != action); } if (v6wild) { @@ -1074,8 +1101,8 @@ add_nic_rule( rule->if_name = estrdup(if_name); } else if (MATCH_IFADDR == match_type) { NTP_REQUIRE(NULL != if_name); - /* set rule->netaddr */ - is_ip = is_ip_address(if_name, &rule->netaddr); + /* set rule->addr */ + is_ip = is_ip_address(if_name, &rule->addr); NTP_REQUIRE(is_ip); } else NTP_REQUIRE(NULL == if_name); @@ -1122,30 +1149,31 @@ action_text( static nic_rule_action interface_action( char * if_name, - isc_netaddr_t * if_netaddr, - isc_uint32_t if_flags + sockaddr_u * if_addr, + u_int32 if_flags ) { - nic_rule *rule; - int isloopback; - int iswildcard; + nic_rule * rule; + int isloopback; + int iswildcard; DPRINTF(4, ("interface_action: interface %s ", (if_name != NULL) ? if_name : "wildcard")); - iswildcard = is_wildcard_netaddr(if_netaddr); + iswildcard = is_wildcard_addr(if_addr); /* * Always listen on 127.0.0.1 - required by ntp_intres */ - if (if_flags & INTERFACE_F_LOOPBACK) { - isloopback = 1; - if (AF_INET == if_netaddr->family) { + if (INT_LOOPBACK & if_flags) { + isloopback = TRUE; + if (IS_IPV4(if_addr)) { DPRINTF(4, ("IPv4 loopback - listen\n")); return ACTION_LISTEN; } - } else - isloopback = 0; + } else { + isloopback = FALSE; + } /* * Find any matching NIC rule from --interface / -I or ntp.conf @@ -1164,7 +1192,7 @@ interface_action( return rule->action; case MATCH_IPV4: - if (AF_INET == if_netaddr->family) { + if (IS_IPV4(if_addr)) { DPRINTF(4, ("nic ipv4 %s\n", action_text(rule->action))); return rule->action; @@ -1172,7 +1200,7 @@ interface_action( break; case MATCH_IPV6: - if (AF_INET6 == if_netaddr->family) { + if (IS_IPV6(if_addr)) { DPRINTF(4, ("nic ipv6 %s\n", action_text(rule->action))); return rule->action; @@ -1189,16 +1217,15 @@ interface_action( case MATCH_IFADDR: if (rule->prefixlen != -1) { - if (isc_netaddr_eqprefix(if_netaddr, - &rule->netaddr, rule->prefixlen)) { + if (addr_eqprefix(if_addr, &rule->addr, + rule->prefixlen)) { DPRINTF(4, ("subnet address match - %s\n", action_text(rule->action))); return rule->action; } } else - if (isc_netaddr_equal(if_netaddr, - &rule->netaddr)) { + if (SOCK_EQ(if_addr, &rule->addr)) { DPRINTF(4, ("address match - %s\n", action_text(rule->action))); @@ -1326,7 +1353,7 @@ convert_isc_if( /* * Clear the loopback flag if the address is not localhost. - * http://bugs.ntp.org/1691 + * http://bugs.ntp.org/1683 */ if (INT_LOOPBACK & itf->flags) { if (AF_INET == itf->family) { @@ -1436,7 +1463,7 @@ sau_from_netaddr( static int is_wildcard_addr( - sockaddr_u *psau + const sockaddr_u *psau ) { if (IS_IPV4(psau) && !NSRCADR(psau)) @@ -1451,19 +1478,6 @@ is_wildcard_addr( } -static int -is_wildcard_netaddr( - const isc_netaddr_t *pna - ) -{ - sockaddr_u sau; - - sau_from_netaddr(&sau, pna); - - return is_wildcard_addr(&sau); -} - - #ifdef OS_NEEDS_REUSEADDR_FOR_IFADDRBIND /* * enable/disable re-use of wildcard address socket @@ -1618,8 +1632,8 @@ update_interfaces( /* * Check if and how we are going to use the interface. */ - switch (interface_action(isc_if.name, &isc_if.address, - isc_if.flags)) { + switch (interface_action(interface.name, &interface.sin, + interface.flags)) { case ACTION_IGNORE: continue; diff --git a/ntpd/ntpd.c b/ntpd/ntpd.c index 62e4f98052..e6135615be 100644 --- a/ntpd/ntpd.c +++ b/ntpd/ntpd.c @@ -556,13 +556,13 @@ ntpdmain( * --interface, listen on specified interfaces */ if (HAVE_OPT( INTERFACE )) { - int ifacect = STACKCT_OPT( INTERFACE ); + int ifacect = STACKCT_OPT( INTERFACE ); const char** ifaces = STACKLST_OPT( INTERFACE ); - isc_netaddr_t netaddr; + sockaddr_u addr; while (ifacect-- > 0) { add_nic_rule( - is_ip_address(*ifaces, &netaddr) + is_ip_address(*ifaces, &addr) ? MATCH_IFADDR : MATCH_IFNAME, *ifaces, -1, ACTION_LISTEN);