⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dnsrv.c

📁 jabber server jabber server jabber server jabber server
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -------------------------------------------------------------------------- * * License * * The contents of this file are subject to the Jabber Open Source License * Version 1.0 (the "JOSL").  You may not copy or use this file, in either * source code or executable form, except in compliance with the JOSL. You * may obtain a copy of the JOSL at http://www.jabber.org/ or at * http://www.opensource.org/.   * * Software distributed under the JOSL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the JOSL * for the specific language governing rights and limitations under the * JOSL. * * Copyrights *  * Portions created by or assigned to Jabber.com, Inc. are  * Copyright (c) 1999-2002 Jabber.com, Inc.  All Rights Reserved.  Contact * information for Jabber.com, Inc. is available at http://www.jabber.com/. * * Portions Copyright (c) 1998-1999 Jeremie Miller. *  * Acknowledgements *  * Special thanks to the Jabber Open Source Contributors for their * suggestions and support of Jabber. *  * Alternatively, the contents of this file may be used under the terms of the * GNU General Public License Version 2 or later (the "GPL"), in which case * the provisions of the GPL are applicable instead of those above.  If you * wish to allow use of your version of this file only under the terms of the * GPL and not to allow others to use your version of this file under the JOSL, * indicate your decision by deleting the provisions above and replace them * with the notice and other provisions required by the GPL.  If you do not * delete the provisions above, a recipient may use your version of this file * under either the JOSL or the GPL.  *  *  * --------------------------------------------------------------------------*//** * @file dnsrv.c * @brief implements the main part of the DNS resolver component * * Config format: * <dnsrv xmlns='jabber:config:dnsrv'> *     <resend service="_jabber._tcp">s2s-component</resend> * </dnsrv> * * Note: You must specify the services in the order you want them tried */#include "jabberd.h"#include "srv_resolv.h"#include <sys/wait.h>#ifdef LIBIDN#  include <idna.h>#endif/** * @brief structure to build a list that holds all hosts to which the packets are resent for a service */typedef struct __dns_resend_list_host_list {    char *host;    int weight;    struct __dns_resend_list_host_list *next;} *dns_resend_list_host_list, _dns_resend_list_host_list;/** * struct to store list of services and resend hosts */typedef struct __dns_resend_list {     char* service;			/**< the service that is defined */     dns_resend_list_host_list hosts;	/**< resend to which hosts */     int weight_sum;			/**< sum of weights of the hosts */     struct __dns_resend_list* next;	/**< next entry in the list */} *dns_resend_list, _dns_resend_list;/** * struct to keep track of a DNS coprocess */typedef struct {     int             in;		 /**< Inbound data handle */     int             out;		 /**< Outbound data handle */     int             pid;		 /**< Coprocess PID */     xht	     packet_table;	 /**< Hash of dns_packet_lists */     int             packet_timeout;	 /**< how long to keep packets in the queue */     xht       	     cache_table;	 /**< Hash of resolved IPs */     int             cache_timeout;	 /**< how long to keep resolutions in the cache */     pool            mempool;		 /**< memory pool to use */     dns_resend_list svclist;		 /**< list of defined services */} *dns_io, _dns_io;/** * prototype for the resolver function * * @param di pointer to the instance global data */typedef int (*RESOLVEFUNC)(dns_io di);/** * struct to store list of dpackets which need to be delivered */typedef struct __dns_packet_list {     dpacket           packet;		/**< the dpacket list item */     int               stamp;		/**< timestamp */     struct __dns_packet_list* next;	/**< next list entry */} *dns_packet_list, _dns_packet_list;/** * signal handler: just die after any signal * * @param sig the signal number that has been sent */void _dnsrv_signal(int sig){    exit(0);}/** * coprocess functionality */void dnsrv_child_process_xstream_io(int type, xmlnode x, void* args) {     dns_io di = (dns_io)args;     char *hostname, *ascii_hostname = NULL;     char *str = NULL;     dns_resend_list iternode = NULL;     if (type == XSTREAM_NODE)     {	  /* Get the hostname out... */	  hostname = xmlnode_get_data(x);	  log_debug2(ZONE, LOGT_IO, "dnsrv: Recv'd lookup request for %s", hostname);	  if (hostname != NULL)	  {#ifdef LIBIDN	      if (idna_to_ascii_8z(hostname, &ascii_hostname, 0) == IDNA_SUCCESS)	      {		  log_debug2(ZONE, LOGT_IO, "dnsrv: IDN conversion %s to %s", hostname, ascii_hostname);		  hostname = ascii_hostname;	      }#endif	       /* For each entry in the svclist, try and resolve using		  the specified service and resend it to the specified host */	       iternode = di->svclist;	       while (iternode != NULL)	       {		    str = srv_lookup(x->p, iternode->service, hostname);		    if (str != NULL)		    {			 dns_resend_list_host_list iterhost = iternode->hosts;			 /* play the dice, to select one of the s2s hosts */			 /* XXX should we statically distribute to the hosts using a hash over the destination? */			 int host_die = iternode->weight_sum <= 1 ? 0 : rand()%(iternode->weight_sum);			 /* find the host selected by our host_die */			 while (host_die >= iterhost->weight && iterhost->next != NULL) {			     /* try next host */			     host_die -= iterhost->weight;			     iterhost = iterhost->next;			 }			 log_debug2(ZONE, LOGT_IO, "Resolved %s(%s): %s\tresend to:%s", hostname, iternode->service, str, iterhost->host);			 xmlnode_put_attrib(x, "ip", str);			 xmlnode_put_attrib(x, "to", iterhost->host);			 break;		    }		    iternode = iternode->next;	       }               str = xmlnode2str(x);	       write(di->out, str, strlen(str));#ifdef LIBIDN	       if (ascii_hostname != NULL)		   free(ascii_hostname);#endif          }     }     xmlnode_free(x);}int dnsrv_child_main(dns_io di){     pool    p   = pool_new();     xstream xs  = xstream_new(p, dnsrv_child_process_xstream_io, di);     int     len;     char    readbuf[1024];     log_debug2(ZONE, LOGT_INIT, "DNSRV CHILD: starting");     /* Transmit stream header */     write(di->out, "<stream>", 8);     /* Loop forever, processing requests and feeding them to the xstream*/          while (1)     {       len = read(di->in, &readbuf, 1024);       if (len <= 0)       {           log_debug2(ZONE, LOGT_IO|LOGT_STRANGE, "dnsrv: Read error on coprocess(%d): %d %s",getppid(),errno,strerror(errno));           break;       }       log_debug2(ZONE, LOGT_IO, "DNSRV CHILD: Read from buffer: %.*s",len,readbuf);       if (xstream_eat(xs, readbuf, len) > XSTREAM_NODE)       {           log_debug2(ZONE, LOGT_IO|LOGT_STRANGE, "DNSRV CHILD: xstream died");           break;       }     }     /* child is out of loop... normal exit so parent will start us again */     log_debug2(ZONE, LOGT_STRANGE|LOGT_CLEANUP, "DNSRV CHILD: out of loop.. exiting normal");     pool_free(p);     exit(0);     return 0;}/* Core functionality */int dnsrv_fork_and_capture(RESOLVEFUNC f, dns_io di){     int left_fds[2], right_fds[2];     int pid;     /* Create left and right pipes */     if (pipe(left_fds) < 0 || pipe(right_fds) < 0)	  return -1;     pid = fork();     if (pid < 0)	  return -1;     else if (pid > 0)		/* Parent */     {	  /* Close unneeded file handles */	  close(left_fds[STDIN_FILENO]);	  close(right_fds[STDOUT_FILENO]);	  /* Return the in and out file descriptors */	  di->in = right_fds[STDIN_FILENO];	  di->out = left_fds[STDOUT_FILENO];          /* Transmit root element to coprocess */          pth_write(di->out, "<stream>", 8);	  return pid;     }     else			/* Child */     {          /* set up the new process */          pth_kill();	  signal(SIGHUP,_dnsrv_signal);	  signal(SIGINT,_dnsrv_signal);	  signal(SIGTERM,_dnsrv_signal);	  close(left_fds[STDOUT_FILENO]);	  close(right_fds[STDIN_FILENO]);	  /* Start the specified function, passing the in/out descriptors */	  di->in = left_fds[STDIN_FILENO]; di->out = right_fds[STDOUT_FILENO];	  return (*f)(di);     }}void dnsrv_resend(xmlnode pkt, char *ip, char *to){    if(ip != NULL)    {	 /* maybe the packet as a query by a component, that wants to get the result back to itself */	 /* this is needed for handling db:verify by the s2s component: if the component is clustered,	  * the result for the db:verify packet has to be the s2s component that verifies the db */	 char *dnsresultto = xmlnode_get_attrib(pkt, "dnsqueryby");	 if (dnsresultto == NULL)	     dnsresultto = to;	 log_debug2(ZONE, LOGT_IO, "delivering DNS result to: %s", dnsresultto);         pkt = xmlnode_wrap(pkt,"route");	 xmlnode_put_attrib(pkt, "to", dnsresultto);	 xmlnode_put_attrib(pkt, "ip", ip);    }else{	 jutil_error_xmpp(pkt, (xterror){502, "Unable to resolve hostname.","wait","service-unavailable"});	 xmlnode_put_attrib(pkt, "iperror", "");    }    deliver(dpacket_new(pkt),NULL);}/* Hostname lookup requested */void dnsrv_lookup(dns_io d, dpacket p){    dns_packet_list l, lnew;    xmlnode req;    char *reqs;    /* make sure we have a child! */    if(d->out <= 0)    {        deliver_fail(p, "DNS Resolver Error");        return;    }    /* Attempt to lookup this hostname in the packet table */    l = (dns_packet_list)xhash_get(d->packet_table, p->host);    /* IF: hashtable has the hostname, a lookup is already pending,       so push the packet on the top of the list (most recent at the top) */    if (l != NULL)    {	 log_debug2(ZONE, LOGT_IO, "dnsrv: Adding lookup request for %s to pending queue.", p->host);	 lnew = pmalloco(p->p, sizeof(_dns_packet_list));	 lnew->packet = p;	 lnew->stamp = time(NULL);	 lnew->next = l;         xhash_put(d->packet_table, p->host, lnew);         return;    }    /* insert the packet into the packet_table using the hostname       as the key and send a request to the coprocess */    log_debug2(ZONE, LOGT_IO, "dnsrv: Creating lookup request queue for %s", p->host);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -