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.
This commit is contained in:
Brian Somers 2000-03-14 01:47:27 +00:00
parent 574a3ffd78
commit d568d6c405
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=58044
11 changed files with 528 additions and 152 deletions

View File

@ -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

View File

@ -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 *);

View File

@ -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) {

View File

@ -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];
}
}
}

View File

@ -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]);

View File

@ -38,6 +38,7 @@
#include <resolv.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <termios.h>
#include <unistd.h>
@ -246,118 +247,179 @@ 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;
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;
ipcp->ns.dns[0].s_addr = ipcp->ns.dns[1].s_addr = INADDR_NONE;
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;
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;
}
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;
}
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);
}
fclose(fp);
}
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);
}
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);
}
if (wlen) {
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;
}
close(fd);
} else {
log_Printf(LogERROR, "setdns: open(): %s\n", strerror(errno));
if (fclose(fp) == EOF) {
log_Printf(LogERROR, "write(): Failed updating %s: %s\n", _PATH_RESCONF,
strerror(errno));
return 0;
}
}
} else
umask(mask);
return 1;
}
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_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, "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
ipcp_Show(struct cmdargs const *arg)
{
@ -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) {

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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);