Skip to content

Instantly share code, notes, and snippets.

@mimuret
Last active August 24, 2016 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mimuret/e68b57561dc76214555c0d9718e9ce4d to your computer and use it in GitHub Desktop.
Save mimuret/e68b57561dc76214555c0d9718e9ce4d to your computer and use it in GitHub Desktop.
manabu-s:~/git/nsd-4.1.11rc2 (master) $ git diff -b 6000ec5d39c409dc3eede9d6e4517f82063e5ea7
diff --git a/configlexer.lex b/configlexer.lex
index d536352..914afa8 100644
--- a/configlexer.lex
+++ b/configlexer.lex
@@ -273,6 +273,7 @@ max-refresh-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MAX_REFRESH_TIM
min-refresh-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MIN_REFRESH_TIME;}
max-retry-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MAX_RETRY_TIME;}
min-retry-time{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MIN_RETRY_TIME;}
+multi-master-check{COLON} { LEXOUT(("v(%s) ", yytext)); return VAR_MULTI_MASTER_CHECK;}
{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++;}
/* Quoted strings. Strip leading and ending quotes */
diff --git a/configparser.y b/configparser.y
index c036c15..17c2c46 100644
--- a/configparser.y
+++ b/configparser.y
@@ -71,6 +71,7 @@ extern config_parser_state_t* cfg_parser;
%token VAR_ROUND_ROBIN VAR_ZONESTATS VAR_REUSEPORT VAR_VERSION
%token VAR_MAX_REFRESH_TIME VAR_MIN_REFRESH_TIME
%token VAR_MAX_RETRY_TIME VAR_MIN_RETRY_TIME
+%token VAR_MULTI_MASTER_CHECK
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -602,7 +603,7 @@ zone_config_item: zone_zonefile | zone_allow_notify | zone_request_xfr |
zone_outgoing_interface | zone_allow_axfr_fallback | include_pattern |
zone_rrl_whitelist | zone_zonestats | zone_max_refresh_time |
zone_min_refresh_time | zone_max_retry_time | zone_min_retry_time |
- zone_size_limit_xfr;
+ zone_size_limit_xfr | zone_multi_master_check;
pattern_name: VAR_NAME STRING
{
OUTYY(("P(pattern_name:%s)\n", $2));
@@ -871,6 +872,15 @@ zone_min_retry_time: VAR_MIN_RETRY_TIME STRING
cfg_parser->current_pattern->min_retry_time_is_default = 0;
}
};
+zone_multi_master_check: VAR_MULTI_MASTER_CHECK STRING
+ {
+ OUTYY(("P(zone_multi_master_check:%s)\n", $2));
+#ifdef MULTI_MASTER_CHECK
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->current_pattern->multi_master_check = (strcmp($2, "yes")==0);
+#endif
+ }
/* key: declaration */
keystart: VAR_KEY
diff --git a/configure.ac b/configure.ac
index a47ae02..8937d40 100644
--- a/configure.ac
+++ b/configure.ac
@@ -792,6 +792,15 @@ case "$enable_ratelimit_default_is_off" in
esac
AC_SUBST(ratelimit_default)
+AC_ARG_ENABLE(multi_master_check, AC_HELP_STRING([--enable-multi-master-check], [Enable multi master xfr check]))
+case "$enable_ratelimit" in
+ yes)
+ AC_DEFINE_UNQUOTED([MULTI_MASTER_CHECK], [], [Define this to enable multi master check.])
+ ;;
+ *)
+ ;;
+esac
+AC_SUBST(multi_master_check)
# we need SSL for TSIG (and maybe also for NSEC3).
CHECK_SSL
diff --git a/nsd-checkconf.c b/nsd-checkconf.c
index b7afdd1..6de41b6 100644
--- a/nsd-checkconf.c
+++ b/nsd-checkconf.c
@@ -320,6 +320,9 @@ config_print_zone(nsd_options_t* opt, const char* k, int s, const char *o,
#ifdef RATELIMIT
ZONE_GET_RRL(rrl_whitelist, o, zone->pattern);
#endif
+#ifdef MULTI_MASTER_CHECK
+ ZONE_GET_BIN(multi_master_check, o, zone->pattern);
+#endif
printf("Zone option not handled: %s %s\n", z, o);
exit(1);
} else if(pat) {
@@ -350,6 +353,9 @@ config_print_zone(nsd_options_t* opt, const char* k, int s, const char *o,
#ifdef RATELIMIT
ZONE_GET_RRL(rrl_whitelist, o, p);
#endif
+#ifdef MULTI_MASTER_CHECK
+ ZONE_GET_BIN(multi_master_check, o, p);
+#endif
printf("Pattern option not handled: %s %s\n", pat, o);
exit(1);
} else {
@@ -437,6 +443,9 @@ static void print_zone_content_elems(pattern_options_t* pat)
#endif
print_acl("allow-notify:", pat->allow_notify);
print_acl("request-xfr:", pat->request_xfr);
+#ifdef MULTI_MASTER_CHECK
+ printf("\tmulti-master-check: %s\n", pat->multi_master_check?"yes":"no");
+#endif
if(!pat->notify_retry_is_default)
printf("\tnotify-retry: %d\n", pat->notify_retry);
print_acl("notify:", pat->notify);
diff --git a/nsd.conf.sample.in b/nsd.conf.sample.in
index cda7dd0..87e88b8 100644
--- a/nsd.conf.sample.in
+++ b/nsd.conf.sample.in
@@ -263,6 +263,9 @@ remote-control:
#min-refresh-time: 0
#max-retry-time: 1209600
#min-retry-time: 0
++ # Slave server tries a zone transfer to all masters.
++ # Default is no, if use this option, compiled with --enable-multi-master-check.
++ # multi-master-check: no
# limit the zone transfer size (in bytes), stops very large transfers
# 0 is no limits enforced.
diff --git a/options.c b/options.c
index 328be62..b2c1ee6 100644
--- a/options.c
+++ b/options.c
@@ -834,6 +834,9 @@ pattern_options_create(region_type* region)
#ifdef RATELIMIT
p->rrl_whitelist = 0;
#endif
+#ifdef MULTI_MASTER_CHECK
+ p->multi_master_check = 0;
+#endif
return p;
}
@@ -964,6 +967,9 @@ copy_pat_fixed(region_type* region, pattern_options_t* orig,
#ifdef RATELIMIT
orig->rrl_whitelist = p->rrl_whitelist;
#endif
+#ifdef MULTI_MASTER_CHECK
+ orig->multi_master_check = p->multi_master_check;
+#endif
}
void
@@ -1049,6 +1055,9 @@ pattern_options_equal(pattern_options_t* p, pattern_options_t* q)
#ifdef RATELIMIT
if(p->rrl_whitelist != q->rrl_whitelist) return 0;
#endif
+#ifdef MULTI_MASTER_CHECK
+ if(!booleq(p->multi_master_check,q->multi_master_check)) return 0;
+#endif
if(p->size_limit_xfr != q->size_limit_xfr) return 0;
return 1;
}
@@ -1208,6 +1217,9 @@ pattern_options_marshal(struct buffer* b, pattern_options_t* p)
marshal_u8(b, p->max_retry_time_is_default);
marshal_u32(b, p->min_retry_time);
marshal_u8(b, p->min_retry_time_is_default);
+#ifdef MULTI_MASTER_CHECK
+ marshal_u8(b, p->multi_master_check);
+#endif
}
pattern_options_t*
@@ -1239,6 +1251,9 @@ pattern_options_unmarshal(region_type* r, struct buffer* b)
p->max_retry_time_is_default = unmarshal_u8(b);
p->min_retry_time = unmarshal_u32(b);
p->min_retry_time_is_default = unmarshal_u8(b);
+#ifdef MULTI_MASTER_CHECK
+ p->multi_master_check = unmarshal_u8(b);
+#endif
return p;
}
@@ -1979,6 +1994,10 @@ config_apply_pattern(const char* name)
pat->provide_xfr);
append_acl(&a->outgoing_interface, &cfg_parser->
current_outgoing_interface, pat->outgoing_interface);
+#ifdef MULTI_MASTER_CHECK
+ if(pat->multi_master_check)
+ a->multi_master_check = pat->multi_master_check;
+#endif
}
void
diff --git a/options.h b/options.h
index e0f749c..1bf339b 100644
--- a/options.h
+++ b/options.h
@@ -163,6 +163,9 @@ struct pattern_options {
uint32_t min_retry_time;
uint8_t min_retry_time_is_default;
uint64_t size_limit_xfr;
+#ifdef MULTI_MASTER_CHECK
+ uint8_t multi_master_check;
+#endif
};
#define PATTERN_IMPLICIT_MARKER "_implicit_"
diff --git a/xfrd-tcp.c b/xfrd-tcp.c
index 9bc01d3..7777398 100644
--- a/xfrd-tcp.c
+++ b/xfrd-tcp.c
@@ -870,6 +870,13 @@ xfrd_tcp_read(struct xfrd_tcp_pipeline* tp)
tp->num_skip++;
/* fall through to remove zone from tp */
case xfrd_packet_transfer:
+#ifdef MULTI_MASTER_CHECK
+ if(zone->zone_options->pattern->multi_master_check) {
+ xfrd_tcp_release(xfrd->tcp_set, zone);
+ xfrd_make_request(zone);
+ break;
+ }
+#endif
xfrd_tcp_release(xfrd->tcp_set, zone);
assert(zone->round_num == -1);
break;
diff --git a/xfrd.c b/xfrd.c
index 0eacce7..2091ec7 100644
--- a/xfrd.c
+++ b/xfrd.c
@@ -437,6 +437,10 @@ xfrd_init_slave_zone(xfrd_state_t* xfrd, zone_options_t* zone_opt)
xzone->udp_waiting = 0;
xzone->is_activated = 0;
+#ifdef MULTI_MASTER_CHECK
+ xzone->multi_master_first_master = -1;
+ xzone->multi_master_update_check = -1;
+#endif
tsig_create_record_custom(&xzone->tsig, NULL, 0, 0, 4);
/* set refreshing anyway, if we have data it may be old */
@@ -875,9 +879,30 @@ xfrd_make_request(xfrd_zone_t* zone)
DEBUG(DEBUG_XFRD,1, (LOG_INFO,
"xfrd zone %s makereq wait_retry, rd %d mr %d nx %d",
zone->apex_str, zone->round_num, zone->master_num, zone->next_master));
+#ifdef MULTI_MASTER_CHECK
+ zone->multi_master_first_master = -1;
+#endif
+ return;
+ }
+ }
+#ifdef MULTI_MASTER_CHECK
+ if(zone->zone_options->pattern->multi_master_check) {
+ if(zone->multi_master_first_master == zone->master_num && zone->round_num > 0 && zone->state != xfrd_zone_expired) {
+ /* tried all servers and update zone */
+ if(zone->multi_master_update_check >= 0) {
+ VERBOSITY(2, (LOG_INFO, "xfrd: multi master check: zone %s complite transfers",zone->apex_str));
+ }
+ zone->round_num = -1; /* next try start anew */
+ zone->multi_master_first_master = -1;
+ xfrd_set_timer_refresh(zone);
return;
}
+ if(zone->multi_master_first_master < 0) {
+ zone->multi_master_first_master = zone->master_num;
+ zone->multi_master_update_check = -1;
+ }
}
+#endif
/* cache ixfr_disabled only for XFRD_NO_IXFR_CACHE time */
if (zone->master->ixfr_disabled &&
@@ -1267,6 +1292,13 @@ xfrd_udp_read(xfrd_zone_t* zone)
xfrd_tcp_obtain(xfrd->tcp_set, zone);
break;
case xfrd_packet_transfer:
+#ifdef MULTI_MASTER_CHECK
+ if(zone->zone_options->pattern->multi_master_check) {
+ xfrd_udp_release(zone);
+ xfrd_make_request(zone);
+ break;
+ }
+#endif
case xfrd_packet_newlease:
/* nothing more to do */
assert(zone->round_num == -1);
@@ -1835,7 +1867,14 @@ xfrd_parse_received_xfr_packet(xfrd_zone_t* zone, buffer_type* packet,
zone->soa_disk_acquired = xfrd_time();
if(zone->soa_nsd.serial == soa->serial)
zone->soa_nsd_acquired = xfrd_time();
+#ifdef MULTI_MASTER_CHECK
+ if(zone->zone_options->pattern->multi_master_check) {
+ region_destroy(tempregion);
+ return xfrd_packet_drop;
+ }
+#endif
xfrd_set_zone_state(zone, xfrd_zone_ok);
DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: zone %s is ok",
zone->apex_str));
if(zone->soa_notified_acquired == 0) {
@@ -2048,6 +2087,13 @@ xfrd_handle_received_xfr_packet(xfrd_zone_t* zone, buffer_type* packet)
DEBUG(DEBUG_XFRD,1, (LOG_INFO,
"xfrd: zone %s is waiting for reload",
zone->apex_str));
+#ifdef MULTI_MASTER_CHECK
+ if(zone->zone_options->pattern->multi_master_check) {
+ zone->multi_master_update_check = zone->master_num;
+ xfrd_set_reload_timeout();
+ return xfrd_packet_transfer;
+ }
+#endif
zone->round_num = -1; /* next try start anew */
xfrd_set_timer_refresh(zone);
xfrd_set_reload_timeout();
diff --git a/xfrd.h b/xfrd.h
index ff903db..5ebf9be 100644
--- a/xfrd.h
+++ b/xfrd.h
@@ -217,6 +217,10 @@ struct xfrd_zone {
tsig_record_type tsig; /* tsig state for IXFR/AXFR */
uint64_t xfrfilenumber; /* identifier for file to store xfr into,
valid if msg_seq_nr nonzero */
+#ifdef MULTI_MASTER_CHECK
+ int multi_master_first_master; /* >0: first check master_num */
+ int multi_master_update_check; /* -1: not update >0: last update master_num */
+#endif
};
enum xfrd_packet_result {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment