/**************************************************************************** Try and find an interface that matches an ip. If we cannot, return NULL **************************************************************************/ static struct interface *iface_find(struct interface *interfaces, struct in_addr ip, bool CheckMask) { struct interface *i; if (is_zero_ip_v4(ip)) return interfaces; for (i=interfaces;i;i=i->next) if (CheckMask) { if (same_net_v4(i->ip,ip,i->nmask)) return i; } else if (i->ip.s_addr == ip.s_addr) return i; return NULL; }
void load_lmhosts_file(const char *fname) { char *name = NULL; int name_type; struct sockaddr_storage ss; TALLOC_CTX *ctx = talloc_init("load_lmhosts_file"); FILE *fp = startlmhosts( fname ); if (!fp) { DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n", fname, strerror(errno))); TALLOC_FREE(ctx); return; } while (getlmhostsent(ctx, fp, &name, &name_type, &ss) ) { struct in_addr ipaddr; struct subnet_record *subrec = NULL; enum name_source source = LMHOSTS_NAME; if (ss.ss_family != AF_INET) { TALLOC_FREE(name); continue; } ipaddr = ((struct sockaddr_in *)&ss)->sin_addr; /* We find a relevent subnet to put this entry on, then add it. */ /* Go through all the broadcast subnets and see if the mask matches. */ for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { if(same_net_v4(ipaddr, subrec->bcast_ip, subrec->mask_ip)) break; } /* If none match add the name to the remote_broadcast_subnet. */ if(subrec == NULL) subrec = remote_broadcast_subnet; if(name_type == -1) { /* Add the (0) and (0x20) names directly into the namelist for this subnet. */ (void)add_name_to_subnet(subrec,name,0x00,(uint16_t)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); (void)add_name_to_subnet(subrec,name,0x20,(uint16_t)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); } else { /* Add the given name type to the subnet namelist. */ (void)add_name_to_subnet(subrec,name,name_type,(uint16_t)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); } } TALLOC_FREE(ctx); endlmhosts(fp); }
bool is_linklocal_addr(const struct sockaddr_storage *pss) { #ifdef HAVE_IPV6 if (pss->ss_family == AF_INET6) { const struct in6_addr *pin6 = &((const struct sockaddr_in6 *)pss)->sin6_addr; return IN6_IS_ADDR_LINKLOCAL(pin6); } #endif if (pss->ss_family == AF_INET) { const struct in_addr *pin = &((const struct sockaddr_in *)pss)->sin_addr; struct in_addr ll_addr; struct in_addr mask_addr; /* 169.254.0.0/16, is link local, see RFC 3927 */ ll_addr.s_addr = 0xa9fe0000; mask_addr.s_addr = 0xffff0000; return same_net_v4(*pin, ll_addr, mask_addr); } return false; }
/** * Are two IPs on the same subnet? */ bool same_net(const struct sockaddr *ip1, const struct sockaddr *ip2, const struct sockaddr *mask) { if (ip1->sa_family != ip2->sa_family) { /* Never on the same net. */ return false; } #if defined(HAVE_IPV6) if (ip1->sa_family == AF_INET6) { struct sockaddr_in6 ip1_6 = *(const struct sockaddr_in6 *)ip1; struct sockaddr_in6 ip2_6 = *(const struct sockaddr_in6 *)ip2; struct sockaddr_in6 mask_6 = *(const struct sockaddr_in6 *)mask; char *p1 = (char *)&ip1_6.sin6_addr; char *p2 = (char *)&ip2_6.sin6_addr; char *m = (char *)&mask_6.sin6_addr; int i; for (i = 0; i < sizeof(struct in6_addr); i++) { *p1++ &= *m; *p2++ &= *m; m++; } return (memcmp(&ip1_6.sin6_addr, &ip2_6.sin6_addr, sizeof(struct in6_addr)) == 0); } #endif if (ip1->sa_family == AF_INET) { return same_net_v4(((const struct sockaddr_in *)ip1)->sin_addr, ((const struct sockaddr_in *)ip2)->sin_addr, ((const struct sockaddr_in *)mask)->sin_addr); } return false; }
/** return true if a IP matches a IP/netmask pair */ bool iface_same_net(const char *ip1, const char *ip2, const char *netmask) { return same_net_v4(interpret_addr2(ip1), interpret_addr2(ip2), interpret_addr2(netmask)); }
/** 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); }