Bonjour/mDNS lib, works with the new network stack
Fork of BonjourLib by
mDNSResponder.cpp@3:b8a78d6da192, 2014-05-30 (annotated)
- Committer:
- Jasper
- Date:
- Fri May 30 09:43:56 2014 +0000
- Revision:
- 3:b8a78d6da192
- Parent:
- 2:18d443d86057
fix A records. some more debugging.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dirkx | 0:1a198985f183 | 1 | /* Class: mDNSResponder |
dirkx | 0:1a198985f183 | 2 | * Copyright 1991, 2003, 2010 Dirk-Willem van Gulik <dirkx(at)apache(punto)org> |
dirkx | 0:1a198985f183 | 3 | * |
dirkx | 0:1a198985f183 | 4 | * License: Any BSD or ASF License. |
dirkx | 0:1a198985f183 | 5 | * |
dirkx | 0:1a198985f183 | 6 | * Rough and ready port of some mDNS code. |
dirkx | 0:1a198985f183 | 7 | * |
dirkx | 0:1a198985f183 | 8 | * Typical use is something like |
dirkx | 0:1a198985f183 | 9 | * |
dirkx | 0:1a198985f183 | 10 | * EthernetNetIf eth; |
dirkx | 0:1a198985f183 | 11 | * HTTPServer svr; |
dirkx | 0:1a198985f183 | 12 | * mDNSResponder mdns; |
dirkx | 0:1a198985f183 | 13 | * |
dirkx | 0:1a198985f183 | 14 | * int main()... |
dirkx | 0:1a198985f183 | 15 | * |
dirkx | 0:1a198985f183 | 16 | * // get internet |
dirkx | 0:1a198985f183 | 17 | * EthernetErr ethErr = eth.setup(); |
dirkx | 0:1a198985f183 | 18 | * ... etc .. |
dirkx | 0:1a198985f183 | 19 | * |
dirkx | 0:1a198985f183 | 20 | * // set up some server |
dirkx | 0:1a198985f183 | 21 | * svr.addHandler<SimpleHandler>("/"); //Default handler |
dirkx | 0:1a198985f183 | 22 | * svr.bind(80); * * |
dirkx | 0:1a198985f183 | 23 | |
dirkx | 0:1a198985f183 | 24 | * // Extract the IP address. |
dirkx | 0:1a198985f183 | 25 | * IpAddr ip = eth.getIp(); |
dirkx | 0:1a198985f183 | 26 | * printf("mbed IP Address is %d.%d.%d.%d\r\n", ip[0], ip[1], ip[2], ip[3]); |
dirkx | 0:1a198985f183 | 27 | * |
dirkx | 0:1a198985f183 | 28 | * // Announce ourselves. |
dirkx | 0:1a198985f183 | 29 | * mdns.announce(ip, "fred", "_http._tcp", 80, "The Little Server that Could", "path=/demo"); |
dirkx | 0:1a198985f183 | 30 | * |
dirkx | 0:1a198985f183 | 31 | * while()... enter some run loop |
dirkx | 0:1a198985f183 | 32 | * ... |
dirkx | 0:1a198985f183 | 33 | * |
dirkx | 0:1a198985f183 | 34 | * This will cause http://fred.local./demo to be announced as 'The Little Server that Could'. |
dirkx | 0:1a198985f183 | 35 | * |
dirkx | 0:1a198985f183 | 36 | * Or as another example: (http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt) |
dirkx | 0:1a198985f183 | 37 | * and the various RFCs: |
dirkx | 0:1a198985f183 | 38 | * |
dirkx | 0:1a198985f183 | 39 | * mdns.announce(ip, "_ssh._tcp", 22, SSH to Serial Gateway", NULL); |
dirkx | 0:1a198985f183 | 40 | * |
dirkx | 0:1a198985f183 | 41 | * CAVEAT - a lot of the buffer overrun and copy checks |
dirkx | 0:1a198985f183 | 42 | * where removed; and this is not anywhere near |
dirkx | 0:1a198985f183 | 43 | * threadsafve or sane. Not for production use. |
dirkx | 0:1a198985f183 | 44 | */ |
Jasper | 2:18d443d86057 | 45 | #include "lwip/lwipopts.h" |
dirkx | 0:1a198985f183 | 46 | #if LWIP_DNS /* don't build if not configured for use in lwipopts.h */ |
dirkx | 0:1a198985f183 | 47 | |
dirkx | 0:1a198985f183 | 48 | #include "mDNSResponder.h" |
dirkx | 0:1a198985f183 | 49 | #include <stdio.h> |
Jasper | 3:b8a78d6da192 | 50 | #include <ctype.h> |
dirkx | 0:1a198985f183 | 51 | |
dirkx | 0:1a198985f183 | 52 | #ifndef DNS_RRTYPE_SRV |
dirkx | 0:1a198985f183 | 53 | #define DNS_RRTYPE_SRV (33) |
dirkx | 0:1a198985f183 | 54 | #endif |
dirkx | 0:1a198985f183 | 55 | |
dirkx | 0:1a198985f183 | 56 | #ifndef DNS_LOCAL |
dirkx | 0:1a198985f183 | 57 | #define DNS_LOCAL "local" |
dirkx | 0:1a198985f183 | 58 | #endif |
dirkx | 0:1a198985f183 | 59 | |
Jasper | 3:b8a78d6da192 | 60 | void pretty_print_block(char *b, int len) |
Jasper | 3:b8a78d6da192 | 61 | { |
Jasper | 3:b8a78d6da192 | 62 | int x, y, indent, count = 0; |
Jasper | 3:b8a78d6da192 | 63 | |
Jasper | 3:b8a78d6da192 | 64 | indent = 16; /* whatever */ |
Jasper | 3:b8a78d6da192 | 65 | |
Jasper | 3:b8a78d6da192 | 66 | printf("\n\r"); |
Jasper | 3:b8a78d6da192 | 67 | |
Jasper | 3:b8a78d6da192 | 68 | while (count < len) |
Jasper | 3:b8a78d6da192 | 69 | { |
Jasper | 3:b8a78d6da192 | 70 | printf("%04x : ", count); |
Jasper | 3:b8a78d6da192 | 71 | for (x = 0 ; x < indent ; x++) |
Jasper | 3:b8a78d6da192 | 72 | { |
Jasper | 3:b8a78d6da192 | 73 | printf("%02x ", b[x + count]); |
Jasper | 3:b8a78d6da192 | 74 | if ((x + count + 1) >= len) |
Jasper | 3:b8a78d6da192 | 75 | { |
Jasper | 3:b8a78d6da192 | 76 | x++; |
Jasper | 3:b8a78d6da192 | 77 | for (y = 0 ; y < (indent - x) ; y++) |
Jasper | 3:b8a78d6da192 | 78 | printf(" "); |
Jasper | 3:b8a78d6da192 | 79 | break; |
Jasper | 3:b8a78d6da192 | 80 | } |
Jasper | 3:b8a78d6da192 | 81 | } |
Jasper | 3:b8a78d6da192 | 82 | printf(": "); |
Jasper | 3:b8a78d6da192 | 83 | |
Jasper | 3:b8a78d6da192 | 84 | for (x = 0 ; x < indent ; x++) |
Jasper | 3:b8a78d6da192 | 85 | { |
Jasper | 3:b8a78d6da192 | 86 | if (isprint(b[x + count])) |
Jasper | 3:b8a78d6da192 | 87 | putchar(b[x + count]); |
Jasper | 3:b8a78d6da192 | 88 | else if (b[x + count] == 0) |
Jasper | 3:b8a78d6da192 | 89 | putchar(' '); |
Jasper | 3:b8a78d6da192 | 90 | else |
Jasper | 3:b8a78d6da192 | 91 | putchar('.'); |
Jasper | 3:b8a78d6da192 | 92 | |
Jasper | 3:b8a78d6da192 | 93 | if ((x + count + 1) >= len) |
Jasper | 3:b8a78d6da192 | 94 | { |
Jasper | 3:b8a78d6da192 | 95 | x++; |
Jasper | 3:b8a78d6da192 | 96 | for (y = 0 ; y < (indent - x) ; y++) |
Jasper | 3:b8a78d6da192 | 97 | putchar(' '); |
Jasper | 3:b8a78d6da192 | 98 | break; |
Jasper | 3:b8a78d6da192 | 99 | } |
Jasper | 3:b8a78d6da192 | 100 | } |
Jasper | 3:b8a78d6da192 | 101 | putchar('\n'); |
Jasper | 3:b8a78d6da192 | 102 | putchar('\r'); |
Jasper | 3:b8a78d6da192 | 103 | count += indent; |
Jasper | 3:b8a78d6da192 | 104 | } |
Jasper | 3:b8a78d6da192 | 105 | putchar('\n'); |
Jasper | 3:b8a78d6da192 | 106 | putchar('\r'); |
Jasper | 3:b8a78d6da192 | 107 | } |
Jasper | 3:b8a78d6da192 | 108 | |
Jasper | 3:b8a78d6da192 | 109 | |
Jasper | 3:b8a78d6da192 | 110 | |
Jasper | 2:18d443d86057 | 111 | void announcer(void const *args) { |
Jasper | 2:18d443d86057 | 112 | printf("in announcer\r\n"); |
Jasper | 2:18d443d86057 | 113 | mDNSResponder *m = (mDNSResponder *)args; |
Jasper | 2:18d443d86057 | 114 | m->periodic(NULL); |
Jasper | 2:18d443d86057 | 115 | } |
Jasper | 2:18d443d86057 | 116 | |
Jasper | 2:18d443d86057 | 117 | mDNSResponder::mDNSResponder() : |
Jasper | 2:18d443d86057 | 118 | moi_txt(NULL), moi_port(0), |
dirkx | 0:1a198985f183 | 119 | moi_name(NULL), moi_proto(NULL), |
dirkx | 0:1a198985f183 | 120 | moi_local_proto(NULL), moi_local_name(NULL), moi_local_pglue(NULL), |
dirkx | 0:1a198985f183 | 121 | #ifdef MDNS_QCACHE |
Jasper | 2:18d443d86057 | 122 | labelCacheCnt(0), labelCacheOffset(0) |
dirkx | 0:1a198985f183 | 123 | #endif |
dirkx | 0:1a198985f183 | 124 | { |
dirkx | 0:1a198985f183 | 125 | initLabelCache(0); |
dirkx | 0:1a198985f183 | 126 | } |
dirkx | 0:1a198985f183 | 127 | |
dirkx | 0:1a198985f183 | 128 | mDNSResponder::~mDNSResponder() { |
dirkx | 0:1a198985f183 | 129 | close(); |
dirkx | 0:1a198985f183 | 130 | } |
dirkx | 0:1a198985f183 | 131 | |
Jasper | 2:18d443d86057 | 132 | void mDNSResponder::announce(ip_addr_t ip, const char * ldn, const char * proto, uint16_t port, const char * name, char ** txt) { |
dirkx | 0:1a198985f183 | 133 | |
dirkx | 0:1a198985f183 | 134 | m_pUDPSocket = new UDPSocket; |
Jasper | 2:18d443d86057 | 135 | // m_pUDPSocket->init(); |
dirkx | 0:1a198985f183 | 136 | |
Jasper | 2:18d443d86057 | 137 | multicast_group = new Endpoint; |
Jasper | 2:18d443d86057 | 138 | multicast_group->set_address(MCAST, MDNS_PORT); |
Jasper | 2:18d443d86057 | 139 | |
Jasper | 2:18d443d86057 | 140 | m_pUDPSocket->bind(MDNS_PORT); |
Jasper | 2:18d443d86057 | 141 | m_pUDPSocket->join_multicast_group(MCAST); |
dirkx | 0:1a198985f183 | 142 | |
dirkx | 0:1a198985f183 | 143 | moi_port = port; |
dirkx | 0:1a198985f183 | 144 | moi_txt = txt; |
dirkx | 0:1a198985f183 | 145 | moi_ip = ip; |
dirkx | 0:1a198985f183 | 146 | moi_proto = proto; |
dirkx | 0:1a198985f183 | 147 | moi_name = name; |
dirkx | 0:1a198985f183 | 148 | |
dirkx | 0:1a198985f183 | 149 | moi_local_proto = (char *)malloc(128); |
dirkx | 0:1a198985f183 | 150 | moi_local_name = (char *)malloc(128); |
dirkx | 0:1a198985f183 | 151 | moi_local_pglue = (char *)malloc(128); |
dirkx | 0:1a198985f183 | 152 | |
dirkx | 0:1a198985f183 | 153 | snprintf(moi_local_proto,128,"%s.%s.", moi_proto, DNS_LOCAL); |
dirkx | 0:1a198985f183 | 154 | snprintf(moi_local_name,128,"%s.%s.", ldn, DNS_LOCAL); |
Jasper | 2:18d443d86057 | 155 | snprintf(moi_local_pglue,128,"%s.%s.%s.", moi_name, moi_proto, DNS_LOCAL); |
Jasper | 2:18d443d86057 | 156 | |
Jasper | 2:18d443d86057 | 157 | printf("starting thread\r\n"); |
dirkx | 0:1a198985f183 | 158 | |
dirkx | 0:1a198985f183 | 159 | // Gratuis intro - and repeat such regularly.. taking some |
dirkx | 0:1a198985f183 | 160 | // care to not go beyond DHCP limits - but not more often |
dirkx | 0:1a198985f183 | 161 | // than makes sense for our TTL. See the .h file for the |
dirkx | 0:1a198985f183 | 162 | // various tradeoffs. |
dirkx | 0:1a198985f183 | 163 | // |
Jasper | 2:18d443d86057 | 164 | // sendReply(DNS_RRTYPE_PTR, 0, NULL); |
Jasper | 2:18d443d86057 | 165 | |
Jasper | 2:18d443d86057 | 166 | printf("starting announcer\r\n"); |
Jasper | 2:18d443d86057 | 167 | mdns_announcer = new RtosTimer(announcer, osTimerPeriodic, this); |
Jasper | 2:18d443d86057 | 168 | mdns_announcer->start(1000 * MDNS_INTERVAL); |
Jasper | 2:18d443d86057 | 169 | printf("kicking it\r\n"); |
Jasper | 2:18d443d86057 | 170 | |
Jasper | 2:18d443d86057 | 171 | Listen(NULL); |
dirkx | 0:1a198985f183 | 172 | } |
dirkx | 0:1a198985f183 | 173 | |
dirkx | 0:1a198985f183 | 174 | void mDNSResponder::close() { |
Jasper | 2:18d443d86057 | 175 | m_pUDPSocket->close(true); |
dirkx | 0:1a198985f183 | 176 | delete m_pUDPSocket; |
dirkx | 0:1a198985f183 | 177 | } |
dirkx | 0:1a198985f183 | 178 | |
dirkx | 0:1a198985f183 | 179 | char * index(char * str, char c) { |
dirkx | 0:1a198985f183 | 180 | for (;str && *str;str++) { |
dirkx | 0:1a198985f183 | 181 | if (*str == c) return str; |
dirkx | 0:1a198985f183 | 182 | }; |
dirkx | 0:1a198985f183 | 183 | return NULL; |
dirkx | 0:1a198985f183 | 184 | } |
dirkx | 0:1a198985f183 | 185 | |
dirkx | 0:1a198985f183 | 186 | #ifdef MDNS_QCACHE |
dirkx | 0:1a198985f183 | 187 | void mDNSResponder::initLabelCache(char * off) { |
dirkx | 0:1a198985f183 | 188 | labelCacheOffset = off; |
dirkx | 0:1a198985f183 | 189 | labelCacheCnt = 0; |
dirkx | 0:1a198985f183 | 190 | memset(_cache_off,0, sizeof(_cache_off)); // Rely on min value to be 12 |
dirkx | 0:1a198985f183 | 191 | }; |
dirkx | 0:1a198985f183 | 192 | |
dirkx | 0:1a198985f183 | 193 | uint16_t mDNSResponder::checkLabelCache(char * name) { |
dirkx | 0:1a198985f183 | 194 | // Bail out if not initialized with a valid (>12) offset. |
dirkx | 0:1a198985f183 | 195 | // |
dirkx | 0:1a198985f183 | 196 | if (!labelCacheOffset) |
dirkx | 0:1a198985f183 | 197 | return 0; |
dirkx | 0:1a198985f183 | 198 | |
dirkx | 0:1a198985f183 | 199 | for (int i=0; i < MDNS_MAXCACHEDNSLABELS; i++) |
dirkx | 0:1a198985f183 | 200 | if (_cache_off[i] && !strcmp(_cache_och[i],name)) |
dirkx | 0:1a198985f183 | 201 | return _cache_off[i]; |
dirkx | 0:1a198985f183 | 202 | return 0; |
dirkx | 0:1a198985f183 | 203 | }; |
dirkx | 0:1a198985f183 | 204 | |
dirkx | 0:1a198985f183 | 205 | void mDNSResponder::addLabelCache(char * p, char * name) { |
dirkx | 0:1a198985f183 | 206 | // Bail out if not initialized with a valid (>12) offset. |
dirkx | 0:1a198985f183 | 207 | // |
dirkx | 0:1a198985f183 | 208 | if (!labelCacheOffset) |
dirkx | 0:1a198985f183 | 209 | return; |
dirkx | 0:1a198985f183 | 210 | |
dirkx | 0:1a198985f183 | 211 | _cache_off[labelCacheCnt] = p - labelCacheOffset; |
dirkx | 0:1a198985f183 | 212 | _cache_och[labelCacheCnt] = name; |
dirkx | 0:1a198985f183 | 213 | |
dirkx | 0:1a198985f183 | 214 | labelCacheCnt++; |
dirkx | 0:1a198985f183 | 215 | // we intentionally do not wack the first entries - as they are the most |
dirkx | 0:1a198985f183 | 216 | // likely ones to be used. |
dirkx | 0:1a198985f183 | 217 | if (labelCacheCnt>= MDNS_MAXCACHEDNSLABELS) |
dirkx | 0:1a198985f183 | 218 | labelCacheCnt = MDNS_MAXCACHEDNSLABELS / 3; |
dirkx | 0:1a198985f183 | 219 | }; |
dirkx | 0:1a198985f183 | 220 | #else |
dirkx | 0:1a198985f183 | 221 | #define initLabelCache(x) {} /* Ignored */ |
dirkx | 0:1a198985f183 | 222 | #define checkLabelCache(x) (0) /* never a hit */ |
dirkx | 0:1a198985f183 | 223 | #define addLabelCache(x,y) {} /* Ignored */ |
dirkx | 0:1a198985f183 | 224 | #endif |
dirkx | 0:1a198985f183 | 225 | |
dirkx | 0:1a198985f183 | 226 | char * mDNSResponder::breakname(char *p, char *name) { |
dirkx | 0:1a198985f183 | 227 | int l = 0, de = 1; |
dirkx | 0:1a198985f183 | 228 | char * q; |
dirkx | 0:1a198985f183 | 229 | uint16_t off; |
dirkx | 0:1a198985f183 | 230 | |
dirkx | 0:1a198985f183 | 231 | do { |
dirkx | 0:1a198985f183 | 232 | if ((off = checkLabelCache(name)) != 0) { |
dirkx | 0:1a198985f183 | 233 | *p++ = 192 + (off >> 8); |
dirkx | 0:1a198985f183 | 234 | *p++ = (off & 0xFF); |
dirkx | 0:1a198985f183 | 235 | return p; |
dirkx | 0:1a198985f183 | 236 | } else { |
dirkx | 0:1a198985f183 | 237 | addLabelCache(p, name); |
dirkx | 0:1a198985f183 | 238 | }; |
dirkx | 0:1a198985f183 | 239 | |
dirkx | 0:1a198985f183 | 240 | q = index(name,'.'); |
dirkx | 0:1a198985f183 | 241 | if (!q) { |
dirkx | 0:1a198985f183 | 242 | q = name + strlen(name); |
dirkx | 0:1a198985f183 | 243 | de = 0; |
dirkx | 0:1a198985f183 | 244 | }; |
dirkx | 0:1a198985f183 | 245 | l = q - name; |
dirkx | 0:1a198985f183 | 246 | *p++ = l; |
dirkx | 0:1a198985f183 | 247 | memcpy(p, name, l); |
dirkx | 0:1a198985f183 | 248 | p+=l; |
dirkx | 0:1a198985f183 | 249 | name = q + 1; |
dirkx | 0:1a198985f183 | 250 | } while (l && *name && de); |
dirkx | 0:1a198985f183 | 251 | |
dirkx | 0:1a198985f183 | 252 | // terminating root field if any (not the case for |
dirkx | 0:1a198985f183 | 253 | // things like TXTs). |
dirkx | 0:1a198985f183 | 254 | if (de) *p++ = 0; |
dirkx | 0:1a198985f183 | 255 | return p; |
dirkx | 0:1a198985f183 | 256 | } |
dirkx | 0:1a198985f183 | 257 | |
dirkx | 0:1a198985f183 | 258 | char * mDNSResponder::mRR(char *p, char * name, uint16_t tpe, uint16_t cls, uint32_t ttl) { |
dirkx | 0:1a198985f183 | 259 | uint16_t i = 0; |
dirkx | 0:1a198985f183 | 260 | uint32_t j = 0; |
dirkx | 0:1a198985f183 | 261 | |
dirkx | 0:1a198985f183 | 262 | p = breakname(p, name); |
dirkx | 0:1a198985f183 | 263 | |
dirkx | 0:1a198985f183 | 264 | // NOTE: Cannot assume proper byte boundaries; so |
dirkx | 0:1a198985f183 | 265 | // we assume the compiler does not allow that for |
dirkx | 0:1a198985f183 | 266 | // casts - and write it out with memcpy's |
dirkx | 0:1a198985f183 | 267 | // |
dirkx | 0:1a198985f183 | 268 | i = htons(tpe); // Type |
dirkx | 0:1a198985f183 | 269 | memcpy(p, &i, 2); |
dirkx | 0:1a198985f183 | 270 | p+=2; |
dirkx | 0:1a198985f183 | 271 | |
dirkx | 0:1a198985f183 | 272 | i = htons(cls); // Class |
dirkx | 0:1a198985f183 | 273 | memcpy(p, &i, 2); |
dirkx | 0:1a198985f183 | 274 | p+=2; |
dirkx | 0:1a198985f183 | 275 | |
dirkx | 0:1a198985f183 | 276 | j = htonl(ttl); // TTL (4 bytes) |
dirkx | 0:1a198985f183 | 277 | memcpy(p, &j, 4); |
dirkx | 0:1a198985f183 | 278 | p+=4; |
dirkx | 0:1a198985f183 | 279 | |
dirkx | 0:1a198985f183 | 280 | return p; |
dirkx | 0:1a198985f183 | 281 | } |
dirkx | 0:1a198985f183 | 282 | |
dirkx | 0:1a198985f183 | 283 | char * mDNSResponder::mRRLABEL(char *p, char * name, uint16_t tpe, char ** rr) { |
dirkx | 0:1a198985f183 | 284 | uint16_t i = 0; |
dirkx | 0:1a198985f183 | 285 | |
dirkx | 0:1a198985f183 | 286 | p = mRR(p, name, tpe, DNS_RRCLASS_IN, MDNS_TTL); // Type, IN, TTL |
dirkx | 0:1a198985f183 | 287 | |
dirkx | 0:1a198985f183 | 288 | // RR String |
dirkx | 0:1a198985f183 | 289 | char * q = p + 2; |
dirkx | 0:1a198985f183 | 290 | |
dirkx | 0:1a198985f183 | 291 | for (;*rr;rr++) |
dirkx | 0:1a198985f183 | 292 | q = breakname(q, *rr); |
dirkx | 0:1a198985f183 | 293 | |
dirkx | 0:1a198985f183 | 294 | i = htons(q - p - 2); // RDLEN |
dirkx | 0:1a198985f183 | 295 | memcpy(p, &i, 2); |
dirkx | 0:1a198985f183 | 296 | return q; |
dirkx | 0:1a198985f183 | 297 | } |
dirkx | 0:1a198985f183 | 298 | |
dirkx | 0:1a198985f183 | 299 | char * mDNSResponder::mPTR(char *p, char * name, char * r) { |
dirkx | 0:1a198985f183 | 300 | char *rr[] = { r, NULL }; |
dirkx | 0:1a198985f183 | 301 | return mRRLABEL(p, name, DNS_RRTYPE_PTR, rr ); |
dirkx | 0:1a198985f183 | 302 | } |
dirkx | 0:1a198985f183 | 303 | |
dirkx | 0:1a198985f183 | 304 | char * mDNSResponder::mTXT(char *p, char * name, char ** rr) { |
dirkx | 0:1a198985f183 | 305 | return mRRLABEL(p, name, DNS_RRTYPE_TXT, rr); |
dirkx | 0:1a198985f183 | 306 | } |
dirkx | 0:1a198985f183 | 307 | |
Jasper | 2:18d443d86057 | 308 | char * mDNSResponder::mARR(char *p, char * name, ip_addr_t ip) { |
dirkx | 0:1a198985f183 | 309 | uint16_t i = 0; |
dirkx | 0:1a198985f183 | 310 | |
dirkx | 0:1a198985f183 | 311 | p = mRR(p, name, DNS_RRTYPE_A, DNS_RRCLASS_IN, MDNS_TTL ); // A, IN |
dirkx | 0:1a198985f183 | 312 | |
dirkx | 0:1a198985f183 | 313 | i = htons(4); // RDLEN - we're just doing a single IPv4 address - our primary link ? |
dirkx | 0:1a198985f183 | 314 | memcpy(p, &i, 2); |
dirkx | 0:1a198985f183 | 315 | |
dirkx | 0:1a198985f183 | 316 | // IP already in network order. |
dirkx | 0:1a198985f183 | 317 | memcpy(p+2, &ip, 4); |
dirkx | 0:1a198985f183 | 318 | |
dirkx | 0:1a198985f183 | 319 | return p + 2 + 4; |
dirkx | 0:1a198985f183 | 320 | } |
dirkx | 0:1a198985f183 | 321 | |
dirkx | 0:1a198985f183 | 322 | char * mDNSResponder::mSRV(char *p, char * name, uint16_t port, char * rr) { |
dirkx | 0:1a198985f183 | 323 | uint16_t i = 0; |
dirkx | 0:1a198985f183 | 324 | char * q; |
dirkx | 0:1a198985f183 | 325 | |
dirkx | 0:1a198985f183 | 326 | p = mRR(p, name, DNS_RRTYPE_SRV, DNS_RRCLASS_IN, MDNS_TTL); // SRV, IN |
dirkx | 0:1a198985f183 | 327 | |
dirkx | 0:1a198985f183 | 328 | // Keep space for RDLEN |
dirkx | 0:1a198985f183 | 329 | q = p; |
dirkx | 0:1a198985f183 | 330 | p+=2; |
dirkx | 0:1a198985f183 | 331 | |
dirkx | 0:1a198985f183 | 332 | i = htons(1); // Priority |
dirkx | 0:1a198985f183 | 333 | memcpy(p, &i, 2); |
dirkx | 0:1a198985f183 | 334 | p+=2; |
dirkx | 0:1a198985f183 | 335 | |
dirkx | 0:1a198985f183 | 336 | i = htons(0); // Weight (see rfc2782) |
dirkx | 0:1a198985f183 | 337 | memcpy(p, &i, 2); |
dirkx | 0:1a198985f183 | 338 | p+=2; |
dirkx | 0:1a198985f183 | 339 | |
dirkx | 0:1a198985f183 | 340 | i = htons(port); // Port |
dirkx | 0:1a198985f183 | 341 | memcpy(p, &i, 2); |
dirkx | 0:1a198985f183 | 342 | p+=2; |
dirkx | 0:1a198985f183 | 343 | |
dirkx | 0:1a198985f183 | 344 | p = breakname(p, rr); |
dirkx | 0:1a198985f183 | 345 | |
dirkx | 0:1a198985f183 | 346 | i = htons(p - q - 2); // RDLEN |
dirkx | 0:1a198985f183 | 347 | memcpy(q, &i, 2); |
dirkx | 0:1a198985f183 | 348 | |
dirkx | 0:1a198985f183 | 349 | return p; |
dirkx | 0:1a198985f183 | 350 | } |
dirkx | 0:1a198985f183 | 351 | |
dirkx | 0:1a198985f183 | 352 | char * mDNSResponder::qANY(char *p, char * name, uint16_t tpe, uint16_t cls) { |
dirkx | 0:1a198985f183 | 353 | uint16_t i = 0; |
dirkx | 0:1a198985f183 | 354 | p = breakname(p, name); // QNAME |
dirkx | 0:1a198985f183 | 355 | |
dirkx | 0:1a198985f183 | 356 | i = htons(tpe); // QTYPE |
dirkx | 0:1a198985f183 | 357 | memcpy(p, &i, 2); |
dirkx | 0:1a198985f183 | 358 | p+=2; |
dirkx | 0:1a198985f183 | 359 | |
dirkx | 0:1a198985f183 | 360 | i = htons(cls); // QCLASS |
dirkx | 0:1a198985f183 | 361 | memcpy(p, &i, 2); |
dirkx | 0:1a198985f183 | 362 | p+=2; |
dirkx | 0:1a198985f183 | 363 | |
dirkx | 0:1a198985f183 | 364 | return p; |
dirkx | 0:1a198985f183 | 365 | } |
dirkx | 0:1a198985f183 | 366 | |
dirkx | 0:1a198985f183 | 367 | char * mDNSResponder::qPTR(char *p, char *name) { |
dirkx | 0:1a198985f183 | 368 | return qANY(p,name,DNS_RRTYPE_PTR,DNS_RRCLASS_IN); |
dirkx | 0:1a198985f183 | 369 | } |
dirkx | 0:1a198985f183 | 370 | |
dirkx | 0:1a198985f183 | 371 | char * mDNSResponder::qA(char *p, char *name) { |
dirkx | 0:1a198985f183 | 372 | return qANY(p,name,DNS_RRTYPE_A,DNS_RRCLASS_IN); |
dirkx | 0:1a198985f183 | 373 | } |
dirkx | 0:1a198985f183 | 374 | |
dirkx | 0:1a198985f183 | 375 | char * mDNSResponder::qSRV(char *p, char *name) { |
dirkx | 0:1a198985f183 | 376 | return qANY(p,name,DNS_RRTYPE_SRV,DNS_RRCLASS_IN); |
dirkx | 0:1a198985f183 | 377 | } |
dirkx | 0:1a198985f183 | 378 | |
Jasper | 3:b8a78d6da192 | 379 | /* This si wrong, i think we're answering our own question? or something? */ |
Jasper | 2:18d443d86057 | 380 | void mDNSResponder::sendAnnounce(void) { |
Jasper | 2:18d443d86057 | 381 | char out[ 1500 ], *p; |
Jasper | 2:18d443d86057 | 382 | DNSPacket * op = (DNSPacket *)out; |
Jasper | 2:18d443d86057 | 383 | |
Jasper | 2:18d443d86057 | 384 | Endpoint quack; |
Jasper | 2:18d443d86057 | 385 | quack.set_address(multicast_group->get_address(), multicast_group->get_port()); |
Jasper | 2:18d443d86057 | 386 | |
Jasper | 2:18d443d86057 | 387 | initLabelCache(out); // Offsets are relative to the ID header. |
Jasper | 2:18d443d86057 | 388 | |
Jasper | 2:18d443d86057 | 389 | op->tid = ntohs(0); |
Jasper | 2:18d443d86057 | 390 | op->flags = ntohs(0x0); |
Jasper | 2:18d443d86057 | 391 | op->question_count = ntohs(1); // Courtesy copy of the question. |
Jasper | 2:18d443d86057 | 392 | op->answer_count = ntohs(0); // The record asked for |
Jasper | 2:18d443d86057 | 393 | op->a_count = ntohs(0); |
Jasper | 2:18d443d86057 | 394 | p = out + 12; |
Jasper | 2:18d443d86057 | 395 | |
Jasper | 2:18d443d86057 | 396 | p = qPTR(p, moi_local_proto); |
Jasper | 2:18d443d86057 | 397 | |
Jasper | 3:b8a78d6da192 | 398 | printf("sendAnnounce1\r\n"); |
Jasper | 3:b8a78d6da192 | 399 | |
Jasper | 2:18d443d86057 | 400 | m_pUDPSocket->sendTo(quack, out, p-out); |
Jasper | 2:18d443d86057 | 401 | |
Jasper | 2:18d443d86057 | 402 | initLabelCache(out); // Offsets are relative to the ID header. |
Jasper | 2:18d443d86057 | 403 | |
Jasper | 2:18d443d86057 | 404 | op->flags = ntohs(0x8400U); |
Jasper | 2:18d443d86057 | 405 | op->question_count = ntohs(0); |
Jasper | 2:18d443d86057 | 406 | op->answer_count = ntohs(4); |
Jasper | 2:18d443d86057 | 407 | |
Jasper | 2:18d443d86057 | 408 | p = out + 12; |
Jasper | 2:18d443d86057 | 409 | |
Jasper | 2:18d443d86057 | 410 | p = mPTR(p, moi_local_proto, moi_local_pglue); |
Jasper | 2:18d443d86057 | 411 | |
Jasper | 2:18d443d86057 | 412 | if (moi_txt && * moi_txt) |
Jasper | 2:18d443d86057 | 413 | p = mTXT(p, moi_local_pglue, moi_txt); |
Jasper | 2:18d443d86057 | 414 | |
Jasper | 2:18d443d86057 | 415 | p = mSRV(p, moi_local_pglue, moi_port, moi_local_name); |
Jasper | 2:18d443d86057 | 416 | |
Jasper | 2:18d443d86057 | 417 | p = mARR(p, moi_local_name, moi_ip); |
Jasper | 2:18d443d86057 | 418 | |
Jasper | 3:b8a78d6da192 | 419 | printf("sendAnnounce2\r\n"); |
Jasper | 2:18d443d86057 | 420 | |
Jasper | 2:18d443d86057 | 421 | m_pUDPSocket->sendTo(quack, out, p-out); |
Jasper | 2:18d443d86057 | 422 | |
Jasper | 2:18d443d86057 | 423 | } |
Jasper | 2:18d443d86057 | 424 | |
Jasper | 2:18d443d86057 | 425 | void mDNSResponder::sendReply(uint16_t t, uint16_t tid, Endpoint *dst) { |
dirkx | 0:1a198985f183 | 426 | // sent a reply - basically a precooked A/PTR/SRV with the TransactionID |
dirkx | 0:1a198985f183 | 427 | // and my URI squeezed in. |
Jasper | 3:b8a78d6da192 | 428 | char *out, *p; |
Jasper | 3:b8a78d6da192 | 429 | out = space; |
dirkx | 0:1a198985f183 | 430 | DNSPacket * op = (DNSPacket *) out; |
dirkx | 0:1a198985f183 | 431 | |
dirkx | 0:1a198985f183 | 432 | initLabelCache(out); // Offsets are relative to the ID header. |
dirkx | 0:1a198985f183 | 433 | |
dirkx | 0:1a198985f183 | 434 | op->tid = ntohs(tid); |
dirkx | 0:1a198985f183 | 435 | op->flags = ntohs(0x8000U); // Answer |
dirkx | 0:1a198985f183 | 436 | op->question_count = ntohs(1); // Courtesy copy of the question. |
dirkx | 0:1a198985f183 | 437 | op->answer_count = ntohs(1); // The record asked for |
dirkx | 0:1a198985f183 | 438 | op->a_count = ntohs(0); |
dirkx | 0:1a198985f183 | 439 | p = out + 12; |
dirkx | 0:1a198985f183 | 440 | |
dirkx | 0:1a198985f183 | 441 | switch (t) { |
dirkx | 0:1a198985f183 | 442 | case DNS_RRTYPE_PTR: // PTR record, SRV, optional TXT and A with my own address. |
dirkx | 0:1a198985f183 | 443 | op->aa_count = ntohs(moi_txt ? 3 : 2); |
dirkx | 0:1a198985f183 | 444 | p = qPTR(p,moi_local_proto); |
dirkx | 0:1a198985f183 | 445 | |
dirkx | 0:1a198985f183 | 446 | p = mPTR(p,moi_local_proto, moi_local_pglue); |
dirkx | 1:bb6472f455e8 | 447 | p = mSRV(p,moi_local_pglue, moi_port, moi_local_name); |
dirkx | 1:bb6472f455e8 | 448 | |
dirkx | 0:1a198985f183 | 449 | if (moi_txt && * moi_txt) |
dirkx | 0:1a198985f183 | 450 | p = mTXT(p,moi_local_pglue,moi_txt); |
dirkx | 0:1a198985f183 | 451 | |
dirkx | 0:1a198985f183 | 452 | break; |
dirkx | 0:1a198985f183 | 453 | case DNS_RRTYPE_A: // A record (and nothing else) |
Jasper | 3:b8a78d6da192 | 454 | op->aa_count = ntohs(0); |
dirkx | 0:1a198985f183 | 455 | p = qA(p,moi_local_name); |
dirkx | 0:1a198985f183 | 456 | break; |
dirkx | 0:1a198985f183 | 457 | |
dirkx | 1:bb6472f455e8 | 458 | case DNS_RRTYPE_SRV: // SRV record, optional TXT and a gratious A record to complete. |
dirkx | 0:1a198985f183 | 459 | op->aa_count = ntohs(moi_txt ? 2 : 1); |
dirkx | 0:1a198985f183 | 460 | p = qSRV(p,moi_local_pglue); |
dirkx | 0:1a198985f183 | 461 | |
dirkx | 1:bb6472f455e8 | 462 | p = mSRV(p,moi_local_pglue, moi_port, moi_local_name); |
dirkx | 0:1a198985f183 | 463 | if (moi_txt && * moi_txt) |
dirkx | 0:1a198985f183 | 464 | p = mTXT(p,moi_local_pglue,moi_txt); |
dirkx | 1:bb6472f455e8 | 465 | break; |
dirkx | 0:1a198985f183 | 466 | } |
Jasper | 3:b8a78d6da192 | 467 | p = mARR(p, moi_local_name, moi_ip); |
Jasper | 2:18d443d86057 | 468 | |
Jasper | 2:18d443d86057 | 469 | printf("sendReply\r\n"); |
Jasper | 2:18d443d86057 | 470 | |
Jasper | 2:18d443d86057 | 471 | if (dst == NULL) { |
Jasper | 2:18d443d86057 | 472 | dst = multicast_group; |
Jasper | 2:18d443d86057 | 473 | } |
Jasper | 2:18d443d86057 | 474 | Endpoint quack; |
Jasper | 2:18d443d86057 | 475 | quack.set_address(dst->get_address(), dst->get_port()); |
Jasper | 3:b8a78d6da192 | 476 | |
Jasper | 3:b8a78d6da192 | 477 | pretty_print_block(out, p - out); |
Jasper | 2:18d443d86057 | 478 | |
Jasper | 2:18d443d86057 | 479 | m_pUDPSocket->sendTo(quack, out, p-out); |
dirkx | 0:1a198985f183 | 480 | } |
dirkx | 0:1a198985f183 | 481 | |
dirkx | 0:1a198985f183 | 482 | char * mDNSResponder::decodeQBlock(char * udp, int len, char *p, char * fqdn, int fqdn_size, uint32_t *Qclass, uint32_t *Qtype) { |
dirkx | 0:1a198985f183 | 483 | char * endp = udp + len; |
dirkx | 0:1a198985f183 | 484 | int depth = 0; |
dirkx | 0:1a198985f183 | 485 | int l, ll = 0; |
dirkx | 0:1a198985f183 | 486 | char * q = 0; |
dirkx | 0:1a198985f183 | 487 | char * ep = fqdn; |
dirkx | 0:1a198985f183 | 488 | |
dirkx | 0:1a198985f183 | 489 | do { |
dirkx | 0:1a198985f183 | 490 | while (((l = *p++) < 192) && (l > 0)) { |
dirkx | 0:1a198985f183 | 491 | if (p + l >= endp) { |
Jasper | 2:18d443d86057 | 492 | printf("Malformed packet or bug, RR field larger than packet itself\n\r"); |
dirkx | 0:1a198985f183 | 493 | return NULL; |
dirkx | 0:1a198985f183 | 494 | }; |
dirkx | 0:1a198985f183 | 495 | |
dirkx | 0:1a198985f183 | 496 | if (ll + l + 1 > fqdn_size) { |
Jasper | 2:18d443d86057 | 497 | printf("Malformed packet or bug, FQDN exceeds %d bytes\n\r", fqdn_size); |
dirkx | 0:1a198985f183 | 498 | return NULL; |
dirkx | 0:1a198985f183 | 499 | } |
dirkx | 0:1a198985f183 | 500 | |
dirkx | 0:1a198985f183 | 501 | memcpy(ep,p,l); |
dirkx | 0:1a198985f183 | 502 | ep[l]='.'; |
dirkx | 0:1a198985f183 | 503 | ep += l + 1; |
dirkx | 0:1a198985f183 | 504 | p += l; |
dirkx | 0:1a198985f183 | 505 | ll += l + 1; |
dirkx | 0:1a198985f183 | 506 | }; |
dirkx | 0:1a198985f183 | 507 | |
dirkx | 0:1a198985f183 | 508 | if (l >= 192) { |
dirkx | 0:1a198985f183 | 509 | // construct an offset pointer by wiping the top 1 bits |
dirkx | 0:1a198985f183 | 510 | // and then getting the remaining 8 bytes to make 14. |
dirkx | 0:1a198985f183 | 511 | l -= 192; |
dirkx | 0:1a198985f183 | 512 | l = l << 8; |
dirkx | 0:1a198985f183 | 513 | l += *p++; |
dirkx | 0:1a198985f183 | 514 | |
dirkx | 0:1a198985f183 | 515 | // rescue our reference; as we've not gotten the Qt's yet |
dirkx | 0:1a198985f183 | 516 | // and these follow the last entry in our record (and not |
dirkx | 0:1a198985f183 | 517 | // that from the compressed values. |
dirkx | 0:1a198985f183 | 518 | // |
dirkx | 0:1a198985f183 | 519 | if (!q) q = p; |
dirkx | 0:1a198985f183 | 520 | |
dirkx | 0:1a198985f183 | 521 | // printf(" [->%d] ",l); |
dirkx | 0:1a198985f183 | 522 | p = udp + l; |
dirkx | 0:1a198985f183 | 523 | |
dirkx | 0:1a198985f183 | 524 | if (p >= udp + len || p < udp + 12) { |
Jasper | 2:18d443d86057 | 525 | printf("Malformed packet or bug, pointer outside UDP packet\n\r"); |
dirkx | 0:1a198985f183 | 526 | return NULL; |
dirkx | 0:1a198985f183 | 527 | }; |
dirkx | 0:1a198985f183 | 528 | }; |
dirkx | 0:1a198985f183 | 529 | |
dirkx | 0:1a198985f183 | 530 | if (depth++ >= 128) { |
Jasper | 2:18d443d86057 | 531 | printf("Malformed packet or bug, depth too high\n\r"); |
dirkx | 0:1a198985f183 | 532 | return NULL; |
dirkx | 0:1a198985f183 | 533 | }; |
dirkx | 0:1a198985f183 | 534 | } while (l); |
dirkx | 0:1a198985f183 | 535 | |
dirkx | 0:1a198985f183 | 536 | // Terminate the FQDN string. |
dirkx | 0:1a198985f183 | 537 | *ep = 0; |
dirkx | 0:1a198985f183 | 538 | |
dirkx | 0:1a198985f183 | 539 | // in case no compression was used at all. |
dirkx | 0:1a198985f183 | 540 | if (!q) |
dirkx | 0:1a198985f183 | 541 | q = p; |
dirkx | 0:1a198985f183 | 542 | |
dirkx | 0:1a198985f183 | 543 | *Qtype = htons(q[0] + q[1]*256); |
dirkx | 0:1a198985f183 | 544 | *Qclass = htons(q[2] + q[3]*256); |
dirkx | 0:1a198985f183 | 545 | return p; |
dirkx | 0:1a198985f183 | 546 | } |
dirkx | 0:1a198985f183 | 547 | |
Jasper | 2:18d443d86057 | 548 | void mDNSResponder::periodic(void const *n) { |
Jasper | 2:18d443d86057 | 549 | /* send this every timeout */ |
Jasper | 2:18d443d86057 | 550 | mDNSResponder::sendAnnounce(); |
Jasper | 2:18d443d86057 | 551 | } |
Jasper | 2:18d443d86057 | 552 | |
Jasper | 3:b8a78d6da192 | 553 | /* |
Jasper | 3:b8a78d6da192 | 554 | Do we support _services._dns-sd._udp.local as well??!? |
Jasper | 3:b8a78d6da192 | 555 | */ |
Jasper | 2:18d443d86057 | 556 | void mDNSResponder::Listen(void const *args) { |
Jasper | 2:18d443d86057 | 557 | Endpoint from; |
dirkx | 0:1a198985f183 | 558 | int len; |
dirkx | 0:1a198985f183 | 559 | |
Jasper | 2:18d443d86057 | 560 | printf("in Listen\r\n"); |
Jasper | 2:18d443d86057 | 561 | |
dirkx | 0:1a198985f183 | 562 | // parse through the packet; find any PTR requests |
dirkx | 0:1a198985f183 | 563 | // and respond to any for _http._tcp._local. |
Jasper | 2:18d443d86057 | 564 | while (true) { |
Jasper | 2:18d443d86057 | 565 | printf("about to receive\r\n"); |
Jasper | 2:18d443d86057 | 566 | len = m_pUDPSocket->receiveFrom(from, space, sizeof(space)); |
Jasper | 2:18d443d86057 | 567 | printf("Got a packet: %s %d\r\n", from.get_address(), len); |
Jasper | 2:18d443d86057 | 568 | DNSPacket * dp = (DNSPacket *) space; |
dirkx | 0:1a198985f183 | 569 | |
dirkx | 0:1a198985f183 | 570 | unsigned int tid = ntohs(dp->tid); |
dirkx | 0:1a198985f183 | 571 | unsigned int flags = ntohs(dp->flags); |
dirkx | 0:1a198985f183 | 572 | unsigned int nQ = ntohs(dp->question_count); |
dirkx | 0:1a198985f183 | 573 | |
Jasper | 2:18d443d86057 | 574 | if (flags & 2 != 0 || nQ < 1) { |
Jasper | 2:18d443d86057 | 575 | printf("Not a Question\r\n"); |
dirkx | 0:1a198985f183 | 576 | continue; // we only want questions |
Jasper | 2:18d443d86057 | 577 | } |
dirkx | 0:1a198985f183 | 578 | |
dirkx | 0:1a198985f183 | 579 | // assume nQ NON terminated fields followed by Qtype & Qclass |
dirkx | 0:1a198985f183 | 580 | // |
Jasper | 2:18d443d86057 | 581 | char * p = space + 12; |
dirkx | 0:1a198985f183 | 582 | for (int i = 0; i < nQ; i++) { |
dirkx | 0:1a198985f183 | 583 | char fqdn[ 256 ]; |
dirkx | 0:1a198985f183 | 584 | uint32_t Qt, Qc; |
dirkx | 0:1a198985f183 | 585 | |
Jasper | 2:18d443d86057 | 586 | if ( (p = decodeQBlock(space, len, p, fqdn, sizeof(fqdn), &Qc, &Qt)) == 0) |
Jasper | 2:18d443d86057 | 587 | break; |
dirkx | 0:1a198985f183 | 588 | |
dirkx | 0:1a198985f183 | 589 | // We only deal with INternet. |
dirkx | 0:1a198985f183 | 590 | // |
dirkx | 0:1a198985f183 | 591 | if (Qc != DNS_RRCLASS_IN) |
dirkx | 0:1a198985f183 | 592 | continue; |
dirkx | 0:1a198985f183 | 593 | |
Jasper | 2:18d443d86057 | 594 | printf("IN query 0x%x for %s\n\r", Qt, fqdn); |
dirkx | 0:1a198985f183 | 595 | |
dirkx | 0:1a198985f183 | 596 | // Normally we'll respond to a mCast query for the PTR of our conceptual |
dirkx | 0:1a198985f183 | 597 | // service; to which we reply with the services we run; and then the A |
dirkx | 0:1a198985f183 | 598 | // records for our actual endpoint. However if one of the requistors their |
dirkx | 0:1a198985f183 | 599 | // cashing is not up to scratch - we may (also) get hit up a bit later for |
dirkx | 0:1a198985f183 | 600 | // the secondary records under their logical names. So we respond to |
dirkx | 0:1a198985f183 | 601 | // all 3. As this is likely to happen due to resource constraints on the |
dirkx | 0:1a198985f183 | 602 | // side of the requestor; we are careful and reply as 'narrow' as possible. |
dirkx | 0:1a198985f183 | 603 | // |
dirkx | 0:1a198985f183 | 604 | // Note that we also respond to the ANY query - as to make a quick 'dig' |
dirkx | 0:1a198985f183 | 605 | // testing command easier. |
dirkx | 0:1a198985f183 | 606 | // |
dirkx | 0:1a198985f183 | 607 | if ((Qt == DNS_RRTYPE_PTR || Qt == 255) && !(strcmp(fqdn,moi_local_proto))) |
Jasper | 2:18d443d86057 | 608 | sendReply(DNS_RRTYPE_PTR, tid, &from); |
dirkx | 0:1a198985f183 | 609 | else if ((Qt == DNS_RRTYPE_A || Qt == 255) && !(strcmp(fqdn,moi_local_name))) |
Jasper | 2:18d443d86057 | 610 | sendReply(DNS_RRTYPE_A, tid, &from); |
dirkx | 0:1a198985f183 | 611 | else if ((Qt == DNS_RRTYPE_SRV || Qt == 255) && !(strcmp(fqdn,moi_local_pglue))) |
Jasper | 2:18d443d86057 | 612 | sendReply(DNS_RRTYPE_SRV, tid, &from); |
dirkx | 0:1a198985f183 | 613 | else |
Jasper | 2:18d443d86057 | 614 | printf(".. which was ignored\n\r"); |
Jasper | 2:18d443d86057 | 615 | } |
dirkx | 0:1a198985f183 | 616 | } |
dirkx | 0:1a198985f183 | 617 | } |
Jasper | 2:18d443d86057 | 618 | |
dirkx | 0:1a198985f183 | 619 | #endif |