diff options
author | dumbbell <dumbbell@FreeBSD.org> | 2011-12-04 14:44:31 +0000 |
---|---|---|
committer | dumbbell <dumbbell@FreeBSD.org> | 2011-12-04 14:44:31 +0000 |
commit | ff8355fd0adf45a0a0be9afa0e0791db4f1251ff (patch) | |
tree | 7f5d2448f6dafab8a79f813bf2da0674512a632a /tools | |
parent | e2bfeee07672c9a691d9ee0ac15d92150d93d457 (diff) | |
download | FreeBSD-src-ff8355fd0adf45a0a0be9afa0e0791db4f1251ff.zip FreeBSD-src-ff8355fd0adf45a0a0be9afa0e0791db4f1251ff.tar.gz |
Support domain-search in dhclient(8)
The "domain-search" option (option 119) allows a DHCP server to publish
a list of implicit domain suffixes used during name lookup. This option
is described in RFC 3397.
For instance, if the domain-search option says:
".example.org .example.com"
and one wants to resolve "foobar", the resolver will try:
1. "foobar.example.org"
2. "foobar.example.com"
The file /etc/resolv.conf is updated with a "search" directive if the
DHCP server provides "domain-search".
A regression test suite is included in this patch under
tools/regression/sbin/dhclient.
PR: bin/151940
Sponsored by Yakaz (http://www.yakaz.com)
Diffstat (limited to 'tools')
-rw-r--r-- | tools/regression/sbin/Makefile | 2 | ||||
-rw-r--r-- | tools/regression/sbin/dhclient/Makefile | 16 | ||||
-rw-r--r-- | tools/regression/sbin/dhclient/fake.c | 60 | ||||
-rw-r--r-- | tools/regression/sbin/dhclient/option-domain-search.c | 328 |
4 files changed, 405 insertions, 1 deletions
diff --git a/tools/regression/sbin/Makefile b/tools/regression/sbin/Makefile index 33d158e..623ff62 100644 --- a/tools/regression/sbin/Makefile +++ b/tools/regression/sbin/Makefile @@ -1,5 +1,5 @@ # $FreeBSD$ -SUBDIR= growfs +SUBDIR= dhclient growfs .include <bsd.subdir.mk> diff --git a/tools/regression/sbin/dhclient/Makefile b/tools/regression/sbin/dhclient/Makefile new file mode 100644 index 0000000..7de3791 --- /dev/null +++ b/tools/regression/sbin/dhclient/Makefile @@ -0,0 +1,16 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../sbin/dhclient + +SRCS= alloc.c convert.c hash.c options.c tables.c \ + fake.c \ + option-domain-search.c + +CFLAGS+= -I${.CURDIR}/../../../../sbin/dhclient +LDADD= -lutil + +PROG= option-domain-search + +WARNS?= 2 + +.include <bsd.prog.mk> diff --git a/tools/regression/sbin/dhclient/fake.c b/tools/regression/sbin/dhclient/fake.c new file mode 100644 index 0000000..91d57b6 --- /dev/null +++ b/tools/regression/sbin/dhclient/fake.c @@ -0,0 +1,60 @@ +/* $FreeBSD$ */ + +#include <setjmp.h> +#include <stdarg.h> +#include <stdio.h> + +#include "dhcpd.h" + +extern jmp_buf env; + +void +error(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + + longjmp(env, 1); +} + +int +warning(char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + + return ret; +} + +int +note(char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = vfprintf(stderr, fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + + return ret; +} + +void +bootp(struct packet *packet) +{ +} + +void +dhcp(struct packet *packet) +{ +} diff --git a/tools/regression/sbin/dhclient/option-domain-search.c b/tools/regression/sbin/dhclient/option-domain-search.c new file mode 100644 index 0000000..b79f9a5 --- /dev/null +++ b/tools/regression/sbin/dhclient/option-domain-search.c @@ -0,0 +1,328 @@ +/* $FreeBSD$ */ + +#include <setjmp.h> +#include <stdlib.h> + +#include "dhcpd.h" + +jmp_buf env; + +void expand_domain_search(struct packet *packet); + +void +no_option_present() +{ + int ret; + struct option_data option; + struct packet p; + + option.data = NULL; + option.len = 0; + p.options[DHO_DOMAIN_SEARCH] = option; + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (p.options[DHO_DOMAIN_SEARCH].len != 0 || + p.options[DHO_DOMAIN_SEARCH].data != NULL) + abort(); +} + +void +one_domain_valid() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0"; + char *expected = "example.org."; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 13; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (option->len != strlen(expected) || + strcmp(option->data, expected) != 0) + abort(); + + free(option->data); +} + +void +one_domain_truncated1() +{ + int ret; + struct option_data *option; + struct packet p; + + char *data = "\007example\003org"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 12; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +one_domain_truncated2() +{ + int ret; + struct option_data *option; + struct packet p; + + char *data = "\007ex"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 3; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_valid() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0\007example\003com\0"; + char *expected = "example.org. example.com."; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 26; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (option->len != strlen(expected) || + strcmp(option->data, expected) != 0) + abort(); + + free(option->data); +} + +void +two_domains_truncated1() +{ + int ret; + struct option_data *option; + struct packet p; + + char *data = "\007example\003org\0\007example\003com"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 25; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_truncated2() +{ + int ret; + struct option_data *option; + struct packet p; + + char *data = "\007example\003org\0\007ex"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 16; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_compressed() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0\006foobar\xc0\x08"; + char *expected = "example.org. foobar.org."; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 22; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (option->len != strlen(expected) || + strcmp(option->data, expected) != 0) + abort(); + + free(option->data); +} + +void +two_domains_infloop() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0\006foobar\xc0\x0d"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 22; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_forwardptr() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\xc0\x0d\006foobar\0"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 22; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +two_domains_truncatedptr() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = "\007example\003org\0\006foobar\xc0"; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 21; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (ret != 1) + abort(); + + free(option->data); +} + +void +multiple_domains_valid() +{ + int ret; + struct packet p; + struct option_data *option; + + char *data = + "\007example\003org\0\002cl\006foobar\003com\0\002fr\xc0\x10"; + + char *expected = "example.org. cl.foobar.com. fr.foobar.com."; + + option = &p.options[DHO_DOMAIN_SEARCH]; + option->len = 33; + option->data = malloc(option->len); + memcpy(option->data, data, option->len); + + ret = setjmp(env); + if (ret == 0) + expand_domain_search(&p); + + if (option->len != strlen(expected) || + strcmp(option->data, expected) != 0) + abort(); + + free(option->data); +} + +int +main(int argc, char *argv[]) +{ + + no_option_present(); + + one_domain_valid(); + one_domain_truncated1(); + one_domain_truncated2(); + + two_domains_valid(); + two_domains_truncated1(); + two_domains_truncated2(); + + two_domains_compressed(); + two_domains_infloop(); + two_domains_forwardptr(); + two_domains_truncatedptr(); + + multiple_domains_valid(); + + return (0); +} |