diff options
author | brian <brian@FreeBSD.org> | 2000-03-14 01:47:27 +0000 |
---|---|---|
committer | brian <brian@FreeBSD.org> | 2000-03-14 01:47:27 +0000 |
commit | 1bc8ab9f4fde76438c6683101c2d510c86e8d978 (patch) | |
tree | 04d2970ad1d86e4a24bfa1b4c7a2b7e16e96b535 | |
parent | 041ec329dc4111a616c48d22712dfcaf9cbfe9bb (diff) | |
download | FreeBSD-src-1bc8ab9f4fde76438c6683101c2d510c86e8d978.zip FreeBSD-src-1bc8ab9f4fde76438c6683101c2d510c86e8d978.tar.gz |
Add the ``resolv'' command for telling ppp how to deal with resolv.conf.
You can now ``resolv restore'' in ppp.linkdown !
Add DNS0 and DNS1 macros.
-rw-r--r-- | usr.sbin/ppp/bundle.c | 17 | ||||
-rw-r--r-- | usr.sbin/ppp/bundle.h | 1 | ||||
-rw-r--r-- | usr.sbin/ppp/command.c | 66 | ||||
-rw-r--r-- | usr.sbin/ppp/filter.c | 24 | ||||
-rw-r--r-- | usr.sbin/ppp/filter.h | 4 | ||||
-rw-r--r-- | usr.sbin/ppp/ipcp.c | 339 | ||||
-rw-r--r-- | usr.sbin/ppp/ipcp.h | 13 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp.8 | 91 | ||||
-rw-r--r-- | usr.sbin/ppp/ppp.8.m4 | 91 | ||||
-rw-r--r-- | usr.sbin/ppp/route.c | 18 | ||||
-rw-r--r-- | usr.sbin/ppp/route.h | 14 |
11 files changed, 527 insertions, 151 deletions
diff --git a/usr.sbin/ppp/bundle.c b/usr.sbin/ppp/bundle.c index f9a9cce..5b5504c 100644 --- a/usr.sbin/ppp/bundle.c +++ b/usr.sbin/ppp/bundle.c @@ -1871,10 +1871,19 @@ void bundle_AdjustFilters(struct bundle *bundle, struct in_addr *my_ip, struct in_addr *peer_ip) { - filter_AdjustAddr(&bundle->filter.in, my_ip, peer_ip); - filter_AdjustAddr(&bundle->filter.out, my_ip, peer_ip); - filter_AdjustAddr(&bundle->filter.dial, my_ip, peer_ip); - filter_AdjustAddr(&bundle->filter.alive, my_ip, peer_ip); + filter_AdjustAddr(&bundle->filter.in, my_ip, peer_ip, NULL); + filter_AdjustAddr(&bundle->filter.out, my_ip, peer_ip, NULL); + filter_AdjustAddr(&bundle->filter.dial, my_ip, peer_ip, NULL); + filter_AdjustAddr(&bundle->filter.alive, my_ip, peer_ip, NULL); +} + +void +bundle_AdjustDNS(struct bundle *bundle, struct in_addr dns[2]) +{ + filter_AdjustAddr(&bundle->filter.in, NULL, NULL, dns); + filter_AdjustAddr(&bundle->filter.out, NULL, NULL, dns); + filter_AdjustAddr(&bundle->filter.dial, NULL, NULL, dns); + filter_AdjustAddr(&bundle->filter.alive, NULL, NULL, dns); } void diff --git a/usr.sbin/ppp/bundle.h b/usr.sbin/ppp/bundle.h index bbdbcbf..2e53ca2 100644 --- a/usr.sbin/ppp/bundle.h +++ b/usr.sbin/ppp/bundle.h @@ -185,6 +185,7 @@ extern int bundle_HighestState(struct bundle *); extern int bundle_Exception(struct bundle *, int); extern void bundle_AdjustFilters(struct bundle *, struct in_addr *, struct in_addr *); +extern void bundle_AdjustDNS(struct bundle *, struct in_addr [2]); extern void bundle_CalculateBandwidth(struct bundle *); extern void bundle_AutoAdjust(struct bundle *, int, int); extern int bundle_WantAutoloadTimer(struct bundle *); diff --git a/usr.sbin/ppp/command.c b/usr.sbin/ppp/command.c index 5e39b72..06ce82d 100644 --- a/usr.sbin/ppp/command.c +++ b/usr.sbin/ppp/command.c @@ -436,6 +436,10 @@ command_Expand(char **nargv, int argc, char const *const *oargv, bundle->ncp.mp.cfg.enddisc.len)); nargv[arg] = subst(nargv[arg], "PROCESSID", pidstr); nargv[arg] = subst(nargv[arg], "LABEL", bundle_GetLabel(bundle)); + nargv[arg] = subst(nargv[arg], "DNS0", + inet_ntoa(bundle->ncp.ipcp.ns.dns[0])); + nargv[arg] = subst(nargv[arg], "DNS1", + inet_ntoa(bundle->ncp.ipcp.ns.dns[1])); } nargv[arg] = NULL; } @@ -554,6 +558,29 @@ FgShellCommand(struct cmdargs const *arg) return ShellCommand(arg, 0); } +static int +ResolvCommand(struct cmdargs const *arg) +{ + if (arg->argc == arg->argn + 1) { + if (!strcasecmp(arg->argv[arg->argn], "reload")) + ipcp_LoadDNS(&arg->bundle->ncp.ipcp); + else if (!strcasecmp(arg->argv[arg->argn], "restore")) + ipcp_RestoreDNS(&arg->bundle->ncp.ipcp); + else if (!strcasecmp(arg->argv[arg->argn], "rewrite")) + ipcp_WriteDNS(&arg->bundle->ncp.ipcp); + else if (!strcasecmp(arg->argv[arg->argn], "readonly")) + arg->bundle->ncp.ipcp.ns.writable = 0; + else if (!strcasecmp(arg->argv[arg->argn], "writable")) + arg->bundle->ncp.ipcp.ns.writable = 1; + else + return -1; + + return 0; + } + + return -1; +} + #ifndef NONAT static struct cmdtab const AliasCommands[] = { @@ -673,6 +700,8 @@ static struct cmdtab const Commands[] = { "Remove a link", "remove"}, {"rename", "mv", RenameCommand, LOCAL_AUTH | LOCAL_CX, "Rename a link", "rename name"}, + {"resolv", NULL, ResolvCommand, LOCAL_AUTH, + "Manipulate resolv.conf", "resolv readonly|reload|restore|rewrite|writable"}, {"save", NULL, SaveCommand, LOCAL_AUTH, "Save settings", "save"}, {"set", "setup", SetCommand, LOCAL_AUTH | LOCAL_CX_OPT, @@ -1669,12 +1698,13 @@ SetVariable(struct cmdargs const *arg) case VAR_NBNS: case VAR_DNS: - if (param == VAR_DNS) + if (param == VAR_DNS) { addr = arg->bundle->ncp.ipcp.cfg.ns.dns; - else + addr[0].s_addr = addr[1].s_addr = INADDR_NONE; + } else { addr = arg->bundle->ncp.ipcp.cfg.ns.nbns; - - addr[0].s_addr = addr[1].s_addr = INADDR_ANY; + addr[0].s_addr = addr[1].s_addr = INADDR_ANY; + } if (arg->argc > arg->argn) { ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn], @@ -1683,10 +1713,14 @@ SetVariable(struct cmdargs const *arg) ParseAddr(&arg->bundle->ncp.ipcp, arg->argv[arg->argn + 1], addr + 1, &dummyaddr, &dummyint); - if (addr[1].s_addr == INADDR_ANY) - addr[1].s_addr = addr[0].s_addr; - if (addr[0].s_addr == INADDR_ANY) + if (addr[0].s_addr == INADDR_ANY) { + addr[0].s_addr = addr[1].s_addr; + addr[1].s_addr = INADDR_ANY; + } + if (addr[0].s_addr == INADDR_NONE) { addr[0].s_addr = addr[1].s_addr; + addr[1].s_addr = INADDR_NONE; + } } break; @@ -1969,7 +2003,7 @@ SetCommand(struct cmdargs const *arg) arg->prompt, arg->cx); else if (arg->prompt) prompt_Printf(arg->prompt, "Use `set ?' to get a list or `set ? <var>' for" - " syntax help.\n"); + " syntax help.\n"); else log_Printf(LogWARN, "set command must have arguments\n"); @@ -1999,6 +2033,10 @@ AddCommand(struct cmdargs const *arg) addrs = ROUTE_DSTMYADDR; else if (!strncasecmp(arg->argv[arg->argn], "HISADDR", 7)) addrs = ROUTE_DSTHISADDR; + else if (!strncasecmp(arg->argv[arg->argn], "DNS0", 4)) + addrs = ROUTE_DSTDNS0; + else if (!strncasecmp(arg->argv[arg->argn], "DNS1", 4)) + addrs = ROUTE_DSTDNS1; } gw = 1; } else { @@ -2008,6 +2046,12 @@ AddCommand(struct cmdargs const *arg) } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { addrs = ROUTE_DSTHISADDR; dest = arg->bundle->ncp.ipcp.peer_ip; + } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { + addrs = ROUTE_DSTDNS0; + dest = arg->bundle->ncp.ipcp.ns.dns[0]; + } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { + addrs = ROUTE_DSTDNS1; + dest = arg->bundle->ncp.ipcp.ns.dns[1]; } else dest = GetIpAddr(arg->argv[arg->argn]); netmask = GetIpAddr(arg->argv[arg->argn+1]); @@ -2046,6 +2090,12 @@ DeleteCommand(struct cmdargs const *arg) } else if (strcasecmp(arg->argv[arg->argn], "HISADDR") == 0) { dest = arg->bundle->ncp.ipcp.peer_ip; addrs = ROUTE_DSTHISADDR; + } else if (strcasecmp(arg->argv[arg->argn], "DNS0") == 0) { + dest = arg->bundle->ncp.ipcp.ns.dns[0]; + addrs = ROUTE_DSTDNS0; + } else if (strcasecmp(arg->argv[arg->argn], "DNS1") == 0) { + dest = arg->bundle->ncp.ipcp.ns.dns[1]; + addrs = ROUTE_DSTDNS1; } else { dest = GetIpAddr(arg->argv[arg->argn]); if (dest.s_addr == INADDR_NONE) { diff --git a/usr.sbin/ppp/filter.c b/usr.sbin/ppp/filter.c index ade48a5..6e6f5f9 100644 --- a/usr.sbin/ppp/filter.c +++ b/usr.sbin/ppp/filter.c @@ -102,6 +102,10 @@ ParseAddr(struct ipcp *ipcp, const char *data, *paddr = ipcp->peer_ip; else if (ipcp && strncasecmp(data, "MYADDR", len) == 0) *paddr = ipcp->my_ip; + else if (ipcp && strncasecmp(data, "DNS0", len) == 0) + *paddr = ipcp->ns.dns[0]; + else if (ipcp && strncasecmp(data, "DNS1", len) == 0) + *paddr = ipcp->ns.dns[1]; else if (len > 15) log_Printf(LogWARN, "ParseAddr: %s: Bad address\n", data); else { @@ -320,6 +324,10 @@ addrtype(const char *addr) return T_MYADDR; if (!strncasecmp(addr, "HISADDR", 7) && (addr[7] == '\0' || addr[7] == '/')) return T_HISADDR; + if (!strncasecmp(addr, "DNS0", 4) && (addr[4] == '\0' || addr[4] == '/')) + return T_DNS0; + if (!strncasecmp(addr, "DNS1", 4) && (addr[4] == '\0' || addr[4] == '/')) + return T_DNS1; return T_ADDR; } @@ -332,6 +340,10 @@ addrstr(struct in_addr addr, unsigned type) return "MYADDR"; case T_HISADDR: return "HISADDR"; + case T_DNS0: + return "DNS0"; + case T_DNS1: + return "DNS1"; } return inet_ntoa(addr); } @@ -670,7 +682,7 @@ filter_Nam2Op(const char *cp) void filter_AdjustAddr(struct filter *filter, struct in_addr *my_ip, - struct in_addr *peer_ip) + struct in_addr *peer_ip, struct in_addr dns[2]) { struct filterent *fp; int n; @@ -689,5 +701,15 @@ filter_AdjustAddr(struct filter *filter, struct in_addr *my_ip, if (fp->f_dsttype == T_HISADDR) fp->f_dst.ipaddr = *peer_ip; } + if (dns) { + if (fp->f_srctype == T_DNS0) + fp->f_src.ipaddr = dns[0]; + if (fp->f_dsttype == T_DNS0) + fp->f_dst.ipaddr = dns[0]; + if (fp->f_srctype == T_DNS1) + fp->f_src.ipaddr = dns[1]; + if (fp->f_dsttype == T_DNS1) + fp->f_dst.ipaddr = dns[1]; + } } } diff --git a/usr.sbin/ppp/filter.h b/usr.sbin/ppp/filter.h index 03922cd..ce6f2e2 100644 --- a/usr.sbin/ppp/filter.h +++ b/usr.sbin/ppp/filter.h @@ -43,6 +43,8 @@ #define T_ADDR 0 #define T_MYADDR 1 #define T_HISADDR 2 +#define T_DNS0 3 +#define T_DNS1 4 /* * There's a struct filterent for each possible filter rule. The @@ -107,4 +109,4 @@ extern const char *filter_Proto2Nam(int); extern const char *filter_Op2Nam(int); extern struct in_addr bits2mask(int); extern void filter_AdjustAddr(struct filter *, struct in_addr *, - struct in_addr *); + struct in_addr *, struct in_addr [2]); diff --git a/usr.sbin/ppp/ipcp.c b/usr.sbin/ppp/ipcp.c index 7ae6a3c..b54cf65 100644 --- a/usr.sbin/ppp/ipcp.c +++ b/usr.sbin/ppp/ipcp.c @@ -38,6 +38,7 @@ #include <resolv.h> #include <stdlib.h> #include <string.h> +#include <sys/stat.h> #include <termios.h> #include <unistd.h> @@ -246,116 +247,177 @@ ipcp_AddOutOctets(struct ipcp *ipcp, int n) throughput_addout(&ipcp->throughput, n); } -static void -getdns(struct ipcp *ipcp, struct in_addr addr[2]) +void +ipcp_LoadDNS(struct ipcp *ipcp) { - FILE *fp; + int fd; + + ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr = INADDR_NONE; - addr[0].s_addr = addr[1].s_addr = INADDR_ANY; - if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { - char buf[LINE_LEN], *cp, *end; - int n; - - n = 0; - buf[sizeof buf - 1] = '\0'; - while (fgets(buf, sizeof buf - 1, fp)) { - if (!strncmp(buf, "nameserver", 10) && issep(buf[10])) { - for (cp = buf + 11; issep(*cp); cp++) - ; - for (end = cp; isip(*end); end++) - ; - *end = '\0'; - if (inet_aton(cp, addr+n) && ++n == 2) - break; + if (ipcp->ns.resolv != NULL) { + free(ipcp->ns.resolv); + ipcp->ns.resolv = NULL; + } + if (ipcp->ns.resolv_nons != NULL) { + free(ipcp->ns.resolv_nons); + ipcp->ns.resolv_nons = NULL; + } + ipcp->ns.resolver = 0; + + if ((fd = open(_PATH_RESCONF, O_RDONLY)) != -1) { + struct stat st; + + if (fstat(fd, &st) == 0) { + ssize_t got; + + if ((ipcp->ns.resolv_nons = (char *)malloc(st.st_size + 1)) == NULL) + log_Printf(LogERROR, "Failed to malloc %lu for %s: %s\n", + (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); + else if ((ipcp->ns.resolv = (char *)malloc(st.st_size + 1)) == NULL) { + log_Printf(LogERROR, "Failed(2) to malloc %lu for %s: %s\n", + (unsigned long)st.st_size, _PATH_RESCONF, strerror(errno)); + free(ipcp->ns.resolv_nons); + ipcp->ns.resolv_nons = NULL; + } else if ((got = read(fd, ipcp->ns.resolv, st.st_size)) != st.st_size) { + if (got == -1) + log_Printf(LogERROR, "Failed to read %s: %s\n", + _PATH_RESCONF, strerror(errno)); + else + log_Printf(LogERROR, "Failed to read %s, got %lu not %lu\n", + _PATH_RESCONF, (unsigned long)got, + (unsigned long)st.st_size); + free(ipcp->ns.resolv_nons); + ipcp->ns.resolv_nons = NULL; + free(ipcp->ns.resolv); + ipcp->ns.resolv = NULL; + } else { + char *cp, *cp_nons, *ncp, ch; + int n; + + ipcp->ns.resolv[st.st_size] = '\0'; + ipcp->ns.resolver = 1; + + cp_nons = ipcp->ns.resolv_nons; + cp = ipcp->ns.resolv; + n = 0; + + while ((ncp = strstr(cp, "nameserver")) != NULL) { + if (ncp != cp) { + memcpy(cp_nons, cp, ncp - cp); + cp_nons += ncp - cp; + } + if ((ncp != cp && ncp[-1] != '\n') || !issep(ncp[10])) { + memcpy(cp_nons, ncp, 9); + cp_nons += 9; + cp = ncp + 9; /* Can't match "nameserver" at cp... */ + continue; + } + + for (cp = ncp + 11; issep(*cp); cp++) /* Skip whitespace */ + ; + + for (ncp = cp; isip(*ncp); ncp++) /* Jump over IP */ + ; + + ch = *ncp; + *ncp = '\0'; + if (n < 2 && inet_aton(cp, ipcp->ns.dns + n)) + n++; + *ncp = ch; + + if ((cp = strchr(ncp, '\n')) == NULL) /* Point at next line */ + cp = ncp + strlen(ncp); + else + cp++; + } + strcpy(cp_nons, cp); /* Copy the end - including the NUL */ + cp_nons += strlen(cp_nons) - 1; + while (cp_nons >= ipcp->ns.resolv_nons && *cp_nons == '\n') + *cp_nons-- = '\0'; + if (n == 2 && ipcp->ns.dns[0].s_addr == INADDR_ANY) { + ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; + ipcp->ns.dns[1].s_addr = INADDR_ANY; + } + bundle_AdjustDNS(ipcp->fsm.bundle, ipcp->ns.dns); } - } - if (n == 1) - addr[1] = addr[0]; - fclose(fp); + } else + log_Printf(LogERROR, "Failed to stat opened %s: %s\n", + _PATH_RESCONF, strerror(errno)); + + close(fd); } } -static int -setdns(struct ipcp *ipcp, struct in_addr addr[2]) +int +ipcp_WriteDNS(struct ipcp *ipcp) { + const char *paddr; + mode_t mask; FILE *fp; - char wbuf[LINE_LEN + 54]; - int wlen; - - if (addr[0].s_addr == INADDR_ANY || addr[1].s_addr == INADDR_ANY) { - struct in_addr old[2]; - - getdns(ipcp, old); - if (addr[0].s_addr == INADDR_ANY) - addr[0] = old[0]; - if (addr[1].s_addr == INADDR_ANY) - addr[1] = old[1]; - } - if (addr[0].s_addr == INADDR_ANY && addr[1].s_addr == INADDR_ANY) { - log_Printf(LogWARN, "%s not modified: All nameservers NAKd\n", + if (ipcp->ns.dns[0].s_addr == INADDR_ANY && + ipcp->ns.dns[1].s_addr == INADDR_ANY) { + log_Printf(LogIPCP, "%s not modified: All nameservers NAKd\n", _PATH_RESCONF); return 0; } - wlen = 0; - if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) { - char buf[LINE_LEN]; - int len; - - buf[sizeof buf - 1] = '\0'; - while (fgets(buf, sizeof buf - 1, fp)) { - if (strncmp(buf, "nameserver", 10) || !issep(buf[10])) { - len = strlen(buf); - if (len > sizeof wbuf - wlen) { - log_Printf(LogWARN, "%s: Can only cope with max file size %d\n", - _PATH_RESCONF, LINE_LEN); - fclose(fp); - return 0; - } - memcpy(wbuf + wlen, buf, len); - wlen += len; - } - } - fclose(fp); + if (ipcp->ns.dns[0].s_addr == INADDR_ANY) { + ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr; + ipcp->ns.dns[1].s_addr = INADDR_ANY; } - if (addr[0].s_addr != INADDR_ANY) { - snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", - inet_ntoa(addr[0])); - log_Printf(LogIPCP, "Primary nameserver set to %s", wbuf + wlen + 11); - wlen += strlen(wbuf + wlen); - } + mask = umask(0644); + if ((fp = ID0fopen(_PATH_RESCONF, "w")) != NULL) { + umask(mask); + fputs(ipcp->ns.resolv_nons, fp); + paddr = inet_ntoa(ipcp->ns.dns[0]); + log_Printf(LogIPCP, "Primary nameserver set to %s\n", paddr); + fprintf(fp, "\nnameserver %s\n", paddr); + if (ipcp->ns.dns[1].s_addr != INADDR_ANY && + ipcp->ns.dns[1].s_addr != INADDR_NONE && + ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) { + paddr = inet_ntoa(ipcp->ns.dns[1]); + log_Printf(LogIPCP, "Secondary nameserver set to %s\n", paddr); + fprintf(fp, "nameserver %s\n", paddr); + } + if (fclose(fp) == EOF) { + log_Printf(LogERROR, "write(): Failed updating %s: %s\n", _PATH_RESCONF, + strerror(errno)); + return 0; + } + } else + umask(mask); - if (addr[1].s_addr != INADDR_ANY && addr[1].s_addr != addr[0].s_addr) { - snprintf(wbuf + wlen, sizeof wbuf - wlen, "nameserver %s\n", - inet_ntoa(addr[1])); - log_Printf(LogIPCP, "Secondary nameserver set to %s", wbuf + wlen + 11); - wlen += strlen(wbuf + wlen); - } + return 1; +} - if (wlen) { +void +ipcp_RestoreDNS(struct ipcp *ipcp) +{ + if (ipcp->ns.resolver) { + ssize_t got; + size_t len; int fd; - if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_CREAT, 0644)) != -1) { - if (write(fd, wbuf, wlen) != wlen) { - log_Printf(LogERROR, "setdns: write(): %s\n", strerror(errno)); - close(fd); - return 0; - } - if (ftruncate(fd, wlen) == -1) { - log_Printf(LogERROR, "setdns: truncate(): %s\n", strerror(errno)); - close(fd); - return 0; + if ((fd = ID0open(_PATH_RESCONF, O_WRONLY|O_TRUNC, 0644)) != -1) { + len = strlen(ipcp->ns.resolv); + if ((got = write(fd, ipcp->ns.resolv, len)) != len) { + if (got == -1) + log_Printf(LogERROR, "Failed rewriting %s: write: %s\n", + _PATH_RESCONF, strerror(errno)); + else + log_Printf(LogERROR, "Failed rewriting %s: wrote %lu of %lu\n", + _PATH_RESCONF, (unsigned long)got, (unsigned long)len); } close(fd); - } else { - log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno)); - return 0; - } - } - - return 1; + } else + log_Printf(LogERROR, "Failed rewriting %s: open: %s\n", _PATH_RESCONF, + strerror(errno)); + } else if (remove(_PATH_RESCONF) == -1) + log_Printf(LogERROR, "Failed removing %s: %s\n", _PATH_RESCONF, + strerror(errno)); + } int @@ -404,11 +466,20 @@ ipcp_Show(struct cmdargs const *arg) inet_ntoa(ipcp->cfg.peer_range.ipaddr), ipcp->cfg.peer_range.width); - prompt_Printf(arg->prompt, " DNS: %s, ", - inet_ntoa(ipcp->cfg.ns.dns[0])); - prompt_Printf(arg->prompt, "%s, %s\n", inet_ntoa(ipcp->cfg.ns.dns[1]), + prompt_Printf(arg->prompt, " DNS: %s", + ipcp->cfg.ns.dns[0].s_addr == INADDR_NONE ? + "none" : inet_ntoa(ipcp->cfg.ns.dns[0])); + if (ipcp->cfg.ns.dns[1].s_addr != INADDR_NONE) + prompt_Printf(arg->prompt, ", %s", inet_ntoa(ipcp->cfg.ns.dns[1])); + prompt_Printf(arg->prompt, ", %s\n", command_ShowNegval(ipcp->cfg.ns.dns_neg)); - prompt_Printf(arg->prompt, " NetBIOS NS: %s, ", + prompt_Printf(arg->prompt, " Resolver DNS: %s", + ipcp->ns.dns[0].s_addr == INADDR_NONE ? + "none" : inet_ntoa(ipcp->ns.dns[0])); + if (ipcp->ns.dns[1].s_addr != INADDR_NONE && + ipcp->ns.dns[1].s_addr != ipcp->ns.dns[0].s_addr) + prompt_Printf(arg->prompt, ", %s", inet_ntoa(ipcp->ns.dns[1])); + prompt_Printf(arg->prompt, "\n NetBIOS NS: %s, ", inet_ntoa(ipcp->cfg.ns.nbns[0])); prompt_Printf(arg->prompt, "%s\n", inet_ntoa(ipcp->cfg.ns.nbns[1])); @@ -489,8 +560,8 @@ ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, iplist_setsrc(&ipcp->cfg.peer_list, ""); ipcp->cfg.HaveTriggerAddress = 0; - ipcp->cfg.ns.dns[0].s_addr = INADDR_ANY; - ipcp->cfg.ns.dns[1].s_addr = INADDR_ANY; + ipcp->cfg.ns.dns[0].s_addr = INADDR_NONE; + ipcp->cfg.ns.dns[1].s_addr = INADDR_NONE; ipcp->cfg.ns.dns_neg = 0; ipcp->cfg.ns.nbns[0].s_addr = INADDR_ANY; ipcp->cfg.ns.nbns[1].s_addr = INADDR_ANY; @@ -512,6 +583,11 @@ ipcp_Init(struct ipcp *ipcp, struct bundle *bundle, struct link *l, memset(&ipcp->vj, '\0', sizeof ipcp->vj); + ipcp->ns.resolv = NULL; + ipcp->ns.resolv_nons = NULL; + ipcp->ns.writable = 1; + ipcp_LoadDNS(ipcp); + throughput_init(&ipcp->throughput, SAMPLE_PERIOD); memset(ipcp->Queue, '\0', sizeof ipcp->Queue); ipcp_Setup(ipcp, INADDR_NONE); @@ -530,6 +606,14 @@ ipcp_Destroy(struct ipcp *ipcp) free(ipcp->cfg.urgent.udp.port); ipcp->cfg.urgent.udp.port = NULL; } + if (ipcp->ns.resolv != NULL) { + free(ipcp->ns.resolv); + ipcp->ns.resolv = NULL; + } + if (ipcp->ns.resolv_nons != NULL) { + free(ipcp->ns.resolv_nons); + ipcp->ns.resolv_nons = NULL; + } } void @@ -611,6 +695,17 @@ ipcp_Setup(struct ipcp *ipcp, u_int32_t mask) ipcp->peer_reject = 0; ipcp->my_reject = 0; + + /* Copy startup values into ipcp->dns? */ + if (ipcp->cfg.ns.dns[0].s_addr != INADDR_NONE) + memcpy(ipcp->dns, ipcp->cfg.ns.dns, sizeof ipcp->dns); + else if (ipcp->ns.dns[0].s_addr != INADDR_NONE) + memcpy(ipcp->dns, ipcp->ns.dns, sizeof ipcp->dns); + else + ipcp->dns[0].s_addr = ipcp->dns[1].s_addr = INADDR_ANY; + + if (ipcp->dns[1].s_addr == INADDR_NONE) + ipcp->dns[1] = ipcp->dns[0]; } static int @@ -669,11 +764,13 @@ ipcp_SetIPaddress(struct bundle *bundle, struct in_addr myaddr, bundle_SetRoute(bundle, RTM_CHANGE, hisaddr, myaddr, none, 0, 0); if (Enabled(bundle, OPT_SROUTES)) - route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr); + route_Change(bundle, bundle->ncp.ipcp.route, myaddr, hisaddr, + bundle->ncp.ipcp.ns.dns); #ifndef NORADIUS if (bundle->radius.valid) - route_Change(bundle, bundle->radius.routes, myaddr, hisaddr); + route_Change(bundle, bundle->radius.routes, myaddr, hisaddr, + bundle->ncp.ipcp.ns.dns); #endif if (Enabled(bundle, OPT_PROXY) || Enabled(bundle, OPT_PROXYALL)) { @@ -773,11 +870,9 @@ IpcpSendConfigReq(struct fsm *fp) if (IsEnabled(ipcp->cfg.ns.dns_neg) && !REJECTED(ipcp, TY_PRIMARY_DNS - TY_ADJUST_NS) && !REJECTED(ipcp, TY_SECONDARY_DNS - TY_ADJUST_NS)) { - struct in_addr dns[2]; - getdns(ipcp, dns); - memcpy(o->data, &dns[0].s_addr, 4); + memcpy(o->data, &ipcp->dns[0].s_addr, 4); INC_LCP_OPT(TY_PRIMARY_DNS, 6, o); - memcpy(o->data, &dns[1].s_addr, 4); + memcpy(o->data, &ipcp->dns[1].s_addr, 4); INC_LCP_OPT(TY_SECONDARY_DNS, 6, o); } @@ -947,15 +1042,13 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, /* Deal with incoming PROTO_IPCP */ struct iface *iface = fp->bundle->iface; struct ipcp *ipcp = fsm2ipcp(fp); - int type, length, gotdns, gotdnsnak, n; + int type, length, gotdnsnak, n; u_int32_t compproto; struct compreq *pcomp; - struct in_addr ipaddr, dstipaddr, have_ip, dns[2], dnsnak[2]; + struct in_addr ipaddr, dstipaddr, have_ip; char tbuff[100], tbuff2[100]; - gotdns = 0; gotdnsnak = 0; - dnsnak[0].s_addr = dnsnak[1].s_addr = INADDR_ANY; while (plen >= sizeof(struct fsmconfig)) { type = *cp; @@ -1174,14 +1267,15 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, dec->rejend += length; break; } - if (!gotdns) { - dns[0] = ipcp->cfg.ns.dns[0]; - dns[1] = ipcp->cfg.ns.dns[1]; - if (dns[0].s_addr == INADDR_ANY && dns[1].s_addr == INADDR_ANY) - getdns(ipcp, dns); - gotdns = 1; + have_ip = ipcp->dns[type == TY_PRIMARY_DNS ? 0 : 1]; + + if (type == TY_PRIMARY_DNS && ipaddr.s_addr != have_ip.s_addr && + ipaddr.s_addr == ipcp->dns[1].s_addr) { + /* Swap 'em 'round */ + ipcp->dns[0] = ipcp->dns[1]; + ipcp->dns[1] = have_ip; + have_ip = ipcp->dns[0]; } - have_ip = dns[type == TY_PRIMARY_DNS ? 0 : 1]; if (ipaddr.s_addr != have_ip.s_addr) { /* @@ -1201,10 +1295,10 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, } break; - case MODE_NAK: /* what does this mean?? */ + case MODE_NAK: if (IsEnabled(ipcp->cfg.ns.dns_neg)) { gotdnsnak = 1; - memcpy(&dnsnak[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4); + memcpy(&ipcp->dns[type == TY_PRIMARY_DNS ? 0 : 1].s_addr, cp + 2, 4); } break; @@ -1264,11 +1358,20 @@ IpcpDecodeConfig(struct fsm *fp, u_char *cp, int plen, int mode_type, cp += length; } - if (gotdnsnak) - if (!setdns(ipcp, dnsnak)) { - ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); - ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); + if (gotdnsnak) { + memcpy(ipcp->ns.dns, ipcp->dns, sizeof ipcp->ns.dns); + if (ipcp->ns.writable) { + log_Printf(LogDEBUG, "Updating resolver\n"); + if (!ipcp_WriteDNS(ipcp)) { + ipcp->peer_reject |= (1 << (TY_PRIMARY_DNS - TY_ADJUST_NS)); + ipcp->peer_reject |= (1 << (TY_SECONDARY_DNS - TY_ADJUST_NS)); + } else + bundle_AdjustDNS(fp->bundle, ipcp->dns); + } else { + log_Printf(LogDEBUG, "Not updating resolver (readonly)\n"); + bundle_AdjustDNS(fp->bundle, ipcp->dns); } + } if (mode_type != MODE_NOP) { if (dec->rejend != dec->rej) { diff --git a/usr.sbin/ppp/ipcp.h b/usr.sbin/ppp/ipcp.h index 6f87eb7..38583d8 100644 --- a/usr.sbin/ppp/ipcp.h +++ b/usr.sbin/ppp/ipcp.h @@ -87,6 +87,14 @@ struct ipcp { struct slstat slstat; /* VJ statistics */ } vj; + struct { + unsigned resolver : 1; /* Found resolv.conf ? */ + unsigned writable : 1; /* Can write resolv.conf ? */ + struct in_addr dns[2]; /* Current DNS addresses */ + char *resolv; /* Contents of resolv.conf */ + char *resolv_nons; /* Contents of resolv.conf without ns */ + } ns; + struct sticky_route *route; /* List of dynamic routes */ unsigned heis1172 : 1; /* True if he is speaking rfc1172 */ @@ -99,6 +107,8 @@ struct ipcp { struct in_addr my_ip; /* IP address I'm willing to use */ u_int32_t my_compproto; /* VJ params I'm willing to use */ + struct in_addr dns[2]; /* DNSs to REQ/ACK */ + u_int32_t peer_reject; /* Request codes rejected by peer */ u_int32_t my_reject; /* Request codes I have rejected */ @@ -133,6 +143,9 @@ extern void ipcp_AddUrgentPort(struct port_range *, u_short); extern void ipcp_RemoveUrgentPort(struct port_range *, u_short); extern void ipcp_ClearUrgentPorts(struct port_range *); extern struct in_addr addr2mask(struct in_addr); +extern int ipcp_WriteDNS(struct ipcp *); +extern void ipcp_RestoreDNS(struct ipcp *); +extern void ipcp_LoadDNS(struct ipcp *); #define ipcp_IsUrgentTcpPort(ipcp, p1, p2) \ ipcp_IsUrgentPort(&(ipcp)->cfg.urgent.tcp, p1, p2) diff --git a/usr.sbin/ppp/ppp.8 b/usr.sbin/ppp/ppp.8 index 7180d50..2a917c4 100644 --- a/usr.sbin/ppp/ppp.8 +++ b/usr.sbin/ppp/ppp.8 @@ -462,7 +462,9 @@ update .Pa /etc/resolv.conf automatically. Refer to the .Dq enable dns -command below for details. +and +.Dq resolv +commands below for details. .El .Sh MANUAL DIALING In the following examples, we assume that your machine name is @@ -1978,9 +1980,16 @@ Ask your ISP to authenticate your nameserver address(es) with the line .Bd -literal -offset indent enable dns .Ed +.Pp Do .Em NOT -do this if you are running an local DNS, as +do this if you are running a local DNS unless you also either use +.Dq resolv readonly , +or have +.Dq resolv restore +in +.Pa /etc/ppp/ppp.linkdown +as .Nm will simply circumvent its use by entering some nameserver lines in .Pa /etc/resolv.conf . @@ -2775,17 +2784,21 @@ command (see for further details). .Pp Routes that contain the -.Dq HISADDR +.Dq HISADDR , +.Dq MYADDR , +.Dq DNS0 , or -.Dq MYADDR +.Dq DNS1 constants are considered .Sq sticky . They are stored in a list (use .Dq show ipcp to see the list), and each time the value of -.Dv HISADDR +.Dv HISADDR , +.Dv MYADDR , +.Dv DNS0 , or -.Dv MYADDR +.Dv DNS1 changes, the appropriate routing table entries are updated. This facility may be disabled using .Dq disable sroutes . @@ -3035,6 +3048,9 @@ This is replaced with the current process id. This is replaced with the username that has been authenticated with PAP or CHAP. Normally, this variable is assigned only in -direct mode. This value is available irrespective of whether utmp logging is enabled. +.It Li DNS0 No " & " Li DNS1 +These are replaced with the primary and secondary nameserver IP numbers. If +nameservers are negotiated by IPCP, the values of these macros will change. .El .Pp These substitutions are also done by the @@ -3356,6 +3372,69 @@ Renaming it to or .Sq USR may make the log file more readable. +.It resolv Ar command +This command controls +.Nm ppp Ns No s +manipulation of the +.Xr resolv.conf 5 +file. When +.Nm +starts up, it loads the contents of this file into memory and retains this +image for future use. +.Ar command +is one of the following: +.Bl -tag -width readonly +.It Em readonly +Treat +.Pa /etc/resolv.conf +as read only. If +.Dq dns +is enabled, +.Nm +will still attempt to negotiate nameservers with the peer, making the results +available via the +.Dv DNS0 +and +.Dv DNS1 +macros. This is the opposite of the +.Dq resolv writable +command. +.It Em reload +Reload +.Pa /etc/resolv.conf +into memory. This may be necessary if for example a DHCP client overwrote +.Pa /etc/resolv.conf . +.It Em restore +Replace +.Pa /etc/resolv.conf +with the version originally read at startup or with the last +.Dq resolv reload +command. This is sometimes a useful command to put in the +.Pa /etc/ppp/ppp.linkdown +file. +.It Em rewrite +Rewrite the +.Pa /etc/resolv.conf +file. This command will work even if the +.Dq resolv readonly +command has been used. It may be useful as a command in the +.Pa /etc/ppp/ppp.linkup +file if you wish to defer updating +.Pa /etc/resolv.conf +until after other commands have finished. +.It Em writable +Allow +.Nm +to update +.Pa /etc/resolv.conf +if +.Dq dns +is enabled and +.Nm +successfully negotiates a DNS. This is the opposite of the +.Dq resolv readonly +command. +.El .It save This option is not (yet) implemented. .It set Ns Xo diff --git a/usr.sbin/ppp/ppp.8.m4 b/usr.sbin/ppp/ppp.8.m4 index 7180d50..2a917c4 100644 --- a/usr.sbin/ppp/ppp.8.m4 +++ b/usr.sbin/ppp/ppp.8.m4 @@ -462,7 +462,9 @@ update .Pa /etc/resolv.conf automatically. Refer to the .Dq enable dns -command below for details. +and +.Dq resolv +commands below for details. .El .Sh MANUAL DIALING In the following examples, we assume that your machine name is @@ -1978,9 +1980,16 @@ Ask your ISP to authenticate your nameserver address(es) with the line .Bd -literal -offset indent enable dns .Ed +.Pp Do .Em NOT -do this if you are running an local DNS, as +do this if you are running a local DNS unless you also either use +.Dq resolv readonly , +or have +.Dq resolv restore +in +.Pa /etc/ppp/ppp.linkdown +as .Nm will simply circumvent its use by entering some nameserver lines in .Pa /etc/resolv.conf . @@ -2775,17 +2784,21 @@ command (see for further details). .Pp Routes that contain the -.Dq HISADDR +.Dq HISADDR , +.Dq MYADDR , +.Dq DNS0 , or -.Dq MYADDR +.Dq DNS1 constants are considered .Sq sticky . They are stored in a list (use .Dq show ipcp to see the list), and each time the value of -.Dv HISADDR +.Dv HISADDR , +.Dv MYADDR , +.Dv DNS0 , or -.Dv MYADDR +.Dv DNS1 changes, the appropriate routing table entries are updated. This facility may be disabled using .Dq disable sroutes . @@ -3035,6 +3048,9 @@ This is replaced with the current process id. This is replaced with the username that has been authenticated with PAP or CHAP. Normally, this variable is assigned only in -direct mode. This value is available irrespective of whether utmp logging is enabled. +.It Li DNS0 No " & " Li DNS1 +These are replaced with the primary and secondary nameserver IP numbers. If +nameservers are negotiated by IPCP, the values of these macros will change. .El .Pp These substitutions are also done by the @@ -3356,6 +3372,69 @@ Renaming it to or .Sq USR may make the log file more readable. +.It resolv Ar command +This command controls +.Nm ppp Ns No s +manipulation of the +.Xr resolv.conf 5 +file. When +.Nm +starts up, it loads the contents of this file into memory and retains this +image for future use. +.Ar command +is one of the following: +.Bl -tag -width readonly +.It Em readonly +Treat +.Pa /etc/resolv.conf +as read only. If +.Dq dns +is enabled, +.Nm +will still attempt to negotiate nameservers with the peer, making the results +available via the +.Dv DNS0 +and +.Dv DNS1 +macros. This is the opposite of the +.Dq resolv writable +command. +.It Em reload +Reload +.Pa /etc/resolv.conf +into memory. This may be necessary if for example a DHCP client overwrote +.Pa /etc/resolv.conf . +.It Em restore +Replace +.Pa /etc/resolv.conf +with the version originally read at startup or with the last +.Dq resolv reload +command. This is sometimes a useful command to put in the +.Pa /etc/ppp/ppp.linkdown +file. +.It Em rewrite +Rewrite the +.Pa /etc/resolv.conf +file. This command will work even if the +.Dq resolv readonly +command has been used. It may be useful as a command in the +.Pa /etc/ppp/ppp.linkup +file if you wish to defer updating +.Pa /etc/resolv.conf +until after other commands have finished. +.It Em writable +Allow +.Nm +to update +.Pa /etc/resolv.conf +if +.Dq dns +is enabled and +.Nm +successfully negotiates a DNS. This is the opposite of the +.Dq resolv readonly +command. +.El .It save This option is not (yet) implemented. .It set Ns Xo diff --git a/usr.sbin/ppp/route.c b/usr.sbin/ppp/route.c index 255d0f2..e147101 100644 --- a/usr.sbin/ppp/route.c +++ b/usr.sbin/ppp/route.c @@ -533,7 +533,7 @@ GetIfIndex(char *name) void route_Change(struct bundle *bundle, struct sticky_route *r, - struct in_addr me, struct in_addr peer) + struct in_addr me, struct in_addr peer, struct in_addr dns[2]) { struct in_addr none, del; @@ -551,6 +551,18 @@ route_Change(struct bundle *bundle, struct sticky_route *r, r->dst = peer; if (r->type & ROUTE_GWHISADDR) r->gw = peer; + } else if ((r->type & ROUTE_DSTDNS0) && r->dst.s_addr != peer.s_addr) { + del.s_addr = r->dst.s_addr & r->mask.s_addr; + bundle_SetRoute(bundle, RTM_DELETE, del, none, none, 1, 0); + r->dst = dns[0]; + if (r->type & ROUTE_GWHISADDR) + r->gw = peer; + } else if ((r->type & ROUTE_DSTDNS1) && r->dst.s_addr != peer.s_addr) { + del.s_addr = r->dst.s_addr & r->mask.s_addr; + bundle_SetRoute(bundle, RTM_DELETE, del, none, none, 1, 0); + r->dst = dns[1]; + if (r->type & ROUTE_GWHISADDR) + r->gw = peer; } else if ((r->type & ROUTE_GWHISADDR) && r->gw.s_addr != peer.s_addr) r->gw = peer; bundle_SetRoute(bundle, RTM_ADD, r->dst, r->gw, r->mask, 1, 0); @@ -648,6 +660,10 @@ route_ShowSticky(struct prompt *p, struct sticky_route *r, const char *tag, prompt_Printf(p, "MYADDR"); else if (r->type & ROUTE_DSTHISADDR) prompt_Printf(p, "HISADDR"); + else if (r->type & ROUTE_DSTDNS0) + prompt_Printf(p, "DNS0"); + else if (r->type & ROUTE_DSTDNS1) + prompt_Printf(p, "DNS1"); else if (!def) prompt_Printf(p, "%s", inet_ntoa(r->dst)); diff --git a/usr.sbin/ppp/route.h b/usr.sbin/ppp/route.h index cf339cc..dc95871 100644 --- a/usr.sbin/ppp/route.h +++ b/usr.sbin/ppp/route.h @@ -26,11 +26,13 @@ struct cmdargs; struct rt_msghdr; struct sockaddr; -#define ROUTE_STATIC 0 -#define ROUTE_DSTMYADDR 1 -#define ROUTE_DSTHISADDR 2 -#define ROUTE_DSTANY 3 -#define ROUTE_GWHISADDR 4 /* May be ORd with DST_MYADDR */ +#define ROUTE_STATIC 0x00 +#define ROUTE_DSTMYADDR 0x01 +#define ROUTE_DSTHISADDR 0x02 +#define ROUTE_DSTDNS0 0x04 +#define ROUTE_DSTDNS1 0x08 +#define ROUTE_DSTANY 0x0f +#define ROUTE_GWHISADDR 0x10 /* May be ORd with DST_* */ struct sticky_route { int type; /* ROUTE_* value (not _STATIC) */ @@ -46,7 +48,7 @@ extern int route_Show(struct cmdargs const *); extern void route_IfDelete(struct bundle *, int); extern const char *Index2Nam(int); extern void route_Change(struct bundle *, struct sticky_route *, - struct in_addr, struct in_addr); + struct in_addr, struct in_addr, struct in_addr[2]); extern void route_Add(struct sticky_route **, int, struct in_addr, struct in_addr, struct in_addr); extern void route_Delete(struct sticky_route **, int, struct in_addr); |