root/src/vfs/smbfs/helpers/lib/interface.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. default_netmask
  2. get_broadcast
  3. interpret_interfaces
  4. load_interfaces
  5. iface_set_default
  6. ismyip
  7. is_local_net
  8. iface_count
  9. we_are_multihomed
  10. get_interface
  11. iface_n_ip
  12. iface_find
  13. iface_hash
  14. iface_bcast
  15. iface_ip

   1 /*
   2    Unix SMB/Netbios implementation.
   3    Version 1.9.
   4    multiple interface handling
   5 
   6    Copyright (C) Andrew Tridgell 1992-1998
   7 
   8    Copyright (C) 2011-2019
   9    Free Software Foundation, Inc.
  10 
  11    This file is part of the Midnight Commander.
  12 
  13    The Midnight Commander is free software: you can redistribute it
  14    and/or modify it under the terms of the GNU General Public License as
  15    published by the Free Software Foundation, either version 3 of the License,
  16    or (at your option) any later version.
  17 
  18    The Midnight Commander is distributed in the hope that it will be useful,
  19    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21    GNU General Public License for more details.
  22 
  23    You should have received a copy of the GNU General Public License
  24    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  25  */
  26 
  27 #include "includes.h"
  28 
  29 extern int DEBUGLEVEL;
  30 
  31 struct in_addr ipzero;
  32 struct in_addr allones_ip;
  33 struct in_addr loopback_ip;
  34 static struct in_addr default_ip;
  35 static struct in_addr default_bcast;
  36 static struct in_addr default_nmask;
  37 static BOOL got_ip = False;
  38 static BOOL got_bcast = False;
  39 static BOOL got_nmask = False;
  40 
  41 static struct interface *local_interfaces = NULL;
  42 
  43 struct interface *last_iface;
  44 
  45 #define ALLONES  ((uint32)0xFFFFFFFF)
  46 #define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
  47 /****************************************************************************
  48 calculate the default netmask for an address
  49 ****************************************************************************/
  50 static void
  51 default_netmask (struct in_addr *inm, struct in_addr *iad)
     /* [previous][next][first][last][top][bottom][index][help]  */
  52 {
  53     /*
  54      ** Guess a netmask based on the class of the IP address given.
  55      */
  56     switch ((ntohl (iad->s_addr) & 0xE0000000))
  57     {
  58     case 0x00000000:           /* Class A addr */
  59     case 0x20000000:
  60     case 0x40000000:
  61     case 0x60000000:
  62         inm->s_addr = htonl (0xFF000000);
  63         break;
  64 
  65     case 0x80000000:           /* Class B addr */
  66     case 0xA0000000:
  67         inm->s_addr = htonl (0xFFFF0000);
  68         break;
  69 
  70     case 0xC0000000:           /* Class C addr */
  71         inm->s_addr = htonl (0xFFFFFF00);
  72         break;
  73 
  74     default:                   /* ??? */
  75         inm->s_addr = htonl (0xFFFFFFF0);
  76     }
  77 }
  78 
  79 
  80 /****************************************************************************
  81   get the broadcast address for our address 
  82 (troyer@saifr00.ateng.az.honeywell.com)
  83 ****************************************************************************/
  84 static void
  85 get_broadcast (struct in_addr *if_ipaddr, struct in_addr *if_bcast, struct in_addr *if_nmask)
     /* [previous][next][first][last][top][bottom][index][help]  */
  86 {
  87     uint32 nm;
  88     short onbc;
  89     short offbc;
  90 
  91     /* get a default netmask and broadcast */
  92     default_netmask (if_nmask, if_ipaddr);
  93 
  94     get_netmask (if_ipaddr, if_nmask);
  95 
  96     /* sanity check on the netmask */
  97     nm = ntohl (if_nmask->s_addr);
  98     onbc = 0;
  99     offbc = 0;
 100     while ((onbc + offbc) < 32)
 101     {
 102         if (nm & 0x80000000)
 103         {
 104             onbc++;
 105             if (offbc)
 106             {
 107                 /* already found an off bit, so mask
 108                    is wrong */
 109                 onbc = 34;
 110             }
 111         }
 112         else
 113         {
 114             offbc++;
 115         }
 116         nm <<= 1;
 117     }
 118     if ((onbc < 8) || (onbc == 34))
 119     {
 120         DEBUG (0, ("Impossible netmask %s - using defaults\n", inet_ntoa (*if_nmask)));
 121         default_netmask (if_nmask, if_ipaddr);
 122     }
 123 
 124     /* derive the broadcast assuming a 1's broadcast, as this is what
 125        all MS operating systems do, we have to comply even if the unix
 126        box is setup differently */
 127     if_bcast->s_addr = MKBCADDR (if_ipaddr->s_addr, if_nmask->s_addr);
 128 
 129     DEBUG (4, ("Derived broadcast address %s\n", inet_ntoa (*if_bcast)));
 130 }
 131 
 132 
 133 
 134 /****************************************************************************
 135 load a list of network interfaces
 136 ****************************************************************************/
 137 static void
 138 interpret_interfaces (char *s, struct interface **interfaces, const char *description)
     /* [previous][next][first][last][top][bottom][index][help]  */
 139 {
 140     char *ptr;
 141     fstring token;
 142     struct interface *iface;
 143     struct in_addr ip;
 144 
 145     ptr = s;
 146     ipzero = *interpret_addr2 ("0.0.0.0");
 147     allones_ip = *interpret_addr2 ("255.255.255.255");
 148     loopback_ip = *interpret_addr2 ("127.0.0.1");
 149 
 150     while (next_token (&ptr, token, NULL, sizeof (token)))
 151     {
 152         /* parse it into an IP address/netmasklength pair */
 153         char *p = strchr (token, '/');
 154         if (p)
 155             *p++ = 0;
 156 
 157         ip = *interpret_addr2 (token);
 158 
 159         /* maybe we already have it listed */
 160         {
 161             struct interface *i;
 162             for (i = (*interfaces); i; i = i->next)
 163                 if (ip_equal (ip, i->ip))
 164                     break;
 165             if (i)
 166                 continue;
 167         }
 168 
 169         iface = (struct interface *) malloc (sizeof (*iface));
 170         if (!iface)
 171             return;
 172 
 173         iface->ip = ip;
 174 
 175         if (p)
 176         {
 177             if (strlen (p) > 2)
 178                 iface->nmask = *interpret_addr2 (p);
 179             else
 180                 iface->nmask.s_addr = htonl (((ALLONES >> atoi (p)) ^ ALLONES));
 181         }
 182         else
 183         {
 184             default_netmask (&iface->nmask, &iface->ip);
 185         }
 186         iface->bcast.s_addr = MKBCADDR (iface->ip.s_addr, iface->nmask.s_addr);
 187         iface->next = NULL;
 188 
 189         if (!(*interfaces))
 190         {
 191             (*interfaces) = iface;
 192         }
 193         else
 194         {
 195             last_iface->next = iface;
 196         }
 197         last_iface = iface;
 198         DEBUG (2, ("Added %s ip=%s ", description, inet_ntoa (iface->ip)));
 199         DEBUG (2, ("bcast=%s ", inet_ntoa (iface->bcast)));
 200         DEBUG (2, ("nmask=%s\n", inet_ntoa (iface->nmask)));
 201     }
 202 
 203     if (*interfaces)
 204         return;
 205 
 206     /* setup a default interface */
 207     iface = (struct interface *) malloc (sizeof (*iface));
 208     if (!iface)
 209         return;
 210 
 211     iface->next = NULL;
 212 
 213     if (got_ip)
 214     {
 215         iface->ip = default_ip;
 216     }
 217     else
 218     {
 219         get_myname (NULL, &iface->ip);
 220     }
 221 
 222     if (got_bcast)
 223     {
 224         iface->bcast = default_bcast;
 225     }
 226     else
 227     {
 228         get_broadcast (&iface->ip, &iface->bcast, &iface->nmask);
 229     }
 230 
 231     if (got_nmask)
 232     {
 233         iface->nmask = default_nmask;
 234         iface->bcast.s_addr = MKBCADDR (iface->ip.s_addr, iface->nmask.s_addr);
 235     }
 236 
 237     if (iface->bcast.s_addr != MKBCADDR (iface->ip.s_addr, iface->nmask.s_addr))
 238     {
 239         DEBUG (2, ("Warning: inconsistent interface %s\n", inet_ntoa (iface->ip)));
 240     }
 241 
 242     iface->next = NULL;
 243     (*interfaces) = last_iface = iface;
 244 
 245     DEBUG (2, ("Added interface ip=%s ", inet_ntoa (iface->ip)));
 246     DEBUG (2, ("bcast=%s ", inet_ntoa (iface->bcast)));
 247     DEBUG (2, ("nmask=%s\n", inet_ntoa (iface->nmask)));
 248 }
 249 
 250 
 251 /****************************************************************************
 252 load the remote and local interfaces
 253 ****************************************************************************/
 254 void
 255 load_interfaces (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 256 {
 257     /* add the machine's interfaces to local interface structure */
 258     interpret_interfaces (lp_interfaces (), &local_interfaces, "interface");
 259 }
 260 
 261 #if 0
 262 /****************************************************************************
 263   override the defaults
 264   **************************************************************************/
 265 void
 266 iface_set_default (char *ip, char *bcast, char *nmask)
     /* [previous][next][first][last][top][bottom][index][help]  */
 267 {
 268     if (ip)
 269     {
 270         got_ip = True;
 271         default_ip = *interpret_addr2 (ip);
 272     }
 273 
 274     if (bcast)
 275     {
 276         got_bcast = True;
 277         default_bcast = *interpret_addr2 (bcast);
 278     }
 279 
 280     if (nmask)
 281     {
 282         got_nmask = True;
 283         default_nmask = *interpret_addr2 (nmask);
 284     }
 285 }
 286 #endif /* 0 */
 287 
 288 /****************************************************************************
 289   check if an IP is one of mine
 290   **************************************************************************/
 291 BOOL
 292 ismyip (struct in_addr ip)
     /* [previous][next][first][last][top][bottom][index][help]  */
 293 {
 294     struct interface *i;
 295     for (i = local_interfaces; i; i = i->next)
 296         if (ip_equal (i->ip, ip))
 297             return True;
 298     return False;
 299 }
 300 
 301 #if 0
 302 /****************************************************************************
 303   check if a packet is from a local (known) net
 304   **************************************************************************/
 305 BOOL
 306 is_local_net (struct in_addr from)
     /* [previous][next][first][last][top][bottom][index][help]  */
 307 {
 308     struct interface *i;
 309     for (i = local_interfaces; i; i = i->next)
 310         if ((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
 311             return True;
 312     return False;
 313 }
 314 #endif /* 0 */
 315 
 316 /****************************************************************************
 317   how many interfaces do we have
 318   **************************************************************************/
 319 int
 320 iface_count (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 321 {
 322     int ret = 0;
 323     struct interface *i;
 324 
 325     for (i = local_interfaces; i; i = i->next)
 326         ret++;
 327     return ret;
 328 }
 329 
 330 #if 0
 331 /****************************************************************************
 332  True if we have two or more interfaces.
 333   **************************************************************************/
 334 BOOL
 335 we_are_multihomed (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 336 {
 337     static int multi = -1;
 338 
 339     if (multi == -1)
 340         multi = (iface_count () > 1 ? True : False);
 341 
 342     return multi;
 343 }
 344 
 345 /****************************************************************************
 346   return the Nth interface
 347   **************************************************************************/
 348 struct interface *
 349 get_interface (int n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 350 {
 351     struct interface *i;
 352 
 353     for (i = local_interfaces; i && n; i = i->next)
 354         n--;
 355 
 356     if (i)
 357         return i;
 358     return NULL;
 359 }
 360 #endif /* 0 */
 361 /****************************************************************************
 362   return IP of the Nth interface
 363   **************************************************************************/
 364 struct in_addr *
 365 iface_n_ip (int n)
     /* [previous][next][first][last][top][bottom][index][help]  */
 366 {
 367     struct interface *i;
 368 
 369     for (i = local_interfaces; i && n; i = i->next)
 370         n--;
 371 
 372     if (i)
 373         return &i->ip;
 374     return NULL;
 375 }
 376 
 377 /****************************************************************************
 378 Try and find an interface that matches an ip. If we cannot, return NULL
 379   **************************************************************************/
 380 static struct interface *
 381 iface_find (struct in_addr ip)
     /* [previous][next][first][last][top][bottom][index][help]  */
 382 {
 383     struct interface *i;
 384     if (zero_ip (ip))
 385         return local_interfaces;
 386 
 387     for (i = local_interfaces; i; i = i->next)
 388         if (same_net (i->ip, ip, i->nmask))
 389             return i;
 390 
 391     return NULL;
 392 }
 393 
 394 #if 0
 395 /****************************************************************************
 396 this function provides a simple hash of the configured interfaces. It is
 397 used to detect a change in interfaces to tell us whether to discard
 398 the current wins.dat file.
 399 Note that the result is independent of the order of the interfaces
 400   **************************************************************************/
 401 unsigned
 402 iface_hash (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 403 {
 404     unsigned ret = 0;
 405     struct interface *i;
 406 
 407     for (i = local_interfaces; i; i = i->next)
 408     {
 409         unsigned x1 = (unsigned) str_checksum (inet_ntoa (i->ip));
 410         unsigned x2 = (unsigned) str_checksum (inet_ntoa (i->nmask));
 411         ret ^= (x1 ^ x2);
 412     }
 413 
 414     return ret;
 415 }
 416 #endif /* 0 */
 417 
 418 /* these 3 functions return the ip/bcast/nmask for the interface
 419    most appropriate for the given ip address. If they can't find
 420    an appropriate interface they return the requested field of the
 421    first known interface. */
 422 
 423 struct in_addr *
 424 iface_bcast (struct in_addr ip)
     /* [previous][next][first][last][top][bottom][index][help]  */
 425 {
 426     struct interface *i = iface_find (ip);
 427     return (i ? &i->bcast : &local_interfaces->bcast);
 428 }
 429 
 430 struct in_addr *
 431 iface_ip (struct in_addr ip)
     /* [previous][next][first][last][top][bottom][index][help]  */
 432 {
 433     struct interface *i = iface_find (ip);
 434     return (i ? &i->ip : &local_interfaces->ip);
 435 }

/* [previous][next][first][last][top][bottom][index][help]  */