Example #1
0
static void
browse_record_callback(AvahiRecordBrowser *b, AvahiIfIndex intf, AvahiProtocol proto,
                       AvahiBrowserEvent event, const char *hostname, uint16_t clazz, uint16_t type,
                       const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata)
{
  struct mdns_record_browser *rb_data;
  AvahiAddress addr;
  char address[AVAHI_ADDRESS_STR_MAX];
  int family;
  int ret;

  rb_data = (struct mdns_record_browser *)userdata;

  if (event == AVAHI_BROWSER_CACHE_EXHAUSTED)
    DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s, proto %d): no more results (CACHE_EXHAUSTED)\n", hostname, proto);
  else if (event == AVAHI_BROWSER_ALL_FOR_NOW)
    DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s, proto %d): no more results (ALL_FOR_NOW)\n", hostname, proto);
  else if (event == AVAHI_BROWSER_FAILURE)
    DPRINTF(E_LOG, L_MDNS, "Avahi Record Browser (%s, proto %d) failure: %s\n", hostname, proto, MDNSERR);
  else if (event == AVAHI_BROWSER_REMOVE)
    return; // Not handled - record browser lifetime too short for this to happen

  if (event != AVAHI_BROWSER_NEW)
    goto out_free_record_browser;

  ret = avahi_address_make(&addr, proto, rdata, size); // Not an avahi function despite the name
  if (ret < 0)
    return;

  family = avahi_proto_to_af(proto);
  avahi_address_snprint(address, sizeof(address), &addr);

  // Avahi will sometimes give us link-local addresses in 169.254.0.0/16 or
  // fe80::/10, which (most of the time) are useless
  // - see also https://lists.freedesktop.org/archives/avahi/2012-September/002183.html
  if ((proto == AVAHI_PROTO_INET && is_v4ll(&addr.data.ipv4)) || (proto == AVAHI_PROTO_INET6 && is_v6ll(&addr.data.ipv6)))
    {
      DPRINTF(E_WARN, L_MDNS, "Ignoring announcement from %s, address %s is link-local\n", hostname, address);
      return;
    }

  DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s, proto %d): NEW record %s for service type '%s'\n", hostname, proto, address, rb_data->mb->type);

  // Execute callback (mb->cb) with all the data
  rb_data->mb->cb(rb_data->name, rb_data->mb->type, rb_data->domain, hostname, family, address, rb_data->port, &rb_data->txt_kv);

  // Stop record browser
 out_free_record_browser:
  keyval_clear(&rb_data->txt_kv);
  free(rb_data->name);
  free(rb_data->domain);
  free(rb_data);

  avahi_record_browser_free(b);
}
Example #2
0
static void
browse_record_callback_v4(AvahiRecordBrowser *b, AvahiIfIndex intf, AvahiProtocol proto,
			  AvahiBrowserEvent event, const char *hostname, uint16_t clazz, uint16_t type,
			  const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata)
{
  char address[INET_ADDRSTRLEN];
  struct in_addr addr;
  struct mdns_record_browser *rb_data;
  int ll;

  rb_data = (struct mdns_record_browser *)userdata;

  switch (event)
    {
      case AVAHI_BROWSER_NEW:
	if (size != sizeof(addr.s_addr))
	  {
	    DPRINTF(E_WARN, L_MDNS, "Got RR type A size %ld (should be %ld)\n", (long)size, (long)sizeof(addr.s_addr));

	    return;
	  }

	memcpy(&addr.s_addr, rdata, sizeof(addr.s_addr));

	ll = is_v4ll(&addr);
	if (ll && !(rb_data->mb->flags & MDNS_WANT_V4LL))
	  {
	    DPRINTF(E_DBG, L_MDNS, "Discarding IPv4 LL, not interested (service %s)\n", rb_data->name);
	    return;
	  }
	else if (!ll && !(rb_data->mb->flags & MDNS_WANT_V4))
	  {
	    DPRINTF(E_DBG, L_MDNS, "Discarding IPv4, not interested (service %s)\n", rb_data->name);
	    return;
	  }

	if (!inet_ntop(AF_INET, &addr.s_addr, address, sizeof(address)))
	  {
	    DPRINTF(E_LOG, L_MDNS, "Could not print IPv4 address: %s\n", strerror(errno));

	    return;
	  }

	DPRINTF(E_DBG, L_MDNS, "Service %s, hostname %s resolved to %s\n", rb_data->name, hostname, address);

	/* Execute callback (mb->cb) with all the data */
	rb_data->mb->cb(rb_data->name, rb_data->mb->type, rb_data->domain, hostname, AF_INET, address, rb_data->port, &rb_data->txt_kv);
	/* Got a suitable address, stop record browser */
	break;

      case AVAHI_BROWSER_REMOVE:
	/* Not handled - record browser lifetime too short for this to happen */
	return;

      case AVAHI_BROWSER_CACHE_EXHAUSTED:
      case AVAHI_BROWSER_ALL_FOR_NOW:
	DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s v4): no more results (%s)\n", hostname,
		(event == AVAHI_BROWSER_CACHE_EXHAUSTED) ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");	

	break;

      case AVAHI_BROWSER_FAILURE:
	DPRINTF(E_LOG, L_MDNS, "Avahi Record Browser (%s v4) failure: %s\n", hostname,
		avahi_strerror(avahi_client_errno(avahi_record_browser_get_client(b))));

	break;
    }

  keyval_clear(&rb_data->txt_kv);      
  free(rb_data->name);
  free(rb_data->domain);
  free(rb_data);

  avahi_record_browser_free(b);
}
Example #3
0
static void
mdns_browse_call_cb(struct mdns_addr_lookup *lu, const char *hostname,
                    const struct sockaddr *address)
{
  char addr_str[INET6_ADDRSTRLEN];

  if (address->sa_family == AF_INET)
    {
      struct sockaddr_in *addr = (struct sockaddr_in *)address;

      if (!inet_ntop(AF_INET, &addr->sin_addr, addr_str, sizeof(addr_str)))
        {
          DPRINTF(E_LOG, L_MDNS, "Could not print IPv4 address: %s\n",
                  strerror(errno));
          return;
        }

      if (!(lu->rs->mb->protocol & kDNSServiceProtocol_IPv4))
        {
          DPRINTF(E_DBG, L_MDNS,
                  "Discarding IPv4, not interested (service %s)\n",
                  lu->rs->service);
          return;
        }
      else if (is_v4ll(&addr->sin_addr))
        {
          DPRINTF(E_WARN, L_MDNS,
                  "Ignoring announcement from %s, address %s is link-local\n",
                  hostname, addr_str);
          return;
        }

    }
  else if (address->sa_family == AF_INET6)
    {
      struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)address;

      if (!inet_ntop(AF_INET6, &addr6->sin6_addr, addr_str, sizeof(addr_str)))
        {
          DPRINTF(E_LOG, L_MDNS, "Could not print IPv6 address: %s\n",
                  strerror(errno));
          return;
        }

      if (!(lu->rs->mb->protocol & kDNSServiceProtocol_IPv6))
        {
          DPRINTF(E_DBG, L_MDNS,
                  "Discarding IPv6, not interested (service %s)\n",
                  lu->rs->service);
          return;
        }
      else if (is_v6ll(&addr6->sin6_addr))
        {
          DPRINTF(E_WARN, L_MDNS,
                  "Ignoring announcement from %s, address %s is link-local\n",
                  hostname, addr_str);
          return;
        }
    }

  DPRINTF(E_DBG, L_MDNS, "Service %s, hostname %s resolved to %s\n",
          lu->rs->service, hostname, addr_str);

  /* Execute callback (mb->cb) with all the data */
  lu->rs->mb->cb(lu->rs->service, lu->rs->regtype, lu->rs->domain, hostname,
                 address->sa_family, addr_str, lu->port, &lu->txt_kv);
}