Commit 352d236d authored by Chen Wei's avatar Chen Wei

--server mod build successfully

parent c2a3d340
......@@ -25,8 +25,10 @@
#define FNV_32_PRIME ((uint32_t)0x01000193)
#define max(A, B) ((A) > (B) ? (A) : (B))
static char buf[MAXDNAME];
/* prototypes */
static struct dict_node *add_or_replace_dictnode (struct dict_node *node, char *label);
static struct dict_node *add_or_lookup_dictnode (struct dict_node *node, char *label);
static struct dict_node *lookup_dictnode (struct dict_node *node, char *label);
static void add_dicttree (struct dict_node *node, struct dict_node *sub);
static void upsize_dicttree (struct dict_node *np);
......@@ -205,7 +207,7 @@ static void add_dicttree (struct dict_node *node, struct dict_node *sub)
/* add a new subnode to node, or update the attr of the subnode with same
* label
* return the subnode */
static struct dict_node *add_or_replace_dictnode (struct dict_node *node,
static struct dict_node *add_or_lookup_dictnode (struct dict_node *node,
char *label)
{
struct dict_node *np;
......@@ -254,13 +256,11 @@ static struct dict_node *lookup_dictnode (struct dict_node *node, char *label)
return NULL;
}
/* look up the whole domain pattern by step over DNS name hierarchy top down.
* for example, if the pattern is cn.debian.org, the lookup will start with
* org, then debian, then cn */
struct dict_node * match_domain_ipsets (struct dict_node *root, char *domain)
struct dict_node * match_domain(struct dict_node *root, char *domain)
{
char buf[MAXDNAME];
char *labels[MAXLABELS];
int i, label_num;
int len = strlen (domain);
......@@ -307,8 +307,8 @@ struct dict_node * match_domain_ipsets (struct dict_node *root, char *domain)
res = node;
}
if (res == NULL)
return NULL;
if (res == NULL)
return NULL;
return res;
}
......@@ -318,7 +318,6 @@ struct dict_node * match_domain_ipsets (struct dict_node *root, char *domain)
* com, then google, then cache */
struct dict_node * lookup_domain (struct dict_node *root, char *domain)
{
char buf[MAXDNAME];
char *labels[MAXLABELS];
int i, label_num;
int len = strlen (domain);
......@@ -354,9 +353,8 @@ struct dict_node * lookup_domain (struct dict_node *root, char *domain)
/* add a domain pattern in the form of google.com to root
* return the node with lowest hierarchy */
struct dict_node *add_domain (struct dict_node *root, char *domain)
struct dict_node *add_or_lookup_domain (struct dict_node *root, char *domain)
{
char buf[MAXDNAME];
char *labels[MAXLABELS];
int i, label_num;
int len = strlen (domain);
......@@ -383,7 +381,7 @@ struct dict_node *add_domain (struct dict_node *root, char *domain)
node = root;
for (i = label_num - 1; i >= 0; i--)
{
node = add_or_replace_dictnode (node, labels[i]);
node = add_or_lookup_dictnode (node, labels[i]);
}
return node;
......@@ -416,3 +414,54 @@ void free_dicttree (struct dict_node *node)
free (node);
}
/* temp area * */
/* only compare addr, source_addr, interface, and flags */
static inline int is_same_server(struct server *s1, struct server *s2)
{
if (memcmp(&s1->addr, &s2->addr, sizeof(union mysockaddr)) != 0)
return -1;
if (strncmp(s1->interface, s2->interface, IF_NAMESIZE + 1) != 0)
return -1;
if (s1->flags != s2->flags)
return -1;
return 0;
}
/* duplicate a struct server, but only copy addr, source_addr, interfaces, and
* flags
* return the allocated pointer */
static inline struct server *serverdup(struct server *src)
{
struct server *dst;
dst = safe_malloc(sizeof(struct server));
memcpy(dst, src, sizeof(struct server));
return dst;
}
struct server *lookup_or_install_new_server(struct server *serv)
{
struct server *res;
res = NULL;
for (res = daemon->servers; res != NULL; res = res->next) {
if (is_same_server(res, serv))
break;
}
if (res == NULL) {
res = serverdup(serv);
res->next = daemon->servers;
daemon->servers = res;
}
return res;
}
......@@ -254,6 +254,9 @@ int main (int argc, char **argv)
ipset_init();
#endif
if (daemon->dh_special_domains == NULL)
daemon->dh_special_domains = new_dictnode(NULL, 0);
#if defined(HAVE_LINUX_NETWORK)
netlink_init();
#elif defined(HAVE_BSD_NETWORK)
......
......@@ -534,6 +534,13 @@ struct dict_node {
struct dict_node **sub;
};
struct special_domain {
struct server *server;
union mysockaddr addr;
int domain_flags;
};
struct ipsets_names {
char **sets; /* ipsets names end with NULL ptr */
int count;
......@@ -965,8 +972,11 @@ extern struct daemon {
struct bogus_addr *bogus_addr, *ignore_addr;
struct server *servers;
struct ipsets *ipsets;
struct dict_node *dh_ipsets;
struct dict_node *dh_ipsets_names;
struct dict_node *dh_special_domains;
int log_fac; /* log facility */
char *log_file; /* optional log file */
int max_logs; /* queue limit */
......@@ -1392,8 +1402,9 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags,
/* dict.c */
struct dict_node *new_dictnode (char *label, int len);
struct dict_node *lookup_domain(struct dict_node *root, char *domain);
struct dict_node *match_domain_ipsets (struct dict_node *root, char *domain);
struct dict_node *add_domain (struct dict_node *root, char *domain);
struct dict_node *match_domain(struct dict_node *root, char *domain);
struct dict_node *add_or_lookup_domain (struct dict_node *root, char *domain);
struct server *lookup_or_install_new_server(struct server *serv);
void free_dicttree (struct dict_node *node);
/* helper.c */
......
This diff is collapsed.
......@@ -2210,11 +2210,74 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
case LOPT_NO_REBIND: /* --rebind-domain-ok */
//TODO fast hash lookup
{
struct server *serv, *newlist = NULL;
unhide_metas(arg);
char *start_addr;
char *err;
struct server newlist;
struct dict_node *np;
struct special_domain *obj;
memset(&newlist, 0, sizeof(struct server));
#ifdef HAVE_LOOP
newlist.uid = rand32();
#endif
if (arg == NULL)
break;
// scan the address part first
// --xxxx=/example.org/ample.com/temple.net/address-of-server
// ^
start_addr = NULL;
if (strchr(arg, '/') == NULL) {
// --xxxx=example.org (only availabe for --rebind-domain-ok)
if (option == LOPT_NO_REBIND)
newlist.flags |= SERV_NO_REBIND;
else if (option == 'S')
// --server=8.8.8.8
start_addr = arg;
} else {
for (start_addr = arg;
(start_addr = strchr(start_addr, '/')) != NULL; ) ;
start_addr++;
}
/* --xxxx=/example.org/# , here "#" means use standard server*/
if (start_addr != NULL) {
if (*start_addr == '#') {
newlist.flags |= SERV_USE_RESOLV;
/* --xxxx=/example.org/here-is-empty */
} else if (*start_addr == '\0') {
if (!(newlist.flags & SERV_NO_REBIND))
newlist.flags |= SERV_NO_ADDR; /* no server */
} else {
/* --xxxx=/example.org/8.8.8.8#53@source-ip|interface#port */
err = parse_server(arg, &newlist.addr, &newlist.source_addr, newlist.interface, &newlist.flags);
if (err)
ret_err(err);
}
}
// --server
if (servers_only && option == 'S')
newlist.flags |= SERV_FROM_FILE;
if (arg && (*arg == '/' || option == LOPT_NO_REBIND))
// --rebind-domain-ok
if (option == LOPT_NO_REBIND)
newlist.flags |= SERV_NO_REBIND;
// --address will be handled inside the domain dict_node
// the arg pattern can be
// --xxxx=example.org (only availabe for --rebind-domain-ok) or
// --xxxx=/example.org/ or
// --xxxx=/example.org/ample.com/temple.net/
if (*arg == '/' || option == LOPT_NO_REBIND)
{
int rebind = !(*arg == '/');
char *end = NULL;
......@@ -2230,75 +2293,49 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
domain = "";
else if (strlen (arg) != 0 && !(domain = canonicalise_opt(arg)))
option = '?';
serv = opt_malloc(sizeof(struct server));
memset(serv, 0, sizeof(struct server));
serv->next = newlist;
newlist = serv;
serv->domain = domain;
serv->flags = domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
np = add_or_lookup_domain(daemon->dh_special_domains, domain);
if (np->obj == NULL) {
obj = opt_malloc(sizeof(struct special_domain));
memset(obj, 0, sizeof(struct special_domain));
obj->domain_flags = 0;
} else {
obj = (struct special_domain *) np->obj;
}
if (option == 'A') {
obj->server = NULL;
obj->domain_flags = SERV_LITERAL_ADDRESS;
memcpy(&obj->addr, &newlist.addr, sizeof(union mysockaddr));
} else if (option == 'S') {
// pointer to one of servers in daemon->servers link list,
// no memory is leaked if obj->server been overwritten
obj->server = lookup_or_install_new_server(&newlist);
}
if (option == LOPT_NO_REBIND) {
// the rebind flag here instead of the one in struct server
// will be used by forward
obj->domain_flags |= SERV_NO_REBIND;
}
if (option == LOPT_LOCAL) {
obj->domain_flags |= SERV_NO_ADDR;
}
//newlist.flags |= domain ? SERV_HAS_DOMAIN : SERV_FOR_NODOTS;
np->obj = (void *) obj;
arg = end;
if (rebind)
break;
}
if (!newlist)
ret_err(gen_err);
}
else
{
newlist = opt_malloc(sizeof(struct server));
memset(newlist, 0, sizeof(struct server));
#ifdef HAVE_LOOP
newlist->uid = rand32();
#endif
}
if (servers_only && option == 'S')
newlist->flags |= SERV_FROM_FILE;
if (option == 'A')
{
newlist->flags |= SERV_LITERAL_ADDRESS;
if (!(newlist->flags & SERV_TYPE))
ret_err(gen_err);
}
else if (option == LOPT_NO_REBIND)
newlist->flags |= SERV_NO_REBIND;
if (!arg || !*arg)
{
if (!(newlist->flags & SERV_NO_REBIND))
newlist->flags |= SERV_NO_ADDR; /* no server */
if (newlist->flags & SERV_LITERAL_ADDRESS)
ret_err(gen_err);
}
else if (strcmp(arg, "#") == 0)
{
newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
if (newlist->flags & SERV_LITERAL_ADDRESS)
ret_err(gen_err);
}
else
{
char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
if (err)
ret_err(err);
}
serv = newlist;
while (serv->next)
{
serv->next->flags = serv->flags;
serv->next->addr = serv->addr;
serv->next->source_addr = serv->source_addr;
strcpy(serv->next->interface, serv->interface);
serv = serv->next;
}
serv->next = daemon->servers;
daemon->servers = newlist;
break;
break;
}
case LOPT_REV_SERV: /* --rev-server */
{
char *string;
......@@ -2368,7 +2405,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
option = '?';
if (domain != NULL)
np = add_domain (daemon->dh_ipsets, domain);
np = add_or_lookup_domain (daemon->dh_ipsets, domain);
arg = end;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment