/** * @brief Checks if a buffer points to a valid short range-expressed network. * "192.168.11.1-50" is valid, "192.168.1.1-50e" and "192.168.1.1-300" are not. * * @param str String to check in. * * @return 1 if str points to a valid short range-network, 0 otherwise. */ static int is_short_range_network (const char *str) { long end; char *ip_str, *end_str, *p; ip_str = g_strdup (str); end_str = strchr (ip_str, '-'); if (end_str == NULL) { g_free (ip_str); return 0; } /* Separate the addreses. */ *end_str = '\0'; end_str++; if (!is_ipv4_address (ip_str) || !isdigit (*end_str)) { g_free (ip_str); return 0; } p = NULL; end = strtol (end_str, &p, 10); g_free (ip_str); if (*p || end < 0 || end > 255) return 0; return 1; }
/** * @brief Checks if a buffer points to an IPv4 CIDR-exprpessed block. * "192.168.12.3/24" is valid, "192.168.1.3/31" is not. * * @param[in] str Buffer to check in. * * @return 1 if valid CIDR-expressed block, 0 otherwise. */ static int is_cidr_block (const char *str) { long block; char *addr_str, *block_str, *p; addr_str = g_strdup (str); block_str = strchr (addr_str, '/'); if (block_str == NULL) { g_free (addr_str); return 0; } /* Separate the address from the block value. */ *block_str = '\0'; block_str++; if (!is_ipv4_address (addr_str) || !isdigit (*block_str)) { g_free (addr_str); return 0; } p = NULL; block = strtol (block_str, &p, 10); g_free (addr_str); if (*p || block <= 0 || block > 30) return 0; return 1; }
static char *get_domain_mask(char *host) { char *ptr; if (strchr(host, '.') == NULL) { /* no dots - toplevel domain or IPv6 address */ ptr = strrchr(host, ':'); if (ptr != NULL) { /* IPv6 address, ban the last 64k addresses */ if (ptr[1] != '\0') strcpy(ptr+1, "*"); } return host; } if (is_ipv4_address(host)) { /* it's an IP address, change last digit to * */ ptr = strrchr(host, '.'); if (ptr != NULL && isdigit(ptr[1])) strcpy(ptr+1, "*"); } else { /* if more than one dot, skip the first (dyn123.blah.net -> *.blah.net) */ ptr = strchr(host, '.'); if (ptr != NULL && strchr(ptr+1, '.') != NULL) { host = ptr-1; host[0] = '*'; } } return host; }
/** * @brief Determines the host type in a buffer. * * @param[in] str Buffer that contains host definition, could a be hostname, * single IPv4 or IPv6, CIDR-expressed block etc,. * * @return Host_TYPE_*, -1 if error. */ static int determine_host_type (const gchar *str_stripped) { /* * We have a single element with no leading or trailing * white spaces. This element could represent different host * definitions: single IPs, host names, CIDR-expressed blocks, * range-expressed networks, IPv6 addresses. */ /* Null or empty string. */ if (str_stripped == NULL || *str_stripped == '\0') return -1; /* Check for regular single IPv4 address. */ if (is_ipv4_address (str_stripped)) return HOST_TYPE_IPV4; /* Check for regular single IPv6 address. */ if (is_ipv6_address (str_stripped)) return HOST_TYPE_IPV6; /* Check for regular IPv4 CIDR-expressed block like "192.168.12.0/24" */ if (is_cidr_block (str_stripped)) return HOST_TYPE_CIDR_BLOCK; /* Check for short range-expressed networks "192.168.12.5-40" */ if (is_short_range_network (str_stripped)) return HOST_TYPE_RANGE_SHORT; /* Check for long range-expressed networks "192.168.1.0-192.168.3.44" */ if (is_long_range_network (str_stripped)) return HOST_TYPE_RANGE_LONG; /* Check for regular IPv6 CIDR-expressed block like "2620:0:2d0:200::7/120" */ if (is_cidr6_block (str_stripped)) return HOST_TYPE_CIDR6_BLOCK; /* Check for short range-expressed networks "::1-ef12" */ if (is_short_range6_network (str_stripped)) return HOST_TYPE_RANGE6_SHORT; /* Check for long IPv6 range-expressed networks like "::1:20:7-::1:25:3" */ if (is_long_range6_network (str_stripped)) return HOST_TYPE_RANGE6_LONG; /* Check for hostname. */ if (is_hostname (str_stripped)) return HOST_TYPE_NAME; /* @todo: If everything else fails, fallback to hostname ? */ return -1; }
/* Start listening for incoming connections */ GIOChannel *dcc_listen(GIOChannel *iface, IPADDR *ip, int *port) { GIOChannel *handle; IPADDR *listen_ip = NULL; const char *dcc_port, *p, *own_ip; int first, last; if (net_getsockname(iface, ip, NULL) == -1) return NULL; /* figure out if we want to listen in IPv4 address or in "any" address, which may mean IPv4+IPv6 or just IPv6 depending on OS. */ own_ip = settings_get_str("dcc_own_ip"); if (*own_ip != '\0') { if (is_ipv4_address(own_ip)) listen_ip = &ip4_any; } else { if (!IPADDR_IS_V6(ip)) listen_ip = &ip4_any; } /* get first port */ dcc_port = settings_get_str("dcc_port"); first = atoi(dcc_port); if (first == 0) { /* random port */ *port = 0; return net_listen(listen_ip, port); } /* get last port */ p = strchr(dcc_port, ' '); if (p == NULL) p = strchr(dcc_port, '-'); dcc_port = p; if (dcc_port == NULL) last = first; else { last = atoi(dcc_port+1); if (last == 0) last = first; } /* use the first available port */ for (*port = first; *port <= last; (*port)++) { handle = net_listen(listen_ip, port); if (handle != NULL) return handle; } return NULL; }
/** * @brief Checks if a buffer points to a valid long range-expressed network. * "192.168.12.1-192.168.13.50" is valid. * * @param[in] str Buffer to check in. * * @return 1 if valid long range-expressed network, 0 otherwise. */ static int is_long_range_network (const char *str) { char *first_str, *second_str; int ret; first_str = g_strdup (str); second_str = strchr (first_str, '-'); if (second_str == NULL) { g_free (first_str); return 0; } /* Separate the addresses. */ *second_str = '\0'; second_str++; ret = is_ipv4_address (first_str) && is_ipv4_address (second_str); g_free (first_str); return ret; }
int main( int narg, char **opts) { int result; if( narg < 2) printf( "Give an IP address string to test on the command line.\n"); else { result = is_ipv4_address( opts[ 1]); printf( "Is '%s' an IPV4 address? rc=%d\n", opts[ 1], result); } exit( 0); }
struct url_breakout *parse_url_string( char *url) { int rc = RC_NORMAL, stlen, port_number = NO_PORT; char *copy = 0, *protocol = 0, *user = 0, *domain = 0, *port = 0, *uri = 0, *query = 0, *pos = 0, *en_protocol = 0, *en_user = 0, *en_domain = 0, *st_port = 0, *st_query = 0, *next = 0, *scan_from = 0, *st_ipv6_port = 0, hold; struct url_breakout *parts = 0; copy = strdup( url); if( !copy) rc = ERR_MALLOC_FAILED; if( rc == RC_NORMAL) { parts = alloc_url_breakout(); if( !parts) rc = ERR_MALLOC_FAILED; } if( rc == RC_NORMAL) { scan_from = pos = copy; next = copy + strlen( copy); en_protocol = strstr( scan_from, PROTOCOL_DELIM); if( en_protocol) { scan_from = en_protocol + strlen( PROTOCOL_DELIM); next = en_protocol; } en_user = strstr( scan_from, USER_DELIM); en_domain = strstr( scan_from, DOMAIN_DELIM); if( en_user) { if( !en_domain) scan_from = en_user + 1; else if( en_user < en_domain) scan_from = en_user + 1; } st_port = strstr( scan_from, PORT_DELIM); st_query = strstr( scan_from, QUERY_DELIM); st_ipv6_port = strstr( scan_from, IPV6_PORT_DELIM); if( st_ipv6_port) { if( en_domain) { /* fixes the case: http://2601:9:5480:7d:59a8:fa5e:a8d2:c72d#8080/something.html */ /* also allows: http://www.foo.com#8080/something.html */ if( st_ipv6_port < en_domain) st_port = st_ipv6_port; } else if( st_query) { /* fixes the case: http://2601:9:5480:7d:59a8:fa5e:a8d2:c72d#8080?data=some */ /* also allows: http://www.foo.com#8080?data=some */ if( st_ipv6_port < st_query) st_port = st_ipv6_port; } /* fixes the case: http://2601:9:5480:7d:59a8:fa5e:a8d2:c72d#8080 */ /* also allows: http://www.foo.com#8080 */ else st_port = st_ipv6_port; } if( en_user) if( en_user < next) next = en_user; if( en_domain) if( en_domain < next) next = en_domain; if( st_port) if( st_port < next) next = st_port; if( st_query) if( st_query < next) next = st_query; } if( rc == RC_NORMAL && next == en_protocol) { hold = *en_protocol; *en_protocol = '\0'; protocol = strdup( pos); *en_protocol = hold; if( !protocol) rc = ERR_MALLOC_FAILED; else { pos = en_protocol + strlen( PROTOCOL_DELIM); next = pos + strlen( pos); if( en_user) if( en_user < next) next = en_user; if( en_domain) if( en_domain < next) next = en_domain; if( st_port) if( st_port < next) next = st_port; if( st_query) if( st_query < next) next = st_query; } } if( rc == RC_NORMAL && next == en_user) { hold = *en_user; *en_user = '******'; user = strdup( pos); *en_user = hold; if( !user) rc = ERR_MALLOC_FAILED; pos = en_user + 1; next = next + strlen( next); if( st_port) if( st_port < next) next = st_port; if( en_domain) if( en_domain < next) next = en_domain; if( st_query) if( st_query < next) next = st_query; } if( rc == RC_NORMAL && next == st_port) { /* This is annoying, but we need to see if the ":" we found was part * of an IPV6 address and not a ":port" suffixs on a domain or IPV4 * address. */ if( en_domain) { hold = *en_domain; *en_domain = '\0'; } if( is_ipv6_address( pos)) { st_port = 0; domain = strdup( pos); if( !domain) rc = ERR_MALLOC_FAILED; if( en_domain) { *en_domain = hold; pos = en_domain; } else pos = pos + strlen( pos); next = pos; } else { if( en_domain) *en_domain = hold; hold = *st_port; *st_port = '\0'; domain = strdup( pos); *st_port = hold; if( !domain) rc = ERR_MALLOC_FAILED; else { stlen = strlen( PORT_DELIM); pos = st_port + stlen; next = next + strlen( next); if( en_domain) if( en_domain < next) next = en_domain; if( st_query) if( st_query < next) next = st_query; hold = *next; *next = '\0'; port = strdup( pos); *next = hold; if( !port) rc = ERR_MALLOC_FAILED; pos = next; } } } if( rc == RC_NORMAL && next == en_domain) { if( !domain) { hold = *en_domain; *en_domain = '\0'; domain = strdup( pos); *en_domain = hold; if( !domain) rc = ERR_MALLOC_FAILED; pos = en_domain; } if( rc == RC_NORMAL) { if( !st_query) { uri = strdup( pos); pos = pos + strlen( pos); next = pos; } else { hold = *st_query; *st_query = '\0'; uri = strdup( pos); *st_query = hold; next = pos = st_query; } if( !uri) rc = ERR_MALLOC_FAILED; } } if( rc == RC_NORMAL && next == st_query) { if( !domain) { hold = *st_query; *st_query = '\0'; domain = strdup( pos); *st_query = hold; if( !domain) rc = ERR_MALLOC_FAILED; } if( rc == RC_NORMAL) { query = strdup( st_query + 1); if( !query) rc = ERR_MALLOC_FAILED; pos = pos + strlen( pos); next = pos; } } if( rc == RC_NORMAL && !domain && !*next && *pos) { domain = strdup( pos); if( !domain) rc = ERR_MALLOC_FAILED; pos = next; } if( rc == RC_NORMAL && port) { if( !isdigit( *port)) rc = ERR_INVALID_DATA; else { errno = 0; port_number = strtoul( port, &pos, BASE10); if( errno) rc = ERR_INVALID_DATA; else if( *pos) rc = ERR_INVALID_DATA; } } if( rc == RC_NORMAL && domain) { pos = strdup( domain); if( !pos) rc = ERR_MALLOC_FAILED; else if( is_ipv4_address( domain)) parts->ip4 = pos; else if( is_ipv6_address( domain)) parts->ip6 = pos; else parts->host = pos; } if( rc == RC_NORMAL) { if( !domain) parts->status = URL_ERROR; else if( !*domain) parts->status = URL_ERROR; else { parts->status = URL_VALID; parts->port = port_number; parts->protocol = protocol; parts->user = user; parts->target = domain; parts->uri = uri; parts->query = query; if( protocol) parts->use_ssl = !strcasecmp( protocol, SSL_PROT_PREFIX); protocol = user = domain = uri = query = 0; } } else if( parts) { parts->status = URL_ERROR; } if( protocol) free( protocol); if( user) free( user); if( domain) free( domain); if( uri) free( uri); if( query) free( query); if( port) free( port); if( copy) free( copy); return( parts); }