📄 nsdb.c
字号:
}/* * writedb writes the entire database to a file, returning * the number of lines written. */intwritedb(file)char *file;{ struct domain *d; FILE *fp; int ret; if ((fp = fopen(file,"w")) == NULL) { perror(file); return(0); } d = Domain; ret = wrdom(d,"",fp); fclose(fp); return(ret);}/* * recursively dump the contents of a domain * to a file. The format is the same as used * in the rfmaster file and can be read by readfile. */static intwrdom(d,name,fp)struct domain *d;char *name; /* name so far */FILE *fp;{ struct res_rec **list; struct res_rec *rec; char dname[64]; int type; char *ctype; int i; if (d == NULL || d->d_rec == NULL) return(0); for (i=0,list=d->d_rec; *list != NULL; list++,i++) { rec = *list;#ifdef RIGHT_TO_LEFT sprintf(dname,"%s.%s",rec->rr_name,name); if (*name == '\0') dname[strlen(dname)-1] = '\0';#else if (*name == '\0') strcpy(dname,rec->rr_name); else sprintf(dname,"%s.%s",name,rec->rr_name);#endif type = rec->rr_type; if (strcmp((ctype=getctype(type)),"NULL") == 0) continue; switch (type) { case RN: fprintf(fp,"%s %s %s %s %s %s\n",dname,ctype, rec->rr_owner, (rec->rr_flag == A_RDONLY)?"RO":"RW", rec->rr_path, rec->rr_desc); break; case DOM: i += wrdom(rec->rr_dom,dname,fp); break; default: fprintf(fp,"%s %s %s\n",dname,ctype, (rec->rr_data)?(rec->rr_data):"NULL"); } } return(i);}/* * read a file in rfmaster format and update the database accordingly. * If clflg is set, the current database will be cleared first, otherwise * the contents of the file will be merged on top of the current database. * If override is set, a record read in from the file will replace any * matching record already in the database (even if that record has just * been read in from the same file), otherwise, duplicate records are * discarded. readfile returns the number of valid records read, * or -1 if it cannot access the file. */intreadfile(file,clflg,override)char *file;int clflg;int override;{ FILE *fp; char buf[BUFSIZ]; int i, j, k; int ret; int itype; int found = FALSE; struct res_rec *res; struct res_rec *tres; struct res_rec **tlist; struct domain *d; int auth; char *name; char *type; char *rdata; LOG4(L_OVER,"%s: read file '%s'%s\n",(clflg)?"readdb":"merge",file, (override)?", override previous values":""); if ((fp = fopen(file,"r")) == NULL) return(-1); if (clflg) freedom(Domain); for (i=1, j=0; fgets(buf,BUFSIZ,fp) != NULL; i++, fflush(Logfd)) { /* ignore comment lines */ if (*buf == '#') continue; /* handle lines ending with backslashes */ while (buf[strlen(buf)-2] == '\\' && fgets(&buf[strlen(buf)-2],BUFSIZ-strlen(buf),fp)) i++; buf[strlen(buf)-1] = '\0'; /* get rid of newline */ LOG3(L_DB|L_OVER,"readfile: line %d: %s\n",i,buf); /* ignore blank lines */ if ((name = strtok(buf,WHITESP)) == NULL) continue; if ((type = strtok(NULL,WHITESP)) == NULL) { PLOG4("Warning: file %s, line %d incomplete '%s'\n", file,i,buf); continue; } if ((itype = gettype(type)) == NULL) { PLOG4("Warning: file %s, line %d, unknown type = '%s'\n", file,i,type); continue; } rdata = type + 2; rdata += strspn(rdata,WHITESP); if ((rdata = strtok(rdata, "\n")) == NULL) { PLOG4("Warning: file %s, line %d incomplete '%s'\n", file,i,buf); continue; } if (!islegal(name,(itype==A)?SZ_MACH:SZ_RES)) { PLOG4("Warning: file %s, line %d, illegal name %s\n", file,i,name); continue; } res = (struct res_rec *) calloc(1,sizeof(struct res_rec)); strncpy(res->rr_name,namepart(name),NAMSIZ); res->rr_type = itype; switch(res->rr_type & MASKNS) { case NSTYPE: if (!islegal(rdata,SZ_MACH)) { PLOG4("Warning: file %s, line %d, illegal name %s\n", file,i,rdata); free(res); continue; } if (strcmp(Dname,rdata) == NULL) auth = TRUE; else auth = FALSE; if ((d=newdom(name)) == NULL) { PLOG4("Warning: file %s, line %d bad domain %s\n", file,i,name); free(res); continue; } /* set authorization of domain */ if (auth) setauth(d,res->rr_type); res->rr_ns = copystr(rdata); break; case A: if (newdom(dompart(name)) == NULL) { PLOG4("Warning: file %s, line %d bad domain %s\n", file,i,name); free(res); continue; } res->rr_a = copystr(rdata); break; case DOM: res->rr_dom = (struct domain *)calloc(1,sizeof(struct domain)); res->rr_dauth = atoi(rdata); res->rr_dsize = 0; break; case RN: if (newdom(dompart(name)) == NULL) { PLOG4("Warning: file %s, line %d bad domain %s\n", file,i,name); free(res); continue; } if ((rdata = strtok(rdata,WHITESP)) == NULL) { PLOG4("Warning: file %s, line %d incomplete '%s'\n", file,i,buf); free(res); continue; } res->rr_rn = (struct rn *) calloc(1,sizeof(struct rn)); res->rr_owner = copystr(rdata); /* the rest of these are optional */ if ((rdata = strtok(NULL,WHITESP)) == NULL) break; if (strcmp(rdata,"RW") == NULL) res->rr_flag = 0; else res->rr_flag = 1; if ((rdata = strtok(NULL,WHITESP)) == NULL) break; res->rr_path = copystr(rdata); if ((rdata = strtok(NULL,"\n")) == NULL) break; res->rr_desc = copystr(rdata); break; default: if (newdom(dompart(name)) == NULL) { PLOG4("Warning: file %s, line %d bad domain %s\n", file,i,name); free(res); continue; } res->rr_data = copystr(rdata); break; } if (override && res->rr_type != DOM) remrr(name,res); if ((res->rr_type & MASKNS) == NSTYPE) { if ((tlist = iquery(dompart(name),NSTYPE,res->rr_data)) != NULL) { found = FALSE; for (k=0; tlist[k]; k++) { LOG4(L_COMM,"(%5d) readfile: check %s and %s\n", Logstamp, namepart(name),tlist[k]->rr_name); if (!strcmp(namepart(name),tlist[k]->rr_name)) { found = TRUE; break; } } freelist(tlist); if (found) { free(res); continue; } } if ((ret=addraw(name,res)) == R_DUP && res->rr_type != SOA) { for (k=res->rr_type&~MASKNS; k < MAXNS; k++) { res->rr_type++; if ((ret=addraw(name,res)) == R_NOERR) break; } } if (ret != R_NOERR) { free(res); continue; } } else if ((ret=addraw(name,res)) != R_NOERR) { free(res); continue; } j++; } fclose(fp); return(j);}/* * free contents of a domain. */intcleardom(dname)char *dname;{ struct domain *d; if ((d = finddom(dname,Domain)) == NULL) { LOG3(L_DB,"(%5d) cleardom: can't find domain %s\n", Logstamp, dname); } else freedom(d);}/* * free everything below this domain. */static intfreedom(d)struct domain *d;{ int i; struct res_rec *rec; for (i=0; i < d->d_size && d->d_rec[i] != NULL; i++) { rec = d->d_rec[i]; freerec(rec); d->d_rec[i] = NULL; }}/* * free a list of resource records, including the list itself. */intfreelist(list)struct res_rec **list;{ register int i; if (!list) return; for (i=0; list[i]; i++) freerec(list[i]); free(list); return;}/* * free this record, if record is a domain, recursively free * free everything under it. */intfreerec(rec)struct res_rec *rec;{ switch(rec->rr_type) { case RN: if (rec->rr_rn) { if (rec->rr_owner) free(rec->rr_owner); if (rec->rr_desc) free(rec->rr_desc); if (rec->rr_path) free(rec->rr_path); free(rec->rr_rn); } break; case DOM: freedom(rec->rr_dom); if (rec->rr_drec) free(rec->rr_drec); if (rec->rr_dom) free(rec->rr_dom); break; default: if (rec->rr_data) free(rec->rr_data); break; } free(rec);}/* * domauth returns the value of the d_auth field for the * domain "name." This value is presumed to be SOA or * NS if this name server has authority over this domain. * Otherwise, it is 0. If the domain cannot be found, * the result is also 0. (Can't be an authority over * a domain you don't have.) */intdomauth(name)char *name;{ struct domain *d; if ((d = finddom(name,Domain)) == NULL) { LOG2(L_DB,"(%5d) domauth: returns 0\n",Logstamp); return(0); } LOG3(L_DB,"(%5d) domauth: returns %d\n",Logstamp,d->d_auth); return(d->d_auth);}/* * findmydoms searches the database looking for domains that * this machine is a name server for. It fills in the * array Mydomains with the names of these domains. * findmydoms returns the number of domains it found. */intfindmydoms(){ LOG3(L_COMM,"(%5d) findmydoms: enter, Dname = %s\n", Logstamp, Dname); Mylastdom = 0; rdfind(Domain,""); return(Mylastdom);}static intrdfind(d,name)struct domain *d;char *name;{ int i; char *fmt; struct res_rec *rec; char nbuf[MAXDNAME]; LOG3(L_COMM,"(%5d) findmydoms: rdfind enter, name = '%s'\n", Logstamp, name); fmt = (*name)?"%s.%s":"%s%s"; for (i=0, rec = d->d_rec[0]; i < d->d_size && rec; rec = d->d_rec[++i]) {#ifdef RIGHT_TO_LEFT sprintf(nbuf,fmt,rec->rr_name,name);#else sprintf(nbuf,fmt,name,rec->rr_name);#endif switch (rec->rr_type & MASKNS) { case DOM: rdfind(rec->rr_dom,nbuf); break; case NSTYPE: LOG4(L_COMM,"(%5d) findmydoms: check dom %s, primary %s\n", Logstamp, name, rec->rr_data); if (strcmp(Dname,rec->rr_data)) break; Mydomains[Mylastdom++] = copystr(nbuf); LOG2(L_OVER,"findmydoms: found domain %s\n", Mydomains[Mylastdom-1]); break; } } return;}/* * make a copy of a resource record. * do not recurse through DOM type records. */struct res_rec *duprec(rec)struct res_rec *rec;{ struct res_rec *rrec; LOG3(L_CONV,"(%5d) duprec: enter with record %s\n", Logstamp,(rec)?prec(rec):"NULL RECORD"); if (!rec) return((struct res_rec *) NULL); if ((rrec = (struct res_rec *) calloc(1,sizeof(struct res_rec))) == NULL) { PLOG2("(%5d) nsdb: calloc 1 failed in duprec\n",Logstamp); return((struct res_rec *) NULL); } strncpy(rrec->rr_name,rec->rr_name,NAMSIZ); rrec->rr_type = rec->rr_type; switch(rec->rr_type) { case RN: if ((rrec->rr_rn = (struct rn *) calloc(1,sizeof(struct rn))) == NULL) { PLOG2("(%5d) nsdb: calloc 2 failed in duprec\n",Logstamp); free(rrec); return((struct res_rec *) NULL); } rrec->rr_owner = copystr(rec->rr_owner); rrec->rr_desc = copystr(rec->rr_desc); rrec->rr_path = copystr(rec->rr_path); rrec->rr_flag = rec->rr_flag; LOG3(L_CONV,"(%5d) duprec: copy record %s\n",Logstamp,prec(rrec)); break; case DOM: if ((rrec->rr_dom = (struct domain *) calloc(1,sizeof(struct domain))) == NULL) { PLOG2("(%5d) nsdb: calloc 3 failed in duprec\n",Logstamp); free(rrec); return((struct res_rec *) NULL); } *(rrec->rr_dom) = *(rec->rr_dom); rrec->rr_drec = NULL; rrec->rr_dsize = 0; LOG3(L_CONV,"(%5d) duprec: copy record %s\n",Logstamp,prec(rrec)); break; default: rrec->rr_data = copystr(rec->rr_data); LOG3(L_CONV,"(%5d) duprec: copy record %s\n",Logstamp,prec(rrec)); break; } return(rrec);}/* * copy the query section of a name server request. */struct question **dupqd(qd,count)struct question **qd;int count;{ register int i; struct question **rqd; LOG3(L_CONV,"(%5d) dupqd: copy question section %x\n",Logstamp,qd); if (!qd || count <= 0) return((struct question **) NULL); if ((rqd = (struct question **) calloc(count,sizeof(struct question *))) == NULL) { PLOG2("(%5d) nsdb: calloc in dupqd fails\n", Logstamp); return((struct question **) NULL); } for (i=0; i < count && qd[i]; i++) { rqd[i] = (struct question *) calloc(1,sizeof(struct question)); rqd[i]->q_name = copystr(qd[i]->q_name); rqd[i]->q_type = qd[i]->q_type; } return(rqd);}/* * copy a list of resource records. */struct res_rec **duplist(list)struct res_rec **list;{ register int i; int count; struct res_rec **rlist; LOG3(L_CONV,"(%5d) duplist: copy list %x\n",Logstamp,list); if (!list) return((struct res_rec **) NULL); for (i=0; list[i]; i++) ; count = i; if ((rlist = (struct res_rec **) calloc(count+1,sizeof(struct res_rec *))) == NULL) { PLOG2("(%5d) nsdb: calloc in duplist fails\n", Logstamp); return((struct res_rec **) NULL); } for (i=0; i < count; i++) rlist[i] = duprec(list[i]); rlist[i] = NULL; return(rlist);}/* * check validity of a domain name. * return TRUE if name is valid. * otherwise return FALSE */intislegal(dname,size)char *dname;int size;{ int len; int sflag=FALSE; /* set when possible error is found */ int i; char dbuf[MAXDNAME]; char *p, *np=NULL; if ((len = strlen(dname)) > MAXDNAME || len <= 0 || *dname == SEPARATOR || dname[len-1] == SEPARATOR) return(FALSE); strcpy(dbuf,dname); p=namepart(dbuf); if (((size == SZ_RES)?v_resname(p):v_uname(p)) != 0 || strlen(p) > size) return(FALSE); for (p=rtoken(dbuf); p != NULL && *p != '\0'; p=rtoken(NULL)) { /* return false only when error is found in domain part of name */ if (sflag) return(FALSE); if (v_dname(p) != 0) sflag = TRUE; else if (strlen(p) > SZ_DELEMENT) sflag = TRUE; } return(TRUE);}/* * look for named domain. If it exists, return a pointer to * the domain structure. If not, add it to the database. */static struct domain *newdom(name)char *name;{ struct res_rec *tres; struct domain *d; if ((d=finddom(name,Domain)) == NULL) { tres = (struct res_rec *) calloc(1,sizeof(struct res_rec)); strncpy(tres->rr_name,namepart(name),NAMSIZ); tres->rr_type = DOM; d = tres->rr_dom = (struct domain *) calloc(1,sizeof(struct domain)); setauth(tres->rr_dom,0); tres->rr_dsize = 0; if (addraw(name,tres) != R_NOERR) { free(tres); return((struct domain *) NULL); } } return(d);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -