~jsvoboda/helenos/dnsr

« back to all changes in this revision

Viewing changes to uspace/srv/net/dnsres/dns_msg.c

  • Committer: Jiri Svoboda
  • Date: 2013-04-20 09:03:34 UTC
  • Revision ID: jiri@wiwaxia-20130420090334-2aelzf342o6ea6aa
Attempt decoding response (no pointer support).

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
#include <bitops.h>
37
37
#include <byteorder.h>
38
38
#include <errno.h>
 
39
#include <macros.h>
39
40
#include <stdint.h>
40
41
#include <stdlib.h>
41
42
#include <str.h>
108
109
        return EOK;
109
110
}
110
111
 
 
112
static int dns_name_decode(uint8_t *buf, size_t size, char **rname,
 
113
    size_t *act_size)
 
114
{
 
115
        uint8_t *bp;
 
116
        size_t bsize;
 
117
        size_t lsize;
 
118
        size_t i;
 
119
 
 
120
        bp = buf;
 
121
        bsize = min(size, DNS_NAME_MAX_SIZE);
 
122
 
 
123
        while (true) {
 
124
                if (bsize == 0) {
 
125
                        return EINVAL;
 
126
                }
 
127
 
 
128
 
 
129
                lsize = *bp;
 
130
                ++bp;
 
131
                --bsize;
 
132
 
 
133
                if (lsize == 0)
 
134
                        break;
 
135
 
 
136
                if (bp != buf + 1)
 
137
                        printf(".");
 
138
 
 
139
                if ((lsize & 0xc0) == 0xc0) {
 
140
                        /* Pointer */
 
141
                        printf("compression not supported!\n");
 
142
                        return EINVAL;
 
143
                }
 
144
 
 
145
                if (lsize > bsize) {
 
146
                        return EINVAL;
 
147
                }
 
148
 
 
149
                for (i = 0; i < lsize; i++) {
 
150
                        printf("%c", *bp);
 
151
                        ++bp;
 
152
                        --bsize;
 
153
                }
 
154
        }
 
155
 
 
156
        printf("\n");
 
157
 
 
158
        *act_size = bp - buf;
 
159
        return EOK;
 
160
}
 
161
 
 
162
/** Decode unaligned big-endian 16-bit integer */
 
163
static uint16_t dns_uint16_t_decode(uint8_t *buf, size_t buf_size)
 
164
{
 
165
        assert(buf_size >= 2);
 
166
 
 
167
        return ((uint16_t)buf[0] << 8) + buf[1];
 
168
}
 
169
 
 
170
/** Encode unaligned big-endian 16-bit integer */
111
171
static void dns_uint16_t_encode(uint16_t w, uint8_t *buf, size_t buf_size)
112
172
{
113
173
        if (buf != NULL && buf_size >= 1)
117
177
                buf[1] = w & 0xff;
118
178
}
119
179
 
 
180
/** Decode unaligned big-endian 32-bit integer */
 
181
static uint16_t dns_uint32_t_decode(uint8_t *buf, size_t buf_size)
 
182
{
 
183
        assert(buf_size >= 4);
 
184
 
 
185
        return ((uint32_t)buf[0] << 24) +
 
186
            ((uint32_t)buf[1] << 16) +
 
187
            ((uint32_t)buf[2] << 8) +
 
188
            buf[0];
 
189
}
 
190
 
120
191
static int dns_question_encode(dns_question_t *question, uint8_t *buf,
121
192
    size_t buf_size, size_t *act_size)
122
193
{
146
217
        return EOK;
147
218
}
148
219
 
 
220
static int dns_question_decode(uint8_t *buf, size_t buf_size,
 
221
    dns_question_t **rquestion, size_t *act_size)
 
222
{
 
223
        dns_question_t *question;
 
224
        size_t name_size;
 
225
        int rc;
 
226
 
 
227
        question = calloc(1, sizeof (dns_question_t));
 
228
        if (question == NULL)
 
229
                return ENOMEM;
 
230
 
 
231
        printf("decode name..\n");
 
232
        rc = dns_name_decode(buf, buf_size, &question->qname, &name_size);
 
233
        if (rc != EOK) {
 
234
                printf("error decoding name..\n");
 
235
                free(question);
 
236
                return ENOMEM;
 
237
        }
 
238
 
 
239
        printf("ok decoding name..\n");
 
240
        if (name_size + 2 * sizeof(uint16_t) > buf_size) {
 
241
                printf("name_size + 2 * 2 = %d >  buf_size = %d\n",
 
242
                    name_size + 2 * sizeof(uint16_t), buf_size);
 
243
                free(question);
 
244
                return EINVAL;
 
245
        }
 
246
 
 
247
        question->qtype = dns_uint16_t_decode(buf + name_size, buf_size - name_size);
 
248
        question->qclass = dns_uint16_t_decode(buf + sizeof(uint16_t) + name_size,
 
249
            buf_size - sizeof(uint16_t) - name_size);
 
250
        *act_size = name_size + 2 * sizeof(uint16_t);
 
251
 
 
252
        *rquestion = question;
 
253
        return EOK;
 
254
}
 
255
 
 
256
static int dns_rr_decode(uint8_t *buf, size_t buf_size,
 
257
    dns_rr_t **retrr, size_t *act_size)
 
258
{
 
259
        dns_rr_t *rr;
 
260
        size_t name_size;
 
261
        uint8_t *bp;
 
262
        size_t bsz;
 
263
        size_t rdlength;
 
264
        int rc;
 
265
 
 
266
        rr = calloc(1, sizeof (dns_rr_t));
 
267
        if (rr == NULL)
 
268
                return ENOMEM;
 
269
 
 
270
        printf("decode name..\n");
 
271
        rc = dns_name_decode(buf, buf_size, &rr->name, &name_size);
 
272
        if (rc != EOK) {
 
273
                printf("error decoding name..\n");
 
274
                free(rr);
 
275
                return ENOMEM;
 
276
        }
 
277
 
 
278
        printf("ok decoding name..\n");
 
279
        if (name_size + 2 * sizeof(uint16_t) > buf_size) {
 
280
                printf("name_size + 2 * 2 = %d >  buf_size = %d\n",
 
281
                    name_size + 2 * sizeof(uint16_t), buf_size);
 
282
                free(rr->name);
 
283
                free(rr);
 
284
                return EINVAL;
 
285
        }
 
286
 
 
287
        bp = buf + name_size;
 
288
        bsz = buf_size - name_size;
 
289
 
 
290
        if (bsz < 3 * sizeof(uint16_t) + sizeof(uint32_t)) {
 
291
                free(rr->name);
 
292
                free(rr);
 
293
                return EINVAL;
 
294
        }
 
295
 
 
296
        rr->rtype = dns_uint16_t_decode(bp, bsz);
 
297
        bp += sizeof(uint16_t); bsz -= sizeof(uint16_t);
 
298
 
 
299
        rr->rclass = dns_uint16_t_decode(bp, bsz);
 
300
        bp += sizeof(uint16_t); bsz -= sizeof(uint16_t);
 
301
 
 
302
        rr->ttl = dns_uint32_t_decode(bp, bsz);
 
303
        bp += sizeof(uint32_t); bsz -= sizeof(uint32_t);
 
304
 
 
305
        rdlength = dns_uint16_t_decode(bp, bsz);
 
306
        bp += sizeof(uint16_t); bsz -= sizeof(uint16_t);
 
307
 
 
308
        if (rdlength > bsz) {
 
309
                free(rr->name);
 
310
                free(rr);
 
311
                return EINVAL;
 
312
        }
 
313
 
 
314
        rr->rdata_size = rdlength;
 
315
        rr->rdata = calloc(1, sizeof(rdlength));
 
316
        if (rr->rdata == NULL) {
 
317
                free(rr->name);
 
318
                free(rr);
 
319
                return ENOMEM;
 
320
        }
 
321
 
 
322
        memcpy(rr->rdata, bp, rdlength);
 
323
        bp += rdlength;
 
324
        bsz -= rdlength;
 
325
 
 
326
        *act_size = bp - buf;
 
327
        *retrr = rr;
 
328
        return EOK;
 
329
}
 
330
 
149
331
int dns_message_encode(dns_message_t *msg, void **rdata, size_t *rsize)
150
332
{
151
333
        uint8_t *data;
206
388
        return EOK;
207
389
}
208
390
 
 
391
int dns_message_decode(void *data, size_t size, dns_message_t **rmsg)
 
392
{
 
393
        dns_message_t *msg;
 
394
        dns_header_t *hdr;
 
395
        uint8_t *dp;
 
396
        size_t dsize;
 
397
        size_t field_size;
 
398
        dns_question_t *question;
 
399
        dns_rr_t *rr;
 
400
        size_t qd_count;
 
401
        size_t an_count;
 
402
        size_t i;
 
403
        int rc;
 
404
 
 
405
        msg = calloc(1, sizeof(dns_message_t));
 
406
        if (msg == NULL)
 
407
                return ENOMEM;
 
408
 
 
409
        if (size < sizeof(dns_header_t))
 
410
                return EINVAL;
 
411
 
 
412
        hdr = data;
 
413
 
 
414
        msg->id = uint16_t_be2host(hdr->id);
 
415
        msg->qr = BIT_RANGE_EXTRACT(uint16_t, OPB_QR, OPB_QR, hdr->opbits);
 
416
        msg->opcode = BIT_RANGE_EXTRACT(uint16_t, OPB_OPCODE_h, OPB_OPCODE_l,
 
417
            hdr->opbits);
 
418
        msg->aa = BIT_RANGE_EXTRACT(uint16_t, OPB_AA, OPB_AA, hdr->opbits);
 
419
        msg->tc = BIT_RANGE_EXTRACT(uint16_t, OPB_TC, OPB_TC, hdr->opbits);
 
420
        msg->rd = BIT_RANGE_EXTRACT(uint16_t, OPB_RD, OPB_RD, hdr->opbits);
 
421
        msg->ra = BIT_RANGE_EXTRACT(uint16_t, OPB_RA, OPB_RA, hdr->opbits);
 
422
        msg->rcode = BIT_RANGE_EXTRACT(uint16_t, OPB_RCODE_h, OPB_RCODE_l,
 
423
            hdr->opbits);
 
424
 
 
425
        list_initialize(&msg->question);
 
426
        list_initialize(&msg->answer);
 
427
        list_initialize(&msg->authority);
 
428
        list_initialize(&msg->additional);
 
429
 
 
430
        dp = (uint8_t *)data + sizeof(dns_header_t);
 
431
        dsize = size - sizeof(dns_header_t);
 
432
 
 
433
        qd_count = uint16_t_be2host(hdr->qd_count);
 
434
        printf("qd_count = %d\n", (int)qd_count);
 
435
 
 
436
        for (i = 0; i < qd_count; i++) {
 
437
                printf("decode question..\n");
 
438
                rc = dns_question_decode(dp, dsize, &question, &field_size);
 
439
                if (rc != EOK) {
 
440
                        printf("error decoding question\n");
 
441
                        goto error;
 
442
                }
 
443
                printf("ok decoding question\n");
 
444
 
 
445
                dp += field_size;
 
446
                dsize -= field_size;
 
447
        }
 
448
 
 
449
        an_count = uint16_t_be2host(hdr->an_count);
 
450
        printf("an_count = %d\n", an_count);
 
451
 
 
452
        for (i = 0; i < an_count; i++) {
 
453
                printf("decode answer..\n");
 
454
                rc = dns_rr_decode(dp, dsize, &rr, &field_size);
 
455
                if (rc != EOK) {
 
456
                        printf("error decoding answer\n");
 
457
                        goto error;
 
458
                }
 
459
                printf("ok decoding answer\n");
 
460
 
 
461
                dp += field_size;
 
462
                dsize -= field_size;
 
463
        }
 
464
 
 
465
        printf("ns_count = %d\n", uint16_t_be2host(hdr->ns_count));
 
466
        printf("ar_count = %d\n", uint16_t_be2host(hdr->ar_count));
 
467
 
 
468
        *rmsg = msg;
 
469
        return EOK;
 
470
error:
 
471
        /* XXX Destroy message */
 
472
        return rc;
 
473
}
 
474
 
209
475
/** @}
210
476
 */