From 9962a048634c590db23a00db1d01daada779844c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 24 Jun 2005 19:02:51 +0000 Subject: * implement new source address check mechanisms * introduce new types AvahiIfIndex and AvahiProtocol to abstract underlying OS structures a bit * document string list, address and other stuff * implement qclass = ANY queries * don't make use of UTF8 collation as RFC mandates git-svn-id: file:///home/lennart/svn/public/avahi/trunk@144 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-common/address.c | 14 +++++++------- avahi-common/address.h | 52 +++++++++++++++++++++++++++++++++++++++++++------- avahi-common/rr.c | 23 +++++++++++++--------- avahi-common/rr.h | 1 + avahi-common/strlst.c | 4 ++-- avahi-common/strlst.h | 44 +++++++++++++++++++++++++++++++++++++----- avahi-common/util.c | 41 +++++++-------------------------------- 7 files changed, 115 insertions(+), 64 deletions(-) (limited to 'avahi-common') diff --git a/avahi-common/address.c b/avahi-common/address.c index 3e6fc97..b982a2c 100644 --- a/avahi-common/address.c +++ b/avahi-common/address.c @@ -33,9 +33,9 @@ guint avahi_address_get_size(const AvahiAddress *a) { g_assert(a); - if (a->family == AF_INET) + if (a->family == AVAHI_PROTO_INET) return 4; - else if (a->family == AF_INET6) + else if (a->family == AVAHI_PROTO_INET6) return 16; return 0; @@ -111,18 +111,18 @@ gchar *avahi_reverse_lookup_name_ipv6_int(const AvahiIPv6Address *a) { return reverse_lookup_name_ipv6(a, "ip6.int"); } -AvahiAddress *avahi_address_parse(const char *s, guchar family, AvahiAddress *ret_addr) { +AvahiAddress *avahi_address_parse(const gchar *s, AvahiProtocol family, AvahiAddress *ret_addr) { g_assert(ret_addr); g_assert(s); - if (family == AF_UNSPEC) { + if (family == AVAHI_PROTO_UNSPEC) { if (inet_pton(AF_INET, s, ret_addr->data.data) <= 0) { if (inet_pton(AF_INET6, s, ret_addr->data.data) <= 0) return NULL; else - ret_addr->family = AF_INET6; + ret_addr->family = AVAHI_PROTO_INET6; } else - ret_addr->family = AF_INET; + ret_addr->family = AVAHI_PROTO_INET; } else { if (inet_pton(family, s, ret_addr->data.data) <= 0) return NULL; @@ -168,7 +168,7 @@ gboolean avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a) { g_assert(a); - if (a->family != AF_INET6) + if (a->family != AVAHI_PROTO_INET6) return FALSE; return memcmp(a->data.ipv6.address, ipv4_in_ipv6, sizeof(ipv4_in_ipv6)) == 0; diff --git a/avahi-common/address.h b/avahi-common/address.h index 22cb74b..4b5fb27 100644 --- a/avahi-common/address.h +++ b/avahi-common/address.h @@ -25,38 +25,76 @@ #include #include +/** Protocol family specification, takes the values AVAHI_INET, AVAHI_INET6, AVAHI_UNSPEC */ +typedef guchar AvahiProtocol; + +/** Numeric network interface index. Takes OS dependent values and the special constant AVAHI_IF_UNSPEC */ +typedef gint AvahiIfIndex; + +/** Values for AvahiProtocol */ +enum { + AVAHI_PROTO_INET = AF_INET, /**< IPv4 */ + AVAHI_PROTO_INET6 = AF_INET6, /**< IPv6 */ + AVAHI_PROTO_UNSPEC = AF_UNSPEC /**< Unspecified/all protocol(s) */ +}; + +/** Special values for AvahiIfIndex */ +enum { + AVAHI_IF_UNSPEC = -1 /**< Unspecifed/all interfaces */ +}; + +/** An IPv4 address */ typedef struct { - guint32 address; + guint32 address; /**< Address data in network byte order. */ } AvahiIPv4Address; +/** An IPv6 address */ typedef struct { - guint8 address[16]; + guint8 address[16]; /**< Address data */ } AvahiIPv6Address; +/** Protocol (address family) independant address structure */ typedef struct { - guchar family; + AvahiProtocol family; /**< Address family */ union { - AvahiIPv6Address ipv6; - AvahiIPv4Address ipv4; - guint8 data[1]; + AvahiIPv6Address ipv6; /** Address when IPv6 */ + AvahiIPv4Address ipv4; /** Address when IPv4 */ + guint8 data[1]; /** Type independant data field */ } data; } AvahiAddress; +/** Return the address data size of the specified address. (4 for IPv4, 16 for IPv6) */ guint avahi_address_get_size(const AvahiAddress *a); + +/** Compare two addresses. Returns 0 when equal, a negative value when a < b, a positive value when a > b. */ gint avahi_address_cmp(const AvahiAddress *a, const AvahiAddress *b); +/** Convert the specified address *a to a human readable character string */ gchar *avahi_address_snprint(char *ret_s, guint length, const AvahiAddress *a); -AvahiAddress *avahi_address_parse(const char *s, guchar family, AvahiAddress *ret_addr); +/** Convert the specifeid human readable character string to an + * address structure. Set af to AVAHI_UNSPEC for automatic address + * family detection. */ +AvahiAddress *avahi_address_parse(const char *s, AvahiProtocol af, AvahiAddress *ret_addr); +/** Make an address structture of a sockaddr structure */ AvahiAddress *avahi_address_from_sockaddr(const struct sockaddr* sa, AvahiAddress *ret_addr); + +/** Return the port number of a sockaddr structure (either IPv4 or IPv6) */ guint16 avahi_port_from_sockaddr(const struct sockaddr* sa); +/** Generate the DNS reverse lookup name for an IPv4 address. g_free() the result! */ gchar* avahi_reverse_lookup_name_ipv4(const AvahiIPv4Address *a); + +/** Generate the modern DNS reverse lookup name for an IPv6 address, ending in ipv6.arpa. g_free() the result! */ gchar* avahi_reverse_lookup_name_ipv6_arpa(const AvahiIPv6Address *a); + +/** Generate the historic DNS reverse lookup name for an IPv6 address, ending in ipv6.int. g_free() the result! */ gchar* avahi_reverse_lookup_name_ipv6_int(const AvahiIPv6Address *a); +/** Check whether the specified IPv6 address is in fact an + * encapsulated IPv4 address */ gboolean avahi_address_is_ipv4_in_ipv6(const AvahiAddress *a); #endif diff --git a/avahi-common/rr.c b/avahi-common/rr.c index 7e974c4..13160fc 100644 --- a/avahi-common/rr.c +++ b/avahi-common/rr.c @@ -148,11 +148,15 @@ void avahi_record_unref(AvahiRecord *r) { const gchar *avahi_dns_class_to_string(guint16 class) { if (class & AVAHI_DNS_CACHE_FLUSH) return "FLUSH"; - - if (class == AVAHI_DNS_CLASS_IN) - return "IN"; - return NULL; + switch (class) { + case AVAHI_DNS_CLASS_IN: + return "IN"; + case AVAHI_DNS_CLASS_ANY: + return "ANY"; + default: + return NULL; + } } const gchar *avahi_dns_type_to_string(guint16 type) { @@ -266,16 +270,17 @@ gboolean avahi_key_pattern_match(const AvahiKey *pattern, const AvahiKey *k) { return avahi_domain_equal(pattern->name, k->name) && (pattern->type == k->type || pattern->type == AVAHI_DNS_TYPE_ANY) && - pattern->class == k->class; + (pattern->class == k->class || pattern->type == AVAHI_DNS_CLASS_ANY); } gboolean avahi_key_is_pattern(const AvahiKey *k) { g_assert(k); - return k->type == AVAHI_DNS_TYPE_ANY; + return + k->type == AVAHI_DNS_TYPE_ANY || + k->class == AVAHI_DNS_CLASS_ANY; } - guint avahi_key_hash(const AvahiKey *k) { g_assert(k); @@ -313,8 +318,8 @@ static gboolean rdata_equal(const AvahiRecord *a, const AvahiRecord *b) { case AVAHI_DNS_TYPE_HINFO: return - !g_utf8_collate(a->data.hinfo.cpu, b->data.hinfo.cpu) && - !g_utf8_collate(a->data.hinfo.os, b->data.hinfo.os); + !strcmp(a->data.hinfo.cpu, b->data.hinfo.cpu) && + !strcmp(a->data.hinfo.os, b->data.hinfo.os); case AVAHI_DNS_TYPE_TXT: return avahi_string_list_equal(a->data.txt.string_list, b->data.txt.string_list); diff --git a/avahi-common/rr.h b/avahi-common/rr.h index 404cc21..da0b285 100644 --- a/avahi-common/rr.h +++ b/avahi-common/rr.h @@ -43,6 +43,7 @@ enum { enum { AVAHI_DNS_CLASS_IN = 0x01, + AVAHI_DNS_CLASS_ANY = 0xFF, AVAHI_DNS_CACHE_FLUSH = 0x8000, AVAHI_DNS_UNICAST_RESPONSE = 0x8000 }; diff --git a/avahi-common/strlst.c b/avahi-common/strlst.c index 866618f..0853414 100644 --- a/avahi-common/strlst.c +++ b/avahi-common/strlst.c @@ -176,7 +176,7 @@ guint avahi_string_list_serialize(AvahiStringList *l, gpointer data, guint size) return used; } -gboolean avahi_string_list_equal(AvahiStringList *a, AvahiStringList *b) { +gboolean avahi_string_list_equal(const AvahiStringList *a, const AvahiStringList *b) { for (;;) { if (!a && !b) @@ -235,7 +235,7 @@ AvahiStringList *avahi_string_list_new_va(va_list va) { return avahi_string_list_add_many_va(NULL, va); } -AvahiStringList *avahi_string_list_copy(AvahiStringList *l) { +AvahiStringList *avahi_string_list_copy(const AvahiStringList *l) { AvahiStringList *r = NULL; for (; l; l = l->next) diff --git a/avahi-common/strlst.h b/avahi-common/strlst.h index 80dfc2c..4fde8eb 100644 --- a/avahi-common/strlst.h +++ b/avahi-common/strlst.h @@ -24,30 +24,64 @@ #include +/** Linked list of strings that can contain any number of binary + * characters, include NUL bytes. An empty list is created by + * assigning a NULL to a pointer to AvahiStringList. The string list + * is stored in reverse order, so that appending to the string list is + * effectively a prepending to the linked list. This object is used + * primarily for storing DNS TXT record data. */ typedef struct AvahiStringList { - struct AvahiStringList *next; - guint size; - guint8 text[1]; + struct AvahiStringList *next; /**< Pointe to the next linked list element */ + guint size; /**< Size of text[] */ + guint8 text[1]; /**< Character data */ } AvahiStringList; +/** Create a new string list by taking a variable list of NUL + * terminated strings. The strings are copied using g_strdup(). The + * argument list must be terminated by a NULL pointer. */ AvahiStringList *avahi_string_list_new(const gchar *txt, ...); + +/** Same as avahi_string_list_new() but pass a va_list structure */ AvahiStringList *avahi_string_list_new_va(va_list va); +/** Free a string list */ void avahi_string_list_free(AvahiStringList *l); +/** Append a NUL terminated string to the specified string list. The + * passed string is copied using g_strdup(). Returns the new list + * start. */ AvahiStringList *avahi_string_list_add(AvahiStringList *l, const gchar *text); + +/** Append am arbitrary length byte string to the list. Returns the + * new list start. */ AvahiStringList *avahi_string_list_add_arbitrary(AvahiStringList *l, const guint8 *text, guint size); + +/** Same as avahi_string_list_add(), but takes a variable number of + * NUL terminated strings. The argument list must be terminated by a + * NULL pointer. Returns the new list start. */ AvahiStringList *avahi_string_list_add_many(AvahiStringList *r, ...); + +/** Same as avahi_string_list_add_many(), but use a va_list + * structure. Returns the new list start. */ AvahiStringList *avahi_string_list_add_many_va(AvahiStringList *r, va_list va); +/** Convert the string list object to a single character string, + * seperated by spaces and enclosed in "". g_free() the result! This + * function doesn't work well with string that contain NUL bytes. */ gchar* avahi_string_list_to_string(AvahiStringList *l); +/** Serialize the string list object in a way that is compatible with + * the storing of DNS TXT records. Strings longer than 255 bytes are truncated. */ guint avahi_string_list_serialize(AvahiStringList *l, gpointer data, guint size); + +/** Inverse of avahi_string_list_serialize() */ AvahiStringList *avahi_string_list_parse(gconstpointer data, guint size); -gboolean avahi_string_list_equal(AvahiStringList *a, AvahiStringList *b); +/** Compare to string lists */ +gboolean avahi_string_list_equal(const AvahiStringList *a, const AvahiStringList *b); -AvahiStringList *avahi_string_list_copy(AvahiStringList *l); +/** Copy a string list */ +AvahiStringList *avahi_string_list_copy(const AvahiStringList *l); #endif diff --git a/avahi-common/util.c b/avahi-common/util.c index a41475a..baf5527 100644 --- a/avahi-common/util.c +++ b/avahi-common/util.c @@ -79,25 +79,18 @@ static gchar *unescape_uneeded(const gchar *src, gchar *ret_dest, size_t size) { gchar *avahi_normalize_name(const gchar *s) { gchar tmp[256]; - gchar *n, *t; guint l; g_assert(s); unescape_uneeded(s, tmp, sizeof(tmp)); - n = g_utf8_normalize(tmp, -1, G_NORMALIZE_DEFAULT); - - if ((l = strlen(n)) == 0) { - g_free(n); + if ((l = strlen(tmp)) == 0) return g_strdup("."); - } - if (n[l-1] == '.') - return n; + if (tmp[l-1] == '.') + return g_strdup(tmp); - t = g_strdup_printf("%s.", n); - g_free(n); - return t; + return g_strdup_printf("%s.", tmp); } gint avahi_timeval_compare(const GTimeVal *a, const GTimeVal *b) { @@ -280,22 +273,6 @@ gchar *avahi_escape_label(const guint8* src, guint src_length, gchar **ret_name, return r; } -static gint utf8_strcasecmp(const gchar *a, const gchar *b) { - gchar *ta, *tb; - gint r; - - g_assert(a); - g_assert(b); - - ta = g_utf8_casefold(a, -1); - tb = g_utf8_casefold(b, -1); - r = g_utf8_collate(ta, tb); - g_free(ta); - g_free(tb); - - return r; -} - gboolean avahi_domain_equal(const gchar *a, const gchar *b) { g_assert(a); g_assert(b); @@ -314,7 +291,7 @@ gboolean avahi_domain_equal(const gchar *a, const gchar *b) { else if ((pa && !pb) || (!pa && pb)) return FALSE; - if (utf8_strcasecmp(pa, pb)) + if (g_ascii_strcasecmp(pa, pb)) return FALSE; } @@ -385,7 +362,7 @@ guint avahi_domain_hash(const gchar *s) { guint hash = 0; for (;;) { - gchar c[65], *n, *m; + gchar c[65], *m; if (!avahi_unescape_label(&s, c, sizeof(c))) return hash; @@ -393,13 +370,9 @@ guint avahi_domain_hash(const gchar *s) { if (!c[0]) continue; - n = g_utf8_normalize(c, -1, G_NORMALIZE_DEFAULT); - m = g_utf8_strdown(n, -1); - + m = g_ascii_strdown(c, -1); hash += g_str_hash(m); - g_free(m); - g_free(n); } } -- cgit