is ignored.
o It is now only necessary to escape the `-' character in chat scripts twice.
See the example files for details.
+o Environment variables and ~ are expanded on in commands
See HISTORY file for additional revisions.
- $OpenBSD: alias_db.c,v 1.6 2000/02/27 01:38:24 brian Exp $
+ $OpenBSD: alias_db.c,v 1.7 2000/03/19 10:33:32 brian Exp $
*/
}
-struct alias_link *
+static struct alias_link *
_FindLinkIn(struct in_addr dst_addr,
struct in_addr alias_addr,
u_short dst_port,
return(link->alias_port);
}
-u_short
+#ifndef NO_FW_PUNCH
+static u_short
GetDestPort(struct alias_link *link)
{
return(link->dst_port);
}
+#endif
void
SetAckModified(struct alias_link *link)
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $OpenBSD: bundle.c,v 1.31 2000/03/03 21:52:56 brian Exp $
+ * $OpenBSD: bundle.c,v 1.32 2000/03/19 10:33:32 brian Exp $
*/
#include <sys/param.h>
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
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $OpenBSD: bundle.h,v 1.12 2000/02/27 01:38:24 brian Exp $
+ * $OpenBSD: bundle.h,v 1.13 2000/03/19 10:33:32 brian Exp $
*/
#define PHASE_DEAD 0 /* Link is dead */
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 *);
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: command.c,v 1.38 2000/02/27 01:38:25 brian Exp $
+ * $OpenBSD: command.c,v 1.39 2000/03/19 10:33:32 brian Exp $
*
*/
#include <sys/param.h>
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;
}
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[] =
{
"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,
return val;
}
+int
+command_Expand_Interpret(char *buff, int nb, char *argv[MAXARGS], int offset)
+{
+ char buff2[LINE_LEN-offset];
+
+ InterpretArg(buff, buff2);
+ strncpy(buff, buff2, LINE_LEN - offset - 1);
+ buff[LINE_LEN - offset - 1] = '\0';
+
+ return command_Interpret(buff, nb, argv);
+}
+
int
command_Interpret(char *buff, int nb, char *argv[MAXARGS])
{
int argc;
char *argv[MAXARGS];
- if ((argc = command_Interpret(buff, nb, argv)) < 0)
+ if ((argc = command_Expand_Interpret(buff, nb, argv, 0)) < 0)
return 0;
command_Run(bundle, argc, (char const *const *)argv, prompt, label, NULL);
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],
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;
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");
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 {
} 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]);
} 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) {
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: command.h,v 1.6 2000/02/27 01:38:25 brian Exp $
+ * $OpenBSD: command.h,v 1.7 2000/03/19 10:33:32 brian Exp $
*
* TODO:
*/
extern void command_Expand(char **, int, char const *const *, struct bundle *,
int, pid_t);
+extern int command_Expand_Interpret(char *, int, char *vector[MAXARGS], int);
extern int command_Interpret(char *, int, char *vector[MAXARGS]);
extern void command_Run(struct bundle *, int, char const *const *,
struct prompt *, const char *, struct datalink *);
const char *);
extern struct link *command_ChooseLink(struct cmdargs const *);
extern const char *command_ShowNegval(unsigned);
+
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: filter.c,v 1.12 2000/02/27 01:38:26 brian Exp $
+ * $OpenBSD: filter.c,v 1.13 2000/03/19 10:33:33 brian Exp $
*
* TODO: Should send ICMP error message when we discard packets.
*/
*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 {
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;
}
return "MYADDR";
case T_HISADDR:
return "HISADDR";
+ case T_DNS0:
+ return "DNS0";
+ case T_DNS1:
+ return "DNS1";
}
return inet_ntoa(addr);
}
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;
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];
+ }
}
}
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: filter.h,v 1.9 2000/02/27 01:38:26 brian Exp $
+ * $OpenBSD: filter.h,v 1.10 2000/03/19 10:33:33 brian Exp $
*
* TODO:
*/
#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
unsigned f_proto : 8; /* Protocol: P_... */
unsigned f_srcop : 2; /* Source port operation: OP_... */
unsigned f_dstop : 2; /* Destination port operation: OP_... */
- unsigned f_srctype : 2; /* T_ value of src */
- unsigned f_dsttype : 2; /* T_ value of dst */
+ unsigned f_srctype : 3; /* T_ value of src */
+ unsigned f_dsttype : 3; /* T_ value of dst */
unsigned f_estab : 1; /* Check TCP ACK bit */
unsigned f_syn : 1; /* Check TCP SYN bit */
unsigned f_finrst : 1; /* Check TCP FIN/RST bits */
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]);
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: ipcp.c,v 1.22 2000/03/03 21:52:57 brian Exp $
+ * $OpenBSD: ipcp.c,v 1.23 2000/03/19 10:33:33 brian Exp $
*
* TODO:
* o Support IPADDRS properly
#include <resolv.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/stat.h>
#include <termios.h>
#include <unistd.h>
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
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]));
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;
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);
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
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
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)) {
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);
}
/* 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;
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) {
/*
}
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;
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) {
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: ipcp.h,v 1.8 2000/02/27 01:38:26 brian Exp $
+ * $OpenBSD: ipcp.h,v 1.9 2000/03/19 10:33:33 brian Exp $
*
* TODO:
*/
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 */
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 */
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)
-.\" $OpenBSD: ppp.8,v 1.79 2000/03/14 21:31:44 aaron Exp $
+.\" $OpenBSD: ppp.8,v 1.80 2000/03/19 10:33:33 brian Exp $
.Dd 20 September 1995
.nr XX \w'\fC00'
.Dt PPP 8
flag for backwards compatability) does the equivalent of a
.Dq nat enable yes ,
enabling
-.Nm ppp Ns No s
+.Nm Ns No 's
network address translation features. This allows
-.Nm ppp
+.Nm
to act as a NAT or masquerading engine for all machines on an internal
LAN. Refer to
.Xr libalias 3
attempts to establish a connection with the peer immediately, but never
becomes a daemon. The link is created in background mode. This is useful
if you wish to control
-.Nm ppp Ns No s
+.Nm Ns No 's
invocation from another process.
.It Fl direct
This is used for receiving incoming connections.
.Pa /etc/syslog.conf .
.It
Although not strictly relevant to
-.Nm ppp Ns No s
+.Nm Ns No 's
operation, you should configure your resolver so that it works correctly.
This can be done by configuring a local DNS
.Pq using Xr named 8
.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
Usually, parity is set to
.Dq none ,
and this is
-.Nm ppp Ns No s
+.Nm Ns No 's
default. Parity is a rather archaic error checking mechanism that is no
longer used because modern modems do their own error checking, and most
link-layer protocols (that's what
.Pa /etc/ppp/ppp.conf
to use. It must contain the
.Dq set ifaddr
-command to define the remote peers IP address. (refer to
-.Pa /etc/ppp/ppp.conf.sample )
+command to define the remote peers IP address.
+(refer to
+.Pa /usr/share/examples/ppp/ppp.conf.sample )
.Bd -literal -offset indent
# ppp -auto pmdemand
.Ed
.Bl -tag -width attempts -compact
.It Ar secs
is the number of seconds to wait before attempting
-to connect again. If the argument is the literal string
+to connect again.
+If the argument is the literal string
.Sq Li random ,
the delay period is a random value between 1 and 30 seconds inclusive.
.It Ar inc
.Nm
in
.Fl auto
-mode on both ends of the link. If each end has the same timeout,
+mode on both ends of the link.
+If each end has the same timeout,
both ends wind up calling each other at the same time if the link
drops and both ends have packets queued.
At some locations, the serial link may not be reliable, and carrier
.Pp
.Sh RECEIVING INCOMING PPP CONNECTIONS (Method 2)
This method differs in that we use
-.Nm ppp
+.Nm
to authenticate the connection rather than
.Xr login 1 :
.Bl -enum
as if passed to the
.Dq set cbcp
command. The value will be used in
-.Nm ppp Ns No s
+.Nm Ns No 's
subsequent CBCP phase.
.Sh PPP OVER TCP and UDP (a.k.a Tunnelling)
Instead of running
.Nm
host as the gateway for the LAN.
.Sh PACKET FILTERING
-This implementation supports packet filtering. There are four kinds of
+This implementation supports packet filtering.
+There are four kinds of
filters; the
.Em in
filter, the
version 2.3.*.
.Sh CONTROLLING IP ADDRESS
.Nm
-uses IPCP to negotiate IP addresses. Each side of the connection
+uses IPCP to negotiate IP addresses.
+Each side of the connection
specifies the IP address that it's willing to use, and if the requested
IP address is acceptable then
.Nm
returns ACK to the requester. Otherwise,
.Nm
-returns NAK to suggest that the peer use a different IP address. When
+returns NAK to suggest that the peer use a different IP address.
+When
both sides of the connection agree to accept the received request (and
send ACK), IPCP is set to the open state and a network level connection
is established.
.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 .
the actual link file descriptor) between different
.Nm
invocations. This facilitates
-.Nm ppp Ns No s
+.Nm Ns No 's
ability to be run from a
.Xr getty 8
or directly from
.Nm
to finish with the link and deliver a signal back to the idle process.
This prevents the confusion that results from
-.Nm ppp Ns No 's
+.Nm Ns No 's
parent considering the link resource available again.
.Pp
For tty devices that have entries in
With this option enabled,
.Nm
will pass traffic for old interface addresses through the NAT engine
-.Pq see Xr libalias 5 ,
+.Pq see Xr libalias 3 ,
resulting in the ability (in
.Fl auto
mode) to properly connect the process that caused the PPP link to
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 .
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
or
.Sq USR
may make the log file more readable.
+.It resolv Ar command
+This command controls
+.Nm 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
.Oc
.Xc
If no arguments are given, CBCP (Microsoft's CallBack Control Protocol)
-is disabled - i.e., configuring CBCP in the
+is disabled - ie, configuring CBCP in the
.Dq set callback
command will result in
.Nm
.Pp
Some modems take more than one second after connecting to assert the carrier
signal. If this delay isn't increased, this will result in
-.Nm ppp Ns No s
+.Nm Ns No 's
inability to detect when the link is dropped, as
.Nm
assumes that the device isn't asserting carrier.
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: route.c,v 1.7 2000/02/27 01:38:28 brian Exp $
+ * $OpenBSD: route.c,v 1.8 2000/03/19 10:33:34 brian Exp $
*
*/
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;
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);
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));
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: route.h,v 1.4 2000/02/27 01:38:28 brian Exp $
+ * $OpenBSD: route.h,v 1.5 2000/03/19 10:33:34 brian Exp $
*
*/
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) */
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);
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: systems.c,v 1.11 2000/02/27 01:38:29 brian Exp $
+ * $OpenBSD: systems.c,v 1.12 2000/03/19 10:33:34 brian Exp $
*
* TODO:
*/
}
/* Move string from ``from'' to ``to'', interpreting ``~'' and $.... */
-static const char *
+const char *
InterpretArg(const char *from, char *to)
{
- const char *env;
char *ptr, *startto, *endto;
- int len;
+ struct passwd *pwd;
+ int len, instring;
+ const char *env;
+ instring = 0;
startto = to;
endto = to + LINE_LEN - 1;
while(issep(*from))
from++;
- if (*from == '~') {
- struct passwd *pwd;
-
- ptr = strchr(++from, '/');
- len = ptr ? ptr - from : strlen(from);
- if (len == 0) {
- pwd = getpwuid(ID0realuid());
- } else {
- strncpy(to, from, len);
- to[len] = '\0';
- pwd = getpwnam(to);
- }
- strncpy(to, pwd ? pwd->pw_dir : _PATH_PPP, endto - to);
- endpwent();
-
- *endto = '\0';
- to += strlen(to);
- from += len;
- }
-
- while (to < endto && !issep(*from) && *from != '#' && *from != '\0') {
- if (*from == '$') {
- if (from[1] == '$') {
- *to = '\0'; /* For an empty var name below */
- from += 2;
- } else if (from[1] == '{') {
- ptr = strchr(from+2, '}');
- if (ptr) {
- len = ptr - from - 2;
- if (endto - to < len )
- len = endto - to;
- if (len) {
- strncpy(to, from+2, len);
- to[len] = '\0';
- from = ptr+1;
+ while (*from != '\0') {
+ switch (*from) {
+ case '"':
+ instring = !instring;
+ *to++ = *from++;
+ break;
+ case '\\':
+ switch (*++from) {
+ case '$':
+ case '~':
+ break; /* Swallow the escapes */
+
+ default:
+ *to++ = '\\'; /* Pass the escapes on, maybe skipping \# */
+ break;
+ }
+ *to++ = *from++;
+ break;
+ case '$':
+ if (from[1] == '$') {
+ *to = '\0'; /* For an empty var name below */
+ from += 2;
+ } else if (from[1] == '{') {
+ ptr = strchr(from+2, '}');
+ if (ptr) {
+ len = ptr - from - 2;
+ if (endto - to < len )
+ len = endto - to;
+ if (len) {
+ strncpy(to, from+2, len);
+ to[len] = '\0';
+ from = ptr+1;
+ } else {
+ *to++ = *from++;
+ continue;
+ }
} else {
*to++ = *from++;
continue;
}
} else {
- *to++ = *from++;
- continue;
+ ptr = to;
+ for (from++; (isalnum(*from) || *from == '_') && ptr < endto; from++)
+ *ptr++ = *from;
+ *ptr = '\0';
}
- } else {
- ptr = to;
- for (from++; (isalnum(*from) || *from == '_') && ptr < endto; from++)
- *ptr++ = *from;
- *ptr = '\0';
- }
- if (*to == '\0')
- *to++ = '$';
- else if ((env = getenv(to)) != NULL) {
- strncpy(to, env, endto - to);
- *endto = '\0';
- to += strlen(to);
- }
- } else {
- if (*from == '\\')
- from++;
- *to++ = *from++;
+ if (*to == '\0')
+ *to++ = '$';
+ else if ((env = getenv(to)) != NULL) {
+ strncpy(to, env, endto - to);
+ *endto = '\0';
+ to += strlen(to);
+ }
+ break;
+
+ case '~':
+ ptr = strchr(++from, '/');
+ len = ptr ? ptr - from : strlen(from);
+ if (len == 0)
+ pwd = getpwuid(ID0realuid());
+ else {
+ strncpy(to, from, len);
+ to[len] = '\0';
+ pwd = getpwnam(to);
+ }
+ if (pwd == NULL)
+ *to++ = '~';
+ else {
+ strncpy(to, pwd->pw_dir, endto - to);
+ *endto = '\0';
+ to += strlen(to);
+ from += len;
+ }
+ endpwent();
+ break;
+
+ case '#':
+ if (!instring)
+ while (*from != '\0')
+ *to++ = *from++;
+ break;
+
+ default:
+ *to++ = *from++;
+ break;
}
}
}
*to = '\0';
- while (issep(*from))
- from++;
-
return from;
}
}
len = strlen(cp);
- if ((argc = command_Interpret(cp, len, argv)) < 0)
+ if ((argc = command_Expand_Interpret(cp, len, argv, cp - line)) < 0)
log_Printf(LogWARN, "%s: %d: Syntax error\n", filename, linenum);
else {
allowcmd = argc > 0 && !strcasecmp(argv[0], "allow");
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * $OpenBSD: systems.h,v 1.4 2000/02/27 01:38:29 brian Exp $
+ * $OpenBSD: systems.h,v 1.5 2000/03/19 10:33:34 brian Exp $
*
*/
extern int AllowModes(struct cmdargs const *);
extern int LoadCommand(struct cmdargs const *);
extern int SaveCommand(struct cmdargs const *);
+extern const char *InterpretArg(const char *, char *);