aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2014-06-07 12:52:57 -0700
committerH. Peter Anvin <hpa@zytor.com>2014-06-07 12:59:33 -0700
commit18ee96a03f8656031b67dd13ad2fcadb5af7ffaf (patch)
tree00cf7e465c3edc37982ac820334c9ed6984b0673
parentc89a63a441cdd176c52740bf386b78548f46d492 (diff)
downloadtftp-hpa-18ee96a03f8656031b67dd13ad2fcadb5af7ffaf.tar.gz
tftpd: allow IPv4/6-specific remapping rules
Allow remapping rules to be conditional on IPv4 vs IPv6. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--tftpd/remap.c18
-rw-r--r--tftpd/remap.h2
-rw-r--r--tftpd/tftpd.c21
3 files changed, 28 insertions, 13 deletions
diff --git a/tftpd/remap.c b/tftpd/remap.c
index 1e7abe7..6f5b409 100644
--- a/tftpd/remap.c
+++ b/tftpd/remap.c
@@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
- * Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
+ * Copyright 2001-2014 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
* as the "OpenBSD" operating system, distributed at
@@ -31,6 +31,8 @@
#define RULE_RESTART 0x08 /* Restart at the top after matching this rule */
#define RULE_ABORT 0x10 /* Terminate processing with an error */
#define RULE_INVERSE 0x20 /* Execute if regex *doesn't* match */
+#define RULE_IPV4 0x40 /* IPv4 only */
+#define RULE_IPV6 0x80 /* IPv6 only */
struct rule {
struct rule *next;
@@ -223,6 +225,12 @@ static int parseline(char *line, struct rule *r, int lineno)
case '~':
r->rule_flags |= RULE_INVERSE;
break;
+ case '4':
+ r->rule_flags |= RULE_IPV4;
+ break;
+ case '6':
+ r->rule_flags |= RULE_IPV6;
+ break;
case 'G':
case 'P':
r->rule_mode = *p;
@@ -326,7 +334,7 @@ void freerules(struct rule *r)
/* Execute a rule set on a string; returns a malloc'd new string. */
char *rewrite_string(const char *input, const struct rule *rules,
- char mode, match_pattern_callback macrosub,
+ char mode, int af, match_pattern_callback macrosub,
const char **errmsg)
{
char *current = tfstrdup(input);
@@ -348,6 +356,12 @@ char *rewrite_string(const char *input, const struct rule *rules,
if (ruleptr->rule_mode && ruleptr->rule_mode != mode)
continue; /* Rule not applicable, try next */
+ if ((ruleptr->rule_flags & RULE_IPV4) && (af != AF_INET))
+ continue; /* Rule not applicable, try next */
+
+ if ((ruleptr->rule_flags & RULE_IPV6) && (af != AF_INET6))
+ continue; /* Rule not applicable, try next */
+
if (!deadman--) {
syslog(LOG_WARNING,
"remap: Breaking loop, input = %s, last = %s", input,
diff --git a/tftpd/remap.h b/tftpd/remap.h
index 69ca08d..7efcf6a 100644
--- a/tftpd/remap.h
+++ b/tftpd/remap.h
@@ -35,7 +35,7 @@ struct rule *parserulefile(FILE *);
void freerules(struct rule *);
/* Execute a rule set on a string; returns a malloc'd new string. */
-char *rewrite_string(const char *, const struct rule *, char,
+char *rewrite_string(const char *, const struct rule *, char, int,
match_pattern_callback, const char **);
#endif /* WITH_REGEX */
diff --git a/tftpd/tftpd.c b/tftpd/tftpd.c
index 1873e70..88d2812 100644
--- a/tftpd/tftpd.c
+++ b/tftpd/tftpd.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* Copyright (c) 1999-2009 H. Peter Anvin
- * Copyright (c) 2011 Intel Corporation; author: H. Peter Anvin
+ * Copyright (c) 2011-2014 Intel Corporation; author: H. Peter Anvin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -1039,18 +1039,18 @@ int main(int argc, char **argv)
tp = (struct tftphdr *)buf;
tp_opcode = ntohs(tp->th_opcode);
if (tp_opcode == RRQ || tp_opcode == WRQ)
- tftp(tp, n);
+ tftp(tp, n);
exit(0);
}
-static char *rewrite_access(char *, int, const char **);
+static char *rewrite_access(char *, int, int, const char **);
static int validate_access(char *, int, const struct formats *, const char **);
static void tftp_sendfile(const struct formats *, struct tftphdr *, int);
static void tftp_recvfile(const struct formats *, struct tftphdr *, int);
struct formats {
const char *f_mode;
- char *(*f_rewrite) (char *, int, const char **);
+ char *(*f_rewrite) (char *, int, int, const char **);
int (*f_validate) (char *, int, const struct formats *, const char **);
void (*f_send) (const struct formats *, struct tftphdr *, int);
void (*f_recv) (const struct formats *, struct tftphdr *, int);
@@ -1112,9 +1112,8 @@ int tftp(struct tftphdr *tp, int size)
nak(EBADOP, "Unknown mode");
exit(0);
}
- if (!(filename =
- (*pf->f_rewrite) (origfilename, tp_opcode,
- &errmsgptr))) {
+ if (!(filename = (*pf->f_rewrite)
+ (origfilename, tp_opcode, from.sa.sa_family, &errmsgptr))) {
nak(EACCESS, errmsgptr); /* File denied by mapping rule */
exit(0);
}
@@ -1398,12 +1397,13 @@ static int rewrite_macros(char macro, char *output)
/*
* Modify the filename, if applicable. If it returns NULL, deny the access.
*/
-static char *rewrite_access(char *filename, int mode, const char **msg)
+static char *rewrite_access(char *filename, int mode, int af,
+ const char **msg)
{
if (rewrite_rules) {
char *newname =
rewrite_string(filename, rewrite_rules,
- mode != RRQ ? 'P' : 'G',
+ mode != RRQ ? 'P' : 'G', af,
rewrite_macros, msg);
filename = newname;
}
@@ -1411,10 +1411,11 @@ static char *rewrite_access(char *filename, int mode, const char **msg)
}
#else
-static char *rewrite_access(char *filename, int mode, const char **msg)
+static char *rewrite_access(char *filename, int mode, int af, const char **msg)
{
(void)mode; /* Avoid warning */
(void)msg;
+ (void)af;
return filename;
}
#endif