Bonjour/Zerconf library

Dependencies:   mbed

Committer:
dirkx
Date:
Thu Jul 22 00:08:38 2010 +0000
Revision:
1:59820ca5c83a
Parent:
0:355018f44c9f
Child:
2:816cbd922d3e

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dirkx 0:355018f44c9f 1 /* Class: mDNSResponder
dirkx 0:355018f44c9f 2 * Copyright 1991, 2003, 2010 Dirk-Willem van Gulik <dirkx(at)apache(punto)org>
dirkx 0:355018f44c9f 3 *
dirkx 0:355018f44c9f 4 * License: Any BSD or ASF License.
dirkx 0:355018f44c9f 5 *
dirkx 0:355018f44c9f 6 * Rough and ready port of some mDNS code.
dirkx 0:355018f44c9f 7 *
dirkx 0:355018f44c9f 8 * Typical use is something like
dirkx 0:355018f44c9f 9 *
dirkx 0:355018f44c9f 10 * EthernetNetIf eth;
dirkx 0:355018f44c9f 11 * HTTPServer svr;
dirkx 0:355018f44c9f 12 * mDNSResponder mdns;
dirkx 0:355018f44c9f 13 *
dirkx 0:355018f44c9f 14 * int main()...
dirkx 0:355018f44c9f 15 *
dirkx 0:355018f44c9f 16 * // get internet
dirkx 0:355018f44c9f 17 * EthernetErr ethErr = eth.setup();
dirkx 0:355018f44c9f 18 * ... etc ..
dirkx 0:355018f44c9f 19 *
dirkx 0:355018f44c9f 20 * // set up some server
dirkx 0:355018f44c9f 21 * svr.addHandler<SimpleHandler>("/"); //Default handler
dirkx 0:355018f44c9f 22 * svr.bind(80); * *
dirkx 0:355018f44c9f 23
dirkx 0:355018f44c9f 24 * // Extract the IP address.
dirkx 0:355018f44c9f 25 * IpAddr ip = eth.getIp();
dirkx 0:355018f44c9f 26 * printf("mbed IP Address is %d.%d.%d.%d\r\n", ip[0], ip[1], ip[2], ip[3]);
dirkx 0:355018f44c9f 27 *
dirkx 0:355018f44c9f 28 * // Announce ourselves.
dirkx 1:59820ca5c83a 29 * mdns.announce(ip, "fred", "_http._tcp", 80, "The Little Server that Could", "path=/demo");
dirkx 0:355018f44c9f 30 *
dirkx 0:355018f44c9f 31 * while()... enter some run loop
dirkx 1:59820ca5c83a 32 * ...
dirkx 1:59820ca5c83a 33 *
dirkx 1:59820ca5c83a 34 * This will cause http://fred.local./demo to be announced as 'The Little Server that Could'.
dirkx 1:59820ca5c83a 35 *
dirkx 1:59820ca5c83a 36 * Or as another example: (http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt)
dirkx 1:59820ca5c83a 37 * and the various RFCs:
dirkx 0:355018f44c9f 38 *
dirkx 0:355018f44c9f 39 * mdns.announce(ip, "_ssh._tcp", 22, SSH to Serial Gateway", NULL);
dirkx 0:355018f44c9f 40 *
dirkx 0:355018f44c9f 41 * CAVEAT - a lot of the buffer overrun and copy checks
dirkx 0:355018f44c9f 42 * where removed; and this is not anywhere near
dirkx 0:355018f44c9f 43 * threadsafve or sane. Not for production use.
dirkx 0:355018f44c9f 44 */
dirkx 0:355018f44c9f 45
dirkx 0:355018f44c9f 46 #include "mDNSResponder.h"
dirkx 0:355018f44c9f 47 #include <stdio.h>
dirkx 0:355018f44c9f 48
dirkx 0:355018f44c9f 49 // #define MCAST 192,168,1,71
dirkx 0:355018f44c9f 50
dirkx 0:355018f44c9f 51 mDNSResponder::mDNSResponder() : NetService(false),
dirkx 0:355018f44c9f 52 moi_txt(NULL), moi_port(0), moi_ip(0),
dirkx 0:355018f44c9f 53 moi_name(NULL), moi_proto(NULL),
dirkx 0:355018f44c9f 54 moi_local_proto(NULL), moi_local_name(NULL), moi_local_pglue(NULL),
dirkx 0:355018f44c9f 55 announcer()
dirkx 0:355018f44c9f 56 {
dirkx 0:355018f44c9f 57 // nothing yet...
dirkx 0:355018f44c9f 58 }
dirkx 0:355018f44c9f 59
dirkx 0:355018f44c9f 60 mDNSResponder::~mDNSResponder() {
dirkx 0:355018f44c9f 61 announcer.stop();
dirkx 0:355018f44c9f 62 close();
dirkx 0:355018f44c9f 63 }
dirkx 0:355018f44c9f 64
dirkx 1:59820ca5c83a 65 void mDNSResponder::announce(IpAddr ip, const char * ldn, const char * proto, uint16_t port, const char * name, char ** txt) {
dirkx 0:355018f44c9f 66 Host localhost(IpAddr(MCAST), MDNS_PORT, NULL /* fqdn */);
dirkx 0:355018f44c9f 67
dirkx 0:355018f44c9f 68 m_pUDPSocket = new UDPSocket;
dirkx 0:355018f44c9f 69 m_pUDPSocket->bind(localhost);
dirkx 0:355018f44c9f 70
dirkx 0:355018f44c9f 71 m_pUDPSocket->setOnEvent(this, &mDNSResponder::onUDPSocketEvent);
dirkx 0:355018f44c9f 72
dirkx 0:355018f44c9f 73 moi_port = port;
dirkx 0:355018f44c9f 74 moi_txt = txt;
dirkx 0:355018f44c9f 75 moi_ip = ip;
dirkx 0:355018f44c9f 76 moi_proto = proto;
dirkx 0:355018f44c9f 77 moi_name = name;
dirkx 0:355018f44c9f 78
dirkx 0:355018f44c9f 79 moi_local_proto = (char *)malloc(128);
dirkx 0:355018f44c9f 80 moi_local_name = (char *)malloc(128);
dirkx 0:355018f44c9f 81 moi_local_pglue = (char *)malloc(128);
dirkx 0:355018f44c9f 82
dirkx 0:355018f44c9f 83 #define LOCAL "local"
dirkx 0:355018f44c9f 84 snprintf(moi_local_proto,128,"%s.%s.", moi_proto, LOCAL);
dirkx 1:59820ca5c83a 85 snprintf(moi_local_name,128,"%s.%s.", ldn, LOCAL);
dirkx 0:355018f44c9f 86 snprintf(moi_local_pglue,128,"%s.%s.%s.", moi_name,moi_proto, LOCAL);
dirkx 0:355018f44c9f 87
dirkx 0:355018f44c9f 88 // Gratuis intro - and repeat such regularly..
dirkx 0:355018f44c9f 89 //
dirkx 0:355018f44c9f 90 mDNSResponder::sendReply(0, localhost);
dirkx 0:355018f44c9f 91 announcer.start();
dirkx 0:355018f44c9f 92 }
dirkx 0:355018f44c9f 93
dirkx 0:355018f44c9f 94 void mDNSResponder::close() {
dirkx 0:355018f44c9f 95 m_pUDPSocket->resetOnEvent();
dirkx 0:355018f44c9f 96 m_pUDPSocket->close();
dirkx 0:355018f44c9f 97 delete m_pUDPSocket;
dirkx 0:355018f44c9f 98 }
dirkx 0:355018f44c9f 99
dirkx 0:355018f44c9f 100
dirkx 0:355018f44c9f 101
dirkx 0:355018f44c9f 102 void mDNSResponder::poll() { //Called by NetServices
dirkx 0:355018f44c9f 103 if (announcer.read_ms() > 1000 * MDNS_INTERVAL) {
dirkx 0:355018f44c9f 104
dirkx 0:355018f44c9f 105 Host mch(IpAddr(MCAST), MDNS_PORT, NULL);
dirkx 0:355018f44c9f 106 mDNSResponder::sendReply(0, mch);
dirkx 0:355018f44c9f 107
dirkx 0:355018f44c9f 108 announcer.reset();
dirkx 0:355018f44c9f 109 }
dirkx 0:355018f44c9f 110 }
dirkx 0:355018f44c9f 111
dirkx 0:355018f44c9f 112 char * index(char * str, char c) {
dirkx 0:355018f44c9f 113 for(;str && *str;str++) {
dirkx 0:355018f44c9f 114 if (*str == c) return str;
dirkx 0:355018f44c9f 115 };
dirkx 0:355018f44c9f 116 return NULL;
dirkx 0:355018f44c9f 117 }
dirkx 0:355018f44c9f 118
dirkx 0:355018f44c9f 119 #ifndef THREADINGCOMPRESS
dirkx 0:355018f44c9f 120 #ifndef MAXCACHEDNSLABELS
dirkx 0:355018f44c9f 121 #define MAXCACHEDNSLABELS (10)
dirkx 0:355018f44c9f 122 #endif
dirkx 0:355018f44c9f 123 static int labelCacheCnt = 0;
dirkx 0:355018f44c9f 124 static uint16_t _cache_off[MAXCACHEDNSLABELS];
dirkx 0:355018f44c9f 125 static char * _cache_och[MAXCACHEDNSLABELS];
dirkx 0:355018f44c9f 126 static char * labelCacheOffset = 0;
dirkx 0:355018f44c9f 127
dirkx 0:355018f44c9f 128 void initLabelCache(char * off) {
dirkx 0:355018f44c9f 129 labelCacheOffset = off;
dirkx 0:355018f44c9f 130 labelCacheCnt = 0;
dirkx 0:355018f44c9f 131 memset(_cache_off,0, sizeof(_cache_off)); // Rely on min value to be 12
dirkx 0:355018f44c9f 132 };
dirkx 0:355018f44c9f 133
dirkx 0:355018f44c9f 134 uint16_t checkLabelCache(char * name) {
dirkx 0:355018f44c9f 135 for(int i=0; i < MAXCACHEDNSLABELS; i++)
dirkx 0:355018f44c9f 136 if (_cache_off[i] && !strcmp(_cache_och[i],name))
dirkx 0:355018f44c9f 137 return _cache_off[i];
dirkx 0:355018f44c9f 138 return 0;
dirkx 0:355018f44c9f 139 };
dirkx 0:355018f44c9f 140
dirkx 0:355018f44c9f 141 void addLabelCache(char * p, char * name) {
dirkx 0:355018f44c9f 142 _cache_off[labelCacheCnt] = p - labelCacheOffset;
dirkx 0:355018f44c9f 143 _cache_och[labelCacheCnt] = name;
dirkx 0:355018f44c9f 144
dirkx 0:355018f44c9f 145 labelCacheCnt++;
dirkx 1:59820ca5c83a 146 // we intentionally do not wack the first entries - as they are the most
dirkx 0:355018f44c9f 147 // likely ones to be used.
dirkx 0:355018f44c9f 148 if (labelCacheCnt>=MAXCACHEDNSLABELS)
dirkx 0:355018f44c9f 149 labelCacheCnt = MAXCACHEDNSLABELS / 3;
dirkx 0:355018f44c9f 150 };
dirkx 0:355018f44c9f 151 #else
dirkx 0:355018f44c9f 152 #define initLabelCache(x) {} /* Ignored */
dirkx 0:355018f44c9f 153 #define checkLabelCache(x) (0) /* never a hit */
dirkx 0:355018f44c9f 154 #define addLabelCache(x,y) {} /* Ignored */
dirkx 0:355018f44c9f 155 #endif
dirkx 0:355018f44c9f 156
dirkx 0:355018f44c9f 157 char * breakname(char *p, char *name) {
dirkx 0:355018f44c9f 158 int l = 0, de = 1;
dirkx 0:355018f44c9f 159 char * q;
dirkx 0:355018f44c9f 160 uint16_t off;
dirkx 0:355018f44c9f 161
dirkx 0:355018f44c9f 162 do {
dirkx 0:355018f44c9f 163 if (off = checkLabelCache(name)) {
dirkx 0:355018f44c9f 164 *p++ = 192 + (off >> 8);
dirkx 0:355018f44c9f 165 *p++ = (off & 0xFF);
dirkx 0:355018f44c9f 166 return p;
dirkx 0:355018f44c9f 167 } else {
dirkx 0:355018f44c9f 168 addLabelCache(p, name);
dirkx 0:355018f44c9f 169 };
dirkx 0:355018f44c9f 170
dirkx 0:355018f44c9f 171 q = index(name,'.');
dirkx 0:355018f44c9f 172 if (!q) {
dirkx 0:355018f44c9f 173 q = name + strlen(name);
dirkx 0:355018f44c9f 174 de = 0;
dirkx 0:355018f44c9f 175 };
dirkx 0:355018f44c9f 176 l = q - name;
dirkx 0:355018f44c9f 177 *p++ = l;
dirkx 0:355018f44c9f 178 memcpy(p, name, l);
dirkx 0:355018f44c9f 179 p+=l;
dirkx 0:355018f44c9f 180 name = q + 1;
dirkx 0:355018f44c9f 181 } while(l && *name);
dirkx 0:355018f44c9f 182
dirkx 0:355018f44c9f 183 // terminating root field if any (not the case for
dirkx 0:355018f44c9f 184 // things like TXTs).
dirkx 0:355018f44c9f 185 if (de) *p++ = 0;
dirkx 0:355018f44c9f 186 return p;
dirkx 0:355018f44c9f 187 }
dirkx 0:355018f44c9f 188
dirkx 0:355018f44c9f 189 char * mRR(char *p, char * name, uint16_t tpe, uint16_t cls, uint32_t ttl)
dirkx 0:355018f44c9f 190 {
dirkx 0:355018f44c9f 191 uint16_t i;
dirkx 0:355018f44c9f 192 uint32_t j;
dirkx 0:355018f44c9f 193
dirkx 0:355018f44c9f 194 p = breakname(p, name);
dirkx 0:355018f44c9f 195
dirkx 0:355018f44c9f 196 // NOTE: Cannot assume proper byte boundaries.
dirkx 0:355018f44c9f 197 //
dirkx 0:355018f44c9f 198 i = htons(tpe); // Type
dirkx 0:355018f44c9f 199 memcpy(p, &i, 2);
dirkx 0:355018f44c9f 200 p+=2;
dirkx 0:355018f44c9f 201
dirkx 0:355018f44c9f 202 i = htons(cls); // Class
dirkx 0:355018f44c9f 203 memcpy(p, &i, 2);
dirkx 0:355018f44c9f 204 p+=2;
dirkx 0:355018f44c9f 205
dirkx 0:355018f44c9f 206 j = htonl(ttl); // TTL (4 bytes)
dirkx 0:355018f44c9f 207 memcpy(p, &j, 4);
dirkx 0:355018f44c9f 208 p+=4;
dirkx 0:355018f44c9f 209
dirkx 0:355018f44c9f 210 return p;
dirkx 0:355018f44c9f 211 }
dirkx 0:355018f44c9f 212
dirkx 1:59820ca5c83a 213 char * mRRLABEL(char *p, char * name, uint16_t tpe, char ** rr) {
dirkx 0:355018f44c9f 214 uint16_t i;
dirkx 0:355018f44c9f 215
dirkx 0:355018f44c9f 216 p = mRR(p, name, tpe, 1, MDNS_TTL); // Type, IN, TTL
dirkx 0:355018f44c9f 217
dirkx 0:355018f44c9f 218 // RR String
dirkx 0:355018f44c9f 219 char * q = p + 2;
dirkx 1:59820ca5c83a 220
dirkx 1:59820ca5c83a 221 for(;*rr;rr++)
dirkx 1:59820ca5c83a 222 q = breakname(q, *rr);
dirkx 1:59820ca5c83a 223
dirkx 0:355018f44c9f 224 i = htons(q - p - 2); // RDLEN
dirkx 0:355018f44c9f 225 memcpy(p, &i, 2);
dirkx 0:355018f44c9f 226 return q;
dirkx 0:355018f44c9f 227 }
dirkx 0:355018f44c9f 228
dirkx 1:59820ca5c83a 229 char * mPTR(char *p, char * name, char * r) {
dirkx 1:59820ca5c83a 230 char *rr[] = { r, NULL };
dirkx 1:59820ca5c83a 231 return mRRLABEL(p, name, 12 /* PTR */, rr );
dirkx 0:355018f44c9f 232 }
dirkx 0:355018f44c9f 233
dirkx 1:59820ca5c83a 234 char * mTXT(char *p, char * name, char ** rr) {
dirkx 0:355018f44c9f 235 return mRRLABEL(p, name, 16 /* TXT */, rr);
dirkx 0:355018f44c9f 236 }
dirkx 0:355018f44c9f 237
dirkx 0:355018f44c9f 238 char * mARR(char *p, char * name, IpAddr ip) {
dirkx 0:355018f44c9f 239 uint16_t i;
dirkx 0:355018f44c9f 240
dirkx 0:355018f44c9f 241 p = mRR(p, name, 1, 1, MDNS_TTL ); // A, IN
dirkx 0:355018f44c9f 242
dirkx 0:355018f44c9f 243 i = htons(4); // RDLEN - we're just doing a single IPv4 address - our primary link ?
dirkx 0:355018f44c9f 244 memcpy(p, &i, 2);
dirkx 0:355018f44c9f 245
dirkx 0:355018f44c9f 246 // IP already in network order.
dirkx 0:355018f44c9f 247 memcpy(p+2, &ip, 4);
dirkx 0:355018f44c9f 248
dirkx 0:355018f44c9f 249 return p + 2 + 4;
dirkx 0:355018f44c9f 250 }
dirkx 0:355018f44c9f 251
dirkx 0:355018f44c9f 252 char * mSRV(char *p, char * name, uint16_t port, char * rr) {
dirkx 0:355018f44c9f 253 uint16_t i;
dirkx 0:355018f44c9f 254 char * q;
dirkx 0:355018f44c9f 255
dirkx 0:355018f44c9f 256 p = mRR(p, name, 33, 1, MDNS_TTL); // SRV, IN
dirkx 0:355018f44c9f 257
dirkx 0:355018f44c9f 258 // Keep space for RDLEN
dirkx 0:355018f44c9f 259 q = p; p+=2;
dirkx 0:355018f44c9f 260
dirkx 0:355018f44c9f 261 i = htons(1); // Priority
dirkx 0:355018f44c9f 262 memcpy(p, &i, 2); p+=2;
dirkx 0:355018f44c9f 263
dirkx 0:355018f44c9f 264 i = htons(0); // Weight (see rfc2782)
dirkx 0:355018f44c9f 265 memcpy(p, &i, 2); p+=2;
dirkx 0:355018f44c9f 266
dirkx 0:355018f44c9f 267 i = htons(port); // Port
dirkx 0:355018f44c9f 268 memcpy(p, &i, 2); p+=2;
dirkx 0:355018f44c9f 269
dirkx 0:355018f44c9f 270 p = breakname(p, rr);
dirkx 0:355018f44c9f 271
dirkx 0:355018f44c9f 272 i = htons(p - q - 2); // RDLEN
dirkx 0:355018f44c9f 273 memcpy(q, &i, 2);
dirkx 0:355018f44c9f 274
dirkx 0:355018f44c9f 275 return p;
dirkx 0:355018f44c9f 276 }
dirkx 0:355018f44c9f 277
dirkx 0:355018f44c9f 278 char * qANY(char *p, char * name, uint16_t tpe, uint16_t cls) {
dirkx 0:355018f44c9f 279 uint16_t i;
dirkx 0:355018f44c9f 280 p = breakname(p, name); // QNAME
dirkx 0:355018f44c9f 281
dirkx 0:355018f44c9f 282 i = htons(tpe); // QTYPE
dirkx 0:355018f44c9f 283 memcpy(p, &i, 2); p+=2;
dirkx 0:355018f44c9f 284
dirkx 0:355018f44c9f 285 i = htons(cls); // QCLASS
dirkx 0:355018f44c9f 286 memcpy(p, &i, 2); p+=2;
dirkx 0:355018f44c9f 287
dirkx 0:355018f44c9f 288 return p;
dirkx 0:355018f44c9f 289 }
dirkx 0:355018f44c9f 290
dirkx 0:355018f44c9f 291 char * qPTR(char *p, char *name) {
dirkx 0:355018f44c9f 292 return qANY(p,name,12 /* PTR */,1);
dirkx 0:355018f44c9f 293 }
dirkx 0:355018f44c9f 294
dirkx 0:355018f44c9f 295
dirkx 0:355018f44c9f 296 void mDNSResponder::sendReply(uint16_t tid, Host dst) {
dirkx 0:355018f44c9f 297 // sent a reply - basically a precooked A/PTR/SRV with the TransactionID
dirkx 0:355018f44c9f 298 // and my URI squeezed in.
dirkx 0:355018f44c9f 299 char out[ 1500 ], *p;
dirkx 0:355018f44c9f 300 DNSPacket * op = (DNSPacket *) out;
dirkx 0:355018f44c9f 301
dirkx 0:355018f44c9f 302 initLabelCache(out); // Offsets are relative to the ID header.
dirkx 0:355018f44c9f 303
dirkx 0:355018f44c9f 304 op->tid = ntohs(tid);
dirkx 0:355018f44c9f 305 op->flags = ntohs(0x8000U); // Answer
dirkx 0:355018f44c9f 306 op->question_count = ntohs(1); // Courtesy copy of the question.
dirkx 0:355018f44c9f 307 op->answer_count = ntohs(1); // The PTR record asked for
dirkx 0:355018f44c9f 308 op->a_count = ntohs(0);
dirkx 0:355018f44c9f 309
dirkx 0:355018f44c9f 310 // The 2 or 3 extra records (A, SRV and optional TXT) we know will be needed next
dirkx 0:355018f44c9f 311 op->aa_count = ntohs(moi_txt ? 3 : 2);
dirkx 0:355018f44c9f 312
dirkx 0:355018f44c9f 313 p = out + 12;
dirkx 0:355018f44c9f 314
dirkx 0:355018f44c9f 315 p = qPTR(p,moi_local_proto);
dirkx 0:355018f44c9f 316 p = mPTR(p,moi_local_proto, moi_local_pglue);
dirkx 0:355018f44c9f 317 p = mSRV(p,moi_local_pglue,80, moi_local_name);
dirkx 1:59820ca5c83a 318 if (moi_txt && * moi_txt)
dirkx 1:59820ca5c83a 319 p = mTXT(p,moi_local_pglue,moi_txt);
dirkx 0:355018f44c9f 320 p = mARR(p,moi_local_name,moi_ip); // fill out my own IP address.
dirkx 0:355018f44c9f 321
dirkx 0:355018f44c9f 322 m_pUDPSocket->sendto(out,p-out,&dst);
dirkx 0:355018f44c9f 323 }
dirkx 0:355018f44c9f 324
dirkx 0:355018f44c9f 325 void mDNSResponder::onUDPSocketEvent(UDPSocketEvent e) {
dirkx 0:355018f44c9f 326 char udp[ 1500 ];
dirkx 0:355018f44c9f 327 Host from;
dirkx 0:355018f44c9f 328 int len;
dirkx 0:355018f44c9f 329
dirkx 0:355018f44c9f 330 switch (e) {
dirkx 0:355018f44c9f 331 case UDPSOCKET_READABLE: //The only event for now
dirkx 0:355018f44c9f 332 // parse through the packet; find any PTR requests
dirkx 0:355018f44c9f 333 // and respond to any for _http._tcp._local.
dirkx 0:355018f44c9f 334 while ( len = m_pUDPSocket->recvfrom( (char*)&udp, sizeof(udp), &from )) {
dirkx 0:355018f44c9f 335 DNSPacket * dp = (DNSPacket *) udp;
dirkx 0:355018f44c9f 336 unsigned int tid = ntohs(dp->tid);
dirkx 0:355018f44c9f 337 unsigned int flags = ntohs(dp->flags);
dirkx 0:355018f44c9f 338 unsigned int nQ = ntohs(dp->question_count);
dirkx 0:355018f44c9f 339 unsigned int nA = ntohs(dp->answer_count);
dirkx 0:355018f44c9f 340
dirkx 0:355018f44c9f 341 if (flags & 2 != 0 || nQ == 0)
dirkx 0:355018f44c9f 342 continue; // we only want questions
dirkx 0:355018f44c9f 343
dirkx 0:355018f44c9f 344 #define MAXDEPTH 64
dirkx 0:355018f44c9f 345 #define MAXRR 192 /* including dot */
dirkx 1:59820ca5c83a 346
dirkx 0:355018f44c9f 347 // assume nQ zero terminated fields followed by Qtype & Qclass
dirkx 0:355018f44c9f 348 char * p = udp + 12;
dirkx 0:355018f44c9f 349 for (int i = 0; i < nQ; i++) {
dirkx 0:355018f44c9f 350 char buff[ MAXDEPTH * MAXRR ], * ep = buff;
dirkx 0:355018f44c9f 351 int depth = 0;
dirkx 0:355018f44c9f 352 int l;
dirkx 0:355018f44c9f 353 char * q = 0;
dirkx 0:355018f44c9f 354
dirkx 0:355018f44c9f 355 do {
dirkx 0:355018f44c9f 356 while (((l = *p++) < 192) && (l > 0)) {
dirkx 0:355018f44c9f 357 if (p + l >= udp + len) {
dirkx 0:355018f44c9f 358 printf("RR longer than packet\r\n");
dirkx 0:355018f44c9f 359 return;
dirkx 0:355018f44c9f 360 };
dirkx 0:355018f44c9f 361
dirkx 0:355018f44c9f 362 memcpy(ep,p,l);
dirkx 0:355018f44c9f 363 ep[l]='.';
dirkx 0:355018f44c9f 364 ep += l + 1;
dirkx 0:355018f44c9f 365 // printf("%d:%s.", p-udp-12,buff);
dirkx 0:355018f44c9f 366 p += l;
dirkx 0:355018f44c9f 367 };
dirkx 0:355018f44c9f 368 if (l >= 192) {
dirkx 0:355018f44c9f 369 // construct an offset pointer by wiping the top 1 bits
dirkx 0:355018f44c9f 370 // and then getting the remaining 8 bytes to make 14.
dirkx 0:355018f44c9f 371 l -= 192;
dirkx 0:355018f44c9f 372 l = l << 8;
dirkx 0:355018f44c9f 373 l += *p++;
dirkx 0:355018f44c9f 374 // rescue our reference; as we've not gotten the Qt's yet.
dirkx 0:355018f44c9f 375 if (!q) q = p;
dirkx 0:355018f44c9f 376
dirkx 0:355018f44c9f 377 // printf(" [->%d] ",l);
dirkx 0:355018f44c9f 378 p = udp + l;
dirkx 0:355018f44c9f 379
dirkx 0:355018f44c9f 380 if (p >= udp + len || p < udp + 12) {
dirkx 0:355018f44c9f 381 printf("Pointer to wrong place\r\n");
dirkx 0:355018f44c9f 382 return;
dirkx 0:355018f44c9f 383 };
dirkx 0:355018f44c9f 384 };
dirkx 0:355018f44c9f 385 if (depth++ >= MAXDEPTH) {
dirkx 0:355018f44c9f 386 printf("Too deep\r\n");
dirkx 0:355018f44c9f 387 return;
dirkx 0:355018f44c9f 388 };
dirkx 0:355018f44c9f 389 } while (l);
dirkx 0:355018f44c9f 390 *ep = 0;
dirkx 0:355018f44c9f 391 // in case no compression was used at all.
dirkx 0:355018f44c9f 392 if (!q) q = p;
dirkx 0:355018f44c9f 393
dirkx 0:355018f44c9f 394 unsigned int Qt = htons(q[0] + q[1]*256);
dirkx 0:355018f44c9f 395 unsigned int Qc = htons(q[2] + q[3]*256);
dirkx 0:355018f44c9f 396 p = q + 4;
dirkx 1:59820ca5c83a 397
dirkx 1:59820ca5c83a 398 printf("Q for %s\r\n", buff);
dirkx 0:355018f44c9f 399 // We want PTR records on the INternet of our type
dirkx 0:355018f44c9f 400 if ((Qt == 12) && (Qc == 1) && !(strcmp(buff,moi_local_proto)))
dirkx 0:355018f44c9f 401 sendReply(tid,from);
dirkx 0:355018f44c9f 402 };
dirkx 0:355018f44c9f 403 }
dirkx 0:355018f44c9f 404 break;
dirkx 0:355018f44c9f 405 }
dirkx 0:355018f44c9f 406 }
dirkx 0:355018f44c9f 407
dirkx 0:355018f44c9f 408