From: Ted Lemon Date: Mon, 19 Jul 1999 01:15:22 +0000 (+0000) Subject: Brian Murrel's latest dns update implementation - more programmability. X-Git-Tag: V3-BETA-1-PATCH-2~5^2~184 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=069e9f4c158eccda7048d6549ebc81c49fde6e0f;p=thirdparty%2Fdhcp.git Brian Murrel's latest dns update implementation - more programmability. --- diff --git a/common/conflex.c b/common/conflex.c index 1d88882a7..08f89b873 100644 --- a/common/conflex.c +++ b/common/conflex.c @@ -22,7 +22,7 @@ #ifndef lint static char copyright[] = -"$Id: conflex.c,v 1.49 1999/07/16 21:33:58 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; +"$Id: conflex.c,v 1.50 1999/07/19 01:15:10 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -414,6 +414,8 @@ static enum dhcp_token intern (atom, dfv) return DDNS_FWD_NAME; if (!strcasecmp (atom + 1, "dns-rev-name")) return DDNS_REV_NAME; + if (!strcasecmp (atom + 1, "ns-update")) + return DNS_UPDATE; if (!strcasecmp (atom + 1, "omain")) return DOMAIN; if (!strcasecmp (atom + 1, "eny")) @@ -513,6 +515,8 @@ static enum dhcp_token intern (atom, dfv) return LEASE; if (!strcasecmp (atom + 1, "eased-address")) return LEASED_ADDRESS; + if (!strcasecmp (atom + 1, "lease-time")) + return LEASE_TIME; if (!strcasecmp (atom + 1, "imit")) return LIMIT; break; diff --git a/common/nsupdate.c b/common/nsupdate.c index daf3ee6a9..b6463d97c 100644 --- a/common/nsupdate.c +++ b/common/nsupdate.c @@ -25,7 +25,7 @@ #ifndef lint static char copyright[] = -"$Id: nsupdate.c,v 1.5 1999/07/18 19:37:23 mellon Exp $ Copyright (c) 1999 The Internet Software Consortium. All rights reserved.\n"; +"$Id: nsupdate.c,v 1.6 1999/07/19 01:15:11 mellon Exp $ Copyright (c) 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -38,7 +38,8 @@ static char copyright[] = necessary which can be any combination and number of remove A, add A, remove PTR, add PTR */ -/* Return the forward name of a lease. */ +#if 0 +/* Return the reverse name of a lease. */ char *ddns_rev_name(lease, state, packet) struct lease *lease; struct lease_state *state; @@ -176,8 +177,9 @@ char *ddns_fwd_name(lease, state, packet) #endif return hostname; } +#endif -int nsupdateA(hostname, ip_addr, ttl, opcode) +static int nsupdateA(hostname, ip_addr, ttl, opcode) char *hostname; char *ip_addr; u_int32_t ttl; @@ -237,7 +239,7 @@ int nsupdateA(hostname, ip_addr, ttl, opcode) return z; } -int nsupdatePTR(hostname, revname, ttl, opcode) +static int nsupdatePTR(revname, hostname, ttl, opcode) char *hostname; char *revname; u_int32_t ttl; @@ -262,6 +264,7 @@ int nsupdatePTR(hostname, revname, ttl, opcode) return z; } +#if 0 void nsupdate(lease, state, packet, opcode) struct lease *lease; struct lease_state *state; @@ -271,6 +274,7 @@ void nsupdate(lease, state, packet, opcode) char *hostname, *revname; u_int32_t ttl = 0; +return; if (!(opcode == ADD || opcode == DELETE)) return; @@ -325,7 +329,7 @@ void nsupdate(lease, state, packet, opcode) if (lease -> ddns_rev_name && (strcmp(hostname, lease -> ddns_fwd_name) || strcmp(revname, lease -> ddns_rev_name)) && - nsupdatePTR(lease -> ddns_fwd_name, revname, + nsupdatePTR(revname, lease -> ddns_fwd_name, ttl, DELETE)) { /* clear the forward DNS name pointer */ if (lease -> ddns_rev_name) @@ -366,7 +370,7 @@ void nsupdate(lease, state, packet, opcode) if (!lease -> ddns_rev_name) { /* add a PTR RR */ - if (nsupdatePTR(hostname, revname, ttl, ADD)) { + if (nsupdatePTR(revname, hostname, ttl, ADD)) { /* remember in the lease struct for a release */ lease -> ddns_rev_name = dmalloc(strlen(revname) + 1, "nsupdate"); @@ -382,8 +386,9 @@ void nsupdate(lease, state, packet, opcode) piaddr(lease->ip_addr), ttl, DELETE); if (lease -> ddns_rev_name && - nsupdatePTR(lease -> ddns_fwd_name, - lease -> ddns_rev_name, ttl, opcode)) { + nsupdatePTR(lease -> ddns_rev_name, + lease -> ddns_fwd_name, + ttl, opcode)) { /* clear the reverse DNS name pointer */ if (lease -> ddns_rev_name) dfree(lease -> ddns_rev_name, @@ -404,4 +409,95 @@ void nsupdate(lease, state, packet, opcode) return; } +#endif + +/* public function to update an A record if needed */ +int updateA(struct data_string *lhs, struct data_string *rhs, unsigned int ttl, + struct lease *lease) +{ + + static char hostname[MAXDNAME]; + static char ipaddr[MAXDNAME]; + + hostname[0] = '\0'; + strncat(hostname, lhs->data, lhs->len); + hostname[lhs->len] = '\0'; + + ipaddr[0] = '\0'; + strncat(ipaddr, rhs->data, rhs->len); + ipaddr[rhs->len] = '\0'; + + /* delete an existing A if the one to be added is different */ + if (lease -> ddns_fwd_name && + strcmp(hostname, lease -> ddns_fwd_name)) { + int y; + y=nsupdateA(lease -> ddns_fwd_name, ipaddr, 0, DELETE); + + if (y) { + /* clear the forward DNS name pointer */ + if (lease -> ddns_fwd_name) + dfree(lease -> ddns_fwd_name, "nsupdate"); + lease -> ddns_fwd_name = 0; + } + } + /* only update if there is no A record there already */ + if (!lease -> ddns_fwd_name) { + int y; + y=nsupdateA(hostname, ipaddr, ttl, ADD); + if (y < 1) + return 0; + + /* remember this in the lease structure for release */ + lease -> ddns_fwd_name = dmalloc(strlen(hostname) + 1, + "nsupdate"); + strcpy (lease -> ddns_fwd_name, hostname); + } + + return 1; +} + +/* public function to update an A record if needed */ +int updatePTR(struct data_string *lhs, struct data_string *rhs, + unsigned int ttl, struct lease *lease) +{ + + static char hostname[MAXDNAME]; + static char revname[MAXDNAME]; + + revname[0] = '\0'; + strncat(revname, lhs->data, lhs->len); + revname[lhs->len] = '\0'; + + hostname[0] = '\0'; + strncat(hostname, rhs->data, rhs->len); + hostname[rhs->len] = '\0'; + + /* delete an existing PTR if the one to be added is different */ + if (lease -> ddns_rev_name && + strcmp(revname, lease -> ddns_rev_name)) { + int y; + y=nsupdatePTR(revname, hostname, 0, DELETE); + + if (y) { + /* clear the reverse DNS name pointer */ + if (lease -> ddns_rev_name) + dfree(lease -> ddns_rev_name, "nsupdate"); + lease -> ddns_rev_name = 0; + } + } + /* only update if there is no PTR record there already */ + if (!lease -> ddns_rev_name) { + int y; + y=nsupdatePTR(revname, hostname, ttl, ADD); + if (y < 1) + return 0; + + /* remember this in the lease structure for release */ + lease -> ddns_rev_name = dmalloc(strlen(revname) + 1, + "nsupdate"); + strcpy (lease -> ddns_rev_name, revname); + } + + return 1; +} #endif /* defined (NSUPDATE) */ diff --git a/common/parse.c b/common/parse.c index fed33e134..871d679d0 100644 --- a/common/parse.c +++ b/common/parse.c @@ -22,7 +22,7 @@ #ifndef lint static char copyright[] = -"$Id: parse.c,v 1.29 1999/07/16 21:33:59 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; +"$Id: parse.c,v 1.30 1999/07/19 01:15:11 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -1883,6 +1883,67 @@ int parse_non_binary (expr, cfile, lose, context) goto norparen; break; + case DNS_UPDATE: +#if !defined (NSUPDATE) + parse_warn ("you are using dns-update() but have not compiled with the NSUPDATE switch."); + skip_to_semi (cfile); + *lose = 1; + return 0; +#endif + token = next_token (&val, cfile); + if (!expression_allocate (expr, "parse_expression: DNS_UPDATE")) + log_fatal ("can't allocate expression"); + (*expr) -> op = expr_dns_update; + + token = next_token (&val, cfile); + if (token != LPAREN) + goto nolparen; + + if (!(parse_data_expression + (&(*expr) -> data.dns_update.type, cfile, lose))) { + expression_dereference (expr, + "parse_expression: noRRtype"); + parse_warn ("expecting DNS RR type."); + skip_to_semi (cfile); + *lose = 1; + return 0; + } + + token = next_token (&val, cfile); + if (token != COMMA) + goto nocomma; + + if (!(parse_data_expression + (&(*expr) -> data.dns_update.expr1, cfile, lose))) + goto nodata; + + token = next_token (&val, cfile); + if (token != COMMA) + goto nocomma; + + if (!(parse_data_expression + (&(*expr) -> data.dns_update.expr2, cfile, lose))) + goto nodata; + + token = next_token (&val, cfile); + if (token != COMMA) + goto nocomma; + + if (!(parse_data_expression + (&(*expr) -> data.dns_update.ttl, cfile, lose))) { + expression_dereference (expr, + "parse_expression: nottl"); + parse_warn ("expecting data expression."); + skip_to_semi (cfile); + *lose = 1; + return 0; + } + + token = next_token (&val, cfile); + if (token != RPAREN) + goto norparen; + break; + case OPTION: case CONFIG_OPTION: if (!expression_allocate (expr, "parse_expression: OPTION")) @@ -1915,6 +1976,14 @@ int parse_non_binary (expr, cfile, lose, context) (*expr) -> op = expr_leased_address; break; + case LEASE_TIME: + token = next_token (&val, cfile); + if (!expression_allocate (expr, + "parse_expression: LEASED_LEASE_TIME")) + log_fatal ("can't allocate expression"); + (*expr) -> op = expr_lease_time; + break; + case HOST_DECL_NAME: token = next_token (&val, cfile); if (!expression_allocate (expr, diff --git a/common/tree.c b/common/tree.c index 466e4cbdf..3f61436f4 100644 --- a/common/tree.c +++ b/common/tree.c @@ -22,7 +22,7 @@ #ifndef lint static char copyright[] = -"$Id: tree.c,v 1.33 1999/07/16 21:33:59 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n"; +"$Id: tree.c,v 1.34 1999/07/19 01:15:11 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -386,6 +386,8 @@ int evaluate_boolean_expression (result, packet, options, lease, expr) struct expression *expr; { struct data_string left, right; + struct data_string rrtype, expr1, expr2, ttl; + int s0, s1, s2, s3; int bleft, bright; int sleft, sright; @@ -524,6 +526,48 @@ int evaluate_boolean_expression (result, packet, options, lease, expr) *result = packet -> known; return 1; + case expr_dns_update: +#if defined (NSUPDATE) + /* we only want to do this on a DHCPREQUEST */ + if (packet -> packet_type != DHCPREQUEST) + return 0; + memset (&rrtype, 0, sizeof expr1); + s0 = evaluate_data_expression (&rrtype, packet, options, lease, + expr -> data.dns_update.type); + memset (&expr1, 0, sizeof expr1); + s1 = evaluate_data_expression (&expr1, packet, options, lease, + expr -> data.dns_update.expr1); + memset (&expr2, 0, sizeof expr2); + s2 = evaluate_data_expression (&expr2, packet, options, lease, + expr -> data.dns_update.expr2); + memset (&ttl, 0, sizeof ttl); + s3 = evaluate_data_expression (&ttl, packet, options, lease, + expr -> data.dns_update.ttl); + + *result = 0; /* assume failure */ + if (s0 && s1 && s2 && s3) { + if (rrtype.len == 1 && + strncmp(rrtype.data, "a", 1) == 0) { +log_info("calling updateA(expr1, expr2, %d, lease)", atol(ttl.data)); + updateA(expr1, expr2, atol(ttl.data), lease); + } else if (rrtype.len == 3 && + strncmp(rrtype.data, "ptr", 3) == 0) { +log_info("calling updatePTR(expr1, expr2, %d, lease)", atol(ttl.data)); + updatePTR(expr1, expr2, atol(ttl.data), lease); + } + *result = 1; + } +#if defined (DEBUG_EXPRESSIONS) + log_info ("dns-update(%s, %s, %s):", + print_hex_1(rrtype.len, rrtype.data, 60), + print_hex_2(expr1.len, expr1.data, 60), + print_hex_3(expr2.len, expr2.data, 60)); +#endif + return 1; +#else + return 0; +#endif + case expr_substring: case expr_suffix: case expr_option: @@ -542,6 +586,7 @@ int evaluate_boolean_expression (result, packet, options, lease, expr) case expr_host_decl_name: case expr_config_option: case expr_leased_address: + case expr_lease_time: log_error ("Data opcode in evaluate_boolean_expression: %d", expr -> op); return 0; @@ -568,7 +613,7 @@ int evaluate_data_expression (result, packet, options, lease, expr) struct expression *expr; { struct data_string data, other; - unsigned long offset, len; + unsigned long offset, len, i; int s0, s1, s2, s3; int status; @@ -1150,6 +1195,31 @@ int evaluate_data_expression (result, packet, options, lease, expr) #endif return 1; + case expr_lease_time: + if (!lease) { + log_error ("data: leased_lease_time: not available"); + return 0; + } + i = lease -> ends - lease -> starts; + if (buffer_allocate (&result -> buffer, 11, "lease-time")) { + result -> data = &result -> buffer -> data [0]; +#if defined (NO_SNPRINTF) + snprintf(result -> data, 11, "%lu", i); +#else + snprintf(result -> data, 11, "%lu", i); +#endif + result -> len = strlen(result -> data); + result -> terminated = 0; + } else { + log_error ("data: leased-lease-time: no memory."); + return 0; + } +#if defined (DEBUG_EXPRESSIONS) + log_info ("data: leased-lease-time = %s", + print_hex_1 (result -> len, result -> data, 60)); +#endif + return 1; + case expr_check: case expr_equal: case expr_and: @@ -1271,6 +1341,7 @@ int evaluate_numeric_expression (result, packet, options, lease, expr) case expr_const_int: *result = expr -> data.const_int; return 1; + } log_error ("evaluate_numeric_expression: bogus opcode %d", expr -> op); @@ -1484,6 +1555,7 @@ void expression_dereference (eptr, name) /* No subexpressions. */ case expr_leased_address: + case expr_lease_time: case expr_const_int: case expr_check: case expr_option: @@ -1547,6 +1619,7 @@ int is_boolean_expression (expr) expr -> op == expr_equal || expr -> op == expr_and || expr -> op == expr_or || + expr -> op == expr_dns_update || expr -> op == expr_not); } @@ -1567,7 +1640,8 @@ int is_data_expression (expr) expr -> op == expr_host_lookup || expr -> op == expr_binary_to_ascii || expr -> op == expr_reverse || - expr -> op == expr_leased_address); + expr -> op == expr_leased_address || + expr -> op == expr_lease_time); } int is_numeric_expression (expr) diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 72d227f60..a8f61e0d6 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -996,7 +996,7 @@ struct lease *find_lease PROTO ((struct packet *, struct lease *mockup_lease PROTO ((struct packet *, struct shared_network *, struct host_decl *)); -void static_lease_dereference PROTO ((struct lease *)); +void static_lease_dereference PROTO ((struct lease *, char *)); struct lease *allocate_lease PROTO ((struct packet *, struct pool *, int)); int permitted PROTO ((struct packet *, struct permit *)); diff --git a/includes/dhctoken.h b/includes/dhctoken.h index 203526cd5..73626ba5a 100644 --- a/includes/dhctoken.h +++ b/includes/dhctoken.h @@ -191,6 +191,8 @@ enum dhcp_token { EXPIRY = 409, RELEASE = 410, COMMIT = 411, + DNS_UPDATE = 412, + LEASE_TIME = 413, }; #define is_identifier(x) ((x) >= FIRST_TOKEN && \ diff --git a/includes/tree.h b/includes/tree.h index b80066b4c..065f8d939 100644 --- a/includes/tree.h +++ b/includes/tree.h @@ -89,6 +89,8 @@ enum expr_op { expr_config_option, expr_host_decl_name, expr_pick_first_value, + expr_lease_time, + expr_dns_update, }; struct expression { @@ -137,6 +139,12 @@ struct expression { struct expression *car; struct expression *cdr; } pick_first_value; + struct { + struct expression *type; + struct expression *expr1; + struct expression *expr2; + struct expression *ttl; + } dns_update; } data; int flags; # define EXPR_EPHEMERAL 1 diff --git a/server/bootp.c b/server/bootp.c index eed80eb50..577890c3e 100644 --- a/server/bootp.c +++ b/server/bootp.c @@ -22,7 +22,7 @@ #ifndef lint static char copyright[] = -"$Id: bootp.c,v 1.52 1999/07/18 19:38:33 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; +"$Id: bootp.c,v 1.53 1999/07/19 01:15:22 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -268,7 +268,7 @@ void bootp (packet) /* Execute the commit statements, if there are any. */ execute_statements (packet, lease, packet -> options, - state -> options, lease -> on_commit); + options, lease -> on_commit); /* We're done with the option state. */ option_state_dereference (&options, "bootrequest"); diff --git a/server/dhcp.c b/server/dhcp.c index b7f95121a..dfe82bbe2 100644 --- a/server/dhcp.c +++ b/server/dhcp.c @@ -22,7 +22,7 @@ #ifndef lint static char copyright[] = -"$Id: dhcp.c,v 1.102 1999/07/18 19:39:14 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dhcp.c,v 1.103 1999/07/19 01:15:22 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -294,14 +294,14 @@ void dhcprelease (packet) /* If we found a lease, release it. */ if (lease) { -#if defined (NSUPDATE) +#if defined (NSUPDATE) && 0 nsupdate (lease, lease -> state, packet, DELETE); #endif /* If there are statements to execute when the lease is committed, execute them. */ if (lease -> on_release) { execute_statements (packet, lease, packet -> options, - state -> options, + (struct option_state *)0, /* XXX */ lease -> on_release); executable_statement_dereference (&lease -> on_release, "dhcprelease"); @@ -1254,10 +1254,12 @@ void ack_lease (packet, lease, offer, when, msg) hanging off the lease. */ /* why not update for static leases too? */ /* Because static leases aren't currently recorded? */ +/* XXX #if defined (NSUPDATE) if (!(lease -> flags & STATIC_LEASE) && offer == DHCPACK) nsupdate (lease, state, packet, ADD); #endif +*/ /* If there are statements to execute when the lease is committed, execute them. */