dns.c revision bbf6b92f662ed909d5b4fca4a43b19e815812b3e
1ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering/* $Id$ */
2ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
3ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering/***
4ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  This file is part of avahi.
5ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
6ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  avahi is free software; you can redistribute it and/or modify it
7ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  under the terms of the GNU Lesser General Public License as
8ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  published by the Free Software Foundation; either version 2.1 of the
9ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  License, or (at your option) any later version.
10ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
11ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  avahi is distributed in the hope that it will be useful, but WITHOUT
12ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  Public License for more details.
15ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
16ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  You should have received a copy of the GNU Lesser General Public
17ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  License along with avahi; if not, write to the Free Software
18ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering  USA.
20ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering***/
21ab84bbc4bef07413f95c3237e29f2287319e0f4cLennart Poettering
22eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering#ifdef HAVE_CONFIG_H
23eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering#include <config.h>
24eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering#endif
25eca309458f9521a2e3276dc11a1792d5f2e227e4Lennart Poettering
264ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <stdlib.h>
274ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <string.h>
284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include <stdio.h>
294f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include <assert.h>
304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
31b91e3b47eaed054189c45c070002f291d7d11166Lennart Poettering#include <sys/types.h>
32eee711106f721fc73a1ef50348984b7a1d9cb595Sebastien Estienne#include <netinet/in.h>
33eee711106f721fc73a1ef50348984b7a1d9cb595Sebastien Estienne
34f6712902a92eb82b6c8d7e7fd0980a20a716fa0dLennart Poettering#include <avahi-common/defs.h>
355ebf655c85076f200955458673a8bbf0dd927407Lennart Poettering#include <avahi-common/domain.h>
364f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include <avahi-common/malloc.h>
374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering#include "dns.h"
394f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering#include "log.h"
404ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
414f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new(unsigned mtu) {
427dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
434f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t max_size;
44c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
45602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (mtu <= 0)
463073103812f0ea376582eb0ff1479945a847b361Lennart Poettering        max_size = AVAHI_DNS_PACKET_SIZE_MAX;
47b6820898d317c29a31f97018ede6da5195d16bfbLennart Poettering    else if (mtu >= AVAHI_DNS_PACKET_EXTRA_SIZE)
48b6820898d317c29a31f97018ede6da5195d16bfbLennart Poettering        max_size = mtu - AVAHI_DNS_PACKET_EXTRA_SIZE;
49602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    else
50602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        max_size = 0;
51602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
52602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (max_size < AVAHI_DNS_PACKET_HEADER_SIZE)
537dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        max_size = AVAHI_DNS_PACKET_HEADER_SIZE;
54c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
554f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_malloc(sizeof(AvahiDnsPacket) + max_size)))
564f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return p;
574f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
587dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    p->size = p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE;
59c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    p->max_size = max_size;
604ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering    p->name_table = NULL;
61943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p->data = NULL;
62c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
637dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memset(AVAHI_DNS_PACKET_DATA(p), 0, p->size);
64c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return p;
65c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering}
66c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
674f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_query(unsigned mtu) {
687dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
69c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
704f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_dns_packet_new(mtu)))
714f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
724f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
737dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(0, 0, 0, 0, 0, 0, 0, 0, 0, 0));
74c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return p;
75c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering}
76c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
774f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_response(unsigned mtu, int aa) {
787dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    AvahiDnsPacket *p;
79c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
804f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(p = avahi_dns_packet_new(mtu)))
814f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
824f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
838d8c0255f0f0242a067b577747740bab1b1021eaLennart Poettering    avahi_dns_packet_set_field(p, AVAHI_DNS_FIELD_FLAGS, AVAHI_DNS_FLAGS(1, 0, aa, 0, 0, 0, 0, 0, 0, 0));
844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return p;
854ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
864ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
874f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiDnsPacket* avahi_dns_packet_new_reply(AvahiDnsPacket* p, unsigned mtu, int copy_queries, int aa) {
88602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    AvahiDnsPacket *r;
894f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
90602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
914f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(r = avahi_dns_packet_new_response(mtu, aa)))
924f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        return NULL;
93602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
94602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    if (copy_queries) {
954f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        unsigned saved_rindex;
964f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint32_t n;
97602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
98602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        saved_rindex = p->rindex;
99602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        p->rindex = AVAHI_DNS_PACKET_HEADER_SIZE;
100602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
101602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        for (n = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); n > 0; n--) {
102602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            AvahiKey *k;
1034f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            int unicast_response;
104602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
105602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            if ((k = avahi_dns_packet_consume_key(p, &unicast_response))) {
106602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                avahi_dns_packet_append_key(r, k, unicast_response);
107602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                avahi_key_unref(k);
108602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering            }
109602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        }
110602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
111602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        p->rindex = saved_rindex;
112602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
113602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering        avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_QDCOUNT, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT));
114602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    }
115602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
116602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_ID, avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_ID));
117602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
118602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    avahi_dns_packet_set_field(r, AVAHI_DNS_FIELD_FLAGS,
119602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering                               (avahi_dns_packet_get_field(r, AVAHI_DNS_FIELD_FLAGS) & ~AVAHI_DNS_FLAG_OPCODE) |
1208d8c0255f0f0242a067b577747740bab1b1021eaLennart Poettering                               (avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_OPCODE));
121602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
122602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering    return r;
123602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering}
124602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
125602a2b6481587b7da2594db39151ec9380f276dfLennart Poettering
1267dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poetteringvoid avahi_dns_packet_free(AvahiDnsPacket *p) {
1274f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1284ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1294ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering    if (p->name_table)
1304f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        avahi_hashmap_free(p->name_table);
1314ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1324f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    avahi_free(p);
1334ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1344ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringvoid avahi_dns_packet_set_field(AvahiDnsPacket *p, unsigned idx, uint16_t v) {
1364f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
1384ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1394f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    ((uint16_t*) AVAHI_DNS_PACKET_DATA(p))[idx] = htons(v);
1404ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1414ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1424f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint16_t avahi_dns_packet_get_field(AvahiDnsPacket *p, unsigned idx) {
1434f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1444f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
1454ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1464f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    return ntohs(((uint16_t*) AVAHI_DNS_PACKET_DATA(p))[idx]);
1474ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
1484ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1494f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringvoid avahi_dns_packet_inc_field(AvahiDnsPacket *p, unsigned idx) {
1504f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(idx < AVAHI_DNS_PACKET_HEADER_SIZE);
152af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering
15366142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering    avahi_dns_packet_set_field(p, idx, avahi_dns_packet_get_field(p, idx) + 1);
154af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering}
155af1ce5fe2245fba0045d2c0d70b58b700938bd2fLennart Poettering
1564f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_name(AvahiDnsPacket *p, const char *name) {
1574f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d, *saved_ptr = NULL;
1584f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t saved_size;
1594ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1604f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
1614f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(name);
1624ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
163c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    saved_size = p->size;
1647dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    saved_ptr = avahi_dns_packet_extend(p, 0);
1654c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering
1664e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering    while (*name) {
1674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint8_t* prev;
1684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        const char *pname;
1694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        char label[64], *u;
1704f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering
1714ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        /* Check whether we can compress this name. */
1724ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1734f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (p->name_table && (prev = avahi_hashmap_lookup(p->name_table, name))) {
1744f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            unsigned idx;
1754ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1764f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            assert(prev >= AVAHI_DNS_PACKET_DATA(p));
1774f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            idx = (unsigned) (prev - AVAHI_DNS_PACKET_DATA(p));
1784ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
1794f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            assert(idx < p->size);
1804ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
18166142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx < 0x4000) {
182973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering                uint8_t *t;
183973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering                if (!(t = (uint8_t*) avahi_dns_packet_extend(p, sizeof(uint16_t))))
1844ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering                    return NULL;
1854ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
186973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering		t[0] = (uint8_t) ((0xC000 | idx) >> 8);
187973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering		t[1] = (uint8_t) idx;
1884c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering                return saved_ptr;
1894ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering            }
1904ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        }
1914e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering
1924e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering        pname = name;
1934ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
194a3596a5e3ec4937a220e6e60218639e2aba82701Lennart Poettering        if (!(avahi_unescape_label(&name, label, sizeof(label))))
195c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering            goto fail;
1964ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
1977dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        if (!(d = avahi_dns_packet_append_string(p, label)))
1984e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering            goto fail;
1994c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering
2004ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering        if (!p->name_table)
201a3596a5e3ec4937a220e6e60218639e2aba82701Lennart Poettering            /* This works only for normalized domain names */
2024f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            p->name_table = avahi_hashmap_new(avahi_string_hash, avahi_string_equal, avahi_free, NULL);
2034ccd2cdd5ae567dc2cb6c05ca5e5a9537a9dc1c4Lennart Poettering
2044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        if (!(u = avahi_strdup(pname)))
2054f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_log_error("avahi_strdup() failed.");
2064f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        else
2074f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            avahi_hashmap_insert(p->name_table, u, d);
2084ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    }
2094ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2107dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, 1)))
211c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        goto fail;
212c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2134e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering    *d = 0;
2144ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2154c8155fa9c85c7ece92182d0ab53f99a982a4abfLennart Poettering    return saved_ptr;
216c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
217c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poetteringfail:
218c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    p->size = saved_size;
219c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    return NULL;
2204ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2214ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2224f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_uint16(AvahiDnsPacket *p, uint16_t v) {
2234f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2244f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(d = avahi_dns_packet_extend(p, sizeof(uint16_t))))
227c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
2284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
229973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[0] = (uint8_t) (v >> 8);
230973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[1] = (uint8_t) v;
2314ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return d;
2324ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2334ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2344f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_append_uint32(AvahiDnsPacket *p, uint32_t v) {
2354f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2364f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
237c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2384f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (!(d = avahi_dns_packet_extend(p, sizeof(uint32_t))))
239c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
240c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
241973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[0] = (uint8_t) (v >> 24);
242973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[1] = (uint8_t) (v >> 16);
243973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[2] = (uint8_t) (v >> 8);
244973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d[3] = (uint8_t) v;
24554247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
24654247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return d;
24754247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering}
24854247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2494f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_append_bytes(AvahiDnsPacket  *p, const void *b, size_t l) {
2504f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t* d;
25154247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2524f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(b);
2544f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l);
2554aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
2567dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, l)))
257c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
25854247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
259c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    memcpy(d, b, l);
26054247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return d;
26154247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering}
26254247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering
2634f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_string(AvahiDnsPacket *p, const char *s) {
2644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t* d;
2654f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t k;
266a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(s);
269a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
270a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if ((k = strlen(s)) >= 255)
271a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        k = 255;
272a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2737dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(d = avahi_dns_packet_extend(p, k+1)))
274a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return NULL;
275a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2764f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    *d = (uint8_t) k;
277a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    memcpy(d+1, s, k);
278a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
279a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return d;
280a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering}
281a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
2824f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t *avahi_dns_packet_extend(AvahiDnsPacket *p, size_t l) {
2834f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *d;
2844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2854f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2864ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
287c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering    if (p->size+l > p->max_size)
288c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering        return NULL;
289c18626ad35cdf94edbff196070ccbb6ae825abd0Lennart Poettering
2907dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    d = AVAHI_DNS_PACKET_DATA(p) + p->size;
2914ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->size += l;
2924ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2934ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return d;
2944ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
2954ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
2961ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poetteringint avahi_dns_packet_check_valid(AvahiDnsPacket *p) {
2974f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t flags;
2984f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
2994ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3001ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (p->size < AVAHI_DNS_PACKET_HEADER_SIZE)
3014ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
3024ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3037dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS);
3041ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3051ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (flags & AVAHI_DNS_FLAG_OPCODE)
3061ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        return -1;
3071ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3081ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    return 0;
3091ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering}
3101ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3111ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poetteringint avahi_dns_packet_check_valid_multicast(AvahiDnsPacket *p) {
3121ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    uint16_t flags;
3131ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    assert(p);
3144ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3151ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (avahi_dns_packet_check_valid(p) < 0)
3161ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        return -1;
3171ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3181ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    flags = avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS);
3191ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
3201ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (flags & AVAHI_DNS_FLAG_RCODE)
3214ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
3224ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3234ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
3244ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_is_query(AvahiDnsPacket *p) {
3274f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
3284ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3297dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return !(avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_FLAGS) & AVAHI_DNS_FLAG_QR);
3304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
3314ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3324f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringstatic int consume_labels(AvahiDnsPacket *p, unsigned idx, char *ret_name, size_t l) {
3334f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int ret = 0;
3344ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    int compressed = 0;
3354ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    int first_label = 1;
3365ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd    unsigned label_ptr;
33783b432c2369d7ef4142811bea0109b6588b6f313Trent Lloyd    int i;
3384f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p && ret_name && l);
3394ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
340451be30b300b390b46738af3fd24fc942ba3158fTrent Lloyd    for (i = 0; i < AVAHI_DNS_LABELS_MAX; i++) {
3414f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering        uint8_t n;
3424ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
34366142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering        if (idx+1 > p->size)
3444ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return -1;
3454ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
34666142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering        n = AVAHI_DNS_PACKET_DATA(p)[idx];
3474ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3484ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        if (!n) {
34966142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx++;
3504ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3514ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret++;
3524ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3534ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (l < 1)
3544ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3554ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            *ret_name = 0;
3564ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3574ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return ret;
3584ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3594ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else if (n <= 63) {
3604ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            /* Uncompressed label */
36166142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx++;
3624ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3634ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret++;
3644ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
36566142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx + n > p->size)
3664ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3674ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            if ((size_t) n + 1 > l)
3694ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3704ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3714ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!first_label) {
3724ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                *(ret_name++) = '.';
3734ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                l--;
3744ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            } else
3754ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                first_label = 0;
3764ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
377d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering            if (!(avahi_escape_label((char*) AVAHI_DNS_PACKET_DATA(p) + idx, n, &ret_name, &l)))
3784e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering                return -1;
3794e2d82b18f7e099cbce933b383c45efa40306161Lennart Poettering
38066142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            idx += n;
3814ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3824ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3834ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret += n;
3844ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else if ((n & 0xC0) == 0xC0) {
3854ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            /* Compressed label */
3864ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
38766142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (idx+2 > p->size)
3884ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                return -1;
3894ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3905ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd            label_ptr = ((unsigned) (AVAHI_DNS_PACKET_DATA(p)[idx] & ~0xC0)) << 8 | AVAHI_DNS_PACKET_DATA(p)[idx+1];
3915ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd
3925ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd            if ((label_ptr < AVAHI_DNS_PACKET_HEADER_SIZE) || (label_ptr >= idx))
3935ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd                return -1;
3945ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd
3955ed5452823a5da7d7a7b36d5a42d3edc09f2342fTrent Lloyd            idx = label_ptr;
3964ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
3974ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            if (!compressed)
3984ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering                ret += 2;
3994ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4004ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            compressed = 1;
4014ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        } else
4024ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering            return -1;
4034ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    }
4046e9695a1e6a5f6a70195b6de37448aaf9cde8e30Trent Lloyd
4056e9695a1e6a5f6a70195b6de37448aaf9cde8e30Trent Lloyd    return -1;
4064ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4074ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4084f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_name(AvahiDnsPacket *p, char *ret_name, size_t l) {
4094f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    int r;
4104ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4114ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if ((r = consume_labels(p, p->rindex, ret_name, l)) < 0)
4124ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4134ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4144ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += r;
4154ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4164ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4174ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4184f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_uint16(AvahiDnsPacket *p, uint16_t *ret_v) {
419973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    uint8_t *d;
420973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering
4214f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4224f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_v);
4234ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4244f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (p->rindex + sizeof(uint16_t) > p->size)
4254ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4264ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
427973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d = (uint8_t*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex);
428973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    *ret_v = (d[0] << 8) | d[1];
4294f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    p->rindex += sizeof(uint16_t);
4304ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4314ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4324ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4334ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4344f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_uint32(AvahiDnsPacket *p, uint32_t *ret_v) {
435973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    uint8_t* d;
436973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering
4374f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4384f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_v);
4394ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4404f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if (p->rindex + sizeof(uint32_t) > p->size)
4414ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4424ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
443973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    d = (uint8_t*) (AVAHI_DNS_PACKET_DATA(p) + p->rindex);
444973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    *ret_v = (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
4454f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    p->rindex += sizeof(uint32_t);
4464ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4474ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4484ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4494ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4504f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_bytes(AvahiDnsPacket *p, void * ret_data, size_t l) {
4514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4524f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_data);
4534f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l > 0);
4544ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4554ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if (p->rindex + l > p->size)
4564ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
4574ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4587dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memcpy(ret_data, AVAHI_DNS_PACKET_DATA(p) + p->rindex, l);
4594ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += l;
4604ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4614ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
4624ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
4634ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
4644f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_consume_string(AvahiDnsPacket *p, char *ret_string, size_t l) {
4654f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t k;
466a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4674f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
4684f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(ret_string);
4694f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(l > 0);
470a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
471a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex >= p->size)
472a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return -1;
473a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4747dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    k = AVAHI_DNS_PACKET_DATA(p)[p->rindex];
475a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
476a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex+1+k > p->size)
477a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        return -1;
478a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
479a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (l > k+1)
480a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        l = k+1;
481a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4827dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    memcpy(ret_string, AVAHI_DNS_PACKET_DATA(p)+p->rindex+1, l-1);
483a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    ret_string[l-1] = 0;
484a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
485a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    p->rindex += 1+k;
486a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
487a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return 0;
488a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering}
489a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
4904f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringconst void* avahi_dns_packet_get_rptr(AvahiDnsPacket *p) {
4914f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
492f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
493a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (p->rindex > p->size)
494f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
495f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
4967dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return AVAHI_DNS_PACKET_DATA(p) + p->rindex;
497f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
498f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
4994f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_skip(AvahiDnsPacket *p, size_t length) {
5004f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
5014ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
5024ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    if (p->rindex + length > p->size)
5034ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering        return -1;
5044ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering
5054ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    p->rindex += length;
5064ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering    return 0;
5074ba1a4b0b4488e5058af67b789187735b529075eLennart Poettering}
508f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
509943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringstatic int parse_rdata(AvahiDnsPacket *p, AvahiRecord *r, uint16_t rdlength) {
510943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    char buf[AVAHI_DOMAIN_NAME_MAX];
5114f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    const void* start;
512943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
5134f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
514943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(r);
515f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
5167dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    start = avahi_dns_packet_get_rptr(p);
517943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
518943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    switch (r->key->type) {
5197dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_PTR:
5207dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_CNAME:
521d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering        case AVAHI_DNS_TYPE_NS:
522a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5237dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
524943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
525a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5264f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.ptr.name = avahi_strdup(buf);
527a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
528a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
529c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5307dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_SRV:
531a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5327dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_uint16(p, &r->data.srv.priority) < 0 ||
5337dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_uint16(p, &r->data.srv.weight) < 0 ||
5347dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_uint16(p, &r->data.srv.port) < 0 ||
5357dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                avahi_dns_packet_consume_name(p, buf, sizeof(buf)) < 0)
536943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
537a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5384f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.srv.name = avahi_strdup(buf);
539a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
540a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5417dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_HINFO:
542a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5437dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0)
544943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
545943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
5464f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.hinfo.cpu = avahi_strdup(buf);
547943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
5487dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_string(p, buf, sizeof(buf)) < 0)
549943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
550943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
5514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            r->data.hinfo.os = avahi_strdup(buf);
552c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
553c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5547dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_TXT:
555a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
556a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            if (rdlength > 0) {
55720011324500a728851e4888c890a756ecf71394bLennart Poettering                if (avahi_string_list_parse(avahi_dns_packet_get_rptr(p), rdlength, &r->data.txt.string_list) < 0)
55820011324500a728851e4888c890a756ecf71394bLennart Poettering                    return -1;
559a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5607dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                if (avahi_dns_packet_skip(p, rdlength) < 0)
561943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                    return -1;
562fc174c871b4f85e558766c1ca55661fa7b1b4c9aLennart Poettering            } else
563fc174c871b4f85e558766c1ca55661fa7b1b4c9aLennart Poettering                r->data.txt.string_list = NULL;
564c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
565a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
566a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5677dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_A:
568a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
569c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("A"); */
570c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
5717dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_bytes(p, &r->data.a.address, sizeof(AvahiIPv4Address)) < 0)
572943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
573a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
574a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
575a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5767dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_AAAA:
577a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
578c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("aaaa"); */
579a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5807dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (avahi_dns_packet_consume_bytes(p, &r->data.aaaa.address, sizeof(AvahiIPv6Address)) < 0)
581943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
582a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
583c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
584c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
585c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        default:
5864aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
587c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*             avahi_log_debug("generic"); */
588a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5894aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering            if (rdlength > 0) {
5904aa744ffac20c7b5e18cb3b23e5dbac8221c0043Lennart Poettering
5914f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering                r->data.generic.data = avahi_memdup(avahi_dns_packet_get_rptr(p), rdlength);
592a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
5937dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                if (avahi_dns_packet_skip(p, rdlength) < 0)
594943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                    return -1;
595a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            }
596c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
597c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
598c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    }
599c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
600a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    /* Check if we read enough data */
6014f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    if ((const uint8_t*) avahi_dns_packet_get_rptr(p) - (const uint8_t*) start != rdlength)
602943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        return -1;
603943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
604943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return 0;
605943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
606943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
607943a6b93697fc0a7bcd0cc574744d7de609c189cLennart PoetteringAvahiRecord* avahi_dns_packet_consume_record(AvahiDnsPacket *p, int *ret_cache_flush) {
608943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    char name[AVAHI_DOMAIN_NAME_MAX];
609943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint16_t type, class;
610943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint32_t ttl;
611943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint16_t rdlength;
612943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    AvahiRecord *r = NULL;
613943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
614943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(p);
615943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
616943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
617943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint16(p, &type) < 0 ||
618943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint16(p, &class) < 0 ||
619943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint32(p, &ttl) < 0 ||
620943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        avahi_dns_packet_consume_uint16(p, &rdlength) < 0 ||
621943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        p->rindex + rdlength > p->size)
622a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering        goto fail;
623a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
624943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (ret_cache_flush)
625943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        *ret_cache_flush = !!(class & AVAHI_DNS_CACHE_FLUSH);
626943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    class &= ~AVAHI_DNS_CACHE_FLUSH;
627943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
628943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (!(r = avahi_record_new_full(name, class, type, ttl)))
629943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
630943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
631943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (parse_rdata(p, r, rdlength) < 0)
632943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
6337e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering
6347e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    if (!avahi_record_is_valid(r))
6357e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        goto fail;
636943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
637a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return r;
638a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
639a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poetteringfail:
640a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    if (r)
6417dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_record_unref(r);
642a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
643a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering    return NULL;
644f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
645f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6464f0a5e7572a4257894b4bfede42c26d65152609eLennart PoetteringAvahiKey* avahi_dns_packet_consume_key(AvahiDnsPacket *p, int *ret_unicast_response) {
6474f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    char name[256];
6484f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint16_t type, class;
6497e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    AvahiKey *k;
650f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6514f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
652f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6537dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (avahi_dns_packet_consume_name(p, name, sizeof(name)) < 0 ||
6547dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &type) < 0 ||
6557dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        avahi_dns_packet_consume_uint16(p, &class) < 0)
656f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
657f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6581ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    if (ret_unicast_response)
6591ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering        *ret_unicast_response = !!(class & AVAHI_DNS_UNICAST_RESPONSE);
660f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6611ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering    class &= ~AVAHI_DNS_UNICAST_RESPONSE;
6621ffedb586bd2fb6daa3970304fac7c5b415cd38fLennart Poettering
6637e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    if (!(k = avahi_key_new(name, class, type)))
6647e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        return NULL;
6657e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering
6667e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    if (!avahi_key_is_valid(k)) {
6677e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        avahi_key_unref(k);
6687e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering        return NULL;
6697e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    }
6707e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering
6717e80cf6838c15be19cad03aeb80996d03a98921bLennart Poettering    return k;
672f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
673f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6744f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringuint8_t* avahi_dns_packet_append_key(AvahiDnsPacket *p, AvahiKey *k, int unicast_response) {
6754f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    uint8_t *t;
6764f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    size_t size;
677f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
6784f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
6794f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(k);
680f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
681d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    size = p->size;
682d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
6837dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    if (!(t = avahi_dns_packet_append_name(p, k->name)) ||
6847dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        !avahi_dns_packet_append_uint16(p, k->type) ||
68514f8d9beb7ef14b0aab5512345e09109bdd8cb0cLennart Poettering        !avahi_dns_packet_append_uint16(p, k->clazz | (unicast_response ? AVAHI_DNS_UNICAST_RESPONSE : 0))) {
686d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering        p->size = size;
687f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering        return NULL;
688d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    }
689f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
690f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering    return t;
691f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
692f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering
693943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringstatic int append_rdata(AvahiDnsPacket *p, AvahiRecord *r) {
6944f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
6954f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(r);
696943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
697c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    switch (r->key->type) {
698c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
6997dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_PTR:
700d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering        case AVAHI_DNS_TYPE_CNAME:
701d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering        case AVAHI_DNS_TYPE_NS:
702d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering
7037dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!(avahi_dns_packet_append_name(p, r->data.ptr.name)))
704943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
705c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
706a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
707a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7087dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_SRV:
709a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7107dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_uint16(p, r->data.srv.priority) ||
7117dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_uint16(p, r->data.srv.weight) ||
7127dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_uint16(p, r->data.srv.port) ||
7137dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_name(p, r->data.srv.name))
714943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
715c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
716c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
717c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
7187dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_HINFO:
7197dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_string(p, r->data.hinfo.cpu) ||
7207dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering                !avahi_dns_packet_append_string(p, r->data.hinfo.os))
721943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
722a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
723a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
724a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7257dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_TXT: {
726a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7274f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            uint8_t *data;
7284f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering            size_t n;
729c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
73066142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            n = avahi_string_list_serialize(r->data.txt.string_list, NULL, 0);
731c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
73266142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            if (!(data = avahi_dns_packet_extend(p, n)))
733943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
734c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
73566142b071a2497d7e3cf58d7bf5159bb1c970d84Lennart Poettering            avahi_string_list_serialize(r->data.txt.string_list, data, n);
736c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering            break;
737c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        }
738c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
739a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7407dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_A:
741a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7427dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_bytes(p, &r->data.a.address, sizeof(r->data.a.address)))
743943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
744a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
745a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
746a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7477dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering        case AVAHI_DNS_TYPE_AAAA:
748a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7497dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering            if (!avahi_dns_packet_append_bytes(p, &r->data.aaaa.address, sizeof(r->data.aaaa.address)))
750943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                return -1;
751a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
752a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
753a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
754c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering        default:
755a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
756943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering            if (r->data.generic.size)
757943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                if (avahi_dns_packet_append_bytes(p, r->data.generic.data, r->data.generic.size))
758943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering                    return -1;
759a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
760a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering            break;
761c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering    }
762c8dd2dc8f91a322178c43281cbc5c8fc16da5219Lennart Poettering
763943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return 0;
764943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
765943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
766a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
767943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringuint8_t* avahi_dns_packet_append_record(AvahiDnsPacket *p, AvahiRecord *r, int cache_flush, unsigned max_ttl) {
768943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    uint8_t *t, *l, *start;
769943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    size_t size;
770943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
771943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(p);
772943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(r);
773943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
774943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    size = p->size;
775943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
776943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (!(t = avahi_dns_packet_append_name(p, r->key->name)) ||
777943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !avahi_dns_packet_append_uint16(p, r->key->type) ||
778943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !avahi_dns_packet_append_uint16(p, cache_flush ? (r->key->clazz | AVAHI_DNS_CACHE_FLUSH) : (r->key->clazz &~ AVAHI_DNS_CACHE_FLUSH)) ||
779943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !avahi_dns_packet_append_uint32(p, (max_ttl && r->ttl > max_ttl) ? max_ttl : r->ttl) ||
780943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        !(l = avahi_dns_packet_append_uint16(p, 0)))
781943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
782943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
783943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    start = avahi_dns_packet_extend(p, 0);
784a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
785943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (append_rdata(p, r) < 0)
786943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        goto fail;
787a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
7887dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    size = avahi_dns_packet_extend(p, 0) - start;
789bbf6b92f662ed909d5b4fca4a43b19e815812b3eLennart Poettering    assert(size <= AVAHI_DNS_RDATA_MAX);
790a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
791c0244c2448a5504581ae24e78b5859760b999b8eLennart Poettering/*     avahi_log_debug("appended %u", size); */
792a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
793973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    l[0] = (uint8_t) ((uint16_t) size >> 8);
794973b9c62f7cbc65f00e9730c6c362d30f9da5163Lennart Poettering    l[1] = (uint8_t) ((uint16_t) size);
795a20c01bd12216d409e0dfc5d3bbacc940352bfceLennart Poettering
79654247ce93dc6f048c0ffea546f454653ce0e25a8Lennart Poettering    return t;
797d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
798d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
799d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poetteringfail:
800d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    p->size = size;
801d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering    return NULL;
802d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering}
803d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
8044f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringint avahi_dns_packet_is_empty(AvahiDnsPacket *p) {
8054f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
806d553a1c2d1cd3fcdd65ade64940b5bd3efc70675Lennart Poettering
8077dce450bdc23ea306a61e00f914481e29ebcb176Lennart Poettering    return p->size <= AVAHI_DNS_PACKET_HEADER_SIZE;
808f0f4bb0c37eeed71934e3191cffa5afb1cfdca0dLennart Poettering}
8090a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
8104f0a5e7572a4257894b4bfede42c26d65152609eLennart Poetteringsize_t avahi_dns_packet_space(AvahiDnsPacket *p) {
8114f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p);
8120a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
8134f0a5e7572a4257894b4bfede42c26d65152609eLennart Poettering    assert(p->size <= p->max_size);
8140a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering
8150a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering    return p->max_size - p->size;
8160a985aa6c5453fe09bf0a3a79fe66d49c698b309Lennart Poettering}
817943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
818943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringint avahi_rdata_parse(AvahiRecord *record, const void* rdata, size_t size) {
819943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    int ret;
820943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    AvahiDnsPacket p;
821943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
822943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(record);
823943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(rdata);
824943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
825943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.data = (void*) rdata;
826943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.max_size = p.size = size;
827943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.rindex = 0;
828943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.name_table = NULL;
829943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
830943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    ret = parse_rdata(&p, record, size);
831943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
832943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(!p.name_table);
833943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
834943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return ret;
835943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
836943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
837943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poetteringsize_t avahi_rdata_serialize(AvahiRecord *record, void *rdata, size_t max_size) {
838943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    int ret;
839943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    AvahiDnsPacket p;
840943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
841943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(record);
842943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(rdata);
843943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    assert(max_size > 0);
844943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
845943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.data = (void*) rdata;
846943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.max_size = max_size;
847943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.size = p.rindex = 0;
848943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    p.name_table = NULL;
849943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
850943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    ret = append_rdata(&p, record);
851943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
852943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (p.name_table)
853943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering         avahi_hashmap_free(p.name_table);
854943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
855943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    if (ret < 0)
856943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering        return (size_t) -1;
857943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering
858943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering    return p.size;
859943a6b93697fc0a7bcd0cc574744d7de609c189cLennart Poettering}
860