summaryrefslogtreecommitdiff
path: root/usr.sbin/ppp/ipcp.c
diff options
context:
space:
mode:
authorBrian Somers <brian@FreeBSD.org>2000-03-14 01:47:27 +0000
committerBrian Somers <brian@FreeBSD.org>2000-03-14 01:47:27 +0000
commitd568d6c405600fff668454f930567249c69279d0 (patch)
tree2cb3fb754b16378953f5e87d80dc1a5d2dd864ae /usr.sbin/ppp/ipcp.c
parent574a3ffd7897c37eb49ac1f81434500de3ac2775 (diff)
downloadsrc-test2-d568d6c405600fff668454f930567249c69279d0.tar.gz
src-test2-d568d6c405600fff668454f930567249c69279d0.zip
Notes
Diffstat (limited to 'usr.sbin/ppp/ipcp.c')
-rw-r--r--usr.sbin/ppp/ipcp.c339
1 files changed, 221 insertions, 118 deletions
diff --git a/usr.sbin/ppp/ipcp.c b/usr.sbin/ppp/ipcp.c
index 7ae6a3c85306..b54cf65a7059 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) {