1ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering/***
2ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  This file is part of avahi.
3a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  avahi is free software; you can redistribute it and/or modify it
5ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  under the terms of the GNU Lesser General Public License as
6ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  published by the Free Software Foundation; either version 2.1 of the
7ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  License, or (at your option) any later version.
8a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
9ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  avahi is distributed in the hope that it will be useful, but WITHOUT
10ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  Public License for more details.
13a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
14ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  You should have received a copy of the GNU Lesser General Public
15ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  License along with avahi; if not, write to the Free Software
16ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  USA.
18ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering***/
19ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
20eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering#ifdef HAVE_CONFIG_H
21eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering#include <config.h>
22eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering#endif
23eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering
244ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <stdlib.h>
254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <string.h>
264ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <stdio.h>
274f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include <assert.h>
284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
29b91e3b47eaed054189c45c070002f291d7d11166Lennart Poettering#include <sys/types.h>
30eee711106f721fc73a1ef50348984b7a1d9cb595Sebastien Estienne#include <netinet/in.h>
31eee711106f721fc73a1ef50348984b7a1d9cb595Sebastien Estienne
32f6712902a92eb82b6c8d7e7fd0980a20a716fa0dLennart Poettering#include <avahi-common/defs.h>
335ebf655c85076f200955458673a8bbf0dd927407Lennart Poettering#include <avahi-common/domain.h>
348e46e738cae449bf44232c66e973c8e9e15fbcb5Robert Ginda#include "avahi-common/avahi-malloc.h"
354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
364ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include "dns.h"
374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include "log.h"
384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
394f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new(unsigned mtu) {
407dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
414f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t max_size;
42c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
43602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (mtu <= 0)
443073103812f0ea376582eb0ff1479945a847b361Lennart Poettering        max_size = AVAHI_DNS_PACKET_SIZE_MAX;
45b6820898d317c29a31f97018ede6da5195d16bfbLennart Poettering    else if (mtu >= AVAHI_DNS_PACKET_EXTRA_SIZE)
46b6820898d317c29a31f97018ede6da5195d16bfbLennart Poettering        max_size = mtu - AVAHI_DNS_PACKET_EXTRA_SIZE;
47602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    else
48602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        max_size = 0;
49602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
50602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (max_size < AVAHI_DNS_PACKET_HEADER_SIZE)
517dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        max_size = AVAHI_DNS_PACKET_HEADER_SIZE;
52a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_malloc(sizeof(AvahiDnsPacket) + max_size)))
544f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return p;
55a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
567dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    p->size = p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE;
57c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    p->max_size = max_size;
584ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering    p->name_table = NULL;
59943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p->data = NULL;
60c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
617dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memset(AVAHI_DNS_PACKET_DATA(p), 0, p->size);
62c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return p;
63c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering}
64c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
654f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_query(unsigned mtu) {
667dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
67c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_dns_packet_new(mtu)))
694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
70a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
717dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
72c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return p;
73c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering}
74c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
754f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_response(unsigned mtu, int aa) {
767dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
77c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_dns_packet_new(mtu)))
794f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
80a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
818d8c0255f0f0242a067b577747740bab1b1021eaLennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(1, 0, aa, 0, 0, 0, 0, 0, 0, 0));
824ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return p;
834ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
854f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_reply(AvahiDnsPacket* p, unsigned mtu, int copy_queries, int aa) {
86602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    AvahiDnsPacket *r;
874f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
88602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
894f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(r = avahi_dns_packet_new_response(mtu, aa)))
904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
91602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
92602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (copy_queries) {
934f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        unsigned saved_rindex;
944f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint32_t n;
95602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
96602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        saved_rindex = p->rindex;
97602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE;
98a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
99602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        for (n = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); n > 0; n--) {
100602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            AvahiKey *k;
1014f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            int unicast_response;
102602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
103602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            if ((k = avahi_dns_packet_consume_key(p, &unicast_response))) {
104602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                avahi_dns_packet_append_key(r, k, unicast_response);
105602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                avahi_key_unref(k);
106602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            }
107602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        }
108602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
109602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        p->rindex = saved_rindex;
110602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
111602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_QDCOUNT, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT));
112602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    }
113602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
114602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_ID, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ID));
115602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
116602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_FLAGS,
117602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                               (avahi_dns_packet_get_field(r, AVAHI_DNS_FIELD_FLAGS) & ~AVAHI_DNS_FLAG_OPCODE) |
1188d8c0255f0f0242a067b577747740bab1b1021eaLennart Poettering                               (avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_OPCODE));
119602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
120602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    return r;
121a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering}
122602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
123602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
1247dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poetteringvoid avahi_dns_packet_free(AvahiDnsPacket *p) {
1254f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1264ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1274ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering    if (p->name_table)
1284f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        avahi_hashmap_free(p->name_table);
129a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1304f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    avahi_free(p);
1314ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1324ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1334f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringvoid avahi_dns_packet_set_field(AvahiDnsPacket *p, unsigned idx, uint16_t v) {
1344f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
136a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    ((uint16_t*) AVAHI_DNS_PACKET_DATA(p))[idx] = htons(v);
1384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1394ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1404f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint16_t avahi_dns_packet_get_field(AvahiDnsPacket *p, unsigned idx) {
1414f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1424f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
1434ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1444f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    return ntohs(((uint16_t*) AVAHI_DNS_PACKET_DATA(p))[idx]);
1454ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1464ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1474f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringvoid avahi_dns_packet_inc_field(AvahiDnsPacket *p, unsigned idx) {
1484f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1494f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
150af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering
15166142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering    avahi_dns_packet_set_field(p, idx, avahi_dns_packet_get_field(p, idx) + 1);
152a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering}
153af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering
154043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd
15572c5d38b3a671e987d59ced6396c74185e3ce660Lennart Poetteringstatic void name_table_cleanup(void *key, void *value, void *user_data) {
15672c5d38b3a671e987d59ced6396c74185e3ce660Lennart Poettering    AvahiDnsPacket *p = user_data;
157a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
15872c5d38b3a671e987d59ced6396c74185e3ce660Lennart Poettering    if ((uint8_t*) value >= AVAHI_DNS_PACKET_DATA(p) + p->size)
15972c5d38b3a671e987d59ced6396c74185e3ce660Lennart Poettering        avahi_hashmap_remove(p->name_table, key);
160043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd}
161043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd
16272c5d38b3a671e987d59ced6396c74185e3ce660Lennart Poetteringvoid avahi_dns_packet_cleanup_name_table(AvahiDnsPacket *p) {
16372c5d38b3a671e987d59ced6396c74185e3ce660Lennart Poettering    if (p->name_table)
16472c5d38b3a671e987d59ced6396c74185e3ce660Lennart Poettering        avahi_hashmap_foreach(p->name_table, name_table_cleanup, p);
165043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd}
166043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd
1674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_name(AvahiDnsPacket *p, const char *name) {
1684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d, *saved_ptr = NULL;
1694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t saved_size;
170a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1714f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1724f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(name);
1734ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
174c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    saved_size = p->size;
1757dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    saved_ptr = avahi_dns_packet_extend(p, 0);
176a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1774e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering    while (*name) {
1784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint8_t* prev;
1794f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        const char *pname;
1804f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        char label[64], *u;
181a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1824ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        /* Check whether we can compress this name. */
1834ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1844f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (p->name_table && (prev = avahi_hashmap_lookup(p->name_table, name))) {
1854f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            unsigned idx;
186a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1874f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            assert(prev >= AVAHI_DNS_PACKET_DATA(p));
1884f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            idx = (unsigned) (prev - AVAHI_DNS_PACKET_DATA(p));
1894ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            assert(idx < p->size);
1914ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
19266142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx < 0x4000) {
193973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering                uint8_t *t;
194973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering                if (!(t = (uint8_t*) avahi_dns_packet_extend(p, sizeof(uint16_t))))
1954ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering                    return NULL;
1964ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
197973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering		t[0] = (uint8_t) ((0xC000 | idx) >> 8);
198973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering		t[1] = (uint8_t) idx;
1994c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering                return saved_ptr;
2004ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering            }
2014ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        }
2024e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering
2034e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering        pname = name;
204a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
205a3596a5e3ec4937a220e6e60218639e2aba82701Lennart Poettering        if (!(avahi_unescape_label(&name, label, sizeof(label))))
206c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering            goto fail;
2074ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2087dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        if (!(d = avahi_dns_packet_append_string(p, label)))
2094e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering            goto fail;
2104c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering
2114ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        if (!p->name_table)
212a3596a5e3ec4937a220e6e60218639e2aba82701Lennart Poettering            /* This works only for normalized domain names */
2134f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            p->name_table = avahi_hashmap_new(avahi_string_hash, avahi_string_equal, avahi_free, NULL);
2144ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
2154f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (!(u = avahi_strdup(pname)))
2164f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_log_error("avahi_strdup() failed.");
2174f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        else
2184f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_hashmap_insert(p->name_table, u, d);
2194ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    }
2204ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2217dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, 1)))
222c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        goto fail;
223a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
2244e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering    *d = 0;
2254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2264c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering    return saved_ptr;
227c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
228c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poetteringfail:
229c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    p->size = saved_size;
230043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd    avahi_dns_packet_cleanup_name_table(p);
231043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd
232c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return NULL;
2334ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2344ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_uint16(AvahiDnsPacket *p, uint16_t v) {
2364f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
238a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
2394f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(d = avahi_dns_packet_extend(p, sizeof(uint16_t))))
240c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
241a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
242973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[0] = (uint8_t) (v >> 8);
243973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[1] = (uint8_t) v;
2444ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return d;
2454ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2464ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2474f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_append_uint32(AvahiDnsPacket *p, uint32_t v) {
2484f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2494f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
250c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(d = avahi_dns_packet_extend(p, sizeof(uint32_t))))
252c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
253a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
254973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[0] = (uint8_t) (v >> 24);
255973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[1] = (uint8_t) (v >> 16);
256973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[2] = (uint8_t) (v >> 8);
257973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[3] = (uint8_t) v;
25854247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
25954247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return d;
26054247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering}
26154247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2624f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_append_bytes(AvahiDnsPacket  *p, const void *b, size_t l) {
2634f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t* d;
26454247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2654f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2664f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(b);
2674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l);
2684aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
2697dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, l)))
270c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
27154247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
272c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    memcpy(d, b, l);
27354247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return d;
27454247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering}
27554247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2764f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_string(AvahiDnsPacket *p, const char *s) {
2774f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t* d;
2784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t k;
279a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
2804f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2814f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
282a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
283a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if ((k = strlen(s)) >= 255)
284a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        k = 255;
285a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
2867dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, k+1)))
287a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return NULL;
288a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2894f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    *d = (uint8_t) k;
290a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    memcpy(d+1, s, k);
291a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
292a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return d;
293a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering}
294a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2954f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_extend(AvahiDnsPacket *p, size_t l) {
2964f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
297a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
2984f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2994ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
300c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    if (p->size+l > p->max_size)
301c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
302a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3037dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    d = AVAHI_DNS_PACKET_DATA(p) + p->size;
3044ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->size += l;
305a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3064ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return d;
3074ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3084ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3091ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poetteringint avahi_dns_packet_check_valid(AvahiDnsPacket *p) {
3104f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t flags;
3114f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
3124ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3131ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (p->size < AVAHI_DNS_PACKET_HEADER_SIZE)
3144ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
3154ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3167dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS);
317a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3181ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (flags & AVAHI_DNS_FLAG_OPCODE)
3191ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        return -1;
3201ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3211ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    return 0;
3221ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering}
3231ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3241ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poetteringint avahi_dns_packet_check_valid_multicast(AvahiDnsPacket *p) {
3251ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    uint16_t flags;
3261ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    assert(p);
3274ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3281ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (avahi_dns_packet_check_valid(p) < 0)
3291ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        return -1;
330a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3311ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS);
332a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3331ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (flags & AVAHI_DNS_FLAG_RCODE)
3344ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
3354ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3364ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
3374ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3394f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_is_query(AvahiDnsPacket *p) {
3404f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
341a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3427dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return !(avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_QR);
3434ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3444ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3454f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringstatic int consume_labels(AvahiDnsPacket *p, unsigned idx, char *ret_name, size_t l) {
3464f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int ret = 0;
3474ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    int compressed = 0;
3484ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    int first_label = 1;
3495ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd    unsigned label_ptr;
35083b432c2369d7ef4142811bea0109b6588b6f313Trent Lloyd    int i;
3514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p && ret_name && l);
352a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
353451be30b300b390b46738af3fd24fc942ba3158fTrent Lloyd    for (i = 0; i < AVAHI_DNS_LABELS_MAX; i++) {
3544f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint8_t n;
3554ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
35666142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering        if (idx+1 > p->size)
3574ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return -1;
3584ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
35966142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering        n = AVAHI_DNS_PACKET_DATA(p)[idx];
3604ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3614ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        if (!n) {
36266142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx++;
3634ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3644ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret++;
3654ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3664ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (l < 1)
3674ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3684ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            *ret_name = 0;
369a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3704ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return ret;
371a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3724ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else if (n <= 63) {
3734ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            /* Uncompressed label */
37466142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx++;
3754ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3764ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret++;
377a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
37866142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx + n > p->size)
3794ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3804ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3814f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            if ((size_t) n + 1 > l)
3824ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3834ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!first_label) {
3854ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                *(ret_name++) = '.';
3864ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                l--;
3874ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            } else
3884ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                first_label = 0;
3894ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
390d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering            if (!(avahi_escape_label((char*) AVAHI_DNS_PACKET_DATA(p) + idx, n, &ret_name, &l)))
3914e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering                return -1;
3924e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering
39366142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx += n;
394a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3954ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3964ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret += n;
3974ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else if ((n & 0xC0) == 0xC0) {
3984ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            /* Compressed label */
3994ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
40066142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx+2 > p->size)
4014ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
4024ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4035ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd            label_ptr = ((unsigned) (AVAHI_DNS_PACKET_DATA(p)[idx] & ~0xC0)) << 8 | AVAHI_DNS_PACKET_DATA(p)[idx+1];
4045ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd
4055ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd            if ((label_ptr < AVAHI_DNS_PACKET_HEADER_SIZE) || (label_ptr >= idx))
4065ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd                return -1;
4075ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd
4085ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd            idx = label_ptr;
4094ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4104ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
4114ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret += 2;
412a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4134ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            compressed = 1;
4144ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else
4154ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return -1;
4164ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    }
4176e9695a1e6a5f6a70195b6de37448aaf9cde8e30Trent Lloyd
4186e9695a1e6a5f6a70195b6de37448aaf9cde8e30Trent Lloyd    return -1;
4194ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4204ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4214f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_name(AvahiDnsPacket *p, char *ret_name, size_t l) {
4224f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int r;
423a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4244ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if ((r = consume_labels(p, p->rindex, ret_name, l)) < 0)
4254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4264ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4274ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += r;
4284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4294ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4314f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_uint16(AvahiDnsPacket *p, uint16_t *ret_v) {
432973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    uint8_t *d;
433973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering
4344f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_v);
4364ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (p->rindex + sizeof(uint16_t) > p->size)
4384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4394ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
440973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d = (uint8_t*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex);
441973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    *ret_v = (d[0] << 8) | d[1];
4424f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    p->rindex += sizeof(uint16_t);
4434ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4444ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4454ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4464ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4474f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_uint32(AvahiDnsPacket *p, uint32_t *ret_v) {
448973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    uint8_t* d;
449973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering
4504f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_v);
4524ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (p->rindex + sizeof(uint32_t) > p->size)
4544ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4554ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
456973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d = (uint8_t*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex);
457973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    *ret_v = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
4584f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    p->rindex += sizeof(uint32_t);
459a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4604ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4614ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4624ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4634f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_bytes(AvahiDnsPacket *p, void * ret_data, size_t l) {
4644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4654f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_data);
4664f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l > 0);
467a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4684ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if (p->rindex + l > p->size)
4694ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4704ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4717dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memcpy(ret_data, AVAHI_DNS_PACKET_DATA(p) + p->rindex, l);
4724ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += l;
4734ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4744ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4754ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4764ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4774f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_string(AvahiDnsPacket *p, char *ret_string, size_t l) {
4784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t k;
479a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4804f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4814f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_string);
4824f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l > 0);
483a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
484a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex >= p->size)
485a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return -1;
486a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4877dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    k = AVAHI_DNS_PACKET_DATA(p)[p->rindex];
488a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
489a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex+1+k > p->size)
490a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return -1;
491a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
492a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (l > k+1)
493a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        l = k+1;
494a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4957dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memcpy(ret_string, AVAHI_DNS_PACKET_DATA(p)+p->rindex+1, l-1);
496a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    ret_string[l-1] = 0;
497a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
498a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    p->rindex += 1+k;
499a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
500a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return 0;
501a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering}
502a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5034f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringconst void* avahi_dns_packet_get_rptr(AvahiDnsPacket *p) {
5044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
505a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
506a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex > p->size)
507f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
508f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
5097dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return AVAHI_DNS_PACKET_DATA(p) + p->rindex;
510f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
511f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
5124f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_skip(AvahiDnsPacket *p, size_t length) {
5134f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
5144ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
5154ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if (p->rindex + length > p->size)
5164ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
5174ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
5184ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += length;
5194ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
5204ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
521f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
522943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringstatic int parse_rdata(AvahiDnsPacket *p, AvahiRecord *r, uint16_t rdlength) {
523943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    char buf[AVAHI_DOMAIN_NAME_MAX];
5244f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    const void* start;
525a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
527943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(r);
528f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
5297dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    start = avahi_dns_packet_get_rptr(p);
530a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
531943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    switch (r->key->type) {
5327dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_PTR:
5337dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_CNAME:
534d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering        case AVAHI_DNS_TYPE_NS:
535a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5367dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
537943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
538a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5394f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.ptr.name = avahi_strdup(buf);
540a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
541a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
542a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5437dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_SRV:
544a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5457dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_uint16(p, &r->data.srv.priority) < 0 ||
5467dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_uint16(p, &r->data.srv.weight) < 0 ||
5477dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_uint16(p, &r->data.srv.port) < 0 ||
5487dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
549943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
550a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.srv.name = avahi_strdup(buf);
552a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
553a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5547dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_HINFO:
555a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5567dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0)
557943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
558a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5594f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.hinfo.cpu = avahi_strdup(buf);
560a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5617dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0)
562943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
563a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.hinfo.os = avahi_strdup(buf);
565c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
566c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5677dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_TXT:
568a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
569a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            if (rdlength > 0) {
57020011324500a728851e4888c890a756ecf71394bLennart Poettering                if (avahi_string_list_parse(avahi_dns_packet_get_rptr(p), rdlength, &r->data.txt.string_list) < 0)
57120011324500a728851e4888c890a756ecf71394bLennart Poettering                    return -1;
572a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5737dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                if (avahi_dns_packet_skip(p, rdlength) < 0)
574943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                    return -1;
575fc174c871b4f85e558766c1ca55661fa7b1b4c9aLennart Poettering            } else
576fc174c871b4f85e558766c1ca55661fa7b1b4c9aLennart Poettering                r->data.txt.string_list = NULL;
577a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
578a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
579a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5807dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_A:
581a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
582c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("A"); */
583c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5847dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_bytes(p, &r->data.a.address, sizeof(AvahiIPv4Address)) < 0)
585943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
586a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
587a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
588a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5897dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_AAAA:
590a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
591c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("aaaa"); */
592a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5937dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_bytes(p, &r->data.aaaa.address, sizeof(AvahiIPv6Address)) < 0)
594943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
595a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
596c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
597a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
598c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        default:
5994aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
600c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("generic"); */
601a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
6024aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering            if (rdlength > 0) {
6034aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
6044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering                r->data.generic.data = avahi_memdup(avahi_dns_packet_get_rptr(p), rdlength);
605a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering                r->data.generic.size = rdlength;
606a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
6077dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                if (avahi_dns_packet_skip(p, rdlength) < 0)
608943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                    return -1;
609a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            }
610c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
611c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
612c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    }
613c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
614a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    /* Check if we read enough data */
6154f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if ((const uint8_t*) avahi_dns_packet_get_rptr(p) - (const uint8_t*) start != rdlength)
616943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        return -1;
617a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
618943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return 0;
619943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
620943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
621943a6b93697fc0a7bcd0cc574744d7de609c189cLennart PoetteringAvahiRecord* avahi_dns_packet_consume_record(AvahiDnsPacket *p, int *ret_cache_flush) {
622943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    char name[AVAHI_DOMAIN_NAME_MAX];
623943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint16_t type, class;
624943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint32_t ttl;
625943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint16_t rdlength;
626943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    AvahiRecord *r = NULL;
627943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
628943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(p);
629943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
630943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
631943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint16(p, &type) < 0 ||
632943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint16(p, &class) < 0 ||
633943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint32(p, &ttl) < 0 ||
634943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint16(p, &rdlength) < 0 ||
635943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        p->rindex + rdlength > p->size)
636a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        goto fail;
637a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
638943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (ret_cache_flush)
639943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        *ret_cache_flush = !!(class & AVAHI_DNS_CACHE_FLUSH);
640943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    class &= ~AVAHI_DNS_CACHE_FLUSH;
641a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
642943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (!(r = avahi_record_new_full(name, class, type, ttl)))
643943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
644a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
645943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (parse_rdata(p, r, rdlength) < 0)
646943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
6477e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering
6487e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    if (!avahi_record_is_valid(r))
6497e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        goto fail;
650a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
651a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return r;
652a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
653a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poetteringfail:
654a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (r)
6557dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_record_unref(r);
656a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
657a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return NULL;
658f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
659f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6604f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiKey* avahi_dns_packet_consume_key(AvahiDnsPacket *p, int *ret_unicast_response) {
6614f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    char name[256];
6624f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t type, class;
6637e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    AvahiKey *k;
664f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6654f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
666f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6677dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
6687dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &type) < 0 ||
6697dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &class) < 0)
670f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
671f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6721ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (ret_unicast_response)
6731ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        *ret_unicast_response = !!(class & AVAHI_DNS_UNICAST_RESPONSE);
674f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6751ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    class &= ~AVAHI_DNS_UNICAST_RESPONSE;
676a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
6777e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    if (!(k = avahi_key_new(name, class, type)))
6787e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        return NULL;
6797e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering
6807e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    if (!avahi_key_is_valid(k)) {
6817e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        avahi_key_unref(k);
6827e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        return NULL;
6837e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    }
6847e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering
6857e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    return k;
686f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
687f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6884f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_key(AvahiDnsPacket *p, AvahiKey *k, int unicast_response) {
6894f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *t;
6904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t size;
691a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
6924f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
6934f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(k);
694f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
695d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    size = p->size;
696a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
6977dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(t = avahi_dns_packet_append_name(p, k->name)) ||
6987dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        !avahi_dns_packet_append_uint16(p, k->type) ||
69914f8d9beb7ef14b0aab5512345e09109bdd8cb0cLennart Poettering        !avahi_dns_packet_append_uint16(p, k->clazz | (unicast_response ? AVAHI_DNS_UNICAST_RESPONSE : 0))) {
700d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering        p->size = size;
701043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd        avahi_dns_packet_cleanup_name_table(p);
702043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd
703f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
704d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    }
705f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
706f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering    return t;
707f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
708f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
709943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringstatic int append_rdata(AvahiDnsPacket *p, AvahiRecord *r) {
7104f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
7114f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(r);
712a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
713c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    switch (r->key->type) {
714a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
7157dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_PTR:
716d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering        case AVAHI_DNS_TYPE_CNAME:
717d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering        case AVAHI_DNS_TYPE_NS:
718a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
7197dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!(avahi_dns_packet_append_name(p, r->data.ptr.name)))
720943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
721a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
722a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
723a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7247dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_SRV:
725a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7267dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_uint16(p, r->data.srv.priority) ||
7277dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_uint16(p, r->data.srv.weight) ||
7287dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_uint16(p, r->data.srv.port) ||
7297dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_name(p, r->data.srv.name))
730943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
731c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
732c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
733c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
7347dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_HINFO:
7357dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_string(p, r->data.hinfo.cpu) ||
7367dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_string(p, r->data.hinfo.os))
737943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
738a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
739a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
740a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7417dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_TXT: {
742a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7434f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            uint8_t *data;
7444f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            size_t n;
745c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
74666142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            n = avahi_string_list_serialize(r->data.txt.string_list, NULL, 0);
747c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
74866142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (!(data = avahi_dns_packet_extend(p, n)))
749943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
750c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
75166142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            avahi_string_list_serialize(r->data.txt.string_list, data, n);
752c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
753c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        }
754c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
755a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7567dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_A:
757a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7587dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_bytes(p, &r->data.a.address, sizeof(r->data.a.address)))
759943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
760a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
761a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
762a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7637dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_AAAA:
764a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
7657dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_bytes(p, &r->data.aaaa.address, sizeof(r->data.aaaa.address)))
766943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
767a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
768a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
769a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
770c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        default:
771a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
772943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering            if (r->data.generic.size)
773b7e1f69e270e38642305d9064e9ca8051419b52cLennart Poettering                if (!avahi_dns_packet_append_bytes(p, r->data.generic.data, r->data.generic.size))
774943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                    return -1;
775a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
776a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
777c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    }
778c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
779943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return 0;
780943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
781943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
782a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
783943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringuint8_t* avahi_dns_packet_append_record(AvahiDnsPacket *p, AvahiRecord *r, int cache_flush, unsigned max_ttl) {
784943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint8_t *t, *l, *start;
785943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    size_t size;
786943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
787943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(p);
788943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(r);
789943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
790943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    size = p->size;
791943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
792943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (!(t = avahi_dns_packet_append_name(p, r->key->name)) ||
793943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !avahi_dns_packet_append_uint16(p, r->key->type) ||
794943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !avahi_dns_packet_append_uint16(p, cache_flush ? (r->key->clazz | AVAHI_DNS_CACHE_FLUSH) : (r->key->clazz &~ AVAHI_DNS_CACHE_FLUSH)) ||
795943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !avahi_dns_packet_append_uint32(p, (max_ttl && r->ttl > max_ttl) ? max_ttl : r->ttl) ||
796943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !(l = avahi_dns_packet_append_uint16(p, 0)))
797943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
798943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
799943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    start = avahi_dns_packet_extend(p, 0);
800a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
801943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (append_rdata(p, r) < 0)
802943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
803a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
8047dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    size = avahi_dns_packet_extend(p, 0) - start;
805bbf6b92f662ed909d5b4fca4a43b19e815812b3eLennart Poettering    assert(size <= AVAHI_DNS_RDATA_MAX);
806a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
807c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*     avahi_log_debug("appended %u", size); */
808a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
809973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    l[0] = (uint8_t) ((uint16_t) size >> 8);
810973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    l[1] = (uint8_t) ((uint16_t) size);
811a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
81254247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return t;
813d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
814d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
815d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poetteringfail:
816d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    p->size = size;
817043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd    avahi_dns_packet_cleanup_name_table(p);
818043eb084c1c76f5b62fc1745942bddfddf17fbf1Trent Lloyd
819d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    return NULL;
820d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering}
821d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
8224f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_is_empty(AvahiDnsPacket *p) {
8234f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
824d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
8257dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return p->size <= AVAHI_DNS_PACKET_HEADER_SIZE;
826f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
8270a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
8284f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringsize_t avahi_dns_packet_space(AvahiDnsPacket *p) {
8294f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
8300a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
8314f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p->size <= p->max_size);
832a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
8330a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering    return p->max_size - p->size;
8340a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering}
835943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
836943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringint avahi_rdata_parse(AvahiRecord *record, const void* rdata, size_t size) {
837943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    int ret;
838943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    AvahiDnsPacket p;
839a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
840943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(record);
841943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(rdata);
842a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
843943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.data = (void*) rdata;
844943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.max_size = p.size = size;
845943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.rindex = 0;
846943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.name_table = NULL;
847943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
848943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    ret = parse_rdata(&p, record, size);
849943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
850943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(!p.name_table);
851a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
852943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return ret;
853943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
854943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
855943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringsize_t avahi_rdata_serialize(AvahiRecord *record, void *rdata, size_t max_size) {
856943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    int ret;
857943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    AvahiDnsPacket p;
858a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
859943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(record);
860943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(rdata);
861943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(max_size > 0);
862943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
863943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.data = (void*) rdata;
864943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.max_size = max_size;
865943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.size = p.rindex = 0;
866943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.name_table = NULL;
867943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
868943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    ret = append_rdata(&p, record);
869943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
870943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (p.name_table)
871943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering         avahi_hashmap_free(p.name_table);
872943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
873943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (ret < 0)
874943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        return (size_t) -1;
875a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
876943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return p.size;
877943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
878