📄 bnf.c
字号:
* @retval Length of valid IP6 address or -1 upon an error. * * @note Scanned IP6 is not always NUL-terminated. */int scan_ip6_address(char **inout_host){ int n, canonize = 0; char *host = *inout_host; char *hexparts[9] = { NULL }; n = span_canonic_ip6_address(host, &canonize, hexparts); if (n == 0) return -1; *inout_host += n; if (canonize) { int len = canonize_ip6_address(host, hexparts); assert(len <= n); if (len < n) host[len] = '\0'; } return n;}/** Return length of valid IP6 reference. */int span_ip6_reference(char const *host){ /* IPv6reference = "[" IPv6address "]" */ if (host && host[0] == '[') { int n = span_ip6_address(host + 1); if (n > 0 && host[n + 1] == ']') return n + 2; } return 0;}/** Scan valid IP6 reference. */int scan_ip6_reference(char **inout_host){ int n, canonize = 0; char *host = *inout_host; char *hexparts[9] = { NULL }; /* IPv6reference = "[" IPv6address "]" */ if (host == NULL || host[0] != '[' || (n = span_canonic_ip6_address(host + 1, &canonize, hexparts)) == 0 || host[n + 1] != ']') return -1; *inout_host += n + 2; if (canonize) { int len = canonize_ip6_address(host + 1, hexparts); assert(len <= n); host[len + 1] = ']'; if (len + 2 < n + 2) host[len + 2] = '\0'; } return n + 2;}/** Return length of valid IP4 or IP6 address. */int span_ip_address(char const *host){ if (!host || !host[0]) return 0; /* IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet */ if (IS_DIGIT(host[0])) { int n = span_ip4_address(host); if (n) return n; } if (host[0] == '[') return span_ip6_reference(host); else return span_ip6_address(host);}/** Scan valid IP4/IP6 address. */int scan_ip_address(char **inout_host){ char *host = *inout_host; if (host == NULL) return -1; /* IPv6reference = "[" IPv6address "]" */ if (host[0] == '[') return scan_ip6_reference(inout_host); if (IS_DIGIT(host[0])) { int n = scan_ip4_address(inout_host); if (n > 0) return n; } return scan_ip6_address(inout_host);}/** Return length of a valid domain label */su_inlinesize_t span_domain_label(char const *label){ /* domainlabel = alphanum / alphanum *( alphanum / "-" ) alphanum */ if (IS_ALPHANUM(*label)) { size_t n; for (n = 1; IS_ALPHANUM(label[n]) || label[n] == '-'; n++) ; if (IS_ALPHANUM(label[n - 1])) return n; } return 0;}/** Scan valid domain name and count number of labels in it. */su_inlinesize_t span_domain_labels(char const *host, size_t *return_labels){ size_t len, n, labels; int c; if (!host || !host[0]) return 0; for (n = 0, labels = 0; ; n += len) { len = span_domain_label(host + n); if (len == 0) return 0; labels++; if (host[n + len] != '.') break; len++; if (!IS_ALPHANUM(host[n + len])) break; } /* Check that last label does not start with number */ if (!IS_ALPHA(host[n])) return 0; c = host[n + len]; if (IS_ALPHANUM(c) || c == '-' || c == '.') return 0; if (return_labels) *return_labels = labels; return n + len;}/** Return length of a valid domain name. * * @code * hostname = *( domainlabel "." ) toplabel [ "." ] * domainlabel = alphanum * / alphanum *( alphanum / "-" ) alphanum * toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum * @endcode */isize_t span_domain(char const *host){ return span_domain_labels(host, NULL);}/** Scan valid domain name. */issize_t scan_domain(char **inout_host){ char *host; size_t n, labels; n = span_domain_labels(host = *inout_host, &labels); if (n == 0) return -1; /* Remove extra dot at the end of hostname */ if (labels > 1 && host[n - 1] == '.') host[n - 1] = '\0'; *inout_host += n; return n;}/** Return length of a valid domain name or IP address. */isize_t span_host(char const *host){ if (!host || !host[0]) return 0; if (host[0] == '[') return span_ip6_reference(host); if (IS_DIGIT(host[0])) { int n = span_ip4_address(host); if (n) return (isize_t)n; } return span_domain(host);}/** Scan valid domain name or IP address. */issize_t scan_host(char **inout_host){ char *host = *inout_host; if (host == NULL) return -1; /* IPv6reference = "[" IPv6address "]" */ if (host[0] == '[') return scan_ip6_reference(inout_host); if (IS_DIGIT(host[0])) { int n = scan_ip4_address(inout_host); if (n > 0) return (issize_t)n; } return scan_domain(inout_host);}#include <sofia-sip/hostdomain.h>/** Return true if @a string is valid IP4 address in dot-notation. * * @note Only 4-octet form is accepted, e.g., @c 127.1 is not considered * valid IP4 address. */int host_is_ip4_address(char const *string){ int n = span_ip4_address(string); return n > 0 && string[n] == '\0';}/** Return true if @a string is valid IP6 address in hex notation. * * E.g., fe80::1 is a valid IP6 address. */int host_is_ip6_address(char const *string){ int n = span_ip6_address(string); return n > 0 && string[n] == '\0';}int host_ip6_reference(char const *string){ return host_is_ip6_reference(string);}/** Return true if @a string is valid IP6 reference, * i.e. hex notation in square brackets. * * E.g., [::1] is a valid IP6 reference. */int host_is_ip6_reference(char const *string){ int n = span_ip6_reference(string); return n > 0 && string[n] == '\0';}/** Return true if @a string is valid IP address. * * Valid IP address is either a IP4 adddress in quad-octet notation, * IP6 hex address or IP6 reference in square brackets ([]). */int host_is_ip_address(char const *string){ int n = span_ip_address(string); return n > 0 && string[n] == '\0';}/** Return true if @a string is valid a domain name. * * Valid domain name consists of alphanumeric labels separated with * dot ("."). There can be a "-" in the middle of label. * The last label must start with a letter. * * @code * hostname = *( domainlabel "." ) toplabel [ "." ] * domainlabel = alphanum * / alphanum *( alphanum / "-" ) alphanum * toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum * @endcode */int host_is_domain(char const *string){ size_t n = string ? span_domain(string) : 0; return string && n > 0 && string[n] == '\0';}/** Return true if @a string is valid a host name. * * Check if the @a string is a domain name, IP address or IP6 reference. */int host_is_valid(char const *string){ size_t n = span_host(string); return n > 0 && string[n] == '\0';}/** Returns true if @a string is describing a local address. * * Uses the definitions of local addresses found in RFC1700 and * RFC4291. */int host_is_local(char const *host){ size_t n; if (host_is_ip6_reference(host)) return (strcmp(host, "[::1]") == 0); else if (host_is_ip6_address(host)) return (strcmp(host, "::1") == 0); else if (host_is_ip4_address(host)) return (strncmp(host, "127.", 4) == 0); n = span_domain(host); return n >= 9 /* strlen("localhost") */ && strncasecmp(host, "localhost", 9) == 0 && (n == 9 || ((n == 10 || /* localhost. */ n == 21 || /* strlen("localhost.localdomain") */ n == 22) && /* strlen("localhost.localdomain.") */ strncasecmp(host + 9, ".localdomain.", n - 9) == 0));}/** Return true if @a string has domain name in "invalid." domain. * */int host_has_domain_invalid(char const *string){ size_t n = span_domain(string); if (n >= 7 && string[n] == '\0') { static char const invalid[] = ".invalid"; if (string[n - 1] == '.') /* .invalid. perhaps? */ n--; if (n == 7 /* strlen("invalid") */) return strncasecmp(string, invalid + 1, 7) == 0; else return strncasecmp(string + n - 8, invalid, 8) == 0; } return 0;}#include <sofia-sip/su.h>static size_t convert_ip_address(char const *s, uint8_t addr[16], size_t *return_addrlen){ size_t len; int canonize = 0; char buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];#if SU_HAVE_IN6 len = span_ip6_reference(s); if (len) { assert(len - 2 < sizeof buf); assert(len > 2); if (s[len]) return 0; len = len - 2; s = memcpy(buf, s + 1, len), buf[len] = '\0'; } else len = span_ip6_address(s); if (len) { if (s[len] == '\0' && su_inet_pton(AF_INET6, s, addr) == 1) { if (SU_IN6_IS_ADDR_V4MAPPED(addr) || SU_IN6_IS_ADDR_V4COMPAT(addr)) { memcpy(addr, addr + 12, 4); return (void)(*return_addrlen = 4), len; } return (void)(*return_addrlen = 16), len; } } else#endif len = span_canonic_ip4_address(s, &canonize); if (len) { if (canonize) { char *tmp = buf; s = memcpy(tmp, s, len + 1); scan_ip4_address(&tmp); } if (s[len] == '\0' && su_inet_pton(AF_INET, s, addr) == 1) return (void)(*return_addrlen = 4), len; } return 0;}/** Compare two host names or IP addresses * * Converts valid IP addresses to the binary format before comparing them. * Note that IP6-mapped IP4 addresses and IP6-compatible IP4 addresses are * compared as IP4 addresses; that is, ::ffff:127.0.0.1, ::127.0.0.1 and * 127.0.0.1 all are all equal. * * @param a IP address or domain name * @param b IP address or domain name * * @retval -1 if a < b * @retval 0 if a == b * @retval 1 if a > b * * @since New in @VERSION_1_12_4. */int host_cmp(char const *a, char const *b){ uint8_t a6[16], b6[16]; size_t alen, blen, asize = 0, bsize = 0; int retval; if (a == NULL || b == NULL) { retval = (a != NULL) - (b != NULL); } else { alen = convert_ip_address(a, a6, &asize); blen = convert_ip_address(b, b6, &bsize); if (alen > 0 && blen > 0) { if (asize < bsize) retval = -1; else if (asize > bsize) retval = 1; else retval = memcmp(a6, b6, asize); } else { retval = strcasecmp(a, b); } } return retval;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -