37 int keep_capabilities = 0;
41#include <systemd/sd-daemon.h>
90int dfd[2] = { -1, -1 };
113 struct sockaddr_in
to;
118struct in_addr
gw = {0};
122 struct stream_list *next;
123 struct interface_info *ifp;
124 struct sockaddr_in6 link;
126} *downstreams, *upstreams;
129static struct stream_list *parse_downstream(
char *);
130static struct stream_list *parse_upstream(
char *);
131static void setup_streams(
void);
140char *dhcrelay_sub_id = NULL;
145 unsigned int,
unsigned int,
struct iaddr,
160static void request_v4_interface(
const char* name,
int flags);
162static const char copyright[] =
163"Copyright 2004-2022 Internet Systems Consortium.";
164static const char arr[] =
"All rights reserved.";
165static const char message[] =
166"Internet Systems Consortium DHCP Relay Agent";
167static const char url[] =
168"For info, please visit https://www.isc.org/software/dhcp/";
174#define DHCRELAY_USAGE \
175"Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \
176" [-A <length>] [-c <hops>]\n" \
177" [-p <port> | -rp <relay-port>]\n" \
178" [-pf <pid-file>] [--no-pid]\n"\
179" [-m append|replace|forward|discard]\n" \
180" [-i interface0 [ ... -i interfaceN]\n" \
181" [-iu interface0 [ ... -iu interfaceN]\n" \
182" [-id interface0 [ ... -id interfaceN]\n" \
183" [-U interface] [-g <ip-address>]\n" \
184" server0 [ ... serverN]\n\n" \
185" %s -6 [-d] [-q] [-I] [-c <hops>]\n" \
186" [-p <port> | -rp <relay-port>]\n" \
187" [-pf <pid-file>] [--no-pid]\n" \
188" [-s <subscriber-id>]\n" \
189" -l lower0 [ ... -l lowerN]\n" \
190" -u upper0 [ ... -u upperN]\n" \
191" lower (client link): [address%%]interface[#index]\n" \
192" upper (server link): [address%%]interface\n\n" \
193" %s {--version|--help|-h}"
195#define DHCRELAY_USAGE \
196"Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \
197" [-A <length>] [-c <hops>] [-p <port>]\n" \
198" [-pf <pid-file>] [--no-pid]\n"\
199" [-m append|replace|forward|discard]\n" \
200" [-i interface0 [ ... -i interfaceN]\n" \
201" [-iu interface0 [ ... -iu interfaceN]\n" \
202" [-id interface0 [ ... -id interfaceN]\n" \
203" [-U interface] [-g <ip-address>]\n" \
204" server0 [ ... serverN]\n\n" \
205" %s -6 [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
206" [-pf <pid-file>] [--no-pid]\n" \
207" [-s <subscriber-id>]\n" \
208" -l lower0 [ ... -l lowerN]\n" \
209" -u upper0 [ ... -u upperN]\n" \
210" lower (client link): [address%%]interface[#index]\n" \
211" upper (server link): [address%%]interface\n\n" \
212" %s {--version|--help|-h}"
216#define DHCRELAY_USAGE \
217"Usage: %s [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>]\n" \
218" [-p <port> | -rp <relay-port>]\n" \
219" [-pf <pid-file>] [--no-pid]\n" \
220" [-m append|replace|forward|discard]\n" \
221" [-i interface0 [ ... -i interfaceN]\n" \
222" [-iu interface0 [ ... -iu interfaceN]\n" \
223" [-id interface0 [ ... -id interfaceN]\n" \
224" [-U interface] [-g <ip-address>]\n" \
225" server0 [ ... serverN]\n\n" \
226" %s {--version|--help|-h}"
228#define DHCRELAY_USAGE \
229"Usage: %s [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>] [-p <port>]\n" \
230" [-pf <pid-file>] [--no-pid]\n" \
231" [-m append|replace|forward|discard]\n" \
232" [-i interface0 [ ... -i interfaceN]\n" \
233" [-iu interface0 [ ... -iu interfaceN]\n" \
234" [-id interface0 [ ... -id interfaceN]\n" \
235" [-U interface] [-g <ip-address>]\n" \
236" server0 [ ... serverN]\n\n" \
237" %s {--version|--help|-h}"
256static const char use_noarg[] =
"No argument for command: %s";
258static const char use_port_defined[] =
"Port already set, %s inappropriate";
259#if !defined (USE_BPF_RECEIVE) && !defined (USE_LPF_RECEIVE)
260static const char bpf_sock_support[] =
"Only LPF and BPF are supported: %s";
264static const char use_badproto[] =
"Protocol already set, %s inappropriate";
265static const char use_v4command[] =
"Command not used for DHCPv6: %s";
266static const char use_v6command[] =
"Command not used for DHCPv4: %s";
270usage(
const char *sfmt,
const char *sarg) {
277#ifdef PRINT_SPECIFIC_CL_ERRORS
295 char *service_local = NULL, *service_remote = NULL;
296 u_int16_t port_local = 0, port_remote = 0;
301 int port_defined = 0;
304 struct stream_list *sl = NULL;
305 int local_family_set = 0;
317 fd = open(
"/dev/null", O_RDWR | O_CLOEXEC);
319 fd = open(
"/dev/null", O_RDWR | O_CLOEXEC);
321 fd = open(
"/dev/null", O_RDWR | O_CLOEXEC);
330 setlogmask(LOG_UPTO(LOG_INFO));
334 for (i = 1; i < argc; i++) {
335 if (!strcmp(argv[i],
"-d")) {
337 }
else if (!strcmp(argv[i],
"--version")) {
340 }
else if (!strcmp(argv[i],
"--help") ||
341 !strcmp(argv[i],
"-h")) {
357 if ((pid = fork ()) < 0)
363 (void) close(
dfd[1]);
367 n = read(
dfd[0], &buf, 1);
370 }
while (n == -1 && errno == EINTR);
374 (void) close(
dfd[0]);
381 log_fatal(
"Can't initialize context: %s",
382 isc_result_totext(status));
388 isc_result_totext(status));
393 for (i = 1; i < argc; i++) {
394 if (!strcmp(argv[i],
"-4")) {
397 usage(use_badproto,
"-4");
399 local_family_set = 1;
401 }
else if (!strcmp(argv[i],
"-6")) {
403 usage(use_badproto,
"-6");
405 local_family_set = 1;
408 }
else if (!strcmp(argv[i],
"-d")) {
410 }
else if (!strcmp(argv[i],
"-q")) {
413 }
else if (!strcmp(argv[i],
"-p")) {
415 usage(use_noarg, argv[i-1]);
418 usage(use_port_defined, argv[i-1]);
422 log_debug(
"binding to user-specified port %d",
425 }
else if (!strcmp(argv[i],
"-rp")) {
427 usage(use_noarg, argv[i-1]);
429 usage(use_port_defined, argv[i-1]);
432 log_debug(
"binding to user-specified relay port %d",
436 }
else if (!strcmp(argv[i],
"-c")) {
439 usage(use_noarg, argv[i-1]);
440 hcount = atoi(argv[i]);
444 usage(
"Bad hop count to -c: %s", argv[i]);
445 }
else if (!strcmp(argv[i],
"-i")) {
448 usage(use_v4command, argv[i]);
450 local_family_set = 1;
454 usage(use_noarg, argv[i-1]);
458 }
else if (!strcmp(argv[i],
"-iu")) {
461 usage(use_v4command, argv[i]);
463 local_family_set = 1;
467 usage(use_noarg, argv[i-1]);
471 }
else if (!strcmp(argv[i],
"-id")) {
474 usage(use_v4command, argv[i]);
476 local_family_set = 1;
480 usage(use_noarg, argv[i-1]);
484 }
else if (!strcmp(argv[i],
"-a")) {
487 usage(use_v4command, argv[i]);
489 local_family_set = 1;
493 }
else if (!strcmp(argv[i],
"-A")) {
496 usage(use_v4command, argv[i]);
498 local_family_set = 1;
502 usage(use_noarg, argv[i-1]);
508 "longest possible MTU\n",
510 }
else if (!strcmp(argv[i],
"-m")) {
513 usage(use_v4command, argv[i]);
515 local_family_set = 1;
519 usage(use_noarg, argv[i-1]);
520 if (!strcasecmp(argv[i],
"append")) {
522 }
else if (!strcasecmp(argv[i],
"replace")) {
524 }
else if (!strcasecmp(argv[i],
"forward")) {
526 }
else if (!strcasecmp(argv[i],
"discard")) {
529 usage(
"Unknown argument to -m: %s", argv[i]);
530 }
else if (!strcmp(argv [i],
"-U")) {
532 usage(use_noarg, argv[i-1]);
535 usage(
"more than one uplink (-U) specified: %s"
540 status = interface_allocate(&
uplink,
MDL);
542 log_fatal(
"%s: uplink interface_allocate: %s",
543 argv[i], isc_result_totext(status));
546 if (strlen(argv[i]) >=
sizeof(
uplink->name)) {
548 " it cannot exceed: %ld characters",
549 argv[i], (
long)(
sizeof(
uplink->name) - 1));
553 strncpy(
uplink->name, argv[i],
554 sizeof(
uplink->name) - 1);
561 }
else if (!strcmp(argv[i],
"-g")) {
563 usage(use_noarg, argv[i-1]);
566 usage(use_v4command, argv[i]);
568 local_family_set = 1;
571 if (inet_pton(AF_INET, argv[i], &
gw) <= 0) {
572 usage(
"Invalid gateway address '%s'", argv[i]);
576 }
else if (!strcmp(argv[i],
"-D")) {
579 usage(use_v4command, argv[i]);
581 local_family_set = 1;
586 }
else if (!strcmp(argv[i],
"-I")) {
588 usage(use_v6command, argv[i]);
590 local_family_set = 1;
593 }
else if (!strcmp(argv[i],
"-l")) {
595 usage(use_v6command, argv[i]);
597 local_family_set = 1;
599 if (downstreams != NULL)
602 usage(use_noarg, argv[i-1]);
603 sl = parse_downstream(argv[i]);
604 sl->next = downstreams;
606 }
else if (!strcmp(argv[i],
"-u")) {
608 usage(use_v6command, argv[i]);
610 local_family_set = 1;
613 usage(use_noarg, argv[i-1]);
614 sl = parse_upstream(argv[i]);
615 sl->next = upstreams;
617 }
else if (!strcmp(argv[i],
"-s")) {
619 usage(use_v6command, argv[i]);
621 local_family_set = 1;
624 usage(use_noarg, argv[i-1]);
625 dhcrelay_sub_id = argv[i];
627 }
else if (!strcmp(argv[i],
"-nc")) {
629 keep_capabilities = 1;
631 }
else if (!strcmp(argv[i],
"-pf")) {
633 usage(use_noarg, argv[i-1]);
636 }
else if (!strcmp(argv[i],
"--no-pid")) {
638 }
else if (argv[i][0] ==
'-') {
639 usage(
"Unknown command: %s", argv[i]);
642 struct in_addr ia, *iap = NULL;
646 usage(use_v4command, argv[i]);
648 local_family_set = 1;
651 if (inet_aton(argv[i], &ia)) {
654 he = gethostbyname(argv[i]);
658 iap = ((
struct in_addr *)
670 memcpy(&sp->
to.sin_addr, iap,
sizeof *iap);
675#if defined(RELAY_PORT) && \
676 !defined (USE_BPF_RECEIVE) && !defined (USE_LPF_RECEIVE)
678 usage(bpf_sock_support,
"-rp");
702 if (!keep_capabilities) {
703 capng_clear(CAPNG_SELECT_BOTH);
704 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
705 CAP_NET_RAW, CAP_NET_BIND_SERVICE, -1);
706 capng_apply(CAPNG_SELECT_BOTH);
707 log_info (
"Dropped all unnecessary capabilities.");
721 service_local =
"bootps";
722 service_remote =
"bootpc";
723 port_local = htons(67);
724 port_remote = htons(68);
728 service_local =
"dhcpv6-server";
729 service_remote =
"dhcpv6-client";
730 port_local = htons(547);
731 port_remote = htons(546);
736 ent = getservbyname(service_local,
"udp");
742 ent = getservbyname(service_remote,
"udp");
761 sp->
to.sin_family = AF_INET;
763 sp->
to.sin_len =
sizeof sp->
to;
772 if (upstreams == NULL || downstreams == NULL) {
773 log_info(
"Must specify at least one lower "
774 "and one upper interface.\n");
786 log_fatal(
"Unable to find the RELAY_MSG "
787 "option definition.");
792 log_fatal(
"Unable to find the INTERFACE_ID "
793 "option definition.");
798 gettimeofday(&
cur_tv, NULL);
817 if (
dfd[0] != -1 &&
dfd[1] != -1) {
818 if (write(
dfd[1], &buf, 1) != 1)
820 (void) close(
dfd[1]);
827 O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
833 pf = fdopen(pfdesc,
"we");
838 fprintf(pf,
"%ld\n",(
long)getpid());
860#if defined(ENABLE_GENTLE_SHUTDOWN)
869 if (!keep_capabilities) {
870 capng_clear(CAPNG_SELECT_BOTH);
871 capng_apply(CAPNG_SELECT_BOTH);
872 log_info (
"Dropped all capabilities.");
876#ifdef HAVE_LIBSYSTEMD
878 sd_notifyf(0,
"READY=1\n"
879 "STATUS=Dispatching packets...\n"
881 (
unsigned long) getpid());
893 unsigned int length,
unsigned int from_port,
struct iaddr from,
896 struct sockaddr_in to;
901 log_info(
"Discarding packet with invalid hlen, received on "
902 "%s interface.",
ip->name);
905 if (
ip->address_count < 1 ||
ip->addresses == NULL) {
906 log_info(
"Discarding packet received on %s interface that "
907 "has no IPv4 address assigned.",
ip->name);
913 if (
packet->giaddr.s_addr) {
935 log_debug(
"Dropping reply received on %s",
ip->name);
942 to.sin_addr =
packet->yiaddr;
948 to.sin_addr.s_addr = htonl(INADDR_BROADCAST);
954 to.sin_family = AF_INET;
956 to.sin_len =
sizeof to;
960 hto.hbuf[0] =
packet->htype;
961 hto.hlen =
packet->hlen + 1;
972 log_error(
"Packet to bogus giaddr %s.\n",
973 inet_ntoa(
packet->giaddr));
986 log_debug(
"Forwarded BOOTREPLY for %s to %s",
989 inet_ntoa(to.sin_addr));
1002 log_debug(
"Dropping request received on %s",
ip->name);
1018 if (!
packet->giaddr.s_addr)
1030 NULL,
packet, length,
ip->addresses[0],
1031 &sp->
to, NULL) < 0) {
1034 log_debug(
"Forwarded BOOTREQUEST for %s to %s",
1037 inet_ntoa(sp->
to.sin_addr));
1056 u_int8_t *op, *nextop, *sp, *max;
1057 int good_agent_option = 0;
1070 max = ((u_int8_t *)
packet) + length;
1105 nextop = op + op[1] + 2;
1115 good_agent_option = 1;
1125 nextop = op + op[1] + 2;
1130 size_t mlen = op[1] + 2;
1131 memmove(sp, op, mlen);
1155 if (!good_agent_option) {
1163 length = sp -((u_int8_t *)
packet);
1190 u_int8_t *buf,
int len) {
1192 u_int8_t *circuit_id = 0;
1193 unsigned circuit_id_len = 0;
1200 i + buf[i + 1] + 2 > len) {
1213 i += buf[i + 1] + 2;
1229 if (
ip->circuit_id &&
1253 unsigned length,
struct in_addr
giaddr) {
1254 int is_dhcp = 0, mms;
1256 u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
1257 int adding_link_select;
1273 && (
packet->giaddr.s_addr == 0));
1291 if (end_pad == NULL)
1311 mms = ntohs(*(op + 2));
1314 max = ((u_int8_t *)
packet) + mms;
1357 nextop = op + op[1] + 2;
1364 size_t mlen = op[1] + 2;
1365 memmove(sp, op, mlen);
1387 if (end_pad != NULL)
1397 if ((
ip->circuit_id_len > 255) ||(
ip->circuit_id_len < 1))
1398 log_fatal(
"Circuit ID length %d out of range [1-255] on "
1399 "%s\n",
ip->circuit_id_len,
ip->name);
1400 optlen =
ip->circuit_id_len + 2;
1402 if (
ip->remote_id) {
1403 if (
ip->remote_id_len > 255 ||
ip->remote_id_len < 1)
1404 log_fatal(
"Remote ID length %d out of range [1-255] "
1405 "on %s\n",
ip->remote_id_len,
ip->name);
1406 optlen +=
ip->remote_id_len + 2;
1409 if (adding_link_select) {
1422 if ((optlen < 3) ||(optlen > 255))
1423 log_fatal(
"Total agent option length(%u) out of range "
1424 "[3 - 255] on %s\n", optlen,
ip->name);
1430 if (max - sp >= optlen + 3) {
1431 log_debug(
"Adding %d-byte relay agent option", optlen + 3);
1439 *sp++ =
ip->circuit_id_len;
1440 memcpy(sp,
ip->circuit_id,
ip->circuit_id_len);
1441 sp +=
ip->circuit_id_len;
1444 if (
ip->remote_id) {
1446 *sp++ =
ip->remote_id_len;
1447 memcpy(sp,
ip->remote_id,
ip->remote_id_len);
1448 sp +=
ip->remote_id_len;
1454 if (adding_link_select) {
1457 memcpy(sp, &
giaddr.s_addr, 4);
1460 log_debug (
"Adding link selection suboption"
1461 " with addr: %s", inet_ntoa(
giaddr));
1473 log_error(
"No room in packet (used %d of %d) "
1474 "for %d-byte relay agent option: omitted",
1475 (
int) (sp - ((u_int8_t *)
packet)),
1476 (
int) (max - ((u_int8_t *)
packet)),
1488 length = sp -((u_int8_t *)
packet);
1504static struct stream_list *
1505parse_downstream(
char *arg) {
1506 struct stream_list *dp, *
up;
1508 char *ifname, *addr, *iid;
1509 isc_result_t status;
1512 (downstreams != NULL))
1513 log_fatal(
"No support for multiple interfaces.");
1516 ifname = strchr(arg,
'%');
1517 if (ifname == NULL) {
1524 iid = strchr(ifname,
'#');
1528 if (strlen(ifname) >=
sizeof(
ifp->name)) {
1529 usage(
"Interface name '%s' too long", ifname);
1533 for (dp = downstreams; dp; dp = dp->next) {
1534 if (strcmp(ifname, dp->ifp->name) == 0)
1535 log_fatal(
"Down interface '%s' declared twice.",
1540 for (
up = upstreams;
up;
up =
up->next) {
1541 if (strcmp(ifname,
up->ifp->name) == 0) {
1542 log_info(
"parse_downstream: Interface '%s' is "
1543 "both down and up.", ifname);
1551 status = interface_allocate(&
ifp,
MDL);
1554 arg, isc_result_totext(status));
1555 strcpy(
ifp->name, ifname);
1565 dp = (
struct stream_list *)
dmalloc(
sizeof(*dp),
MDL);
1575 if (addr && (inet_pton(AF_INET6, addr, &dp->link.sin6_addr) <= 0))
1576 log_fatal(
"Bad link address '%s'", addr);
1584static struct stream_list *
1585parse_upstream(
char *arg) {
1586 struct stream_list *
up, *dp;
1588 char *ifname, *addr;
1589 isc_result_t status;
1592 ifname = strchr(arg,
'%');
1593 if (ifname == NULL) {
1600 if (strlen(ifname) >=
sizeof(
ifp->name)) {
1601 log_fatal(
"Interface name '%s' too long", ifname);
1605 for (
up = upstreams;
up;
up =
up->next) {
1606 if (strcmp(ifname,
up->ifp->name) == 0) {
1611 for (dp = downstreams; dp; dp = dp->next) {
1612 if (strcmp(ifname, dp->ifp->name) == 0) {
1613 log_info(
"parse_upstream: Interface '%s' is "
1614 "both down and up.", ifname);
1622 status = interface_allocate(&
ifp,
MDL);
1625 arg, isc_result_totext(status));
1626 strcpy(
ifp->name, ifname);
1642 if (inet_pton(AF_INET6, addr, &
up->link.sin6_addr) <= 0)
1652setup_streams(
void) {
1653 struct stream_list *dp, *
up;
1657 for (dp = downstreams; dp; dp = dp->next) {
1659 if (dp->ifp->v6address_count == 0)
1660 log_fatal(
"Interface '%s' has no IPv6 addresses.",
1664 if (IN6_IS_ADDR_UNSPECIFIED(&dp->link.sin6_addr))
1668 for (i = 0; i < dp->ifp->v6address_count; i++) {
1669 if (IN6_IS_ADDR_LINKLOCAL(&dp->ifp->v6addresses[i]))
1673 if (!memcmp(&dp->ifp->v6addresses[i],
1674 &dp->link.sin6_addr,
1675 sizeof(dp->link.sin6_addr)))
1678 if (i == dp->ifp->v6address_count)
1679 log_fatal(
"Interface %s does not have global IPv6 "
1680 "address assigned.", dp->ifp->name);
1682 memcpy(&dp->link.sin6_addr,
1683 &dp->ifp->v6addresses[i],
1684 sizeof(dp->link.sin6_addr));
1688 dp->id = dp->ifp->index;
1691 for (
up = upstreams;
up;
up =
up->next) {
1693 up->link.sin6_family = AF_INET6;
1695 up->link.sin6_len =
sizeof(
up->link);
1698 if (
up->ifp->v6address_count == 0)
1699 log_fatal(
"Interface '%s' has no IPv6 addresses.",
1705 if (IN6_IS_ADDR_MULTICAST(&
up->link.sin6_addr)) {
1714static const int required_forw_opts[] = {
1717#if defined(RELAY_PORT)
1728process_up6(
struct packet *
packet,
struct stream_list *dp) {
1729 char forw_data[65535];
1733 struct stream_list *
up;
1734 u_int16_t relay_client_port = 0;
1749 log_info(
"Relaying %s from %s port %d going up.",
1761 log_info(
"Discarding %s from %s port %d going up.",
1768 log_info(
"Unknown %d type from %s port %d going up.",
1789 if (!use_if_id && downstreams->next) {
1790 log_info(
"Shan't get back the interface.");
1810 log_fatal(
"No memory for upwards options.");
1819 }
else if (!downstreams->next) {
1820 if_id = downstreams->id;
1822 log_info(
"Don't know the interface.");
1828 NULL, (
unsigned char *) &if_id,
1839 if (dhcrelay_sub_id != NULL) {
1841 (
unsigned char *) dhcrelay_sub_id,
1842 strlen(dhcrelay_sub_id),
1851#if defined(RELAY_PORT)
1862 (
unsigned char *) &relay_client_port,
1865 log_error(
"Can't save relay-source-port.");
1872 (void)(relay_client_port);
1887 sizeof(forw_data) - cursor,
1889 required_forw_opts, NULL);
1893 for (
up = upstreams;
up;
up =
up->next) {
1895 (
size_t) cursor, &
up->link);
1904 struct stream_list *dp;
1909#if defined(RELAY_PORT)
1912 struct sockaddr_in6 to;
1918 log_info(
"Discarding %s from %s port %d going down.",
1923 log_info(
"Unknown %d type from %s port %d going down.",
1931 memset(&relay_msg, 0,
sizeof(relay_msg));
1932 memset(&if_id, 0,
sizeof(if_id));
1933#if defined(RELAY_PORT)
1934 memset(&down_port, 0,
sizeof(down_port));
1936 memset(&to, 0,
sizeof(to));
1937 to.sin6_family = AF_INET6;
1939 to.sin6_len =
sizeof(to);
1953 (relay_msg.len < offsetof(
struct dhcpv6_packet, options))) {
1968 (if_id.len !=
sizeof(
int))) {
1969 log_info(
"Can't evaluate interface-id.");
1972 memcpy(&if_index, if_id.data,
sizeof(
int));
1973 for (dp = downstreams; dp; dp = dp->next) {
1974 if (dp->id == if_index)
1983 for (dp = downstreams; dp; dp = dp->next) {
1985 if (!memcmp(&dp->link.sin6_addr,
1987 sizeof(
struct in6_addr)))
1992 if (!dp && downstreams && !downstreams->next)
1995 log_info(
"Can't find the down interface.");
2007#if defined(RELAY_PORT)
2011 u_int16_t down_relay_port;
2013 memset(&down_port, 0,
sizeof(down_port));
2017 (down_port.len !=
sizeof(u_int16_t))) {
2019 "relay-source-port.");
2022 memcpy(&down_relay_port, down_port.data,
2031 if (down_relay_port) {
2032 to.sin6_port = down_relay_port;
2045 log_info(
"Relaying %s to %s port %d down.",
2048 ntohs(to.sin6_port));
2061 log_info(
"Discarding %s to %s port %d down.",
2064 ntohs(to.sin6_port));
2068 log_info(
"Unknown %d type to %s port %d down.",
2071 ntohs(to.sin6_port));
2076 send_packet6(dp->ifp, (
unsigned char *) relay_msg.data,
2077 (
size_t) relay_msg.len, &to);
2080 if (relay_msg.data != NULL)
2082 if (if_id.data != NULL)
2093 struct stream_list *dp;
2101 for (dp = downstreams; dp; dp = dp->next) {
2109 process_up6(
packet, NULL);
2113 log_info(
"Can't process packet from interface '%s'.",
2130#if defined(DHCPv6) && defined(DHCP4o6)
2148find_class(
struct class **
class,
const char *c1,
const char *c2,
int i) {
2149 return ISC_R_NOTFOUND;
2173 (void) close(
dfd[1]);
2192void request_v4_interface(
const char* name,
int flags) {
2194 int len = strlen(
name);
2195 isc_result_t status;
2197 if (len >=
sizeof(tmp->
name)) {
2198 log_fatal(
"%s: interface name too long (is %d)",
name, len);
2201 status = interface_allocate(&tmp,
MDL);
2204 isc_result_totext(status));
2207 log_debug(
"Requesting: %s as upstream: %c downstream: %c",
name,
2213 interface_dereference(&tmp,
MDL);
void data_string_forget(struct data_string *data, const char *file, int line)
int option_state_allocate(struct option_state **ptr, const char *file, int line)
int option_state_dereference(struct option_state **ptr, const char *file, int line)
int save_option_buffer(struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, unsigned code, int terminatep)
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
int store_options6(char *buf, int buflen, struct option_state *opt_state, struct packet *packet, const int *required_opts, struct data_string *oro)
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
#define _PATH_DHCRELAY_PID
isc_boolean_t no_pid_file
int dhcp_max_agent_option_packet_length
#define DHCPV6_RELAY_REPL
#define D6O_RELAY_SOURCE_PORT
#define DHCPV6_RELAY_FORW
#define DHCPV6_LEASEQUERY
#define DHCPV6_DHCPV4_QUERY
#define DHCPV6_INFORMATION_REQUEST
#define DHCPV6_RECONFIGURE
#define D6O_SUBSCRIBER_ID
#define DHCPV6_DHCPV4_RESPONSE
#define DHCPV6_LEASEQUERY_REPLY
#define DHO_DHCP_MAX_MESSAGE_SIZE
#define DHO_DHCP_AGENT_OPTIONS
#define DHO_DHCP_MESSAGE_TYPE
#define DHCP_OPTIONS_COOKIE
void do_packet6(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
#define INTERFACE_UPSTREAM
#define INTERFACE_REQUESTED
#define INTERFACE_DOWNSTREAM
int supports_multiple_interfaces(struct interface_info *)
#define INTERFACE_STREAMS
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
void(* dhcpv6_packet_handler)(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
#define _PATH_DHCRELAY6_PID
ssize_t send_packet6(struct interface_info *, const unsigned char *, size_t, struct sockaddr_in6 *)
void set_multicast_hop_limit(struct interface_info *info, int hop_limit)
int can_unicast_without_arp(struct interface_info *)
void dhcpv6(struct packet *)
struct tree_cache * global_options[256]
int corrupt_agent_options
void bootp(struct packet *packet)
int find_interface_by_agent_option(struct dhcp_packet *, struct interface_info **, u_int8_t *, int)
void dhcp(struct packet *packet)
isc_result_t find_class(struct class **class, const char *c1, const char *c2, int i)
int main(int argc, char **argv)
struct interface_info * uplink
int add_rfc3527_suboption
int drop_agent_mismatches
int check_collection(struct packet *p, struct lease *l, struct collection *c)
isc_boolean_t use_fake_gw
isc_boolean_t no_dhcrelay_pid
int strip_relay_agent_options(struct interface_info *, struct interface_info **, struct dhcp_packet *, unsigned)
enum @303200353100004055321306000055142301010272207022 agent_relay_mode
int server_packets_relayed
void classify(struct packet *p, struct class *c)
int add_relay_agent_options(struct interface_info *, struct dhcp_packet *, unsigned, struct in_addr)
isc_result_t dhcp_set_control_state(control_object_state_t oldstate, control_object_state_t newstate)
int client_packets_relayed
struct server_list * servers
const char * path_dhcrelay_pid
int parse_allow_deny(struct option_cache **oc, struct parse *p, int i)
struct option * requested_opts[2]
struct interface_info * interfaces
struct interface_info * fallback_interface
void discover_interfaces(int state)
int quiet_interface_discovery
isc_result_t interface_setup()
void(* bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)
void interface_snorf(struct interface_info *tmp, int ir)
u_int16_t validate_port(char *port)
const char * piaddr(const struct iaddr addr)
isc_result_t dhcp_context_create(int flags, struct in_addr *local4, struct in6_addr *local6)
void dhcp_signal_handler(int signal)
#define DHCP_CONTEXT_PRE_DB
#define ISC_R_NOTIMPLEMENTED
struct __omapi_object omapi_object_t
isc_result_t omapi_init(void)
void * dmalloc(size_t, const char *, int)
int log_error(const char *,...) __attribute__((__format__(__printf__
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
unsigned char link_address[16]
unsigned char peer_address[16]
struct interface_info * next
struct in_addr * addresses
struct in6_addr dhcpv6_link_address
unsigned char dhcpv6_msg_type
unsigned char dhcpv6_hop_count
struct interface_info * interface
struct in6_addr dhcpv6_peer_address
struct option_state * options
struct server_list * next
const int dhcpv6_type_name_max
const char * dhcpv6_type_names[]
struct universe dhcpv6_universe
void initialize_common_option_spaces()
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
struct binding_scope * global_scope