37 int keep_capabilities = 0;
86 int dfd[2] = { -1, -1 };
90 isc_boolean_t use_if_id = ISC_FALSE;
109 struct sockaddr_in
to;
116 struct stream_list *next;
118 struct sockaddr_in6 link;
120 } *downstreams, *upstreams;
122 static struct stream_list *parse_downstream(
char *);
123 static struct stream_list *parse_upstream(
char *);
124 static void setup_streams(
void);
132 char *dhcrelay_sub_id = NULL;
136 unsigned int,
unsigned int,
struct iaddr,
141 static int find_interface_by_agent_option(
struct dhcp_packet *,
147 static void request_v4_interface(
const char* name,
int flags);
149 static const char copyright[] =
150 "Copyright 2004-2018 Internet Systems Consortium.";
151 static const char arr[] =
"All rights reserved.";
152 static const char message[] =
153 "Internet Systems Consortium DHCP Relay Agent";
154 static const char url[] =
155 "For info, please visit https://www.isc.org/software/dhcp/";
161 #define DHCRELAY_USAGE \ 162 "Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \ 163 " [-A <length>] [-c <hops>]\n" \ 164 " [-p <port> | -rp <relay-port>]\n" \ 165 " [-pf <pid-file>] [--no-pid]\n"\ 166 " [-m append|replace|forward|discard]\n" \ 167 " [-i interface0 [ ... -i interfaceN]\n" \ 168 " [-iu interface0 [ ... -iu interfaceN]\n" \ 169 " [-id interface0 [ ... -id interfaceN]\n" \ 170 " [-U interface]\n" \ 171 " server0 [ ... serverN]\n\n" \ 172 " %s -6 [-d] [-q] [-I] [-c <hops>]\n" \ 173 " [-p <port> | -rp <relay-port>]\n" \ 174 " [-pf <pid-file>] [--no-pid]\n" \ 175 " [-s <subscriber-id>]\n" \ 176 " -l lower0 [ ... -l lowerN]\n" \ 177 " -u upper0 [ ... -u upperN]\n" \ 178 " lower (client link): [address%%]interface[#index]\n" \ 179 " upper (server link): [address%%]interface\n\n" \ 180 " %s {--version|--help|-h}" 182 #define DHCRELAY_USAGE \ 183 "Usage: %s [-4] [-d] [-q] [-a] [-D]\n" \ 184 " [-A <length>] [-c <hops>] [-p <port>]\n" \ 185 " [-pf <pid-file>] [--no-pid]\n"\ 186 " [-m append|replace|forward|discard]\n" \ 187 " [-i interface0 [ ... -i interfaceN]\n" \ 188 " [-iu interface0 [ ... -iu interfaceN]\n" \ 189 " [-id interface0 [ ... -id interfaceN]\n" \ 190 " [-U interface]\n" \ 191 " server0 [ ... serverN]\n\n" \ 192 " %s -6 [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \ 193 " [-pf <pid-file>] [--no-pid]\n" \ 194 " [-s <subscriber-id>]\n" \ 195 " -l lower0 [ ... -l lowerN]\n" \ 196 " -u upper0 [ ... -u upperN]\n" \ 197 " lower (client link): [address%%]interface[#index]\n" \ 198 " upper (server link): [address%%]interface\n\n" \ 199 " %s {--version|--help|-h}" 203 #define DHCRELAY_USAGE \ 204 "Usage: %s [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>]\n" \ 205 " [-p <port> | -rp <relay-port>]\n" \ 206 " [-pf <pid-file>] [--no-pid]\n" \ 207 " [-m append|replace|forward|discard]\n" \ 208 " [-i interface0 [ ... -i interfaceN]\n" \ 209 " [-iu interface0 [ ... -iu interfaceN]\n" \ 210 " [-id interface0 [ ... -id interfaceN]\n" \ 211 " [-U interface]\n" \ 212 " server0 [ ... serverN]\n\n" \ 213 " %s {--version|--help|-h}" 215 #define DHCRELAY_USAGE \ 216 "Usage: %s [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>] [-p <port>]\n" \ 217 " [-pf <pid-file>] [--no-pid]\n" \ 218 " [-m append|replace|forward|discard]\n" \ 219 " [-i interface0 [ ... -i interfaceN]\n" \ 220 " [-iu interface0 [ ... -iu interfaceN]\n" \ 221 " [-id interface0 [ ... -id interfaceN]\n" \ 222 " [-U interface]\n" \ 223 " server0 [ ... serverN]\n\n" \ 224 " %s {--version|--help|-h}" 243 static const char use_noarg[] =
"No argument for command: %s";
245 static const char use_port_defined[] =
"Port already set, %s inappropriate";
246 #if !defined (USE_BPF_RECEIVE) && !defined (USE_LPF_RECEIVE) 247 static const char bpf_sock_support[] =
"Only LPF and BPF are supported: %s";
251 static const char use_badproto[] =
"Protocol already set, %s inappropriate";
252 static const char use_v4command[] =
"Command not used for DHCPv6: %s";
253 static const char use_v6command[] =
"Command not used for DHCPv4: %s";
257 usage(
const char *sfmt,
const char *sarg) {
264 #ifdef PRINT_SPECIFIC_CL_ERRORS 282 char *service_local = NULL, *service_remote = NULL;
283 u_int16_t port_local = 0, port_remote = 0;
288 int port_defined = 0;
291 struct stream_list *sl = NULL;
292 int local_family_set = 0;
304 fd = open(
"/dev/null", O_RDWR | O_CLOEXEC);
306 fd = open(
"/dev/null", O_RDWR | O_CLOEXEC);
308 fd = open(
"/dev/null", O_RDWR | O_CLOEXEC);
317 setlogmask(LOG_UPTO(LOG_INFO));
321 for (i = 1; i < argc; i++) {
322 if (!strcmp(argv[i],
"-d")) {
324 }
else if (!strcmp(argv[i],
"--version")) {
327 }
else if (!strcmp(argv[i],
"--help") ||
328 !strcmp(argv[i],
"-h")) {
344 if ((pid = fork ()) < 0)
350 (void) close(
dfd[1]);
354 n = read(
dfd[0], &buf, 1);
357 }
while (n == -1 && errno == EINTR);
361 (void) close(
dfd[0]);
367 if (status != ISC_R_SUCCESS)
368 log_fatal(
"Can't initialize context: %s",
369 isc_result_totext(status));
373 if (status != ISC_R_SUCCESS)
375 isc_result_totext(status));
380 for (i = 1; i < argc; i++) {
381 if (!strcmp(argv[i],
"-4")) {
384 usage(use_badproto,
"-4");
386 local_family_set = 1;
388 }
else if (!strcmp(argv[i],
"-6")) {
390 usage(use_badproto,
"-6");
392 local_family_set = 1;
395 }
else if (!strcmp(argv[i],
"-d")) {
397 }
else if (!strcmp(argv[i],
"-q")) {
400 }
else if (!strcmp(argv[i],
"-p")) {
402 usage(use_noarg, argv[i-1]);
405 usage(use_port_defined, argv[i-1]);
409 log_debug(
"binding to user-specified port %d",
412 }
else if (!strcmp(argv[i],
"-rp")) {
414 usage(use_noarg, argv[i-1]);
416 usage(use_port_defined, argv[i-1]);
419 log_debug(
"binding to user-specified relay port %d",
423 }
else if (!strcmp(argv[i],
"-c")) {
426 usage(use_noarg, argv[i-1]);
427 hcount = atoi(argv[i]);
431 usage(
"Bad hop count to -c: %s", argv[i]);
432 }
else if (!strcmp(argv[i],
"-i")) {
435 usage(use_v4command, argv[i]);
437 local_family_set = 1;
441 usage(use_noarg, argv[i-1]);
445 }
else if (!strcmp(argv[i],
"-iu")) {
448 usage(use_v4command, argv[i]);
450 local_family_set = 1;
454 usage(use_noarg, argv[i-1]);
458 }
else if (!strcmp(argv[i],
"-id")) {
461 usage(use_v4command, argv[i]);
463 local_family_set = 1;
467 usage(use_noarg, argv[i-1]);
471 }
else if (!strcmp(argv[i],
"-a")) {
474 usage(use_v4command, argv[i]);
476 local_family_set = 1;
480 }
else if (!strcmp(argv[i],
"-A")) {
483 usage(use_v4command, argv[i]);
485 local_family_set = 1;
489 usage(use_noarg, argv[i-1]);
495 "longest possible MTU\n",
497 }
else if (!strcmp(argv[i],
"-m")) {
500 usage(use_v4command, argv[i]);
502 local_family_set = 1;
506 usage(use_noarg, argv[i-1]);
507 if (!strcasecmp(argv[i],
"append")) {
509 }
else if (!strcasecmp(argv[i],
"replace")) {
511 }
else if (!strcasecmp(argv[i],
"forward")) {
513 }
else if (!strcasecmp(argv[i],
"discard")) {
516 usage(
"Unknown argument to -m: %s", argv[i]);
517 }
else if (!strcmp(argv [i],
"-U")) {
519 usage(use_noarg, argv[i-1]);
522 usage(
"more than one uplink (-U) specified: %s" 527 status = interface_allocate(&
uplink,
MDL);
528 if (status != ISC_R_SUCCESS) {
529 log_fatal(
"%s: uplink interface_allocate: %s",
530 argv[i], isc_result_totext(status));
533 if (strlen(argv[i]) >=
sizeof(
uplink->
name)) {
535 " it cannot exceed: %ld characters",
548 }
else if (!strcmp(argv[i],
"-D")) {
551 usage(use_v4command, argv[i]);
553 local_family_set = 1;
558 }
else if (!strcmp(argv[i],
"-I")) {
560 usage(use_v6command, argv[i]);
562 local_family_set = 1;
564 use_if_id = ISC_TRUE;
565 }
else if (!strcmp(argv[i],
"-l")) {
567 usage(use_v6command, argv[i]);
569 local_family_set = 1;
571 if (downstreams != NULL)
572 use_if_id = ISC_TRUE;
574 usage(use_noarg, argv[i-1]);
575 sl = parse_downstream(argv[i]);
576 sl->next = downstreams;
578 }
else if (!strcmp(argv[i],
"-u")) {
580 usage(use_v6command, argv[i]);
582 local_family_set = 1;
585 usage(use_noarg, argv[i-1]);
586 sl = parse_upstream(argv[i]);
587 sl->next = upstreams;
589 }
else if (!strcmp(argv[i],
"-s")) {
591 usage(use_v6command, argv[i]);
593 local_family_set = 1;
596 usage(use_noarg, argv[i-1]);
597 dhcrelay_sub_id = argv[i];
599 }
else if (!strcmp(argv[i],
"-nc")) {
600 #ifdef HAVE_LIBCAP_NG 601 keep_capabilities = 1;
603 }
else if (!strcmp(argv[i],
"-pf")) {
605 usage(use_noarg, argv[i-1]);
608 }
else if (!strcmp(argv[i],
"--no-pid")) {
610 }
else if (argv[i][0] ==
'-') {
611 usage(
"Unknown command: %s", argv[i]);
614 struct in_addr ia, *iap = NULL;
618 usage(use_v4command, argv[i]);
620 local_family_set = 1;
623 if (inet_aton(argv[i], &ia)) {
626 he = gethostbyname(argv[i]);
630 iap = ((
struct in_addr *)
642 memcpy(&sp->
to.sin_addr, iap,
sizeof *iap);
647 #if defined(RELAY_PORT) && \ 648 !defined (USE_BPF_RECEIVE) && !defined (USE_LPF_RECEIVE) 650 usage(bpf_sock_support,
"-rp");
672 #ifdef HAVE_LIBCAP_NG 674 if (!keep_capabilities) {
675 capng_clear(CAPNG_SELECT_BOTH);
676 capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
677 CAP_NET_RAW, CAP_NET_BIND_SERVICE, -1);
678 capng_apply(CAPNG_SELECT_BOTH);
679 log_info (
"Dropped all unnecessary capabilities.");
693 service_local =
"bootps";
694 service_remote =
"bootpc";
695 port_local = htons(67);
696 port_remote = htons(68);
700 service_local =
"dhcpv6-server";
701 service_remote =
"dhcpv6-client";
702 port_local = htons(547);
703 port_remote = htons(546);
708 ent = getservbyname(service_local,
"udp");
714 ent = getservbyname(service_remote,
"udp");
733 sp->
to.sin_family = AF_INET;
735 sp->
to.sin_len =
sizeof sp->
to;
744 if (upstreams == NULL || downstreams == NULL) {
745 log_info(
"Must specify at least one lower " 746 "and one upper interface.\n");
758 log_fatal(
"Unable to find the RELAY_MSG " 759 "option definition.");
764 log_fatal(
"Unable to find the INTERFACE_ID " 765 "option definition.");
770 gettimeofday(&
cur_tv, NULL);
789 if (
dfd[0] != -1 &&
dfd[1] != -1) {
790 if (write(
dfd[1], &buf, 1) != 1)
792 (void) close(
dfd[1]);
799 O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC, 0644);
805 pf = fdopen(pfdesc,
"we");
810 fprintf(pf,
"%ld\n",(
long)getpid());
832 #if defined(ENABLE_GENTLE_SHUTDOWN) 839 #ifdef HAVE_LIBCAP_NG 841 if (!keep_capabilities) {
842 capng_clear(CAPNG_SELECT_BOTH);
843 capng_apply(CAPNG_SELECT_BOTH);
844 log_info (
"Dropped all capabilities.");
857 unsigned int length,
unsigned int from_port,
struct iaddr from,
860 struct sockaddr_in to;
865 log_info(
"Discarding packet with invalid hlen, received on " 866 "%s interface.",
ip->name);
869 if (
ip->address_count < 1 ||
ip->addresses == NULL) {
870 log_info(
"Discarding packet received on %s interface that " 871 "has no IPv4 address assigned.",
ip->name);
877 if (
packet->giaddr.s_addr) {
899 log_debug(
"Dropping reply received on %s",
ip->name);
905 to.sin_addr =
packet->yiaddr;
911 to.sin_addr.s_addr = htonl(INADDR_BROADCAST);
917 to.sin_family = AF_INET;
919 to.sin_len =
sizeof to;
923 hto.hbuf[0] =
packet->htype;
924 hto.hlen =
packet->hlen + 1;
931 strip_relay_agent_options(
ip, &out,
packet, length)))
935 log_error(
"Packet to bogus giaddr %s.\n",
936 inet_ntoa(
packet->giaddr));
945 log_debug(
"Forwarded BOOTREPLY for %s to %s",
948 inet_ntoa(to.sin_addr));
961 log_debug(
"Dropping request received on %s",
ip->name);
968 if (!(length = add_relay_agent_options(
ip,
packet, length,
977 if (!
packet->giaddr.s_addr)
989 NULL,
packet, length,
ip->addresses[0],
990 &sp->
to, NULL) < 0) {
993 log_debug(
"Forwarded BOOTREQUEST for %s to %s",
996 inet_ntoa(sp->
to.sin_addr));
1013 u_int8_t *op, *nextop, *sp, *max;
1014 int good_agent_option = 0;
1027 max = ((u_int8_t *)
packet) + length;
1062 nextop = op + op[1] + 2;
1066 status = find_interface_by_agent_option(
packet,
1072 good_agent_option = 1;
1082 nextop = op + op[1] + 2;
1087 memmove(sp, op, op[1] + 2);
1107 if (!good_agent_option) {
1115 length = sp -((u_int8_t *)
packet);
1142 u_int8_t *buf,
int len) {
1144 u_int8_t *circuit_id = 0;
1145 unsigned circuit_id_len = 0;
1152 i + buf[i + 1] + 2 > len) {
1165 i += buf[i + 1] + 2;
1181 if (
ip->circuit_id &&
1205 unsigned length,
struct in_addr
giaddr) {
1206 int is_dhcp = 0, mms;
1208 u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
1209 int adding_link_select;
1225 && (
packet->giaddr.s_addr == 0));
1243 if (end_pad == NULL)
1263 mms = ntohs(*(op + 2));
1266 max = ((u_int8_t *)
packet) + mms;
1309 nextop = op + op[1] + 2;
1316 memmove(sp, op, op[1] + 2);
1334 if (end_pad != NULL)
1344 if ((
ip->circuit_id_len > 255) ||(
ip->circuit_id_len < 1))
1345 log_fatal(
"Circuit ID length %d out of range [1-255] on " 1346 "%s\n",
ip->circuit_id_len,
ip->name);
1347 optlen =
ip->circuit_id_len + 2;
1349 if (
ip->remote_id) {
1350 if (
ip->remote_id_len > 255 ||
ip->remote_id_len < 1)
1351 log_fatal(
"Remote ID length %d out of range [1-255] " 1352 "on %s\n",
ip->remote_id_len,
ip->name);
1353 optlen +=
ip->remote_id_len + 2;
1356 if (adding_link_select) {
1369 if ((optlen < 3) ||(optlen > 255))
1370 log_fatal(
"Total agent option length(%u) out of range " 1371 "[3 - 255] on %s\n", optlen,
ip->name);
1377 if (max - sp >= optlen + 3) {
1378 log_debug(
"Adding %d-byte relay agent option", optlen + 3);
1386 *sp++ =
ip->circuit_id_len;
1387 memcpy(sp,
ip->circuit_id,
ip->circuit_id_len);
1388 sp +=
ip->circuit_id_len;
1391 if (
ip->remote_id) {
1393 *sp++ =
ip->remote_id_len;
1394 memcpy(sp,
ip->remote_id,
ip->remote_id_len);
1395 sp +=
ip->remote_id_len;
1401 if (adding_link_select) {
1404 memcpy(sp, &
giaddr.s_addr, 4);
1407 log_debug (
"Adding link selection suboption" 1408 " with addr: %s", inet_ntoa(
giaddr));
1420 log_error(
"No room in packet (used %d of %d) " 1421 "for %d-byte relay agent option: omitted",
1422 (
int) (sp - ((u_int8_t *)
packet)),
1423 (
int) (max - ((u_int8_t *)
packet)),
1435 length = sp -((u_int8_t *)
packet);
1450 static struct stream_list *
1451 parse_downstream(
char *arg) {
1452 struct stream_list *dp, *
up;
1454 char *ifname, *addr, *iid;
1455 isc_result_t status;
1458 (downstreams != NULL))
1459 log_fatal(
"No support for multiple interfaces.");
1462 ifname = strchr(arg,
'%');
1463 if (ifname == NULL) {
1470 iid = strchr(ifname,
'#');
1474 if (strlen(ifname) >=
sizeof(
ifp->name)) {
1475 usage(
"Interface name '%s' too long", ifname);
1479 for (dp = downstreams; dp; dp = dp->next) {
1480 if (strcmp(ifname, dp->ifp->name) == 0)
1481 log_fatal(
"Down interface '%s' declared twice.",
1486 for (
up = upstreams;
up;
up =
up->next) {
1487 if (strcmp(ifname,
up->ifp->name) == 0) {
1488 log_info(
"parse_downstream: Interface '%s' is " 1489 "both down and up.", ifname);
1497 status = interface_allocate(&
ifp,
MDL);
1498 if (status != ISC_R_SUCCESS)
1500 arg, isc_result_totext(status));
1501 strcpy(
ifp->name, ifname);
1511 dp = (
struct stream_list *)
dmalloc(
sizeof(*dp),
MDL);
1521 if (addr && (inet_pton(AF_INET6, addr, &dp->link.sin6_addr) <= 0))
1522 log_fatal(
"Bad link address '%s'", addr);
1530 static struct stream_list *
1531 parse_upstream(
char *arg) {
1532 struct stream_list *
up, *dp;
1534 char *ifname, *addr;
1535 isc_result_t status;
1538 ifname = strchr(arg,
'%');
1539 if (ifname == NULL) {
1546 if (strlen(ifname) >=
sizeof(
ifp->name)) {
1547 log_fatal(
"Interface name '%s' too long", ifname);
1551 for (
up = upstreams;
up;
up =
up->next) {
1552 if (strcmp(ifname,
up->ifp->name) == 0) {
1557 for (dp = downstreams; dp; dp = dp->next) {
1558 if (strcmp(ifname, dp->ifp->name) == 0) {
1559 log_info(
"parse_upstream: Interface '%s' is " 1560 "both down and up.", ifname);
1568 status = interface_allocate(&
ifp,
MDL);
1569 if (status != ISC_R_SUCCESS)
1571 arg, isc_result_totext(status));
1572 strcpy(
ifp->name, ifname);
1588 if (inet_pton(AF_INET6, addr, &
up->link.sin6_addr) <= 0)
1598 setup_streams(
void) {
1599 struct stream_list *dp, *
up;
1601 isc_boolean_t link_is_set;
1603 for (dp = downstreams; dp; dp = dp->next) {
1605 if (dp->ifp->v6address_count == 0)
1606 log_fatal(
"Interface '%s' has no IPv6 addresses.",
1610 if (IN6_IS_ADDR_UNSPECIFIED(&dp->link.sin6_addr))
1611 link_is_set = ISC_FALSE;
1613 link_is_set = ISC_TRUE;
1614 for (i = 0; i < dp->ifp->v6address_count; i++) {
1615 if (IN6_IS_ADDR_LINKLOCAL(&dp->ifp->v6addresses[i]))
1619 if (!memcmp(&dp->ifp->v6addresses[i],
1620 &dp->link.sin6_addr,
1621 sizeof(dp->link.sin6_addr)))
1624 if (i == dp->ifp->v6address_count)
1625 log_fatal(
"Interface %s does not have global IPv6 " 1626 "address assigned.", dp->ifp->name);
1628 memcpy(&dp->link.sin6_addr,
1629 &dp->ifp->v6addresses[i],
1630 sizeof(dp->link.sin6_addr));
1634 dp->id = dp->ifp->index;
1637 for (
up = upstreams;
up;
up =
up->next) {
1639 up->link.sin6_family = AF_INET6;
1641 up->link.sin6_len =
sizeof(
up->link);
1644 if (
up->ifp->v6address_count == 0)
1645 log_fatal(
"Interface '%s' has no IPv6 addresses.",
1651 if (IN6_IS_ADDR_MULTICAST(&
up->link.sin6_addr)) {
1660 static const int required_forw_opts[] = {
1663 #if defined(RELAY_PORT) 1674 process_up6(
struct packet *
packet,
struct stream_list *dp) {
1675 char forw_data[65535];
1679 struct stream_list *
up;
1680 u_int16_t relay_client_port = 0;
1695 log_info(
"Relaying %s from %s port %d going up.",
1707 log_info(
"Discarding %s from %s port %d going up.",
1714 log_info(
"Unknown %d type from %s port %d going up.",
1735 if (!use_if_id && downstreams->next) {
1736 log_info(
"Shan't get back the interface.");
1756 log_fatal(
"No memory for upwards options.");
1765 }
else if (!downstreams->next) {
1766 if_id = downstreams->id;
1768 log_info(
"Don't know the interface.");
1774 NULL, (
unsigned char *) &if_id,
1785 if (dhcrelay_sub_id != NULL) {
1787 (
unsigned char *) dhcrelay_sub_id,
1788 strlen(dhcrelay_sub_id),
1797 #if defined(RELAY_PORT) 1808 (
unsigned char *) &relay_client_port,
1811 log_error(
"Can't save relay-source-port.");
1818 (void)(relay_client_port);
1833 sizeof(forw_data) - cursor,
1835 required_forw_opts, NULL);
1839 for (
up = upstreams;
up;
up =
up->next) {
1841 (
size_t) cursor, &
up->link);
1850 struct stream_list *dp;
1855 #if defined(RELAY_PORT) 1858 struct sockaddr_in6 to;
1864 log_info(
"Discarding %s from %s port %d going down.",
1869 log_info(
"Unknown %d type from %s port %d going down.",
1877 memset(&relay_msg, 0,
sizeof(relay_msg));
1878 memset(&if_id, 0,
sizeof(if_id));
1879 #if defined(RELAY_PORT) 1880 memset(&down_port, 0,
sizeof(down_port));
1882 memset(&to, 0,
sizeof(to));
1883 to.sin6_family = AF_INET6;
1885 to.sin6_len =
sizeof(to);
1899 (relay_msg.len < offsetof(
struct dhcpv6_packet, options))) {
1914 (if_id.len !=
sizeof(
int))) {
1915 log_info(
"Can't evaluate interface-id.");
1918 memcpy(&if_index, if_id.data,
sizeof(
int));
1919 for (dp = downstreams; dp; dp = dp->next) {
1920 if (dp->id == if_index)
1929 for (dp = downstreams; dp; dp = dp->next) {
1931 if (!memcmp(&dp->link.sin6_addr,
1933 sizeof(
struct in6_addr)))
1938 if (!dp && downstreams && !downstreams->next)
1941 log_info(
"Can't find the down interface.");
1953 #if defined(RELAY_PORT) 1957 u_int16_t down_relay_port;
1959 memset(&down_port, 0,
sizeof(down_port));
1963 (down_port.len !=
sizeof(u_int16_t))) {
1965 "relay-source-port.");
1968 memcpy(&down_relay_port, down_port.data,
1977 if (down_relay_port) {
1978 to.sin6_port = down_relay_port;
1991 log_info(
"Relaying %s to %s port %d down.",
1994 ntohs(to.sin6_port));
2007 log_info(
"Discarding %s to %s port %d down.",
2010 ntohs(to.sin6_port));
2014 log_info(
"Unknown %d type to %s port %d down.",
2017 ntohs(to.sin6_port));
2022 send_packet6(dp->ifp, (
unsigned char *) relay_msg.data,
2023 (
size_t) relay_msg.len, &to);
2026 if (relay_msg.data != NULL)
2028 if (if_id.data != NULL)
2037 struct stream_list *dp;
2045 for (dp = downstreams; dp; dp = dp->next) {
2053 process_up6(
packet, NULL);
2057 log_info(
"Can't process packet from interface '%s'.",
2073 #if defined(DHCPv6) && defined(DHCP4o6) 2076 return ISC_R_NOTIMPLEMENTED;
2091 find_class(
struct class **
class,
const char *c1,
const char *c2,
int i) {
2092 return ISC_R_NOTFOUND;
2106 return ISC_R_SUCCESS;
2113 (void) close(
dfd[1]);
2132 void request_v4_interface(
const char* name,
int flags) {
2134 int len = strlen(
name);
2135 isc_result_t status;
2137 if (len >=
sizeof(tmp->
name)) {
2138 log_fatal(
"%s: interface name too long (is %d)",
name, len);
2141 status = interface_allocate(&tmp,
MDL);
2142 if (status != ISC_R_SUCCESS) {
2144 isc_result_totext(status));
2147 log_debug(
"Requesting: %s as upstream: %c downstream: %c",
name,
2153 interface_dereference(&tmp,
MDL);
void do_packet6(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
void(* dhcpv6_packet_handler)(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
unsigned char peer_address[16]
#define DHO_DHCP_AGENT_OPTIONS
int drop_agent_mismatches
isc_boolean_t no_dhcrelay_pid
struct tree_cache * global_options[256]
struct binding_scope * global_scope
const char * piaddr(const struct iaddr addr)
void bootp(struct packet *packet)
unsigned char options[FLEXIBLE_ARRAY_MEMBER]
void(* bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)
int check_collection(struct packet *p, struct lease *l, struct collection *c)
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
const char * dhcpv6_type_names[]
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
#define DHCPV6_RECONFIGURE
const char * path_dhcrelay_pid
isc_result_t dhcp_set_control_state(control_object_state_t oldstate, control_object_state_t newstate)
#define DHCP_CONTEXT_PRE_DB
struct in_addr * addresses
void data_string_forget(struct data_string *data, const char *file, int line)
int log_error(const char *,...) __attribute__((__format__(__printf__
#define DHCPV6_DHCPV4_QUERY
#define D6O_RELAY_SOURCE_PORT
int dhcp_max_agent_option_packet_length
struct option_state * options
unsigned char dhcpv6_hop_count
unsigned char link_address[16]
unsigned char dhcpv6_msg_type
void log_fatal(const char *,...) __attribute__((__format__(__printf__
#define DHCPV6_RELAY_REPL
#define DHCPV6_LEASEQUERY
isc_boolean_t no_pid_file
struct option * requested_opts[2]
u_int16_t validate_port(char *port)
void dhcp_signal_handler(int signal)
struct server_list * next
struct interface_info * fallback_interface
int option_state_allocate(struct option_state **ptr, const char *file, int line)
isc_result_t dhcp_context_create(int flags, struct in_addr *local4, struct in6_addr *local6)
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)
#define DHCPV6_DHCPV4_RESPONSE
enum @28 agent_relay_mode
#define _PATH_DHCRELAY6_PID
struct interface_info * interface
ssize_t send_packet6(struct interface_info *, const unsigned char *, size_t, struct sockaddr_in6 *)
#define D6O_SUBSCRIBER_ID
int parse_allow_deny(struct option_cache **oc, struct parse *p, int i)
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
#define DHCPV6_RELAY_FORW
int save_option_buffer(struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, unsigned code, int terminatep)
struct interface_info * uplink
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
int int log_info(const char *,...) __attribute__((__format__(__printf__
void * dmalloc(size_t, const char *, int)
int server_packets_relayed
struct interface_info * interfaces
void interface_snorf(struct interface_info *tmp, int ir)
void dhcp(struct packet *packet)
#define DHO_DHCP_MAX_MESSAGE_SIZE
#define DHCPV6_LEASEQUERY_REPLY
int store_options6(char *buf, int buflen, struct option_state *opt_state, struct packet *packet, const int *required_opts, struct data_string *oro)
int quiet_interface_discovery
int option_state_dereference(struct option_state **ptr, const char *file, int line)
void initialize_common_option_spaces()
void dhcpv6(struct packet *)
const int dhcpv6_type_name_max
struct interface_info * next
struct universe dhcpv6_universe
void classify(struct packet *p, struct class *c)
int supports_multiple_interfaces(struct interface_info *)
isc_result_t interface_setup()
#define INTERFACE_UPSTREAM
struct server_list * servers
void set_multicast_hop_limit(struct interface_info *info, int hop_limit)
#define INTERFACE_DOWNSTREAM
option_code_hash_t * code_hash
#define _PATH_DHCRELAY_PID
struct in6_addr dhcpv6_peer_address
int can_unicast_without_arp(struct interface_info *)
int add_rfc3527_suboption
#define DHO_DHCP_MESSAGE_TYPE
int corrupt_agent_options
#define DHCPV6_INFORMATION_REQUEST
#define INTERFACE_STREAMS
struct in6_addr dhcpv6_link_address
int main(int argc, char **argv)
void discover_interfaces(int state)
#define DHCP_OPTIONS_COOKIE
#define INTERFACE_REQUESTED
int client_packets_relayed
isc_result_t omapi_init(void)
isc_result_t find_class(struct class **class, const char *c1, const char *c2, int i)