📄 ns_validate.c
字号:
free(nameaddrlist[firstNA].nsname); nameaddrlist[firstNA].nsname = 0; lastNA = (lastNA+1) % MAXNAMECACHE; } return;}/* * Decode the resource record 'rrp' and validate the RR. * Borrows code almost entirely from doupdate(). is a rather * non-invasive routine since it just goes thru the same motions * as doupdate but just marks the array validatelist entry as * the return code from validate(). This is later used in doupdate * to cache/not cache the entry. also used in update_msg() to * delete/keep the record from the outgoing message. */intdovalidate(msg, msglen, rrp, zone, flags, server, VCode) char *msg; u_char *rrp; int msglen, zone, flags; struct sockaddr_in *server; int *VCode;{ register u_char *cp; register int n; int class, type, dlen, n1; u_int32_t ttl; char dname[MAXDNAME]; u_char *cp1; u_char data[BUFSIZ]; register HEADER *hp = (HEADER *) msg; dprintf(2, (ddt, "dovalidate(zone %d, flags %x)\n", zone, flags));#ifdef DEBUG if(debug >= 10) fp_query((char *)msg,ddt);#endif cp = rrp; if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen, cp, (u_char *)dname, sizeof(dname))) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; GETSHORT(type, cp); GETSHORT(class, cp); GETLONG(ttl, cp); GETSHORT(dlen, cp); dprintf(2, (ddt, "dovalidate: dname %s type %d class %d ttl %d\n", dname, type, class, ttl)); /* * Convert the resource record data into the internal * database format. */ switch (type) { case T_A: case T_WKS: case T_HINFO: case T_UINFO: case T_UID: case T_GID: case T_TXT:#ifdef ALLOW_T_UNSPEC case T_UNSPEC:#endif cp1 = cp; n = dlen; cp += n; break; case T_CNAME: case T_MB: case T_MG: case T_MR: case T_NS: case T_PTR: if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen, cp, data, sizeof(data))) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; cp1 = data; n = strlen((char *)data) + 1; break; case T_MINFO: case T_SOA: case T_RP: if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen, cp, data, sizeof(data))) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; cp1 = data + (n = strlen((char *)data) + 1); n1 = sizeof(data) - n; if (type == T_SOA) n1 -= 5 * sizeof(u_int32_t); if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen, cp, cp1, n1)) < 0) { hp->rcode = FORMERR; return (-1); } cp += n; cp1 += strlen((char *)cp1) + 1; if (type == T_SOA) { bcopy((char *)cp, (char *)cp1, n = 5 * sizeof(u_int32_t)); cp += n; cp1 += n; } n = cp1 - data; cp1 = data; break; case T_MX: case T_AFSDB: /* grab preference */ bcopy((char *)cp, data, sizeof(u_int16_t)); cp1 = data + sizeof(u_int16_t); cp += sizeof(u_int16_t); /* get name */ if ((n = dn_expand((u_char *)msg, (u_char *)msg + msglen, cp, cp1, sizeof(data) - sizeof(u_int16_t))) < 0) { hp->rcode = FORMERR; return(-1); } cp += n; /* compute end of data */ cp1 += strlen((char *)cp1) + 1; /* compute size of data */ n = cp1 - data; cp1 = data; break; default: dprintf(3, (ddt, "unknown type %d\n", type)); return ((cp - rrp) + dlen); } if (n > MAXDATA) { dprintf(2, (ddt, "update type %d: %d bytes is too much data\n", type, n)); hp->rcode = NOCHANGE; /* XXX - FORMERR ??? */ return(-1); } *VCode = validate(dname, server, type, class,(char *)cp1, n#ifdef NCACHE ,NOERROR#endif ); if (*VCode == INVALID) { dprintf(2, (ddt, "validation failed d:%s, t:%d, c:%d\n", dname, type, class)); } else { dprintf(2, (ddt, "validation succeeded d:%s, t:%d, c:%d\n", dname, type, class)); } return(cp -rrp);}/****************************************************************** * This manages a data structure that stores all RRs that we were * unable to validate. Am not sure exactly what purpose this might * serve but until such time as we are sure it will not help, let * me do it anyway. *****************************************************************/static voidstick_in_queue(dname, type, class, data) char *dname; int type; int class; char *data;{ struct timeval tp; struct timezone tzp; TO_Validate *tempVQ; u_long leasttime; if (validateQ == NULL) { validateQ = (TO_Validate *)malloc(sizeof(TO_Validate)); validateQ->type = type; validateQ->class = class; validateQ->dname = malloc((unsigned)strlen(dname)+1); strcpy(validateQ->dname, dname); validateQ->data = malloc((unsigned)strlen(data)+1); strcpy(validateQ->data, data); gettimeofday(&tp, &tzp); validateQ->time = tp.tv_sec; VQcount = 1; validateQ->next = validateQ->prev = NULL; currentVQ = validateQ; return; } if (VQcount < MAXVQ) { tempVQ =(TO_Validate *)malloc(sizeof(TO_Validate)); tempVQ->type = type; tempVQ->class = class; tempVQ->dname = malloc((unsigned)strlen(dname)+1); strcpy(tempVQ->dname, dname); tempVQ->data = malloc((unsigned)strlen(data)+1); strcpy(tempVQ->data, data); gettimeofday(&tp,&tzp); tempVQ->time = tp.tv_sec; tempVQ->next = currentVQ->next; tempVQ->prev = currentVQ; if (currentVQ->next != NULL) currentVQ->next->prev = tempVQ; currentVQ->next = tempVQ; currentVQ = tempVQ; VQcount++; return; } gettimeofday(&tp, &tzp); leasttime = validateQ->time; currentVQ = validateQ; for (tempVQ = validateQ; tempVQ != NULL; tempVQ = tempVQ->next) { if (tp.tv_sec >= tempVQ->time +VQEXPIRY) { tempVQ->type = type; tempVQ->class = class; strcpy(tempVQ->dname, dname); strcpy(tempVQ->data, data); tempVQ->time = tp.tv_sec; currentVQ = tempVQ; return; } if (tempVQ->time < leasttime) { leasttime = tempVQ->time; currentVQ = tempVQ; } } currentVQ->type = type; currentVQ->class = class; strcpy(currentVQ->dname, dname); strcpy(currentVQ->data, data); currentVQ->time = tp.tv_sec; return;}/* removes any INVALID RR's from the msg being returned, updates msglen to * reflect the new message length. */intupdate_msg(msg, msglen, Vlist, c) u_char *msg; int *msglen; int Vlist[]; int c;{ register HEADER *hp; register u_char *cp; int i; int n = 0; u_char *tempcp, *newcp; int *RRlen; int qlen; /* the length of the query section*/ u_int16_t rdlength; u_int16_t ancount, nscount; u_int16_t new_ancount, new_nscount, new_arcount; char dname[MAXDNAME], qname[MAXDNAME]; u_char data[MAXDNAME]; u_char **dpp; u_char *dnptrs[40]; u_char **edp = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]); u_char *eom = msg + *msglen; int n_new; int rembuflen, newlen; u_char *newmsg; u_int16_t type, class, dlen; u_int32_t ttl; int inv = 0;#ifdef DEBUG if (debug) { fprintf(ddt, "update_msg: msglen:%d, c:%d\n", *msglen, c); if (debug >= 10) fp_query((char *)msg,ddt); }#endif /* just making sure we do not do all the work for nothing */ for (i=0; i<c; i++) { if (Vlist[i] == INVALID) { inv = 1; break; } } if (inv != 1) { /* no invalid records, go about your job */ return (0); } dprintf(2, (ddt, "update_msg: NEEDS updating:\n")); RRlen = (int *)malloc((unsigned)c*sizeof(int)); hp = (HEADER *)msg; new_ancount = ancount = ntohs(hp->ancount); new_nscount = nscount = ntohs(hp->nscount); new_arcount = ntohs(hp->nscount); cp = msg + sizeof(HEADER); newlen = sizeof(HEADER); /* skip the query section */ qlen = dn_expand(msg, eom, cp, (u_char *)qname, sizeof(qname)); if (qlen <= 0) { dprintf(2, (ddt, "dn_skipname() failed, bad record\n")); goto badend; } cp +=qlen; GETSHORT(type,cp); GETSHORT(class,cp); qlen += 2 * sizeof(u_int16_t); newlen += qlen; for (i = 0; i < c; i++) { if (Vlist[i] == INVALID) { if (i < ancount) new_ancount--; else if (i < ancount+nscount) new_nscount--; else new_arcount--; } RRlen[i] = dn_skipname(cp, msg + *msglen); if (RRlen[i] <= 0) { dprintf(2, (ddt, "dn_skipname() failed, bad record\n")); goto badend; } RRlen[i] += 2 * sizeof(u_int16_t) + sizeof(u_int32_t); /*type+class+TTL*/ cp += RRlen[i]; GETSHORT(rdlength, cp); RRlen[i] += sizeof(u_int16_t); /*rdlength*/ RRlen[i] += rdlength; /*rdata field*/ dprintf(3, (ddt, "RRlen[%d]=%d\n", i, RRlen[i])); if (Vlist[i] != INVALID) newlen += RRlen[i]; cp += rdlength; /*increment pointer to next RR*/ } hp->ancount = htons(new_ancount); hp->nscount = htons(new_nscount); hp->arcount = htons(new_nscount); /* get new buffer */ dprintf(3, (ddt, "newlen:%d, if no RR is INVALID == msglen\n", newlen)); newmsg = (u_char *)calloc(1,newlen + MAXDNAME); if(newmsg == NULL) goto badend; dpp = dnptrs; *dpp++ = newmsg; *dpp = NULL; /* bcopy the header, with all the length fields correctly put in */ bcopy((char *)msg, (char*)newmsg, sizeof(HEADER)); /*header copied */ newcp = newmsg +sizeof(HEADER); /*need a pointer in the new buffer */ rembuflen = newlen +MAXDNAME - sizeof(HEADER); /*buflen we can workin*/ newlen = sizeof(HEADER); /* this will now contain the length of msg */ n_new = dn_comp((u_char *)qname, (u_char *)newcp, rembuflen, (u_char **)dnptrs, (u_char **)edp); if (n_new < 0) goto badend; newcp += n_new; PUTSHORT(type, newcp); PUTSHORT(class, newcp); /*query section complete*/ newlen += (n_new+2*sizeof(u_int16_t)); rembuflen -= (n_new+2*sizeof(u_int16_t)); /* have to decode and copy every Valid RR from here */ cp = msg +sizeof(HEADER) +qlen; /*skip header and query section*/ for (i = 0; i < c; i++) { if (Vlist[i] == INVALID) { /* go to next RR if this one is not INVALID */ cp += RRlen[i]; continue; } /* we have a valid record, must put it in the newmsg */ if ((n = dn_expand((u_char *)msg, eom, cp, (u_char *)dname, sizeof(dname))) < 0) { hp->rcode = FORMERR; goto badend; } n_new = dn_comp((u_char *)dname, (u_char *)newcp, rembuflen, (u_char **)dnptrs, (u_char **)edp); if (n_new < 0) goto badend; cp += n; newcp += n_new; dprintf(5, (ddt, "cp:0x%x newcp:0x%x after getting name\n", cp, newcp)); GETSHORT(type, cp); PUTSHORT(type, newcp); dprintf(5, (ddt, "cp:0x%x newcp:0x%x after getting type\n", cp, newcp)); GETSHORT(class, cp); PUTSHORT(class, newcp); dprintf(5, (ddt, "cp:0x%x newcp:0x%x after getting class\n", cp, newcp)); GETLONG(ttl, cp); PUTLONG(ttl, newcp); dprintf(5, (ddt, "cp:0x%x newcp:0x%x after getting ttl\n", cp, newcp)); /* this will probably be modified for newmsg, * will put this in later, after compression */ GETSHORT(dlen, cp); newlen += (n_new+3*sizeof(u_int16_t) + sizeof(u_int32_t)); rembuflen -= (n_new+3*sizeof(u_int16_t)+ sizeof(u_int32_t)); tempcp = newcp; newcp += sizeof(u_int16_t); /*advance to rdata field*/ dprintf(5, (ddt, "tempcp:0x%x newcp:0x%x\n", tempcp, newcp)); dprintf(3, (ddt, "update_msg: dname %s type %d class %d ttl %d\n", dname, type, class, ttl)); /* read off the data section */ switch (type) { case T_A: case T_WKS: case T_HINFO: case T_UINFO: case T_UID: case T_GID: case T_TXT:#ifdef ALLOW_T_UNSPEC case T_UNSPEC:#endif n = dlen; PUTSHORT(n, tempcp); /*time to put in the dlen*/ bcopy(cp, newcp,n); /*done here*/ cp +=n; newcp +=n; newlen += n; rembuflen -= n; dprintf(3, (ddt, "\tcp:0x%x newcp:0x%x dlen:%d\n", cp, newcp, dlen)); break; case T_CNAME: case T_MB: case T_MG: case T_MR: case T_NS: case T_PTR: /*read off name from data section */ if ((n = dn_expand((u_char *)msg, eom, cp, data, sizeof(data))) < 0) { hp->rcode = FORMERR; goto badend; } cp += n; /*advance pointer*/ /* fill in new packet */ n_new = dn_comp((u_char *)data, (u_char *)newcp, rembuflen, (u_char **)dnptrs, (u_char **)edp); if (n_new < 0) goto badend; PUTSHORT(n_new,tempcp); /*put in dlen field*/ newcp += n_new; /*advance new pointer*/ newlen += n_new; rembuflen -= n_new; break; case T_MINFO: case T_SOA: case T_RP: if ((n = dn_expand((u_char *)msg, eom, cp, data, sizeof(data))) < 0) { hp->rcode = FORMERR; goto badend; } cp += n; n_new = dn_comp((u_char *)data, (u_char *)newcp, rembuflen, (u_char **)dnptrs, (u_char **)edp); if (n_new < 0) goto badend; newcp += n_new; newlen += n_new; rembuflen -= n_new; dlen = n_new; if ((n = dn_expand((u_char *)msg, eom, cp, data, sizeof(data))) < 0) { hp->rcode = FORMERR; goto badend; } cp += n; n_new = dn_comp((u_char *)data, (u_char *)newcp, rembuflen, (u_char **)dnptrs, (u_char **)edp); if (n_new < 0) goto badend; newcp += n_new; newlen += n_new; rembuflen -= n_new; dlen += n_new; if (type == T_SOA) { bcopy(cp, newcp, n = 5*sizeof(u_int32_t)); cp += n; newcp += n; newlen +=n; rembuflen -= n; dlen +=n; } PUTSHORT(dlen, tempcp); break; case T_MX: case T_AFSDB: /* grab preference */ bcopy(cp,newcp,sizeof(u_int16_t)); cp += sizeof(u_int16_t); newcp += sizeof(u_int16_t); /* get name */ if ((n = dn_expand((u_char *)msg, eom, cp, data, sizeof(data))) < 0) { hp->rcode = FORMERR; goto badend; } cp += n; n_new = dn_comp((u_char *)data, (u_char *)newcp, rembuflen, (u_char **)dnptrs, (u_char **)edp); if (n_new < 0) goto badend; PUTSHORT(n_new+sizeof(u_int16_t), tempcp); newcp += n_new; newlen += n_new+sizeof(u_int16_t); rembuflen -= n_new+sizeof(u_int16_t); break; default: dprintf(3, (ddt, "unknown type %d\n", type)); goto badend; } dprintf(2, (ddt, "newlen:%d, i:%d newcp:0x%x cp:0x%x\n\n", newlen, i, newcp, cp)); } bcopy(newmsg, msg, newlen); n = *msglen - newlen; if (n < 0) { dprintf(2, (ddt, "update_msg():newmsg longer than old: n:%d o:%d ???\n", newlen, *msglen)); } *msglen = newlen; free((char *)newmsg); #ifdef DEBUG if (debug >= 10) fp_query((char *)msg, ddt);#endif free((char *)RRlen); return(n);badend: dprintf(2, (ddt, "encountered problems: UPDATE_MSG\n")); free((char *)RRlen); return(-1);}#endif /*VALIDATE*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -