Exemplo n.º 1
0
struct ResolvQuery *
resolv_query(const char *hostname, void (*client_cb)(struct sockaddr *, void *),
             void (*client_free_cb)(void *), void *client_cb_data,
             uint16_t port)
{
    struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;

    /*
     * Wrap udns's call back in our own
     */
    struct ResolvQuery *cb_data = ss_malloc(sizeof(struct ResolvQuery));
    if (cb_data == NULL) {
        LOGE("Failed to allocate memory for DNS query callback data.");
        return NULL;
    }
    memset(cb_data, 0, sizeof(struct ResolvQuery));

    cb_data->client_cb      = client_cb;
    cb_data->client_free_cb = client_free_cb;
    cb_data->client_cb_data = client_cb_data;
    memset(cb_data->queries, 0, sizeof(cb_data->queries));
    cb_data->response_count = 0;
    cb_data->responses      = NULL;
    cb_data->port           = port;

    /* Submit A and AAAA queries */
    if (resolv_mode != MODE_IPV6_ONLY) {
        cb_data->queries[0] = dns_submit_a4(ctx,
                                            hostname, 0,
                                            dns_query_v4_cb, cb_data);
        if (cb_data->queries[0] == NULL) {
            LOGE("Failed to submit DNS query: %s",
                 dns_strerror(dns_status(ctx)));
        }
    }

    if (resolv_mode != MODE_IPV4_ONLY) {
        cb_data->queries[1] = dns_submit_a6(ctx,
                                            hostname, 0,
                                            dns_query_v6_cb, cb_data);
        if (cb_data->queries[1] == NULL) {
            LOGE("Failed to submit DNS query: %s",
                 dns_strerror(dns_status(ctx)));
        }
    }

    if (all_queries_are_null(cb_data)) {
        if (cb_data->client_free_cb != NULL) {
            cb_data->client_free_cb(cb_data->client_cb_data);
        }
        ss_free(cb_data);
    }

    return cb_data;
}
Exemplo n.º 2
0
EAPI int
ecore_con_info_get(Ecore_Con_Server *svr,
                   Ecore_Con_Info_Cb done_cb,
                   void *data,
                   struct addrinfo *hints)
{
   Ecore_Con_DNS *dns;
   int error = 0;

   dns = calloc(1, sizeof(Ecore_Con_DNS));
   if (!dns) return 0;

   dns->svr = svr;
   dns->done_cb = done_cb;
   dns->data = data;

   if (hints)
     memcpy(&dns->hints, hints, sizeof(struct addrinfo));

   if (!(dns->resolv = dns_res_open(resconf, hosts, dns_hints_mortal(dns_hints_local(resconf, &error)), NULL, dns_opts(), &error)))
     {
        ERR("res_open: %s", dns_strerror(error));
        goto reserr;

     }

   error = _dns_addrinfo_get(dns, svr->ecs ? svr->ecs->ip : svr->name, dns->svr->ecs ? dns->svr->ecs->port : dns->svr->port);
   if (error && (error != EAGAIN))
     {
        ERR("resolver: %s", dns_strerror(error));
        goto seterr;
     }

   switch (_ecore_con_dns_check(dns))
     {
      case 0:
        break;
      case 1:
        dns->fdh = ecore_main_fd_handler_add(dns_ai_pollfd(dns->ai), dns_ai_events(dns->ai), (Ecore_Fd_Cb)_dns_fd_cb, dns, NULL, NULL);
        svr->infos = eina_list_append(svr->infos, dns);
        dns->timer = ecore_timer_add(5.0, (Ecore_Task_Cb)_dns_timer_cb, dns);
        break;
      default:
        return 0;
     }

   return 1;
seterr:
   if (dns->resolv) dns_res_close(dns_res_mortal(dns->resolv));
reserr:
   free(dns);
   return 0;
}
Exemplo n.º 3
0
struct ResolvQuery *
resolv_query(const char *hostname, void (*client_cb)(struct Address *, void *), void (*client_free_cb)(void *), void *client_cb_data) {
    struct dns_ctx *ctx = (struct dns_ctx *)resolv_io_watcher.data;

    /*
     * Wrap udns's call back in our own
     */
    struct ResolvQuery *cb_data = malloc(sizeof(struct ResolvQuery));
    if (cb_data == NULL) {
        err("Failed to allocate memory for DNS query callback data.");
        return NULL;
    }
    cb_data->client_cb = client_cb;
    cb_data->client_free_cb = client_free_cb;
    cb_data->client_cb_data = client_cb_data;

    /* Just resolving A records for now */
    cb_data->query = dns_submit_a4(ctx,
            hostname, 0,
            dns_query_cb, cb_data);
    if (cb_data->query == NULL) {
        err("Failed to submit DNS query: %s", dns_strerror(dns_status(ctx)));
        cb_data->client_free_cb(cb_data->client_cb_data);
        free(cb_data);
        return NULL;
    }

    return cb_data;
}
Exemplo n.º 4
0
static void dnserror(struct rblookup *ipl, const char *what) {
  char buf[4*4];
  error(0, "unable to %s for %s (%s): %s",
          what, dns_ntop(AF_INET, &ipl->key, buf, sizeof(buf)),
          ipl->zone, dns_strerror(dns_status(0)));
  ++failures;
}
Exemplo n.º 5
0
static void namecb(struct dns_ctx *ctx, struct dns_rr_a4 *rr, void *data) {
  struct ipcheck *ipc = data;
  if (rr) {
    submit_a_queries(ipc, rr->dnsa4_nrr, rr->dnsa4_addr);
    free(rr);
  }
  else
    fprintf(stderr, "%s: unable to lookup %s: %s\n",
            progname, ipc->name, dns_strerror(dns_status(ctx)));
}
Exemplo n.º 6
0
static int submit(struct ipcheck *ipc) {
  struct in_addr addr;
  if (inet_aton(ipc->name, &addr)) {
    submit_a_queries(ipc, 1, &addr);
    ipc->name = NULL;
  }
  else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc))
    fprintf(stderr, "%s: unable to submit name query for %s: %s\n",
            progname, ipc->name, dns_strerror(dns_status(0)));
  return 0;
}
Exemplo n.º 7
0
static void namecb(struct dns_ctx *ctx, struct dns_rr_a4 *rr, void *data) {
  struct ipcheck *ipc = data;
  if (rr) {
    submit_a_queries(ipc, rr->dnsa4_nrr, rr->dnsa4_addr);
    free(rr);
  }
  else {
    error(0, "unable to lookup `%s': %s",
          ipc->name, dns_strerror(dns_status(ctx)));
    ++failures;
  }
}
Exemplo n.º 8
0
/*
 * Wrapper for client callback we provide to udns
 */
static void
dns_query_cb(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data) {
    struct ResolvQuery *cb_data = (struct ResolvQuery *)data;
    struct Address *address = NULL;

    if (result == NULL) {
        info("resolv: %s\n", dns_strerror(dns_status(ctx)));
    } else if (result->dnsa4_nrr > 0) {
        struct sockaddr_in sa = {
            .sin_family = AF_INET,
            .sin_port = 0,
            .sin_addr = result->dnsa4_addr[0],
        };

        address = new_address_sa((struct sockaddr *)&sa, sizeof(sa));
        if (address == NULL)
            err("Failed to allocate memory for DNS query result address");
    }

    cb_data->client_cb(address, cb_data->client_cb_data);

    cb_data->client_free_cb(cb_data->client_cb_data);
    free(cb_data);
    free(result);
    free(address);
}

/*
 * DNS timeout callback
 */
static void
resolv_timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents) {
    struct dns_ctx *ctx = (struct dns_ctx *)w->data;

    dns_timeouts(ctx, 30, ev_now(loop));
}

/*
 * Callback to setup DNS timeout callback
 */
static void
dns_timer_setup_cb(struct dns_ctx *ctx, int timeout, void *data) {
    struct ev_loop *loop = (struct ev_loop *)data;

    if (ev_is_active(&resolv_timeout_watcher))
        ev_timer_stop(loop, &resolv_timeout_watcher);

    if (ctx != NULL && timeout >= 0) {
        ev_timer_set(&resolv_timeout_watcher, timeout, 0.0);
        ev_timer_start(loop, &resolv_timeout_watcher);
    }
}
Exemplo n.º 9
0
static int submit(struct ipcheck *ipc) {
  struct in_addr addr;
  if (dns_pton(AF_INET, ipc->name, &addr) > 0) {
    submit_a_queries(ipc, 1, &addr);
    ipc->name = NULL;
  }
  else if (!dns_submit_a4(0, ipc->name, 0, namecb, ipc)) {
    error(0, "unable to submit name query for %s: %s\n",
          ipc->name, dns_strerror(dns_status(0)));
    ++failures;
  }
  return 0;
}
Exemplo n.º 10
0
void
printtxtlist (const char *msg, ptr<txtlist> t, int dns_errno)
{
  if (msg)
    printf ("%s (txtlist):\n", msg);

  if (!t) {
    printf ("   Error: %s\n", dns_strerror (dns_errno));
    return;
  }

  printf ("    Name: %s\n", t->t_name);
  for (int i = 0; i < t->t_ntxt; i++)
    printf ("     TXT: %s\n", t->t_txts[i]);
}
Exemplo n.º 11
0
int
ecore_con_info_init(void)
{
   int err;
   if (_ecore_con_dns_init) return ++_ecore_con_dns_init;

   resconf = dns_resconf_local(&err);
   if (!resconf)
     {
        ERR("resconf_open: %s", dns_strerror(err));
        return 0;
     }
   hosts = dns_hosts_local(&err);
   if (!hosts)
     {
        ERR("hosts_open: %s", dns_strerror(err));
        dns_resconf_close(resconf);
        resconf = NULL;
        return 0;
     }
   /* this is super slow don't do it */
   //resconf->options.recurse = 1;
   return ++_ecore_con_dns_init;
}
Exemplo n.º 12
0
static void
dns_query_v6_cb(struct dns_ctx *ctx, struct dns_rr_a6 *result, void *data)
{
    struct ResolvQuery *cb_data = (struct ResolvQuery *)data;

    if (result == NULL) {
        if (verbose) {
            LOGI("IPv6 resolv: %s", dns_strerror(dns_status(ctx)));
        }
    } else if (result->dnsa6_nrr > 0) {
        struct sockaddr **new_responses = ss_realloc(cb_data->responses,
                                                     (cb_data->response_count +
                                                      result->dnsa6_nrr) *
                                                     sizeof(struct sockaddr *));
        if (new_responses == NULL) {
            LOGE("Failed to allocate memory for additional DNS responses");
        } else {
            cb_data->responses = new_responses;

            for (int i = 0; i < result->dnsa6_nrr; i++) {
                struct sockaddr_in6 *sa = ss_malloc(sizeof(struct sockaddr_in6));
                memset(sa, 0, sizeof(struct sockaddr_in6));
                sa->sin6_family = AF_INET6;
                sa->sin6_port   = cb_data->port;
                sa->sin6_addr   = result->dnsa6_addr[i];

                cb_data->responses[cb_data->response_count] =
                    (struct sockaddr *)sa;
                if (cb_data->responses[cb_data->response_count] == NULL) {
                    LOGE(
                        "Failed to allocate memory for DNS query result address");
                } else {
                    cb_data->response_count++;
                }
            }
        }
    }

    ss_free(result);
    cb_data->queries[1] = NULL; /* mark AAAA query as being completed */

    /* Once all queries have completed, call client callback */
    if (all_queries_are_null(cb_data)) {
        return process_client_callback(cb_data);
    }
}
Exemplo n.º 13
0
void
printmxlist (const char *msg, ptr<mxlist> m, int dns_errno)
{
  int i;

  if (msg)
    printf ("%s (mxlist):\n", msg);

  if (!m) {
    printf ("    Error: %s\n", dns_strerror (dns_errno));
    return;
  }

  printf ("     Name: %s\n", m->m_name);
  for (i = 0; i < m->m_nmx; i++)
    printf ("       MX: %3d %s\n", m->m_mxes[i].pref, m->m_mxes[i].name);
  printhints (m->m_hints);
}
Exemplo n.º 14
0
void
printsrvlist (const char *msg, ptr<srvlist> s, int dns_errno)
{
  int i;

  if (msg)
    printf ("%s (srvlist):\n", msg);

  if (!s) {
    printf ("   Error: %s\n", dns_strerror (dns_errno));
    return;
  }

  printf ("    Name: %s\n", s->s_name);
  for (i = 0; i < s->s_nsrv; i++)
    printf ("     SRV: %3d %3d %3d %s\n", s->s_srvs[i].prio,
	    s->s_srvs[i].weight, s->s_srvs[i].port, s->s_srvs[i].name);
  printhints (s->s_hints);
}
Exemplo n.º 15
0
void
printaddrs (const char *msg, ptr<hostent> h, int dns_errno)
{
  char **aliases;
  struct in_addr **addrs;

  if (msg)
    printf ("%s (hostent):\n", msg);

  if (! h) {
    printf ("   Error: %s\n", dns_strerror (dns_errno));
    return;
  }

  aliases = h->h_aliases;
  addrs = (struct in_addr **) h->h_addr_list;

  printf ("    Name: %s\n", h->h_name);
  while (*aliases)
    printf ("   Alias: %s\n", *aliases++);
  while (*addrs)
    printf (" Address: %s\n", inet_ntoa (**addrs++));
}
Exemplo n.º 16
0
static void dnserror(struct rblookup *ipl, const char *what) {
  fprintf(stderr, "%s: unable to %s for %s (%s): %s\n",
          progname, what, inet_ntoa(ipl->key), ipl->zone,
          dns_strerror(dns_status(0)));
  ++failures;
}
Exemplo n.º 17
0
static void dns_cb(struct dns_ctx *ctx, void *result, void *data) {
  int r = dns_status(ctx);
  int len, i;
  struct dns_check_info *ci = data;
  struct dns_parse p;
  struct dns_rr rr;
  unsigned nrr;
  unsigned char dn[DNS_MAXDN];
  const unsigned char *pkt, *cur, *end;
  char *result_str[MAX_RR] = { NULL };
  char *result_combined = NULL;

  /* If out ci isn't active, we must have timed out already */
  if(!__isactive_ci(ci)) {
    if(result) free(result);
    return;
  }

  ci->timed_out = 0;
  /* If we don't have a result, explode */
  if (!result) {
    ci->error = strdup(dns_strerror(r));
    goto cleanup;
  }

  /* Process the packet */
  pkt = result; end = pkt + r; cur = dns_payload(pkt);
  dns_getdn(pkt, &cur, end, dn, sizeof(dn));
  dns_initparse(&p, NULL, pkt, cur, end);
  p.dnsp_qcls = 0;
  p.dnsp_qtyp = 0;
  nrr = 0;

  while((r = dns_nextrr(&p, &rr)) > 0) {
    if (!dns_dnequal(dn, rr.dnsrr_dn)) continue;
    if ((ci->query_ctype == DNS_C_ANY || ci->query_ctype == rr.dnsrr_cls) &&
        (ci->query_rtype == DNS_T_ANY || ci->query_rtype == rr.dnsrr_typ))
      ++nrr;
    else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
      if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
                    p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
          rr.dnsrr_dptr != rr.dnsrr_dend) {
        ci->error = strdup("protocol error");
        break;
      }
      else {
        int32_t on = 1;
        /* This actually updates what we're looking for */
        dns_dntodn(p.dnsp_dnbuf, ci->dn, sizeof(dn));
        noit_stats_set_metric(ci->check, &ci->current, "cname", METRIC_INT32, &on);

        /* Now follow the leader */
        noitL(nldeb, "%s. CNAME %s.\n", dns_dntosp(dn),
              dns_dntosp(p.dnsp_dnbuf));
        dns_dntodn(p.dnsp_dnbuf, dn, sizeof(dn));
        noitL(nldeb, " ---> '%s'\n", dns_dntosp(dn));
      }
    }
  }
  if (!r && !nrr) {
    ci->error = strdup("no data");
  }

  dns_rewind(&p, NULL);
  p.dnsp_qtyp = ci->query_rtype == DNS_T_ANY ? 0 : ci->query_rtype;
  p.dnsp_qcls = ci->query_ctype == DNS_C_ANY ? 0 : ci->query_ctype;
  while(dns_nextrr(&p, &rr) && ci->nrr < MAX_RR)
    decode_rr(ci, &p, &rr, &result_str[ci->nrr]);
  if(ci->sort)
    qsort(result_str, ci->nrr, sizeof(*result_str), cstring_cmp);
  /* calculate the length and allocate on the stack */
  len = 0;
  for(i=0; i<ci->nrr; i++) len += strlen(result_str[i]) + 2;
  result_combined = alloca(len);
  result_combined[0] = '\0';
  /* string it together */
  len = 0;
  for(i=0; i<ci->nrr; i++) {
    int slen;
    if(i) { memcpy(result_combined + len, ", ", 2); len += 2; }
    slen = strlen(result_str[i]);
    memcpy(result_combined + len, result_str[i], slen);
    len += slen;
    result_combined[len] = '\0';
    free(result_str[i]); /* free as we go */
  }
  noit_stats_set_metric(ci->check, &ci->current, "answer", METRIC_STRING, result_combined);

 cleanup:
  if(result) free(result);
  if(ci->timeout_event) {
    eventer_t e = eventer_remove(ci->timeout_event);
    ci->timeout_event = NULL;
    if(e) eventer_free(e);
  }
  ci->check->flags &= ~NP_RUNNING;
  dns_check_log_results(ci);
  __deactivate_ci(ci);
}
Exemplo n.º 18
0
static int
_ecore_con_dns_check(Ecore_Con_DNS *dns)
{
   struct addrinfo *ent = NULL;
   int error = 0;
 
   error = dns_ai_nextent(&ent, dns->ai);

   switch (error)
     {
      case 0:
        break;
      case EAGAIN:
        return 1;
      default:
        ERR("resolve failed: %s", dns_strerror(error));
        goto error;
     }

   {
      Ecore_Con_Info result = {0, .ip = {0}, .service = {0}};
#if 0
      char pretty[512];
      dns_ai_print(pretty, sizeof(pretty), ent, dns->ai);
      printf("%s\n", pretty);
#endif
      result.size = 0;
      dns_inet_ntop(dns_sa_family(ent->ai_addr), dns_sa_addr(dns_sa_family(ent->ai_addr), ent->ai_addr), result.ip, sizeof(result.ip));
      snprintf(result.service, sizeof(result.service), "%u", ntohs(*dns_sa_port(dns_sa_family(ent->ai_addr), ent->ai_addr)));
      memcpy(&result.info, ent, sizeof(result.info));
      if (dns->fdh) ecore_main_fd_handler_del(dns->fdh);
      dns->fdh = NULL;
      dns->done_cb(dns->data, &result);
      free(ent);
      _ecore_con_dns_free(dns);
   }

   return 0;
error:
   dns->done_cb(dns->data, NULL);
   _ecore_con_dns_free(dns);
   return -1;
}

static Eina_Bool
_dns_fd_cb(Ecore_Con_DNS *dns, Ecore_Fd_Handler *fdh __UNUSED__)
{
   if (_ecore_con_dns_check(dns) != 1) return ECORE_CALLBACK_RENEW;
   if (ecore_main_fd_handler_fd_get(dns->fdh) != dns_ai_pollfd(dns->ai))
     {
        ecore_main_fd_handler_del(dns->fdh);
        dns->fdh = ecore_main_fd_handler_add(dns_ai_pollfd(dns->ai), dns_ai_events(dns->ai), (Ecore_Fd_Cb)_dns_fd_cb, dns, NULL, NULL);
     }
   else
     ecore_main_fd_handler_active_set(dns->fdh, dns_ai_events(dns->ai));
   return ECORE_CALLBACK_RENEW;
}

static Eina_Bool
_dns_timer_cb(Ecore_Con_DNS *dns)
{
   dns->done_cb(dns->data, NULL);
   _ecore_con_dns_free(dns);
   dns->timer = NULL;
   return EINA_FALSE;
}
Exemplo n.º 19
0
/* forwards a request to dst
 * parameters:
 *   msg       - sip msg
 *   dst       - destination name, if non-null it will be resolved and
 *               send_info updated with the ip/port. Even if dst is non
 *               null send_info must contain the protocol and if a non
 *               default port or non srv. lookup is desired, the port must
 *               be !=0 
 *   port      - used only if dst!=0 (else the port in send_info->to is used)
 *   send_info - value/result partially filled dest_info structure:
 *                 - send_info->proto and comp are used
 *                 - send_info->to will be filled (dns)
 *                 - send_info->send_flags is filled from the message
 *                 - if the send_socket member is null, a send_socket will be 
 *                   chosen automatically
 * WARNING: don't forget to zero-fill all the  unused members (a non-zero 
 * random id along with proto==PROTO_TCP can have bad consequences, same for
 *   a bogus send_socket value)
 */
int forward_request(struct sip_msg* msg, str* dst, unsigned short port,
							struct dest_info* send_info)
{
	unsigned int len;
	char* buf;
	char md5[MD5_LEN];
	struct socket_info* orig_send_sock; /* initial send_sock */
	int ret;
	struct ip_addr ip; /* debugging only */
	char proto;
#ifdef USE_DNS_FAILOVER
	struct socket_info* prev_send_sock;
	int err;
	struct dns_srv_handle dns_srv_h;
	
	prev_send_sock=0;
	err=0;
#endif
	
	
	buf=0;
	orig_send_sock=send_info->send_sock;
	proto=send_info->proto;
	ret=0;

	if(dst){
#ifdef USE_DNS_FAILOVER
		if (cfg_get(core, core_cfg, use_dns_failover)){
			dns_srv_handle_init(&dns_srv_h);
			err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port,
									&proto, dns_flags);
			if (err!=0){
				LOG(L_ERR, "ERROR: forward_request: resolving \"%.*s\""
						" failed: %s [%d]\n", dst->len, ZSW(dst->s),
						dns_strerror(err), err);
				ret=E_BAD_ADDRESS;
				goto error;
			}
		}else
#endif
		if (sip_hostport2su(&send_info->to, dst, port, &proto)<0){
			LOG(L_ERR, "ERROR: forward_request: bad host name %.*s,"
						" dropping packet\n", dst->len, ZSW(dst->s));
			ret=E_BAD_ADDRESS;
			goto error;
		}
	}/* dst */
	send_info->send_flags=msg->fwd_send_flags;
	/* calculate branch for outbound request;  if syn_branch is turned off,
	   calculate is from transaction key, i.e., as an md5 of From/To/CallID/
	   CSeq exactly the same way as TM does; good for reboot -- than messages
	   belonging to transaction lost due to reboot will still be forwarded
	   with the same branch parameter and will be match-able downstream
	
	   if it is turned on, we don't care about reboot; we simply put a simple
	   value in there; better for performance
	*/
	if (syn_branch ) {
	        memcpy(msg->add_to_branch_s, "z9hG4bKcydzigwkX", 16);
		msg->add_to_branch_len=16;
	} else {
		if (!char_msg_val( msg, md5 )) 	{ /* parses transaction key */
			LOG(L_ERR, "ERROR: forward_request: char_msg_val failed\n");
			ret=E_UNSPEC;
			goto error;
		}
		msg->hash_index=hash( msg->callid->body, get_cseq(msg)->number);
		if (!branch_builder( msg->hash_index, 0, md5, 0 /* 0-th branch */,
					msg->add_to_branch_s, &msg->add_to_branch_len )) {
			LOG(L_ERR, "ERROR: forward_request: branch_builder failed\n");
			ret=E_UNSPEC;
			goto error;
		}
	}
	/* try to send the message until success or all the ips are exhausted
	 *  (if dns lookup is performed && the dns cache used ) */
#ifdef USE_DNS_FAILOVER
	do{
#endif
		if (orig_send_sock==0) /* no forced send_sock => find it **/
			send_info->send_sock=get_send_socket(msg, &send_info->to, proto);
		if (send_info->send_sock==0){
			LOG(L_ERR, "forward_req: ERROR: cannot forward to af %d, proto %d "
						"no corresponding listening socket\n",
						send_info->to.s.sa_family, proto);
			ret=ser_error=E_NO_SOCKET;
#ifdef USE_DNS_FAILOVER
			/* continue, maybe we find a socket for some other ip */
			continue;
#else
			goto error;
#endif
		}
	
#ifdef USE_DNS_FAILOVER
		if (prev_send_sock!=send_info->send_sock){
			/* rebuild the message only if the send_sock changed */
			prev_send_sock=send_info->send_sock;
#endif
			if (buf) pkg_free(buf);
			send_info->proto=proto;
			buf = build_req_buf_from_sip_req(msg, &len, send_info, 0);
			if (!buf){
				LOG(L_ERR, "ERROR: forward_request: building failed\n");
				ret=E_OUT_OF_MEM; /* most probable */
				goto error;
			}
#ifdef USE_DNS_FAILOVER
		}
#endif
		 /* send it! */
		DBG("Sending:\n%.*s.\n", (int)len, buf);
		DBG("orig. len=%d, new_len=%d, proto=%d\n",
				msg->len, len, send_info->proto );
	
		if (run_onsend(msg, send_info, buf, len)==0){
			su2ip_addr(&ip, &send_info->to);
			LOG(L_INFO, "forward_request: request to %s:%d(%d) dropped"
					" (onsend_route)\n", ip_addr2a(&ip),
						su_getport(&send_info->to), send_info->proto);
			ser_error=E_OK; /* no error */
			ret=E_ADM_PROHIBITED;
#ifdef USE_DNS_FAILOVER
			continue; /* try another ip */
#else
			goto error; /* error ? */
#endif
		}
#ifdef USE_DST_BLACKLIST
		if (cfg_get(core, core_cfg, use_dst_blacklist)){
			if (dst_is_blacklisted(send_info, msg)){
				su2ip_addr(&ip, &send_info->to);
				LOG(L_DBG, "DEBUG: blacklisted destination:%s:%d (%d)\n",
							ip_addr2a(&ip), su_getport(&send_info->to),
							send_info->proto);
				ret=ser_error=E_SEND;
#ifdef USE_DNS_FAILOVER
				continue; /* try another ip */
#else
				goto error;
#endif
			}
		}
#endif
		if (msg_send(send_info, buf, len)<0){
			ret=ser_error=E_SEND;
#ifdef USE_DST_BLACKLIST
			(void)dst_blacklist_add(BLST_ERR_SEND, send_info, msg);
#endif
#ifdef USE_DNS_FAILOVER
			continue; /* try another ip */
#else
			goto error;
#endif
		}else{
			ret=ser_error=E_OK;
			/* sent requests stats */
			STATS_TX_REQUEST(  msg->first_line.u.request.method_value );
			/* exit succcesfully */
			goto end;
		}
#ifdef USE_DNS_FAILOVER
	}while(dst && cfg_get(core, core_cfg, use_dns_failover) &&
			dns_srv_handle_next(&dns_srv_h, err) && 
			((err=dns_sip_resolve2su(&dns_srv_h, &send_info->to, dst, port,
										&proto, dns_flags))==0));
	if ((err!=0) && (err!=-E_DNS_EOR)){
		LOG(L_ERR, "ERROR:  resolving %.*s host name in uri"
							" failed: %s [%d] (dropping packet)\n",
									dst->len, ZSW(dst->s),
									dns_strerror(err), err);
		ret=ser_error=E_BAD_ADDRESS;
		goto error;
	}
#endif
	
error:
	STATS_TX_DROPS;
end:
#ifdef USE_DNS_FAILOVER
	if (dst && cfg_get(core, core_cfg, use_dns_failover)){
				dns_srv_handle_put(&dns_srv_h);
	}
#endif
	if (buf) pkg_free(buf);
	/* received_buf & line_buf will be freed in receive_msg by free_lump_list*/
#if defined STATS_REQ_FWD_OK || defined STATS_REQ_FWD_DROP
	if(ret==0)
		STATS_REQ_FWD_OK();
	else
		STATS_REQ_FWD_DROP();
#endif /* STATS_REQ_FWD_* */
	return ret;
}
Exemplo n.º 20
0
struct dest_info *msrp_uri_to_dstinfo(struct dns_srv_handle* dns_h,
		struct dest_info* dst, struct socket_info *force_send_socket,
		snd_flags_t sflags, str *uri)
{
	msrp_uri_t parsed_uri;
	str* host;
	int port;
	int ip_found;
	union sockaddr_union to;
	int err;

	init_dest_info(dst);

	if (msrp_parse_uri(uri->s, uri->len, &parsed_uri) < 0) {
		LM_ERR("bad msrp uri: %.*s\n", uri->len, uri->s );
		return 0;
	}
	
	if (parsed_uri.scheme_no==MSRP_SCHEME_MSRPS){
		dst->proto = PROTO_TLS;
	} else {
		dst->proto = PROTO_TCP;
	}
	
	dst->send_flags=sflags;
	host=&parsed_uri.host;
	port = parsed_uri.port_no;

	if (dns_h && cfg_get(core, core_cfg, use_dns_failover)){
		ip_found=0;
		do{
			/* try all the ips until we find a good send socket */
			err=dns_sip_resolve2su(dns_h, &to, host,
								port, &dst->proto, dns_flags);
			if (err!=0){
				if (ip_found==0){
					if (err!=-E_DNS_EOR)
						LM_ERR("failed to resolve \"%.*s\" :"
								"%s (%d)\n", host->len, ZSW(host->s),
									dns_strerror(err), err);
					return 0; /* error, no ip found */
				}
				break;
			}
			if (ip_found==0){
				dst->to=to;
				ip_found=1;
			}
			dst->send_sock = get_send_socket2(force_send_socket, &to,
												dst->proto, 0);
			if (dst->send_sock){
				dst->to=to;
				return dst; /* found a good one */
			}
		} while(dns_srv_handle_next(dns_h, err));
		ERR("no corresponding socket for \"%.*s\" af %d\n", host->len, 
				ZSW(host->s), dst->to.s.sa_family);
		/* try to continue */
		return dst;
	}

	if (sip_hostport2su(&dst->to, host, port, &dst->proto)!=0){
		ERR("failed to resolve \"%.*s\"\n", host->len, ZSW(host->s));
		return 0;
	}
	dst->send_sock = get_send_socket2(force_send_socket, &dst->to,
			dst->proto, 0);
	if (dst->send_sock==0) {
		ERR("no corresponding socket for af %d\n", dst->to.s.sa_family);
		/* try to continue */
	}
	return dst;
}