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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [libnetworking/] [libc/] [res_update.c] - Blame information for rev 373

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
#if !defined(__rtems__)
2
#if !defined(lint) && !defined(SABER)
3
static char rcsid[] = "$Id: res_update.c,v 1.2 2001-09-27 12:01:53 chris Exp $";
4
#endif /* not lint */
5
#endif /* not rtems */
6
 
7
/*
8
 * Copyright (c) 1996 by Internet Software Consortium.
9
 *
10
 * Permission to use, copy, modify, and distribute this software for any
11
 * purpose with or without fee is hereby granted, provided that the above
12
 * copyright notice and this permission notice appear in all copies.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
15
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
16
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
17
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
18
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
19
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
20
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21
 * SOFTWARE.
22
 */
23
 
24
/*
25
 * Based on the Dynamic DNS reference implementation by Viraj Bais
26
 * <viraj_bais@ccm.fm.intel.com>
27
 */
28
 
29
#include <sys/param.h>
30
#include <sys/socket.h>
31
#include <sys/time.h>
32
#include <netinet/in.h>
33
#include <arpa/inet.h>
34
#include <arpa/nameser.h>
35
#include <errno.h>
36
#include <limits.h>
37
#include <netdb.h>
38
#include <resolv.h>
39
#include <stdio.h>
40
#include <stdlib.h>
41
#include <string.h>
42
 
43
/*
44
 * Separate a linked list of records into groups so that all records
45
 * in a group will belong to a single zone on the nameserver.
46
 * Create a dynamic update packet for each zone and send it to the
47
 * nameservers for that zone, and await answer.
48
 * Abort if error occurs in updating any zone.
49
 * Return the number of zones updated on success, < 0 on error.
50
 *
51
 * On error, caller must deal with the unsynchronized zones
52
 * eg. an A record might have been successfully added to the forward
53
 * zone but the corresponding PTR record would be missing if error
54
 * was encountered while updating the reverse zone.
55
 */
56
 
57
#define NSMAX 16
58
 
59
struct ns1 {
60
        char nsname[MAXDNAME];
61
        struct in_addr nsaddr1;
62
};
63
 
64
struct zonegrp {
65
        char            z_origin[MAXDNAME];
66
        int16_t         z_class;
67
        char            z_soardata[MAXDNAME + 5 * INT32SZ];
68
        struct ns1      z_ns[NSMAX];
69
        int             z_nscount;
70
        ns_updrec *     z_rr;
71
        struct zonegrp *z_next;
72
};
73
 
74
 
75
int
76
res_update(ns_updrec *rrecp_in) {
77
        ns_updrec *rrecp, *tmprrecp;
78
        u_char buf[PACKETSZ], answer[PACKETSZ], packet[2*PACKETSZ];
79
        char name[MAXDNAME], zname[MAXDNAME], primary[MAXDNAME],
80
             mailaddr[MAXDNAME];
81
        u_char soardata[2*MAXCDNAME+5*INT32SZ];
82
        char *dname, *svdname, *cp1, *target;
83
        u_char *cp, *eom;
84
        HEADER *hp = (HEADER *) answer;
85
        struct zonegrp *zptr = NULL, *tmpzptr, *prevzptr, *zgrp_start = NULL;
86
        int i, j, k = 0, n, ancount, nscount, arcount, rcode, rdatasize,
87
            newgroup, done, myzone, seen_before, numzones = 0;
88
        u_int16_t dlen, class, qclass, type, qtype;
89
        u_int32_t ttl;
90
 
91
        if ((_res.options & RES_INIT) == 0 && res_init() == -1) {
92
                h_errno = NETDB_INTERNAL;
93
                return (-1);
94
        }
95
 
96
        for (rrecp = rrecp_in; rrecp; rrecp = rrecp->r_next) {
97
                dname = rrecp->r_dname;
98
                n = strlen(dname);
99
                if (dname[n-1] == '.')
100
                        dname[n-1] = '\0';
101
                qtype = T_SOA;
102
                qclass = rrecp->r_class;
103
                done = 0;
104
                seen_before = 0;
105
 
106
                while (!done && dname) {
107
                    if (qtype == T_SOA) {
108
                        for (tmpzptr = zgrp_start;
109
                             tmpzptr && !seen_before;
110
                             tmpzptr = tmpzptr->z_next) {
111
                                if (strcasecmp(dname,
112
                                               tmpzptr->z_origin) == 0 &&
113
                                    tmpzptr->z_class == qclass)
114
                                        seen_before++;
115
                                for (tmprrecp = tmpzptr->z_rr;
116
                                     tmprrecp && !seen_before;
117
                                     tmprrecp = tmprrecp->r_grpnext)
118
                                if (strcasecmp(dname, tmprrecp->r_dname) == 0
119
                                    && tmprrecp->r_class == qclass) {
120
                                        seen_before++;
121
                                        break;
122
                                }
123
                                if (seen_before) {
124
                                        /*
125
                                         * Append to the end of
126
                                         * current group.
127
                                         */
128
                                        for (tmprrecp = tmpzptr->z_rr;
129
                                             tmprrecp->r_grpnext;
130
                                             tmprrecp = tmprrecp->r_grpnext)
131
                                                (void)NULL;
132
                                        tmprrecp->r_grpnext = rrecp;
133
                                        rrecp->r_grpnext = NULL;
134
                                        done = 1;
135
                                        break;
136
                                }
137
                        }
138
                } else if (qtype == T_A) {
139
                    for (tmpzptr = zgrp_start;
140
                         tmpzptr && !done;
141
                         tmpzptr = tmpzptr->z_next)
142
                            for (i = 0; i < tmpzptr->z_nscount; i++)
143
                                if (tmpzptr->z_class == qclass &&
144
                                    strcasecmp(tmpzptr->z_ns[i].nsname,
145
                                               dname) == 0 &&
146
                                    tmpzptr->z_ns[i].nsaddr1.s_addr != 0) {
147
                                        zptr->z_ns[k].nsaddr1.s_addr =
148
                                         tmpzptr->z_ns[i].nsaddr1.s_addr;
149
                                        done = 1;
150
                                        break;
151
                                }
152
                }
153
                if (done)
154
                    break;
155
                n = res_mkquery(QUERY, dname, qclass, qtype, NULL,
156
                                0, NULL, buf, sizeof buf);
157
                if (n <= 0) {
158
                    fprintf(stderr, "res_update: mkquery failed\n");
159
                    return (n);
160
                }
161
                n = res_send(buf, n, answer, sizeof answer);
162
                if (n < 0) {
163
                    fprintf(stderr, "res_update: send error for %s\n",
164
                            rrecp->r_dname);
165
                    return (n);
166
                }
167
                if (n < HFIXEDSZ)
168
                        return (-1);
169
                ancount = ntohs(hp->ancount);
170
                nscount = ntohs(hp->nscount);
171
                arcount = ntohs(hp->arcount);
172
                rcode = hp->rcode;
173
                cp = answer + HFIXEDSZ;
174
                eom = answer + n;
175
                /* skip the question section */
176
                n = dn_skipname(cp, eom);
177
                if (n < 0 || cp + n + 2 * INT16SZ > eom)
178
                        return (-1);
179
                cp += n + 2 * INT16SZ;
180
 
181
                if (qtype == T_SOA) {
182
                    if (ancount == 0 && nscount == 0 && arcount == 0) {
183
                        /*
184
                         * if (rcode == NOERROR) then the dname exists but
185
                         * has no soa record associated with it.
186
                         * if (rcode == NXDOMAIN) then the dname does not
187
                         * exist and the server is replying out of NCACHE.
188
                         * in either case, proceed with the next try
189
                         */
190
                        dname = strchr(dname, '.');
191
                        if (dname != NULL)
192
                                dname++;
193
                        continue;
194
                    } else if ((rcode == NOERROR || rcode == NXDOMAIN) &&
195
                               ancount == 0 &&
196
                               nscount == 1 && arcount == 0) {
197
                        /*
198
                         * name/data does not exist, soa record supplied in the
199
                         * authority section
200
                         */
201
                        /* authority section must contain the soa record */
202
                        if ((n = dn_expand(answer, eom, cp, zname,
203
                                        sizeof zname)) < 0)
204
                            return (n);
205
                        cp += n;
206
                        if (cp + 2 * INT16SZ > eom)
207
                                return (-1);
208
                        GETSHORT(type, cp);
209
                        GETSHORT(class, cp);
210
                        if (type != T_SOA || class != qclass) {
211
                            fprintf(stderr, "unknown answer\n");
212
                            return (-1);
213
                        }
214
                        myzone = 0;
215
                        svdname = dname;
216
                        while (dname)
217
                            if (strcasecmp(dname, zname) == 0) {
218
                                myzone = 1;
219
                                break;
220
                            } else if ((dname = strchr(dname, '.')) != NULL)
221
                                dname++;
222
                        if (!myzone) {
223
                            dname = strchr(svdname, '.');
224
                            if (dname != NULL)
225
                                dname++;
226
                            continue;
227
                        }
228
                        nscount = 0;
229
                        /* fallthrough */
230
                    } else if (rcode == NOERROR && ancount == 1) {
231
                        /*
232
                         * found the zone name
233
                         * new servers will supply NS records for the zone
234
                         * in authority section and A records for those
235
                         * nameservers in the additional section
236
                         * older servers have to be explicitly queried for
237
                         * NS records for the zone
238
                         */
239
                        /* answer section must contain the soa record */
240
                        if ((n = dn_expand(answer, eom, cp, zname,
241
                                           sizeof zname)) < 0)
242
                                return (n);
243
                        else
244
                                cp += n;
245
                        if (cp + 2 * INT16SZ > eom)
246
                                return (-1);
247
                        GETSHORT(type, cp);
248
                        GETSHORT(class, cp);
249
                        if (type == T_CNAME) {
250
                                dname = strchr(dname, '.');
251
                                if (dname != NULL)
252
                                        dname++;
253
                                continue;
254
                        }
255
                        if (strcasecmp(dname, zname) != 0 ||
256
                            type != T_SOA ||
257
                            class != rrecp->r_class) {
258
                                fprintf(stderr, "unknown answer\n");
259
                                return (-1);
260
                        }
261
                        /* FALLTHROUGH */
262
                    } else {
263
                        fprintf(stderr,
264
                "unknown response: ans=%d, auth=%d, add=%d, rcode=%d\n",
265
                                ancount, nscount, arcount, hp->rcode);
266
                        return (-1);
267
                    }
268
                    if (cp + INT32SZ + INT16SZ > eom)
269
                            return (-1);
270
                    /* continue processing the soa record */
271
                    GETLONG(ttl, cp);
272
                    GETSHORT(dlen, cp);
273
                    if (cp + dlen > eom)
274
                            return (-1);
275
                    newgroup = 1;
276
                    zptr = zgrp_start;
277
                    prevzptr = NULL;
278
                    while (zptr) {
279
                        if (strcasecmp(zname, zptr->z_origin) == 0 &&
280
                            type == T_SOA && class == qclass) {
281
                                newgroup = 0;
282
                                break;
283
                        }
284
                        prevzptr = zptr;
285
                        zptr = zptr->z_next;
286
                    }
287
                    if (!newgroup) {
288
                        for (tmprrecp = zptr->z_rr;
289
                             tmprrecp->r_grpnext;
290
                             tmprrecp = tmprrecp->r_grpnext)
291
                                    ;
292
                        tmprrecp->r_grpnext = rrecp;
293
                        rrecp->r_grpnext = NULL;
294
                        done = 1;
295
                        cp += dlen;
296
                        break;
297
                    } else {
298
                        if ((n = dn_expand(answer, eom, cp, primary,
299
                                           sizeof primary)) < 0)
300
                            return (n);
301
                        cp += n;
302
                        /*
303
                         * We don't have to bounds check here because the
304
                         * next use of 'cp' is in dn_expand().
305
                         */
306
                        cp1 = (char *)soardata;
307
                        strcpy(cp1, primary);
308
                        cp1 += strlen(cp1) + 1;
309
                        if ((n = dn_expand(answer, eom, cp, mailaddr,
310
                                           sizeof mailaddr)) < 0)
311
                            return (n);
312
                        cp += n;
313
                        strcpy(cp1, mailaddr);
314
                        cp1 += strlen(cp1) + 1;
315
                        if (cp + 5*INT32SZ > eom)
316
                                return (-1);
317
                        memcpy(cp1, cp, 5*INT32SZ);
318
                        cp += 5*INT32SZ;
319
                        cp1 += 5*INT32SZ;
320
                        rdatasize = (u_char *)cp1 - soardata;
321
                        zptr = calloc(1, sizeof(struct zonegrp));
322
                        if (zptr == NULL)
323
                            return (-1);
324
                        if (zgrp_start == NULL)
325
                            zgrp_start = zptr;
326
                        else
327
                            prevzptr->z_next = zptr;
328
                        zptr->z_rr = rrecp;
329
                        rrecp->r_grpnext = NULL;
330
                        strcpy(zptr->z_origin, zname);
331
                        zptr->z_class = class;
332
                        memcpy(zptr->z_soardata, soardata, rdatasize);
333
                        /* fallthrough to process NS and A records */
334
                    }
335
                } else if (qtype == T_NS) {
336
                    if (rcode == NOERROR && ancount > 0) {
337
                        strcpy(zname, dname);
338
                        for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {
339
                            if (strcasecmp(zname, zptr->z_origin) == 0)
340
                                break;
341
                        }
342
                        if (zptr == NULL)
343
                            /* should not happen */
344
                            return (-1);
345
                        if (nscount > 0) {
346
                            /*
347
                             * answer and authority sections contain
348
                             * the same information, skip answer section
349
                             */
350
                            for (j = 0; j < ancount; j++) {
351
                                n = dn_skipname(cp, eom);
352
                                if (n < 0)
353
                                        return (-1);
354
                                n += 2*INT16SZ + INT32SZ;
355
                                if (cp + n + INT16SZ > eom)
356
                                        return (-1);
357
                                cp += n;
358
                                GETSHORT(dlen, cp);
359
                                cp += dlen;
360
                            }
361
                        } else
362
                            nscount = ancount;
363
                        /* fallthrough to process NS and A records */
364
                    } else {
365
                        fprintf(stderr, "cannot determine nameservers for %s:\
366
ans=%d, auth=%d, add=%d, rcode=%d\n",
367
                                dname, ancount, nscount, arcount, hp->rcode);
368
                        return (-1);
369
                    }
370
                } else if (qtype == T_A) {
371
                    if (rcode == NOERROR && ancount > 0) {
372
                        arcount = ancount;
373
                        ancount = nscount = 0;
374
                        /* fallthrough to process A records */
375
                    } else {
376
                        fprintf(stderr, "cannot determine address for %s:\
377
ans=%d, auth=%d, add=%d, rcode=%d\n",
378
                                dname, ancount, nscount, arcount, hp->rcode);
379
                        return (-1);
380
                    }
381
                }
382
                /* process NS records for the zone */
383
                j = 0;
384
                for (i = 0; i < nscount; i++) {
385
                    if ((n = dn_expand(answer, eom, cp, name,
386
                                        sizeof name)) < 0)
387
                        return (n);
388
                    cp += n;
389
                    if (cp + 3 * INT16SZ + INT32SZ > eom)
390
                            return (-1);
391
                    GETSHORT(type, cp);
392
                    GETSHORT(class, cp);
393
                    GETLONG(ttl, cp);
394
                    GETSHORT(dlen, cp);
395
                    if (cp + dlen > eom)
396
                        return (-1);
397
                    if (strcasecmp(name, zname) == 0 &&
398
                        type == T_NS && class == qclass) {
399
                                if ((n = dn_expand(answer, eom, cp,
400
                                                   name, sizeof name)) < 0)
401
                                        return (n);
402
                            target = zptr->z_ns[j++].nsname;
403
                            strcpy(target, name);
404
                    }
405
                    cp += dlen;
406
                }
407
                if (zptr->z_nscount == 0)
408
                    zptr->z_nscount = j;
409
                /* get addresses for the nameservers */
410
                for (i = 0; i < arcount; i++) {
411
                    if ((n = dn_expand(answer, eom, cp, name,
412
                                        sizeof name)) < 0)
413
                        return (n);
414
                    cp += n;
415
                    if (cp + 3 * INT16SZ + INT32SZ > eom)
416
                        return (-1);
417
                    GETSHORT(type, cp);
418
                    GETSHORT(class, cp);
419
                    GETLONG(ttl, cp);
420
                    GETSHORT(dlen, cp);
421
                    if (cp + dlen > eom)
422
                            return (-1);
423
                    if (type == T_A && dlen == INT32SZ && class == qclass) {
424
                        for (j = 0; j < zptr->z_nscount; j++)
425
                            if (strcasecmp(name, zptr->z_ns[j].nsname) == 0) {
426
                                memcpy(&zptr->z_ns[j].nsaddr1.s_addr, cp,
427
                                       INT32SZ);
428
                                break;
429
                            }
430
                    }
431
                    cp += dlen;
432
                }
433
                if (zptr->z_nscount == 0) {
434
                    dname = zname;
435
                    qtype = T_NS;
436
                    continue;
437
                }
438
                done = 1;
439
                for (k = 0; k < zptr->z_nscount; k++)
440
                    if (zptr->z_ns[k].nsaddr1.s_addr == 0) {
441
                        done = 0;
442
                        dname = zptr->z_ns[k].nsname;
443
                        qtype = T_A;
444
                    }
445
 
446
            } /* while */
447
        }
448
 
449
        _res.options |= RES_DEBUG;
450
        for (zptr = zgrp_start; zptr; zptr = zptr->z_next) {
451
 
452
                /* append zone section */
453
                rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
454
                                     zptr->z_class, ns_t_soa, 0);
455
                if (rrecp == NULL) {
456
                        fprintf(stderr, "saverrec error\n");
457
                        fflush(stderr);
458
                        return (-1);
459
                }
460
                rrecp->r_grpnext = zptr->z_rr;
461
                zptr->z_rr = rrecp;
462
 
463
                n = res_mkupdate(zptr->z_rr, packet, sizeof packet);
464
                if (n < 0) {
465
                        fprintf(stderr, "res_mkupdate error\n");
466
                        fflush(stderr);
467
                        return (-1);
468
                } else
469
                        fprintf(stdout, "res_mkupdate: packet size = %d\n", n);
470
 
471
                /*
472
                 * Override the list of NS records from res_init() with
473
                 * the authoritative nameservers for the zone being updated.
474
                 * Sort primary to be the first in the list of nameservers.
475
                 */
476
                for (i = 0; i < zptr->z_nscount; i++) {
477
                        if (strcasecmp(zptr->z_ns[i].nsname,
478
                                       zptr->z_soardata) == 0) {
479
                                struct in_addr tmpaddr;
480
 
481
                                if (i != 0) {
482
                                        strcpy(zptr->z_ns[i].nsname,
483
                                               zptr->z_ns[0].nsname);
484
                                        strcpy(zptr->z_ns[0].nsname,
485
                                               zptr->z_soardata);
486
                                        tmpaddr = zptr->z_ns[i].nsaddr1;
487
                                        zptr->z_ns[i].nsaddr1 =
488
                                                zptr->z_ns[0].nsaddr1;
489
                                        zptr->z_ns[0].nsaddr1 = tmpaddr;
490
                                }
491
                                break;
492
                        }
493
                }
494
                for (i = 0; i < MAXNS; i++) {
495
                        _res.nsaddr_list[i].sin_addr = zptr->z_ns[i].nsaddr1;
496
                        _res.nsaddr_list[i].sin_family = AF_INET;
497
                        _res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
498
                }
499
                _res.nscount = (zptr->z_nscount < MAXNS) ?
500
                                        zptr->z_nscount : MAXNS;
501
                n = res_send(packet, n, answer, sizeof(answer));
502
                if (n < 0) {
503
                        fprintf(stderr, "res_send: send error, n=%d\n", n);
504
                        break;
505
                } else
506
                        numzones++;
507
        }
508
 
509
        /* free malloc'ed memory */
510
        while(zgrp_start) {
511
                zptr = zgrp_start;
512
                zgrp_start = zgrp_start->z_next;
513
                res_freeupdrec(zptr->z_rr);  /* Zone section we allocated. */
514
                free((char *)zptr);
515
        }
516
 
517
        return (numzones);
518
}

powered by: WebSVN 2.1.0

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