docs: Add manpage for vfs_shadow_copy2.
[metze/samba/wip.git] / source3 / lib / interface.c
index 1471a06f46cf0c5db3f01ee2163dfa34f7223fcc..48fa4d32a93a1e01669f17c623e592fa602287da 100644 (file)
@@ -29,11 +29,11 @@ static struct interface *local_interfaces;
  Check if an IP is one of mine.
 **************************************************************************/
 
-bool ismyaddr(const struct sockaddr_storage *ip)
+bool ismyaddr(const struct sockaddr *ip)
 {
        struct interface *i;
        for (i=local_interfaces;i;i=i->next) {
-               if (addr_equal(&i->ip,ip)) {
+               if (sockaddr_equal((struct sockaddr *)&i->ip,ip)) {
                        return true;
                }
        }
@@ -44,14 +44,14 @@ bool ismyip_v4(struct in_addr ip)
 {
        struct sockaddr_storage ss;
        in_addr_to_sockaddr_storage(&ss, ip);
-       return ismyaddr(&ss);
+       return ismyaddr((struct sockaddr *)&ss);
 }
 
 /****************************************************************************
  Try and find an interface that matches an ip. If we cannot, return NULL.
 **************************************************************************/
 
-static struct interface *iface_find(const struct sockaddr_storage *ip,
+static struct interface *iface_find(const struct sockaddr *ip,
                                bool check_mask)
 {
        struct interface *i;
@@ -62,10 +62,10 @@ static struct interface *iface_find(const struct sockaddr_storage *ip,
 
        for (i=local_interfaces;i;i=i->next) {
                if (check_mask) {
-                       if (same_net(ip, &i->ip, &i->netmask)) {
+                       if (same_net(ip, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
                                return i;
                        }
-               } else if (addr_equal(&i->ip, ip)) {
+               } else if (sockaddr_equal((struct sockaddr *)&i->ip, ip)) {
                        return i;
                }
        }
@@ -77,17 +77,32 @@ static struct interface *iface_find(const struct sockaddr_storage *ip,
  Check if a packet is from a local (known) net.
 **************************************************************************/
 
-bool is_local_net(const struct sockaddr_storage *from)
+bool is_local_net(const struct sockaddr *from)
 {
        struct interface *i;
        for (i=local_interfaces;i;i=i->next) {
-               if (same_net(from, &i->ip, &i->netmask)) {
+               if (same_net(from, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) {
                        return true;
                }
        }
        return false;
 }
 
+#if defined(HAVE_IPV6)
+void setup_linklocal_scope_id(struct sockaddr *pss)
+{
+       struct interface *i;
+       for (i=local_interfaces;i;i=i->next) {
+               if (sockaddr_equal((struct sockaddr *)&i->ip,pss)) {
+                       struct sockaddr_in6 *psa6 =
+                               (struct sockaddr_in6 *)pss;
+                       psa6->sin6_scope_id = if_nametoindex(i->name);
+                       return;
+               }
+       }
+}
+#endif
+
 /****************************************************************************
  Check if a packet is from a local (known) net.
 **************************************************************************/
@@ -97,7 +112,7 @@ bool is_local_net_v4(struct in_addr from)
        struct sockaddr_storage ss;
 
        in_addr_to_sockaddr_storage(&ss, from);
-       return is_local_net(&ss);
+       return is_local_net((struct sockaddr *)&ss);
 }
 
 /****************************************************************************
@@ -116,15 +131,18 @@ int iface_count(void)
 }
 
 /****************************************************************************
- How many interfaces do we have (v4 only) ?
+ How many non-loopback IPv4 interfaces do we have ?
 **************************************************************************/
 
-int iface_count_v4(void)
+int iface_count_v4_nl(void)
 {
        int ret = 0;
        struct interface *i;
 
        for (i=local_interfaces;i;i=i->next) {
+               if (is_loopback_addr((struct sockaddr *)&i->ip)) {
+                       continue;
+               }
                if (i->ip.ss_family == AF_INET) {
                        ret++;
                }
@@ -247,7 +265,7 @@ const struct sockaddr_storage *iface_n_bcast(int n)
    an appropriate interface they return the requested field of the
    first known interface. */
 
-const struct sockaddr_storage *iface_ip(const struct sockaddr_storage *ip)
+const struct sockaddr_storage *iface_ip(const struct sockaddr *ip)
 {
        struct interface *i = iface_find(ip, true);
        if (i) {
@@ -258,7 +276,7 @@ const struct sockaddr_storage *iface_ip(const struct sockaddr_storage *ip)
         * matching address family. */
 
        for (i=local_interfaces;i;i=i->next) {
-               if (i->ip.ss_family == ip->ss_family) {
+               if (i->ip.ss_family == ip->sa_family) {
                        return &i->ip;
                }
        }
@@ -269,9 +287,9 @@ const struct sockaddr_storage *iface_ip(const struct sockaddr_storage *ip)
   return True if a IP is directly reachable on one of our interfaces
 */
 
-bool iface_local(struct sockaddr_storage *ip)
+bool iface_local(const struct sockaddr *ip)
 {
-       return iface_find(ip, True) ? true : false;
+       return iface_find(ip, true) ? true : false;
 }
 
 /****************************************************************************
@@ -283,14 +301,13 @@ static void add_interface(const struct iface_struct *ifs)
        char addr[INET6_ADDRSTRLEN];
        struct interface *iface;
 
-       if (iface_find(&ifs->ip, False)) {
+       if (iface_find((struct sockaddr *)&ifs->ip, False)) {
                DEBUG(3,("add_interface: not adding duplicate interface %s\n",
-                       print_sockaddr(addr, sizeof(addr),
-                               &ifs->ip, sizeof(struct sockaddr_storage)) ));
+                       print_sockaddr(addr, sizeof(addr), &ifs->ip) ));
                return;
        }
 
-       if (!(ifs->flags & IFF_BROADCAST)) {
+       if (!(ifs->flags & (IFF_BROADCAST|IFF_LOOPBACK))) {
                DEBUG(3,("not adding non-broadcast interface %s\n",
                                        ifs->name ));
                return;
@@ -317,110 +334,13 @@ static void add_interface(const struct iface_struct *ifs)
 
        DEBUG(2,("added interface %s ip=%s ",
                iface->name,
-               print_sockaddr(addr, sizeof(addr),
-                       &iface->ip, sizeof(struct sockaddr_storage)) ));
+               print_sockaddr(addr, sizeof(addr), &iface->ip) ));
        DEBUG(2,("bcast=%s ",
                print_sockaddr(addr, sizeof(addr),
-                       &iface->bcast,
-                       sizeof(struct sockaddr_storage)) ));
+                       &iface->bcast) ));
        DEBUG(2,("netmask=%s\n",
                print_sockaddr(addr, sizeof(addr),
-                       &iface->netmask,
-                       sizeof(struct sockaddr_storage)) ));
-}
-
-/****************************************************************************
- Create a struct sockaddr_storage with the netmask bits set to 1.
-****************************************************************************/
-
-static bool make_netmask(struct sockaddr_storage *pss_out,
-                       const struct sockaddr_storage *pss_in,
-                       unsigned long masklen)
-{
-       *pss_out = *pss_in;
-       /* Now apply masklen bits of mask. */
-#if defined(AF_INET6)
-       if (pss_in->ss_family == AF_INET6) {
-               char *p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr;
-               unsigned int i;
-
-               if (masklen > 128) {
-                       return false;
-               }
-               for (i = 0; masklen >= 8; masklen -= 8, i++) {
-                       *p++ = 0xff;
-               }
-               /* Deal with the partial byte. */
-               *p++ &= (0xff & ~(0xff>>masklen));
-               i++;
-               for (;i < sizeof(struct in6_addr); i++) {
-                       *p++ = '\0';
-               }
-               return true;
-       }
-#endif
-       if (pss_in->ss_family == AF_INET) {
-               if (masklen > 32) {
-                       return false;
-               }
-               ((struct sockaddr_in *)pss_out)->sin_addr.s_addr =
-                       htonl(((0xFFFFFFFFL >> masklen) ^ 0xFFFFFFFFL));
-               return true;
-       }
-       return false;
-}
-
-/****************************************************************************
- Create a struct sockaddr_storage set to the broadcast or network adress from
- an incoming sockaddr_storage.
-****************************************************************************/
-
-static void make_bcast_or_net(struct sockaddr_storage *pss_out,
-                       const struct sockaddr_storage *pss_in,
-                       const struct sockaddr_storage *nmask,
-                       bool make_bcast)
-{
-       unsigned int i = 0, len = 0;
-       char *pmask = NULL;
-       char *p = NULL;
-       *pss_out = *pss_in;
-
-       /* Set all zero netmask bits to 1. */
-#if defined(AF_INET6)
-       if (pss_in->ss_family == AF_INET6) {
-               p = (char *)&((struct sockaddr_in6 *)pss_out)->sin6_addr;
-               pmask = (char *)&((struct sockaddr_in6 *)nmask)->sin6_addr;
-               len = 16;
-       }
-#endif
-       if (pss_in->ss_family == AF_INET) {
-               p = (char *)&((struct sockaddr_in *)pss_out)->sin_addr;
-               pmask = (char *)&((struct sockaddr_in *)nmask)->sin_addr;
-               len = 4;
-       }
-
-       for (i = 0; i < len; i++, p++, pmask++) {
-               if (make_bcast) {
-                       *p = (*p & *pmask) | (*pmask ^ 0xff);
-               } else {
-                       /* make_net */
-                       *p = (*p & *pmask);
-               }
-       }
-}
-
-static void make_bcast(struct sockaddr_storage *pss_out,
-                       const struct sockaddr_storage *pss_in,
-                       const struct sockaddr_storage *nmask)
-{
-       make_bcast_or_net(pss_out, pss_in, nmask, true);
-}
-
-static void make_net(struct sockaddr_storage *pss_out,
-                       const struct sockaddr_storage *pss_in,
-                       const struct sockaddr_storage *nmask)
-{
-       make_bcast_or_net(pss_out, pss_in, nmask, false);
+                       &iface->netmask) ));
 }
 
 /****************************************************************************
@@ -460,9 +380,15 @@ static void interpret_interface(char *token)
 
        /* maybe it is a DNS name */
        p = strchr_m(token,'/');
-       if (!p && interpret_string_addr(&ss, token)) {
+       if (p == NULL) {
+               if (!interpret_string_addr(&ss, token, 0)) {
+                       DEBUG(2, ("interpret_interface: Can't find address "
+                                 "for %s\n", token));
+                       return;
+               }
+
                for (i=0;i<total_probed;i++) {
-                       if (addr_equal(&ss, &probed_ifaces[i].ip)) {
+                       if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&probed_ifaces[i].ip)) {
                                add_interface(&probed_ifaces[i]);
                                return;
                        }
@@ -475,7 +401,7 @@ static void interpret_interface(char *token)
 
        /* parse it into an IP address/netmasklength pair */
        *p = 0;
-       goodaddr = interpret_string_addr(&ss, token);
+       goodaddr = interpret_string_addr(&ss, token, 0);
        *p++ = '/';
 
        if (!goodaddr) {
@@ -486,7 +412,7 @@ static void interpret_interface(char *token)
        }
 
        if (strlen(p) > 2) {
-               goodaddr = interpret_string_addr(&ss_mask, p);
+               goodaddr = interpret_string_addr(&ss_mask, p, 0);
                if (!goodaddr) {
                        DEBUG(2,("interpret_interface: "
                                "can't determine netmask from %s\n",
@@ -515,9 +441,12 @@ static void interpret_interface(char *token)
        make_net(&ss_net, &ss, &ss_mask);
 
        /* Maybe the first component was a broadcast address. */
-       if (addr_equal(&ss_bcast, &ss) || addr_equal(&ss_net, &ss)) {
+       if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) ||
+               sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) {
                for (i=0;i<total_probed;i++) {
-                       if (same_net(&ss, &probed_ifaces[i].ip, &ss_mask)) {
+                       if (same_net((struct sockaddr *)&ss, 
+                                                (struct sockaddr *)&probed_ifaces[i].ip, 
+                                                (struct sockaddr *)&ss_mask)) {
                                /* Temporarily replace netmask on
                                 * the detected interface - user knows
                                 * best.... */
@@ -546,7 +475,7 @@ static void interpret_interface(char *token)
                token));
 
        ZERO_STRUCT(ifs);
-       safe_strcpy(ifs.name, token, sizeof(ifs.name)-1);
+       (void)strlcpy(ifs.name, token, sizeof(ifs.name));
        ifs.flags = IFF_BROADCAST;
        ifs.ip = ss;
        ifs.netmask = ss_mask;