283 lines
7.3 KiB
Diff
283 lines
7.3 KiB
Diff
|
|
diff --git a/lib/dns/dispatch.c b/lib/dns/dispatch.c
|
||
|
|
index c93651d..d03ef2d 100644
|
||
|
|
--- a/lib/dns/dispatch.c
|
||
|
|
+++ b/lib/dns/dispatch.c
|
||
|
|
@@ -49,6 +49,7 @@
|
||
|
|
#include <dns/tcpmsg.h>
|
||
|
|
#include <dns/types.h>
|
||
|
|
|
||
|
|
+const char *conffile = "/etc/dns_port.conf";
|
||
|
|
typedef ISC_LIST(dns_dispentry_t) dns_displist_t;
|
||
|
|
|
||
|
|
typedef struct dispsocket dispsocket_t;
|
||
|
|
@@ -1933,6 +1934,168 @@ open_socket(isc_socketmgr_t *mgr, isc_sockaddr_t *local,
|
||
|
|
return (ISC_R_SUCCESS);
|
||
|
|
}
|
||
|
|
|
||
|
|
+static int convert_num(char *str)
|
||
|
|
+{
|
||
|
|
+ int negative = 0;
|
||
|
|
+ int tval;
|
||
|
|
+ int val = 0;
|
||
|
|
+ int base = 10;
|
||
|
|
+ char *ptr = str;
|
||
|
|
+ if (str == NULL)
|
||
|
|
+ return -ISC_R_FAILURE;
|
||
|
|
+
|
||
|
|
+ if (*ptr == '-') {
|
||
|
|
+ negative = 1;
|
||
|
|
+ ++ptr;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ do {
|
||
|
|
+ tval = *ptr++;
|
||
|
|
+ /* XXX assumes ASCII... */
|
||
|
|
+ if (tval >= '0')
|
||
|
|
+ tval -= '0';
|
||
|
|
+ else {
|
||
|
|
+ syslog (LOG_ERR, "Bogus number: %s.", str);
|
||
|
|
+ return -ISC_R_BADNUMBER;
|
||
|
|
+ }
|
||
|
|
+ if (tval >= base) {
|
||
|
|
+ syslog (LOG_ERR, "Bogus number: %s.", str);
|
||
|
|
+ return -ISC_R_BADNUMBER;
|
||
|
|
+ }
|
||
|
|
+ val = val * base + tval;
|
||
|
|
+ } while (*ptr);
|
||
|
|
+
|
||
|
|
+ if (negative)
|
||
|
|
+ val = -val;
|
||
|
|
+ return val;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+static int str_token(char *str, int *digit, unsigned int len, const char *semi)
|
||
|
|
+{
|
||
|
|
+ int num = 0;
|
||
|
|
+ char *p;
|
||
|
|
+ p = strtok(str, semi);
|
||
|
|
+ while (p !=NULL) {
|
||
|
|
+ if (num >= len-1) {
|
||
|
|
+ digit[num] = '\0';
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
+ /* convert string to integer */
|
||
|
|
+ digit[num] = convert_num(p);
|
||
|
|
+ if (digit[num] < 0)
|
||
|
|
+ return -ISC_R_BADNUMBER;
|
||
|
|
+
|
||
|
|
+ p = strtok(NULL, semi);
|
||
|
|
+ num++;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return num;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+static int parse_port_config(const char *buffer, const char *sub_buf, int *ports, unsigned int len, const char *semi)
|
||
|
|
+{
|
||
|
|
+ char *str;
|
||
|
|
+ char string[256] = {0};
|
||
|
|
+ int start, end;
|
||
|
|
+ int ret = -ISC_R_DISABLED;
|
||
|
|
+
|
||
|
|
+ if (str = strstr(buffer, sub_buf)) {
|
||
|
|
+ start = strlen(sub_buf);
|
||
|
|
+ end = strlen(str);
|
||
|
|
+ strncpy(string, str + start, end - start -1);
|
||
|
|
+ /* string segmentation with semi character */
|
||
|
|
+ ret = str_token(string, ports, len, semi);
|
||
|
|
+ if (ret < 0)
|
||
|
|
+ return -ISC_R_BADNUMBER;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return ret;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+static isc_result_t
|
||
|
|
+parse_config(const char *file, in_port_t *port_lo, in_port_t *port_hi, in_port_t *no_use_ports)
|
||
|
|
+{
|
||
|
|
+ FILE *fp;
|
||
|
|
+ char *str = NULL;
|
||
|
|
+ char buffer[256] = {0};
|
||
|
|
+ int ports[8] = {0};
|
||
|
|
+ int unports[17] = {0};
|
||
|
|
+ int i = 0;
|
||
|
|
+ int ret;
|
||
|
|
+
|
||
|
|
+ fp = fopen(file, "r");
|
||
|
|
+ if (fp) {
|
||
|
|
+ while (fgets(buffer, 256, fp)) {
|
||
|
|
+ const char *buffer_s = buffer;
|
||
|
|
+ str = buffer;
|
||
|
|
+ /* skip the comment line */
|
||
|
|
+ while (isspace(*str))
|
||
|
|
+ str++;
|
||
|
|
+ if (strncmp(str, "#", 1) == 0)
|
||
|
|
+ continue;
|
||
|
|
+ /* get default set of dispatch ports */
|
||
|
|
+ ret = parse_port_config(buffer_s, "dns-range-port", ports, 8, " ");
|
||
|
|
+ if (ret == 2) {
|
||
|
|
+ *port_lo = (in_port_t)ports[0];
|
||
|
|
+ *port_hi = (in_port_t)ports[1];
|
||
|
|
+ if (*port_lo < 1024 || *port_hi > 65535 || *port_lo > *port_hi) {
|
||
|
|
+ syslog(LOG_ERR,
|
||
|
|
+ "Unexpected ports contents in %s file.", file);
|
||
|
|
+ fclose(fp);
|
||
|
|
+ fp = NULL;
|
||
|
|
+ return ISC_R_INVALIDFILE;
|
||
|
|
+ }
|
||
|
|
+ } else if (ret != -ISC_R_DISABLED){
|
||
|
|
+ syslog(LOG_ERR,
|
||
|
|
+ "Unexpected ports contents in %s file.", file);
|
||
|
|
+ fclose(fp);
|
||
|
|
+ fp = NULL;
|
||
|
|
+ return ISC_R_INVALIDFILE;
|
||
|
|
+ }
|
||
|
|
+ /* get excluded ports */
|
||
|
|
+ ret = parse_port_config(buffer_s, "dns-excluded-ports", unports, 17, " ");
|
||
|
|
+ if (ret > 0) {
|
||
|
|
+ while (unports[i] != '\0') {
|
||
|
|
+ no_use_ports[i] = (in_port_t)unports[i];
|
||
|
|
+ i++;
|
||
|
|
+ }
|
||
|
|
+ } else if (ret != -ISC_R_DISABLED) {
|
||
|
|
+ syslog(LOG_ERR,
|
||
|
|
+ "Unexpected ports contents in %s file.", file);
|
||
|
|
+ fclose(fp);
|
||
|
|
+ fp = NULL;
|
||
|
|
+ return ISC_R_INVALIDFILE;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ fclose(fp);
|
||
|
|
+ fp = NULL;
|
||
|
|
+ return ISC_R_SUCCESS;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ syslog(LOG_ERR,
|
||
|
|
+ "Open %s fail, return.\n", file);
|
||
|
|
+ return ISC_R_FILENOTFOUND;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+/*%
|
||
|
|
+ * Create a temporary port list to set the initial default set of dispatch
|
||
|
|
+ * ports and excluded ports. This is almost meaningless as the application will
|
||
|
|
+ * normally set the ports explicitly, but is provided to fill some minor corner
|
||
|
|
+ * cases.
|
||
|
|
+ */
|
||
|
|
+static isc_result_t
|
||
|
|
+create_portset_by_range(isc_mem_t *mctx, isc_portset_t **portsetp, in_port_t port_lo, in_port_t port_hi, in_port_t *no_use_ports) {
|
||
|
|
+ isc_result_t result;
|
||
|
|
+
|
||
|
|
+ result = isc_portset_create(mctx, portsetp);
|
||
|
|
+ if (result != ISC_R_SUCCESS)
|
||
|
|
+ return (result);
|
||
|
|
+ isc_portset_addrange_by_range(*portsetp, port_lo, port_hi, no_use_ports);
|
||
|
|
+
|
||
|
|
+ return (ISC_R_SUCCESS);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/*%
|
||
|
|
* Create a temporary port list to set the initial default set of dispatch
|
||
|
|
* ports: [1024, 65535]. This is almost meaningless as the application will
|
||
|
|
@@ -1963,6 +2125,9 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
|
||
|
|
isc_result_t result;
|
||
|
|
isc_portset_t *v4portset = NULL;
|
||
|
|
isc_portset_t *v6portset = NULL;
|
||
|
|
+ in_port_t port_lo = 1024;
|
||
|
|
+ in_port_t port_hi = 65535;
|
||
|
|
+ in_port_t no_use_ports[17] = {0};
|
||
|
|
|
||
|
|
REQUIRE(mctx != NULL);
|
||
|
|
REQUIRE(mgrp != NULL && *mgrp == NULL);
|
||
|
|
@@ -2063,14 +2228,23 @@ dns_dispatchmgr_create(isc_mem_t *mctx, isc_entropy_t *entropy,
|
||
|
|
mgr->nv6ports = 0;
|
||
|
|
mgr->magic = DNS_DISPATCHMGR_MAGIC;
|
||
|
|
|
||
|
|
- result = create_default_portset(mctx, &v4portset);
|
||
|
|
+ /* parse port list file, get default set of dispatch ports and excluded ports */
|
||
|
|
+ result = parse_config(conffile, &port_lo, &port_hi, no_use_ports);
|
||
|
|
if (result == ISC_R_SUCCESS) {
|
||
|
|
- result = create_default_portset(mctx, &v6portset);
|
||
|
|
- if (result == ISC_R_SUCCESS) {
|
||
|
|
- result = dns_dispatchmgr_setavailports(mgr,
|
||
|
|
- v4portset,
|
||
|
|
- v6portset);
|
||
|
|
- }
|
||
|
|
+ create_portset_by_range(mctx, &v4portset, port_lo, port_hi, no_use_ports);
|
||
|
|
+ if (result == ISC_R_SUCCESS)
|
||
|
|
+ result = create_portset_by_range(mctx, &v6portset, port_lo, port_hi, no_use_ports);
|
||
|
|
+ }
|
||
|
|
+ else {
|
||
|
|
+ result = create_default_portset(mctx, &v4portset);
|
||
|
|
+ if (result == ISC_R_SUCCESS)
|
||
|
|
+ result = create_default_portset(mctx, &v6portset);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (result == ISC_R_SUCCESS) {
|
||
|
|
+ result = dns_dispatchmgr_setavailports(mgr,
|
||
|
|
+ v4portset,
|
||
|
|
+ v6portset);
|
||
|
|
}
|
||
|
|
if (v4portset != NULL)
|
||
|
|
isc_portset_destroy(mctx, &v4portset);
|
||
|
|
diff --git a/lib/isc/include/isc/portset.h b/lib/isc/include/isc/portset.h
|
||
|
|
index 774d6bb..cfd0bcb 100644
|
||
|
|
--- a/lib/isc/include/isc/portset.h
|
||
|
|
+++ b/lib/isc/include/isc/portset.h
|
||
|
|
@@ -125,6 +125,19 @@ isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
|
||
|
|
*/
|
||
|
|
|
||
|
|
void
|
||
|
|
+isc_portset_addrange_by_range(isc_portset_t *portset, in_port_t port_lo,
|
||
|
|
+ in_port_t port_hi, in_port_t *no_use_ports);
|
||
|
|
+/*%<
|
||
|
|
+ * Add a subset of [port_lo, port_hi] (inclusive) and no_use_ports(exclusive) to the portset. Ports in the
|
||
|
|
+ * subset may or may not be stored in portset.
|
||
|
|
+ *
|
||
|
|
+ * Requires:
|
||
|
|
+ *\li 'portlist' to be valid.
|
||
|
|
+ *\li port_lo <= port_hi
|
||
|
|
+ *\li no_use_ports > 0
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
|
||
|
|
in_port_t port_hi);
|
||
|
|
/*%<
|
||
|
|
diff --git a/lib/isc/portset.c b/lib/isc/portset.c
|
||
|
|
index 471ca8e..0ebd79f 100644
|
||
|
|
--- a/lib/isc/portset.c
|
||
|
|
+++ b/lib/isc/portset.c
|
||
|
|
@@ -128,6 +128,31 @@ isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
+isc_portset_addrange_by_range(isc_portset_t *portset, in_port_t port_lo,
|
||
|
|
+ in_port_t port_hi, in_port_t *no_use_ports)
|
||
|
|
+{
|
||
|
|
+ in_port_t p;
|
||
|
|
+ int i, flag;
|
||
|
|
+ REQUIRE(portset != NULL);
|
||
|
|
+ REQUIRE(port_lo <= port_hi);
|
||
|
|
+
|
||
|
|
+ p = port_lo;
|
||
|
|
+ do {
|
||
|
|
+ i = 0;
|
||
|
|
+ flag = 0;
|
||
|
|
+ while (no_use_ports[i] != '\0') {
|
||
|
|
+ if (no_use_ports[i] == p) {
|
||
|
|
+ flag = 1;
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
+ i++;
|
||
|
|
+ }
|
||
|
|
+ if (flag == 0)
|
||
|
|
+ portset_add(portset, p);
|
||
|
|
+ } while (p++ < port_hi);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
|
||
|
|
in_port_t port_hi)
|
||
|
|
{
|