1: #ifndef lint
   2: static char sccsid[] = "@(#)ns_resp.c	4.3 (Berkeley) 5/30/86";
   3: #endif
   4: 
   5: /*
   6:  * Copyright (c) 1986 Regents of the University of California
   7:  *	All Rights Reserved
   8:  */
   9: 
  10: #include <stdio.h>
  11: #include <sys/types.h>
  12: #include <sys/time.h>
  13: #include <sys/socket.h>
  14: #include <netinet/in.h>
  15: #include <syslog.h>
  16: #include <arpa/nameser.h>
  17: #include "ns.h"
  18: #include "db.h"
  19: 
  20: extern int errno;
  21: extern char *dnptrs[];
  22: extern char *malloc();
  23: struct  databuf *nsp[MAXNS], **nspp;
  24: 
  25: /*
  26:  * Handle a response from a forwarded query.
  27:  */
  28: ns_resp(msg, msglen)
  29:     char *msg;
  30:     int msglen;
  31: {
  32:     register struct qinfo *qp;
  33:     register HEADER *hp;
  34:     register char *cp, *tp;
  35:     int i, c, n, ancount, nscount, arcount;
  36:     int type;
  37:     int qtype, qclass;
  38:     int cname = 0; /* flag for processing cname response */
  39:     int count, founddata;
  40:     int buflen;
  41:     int newmsglen;
  42:     char name[MAXDNAME], *dname;
  43:     char *fname;
  44:     char *newmsg;
  45: 
  46:     struct hashbuf *htp;
  47:     struct databuf *dp, *tmp, *pdp;
  48:     struct namebuf *np;
  49: 
  50: #ifdef DEBUG
  51:     if (debug >= 3)
  52:         fprintf(ddt,"ns_resp(%x, %d)\n", msg, msglen);
  53: #endif
  54:     hp = (HEADER *) msg;
  55:     if( (qp = qfindid(hp->id)) == NULL )
  56:         return;
  57: 
  58:     if (hp->rcode != NOERROR || hp->opcode != QUERY)
  59:         goto retmsg;
  60:     /*
  61: 	 * Skip query section
  62: 	 */
  63:     cp = msg + sizeof(HEADER);
  64:     if (hp->qdcount) {
  65:         if ((n = dn_skip(cp)) < 0) {
  66: #ifdef DEBUG
  67:             if (debug)
  68:                 fprintf(ddt,"FORMERR ns_resp() dn_skip failed\n");
  69: #endif
  70:             hp->rcode = FORMERR;
  71:             goto retmsg;
  72:         }
  73:         cp += n;
  74:         qtype = getshort(cp);
  75:         cp += sizeof(u_short);
  76:         qclass = getshort(cp);
  77:         cp += sizeof(u_short);
  78:     }
  79:     /*
  80: 	 * Save answers, name server, and additional records for future use.
  81: 	 */
  82:     ancount = ntohs(hp->ancount);
  83:     nscount = ntohs(hp->nscount);
  84:     arcount = ntohs(hp->arcount);
  85:     if (ancount == 1 || nscount) {
  86:         /*
  87: 	 	 *  Check if it's a CNAME responce
  88: 	 	 */
  89:         tp = cp;
  90:         tp += dn_skip(tp); /* name */
  91:         type = getshort(tp);
  92:         tp += sizeof(u_short); /* type */
  93:         if (type == T_CNAME) {
  94:             tp += sizeof(u_short); /* class */
  95:             tp += sizeof(u_long);  /* ttl */
  96:             tp += sizeof(u_short); /* dlen */
  97:             cname++;
  98: #ifdef DEBUG
  99:             if (debug) {
 100:                 fprintf(ddt,"CNAME - needs more processing\n");
 101:             }
 102: #endif
 103:             if (!qp->q_cmsglen) {
 104:                 qp->q_cmsg = qp->q_msg;
 105:                 qp->q_cmsglen = qp->q_msglen;
 106:             }
 107:         }
 108:     }
 109:     /*
 110: 	 * Add the info recived in the responce to the Data Base
 111: 	 */
 112:     c = ancount + nscount + arcount;
 113:     nspp = nsp;
 114:     for (i = 0; i < c; i++) {
 115:         if (cp >= msg + msglen) {
 116: #ifdef DEBUG
 117:             if (debug)
 118:                 fprintf(ddt, "FORMERR ns_resp() message bad count?\n");
 119: #endif
 120:             hp->rcode = FORMERR;
 121:             goto retmsg;
 122:         }
 123:         if ((n = doupdate(msg, msglen, cp, 0,
 124:             !ancount && i < nscount)) < 0) {
 125: #ifdef DEBUG
 126:             if (debug)
 127:                 fprintf(ddt,"FORMERR ns_resp() doupdate failed\n");
 128: #endif
 129:             hp->rcode = FORMERR;
 130:             goto retmsg;
 131:         }
 132:         cp += n;
 133:     }
 134:     if (cp > msg + msglen) {
 135: #ifdef DEBUG
 136:         if (debug)
 137:             fprintf(ddt,"FORMERR ns_resp()  packet size err %d, %d\n",
 138:                cp-msg, msglen);
 139: #endif
 140:         hp->rcode = FORMERR;
 141:         goto retmsg;
 142:     }
 143:     if ((qtype == C_ANY) && ancount)
 144:         goto retmsg;
 145:     if ((!cname && !qp->q_cmsglen) && (ancount || nscount == 0))
 146:         goto retmsg;
 147: 
 148:     /*
 149: 	 * All messages in here need further processing.  i.e. they
 150: 	 * are either CNAMEs or we got referred again.
 151: 	 */
 152:     count = 0;
 153:     founddata = 0;
 154:     dname = name;
 155:     if ((newmsg = malloc(BUFSIZ)) == NULL) {
 156: #if DEBUG
 157:         if (debug)
 158:             fprintf(ddt,"ns_resp: malloc error\n");
 159: #endif
 160:         syslog(LOG_ERR, "ns_resp: Out Of Memory");
 161:         hp->rcode = SERVFAIL;
 162:         goto retmsg;
 163:     }
 164:     buflen = BUFSIZ;
 165:     if ((!cname && qp->q_cmsglen) && ancount) {
 166: #if DEBUG
 167:         if (debug) {
 168:             fprintf(ddt,"Cname second pass\n");
 169:         }
 170: #endif
 171:         newmsglen = qp->q_cmsglen;
 172:         bcopy(qp->q_cmsg, newmsg, newmsglen);
 173:     } else {
 174:         newmsglen = msglen;
 175:         bcopy(msg, newmsg, newmsglen);
 176:     }
 177:     buflen = buflen - newmsglen;
 178:     hp = (HEADER *) newmsg;
 179:     dnptrs[0] = newmsg;
 180:     dnptrs[1] = NULL;
 181:     cp = newmsg + sizeof(HEADER);
 182:     if (cname)
 183:         cp += dn_skip(cp) + QFIXEDSZ;
 184:     if ((n = dn_expand(newmsg, newmsg + newmsglen,
 185:         cp, dname, sizeof(name))) < 0) {
 186: #ifdef DEBUG
 187:         if (debug)
 188:             fprintf(ddt,"dn_expand failed\n" );
 189: #endif
 190:         hp->rcode = SERVFAIL;
 191:         free(newmsg);
 192:         goto retmsg;
 193:     }
 194:     cp = newmsg + sizeof(HEADER);
 195:     if (cname)
 196:         cp += dn_skip(cp);
 197:     else
 198:         cp += n;
 199:     cp += QFIXEDSZ;
 200: 
 201: again:
 202:     htp = hashtab;      /* lookup relative to root */
 203: #ifdef DEBUG
 204:     if (debug)
 205:         fprintf(ddt,"ns_resp() nlookup(%s)\n",dname);
 206: #endif
 207:     np = nlookup(dname, &htp, &fname, 0);
 208:     if (np == (struct namebuf *)NULL)
 209:         fname = "";
 210:     if (fname != dname)
 211:         goto findns;
 212: #ifdef DEBUG
 213:     if (debug)
 214:         fprintf(ddt,"found '%s'\n", dname);
 215: #endif
 216:     pdp = NULL;
 217:     dp = np->n_data;
 218:     /* look for the data */
 219:     while (dp != NULL) {
 220:         if (!wanted(dp, qclass, qtype)) {
 221:             pdp = dp;
 222:             dp = dp->d_next;
 223:             continue;
 224:         }
 225:         if ((n = make_rr(dname, dp, cp, buflen, 1)) < 0) {
 226:             if (n == -1) {
 227:                 hp->tc = 1;
 228:                 break;
 229:             }
 230:             /* delete old cache entry */
 231: #ifdef DEBUG
 232:             if (debug >= 5)
 233:                 fprintf(ddt,"deleting cache entry\n");
 234: #endif
 235:             rminv(dp);
 236:             tmp = dp->d_next;
 237:             free((char *)dp);
 238:             dp = tmp;
 239:             if (pdp == NULL)
 240:                 np->n_data = dp;
 241:             else
 242:                 pdp->d_next = dp;
 243:             continue;
 244:         }
 245:         cp += n;
 246:         buflen -= n;
 247:         count++;
 248:         if (dp->d_zone)
 249:             hp->aa = 1;
 250:         if (dp->d_type == T_CNAME) {
 251:             if (type == T_ANY)
 252:                 break;
 253:             dname = dp->d_data;
 254:             goto again;
 255:         }
 256:         founddata++;
 257:         pdp = dp;
 258:         dp = dp->d_next;
 259:     }
 260: #ifdef DEBUG
 261:     if (debug >= 5)
 262:         fprintf(ddt,"count = %d, founddata = %d\n", count, founddata);
 263: #endif
 264:     if (count)
 265:         hp->ancount = htons((u_short)count);
 266: 
 267: findns:
 268: 
 269:     /*
 270:  	 * Look for name servers to refer to and fill in the authority
 271:  	 * section or record the address for forwarding the query
 272:  	 * (recursion desired).
 273:  	 */
 274:     for (count = 0;; np = np->n_parent) {
 275: #ifdef DEBUG
 276:         if (debug >= 5)
 277:             fprintf(ddt, "fname = '%s'\n", fname);
 278: #endif
 279:         if (*fname == '\0') {
 280:             for (np = hashtab->h_tab[0]; np != NULL;
 281:                  np = np->n_next)
 282:                 if (np->n_dname[0] == '\0')
 283:                     goto foundns;
 284: #ifdef DEBUG
 285:             if (debug)
 286:                 fprintf(ddt, "No root nameserver?\n");
 287: #endif
 288:             syslog(LOG_ERR, "No root Nameserver\n");
 289:             hp->rcode = SERVFAIL;
 290:             break;
 291:         }
 292: foundns:
 293:         nspp = nsp;
 294:         pdp = NULL;
 295:         dp = np->n_data;
 296:         while (dp != NULL) {
 297:             if (!match(dp, qclass, T_NS)) {
 298:                 pdp = dp;
 299:                 dp = dp->d_next;
 300:                 continue;
 301:             }
 302:             if (!founddata) {
 303:                 if (nspp < &nsp[MAXNS-1])
 304:                     *nspp++ = dp;
 305:                 pdp = dp;
 306:                 dp = dp->d_next;
 307:                 continue;
 308:             }
 309:             if ((n = make_rr(fname, dp, cp, buflen, 1)) < 0) {
 310:                 if (n == -1) {
 311:                     hp->tc = 1;
 312:                     break;
 313:                 }
 314:                 /* delete old cache entry */
 315: #ifdef DEBUG
 316:                 if (debug)
 317:                     fprintf(ddt,"deleting cache entry\n");
 318: #endif
 319:                 rminv(dp);
 320:                 tmp = dp->d_next;
 321:                 free((char *)dp);
 322:                 dp = tmp;
 323:                 if (pdp == NULL)
 324:                     np->n_data = dp;
 325:                 else
 326:                     pdp->d_next = dp;
 327:                 continue;
 328:             }
 329:             cp += n;
 330:             buflen -= n;
 331:             count++;
 332:             pdp = dp;
 333:             dp = dp->d_next;
 334:         }
 335:         if ((*fname == '\0') || (count > 0))
 336:             break;
 337:         if (nspp != nsp)
 338:             break;
 339:         if ((fname = index(fname, '.')) == NULL)
 340:             fname = "";
 341:         else
 342:             fname++;
 343:     }
 344: 
 345:     if (count && founddata) {
 346:         hp->nscount = htons((u_short)count);
 347:         cp += doaddinfo(hp, cp, buflen);
 348:         buflen = cp - newmsg;
 349:         msg = newmsg;
 350:         msglen = buflen;
 351:         hp = (HEADER *) msg;
 352:         goto retmsg;
 353:     }
 354: 
 355:     *nspp = NULL;
 356:     if (cname) {
 357:         newmsglen = res_mkquery(QUERY, dname, C_ANY, T_A, (char *)NULL,
 358:                     0, NULL, newmsg, BUFSIZ);
 359:         qp->q_msglen = newmsglen;
 360:         hp->id = qp->q_nsid;
 361:     } else {
 362:         hp->ancount = 0;
 363:         hp->nscount = 0;
 364:         hp->arcount = 0;
 365:         hp->qr = 0;
 366:     }
 367:     qp->q_naddr = 0;
 368:     qp->q_curaddr = 0;
 369:     n = nslookup(nsp, qp);
 370: 
 371: #ifdef DEBUG
 372:         if (debug > 7) {
 373:             int kjd;
 374: 
 375:             fprintf(ddt,"n = %d\n",n);
 376:             for (kjd = 0; kjd < qp->q_naddr; kjd++ )
 377:                 fprintf(ddt,"list %d-> %s (%d)\n",  kjd,
 378:                     inet_ntoa(qp->q_addr[kjd].sin_addr),
 379:                     ntohs(qp->q_addr[kjd].sin_port));
 380:         }
 381: #endif DEBUG
 382:     qp->q_msg = newmsg;
 383:     if (qp->q_cname++ == MAXCNAMES) {
 384:         hp->id = qp->q_id;
 385:         hp->rd = 1;
 386:         hp->ra = 1;
 387:         if (qp->q_stream != QSTREAM_NULL) {
 388:             (void) writemsg(qp->q_stream->s_rfd, newmsg, newmsglen);
 389:             qp->q_stream->s_time = tt.tv_sec;
 390:             qp->q_stream->s_refcnt--;
 391:         } else {
 392:             if (sendto(ds, newmsg, newmsglen, 0, &qp->q_from,
 393:                 sizeof(qp->q_from)) < 0) {
 394: #ifdef DEBUG
 395:                 if (debug)
 396:                     fprintf(ddt,"sendto failed\n");
 397: #endif
 398:             }
 399:         }
 400:         qremove(qp);
 401:         return;
 402:     }
 403: #ifdef DEBUG
 404:     if (debug)
 405:         fprintf(ddt,"q_cname = %d\n",qp->q_cname);
 406: #endif
 407:     unsched(qp);
 408:     schedretry(qp, (time_t)RETRYTIME);
 409: 
 410: #ifdef DEBUG
 411:     if (debug >= 3)
 412:         fp_query(qp->q_msg, ddt);
 413:     if (debug)
 414:         fprintf(ddt,"try -> %s (%d)\n",
 415:             inet_ntoa(qp->q_addr[0].sin_addr),
 416:             ntohs(qp->q_addr[0].sin_port));
 417: #endif
 418:     if (sendto(ds, qp->q_msg, qp->q_msglen, 0,
 419:         &qp->q_addr[0], sizeof(qp->q_addr[0])) < 0) {
 420: #ifdef DEBUG
 421:         if (debug)
 422:             fprintf(ddt, "error returning msg errno=%d\n",errno);
 423: #endif
 424:     }
 425:     return;
 426: 
 427: retmsg:
 428:     /*
 429: 	 * Pass answer back to original requestor.
 430: 	 */
 431:     hp->id = qp->q_id;
 432:     hp->rd = 1;     /* restore Recursion Desired bit */
 433:     hp->ra = 1;     /* Recursion is Available */
 434: #ifdef DEBUG
 435:     if (debug)
 436:         fprintf(ddt,"respond -> %s (%d)\n",
 437:             inet_ntoa(qp->q_from.sin_addr),
 438:             ntohs(qp->q_from.sin_port));
 439:     if (debug >= 10)
 440:         fp_query(msg, ddt);
 441: #endif
 442:     if (qp->q_stream == QSTREAM_NULL) {
 443:         if (sendto(ds, msg, msglen, 0,
 444:             &qp->q_from, sizeof(qp->q_from)) < 0) {
 445: #ifdef DEBUG
 446:             if (debug)
 447:                 fprintf(ddt,"sendto failed\n");
 448: #endif
 449:         }
 450: 
 451:     } else {
 452:         (void) writemsg(qp->q_stream->s_rfd, msg, msglen);
 453:         qp->q_stream->s_time = tt.tv_sec;
 454:         qp->q_stream->s_refcnt--;
 455:     }
 456:     if (msg == newmsg)
 457:         (void) free(newmsg);
 458:     /*
 459: 	 * Remove from table
 460: 	 */
 461:     qremove(qp);
 462: }
 463: 
 464: /*
 465:  * Decode the resource record 'rrp' and update the database.
 466:  * If savens is true, record pointer for forwarding queries a second time.
 467:  */
 468: doupdate(msg, msglen, rrp, zone, savens)
 469:     char *msg ;
 470:     char *rrp;
 471:     int  msglen, zone, savens;
 472: {
 473:     register char *cp;
 474:     register int n;
 475:     int class, type, dlen, n1;
 476:     u_long ttl;
 477:     struct databuf *dp;
 478:     char dname[MAXDNAME];
 479:     char data[BUFSIZ], *cp1;
 480: 
 481: #ifdef DEBUG
 482:     if (debug >= 3)
 483:         fprintf(ddt,"doupdate(%d, %d)\n", zone, savens);
 484: #endif
 485: 
 486:     cp = rrp;
 487:     if ((n = dn_expand(msg, msg + msglen, cp, dname, sizeof(dname))) < 0)
 488:         return (-1);
 489:     cp += n;
 490:     type = getshort(cp);
 491:     cp += sizeof(u_short);
 492:     class = getshort(cp);
 493:     cp += sizeof(u_short);
 494:     ttl = getlong(cp);
 495:     cp += sizeof(u_long);
 496:     dlen = getshort(cp);
 497:     cp += sizeof(u_short);
 498:     if (zone == 0) {
 499:         if (ttl == 0)
 500:             ttl = 5 * 60;
 501:         ttl += (u_long) tt.tv_sec;
 502:     }
 503:     /*
 504: 	 * Convert the resource record data into the internal
 505: 	 * database format.
 506: 	 */
 507:     switch (type) {
 508:     case T_A:
 509:     case T_HINFO:
 510:     case T_UINFO:
 511:     case T_UID:
 512:     case T_GID:
 513:         cp1 = cp;
 514:         n = dlen;
 515:         cp += n;
 516:         break;
 517: 
 518:     case T_CNAME:
 519:     case T_MB:
 520:     case T_MG:
 521:     case T_MR:
 522:     case T_NS:
 523:     case T_PTR:
 524:         if ((n = dn_expand(msg, msg + msglen, cp, data,
 525:            sizeof(data))) < 0)
 526:             return (-1);
 527:         cp += n;
 528:         cp1 = data;
 529:         n = strlen(data) + 1;
 530:         break;
 531: 
 532:     case T_MINFO:
 533:     case T_SOA:
 534:         if ((n = dn_expand(msg, msg + msglen, cp, data,
 535:             sizeof(data))) < 0)
 536:             return (-1);
 537:         cp += n;
 538:         cp1 = data + (n = strlen(data) + 1);
 539:         n1 = sizeof(data) - n;
 540:         if (type == T_SOA)
 541:             n1 -= 5 * sizeof(u_long);
 542:         if ((n = dn_expand(msg, msg + msglen, cp, cp1, n1)) < 0)
 543:             return (-1);
 544:         cp += n;
 545:         cp1 += strlen(cp1) + 1;
 546:         if (type == T_SOA) {
 547:             bcopy(cp, cp1, n = 5 * sizeof(u_long));
 548:             cp += n;
 549:             cp1 += n;
 550:         }
 551:         n = cp1 - data;
 552:         cp1 = data;
 553:         break;
 554: 
 555:     case T_MX:
 556:         /* grab preference */
 557:         bcopy(cp,data,sizeof(u_short));
 558:         cp1 = data + sizeof(u_short);
 559:         cp += sizeof(u_short);
 560: 
 561:         /* get name */
 562:         if ((n = dn_expand(msg, msg + msglen, cp, cp1,
 563:             sizeof(data)-sizeof(u_short))) < 0)
 564:             return(-1);
 565:         cp += n;
 566: 
 567:         /* compute end of data */
 568:         cp1 += strlen(cp1) + 1;
 569:         /* compute size of data */
 570:         n = cp1 - data;
 571:         cp1 = data;
 572:         break;
 573: 
 574:     default:
 575: #ifdef DEBUG
 576:         if (debug >= 3)
 577:             fprintf(ddt,"unknown type %d\n", type);
 578: #endif
 579:         return ((cp - rrp) + dlen);
 580:     }
 581:     dp = savedata(class, type, ttl, cp1, n);
 582:     dp->d_zone = zone;
 583:     if ((n = db_update(dname, dp, dp, DB_NODATA)) < 0) {
 584: #ifdef DEBUG
 585:         if (debug && (n != DATAEXISTS))
 586:             fprintf(ddt,"update failed (%d)\n", n);
 587:         else if (debug >= 3)
 588:             fprintf(ddt,"update failed (DATAEXISTS)\n");
 589: #endif
 590:         (void) free((char *)dp);
 591:     } else if (savens && type == T_NS && nspp < &nsp[MAXNS-1])
 592:         *nspp++ = dp;
 593:     return (cp - rrp);
 594: }

Defined functions

doupdate defined in line 468; used 3 times
ns_resp defined in line 28; used 1 times

Defined variables

nsp defined in line 23; used 6 times
nspp defined in line 23; used 8 times
sccsid defined in line 2; never used
Last modified: 1986-05-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2160
Valid CSS Valid XHTML 1.0 Strict