/**************************************************************************** Try and find an interface that matches an ip. If we cannot, return NULL **************************************************************************/ static struct interface *iface_find(struct in_addr ip) { struct interface *i; if (zero_ip(ip)) return local_interfaces; for (i=local_interfaces;i;i=i->next) if (same_net(i->ip,ip,i->nmask)) return i; return NULL; }
bool is_local_net(const struct sockaddr *from) { struct interface *i; for (i=local_interfaces;i;i=i->next) { if (same_net(from, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) { return true; } } return false; }
/* masked_match - match address against netnumber/netmask */ static bool masked_match(const char *tok, const char *slash, const char *s) { struct sockaddr_storage ss_mask; struct sockaddr_storage ss_tok; struct sockaddr_storage ss_host; char *tok_copy = NULL; if (!interpret_string_addr(&ss_host, s, 0)) { return false; } if (*tok == '[') { /* IPv6 address - remove braces. */ tok_copy = SMB_STRDUP(tok+1); if (!tok_copy) { return false; } /* Remove the terminating ']' */ tok_copy[PTR_DIFF(slash,tok)-1] = '\0'; } else { tok_copy = SMB_STRDUP(tok); if (!tok_copy) { return false; } /* Remove the terminating '/' */ tok_copy[PTR_DIFF(slash,tok)] = '\0'; } if (!interpret_string_addr(&ss_tok, tok_copy, 0)) { SAFE_FREE(tok_copy); return false; } SAFE_FREE(tok_copy); if (strlen(slash + 1) > 2) { if (!interpret_string_addr(&ss_mask, slash+1, 0)) { return false; } } else { char *endp = NULL; unsigned long val = strtoul(slash+1, &endp, 0); if (slash+1 == endp || (endp && *endp != '\0')) { return false; } if (!make_netmask(&ss_mask, &ss_tok, val)) { return false; } } return same_net((struct sockaddr *)(void *)&ss_host, (struct sockaddr *)(void *)&ss_tok, (struct sockaddr *)(void *)&ss_mask); }
/**************************************************************************** Try and find an interface that matches an ip. If we cannot, return NULL **************************************************************************/ static struct interface *iface_find(struct in_addr ip, BOOL CheckMask) { struct interface *i; if (is_zero_ip(ip)) return local_interfaces; for (i=local_interfaces; i; i=i->next) if (CheckMask) { if (same_net(i->ip,ip,i->nmask)) return i; } else if ((i->ip).s_addr == ip.s_addr) return i; return NULL; }
/**************************************************************************** Load a lmhosts file. ****************************************************************************/ void load_lmhosts_file(char *fname) { pstring name; int name_type; struct in_addr ipaddr; FILE *fp = startlmhosts( fname ); if (!fp) { DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n", fname, strerror(errno))); return; } while (getlmhostsent(fp, name, &name_type, &ipaddr) ) { struct subnet_record *subrec = NULL; enum name_source source = LMHOSTS_NAME; /* 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(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)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); (void)add_name_to_subnet(subrec,name,0x20,(uint16)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)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); } } endlmhosts(fp); }
/** return true if a IP matches a IP/netmask pair */ bool iface_list_same_net(const char *ip1, const char *ip2, const char *netmask) { struct sockaddr_storage ip1_ss, ip2_ss, nm_ss; if (!interpret_string_addr(&ip1_ss, ip1, AI_NUMERICHOST)) { return false; } if (!interpret_string_addr(&ip2_ss, ip2, AI_NUMERICHOST)) { return false; } if (!interpret_string_addr(&nm_ss, netmask, AI_NUMERICHOST)) { return false; } return same_net((struct sockaddr *)&ip1_ss, (struct sockaddr *)&ip2_ss, (struct sockaddr *)&nm_ss); }
static struct interface *iface_find(const struct sockaddr *ip, bool check_mask) { struct interface *i; if (is_address_any(ip)) { return local_interfaces; } for (i=local_interfaces;i;i=i->next) { if (check_mask) { if (same_net(ip, (struct sockaddr *)&i->ip, (struct sockaddr *)&i->netmask)) { return i; } } else if (sockaddr_equal((struct sockaddr *)&i->ip, ip)) { return i; } } return NULL; }
/**************************************************************************** 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, bool enable_ipv6) { struct sockaddr_storage ss; struct sockaddr_storage ss_mask; struct sockaddr_storage ss_net; struct sockaddr_storage ss_bcast; struct iface_struct ifs; char *p; int i; bool added=false; bool goodaddr = false; /* 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], local_interfaces, enable_ipv6); added = true; } } if (added) { return; } /* maybe it is a DNS name */ p = strchr_m(token,'/'); if (p == NULL) { if (!interpret_string_addr(&ss, token, 0)) { DEBUG(2, ("interpret_interface: Can't find address " "for %s\n", token)); return; } for (i=0; i<total_probed; i++) { if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&probed_ifaces[i].ip)) { add_interface(mem_ctx, &probed_ifaces[i], local_interfaces, enable_ipv6); return; } } DEBUG(2,("interpret_interface: " "can't determine interface for %s\n", token)); return; } /* parse it into an IP address/netmasklength pair */ *p = 0; goodaddr = interpret_string_addr(&ss, token, 0); *p++ = '/'; if (!goodaddr) { DEBUG(2,("interpret_interface: " "can't determine interface for %s\n", token)); return; } if (strlen(p) > 2) { goodaddr = interpret_string_addr(&ss_mask, p, 0); if (!goodaddr) { DEBUG(2,("interpret_interface: " "can't determine netmask from %s\n", p)); return; } } else { char *endp = NULL; unsigned long val = strtoul(p, &endp, 0); if (p == endp || (endp && *endp != '\0')) { DEBUG(2,("interpret_interface: " "can't determine netmask value from %s\n", p)); return; } if (!make_netmask(&ss_mask, &ss, val)) { DEBUG(2,("interpret_interface: " "can't apply netmask value %lu from %s\n", val, p)); return; } } make_bcast(&ss_bcast, &ss, &ss_mask); make_net(&ss_net, &ss, &ss_mask); /* Maybe the first component was a broadcast address. */ if (sockaddr_equal((struct sockaddr *)&ss_bcast, (struct sockaddr *)&ss) || sockaddr_equal((struct sockaddr *)&ss_net, (struct sockaddr *)&ss)) { for (i=0; i<total_probed; i++) { if (same_net((struct sockaddr *)&ss, (struct sockaddr *)&probed_ifaces[i].ip, (struct sockaddr *)&ss_mask)) { /* Temporarily replace netmask on * the detected interface - user knows * best.... */ struct sockaddr_storage saved_mask = probed_ifaces[i].netmask; probed_ifaces[i].netmask = ss_mask; DEBUG(2,("interpret_interface: " "using netmask value %s from " "config file on interface %s\n", p, probed_ifaces[i].name)); add_interface(mem_ctx, &probed_ifaces[i], local_interfaces, enable_ipv6); probed_ifaces[i].netmask = saved_mask; return; } } DEBUG(2,("interpret_interface: Can't determine ip for " "broadcast address %s\n", token)); return; } /* Just fake up the interface definition. User knows best. */ DEBUG(2,("interpret_interface: Adding interface %s\n", token)); ZERO_STRUCT(ifs); (void)strlcpy(ifs.name, token, sizeof(ifs.name)); ifs.flags = IFF_BROADCAST; ifs.ip = ss; ifs.netmask = ss_mask; ifs.bcast = ss_bcast; add_interface(mem_ctx, &ifs, local_interfaces, enable_ipv6); }
int sdp_mangle_ip (struct sip_msg *msg, char *oldip, char *newip) { int i, oldContentLength, newContentLength, diff, oldlen,len,off,ret,needToDealocate; unsigned int mask, address, locatedIp; struct lump *l; regmatch_t pmatch; regex_t *re; char *s, *pos,*begin,*key; char buffer[16]; /* 123.456.789.123\0 */ #ifdef DEBUG fprintf (stdout,"---START--------MANGLE IP-----------------\n"); #endif key = IP_REGEX; /* * Checking if msg has a payload */ if (msg == NULL) { LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for msg\n"); return -1; } if ((msg->content_length==0) && ((parse_headers(msg,HDR_CONTENTLENGTH,0)==-1) || (msg->content_length==0) )){ LOG(L_ERR,"ERROR: sdp_mangle_port: bad or missing " "Content-Length \n"); return -2; } oldContentLength = get_content_length(msg); if (oldContentLength <= 0) { LOG(L_ERR,"ERROR: sdp_mangle_ip: Received <= for Content-Length\n"); return -2; } /* checking oldip */ if (oldip == NULL) { LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for oldip\n"); return -3; } /* checking newip */ if (newip == NULL) { LOG(L_ERR,"ERROR: sdp_mangle_ip: Received NULL for newip\n"); return -4; } i = parse_ip_netmask (oldip, &pos, &mask); if (i == -1) { /* invalid value for the netmask specified in oldip */ LOG(L_ERR,"ERROR: sdp_mangle_ip: invalid value for the netmask specified in oldip\n"); return -5; } else { i = parse_ip_address (pos, &address); if (pos != NULL) free (pos); if (i == 0) { LOG(L_ERR,"ERROR: sdp_mangle_ip: invalid value for the ip specified in oldip\n"); return -6; /* parse error in ip */ } } /* now we have in address/netmask binary values */ begin = get_body(msg);//msg->buf + msg->first_line.len; // inlocuiesc cu begin = getbody */ ret = -1; len = strlen (newip); /* try to use precompiled expressions */ needToDealocate = 0; if (ipExpression != NULL) { re = ipExpression; #ifdef DEBUG fprintf(stdout,"Using PRECOMPILED expression for ip ...\n"); #endif } else /* we are not using precompiled expressions */ { re = pkg_malloc(sizeof(regex_t)); if (re == NULL) { LOG(L_ERR,"ERROR: sdp_mangle_ip: Unable to allocate re\n"); return -7; } needToDealocate = 1; if ((regcomp (re, key, REG_EXTENDED)) != 0) { LOG(L_ERR,"ERROR: sdp_mangle_ip: Unable to compile %s \n",key); return -8; } #ifdef DEBUG fprintf(stdout,"Using ALLOCATED expression for ip ...\n"); #endif } diff = 0; while ((begin < msg->buf + msg->len) && (regexec (re, begin, 1, &pmatch, 0) == 0)) { off = begin - msg->buf; if (pmatch.rm_so == -1) { LOG (L_ERR,"ERROR: sdp_mangler_ip: offset unknown\n"); return -9; } #ifdef STRICT_CHECK pmatch.rm_eo --; /* return with one space,\n,\r */ #endif /* for BSD and Solaris we avoid memrchr pos = (char *) memrchr (begin + pmatch.rm_so, ' ',pmatch.rm_eo - pmatch.rm_so); */ pos = begin+pmatch.rm_eo; do pos--; while (*pos != ' '); /* we should find ' ' because we matched c=IN IP4 ip */ pos++; /* jumping over space */ oldlen = (pmatch.rm_eo - pmatch.rm_so) - (pos - (begin + pmatch.rm_so)); /* ip length */ if (oldlen > 15) { LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail because oldlen > 15\n"); #ifdef STRICT_CHECK return -10; #else goto continue2; /* silent fail return -10; invalid ip format ,probably like 1000.3.12341.2 */ #endif } buffer[0] = '\0'; strncat ((char *) buffer, pos, oldlen); buffer[oldlen] = '\0'; i = parse_ip_address (buffer, &locatedIp); if (i == 0) { LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail on parsing matched address \n"); #ifdef STRICT_CHECK return -11; #else goto continue2; #endif } if (same_net (locatedIp, address, mask) == 0) { LOG(L_WARN,"WARNING: sdp_mangle_ip: Silent fail because matched address is not in network\n"); #ifdef DEBUG fprintf(stdout,"Extracted ip is %s and not mangling \n",buffer); #endif goto continue2; /* not in the same net, skiping */ } #ifdef DEBUG fprintf(stdout,"Extracted ip is %s and mangling to %s\n",buffer,newip); #endif /* replacing ip */ /* deleting old ip */ if ((l = del_lump (msg,pmatch.rm_so + off + (pos - (begin + pmatch.rm_so)),oldlen, 0)) == 0) { LOG (L_ERR,"ERROR: sdp_mangle_ip: del_lump failed\n"); return -12; } s = pkg_malloc (len); if (s == 0) { LOG (L_ERR,"ERROR: sdp_mangle_ip: mem. allocation failure\n"); return -13; } memcpy (s, newip, len); if (insert_new_lump_after (l, s, len, 0) == 0) { LOG (L_ERR, "ERROR: sdp_mangle_ip: could not insert new lump\n"); pkg_free (s); return -14; } diff = diff + len /*new length */ - oldlen; /* new cycle */ ret++; continue2: begin = begin + pmatch.rm_eo; } /* while */ if (needToDealocate) { regfree (re); /* if I am going to use precompiled expressions to be removed */ pkg_free(re); #ifdef DEBUG fprintf(stdout,"Dealocating expression for ip ...\n"); #endif } if (diff != 0) { newContentLength = oldContentLength + diff; patch_content_length (msg, newContentLength); } #ifdef DEBUG fprintf (stdout,"---END--------MANGLE IP-----------------\n"); #endif return ret+2; }