OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [libnetworking/] [libc/] [ns_name.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 158 chris
/*
2
 * Copyright (c) 1996 by Internet Software Consortium.
3
 *
4
 * Permission to use, copy, modify, and distribute this software for any
5
 * purpose with or without fee is hereby granted, provided that the above
6
 * copyright notice and this permission notice appear in all copies.
7
 *
8
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15
 * SOFTWARE.
16
 */
17
 
18
#if !defined(__rtems__)
19
#if !defined(LINT) && !defined(CODECENTER)
20 208 chris
static char rcsid[] = "$Id: ns_name.c,v 1.2 2001-09-27 12:01:53 chris Exp $";
21 158 chris
#endif /* not lint */
22
#endif /* not rtems */
23
 
24
#include <sys/types.h>
25
 
26
#include <netinet/in.h>
27
#include <arpa/nameser.h>
28
 
29
#include <errno.h>
30
#include <resolv.h>
31
#include <string.h>
32
 
33
/* Data. */
34
 
35
static char             digits[] = "0123456789";
36
 
37
/* Forward. */
38
 
39
static int              special(int);
40
static int              printable(int);
41
static int              dn_find(const u_char *, const u_char *,
42
                                const u_char * const *,
43
                                const u_char * const *);
44
 
45
/* Public. */
46
 
47
/*
48
 * ns_name_ntop(src, dst, dstsiz)
49
 *      Convert an encoded domain name to printable ascii as per RFC1035.
50
 * return:
51
 *      Number of bytes written to buffer, or -1 (with errno set)
52
 * notes:
53
 *      The root is returned as "."
54
 *      All other domains are returned in non absolute form
55
 */
56
int
57
ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) {
58
        const u_char *cp;
59
        char *dn, *eom;
60
        u_char c;
61
        u_int n;
62
 
63
        cp = src;
64
        dn = dst;
65
        eom = dst + dstsiz;
66
 
67
        while ((n = *cp++) != 0) {
68
                if ((n & NS_CMPRSFLGS) != 0) {
69
                        /* Some kind of compression pointer. */
70
                        errno = EMSGSIZE;
71
                        return (-1);
72
                }
73
                if (dn != dst) {
74
                        if (dn >= eom) {
75
                                errno = EMSGSIZE;
76
                                return (-1);
77
                        }
78
                        *dn++ = '.';
79
                }
80
                if (dn + n >= eom) {
81
                        errno = EMSGSIZE;
82
                        return (-1);
83
                }
84
                for ((void)NULL; n > 0; n--) {
85
                        c = *cp++;
86
                        if (special(c)) {
87
                                if (dn + 1 >= eom) {
88
                                        errno = EMSGSIZE;
89
                                        return (-1);
90
                                }
91
                                *dn++ = '\\';
92
                                *dn++ = (char)c;
93
                        } else if (!printable(c)) {
94
                                if (dn + 3 >= eom) {
95
                                        errno = EMSGSIZE;
96
                                        return (-1);
97
                                }
98
                                *dn++ = '\\';
99
                                *dn++ = digits[c / 100];
100
                                *dn++ = digits[(c % 100) / 10];
101
                                *dn++ = digits[c % 10];
102
                        } else {
103
                                if (dn >= eom) {
104
                                        errno = EMSGSIZE;
105
                                        return (-1);
106
                                }
107
                                *dn++ = (char)c;
108
                        }
109
                }
110
        }
111
        if (dn == dst) {
112
                if (dn >= eom) {
113
                        errno = EMSGSIZE;
114
                        return (-1);
115
                }
116
                *dn++ = '.';
117
        }
118
        if (dn >= eom) {
119
                errno = EMSGSIZE;
120
                return (-1);
121
        }
122
        *dn++ = '\0';
123
        return (dn - dst);
124
}
125
 
126
/*
127
 * ns_name_pton(src, dst, dstsiz)
128
 *      Convert a ascii string into an encoded domain name as per RFC1035.
129
 * return:
130
 *      -1 if it fails
131
 *      1 if string was fully qualified
132
 *      0 is string was not fully qualified
133
 * notes:
134
 *      Enforces label and domain length limits.
135
 */
136
 
137
int
138
ns_name_pton(const char *src, u_char *dst, size_t dstsiz) {
139
        u_char *label, *bp, *eom;
140
        int c, n, escaped;
141
        char *cp;
142
 
143
        escaped = 0;
144
        bp = dst;
145
        eom = dst + dstsiz;
146
        label = bp++;
147
 
148
        while ((c = *src++) != 0) {
149
                if (escaped) {
150
                        if ((cp = strchr(digits, c)) != NULL) {
151
                                n = (cp - digits) * 100;
152
                                if ((c = *src++) == 0 ||
153
                                    (cp = strchr(digits, c)) == NULL) {
154
                                        errno = EMSGSIZE;
155
                                        return (-1);
156
                                }
157
                                n += (cp - digits) * 10;
158
                                if ((c = *src++) == 0 ||
159
                                    (cp = strchr(digits, c)) == NULL) {
160
                                        errno = EMSGSIZE;
161
                                        return (-1);
162
                                }
163
                                n += (cp - digits);
164
                                if (n > 255) {
165
                                        errno = EMSGSIZE;
166
                                        return (-1);
167
                                }
168
                                c = n;
169
                        }
170
                        escaped = 0;
171
                } else if (c == '\\') {
172
                        escaped = 1;
173
                        continue;
174
                } else if (c == '.') {
175
                        c = (bp - label - 1);
176
                        if ((c & NS_CMPRSFLGS) != 0) {   /* Label too big. */
177
                                errno = EMSGSIZE;
178
                                return (-1);
179
                        }
180
                        if (label >= eom) {
181
                                errno = EMSGSIZE;
182
                                return (-1);
183
                        }
184
                        *label = c;
185
                        /* Fully qualified ? */
186
                        if (*src == '\0') {
187
                                if (c != 0) {
188
                                        if (bp >= eom) {
189
                                                errno = EMSGSIZE;
190
                                                return (-1);
191
                                        }
192
                                        *bp++ = '\0';
193
                                }
194
                                if ((bp - dst) > MAXCDNAME) {
195
                                        errno = EMSGSIZE;
196
                                        return (-1);
197
                                }
198
                                return (1);
199
                        }
200
                        if (c == 0) {
201
                                errno = EMSGSIZE;
202
                                return (-1);
203
                        }
204
                        label = bp++;
205
                        continue;
206
                }
207
                if (bp >= eom) {
208
                        errno = EMSGSIZE;
209
                        return (-1);
210
                }
211
                *bp++ = (u_char)c;
212
        }
213
        c = (bp - label - 1);
214
        if ((c & NS_CMPRSFLGS) != 0) {           /* Label too big. */
215
                errno = EMSGSIZE;
216
                return (-1);
217
        }
218
        if (label >= eom) {
219
                errno = EMSGSIZE;
220
                return (-1);
221
        }
222
        *label = c;
223
        if (c != 0) {
224
                if (bp >= eom) {
225
                        errno = EMSGSIZE;
226
                        return (-1);
227
                }
228
                *bp++ = 0;
229
        }
230
        if ((bp - dst) > MAXCDNAME) {   /* src too big */
231
                errno = EMSGSIZE;
232
                return (-1);
233
        }
234
        return (0);
235
}
236
 
237
/*
238
 * ns_name_unpack(msg, eom, src, dst, dstsiz)
239
 *      Unpack a domain name from a message, source may be compressed.
240
 * return:
241
 *      -1 if it fails, or consumed octets if it succeeds.
242
 */
243
int
244
ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
245
               u_char *dst, size_t dstsiz)
246
{
247
        const u_char *srcp, *dstlim;
248
        u_char *dstp;
249
        int n, len, checked;
250
 
251
        len = -1;
252
        checked = 0;
253
        dstp = dst;
254
        srcp = src;
255
        dstlim = dst + dstsiz;
256
        if (srcp < msg || srcp >= eom) {
257
                errno = EMSGSIZE;
258
                return (-1);
259
        }
260
        /* Fetch next label in domain name. */
261
        while ((n = *srcp++) != 0) {
262
                /* Check for indirection. */
263
                switch (n & NS_CMPRSFLGS) {
264
                case 0:
265
                        /* Limit checks. */
266
                        if (dstp + n + 1 >= dstlim || srcp + n >= eom) {
267
                                errno = EMSGSIZE;
268
                                return (-1);
269
                        }
270
                        checked += n + 1;
271
                        *dstp++ = n;
272
                        memcpy(dstp, srcp, n);
273
                        dstp += n;
274
                        srcp += n;
275
                        break;
276
 
277
                case NS_CMPRSFLGS:
278
                        if (srcp >= eom) {
279
                                errno = EMSGSIZE;
280
                                return (-1);
281
                        }
282
                        if (len < 0)
283
                                len = srcp - src + 1;
284
                        srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
285
                        if (srcp < msg || srcp >= eom) {  /* Out of range. */
286
                                errno = EMSGSIZE;
287
                                return (-1);
288
                        }
289
                        checked += 2;
290
                        /*
291
                         * Check for loops in the compressed name;
292
                         * if we've looked at the whole message,
293
                         * there must be a loop.
294
                         */
295
                        if (checked >= eom - msg) {
296
                                errno = EMSGSIZE;
297
                                return (-1);
298
                        }
299
                        break;
300
 
301
                default:
302
                        errno = EMSGSIZE;
303
                        return (-1);                    /* flag error */
304
                }
305
        }
306
        *dstp = '\0';
307
        if (len < 0)
308
                len = srcp - src;
309
        return (len);
310
}
311
 
312
/*
313
 * ns_name_pack(src, dst, dstsiz, dnptrs, lastdnptr)
314
 *      Pack domain name 'domain' into 'comp_dn'.
315
 * return:
316
 *      Size of the compressed name, or -1.
317
 * notes:
318
 *      'dnptrs' is an array of pointers to previous compressed names.
319
 *      dnptrs[0] is a pointer to the beginning of the message. The array
320
 *      ends with NULL.
321
 *      'lastdnptr' is a pointer to the end of the array pointed to
322
 *      by 'dnptrs'.
323
 * Side effects:
324
 *      The list of pointers in dnptrs is updated for labels inserted into
325
 *      the message as we compress the name.  If 'dnptr' is NULL, we don't
326
 *      try to compress names. If 'lastdnptr' is NULL, we don't update the
327
 *      list.
328
 */
329
int
330
ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
331
             const u_char **dnptrs, const u_char **lastdnptr)
332
{
333
        u_char *dstp;
334
        const u_char **cpp, **lpp, *eob, *msg;
335
        const u_char *srcp;
336
        int n, l;
337
 
338
        srcp = src;
339
        dstp = dst;
340
        eob = dstp + dstsiz;
341
        lpp = cpp = NULL;
342
        if (dnptrs != NULL) {
343
                if ((msg = *dnptrs++) != NULL) {
344
                        for (cpp = dnptrs; *cpp != NULL; cpp++)
345
                                (void)NULL;
346
                        lpp = cpp;      /* end of list to search */
347
                }
348
        } else
349
                msg = NULL;
350
 
351
        /* make sure the domain we are about to add is legal */
352
        l = 0;
353
        do {
354
                n = *srcp;
355
                if ((n & NS_CMPRSFLGS) != 0) {
356
                        errno = EMSGSIZE;
357
                        return (-1);
358
                }
359
                l += n + 1;
360
                if (l > MAXCDNAME) {
361
                        errno = EMSGSIZE;
362
                        return (-1);
363
                }
364
                srcp += n + 1;
365
        } while (n != 0);
366
 
367
        srcp = src;
368
        do {
369
                /* Look to see if we can use pointers. */
370
                n = *srcp;
371
                if (n != 0 && msg != NULL) {
372
                        l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
373
                                    (const u_char * const *)lpp);
374
                        if (l >= 0) {
375
                                if (dstp + 1 >= eob) {
376
                                        errno = EMSGSIZE;
377
                                        return (-1);
378
                                }
379
                                *dstp++ = (l >> 8) | NS_CMPRSFLGS;
380
                                *dstp++ = l % 256;
381
                                return (dstp - dst);
382
                        }
383
                        /* Not found, save it. */
384
                        if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
385
                            (dstp - msg) < 0x4000) {
386
                                *cpp++ = dstp;
387
                                *cpp = NULL;
388
                        }
389
                }
390
                /* copy label to buffer */
391
                if (n & NS_CMPRSFLGS) {         /* Should not happen. */
392
                        errno = EMSGSIZE;
393
                        return (-1);
394
                }
395
                if (dstp + 1 + n >= eob) {
396
                        errno = EMSGSIZE;
397
                        return (-1);
398
                }
399
                memcpy(dstp, srcp, n + 1);
400
                srcp += n + 1;
401
                dstp += n + 1;
402
        } while (n != 0);
403
 
404
        if (dstp > eob) {
405
                if (msg != NULL)
406
                        *lpp = NULL;
407
                errno = EMSGSIZE;
408
                return (-1);
409
        }
410
        return (dstp - dst);
411
}
412
 
413
/*
414
 * ns_name_uncompress(msg, eom, src, dst, dstsiz)
415
 *      Expand compressed domain name to presentation format.
416
 * return:
417
 *      Number of bytes read out of `src', or -1 (with errno set).
418
 * note:
419
 *      Root domain returns as "." not "".
420
 */
421
int
422
ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
423
                   char *dst, size_t dstsiz)
424
{
425
        u_char tmp[NS_MAXCDNAME];
426
        int n;
427
 
428
        if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
429
                return (-1);
430
        if (ns_name_ntop(tmp, dst, dstsiz) == -1)
431
                return (-1);
432
        return (n);
433
}
434
 
435
/*
436
 * ns_name_compress(src, dst, dstsiz, dnptrs, lastdnptr)
437
 *      Compress a domain name into wire format, using compression pointers.
438
 * return:
439
 *      Number of bytes consumed in `dst' or -1 (with errno set).
440
 * notes:
441
 *      'dnptrs' is an array of pointers to previous compressed names.
442
 *      dnptrs[0] is a pointer to the beginning of the message.
443
 *      The list ends with NULL.  'lastdnptr' is a pointer to the end of the
444
 *      array pointed to by 'dnptrs'. Side effect is to update the list of
445
 *      pointers for labels inserted into the message as we compress the name.
446
 *      If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
447
 *      is NULL, we don't update the list.
448
 */
449
int
450
ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
451
                 const u_char **dnptrs, const u_char **lastdnptr)
452
{
453
        u_char tmp[NS_MAXCDNAME];
454
 
455
        if (ns_name_pton(src, tmp, sizeof tmp) == -1)
456
                return (-1);
457
        return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
458
}
459
 
460
/*
461
 * ns_name_skip(ptrptr, eom)
462
 *      Advance *ptrptr to skip over the compressed name it points at.
463
 * return:
464
 *      0 on success, -1 (with errno set) on failure.
465
 */
466
int
467
ns_name_skip(const u_char **ptrptr, const u_char *eom) {
468
        const u_char *cp;
469
        u_int n;
470
 
471
        cp = *ptrptr;
472
        while (cp < eom && (n = *cp++) != 0) {
473
                /* Check for indirection. */
474
                switch (n & NS_CMPRSFLGS) {
475
                case 0:                  /* normal case, n == len */
476
                        cp += n;
477
                        continue;
478
                case NS_CMPRSFLGS:      /* indirection */
479
                        cp++;
480
                        break;
481
                default:                /* illegal type */
482
                        errno = EMSGSIZE;
483
                        return (-1);
484
                }
485
                break;
486
        }
487
        if (cp > eom) {
488
                errno = EMSGSIZE;
489
                return (-1);
490
        }
491
        *ptrptr = cp;
492
        return (0);
493
}
494
 
495
/* Private. */
496
 
497
/*
498
 * special(ch)
499
 *      Thinking in noninternationalized USASCII (per the DNS spec),
500
 *      is this characted special ("in need of quoting") ?
501
 * return:
502
 *      boolean.
503
 */
504
static int
505
special(int ch) {
506
        switch (ch) {
507
        case 0x22: /* '"' */
508
        case 0x2E: /* '.' */
509
        case 0x3B: /* ';' */
510
        case 0x5C: /* '\\' */
511
        /* Special modifiers in zone files. */
512
        case 0x40: /* '@' */
513
        case 0x24: /* '$' */
514
                return (1);
515
        default:
516
                return (0);
517
        }
518
}
519
 
520
/*
521
 * printable(ch)
522
 *      Thinking in noninternationalized USASCII (per the DNS spec),
523
 *      is this character visible and not a space when printed ?
524
 * return:
525
 *      boolean.
526
 */
527
static int
528
printable(int ch) {
529
        return (ch > 0x20 && ch < 0x7f);
530
}
531
 
532
/*
533
 *      Thinking in noninternationalized USASCII (per the DNS spec),
534
 *      convert this character to lower case if it's upper case.
535
 */
536
static int
537
mklower(int ch) {
538
        if (ch >= 0x41 && ch <= 0x5A)
539
                return (ch + 0x20);
540
        return (ch);
541
}
542
 
543
/*
544
 * dn_find(domain, msg, dnptrs, lastdnptr)
545
 *      Search for the counted-label name in an array of compressed names.
546
 * return:
547
 *      offset from msg if found, or -1.
548
 * notes:
549
 *      dnptrs is the pointer to the first name on the list,
550
 *      not the pointer to the start of the message.
551
 */
552
static int
553
dn_find(const u_char *domain, const u_char *msg,
554
        const u_char * const *dnptrs,
555
        const u_char * const *lastdnptr)
556
{
557
        const u_char *dn, *cp, *sp;
558
        const u_char * const *cpp;
559
        u_int n;
560
 
561
        for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
562
                dn = domain;
563
                sp = cp = *cpp;
564
                while ((n = *cp++) != 0) {
565
                        /*
566
                         * check for indirection
567
                         */
568
                        switch (n & NS_CMPRSFLGS) {
569
                        case 0:                  /* normal case, n == len */
570
                                if (n != *dn++)
571
                                        goto next;
572
                                for ((void)NULL; n > 0; n--)
573
                                        if (mklower(*dn++) != mklower(*cp++))
574
                                                goto next;
575
                                /* Is next root for both ? */
576
                                if (*dn == '\0' && *cp == '\0')
577
                                        return (sp - msg);
578
                                if (*dn)
579
                                        continue;
580
                                goto next;
581
 
582
                        case NS_CMPRSFLGS:      /* indirection */
583
                                cp = msg + (((n & 0x3f) << 8) | *cp);
584
                                break;
585
 
586
                        default:        /* illegal type */
587
                                errno = EMSGSIZE;
588
                                return (-1);
589
                        }
590
                }
591
 next: ;
592
        }
593
        errno = ENOENT;
594
        return (-1);
595
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.