92 lease_reference(retval, newest,
MDL);
98 const struct lease *newest,
99 u_int32_t *associated_ips,
100 unsigned int associated_ips_size) {
102 const struct lease *p;
115 if (cnt < associated_ips_size) {
116 memcpy(&associated_ips[cnt],
118 sizeof(associated_ips[cnt]));
135 struct lease *tmp_lease;
137 int want_associated_ip;
139 u_int32_t assoc_ips[40];
140 const int nassoc_ips =
sizeof(assoc_ips) /
sizeof(assoc_ips[0]);
142 unsigned char dhcpMsgType;
143 const char *dhcp_msg_type_name;
145 struct group *relay_group;
148 int allow_leasequery;
150 u_int32_t lease_duration;
151 u_int32_t time_renewal;
152 u_int32_t time_rebinding;
153 u_int32_t time_expiry;
154 u_int32_t client_last_transaction_time;
155#if defined(RELAY_PORT)
158 struct sockaddr_in to;
159 struct in_addr siaddr;
171 snprintf(msgbuf,
sizeof(msgbuf),
183 log_info(
"%s: missing giaddr, ciaddr is %s, no reply sent",
209 log_error(
"No memory for option state.");
210 log_info(
"%s: out of memory, no reply sent", msgbuf);
229 allow_leasequery = 0;
241 if (!allow_leasequery) {
242 log_info(
"%s: LEASEQUERY not allowed, query ignored", msgbuf);
259 lease = tmp_lease = NULL;
260 if (memcmp(cip.
iabuf,
"\0\0\0", 4)) {
262 want_associated_ip = 0;
264 snprintf(dbg_info,
sizeof(dbg_info),
"IP %s",
piaddr(cip));
270 want_associated_ip = 1;
278 memset(&uid, 0,
sizeof(uid));
311 assoc_ip_cnt = get_associated_ips(tmp_lease,
320 log_info(
"%s: hardware length too long, "
321 "no reply sent", msgbuf);
341 assoc_ip_cnt = get_associated_ips(tmp_lease,
349 lease_dereference(&tmp_lease,
MDL);
361 if (want_associated_ip && (assoc_ip_cnt > nassoc_ips)) {
362 log_info(
"%d IP addresses associated with %s, "
363 "only %d sent in reply.",
364 assoc_ip_cnt, dbg_info, nassoc_ips);
372 snprintf(msgbuf,
sizeof(msgbuf),
373 "DHCPLEASEQUERY from %s for %s",
381 dhcp_msg_type_name =
"DHCPLEASEUNKNOWN";
385 dhcp_msg_type_name =
"DHCPLEASEACTIVE";
388 dhcp_msg_type_name =
"DHCPLEASEUNASSIGNED";
418 log_error(
"%s: out of memory, no reply sent", msgbuf);
443 log_info(
"%s: out of memory, no reply sent",
460 (lease_duration / 2);
462 (lease_duration / 2) +
463 (lease_duration / 4) +
464 (lease_duration / 8);
467 time_renewal = htonl(time_renewal -
cur_time);
472 sizeof(time_renewal))) {
475 log_info(
"%s: out of memory, no reply sent",
482 time_rebinding = htonl(time_rebinding -
cur_time);
487 sizeof(time_rebinding))) {
490 log_info(
"%s: out of memory, no reply sent",
502 sizeof(time_expiry))) {
505 log_info(
"%s: out of memory, no reply sent",
515 memset(&vendor_class, 0,
sizeof(vendor_class));
518 "vendor-class-identifier")) {
521 (
void *)vendor_class.
data,
527 "class identifier, no reply "
567 client_last_transaction_time =
570 client_last_transaction_time = htonl(0);
574 &client_last_transaction_time,
575 sizeof(client_last_transaction_time))) {
578 log_info(
"%s: out of memory, no reply sent",
587 if (want_associated_ip && (assoc_ip_cnt > 0)) {
591 assoc_ip_cnt *
sizeof(assoc_ips[0]))) {
594 log_info(
"%s: out of memory, no reply sent",
613 sizeof(dhcpMsgType))) {
616 log_info(
"%s: error adding option, no reply sent", msgbuf);
634 memset(&prl, 0,
sizeof(prl));
672 to.sin_family = AF_INET;
674 to.sin_len =
sizeof(to);
676 memset(to.sin_zero, 0,
sizeof(to.sin_zero));
678#if defined(RELAY_PORT)
687#if defined(RELAY_PORT)
709 log_info(
"%s to %s for %s (%d associated IPs)",
711 inet_ntoa(to.sin_addr), dbg_info, assoc_ip_cnt);
745 struct packet *packet;
746 struct data_string client_id;
747 struct data_string server_id;
748 struct data_string lq_query;
750 struct in6_addr link_addr;
751 struct option_state *query_opts;
753 struct option_state *reply_opts;
756 unsigned char data[65536];
757 struct dhcpv6_packet reply;
764static const int required_opts_lq[] = {
773static const int required_opt_CLIENT_DATA[] = {
785get_lq_query(
struct lq6_state *lq)
794 if ((lq_query->
data != NULL) || (lq_query->
len != 0)) {
800 return ISC_R_NOTFOUND;
806 return ISC_R_FAILURE;
817valid_query_msg(
struct lq6_state *lq) {
829 "client identifier missing",
834 log_error(
"Error processing %s from %s; "
835 "unable to evaluate Client Identifier",
847 "server identifier found "
848 "(CLIENTID %s, SERVERID %s)",
852 lq->client_id.data, 60),
854 lq->server_id.data, 60));
857 "server identifier found "
861 lq->client_id.data, 60),
867 switch (get_lq_query(lq)) {
871 log_debug(
"Discarding %s from %s; lq-query missing",
876 log_error(
"Error processing %s from %s; "
877 "unable to evaluate LQ-Query",
899set_error(
struct lq6_state *lq, u_int16_t code,
const char *message) {
903 memset(&d, 0,
sizeof(d));
904 d.len =
sizeof(code) + strlen(message);
906 log_fatal(
"set_error: no memory for status code.");
908 d.data = d.buffer->data;
910 memcpy(d.buffer->data +
sizeof(code), message, d.len -
sizeof(code));
912 d.buffer, (
unsigned char *)d.data, d.len,
914 log_error(
"set_error: error saving status code.");
927process_lq_by_address(
struct lq6_state *lq) {
932 struct in6_addr addr;
945 "No OPTION_IAADDR.")) {
946 log_error(
"process_lq_by_address: unable "
947 "to set MalformedQuery status code.");
952 memset(&data, 0,
sizeof(data));
955 lq->query_opts, NULL,
958 log_error(
"process_lq_by_address: error evaluating IAADDR.");
961 memcpy(&addr, data.data,
sizeof(addr));
972 "Address not in a pool.")) {
973 log_error(
"process_lq_by_address: unable "
974 "to set NotConfigured status code.");
980 if (iasubopt_hash_lookup(&iaaddr,
pool->leases, &addr,
981 sizeof(addr),
MDL) == 0) {
996 "no memory for option state.");
1004 NULL, (
unsigned char *)data.data, data.len,
1006 log_error(
"process_lq_by_address: error saving client ID.");
1013 log_error(
"process_lq_by_address: no memory for ia-addr.");
1016 data.data = data.buffer->data;
1017 memcpy(data.buffer->data, &iaaddr->
addr, 16);
1018 lifetime = iaaddr->
prefer;
1019 putULong(data.buffer->data + 16, lifetime);
1020 lifetime = iaaddr->
valid;
1021 putULong(data.buffer->data + 20, lifetime);
1023 NULL, (
unsigned char *)data.data, data.len,
1025 log_error(
"process_lq_by_address: error saving ia-addr.");
1030 lifetime = htonl(iaaddr->
ia->
cltt);
1032 NULL, (
unsigned char *)&lifetime, 4,
1034 log_error(
"process_lq_by_address: error saving clt time.");
1041 opt_cursor = lq->cursor;
1048 sizeof(lq->buf) - lq->cursor,
1049 opt_state, lq->packet,
1050 required_opt_CLIENT_DATA, NULL);
1052 putUShort(lq->buf.data + opt_cursor + 2,
1053 lq->cursor - (opt_cursor + 4));
1059 if (data.data != NULL)
1065 if (opt_state != NULL)
1076 static struct lq6_state lq;
1084 memset(&lq.client_id, 0,
sizeof(lq.client_id));
1085 memset(&lq.server_id, 0,
sizeof(lq.server_id));
1086 memset(&lq.lq_query, 0,
sizeof(lq.lq_query));
1087 lq.query_opts = NULL;
1088 lq.reply_opts = NULL;
1094 if (!valid_query_msg(&lq)) {
1102 log_error(
"dhcpv6_leasequery: no memory for option state.");
1106 lq.packet->options, lq.reply_opts,
1111 memcpy(lq.buf.reply.transaction_id,
1112 lq.packet->dhcpv6_transaction_id,
1113 sizeof(lq.buf.reply.transaction_id));
1135 log_info(
"dhcpv6_leasequery: not allowed, query ignored.");
1148 if (lq.server_id.data == NULL)
1153 (
unsigned char *)lq.server_id.data,
1158 "error saving server identifier.");
1165 lq.client_id.buffer,
1166 (
unsigned char *)lq.client_id.data,
1171 "error saving client identifier.");
1183 "OPTION_LQ_QUERY too short.")) {
1185 "to set MalformedQuery status code.");
1191 lq.query_type = lq.lq_query.data [0];
1192 memcpy(&lq.link_addr, lq.lq_query.data + 1,
sizeof(lq.link_addr));
1193 switch (lq.query_type) {
1198 "QUERY_BY_CLIENTID not supported.")) {
1199 log_error(
"dhcpv6_leasequery: unable to "
1200 "set UnknownQueryType status code.");
1206 "Unknown query-type.")) {
1207 log_error(
"dhcpv6_leasequery: unable to "
1208 "set UnknownQueryType status code.");
1215 log_error(
"dhcpv6_leasequery: no memory for option state.");
1222 log_error(
"dhcpv6_leasequery: error parsing query-options.");
1224 "Bad query-options.")) {
1226 "to set MalformedQuery status code.");
1233 if (!process_lq_by_address(&lq))
1239 sizeof(lq.buf) - lq.cursor,
1246 reply_ret->
len = lq.cursor;
1247 reply_ret->
buffer = NULL;
1249 log_fatal(
"dhcpv6_leasequery: no memory to store Reply.");
1251 memcpy(reply_ret->
buffer->
data, lq.buf.data, lq.cursor);
1256 if (lq.packet != NULL)
1258 if (lq.client_id.data != NULL)
1260 if (lq.server_id.data != NULL)
1262 if (lq.lq_query.data != NULL)
1264 if (lq.query_opts != NULL)
1266 if (lq.reply_opts != NULL)
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
void data_string_forget(struct data_string *data, const char *file, int line)
int option_chain_head_reference(struct option_chain_head **ptr, struct option_chain_head *bp, 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 packet_reference(struct packet **ptr, struct packet *bp, const char *file, int line)
int packet_dereference(struct packet **ptr, const char *file, int line)
void data_string_copy(struct data_string *dest, const struct data_string *src, 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)
int get_option(struct data_string *result, struct universe *universe, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct option_state *options, struct binding_scope **scope, unsigned code, const char *file, int line)
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)
int add_option(struct option_state *options, unsigned int option_num, void *data, unsigned int data_len)
int parse_option_buffer(struct option_state *options, const unsigned char *buffer, unsigned length, struct universe *universe)
int cons_options(struct packet *inpacket, struct dhcp_packet *outpacket, struct lease *lease, struct client_state *client_state, int mms, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, int overload_avail, int terminate, int bootpp, struct data_string *prl, const char *vuname)
char * print_hw_addr(int htype, const int hlen, const unsigned char *data) const
void putUShort(unsigned char *, u_int32_t)
void putULong(unsigned char *, u_int32_t)
int find_subnet(struct subnet **sp, struct iaddr addr, const char *file, int line)
#define D6O_LQ_RELAY_DATA
#define D6O_LQ_CLIENT_LINK
#define STATUS_NotConfigured
#define STATUS_UnknownQueryType
#define STATUS_MalformedQuery
#define LQ6QT_BY_CLIENTID
#define DHCPV6_LEASEQUERY_REPLY
#define DHO_DHCP_PARAMETER_REQUEST_LIST
#define DHO_VENDOR_CLASS_IDENTIFIER
#define DHO_CLIENT_LAST_TRANSACTION_TIME
#define DHO_DHCP_CLIENT_IDENTIFIER
#define DHO_ASSOCIATED_IP
#define DHO_PXE_CLIENT_ID
#define DHO_DHCP_MESSAGE_TYPE
#define DHCPLEASEUNASSIGNED
#define DHO_DHCP_RENEWAL_TIME
#define DHO_DHCP_REBINDING_TIME
#define DHO_DHCP_LEASE_TIME
u_int16_t dhcp_check_relayport(struct packet *packet)
void dhcpv6_leasequery(struct data_string *, struct packet *)
isc_result_t get_client_id(struct packet *, struct data_string *)
struct universe agent_universe
int find_lease_by_uid(struct lease **, const unsigned char *, unsigned, const char *, int)
void copy_server_duid(struct data_string *ds, const char *file, int line)
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
int find_lease_by_hw_addr(struct lease **, const unsigned char *, unsigned, const char *, int)
struct universe server_universe
struct universe dhcp_universe
#define print_hex_2(len, data, limit)
isc_result_t find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type, const struct in6_addr *addr)
int find_lease_by_ip_addr(struct lease **, struct iaddr, const char *, int)
isc_result_t ipv6_pool_dereference(struct ipv6_pool **pool, const char *file, int line)
de-reference an IPv6 pool structure.
isc_result_t iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line)
void get_server_source_address(struct in_addr *from, struct option_state *options, struct option_state *out_options, struct packet *packet)
#define print_hex_1(len, data, limit)
void get_newest_lease(struct lease **retval, struct lease *lease, struct lease *(*next)(const struct lease *))
void dhcpleasequery(struct packet *packet, int ms_nulltp)
struct interface_info * fallback_interface
void execute_statements_in_scope(struct binding_value **result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *out_options, struct binding_scope **scope, struct group *group, struct group *limiting_group, struct on_star *on_star)
const char * piaddr(const struct iaddr addr)
struct group * root_group
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__
#define DHCP_R_INVALIDARG
const unsigned char * data
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
struct data_string iaid_duid
struct binding_scope * scope
struct hardware hardware_addr
struct option_chain_head * agent_options
binding_state_t binding_state
unsigned char dhcpv6_msg_type
struct interface_info * interface
struct option_state * options
struct class * classes[PACKET_MAX_CLASSES]
const char * dhcpv6_type_names[]
struct universe dhcpv6_universe
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)
int evaluate_boolean_option_cache(int *ignorep, 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
int find_bound_string(struct data_string *value, struct binding_scope *scope, const char *name)