📄 nslint.c
字号:
fprintf(stderr, "%s: nslint: calloc: %s\n", prog, strerror(errno)); exit(1); } ipp = itemlist; for (n = 0, ip = items; n < ITEMSIZE; ++n, ++ip) { if (ip->host == NULL) continue; /* Save entries with addresses for later check */ if (ip->addr != 0) *ipp++ = ip; if (debug > 1) { if (debug > 2) printf("%d\t", n); printf("%s\t%s\t0x%x\t0x%x\n", ip->host, intoa(ip->addr), ip->records, ip->flags); } /* Check for illegal hostnames (rfc1034) */ if (rfc1034host(ip->host, ip->records)) ++errors; /* Check for missing ptr records (ok if also an ns record) */ records = ip->records & MASK_CHECK_REC; if ((ip->records & MASK_TEST_REC) != 0) records |= REC_OTHER; switch (records) { case REC_A | REC_OTHER | REC_PTR | REC_REF: case REC_A | REC_OTHER | REC_PTR: case REC_A | REC_PTR | REC_REF: case REC_A | REC_PTR: case REC_CNAME: /* These are O.K. */ break; case REC_CNAME | REC_REF: ++errors; fprintf(stderr, "%s: \"cname\" referenced by other" " \"cname\" or \"mx\": %s\n", prog, ip->host); break; case REC_OTHER | REC_REF: case REC_OTHER: /* * This is only an error if there is an address * associated with the hostname; this means * there was a wks entry with bogus address. * Otherwise, we have an mx or hinfo. */ if (ip->addr != 0) { ++errors; fprintf(stderr, "%s: \"wks\" without \"a\" and \"ptr\": %s -> %s\n", prog, ip->host, intoa(ip->addr)); } break; case REC_REF: ++errors; fprintf(stderr, "%s: name referenced without other records: %s\n", prog, ip->host); break; case REC_A | REC_OTHER | REC_REF: case REC_A | REC_OTHER: case REC_A | REC_REF: case REC_A: ++errors; fprintf(stderr, "%s: missing \"ptr\": %s -> %s\n", prog, ip->host, intoa(ip->addr)); break; case REC_OTHER | REC_PTR | REC_REF: case REC_OTHER | REC_PTR: case REC_PTR | REC_REF: case REC_PTR: ++errors; fprintf(stderr, "%s: missing \"a\": %s -> %s\n", prog, ip->host, intoa(ip->addr)); break; case REC_A | REC_CNAME | REC_OTHER | REC_PTR | REC_REF: case REC_A | REC_CNAME | REC_OTHER | REC_PTR: case REC_A | REC_CNAME | REC_OTHER | REC_REF: case REC_A | REC_CNAME | REC_OTHER: case REC_A | REC_CNAME | REC_PTR | REC_REF: case REC_A | REC_CNAME | REC_PTR: case REC_A | REC_CNAME | REC_REF: case REC_A | REC_CNAME: case REC_CNAME | REC_OTHER | REC_PTR | REC_REF: case REC_CNAME | REC_OTHER | REC_PTR: case REC_CNAME | REC_OTHER | REC_REF: case REC_CNAME | REC_OTHER: case REC_CNAME | REC_PTR | REC_REF: case REC_CNAME | REC_PTR: ++errors; fprintf(stderr, "%s: \"cname\" %s has other records\n", prog, ip->host); break; case 0: /* Second level test */ if ((ip->records & ~(REC_NS | REC_TXT)) == 0) break; /* Fall through... */ default: ++errors; fprintf(stderr, "%s: records == 0x%x: can't happen (%s 0x%x)\n", prog, records, ip->host, ip->records); break; } /* Check for smtp problems */ flags = ip->flags & MASK_TEST_SMTP; if ((flags & FLG_SELFMX) != 0 && (ip->records & REC_A) == 0) { ++errors; fprintf(stderr, "%s: self \"mx\" for %s missing \"a\" record\n", prog, ip->host); } switch (flags) { case 0: case FLG_SELFMX | FLG_SMTPWKS: /* These are O.K. */ break; case FLG_SELFMX: if ((ip->records & REC_WKS) != 0) { ++errors; fprintf(stderr, "%s: smtp/tcp missing from \"wks\": %s\n", prog, ip->host); } break; case FLG_SMTPWKS: ++errors; fprintf(stderr, "%s: saw smtp/tcp without self \"mx\": %s\n", prog, ip->host); break; default: ++errors; fprintf(stderr, "%s: flags == 0x%x: can't happen (%s)\n", prog, flags, ip->host); } /* Check for chained MX records */ if ((ip->flags & (FLG_SELFMX | FLG_MXREF)) == FLG_MXREF && (ip->records & REC_MX) != 0) { ++errors; fprintf(stderr, "%s: \"mx\" referenced by other" " \"mx\" record: %s\n", prog, ip->host); } } /* Check for doubly booked addresses */ n = ipp - itemlist; qsort(itemlist, n, sizeof(itemlist[0]), cmpaddr); lastaddr = 0; ip = NULL; for (ipp = itemlist; n > 0; ++ipp, --n) { addr = (*ipp)->addr; if (lastaddr == addr && ((*ipp)->flags & FLG_ALLOWDUPA) == 0 && (ip->flags & FLG_ALLOWDUPA) == 0) { ++errors; fprintf(stderr, "%s: %s in use by %s and %s\n", prog, intoa(addr), (*ipp)->host, ip->host); } lastaddr = addr; ip = *ipp; } /* Check for hosts with multiple addresses on the same subnet */ n = ipp - itemlist; qsort(itemlist, n, sizeof(itemlist[0]), cmphost); if (netlistcnt > 0) { n = ipp - itemlist; lastaip = NULL; for (ipp = itemlist; n > 0; ++ipp, --n) { ip = *ipp; if ((ip->records & REC_A) == 0 || (ip->flags & FLG_ALLOWDUPA) != 0) continue; if (lastaip != NULL && strcasecmp(ip->host, lastaip->host) == 0) { mask = findmask(ip->addr); if (mask == 0) { ++errors; fprintf(stderr, "%s: can't find mask for %s (%s)\n", prog, ip->host, intoa(ip->addr)); } else if ((lastaip->addr & mask) == (ip->addr & mask) ) { ++errors; fprintf(stderr, "%s: multiple \"a\" records for %s on subnet %s", prog, ip->host, intoa(ip->addr & mask)); fprintf(stderr, "\n\t(%s", intoa(lastaip->addr)); fprintf(stderr, " and %s)\n", intoa(ip->addr)); } } lastaip = ip; } } if (debug) printf("%s: %d/%d items used, %d error%s\n", prog, itemcnt, ITEMSIZE, errors, errors == 1 ? "" : "s"); return (errors != 0);}/* Similar to inet_ntoa() */char *intoa(u_int32_t addr){ register char *cp; register u_int byte; register int n; static char buf[sizeof(".xxx.xxx.xxx.xxx")]; cp = &buf[sizeof buf]; *--cp = '\0'; n = 4; do { byte = addr & 0xff; *--cp = byte % 10 + '0'; byte /= 10; if (byte > 0) { *--cp = byte % 10 + '0'; byte /= 10; if (byte > 0) *--cp = byte + '0'; } *--cp = '.'; addr >>= 8; } while (--n > 0); return cp + 1;}intparseinaddr(register const char *cp, register u_int32_t *netp, register u_int32_t *maskp){ register int i, bits; register u_int32_t o, net, mask; if (!isdigit(*cp)) return (0); net = 0; mask = 0xff000000; bits = 0; o = 0; do { o = o * 10 + (*cp++ - '0'); } while (isdigit(*cp)); net = o << 24; /* Check for classless delegation mask width */ if (*cp == '/') { ++cp; o = 0; do { o = o * 10 + (*cp++ - '0'); } while (isdigit(*cp)); bits = o; if (bits <= 0 || bits > 32) return (0); } if (*cp == '.' && isdigit(cp[1])) { ++cp; o = 0; do { o = o * 10 + (*cp++ - '0'); } while (isdigit(*cp)); net = (net >> 8) | (o << 24); mask = 0xffff0000; if (*cp == '.' && isdigit(cp[1])) { ++cp; o = 0; do { o = o * 10 + (*cp++ - '0'); } while (isdigit(*cp)); net = (net >> 8) | (o << 24); mask = 0xffffff00; if (*cp == '.' && isdigit(cp[1])) { ++cp; o = 0; do { o = o * 10 + (*cp++ - '0'); } while (isdigit(*cp)); net = (net >> 8) | (o << 24); mask = 0xffffffff; } } } if (strcasecmp(cp, inaddr) != 0) return (0); /* Classless delegation */ /* XXX check that calculated mask isn't smaller than octet mask? */ if (bits != 0) for (mask = 0, i = 31; bits > 0; --i, --bits) mask |= (1 << i); *netp = net; *maskp = mask; return (1);}u_int32_tparseptr(register const char *cp, u_int32_t net, u_int32_t mask, register char **errstrp){ register u_int32_t o, addr; register int shift; addr = 0; shift = 0; while (isdigit(*cp) && shift < 32) { o = 0; do { o = o * 10 + (*cp++ - '0'); } while (isdigit(*cp)); addr |= o << shift; shift += 8; if (*cp != '.') { if (*cp == '\0') break; *errstrp = "missing dot"; return (0); } ++cp; } if (shift > 32) { *errstrp = "more than 4 octets"; return (0); } if (shift == 32 && strcasecmp(cp, inaddr + 1) == 0) return (addr);#ifdef notdef if (*cp != '\0') { *errstrp = "trailing junk"; return (0); }#endif#ifdef notdef if ((~mask & net) != 0) { *errstrp = "too many octets for net"; return (0); }#endif return (net | addr);}intcheckwks(register FILE *f, register char *proto, register int *smtpp, register char **errstrp){ register int n, sawparen; register char *cp, *serv, **p; static char errstr[132]; char buf[1024]; char psbuf[512]; if (!protoserv_init) { initprotoserv(); ++protoserv_init; } /* Line count */ n = 0; /* Terminate protocol */ cp = proto; while (!isspace(*cp) && *cp != '\0') ++cp; if (*cp != '\0') *cp++ = '\0'; /* Find services */ *smtpp = 0; sawparen = 0; if (*cp == '(') { ++sawparen; ++cp; while (isspace(*cp)) ++cp; } for (;;) { if (*cp == '\0') { if (!sawparen) break; if (fgets(buf, sizeof(buf), f) == NULL) { *errstrp = "mismatched parens"; return (n); } ++n; cp = buf; while (isspace(*cp)) ++cp; } /* Find end of service, converting to lowercase */ for (serv = cp; !isspace(*cp) && *cp != '\0'; ++cp) if (isupper(*cp)) *cp = tolower(*cp); if (*cp != '\0') *cp++ = '\0'; if (sawparen && *cp == ')') { /* XXX should check for trailing junk */ break; } (void)sprintf(psbuf, "%s/%s", serv, proto); if (*serv == 's' && strcmp(psbuf, "tcp/smtp") == 0) ++*smtpp; for (p = protoserv; *p != NULL; ++p) if (*psbuf == **p && strcmp(psbuf, *p) == 0) { break; } if (*p == NULL) { sprintf(errstr, "%s unknown", psbuf); *errstrp = errstr; break; } } return (n);}intcheckserv(register const char *serv, register char **p){ for (; *p != NULL; ++p) if (*serv == **p && strcmp(serv, *p) == 0) return (1); return (0);}voidinitprotoserv(void){ register char *cp; register struct servent *sp; char psbuf[512]; protoserv_len = 256; protoserv = (char **)malloc(protoserv_len * sizeof(*protoserv)); if (protoserv == NULL) { fprintf(stderr, "%s: nslint: malloc: %s\n", prog, strerror(errno)); exit(1); } while ((sp = getservent()) != NULL) { (void)sprintf(psbuf, "%s/%s", sp->s_name, sp->s_proto); /* Convert to lowercase */ for (cp = psbuf; *cp != '\0'; ++cp) if (isupper(*cp)) *cp = tolower(*cp); if (protoserv_last + 1 >= protoserv_len) { protoserv_len <<= 1; protoserv = realloc(protoserv, protoserv_len * sizeof(*protoserv)); if (protoserv == NULL) { fprintf(stderr, "%s: nslint: realloc: %s\n", prog, strerror(errno)); exit(1); } } protoserv[protoserv_last] = savestr(psbuf); ++protoserv_last; } protoserv[protoserv_last] = NULL;}/* * Returns true if name contains a dot but not a trailing dot. * Special case: allow a single dot if the second part is not one * of the 3 or 4 letter top level domains or is any 2 letter TLD */intcheckdots(register const char *name){ register const char *cp, *cp2; if ((cp = strchr(name, '.')) == NULL) return (0); cp2 = name + strlen(name) - 1; if (cp2 >= name && *cp2 == '.') return (0); /* Return true of more than one dot*/ ++cp; if (strchr(cp, '.') != NULL) return (1); if (strlen(cp) == 2 || strcasecmp(cp, "gov") == 0 || strcasecmp(cp, "edu") == 0 || strcasecmp(cp, "com") == 0 || strcasecmp(cp, "net") == 0 || strcasecmp(cp, "org") == 0 || strcasecmp(cp, "mil") == 0 || strcasecmp(cp, "int") == 0 || strcasecmp(cp, "nato") == 0 || strcasecmp(cp, "arpa") == 0) return (1); return (0);}intcmpaddr(register const void *ip1, register const void *ip2){ register u_int32_t a1, a2; a1 = (*(struct item **)ip1)->addr; a2 = (*(struct item **)ip2)->addr; if (a1 < a2) return (-1); else if (a1 > a2) return (1); else return (0);}intcmphost(register const void *ip1, register const void *ip2){ register const char *s1, *s2; s1 = (*(struct item **)ip1)->host; s2 = (*(struct item **)ip2)->host; return (strcasecmp(s1, s2));}/* Returns a pointer after the next token or quoted string, else NULL */char *parsequoted(register char *cp){ if (*cp == '"') { ++cp; while (*cp != '"' && *cp != '\0') ++cp; if (*cp != '"') return (NULL); ++cp; } else { while (!isspace(*cp) && *cp != '\0') ++cp; } return (cp);}__dead voidusage(void){ extern char version[]; fprintf(stderr, "Version %s\n", version); fprintf(stderr, "usage: %s [-d] [-b named.boot] [-B nslint.boot]\n", prog); fprintf(stderr, " %s [-d] [-c named.conf] [-C nslint.conf]\n", prog); exit(1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -