root/source4/lib/socket/interface.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iface_find
  2. add_interface
  3. interpret_interface
  4. load_interfaces
  5. iface_count
  6. iface_n_ip
  7. iface_n_bcast
  8. iface_n_netmask
  9. iface_best_ip
  10. iface_is_local
  11. iface_same_net

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    multiple interface handling
   5 
   6    Copyright (C) Andrew Tridgell 1992-2005
   7    
   8    This program is free software; you can redistribute it and/or modify
   9    it under the terms of the GNU General Public License as published by
  10    the Free Software Foundation; either version 3 of the License, or
  11    (at your option) any later version.
  12    
  13    This program is distributed in the hope that it will be useful,
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16    GNU General Public License for more details.
  17    
  18    You should have received a copy of the GNU General Public License
  19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  20 */
  21 
  22 #include "includes.h"
  23 #include "system/network.h"
  24 #include "lib/socket/netif.h"
  25 #include "../lib/util/dlinklist.h"
  26 
  27 /** used for network interfaces */
  28 struct interface {
  29         struct interface *next, *prev;
  30         struct in_addr ip;
  31         struct in_addr nmask;
  32         const char *ip_s;
  33         const char *bcast_s;
  34         const char *nmask_s;
  35 };
  36 
  37 #define ALLONES  ((uint32_t)0xFFFFFFFF)
  38 /*
  39   address construction based on a patch from fred@datalync.com
  40 */
  41 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
  42 #define MKNETADDR(_IP, _NM) (_IP & _NM)
  43 
  44 /****************************************************************************
  45 Try and find an interface that matches an ip. If we cannot, return NULL
  46   **************************************************************************/
  47 static struct interface *iface_find(struct interface *interfaces, 
     /* [<][>][^][v][top][bottom][index][help] */
  48                                     struct in_addr ip, bool CheckMask)
  49 {
  50         struct interface *i;
  51         if (is_zero_ip_v4(ip)) return interfaces;
  52 
  53         for (i=interfaces;i;i=i->next)
  54                 if (CheckMask) {
  55                         if (same_net_v4(i->ip,ip,i->nmask)) return i;
  56                 } else if (i->ip.s_addr == ip.s_addr) return i;
  57 
  58         return NULL;
  59 }
  60 
  61 
  62 /****************************************************************************
  63 add an interface to the linked list of interfaces
  64 ****************************************************************************/
  65 static void add_interface(TALLOC_CTX *mem_ctx, struct in_addr ip, struct in_addr nmask, struct interface **interfaces)
     /* [<][>][^][v][top][bottom][index][help] */
  66 {
  67         struct interface *iface;
  68         struct in_addr bcast;
  69 
  70         if (iface_find(*interfaces, ip, false)) {
  71                 DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip)));
  72                 return;
  73         }
  74 
  75         iface = talloc(*interfaces == NULL ? mem_ctx : *interfaces, struct interface);
  76         if (iface == NULL) 
  77                 return;
  78         
  79         ZERO_STRUCTPN(iface);
  80 
  81         iface->ip = ip;
  82         iface->nmask = nmask;
  83         bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
  84 
  85         /* keep string versions too, to avoid people tripping over the implied
  86            static in inet_ntoa() */
  87         iface->ip_s = talloc_strdup(iface, inet_ntoa(iface->ip));
  88         iface->nmask_s = talloc_strdup(iface, inet_ntoa(iface->nmask));
  89         
  90         if (nmask.s_addr != ~0) {
  91                 iface->bcast_s = talloc_strdup(iface, inet_ntoa(bcast));
  92         }
  93 
  94         DLIST_ADD_END(*interfaces, iface, struct interface *);
  95 
  96         DEBUG(2,("added interface ip=%s nmask=%s\n", iface->ip_s, iface->nmask_s));
  97 }
  98 
  99 
 100 
 101 /**
 102 interpret a single element from a interfaces= config line 
 103 
 104 This handles the following different forms:
 105 
 106 1) wildcard interface name
 107 2) DNS name
 108 3) IP/masklen
 109 4) ip/mask
 110 5) bcast/mask
 111 **/
 112 static void interpret_interface(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 113                                 const char *token, 
 114                                 struct iface_struct *probed_ifaces, 
 115                                 int total_probed,
 116                                 struct interface **local_interfaces)
 117 {
 118         struct in_addr ip, nmask;
 119         char *p;
 120         char *address;
 121         int i, added=0;
 122 
 123         ip.s_addr = 0;
 124         nmask.s_addr = 0;
 125         
 126         /* first check if it is an interface name */
 127         for (i=0;i<total_probed;i++) {
 128                 if (gen_fnmatch(token, probed_ifaces[i].name) == 0) {
 129                         add_interface(mem_ctx, probed_ifaces[i].ip,
 130                                       probed_ifaces[i].netmask,
 131                                       local_interfaces);
 132                         added = 1;
 133                 }
 134         }
 135         if (added) return;
 136 
 137         /* maybe it is a DNS name */
 138         p = strchr_m(token,'/');
 139         if (!p) {
 140                 /* don't try to do dns lookups on wildcard names */
 141                 if (strpbrk(token, "*?") != NULL) {
 142                         return;
 143                 }
 144                 ip.s_addr = interpret_addr2(token).s_addr;
 145                 for (i=0;i<total_probed;i++) {
 146                         if (ip.s_addr == probed_ifaces[i].ip.s_addr) {
 147                                 add_interface(mem_ctx, probed_ifaces[i].ip,
 148                                               probed_ifaces[i].netmask,
 149                                               local_interfaces);
 150                                 return;
 151                         }
 152                 }
 153                 DEBUG(2,("can't determine netmask for %s\n", token));
 154                 return;
 155         }
 156 
 157         address = talloc_strdup(mem_ctx, token);
 158         p = strchr_m(address,'/');
 159 
 160         /* parse it into an IP address/netmasklength pair */
 161         *p++ = 0;
 162 
 163         ip.s_addr = interpret_addr2(address).s_addr;
 164 
 165         if (strlen(p) > 2) {
 166                 nmask.s_addr = interpret_addr2(p).s_addr;
 167         } else {
 168                 nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
 169         }
 170 
 171         /* maybe the first component was a broadcast address */
 172         if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) ||
 173             ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) {
 174                 for (i=0;i<total_probed;i++) {
 175                         if (same_net_v4(ip, probed_ifaces[i].ip, nmask)) {
 176                                 add_interface(mem_ctx, probed_ifaces[i].ip, nmask,
 177                                               local_interfaces);
 178                                 talloc_free(address);
 179                                 return;
 180                         }
 181                 }
 182                 DEBUG(2,("Can't determine ip for broadcast address %s\n", address));
 183                 talloc_free(address);
 184                 return;
 185         }
 186 
 187         add_interface(mem_ctx, ip, nmask, local_interfaces);
 188         talloc_free(address);
 189 }
 190 
 191 
 192 /**
 193 load the list of network interfaces
 194 **/
 195 void load_interfaces(TALLOC_CTX *mem_ctx, const char **interfaces, struct interface **local_interfaces)
     /* [<][>][^][v][top][bottom][index][help] */
 196 {
 197         const char **ptr = interfaces;
 198         int i;
 199         struct iface_struct ifaces[MAX_INTERFACES];
 200         struct in_addr loopback_ip;
 201         int total_probed;
 202 
 203         *local_interfaces = NULL;
 204 
 205         loopback_ip = interpret_addr2("127.0.0.1");
 206 
 207         /* probe the kernel for interfaces */
 208         total_probed = get_interfaces(ifaces, MAX_INTERFACES);
 209 
 210         /* if we don't have a interfaces line then use all interfaces
 211            except loopback */
 212         if (!ptr || !*ptr || !**ptr) {
 213                 if (total_probed <= 0) {
 214                         DEBUG(0,("ERROR: Could not determine network interfaces, you must use a interfaces config line\n"));
 215                 }
 216                 for (i=0;i<total_probed;i++) {
 217                         if (ifaces[i].ip.s_addr != loopback_ip.s_addr) {
 218                                 add_interface(mem_ctx, ifaces[i].ip, 
 219                                               ifaces[i].netmask, local_interfaces);
 220                         }
 221                 }
 222         }
 223 
 224         while (ptr && *ptr) {
 225                 interpret_interface(mem_ctx, *ptr, ifaces, total_probed, local_interfaces);
 226                 ptr++;
 227         }
 228 
 229         if (!*local_interfaces) {
 230                 DEBUG(0,("WARNING: no network interfaces found\n"));
 231         }
 232 }
 233 
 234 /**
 235   how many interfaces do we have
 236   **/
 237 int iface_count(struct interface *ifaces)
     /* [<][>][^][v][top][bottom][index][help] */
 238 {
 239         int ret = 0;
 240         struct interface *i;
 241 
 242         for (i=ifaces;i;i=i->next)
 243                 ret++;
 244         return ret;
 245 }
 246 
 247 /**
 248   return IP of the Nth interface
 249   **/
 250 const char *iface_n_ip(struct interface *ifaces, int n)
     /* [<][>][^][v][top][bottom][index][help] */
 251 {
 252         struct interface *i;
 253   
 254         for (i=ifaces;i && n;i=i->next)
 255                 n--;
 256 
 257         if (i) {
 258                 return i->ip_s;
 259         }
 260         return NULL;
 261 }
 262 
 263 /**
 264   return bcast of the Nth interface
 265   **/
 266 const char *iface_n_bcast(struct interface *ifaces, int n)
     /* [<][>][^][v][top][bottom][index][help] */
 267 {
 268         struct interface *i;
 269   
 270         for (i=ifaces;i && n;i=i->next)
 271                 n--;
 272 
 273         if (i) {
 274                 return i->bcast_s;
 275         }
 276         return NULL;
 277 }
 278 
 279 /**
 280   return netmask of the Nth interface
 281   **/
 282 const char *iface_n_netmask(struct interface *ifaces, int n)
     /* [<][>][^][v][top][bottom][index][help] */
 283 {
 284         struct interface *i;
 285   
 286         for (i=ifaces;i && n;i=i->next)
 287                 n--;
 288 
 289         if (i) {
 290                 return i->nmask_s;
 291         }
 292         return NULL;
 293 }
 294 
 295 /**
 296   return the local IP address that best matches a destination IP, or
 297   our first interface if none match
 298 */
 299 const char *iface_best_ip(struct interface *ifaces, const char *dest)
     /* [<][>][^][v][top][bottom][index][help] */
 300 {
 301         struct interface *iface;
 302         struct in_addr ip;
 303 
 304         ip.s_addr = interpret_addr(dest);
 305         iface = iface_find(ifaces, ip, true);
 306         if (iface) {
 307                 return iface->ip_s;
 308         }
 309         return iface_n_ip(ifaces, 0);
 310 }
 311 
 312 /**
 313   return true if an IP is one one of our local networks
 314 */
 315 bool iface_is_local(struct interface *ifaces, const char *dest)
     /* [<][>][^][v][top][bottom][index][help] */
 316 {
 317         struct in_addr ip;
 318 
 319         ip.s_addr = interpret_addr(dest);
 320         if (iface_find(ifaces, ip, true)) {
 321                 return true;
 322         }
 323         return false;
 324 }
 325 
 326 /**
 327   return true if a IP matches a IP/netmask pair
 328 */
 329 bool iface_same_net(const char *ip1, const char *ip2, const char *netmask)
     /* [<][>][^][v][top][bottom][index][help] */
 330 {
 331         return same_net_v4(interpret_addr2(ip1),
 332                         interpret_addr2(ip2),
 333                         interpret_addr2(netmask));
 334 }

/* [<][>][^][v][top][bottom][index][help] */