summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/lib/interface.c88
1 files changed, 55 insertions, 33 deletions
diff --git a/source3/lib/interface.c b/source3/lib/interface.c
index 95c0b9d53c..7ae97e9119 100644
--- a/source3/lib/interface.c
+++ b/source3/lib/interface.c
@@ -37,30 +37,32 @@ static struct interface *local_interfaces = NULL;
struct interface *last_iface;
+#define ALLONES ((uint32)0xFFFFFFFF)
+#define MKBCADDR(_IP, _NM) ((_IP & _NM) | (_NM ^ ALLONES))
/****************************************************************************
calculate the default netmask for an address
****************************************************************************/
static void default_netmask(struct in_addr *inm, struct in_addr *iad)
{
- uint32 ad = ntohl(iad->s_addr);
- uint32 nm;
- /*
- ** Guess a netmask based on the class of the IP address given.
- */
- if ( (ad & 0x80000000) == 0 ) {
- /* class A address */
- nm = 0xFF000000;
- } else if ( (ad & 0xC0000000) == 0x80000000 ) {
- /* class B address */
- nm = 0xFFFF0000;
- } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
- /* class C address */
- nm = 0xFFFFFF00;
- } else {
- /* class D or E; netmask doesn't make much sense - guess 4 bits */
- nm = 0xFFFFFFF0;
- }
- inm->s_addr = htonl(nm);
+ /*
+ ** Guess a netmask based on the class of the IP address given.
+ */
+ switch((ntohl(iad->s_addr) & 0xE0000000)) {
+ case 0: /* Class A addr */
+ inm->s_addr = htonl(0xFF000000);
+ break;
+
+ case 0x80000000: /* Class B addr */
+ inm->s_addr = htonl(0xFFFF0000);
+ break;
+
+ case 0xC0000000: /* Class C addr */
+ inm->s_addr = htonl(0xFFFFFF00);
+ break;
+
+ default: /* ??? */
+ inm->s_addr = htonl(0xFFFFFFF0);
+ }
}
@@ -228,8 +230,30 @@ static void get_broadcast(struct in_addr *if_ipaddr,
/* sanity check on the netmask */
{
- uint32 nm = ntohl(if_nmask->s_addr);
- if ((nm >> 24) != 0xFF) {
+ uint32 nm;
+ short onbc;
+ short offbc;
+
+ nm = ntohl(if_nmask->s_addr);
+ onbc = 0;
+ offbc = 0;
+ while( (onbc + offbc) < 32 )
+ {
+ if( nm & 0x80000000 )
+ {
+ onbc++;
+ if( offbc ) /* already found an off bit, so mask is wrong */
+ {
+ onbc = 34;
+ }
+ }
+ else
+ {
+ offbc++;
+ }
+ nm <<= 1;
+ }
+ if ((onbc < 8)||(onbc == 34)) {
DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
default_netmask(if_nmask, if_ipaddr);
}
@@ -239,10 +263,7 @@ static void get_broadcast(struct in_addr *if_ipaddr,
all MS operating systems do, we have to comply even if the unix
box is setup differently */
{
- uint32 ad = ntohl(if_ipaddr->s_addr);
- uint32 nm = ntohl(if_nmask->s_addr);
- uint32 bc = (ad & nm) | (0xffffffff & ~nm);
- if_bcast->s_addr = htonl(bc);
+ if_bcast->s_addr = MKBCADDR(if_ipaddr->s_addr, if_nmask->s_addr);
}
DEBUG(4,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
@@ -256,11 +277,12 @@ load a list of network interfaces
static void interpret_interfaces(char *s, struct interface **interfaces,
char *description)
{
- char *ptr = s;
+ char *ptr;
fstring token;
struct interface *iface;
struct in_addr ip;
+ ptr = s;
ipzero = *interpret_addr2("0.0.0.0");
allones_ip = *interpret_addr2("255.255.255.255");
loopback_ip = *interpret_addr2("127.0.0.1");
@@ -268,7 +290,7 @@ static void interpret_interfaces(char *s, struct interface **interfaces,
while (next_token(&ptr,token,NULL)) {
/* parse it into an IP address/netmasklength pair */
char *p = strchr(token,'/');
- if (p) *p = 0;
+ if (p) *p++ = 0;
ip = *interpret_addr2(token);
@@ -286,14 +308,14 @@ static void interpret_interfaces(char *s, struct interface **interfaces,
iface->ip = ip;
if (p) {
- if (strlen(p+1)>2)
- iface->nmask = *interpret_addr2(p+1);
+ if (strlen(p) > 2)
+ iface->nmask = *interpret_addr2(p);
else
- iface->nmask.s_addr = htonl(~((1<<(32-atoi(p+1)))-1));
+ iface->nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES));
} else {
default_netmask(&iface->nmask,&iface->ip);
}
- iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr;
+ iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
iface->next = NULL;
if (!(*interfaces)) {
@@ -329,10 +351,10 @@ static void interpret_interfaces(char *s, struct interface **interfaces,
if (got_nmask) {
iface->nmask = default_nmask;
- iface->bcast.s_addr = iface->ip.s_addr | ~iface->nmask.s_addr;
+ iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr);
}
- if (iface->bcast.s_addr != (iface->ip.s_addr | ~iface->nmask.s_addr)) {
+ if (iface->bcast.s_addr != MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr)) {
DEBUG(2,("Warning: inconsistant interface %s\n",inet_ntoa(iface->ip)));
}