/**************************************************************************** add an interface to the linked list of interfaces ****************************************************************************/ static void add_interface(struct in_addr ip, struct in_addr nmask) { struct interface *iface; if (iface_find(ip, False)) { DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip))); return; } #if !defined(__s390__) if (ip_equal(nmask, allones_ip)) { DEBUG(3,("not adding non-broadcast interface %s\n",inet_ntoa(ip))); return; } #endif iface = SMB_MALLOC_P(struct interface); if (!iface) return; ZERO_STRUCTPN(iface); iface->ip = ip; iface->nmask = nmask; iface->bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); DLIST_ADD(local_interfaces, iface); DEBUG(2,("added interface ip=%s ",inet_ntoa(iface->ip))); DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast))); DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask))); }
/**************************************************************************** add an interface to the linked list of interfaces ****************************************************************************/ static void add_interface(TALLOC_CTX *mem_ctx, struct in_addr ip, struct in_addr nmask, struct interface **interfaces) { struct interface *iface; struct in_addr bcast; if (iface_find(*interfaces, ip, false)) { DEBUG(3,("not adding duplicate interface %s\n",inet_ntoa(ip))); return; } iface = talloc(*interfaces == NULL ? mem_ctx : *interfaces, struct interface); if (iface == NULL) return; ZERO_STRUCTPN(iface); iface->ip = ip; iface->nmask = nmask; bcast.s_addr = MKBCADDR(iface->ip.s_addr, iface->nmask.s_addr); /* keep string versions too, to avoid people tripping over the implied static in inet_ntoa() */ iface->ip_s = talloc_strdup(iface, inet_ntoa(iface->ip)); iface->nmask_s = talloc_strdup(iface, inet_ntoa(iface->nmask)); if (nmask.s_addr != ~0) { iface->bcast_s = talloc_strdup(iface, inet_ntoa(bcast)); } DLIST_ADD_END(*interfaces, iface, struct interface *); DEBUG(3,("added interface ip=%s nmask=%s\n", iface->ip_s, iface->nmask_s)); }
/**************************************************************************** get the broadcast address for our address ([email protected]) ****************************************************************************/ static void get_broadcast (struct in_addr *if_ipaddr, struct in_addr *if_bcast, struct in_addr *if_nmask) { uint32 nm; short onbc; short offbc; /* get a default netmask and broadcast */ default_netmask (if_nmask, if_ipaddr); get_netmask (if_ipaddr, if_nmask); /* sanity check on the netmask */ 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); } /* derive the broadcast assuming a 1's broadcast, as this is what all MS operating systems do, we have to comply even if the unix box is setup differently */ if_bcast->s_addr = MKBCADDR (if_ipaddr->s_addr, if_nmask->s_addr); DEBUG (4, ("Derived broadcast address %s\n", inet_ntoa (*if_bcast))); }
/**************************************************************************** load a list of network interfaces ****************************************************************************/ static void interpret_interfaces (char *s, struct interface **interfaces, const char *description) { 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"); while (next_token (&ptr, token, NULL, sizeof (token))) { /* parse it into an IP address/netmasklength pair */ char *p = strchr (token, '/'); if (p) *p++ = 0; ip = *interpret_addr2 (token); /* maybe we already have it listed */ { struct interface *i; for (i = (*interfaces); i; i = i->next) if (ip_equal (ip, i->ip)) break; if (i) continue; } iface = (struct interface *) malloc (sizeof (*iface)); if (!iface) return; iface->ip = ip; if (p) { if (strlen (p) > 2) iface->nmask = *interpret_addr2 (p); else iface->nmask.s_addr = htonl (((ALLONES >> atoi (p)) ^ ALLONES)); } else { default_netmask (&iface->nmask, &iface->ip); } iface->bcast.s_addr = MKBCADDR (iface->ip.s_addr, iface->nmask.s_addr); iface->next = NULL; if (!(*interfaces)) { (*interfaces) = iface; } else { last_iface->next = iface; } last_iface = iface; DEBUG (2, ("Added %s ip=%s ", description, inet_ntoa (iface->ip))); DEBUG (2, ("bcast=%s ", inet_ntoa (iface->bcast))); DEBUG (2, ("nmask=%s\n", inet_ntoa (iface->nmask))); }
/**************************************************************************** interpret a single element from a interfaces= config line This handles the following different forms: 1) wildcard interface name 2) DNS name 3) IP/masklen 4) ip/mask 5) bcast/mask ****************************************************************************/ static void interpret_interface(char *token) { struct in_addr ip, nmask; char *p; int i, added=0; zero_ip(&ip); zero_ip(&nmask); /* first check if it is an interface name */ for (i=0; i<total_probed; i++) { if (gen_fnmatch(token, probed_ifaces[i].name) == 0) { add_interface(probed_ifaces[i].ip, probed_ifaces[i].netmask); added = 1; } } if (added) return; /* maybe it is a DNS name */ p = strchr_m(token,'/'); if (!p) { ip = *interpret_addr2(token); for (i=0; i<total_probed; i++) { if (ip.s_addr == probed_ifaces[i].ip.s_addr && !ip_equal(allones_ip, probed_ifaces[i].netmask)) { add_interface(probed_ifaces[i].ip, probed_ifaces[i].netmask); return; } } DEBUG(2,("can't determine netmask for %s\n", token)); return; } /* parse it into an IP address/netmasklength pair */ *p = 0; ip = *interpret_addr2(token); *p++ = '/'; if (strlen(p) > 2) { nmask = *interpret_addr2(p); } else { nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); } /* maybe the first component was a broadcast address */ if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) || ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) { for (i=0; i<total_probed; i++) { if (same_net(ip, probed_ifaces[i].ip, nmask)) { add_interface(probed_ifaces[i].ip, nmask); return; } } DEBUG(2,("Can't determine ip for broadcast address %s\n", token)); return; } add_interface(ip, nmask); }
/** interpret a single element from a interfaces= config line This handles the following different forms: 1) wildcard interface name 2) DNS name 3) IP/masklen 4) ip/mask 5) bcast/mask **/ static void interpret_interface(TALLOC_CTX *mem_ctx, const char *token, struct iface_struct *probed_ifaces, int total_probed, struct interface **local_interfaces) { struct in_addr ip, nmask; char *p; char *address; int i, added=0; ip.s_addr = 0; nmask.s_addr = 0; /* first check if it is an interface name */ for (i=0;i<total_probed;i++) { if (gen_fnmatch(token, probed_ifaces[i].name) == 0) { add_interface(mem_ctx, probed_ifaces[i].ip, probed_ifaces[i].netmask, local_interfaces); added = 1; } } if (added) return; /* maybe it is a DNS name */ p = strchr_m(token,'/'); if (!p) { /* don't try to do dns lookups on wildcard names */ if (strpbrk(token, "*?") != NULL) { return; } ip.s_addr = interpret_addr2(token).s_addr; for (i=0;i<total_probed;i++) { if (ip.s_addr == probed_ifaces[i].ip.s_addr) { add_interface(mem_ctx, probed_ifaces[i].ip, probed_ifaces[i].netmask, local_interfaces); return; } } DEBUG(2,("can't determine netmask for %s\n", token)); return; } address = talloc_strdup(mem_ctx, token); p = strchr_m(address,'/'); /* parse it into an IP address/netmasklength pair */ *p++ = 0; ip.s_addr = interpret_addr2(address).s_addr; if (strlen(p) > 2) { nmask.s_addr = interpret_addr2(p).s_addr; } else { nmask.s_addr = htonl(((ALLONES >> atoi(p)) ^ ALLONES)); } /* maybe the first component was a broadcast address */ if (ip.s_addr == MKBCADDR(ip.s_addr, nmask.s_addr) || ip.s_addr == MKNETADDR(ip.s_addr, nmask.s_addr)) { for (i=0;i<total_probed;i++) { if (same_net_v4(ip, probed_ifaces[i].ip, nmask)) { add_interface(mem_ctx, probed_ifaces[i].ip, nmask, local_interfaces); talloc_free(address); return; } } DEBUG(2,("Can't determine ip for broadcast address %s\n", address)); talloc_free(address); return; } add_interface(mem_ctx, ip, nmask, local_interfaces); talloc_free(address); }