📄 setup.c
字号:
/* * setup.c * - configuration file parsing * - management of global state *//* * This file is * Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk> * * It is part of adns, which is * Copyright (C) 1997-2000 Ian Jackson <ian@davenant.greenend.org.uk> * Copyright (C) 1999-2000 Tony Finch <dot@dotat.at> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <stdlib.h>#include <errno.h>#include <limits.h>#include <unistd.h>#include <fcntl.h>#include <netdb.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include "internal.h"static void readconfig(adns_state ads, const char *filename, int warnmissing);static void addserver(adns_state ads, struct in_addr addr) { int i; struct server *ss; for (i=0; i<ads->nservers; i++) { if (ads->servers[i].addr.s_addr == addr.s_addr) { adns__debug(ads,-1,0,"duplicate nameserver %s ignored",inet_ntoa(addr)); return; } } if (ads->nservers>=MAXSERVERS) { adns__diag(ads,-1,0,"too many nameservers, ignoring %s",inet_ntoa(addr)); return; } ss= ads->servers+ads->nservers; ss->addr= addr; ads->nservers++;}static void freesearchlist(adns_state ads) { if (ads->nsearchlist) free(*ads->searchlist); free(ads->searchlist);}static void saveerr(adns_state ads, int en) { if (!ads->configerrno) ads->configerrno= en;}static void configparseerr(adns_state ads, const char *fn, int lno, const char *fmt, ...) { va_list al; saveerr(ads,EINVAL); if (!ads->diagfile || (ads->iflags & adns_if_noerrprint)) return; if (lno==-1) fprintf(ads->diagfile,"adns: %s: ",fn); else fprintf(ads->diagfile,"adns: %s:%d: ",fn,lno); va_start(al,fmt); vfprintf(ads->diagfile,fmt,al); va_end(al); fputc('\n',ads->diagfile);}static int nextword(const char **bufp_io, const char **word_r, int *l_r) { const char *p, *q; p= *bufp_io; while (ctype_whitespace(*p)) p++; if (!*p) return 0; q= p; while (*q && !ctype_whitespace(*q)) q++; *l_r= q-p; *word_r= p; *bufp_io= q; return 1;}static void ccf_nameserver(adns_state ads, const char *fn, int lno, const char *buf) { struct in_addr ia; if (!inet_aton(buf,&ia)) { configparseerr(ads,fn,lno,"invalid nameserver address `%s'",buf); return; } adns__debug(ads,-1,0,"using nameserver %s",inet_ntoa(ia)); addserver(ads,ia);}static void ccf_search(adns_state ads, const char *fn, int lno, const char *buf) { const char *bufp, *word; char *newchars, **newptrs, **pp; int count, tl, l; if (!buf) return; bufp= buf; count= 0; tl= 0; while (nextword(&bufp,&word,&l)) { count++; tl += l+1; } newptrs= malloc(sizeof(char*)*count); if (!newptrs) { saveerr(ads,errno); return; } newchars= malloc(tl); if (!newchars) { saveerr(ads,errno); free(newptrs); return; } bufp= buf; pp= newptrs; while (nextword(&bufp,&word,&l)) { *pp++= newchars; memcpy(newchars,word,l); newchars += l; *newchars++ = 0; } freesearchlist(ads); ads->nsearchlist= count; ads->searchlist= newptrs;}static void ccf_sortlist(adns_state ads, const char *fn, int lno, const char *buf) { const char *word; char tbuf[200], *slash, *ep; struct in_addr base, mask; int l; unsigned long initial, baselocal; if (!buf) return; ads->nsortlist= 0; while (nextword(&buf,&word,&l)) { if (ads->nsortlist >= MAXSORTLIST) { adns__diag(ads,-1,0,"too many sortlist entries, ignoring %.*s onwards",l,word); return; } if (l >= sizeof(tbuf)) { configparseerr(ads,fn,lno,"sortlist entry `%.*s' too long",l,word); continue; } memcpy(tbuf,word,l); tbuf[l]= 0; slash= strchr(tbuf,'/'); if (slash) *slash++= 0; if (!inet_aton(tbuf,&base)) { configparseerr(ads,fn,lno,"invalid address `%s' in sortlist",tbuf); continue; } if (slash) { if (strchr(slash,'.')) { if (!inet_aton(slash,&mask)) { configparseerr(ads,fn,lno,"invalid mask `%s' in sortlist",slash); continue; } if (base.s_addr & ~mask.s_addr) { configparseerr(ads,fn,lno, "mask `%s' in sortlist overlaps address `%s'",slash,tbuf); continue; } } else { initial= strtoul(slash,&ep,10); if (*ep || initial>32) { configparseerr(ads,fn,lno,"mask length `%s' invalid",slash); continue; } mask.s_addr= htonl((0x0ffffffffUL) << (32-initial)); } } else { baselocal= ntohl(base.s_addr); if (!baselocal & 0x080000000UL) /* class A */ mask.s_addr= htonl(0x0ff000000UL); else if ((baselocal & 0x0c0000000UL) == 0x080000000UL) mask.s_addr= htonl(0x0ffff0000UL); /* class B */ else if ((baselocal & 0x0f0000000UL) == 0x0e0000000UL) mask.s_addr= htonl(0x0ff000000UL); /* class C */ else { configparseerr(ads,fn,lno, "network address `%s' in sortlist is not in classed ranges," " must specify mask explicitly", tbuf); continue; } } ads->sortlist[ads->nsortlist].base= base; ads->sortlist[ads->nsortlist].mask= mask; ads->nsortlist++; }}static void ccf_options(adns_state ads, const char *fn, int lno, const char *buf) { const char *word; char *ep; unsigned long v; int l; if (!buf) return; while (nextword(&buf,&word,&l)) { if (l==5 && !memcmp(word,"debug",5)) { ads->iflags |= adns_if_debug; continue; } if (l>=6 && !memcmp(word,"ndots:",6)) { v= strtoul(word+6,&ep,10); if (l==6 || ep != word+l || v > INT_MAX) { configparseerr(ads,fn,lno,"option `%.*s' malformed or has bad value",l,word); continue; } ads->searchndots= v; continue; } if (l>=12 && !memcmp(word,"adns_checkc:",12)) { if (!strcmp(word+12,"none")) { ads->iflags &= ~adns_if_checkc_freq; ads->iflags |= adns_if_checkc_entex; } else if (!strcmp(word+12,"entex")) { ads->iflags &= ~adns_if_checkc_freq; ads->iflags |= adns_if_checkc_entex; } else if (!strcmp(word+12,"freq")) { ads->iflags |= adns_if_checkc_freq; } else { configparseerr(ads,fn,lno, "option adns_checkc has bad value `%s' " "(must be none, entex or freq", word+12); } continue; } adns__diag(ads,-1,0,"%s:%d: unknown option `%.*s'", fn,lno, l,word); }}static void ccf_clearnss(adns_state ads, const char *fn, int lno, const char *buf) { ads->nservers= 0;}static void ccf_include(adns_state ads, const char *fn, int lno, const char *buf) { if (!*buf) { configparseerr(ads,fn,lno,"`include' directive with no filename"); return; } readconfig(ads,buf,1);}static const struct configcommandinfo { const char *name; void (*fn)(adns_state ads, const char *fn, int lno, const char *buf);} configcommandinfos[]= { { "nameserver", ccf_nameserver }, { "domain", ccf_search }, { "search", ccf_search }, { "sortlist", ccf_sortlist }, { "options", ccf_options }, { "clearnameservers", ccf_clearnss }, { "include", ccf_include }, { 0 }};typedef union { FILE *file; const char *text;} getline_ctx;static int gl_file(adns_state ads, getline_ctx *src_io, const char *filename, int lno, char *buf, int buflen) { FILE *file= src_io->file; int c, i; char *p; p= buf; buflen--; i= 0; for (;;) { /* loop over chars */ if (i == buflen) { adns__diag(ads,-1,0,"%s:%d: line too long, ignored",filename,lno); goto x_badline; } c= getc(file); if (!c) { adns__diag(ads,-1,0,"%s:%d: line contains nul, ignored",filename,lno); goto x_badline; } else if (c == '\n') { break; } else if (c == EOF) { if (ferror(file)) { saveerr(ads,errno); adns__diag(ads,-1,0,"%s:%d: read error: %s",filename,lno,strerror(errno)); return -1; } if (!i) return -1; break; } else { *p++= c; i++; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -