/*
 *  This file is derived from avahi_client_browse.c, part of avahi.
 *
 *  avahi is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU Lesser General Public License as
 *  published by the Free Software Foundation; either version 2.1 of the
 *  License, or (at your option) any later version.
 *
 *  avahi is distributed in the hope that it will be useful, but WITHOUT
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
 *  Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with avahi; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 *  USA.
 */

/*
 * dnssd_hosts
 * Find all stations sending DNS-SD notifications by looking for
 * _workstation._tcp. For all stations where we have a MAC address,
 * output the MAC address and hostname.
 */

#include <assert.h>
#include <ctype.h>
#include <net/if.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>

#include <avahi-client/client.h>
#include <avahi-client/lookup.h>

#include <avahi-common/simple-watch.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>

static AvahiSimplePoll *simple_poll = NULL;


static void replace_newlines(const char *src, char *dst, int dstlen)
{
  int i;
  for (i = 0; src[i] != '\0' && i < (dstlen - 1); i++) {
    dst[i] = (src[i] == '\n') ? '.' : src[i];
  }
  dst[i] = '\0';
}


static void service_resolver_callback(
    AvahiServiceResolver *r,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiResolverEvent event,
    const char *name,
    const char *type,
    const char *domain,
    const char *host_name,
    const AvahiAddress *a,
    uint16_t port,
    AvahiStringList *txt,
    AvahiLookupResultFlags flags,
    void *userdata)
{
  AvahiClient *c = (AvahiClient *)userdata;
  int err;
  char buf[AVAHI_ADDRESS_STR_MAX];
  char host[80];

  assert(c);
  memset(buf, 0, sizeof(buf));
  switch (event) {
    case AVAHI_RESOLVER_FAILURE:
      err = avahi_client_errno(c);
      fprintf(stderr, "AVAHI_RESOLVER_FAILURE %s\n", avahi_strerror(err));
      avahi_simple_poll_quit(simple_poll);
      return;

    case AVAHI_RESOLVER_FOUND:
      avahi_address_snprint(buf, sizeof(buf), a);
      replace_newlines(host_name, host, sizeof(host));
      printf("%s|%s\n", buf, host);
      break;
  }
}


static void service_browser_callback(
    AvahiServiceBrowser *b,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiBrowserEvent event,
    const char *name,
    const char *type,
    const char *domain,
    AvahiLookupResultFlags flags,
    void *userdata)
{
  AvahiClient *c = (AvahiClient *)userdata;
  int err;

  assert(c);
  switch (event) {
    case AVAHI_BROWSER_FAILURE:
      err = avahi_client_errno(c);
      fprintf(stderr, "AVAHI_BROWSER_FAILURE %s\n", avahi_strerror(err));
      avahi_simple_poll_quit(simple_poll);
      return;

    case AVAHI_BROWSER_NEW:
      if (avahi_service_resolver_new(
          c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC,
          0, service_resolver_callback, c) == NULL) {
        fprintf(stderr, "avahi_service_resolver_new failed.\n");
      }
      break;

    case AVAHI_BROWSER_REMOVE:
      break;

    case AVAHI_BROWSER_ALL_FOR_NOW:
      avahi_simple_poll_quit(simple_poll);
      break;

    case AVAHI_BROWSER_CACHE_EXHAUSTED:
      break;
  }
}


static void service_type_browser_callback(
    AvahiServiceTypeBrowser *b,
    AvahiIfIndex interface,
    AvahiProtocol protocol,
    AvahiBrowserEvent event,
    const char *type,
    const char *domain,
    AvahiLookupResultFlags flags,
    void *userdata)
{
  AvahiClient *c = (AvahiClient *)userdata;
  int err;

  assert(c);
  switch (event) {
    case AVAHI_BROWSER_FAILURE:
      err = avahi_client_errno(c);
      fprintf(stderr, "AVAHI_BROWSER_FAILURE %s\n", avahi_strerror(err));
      avahi_simple_poll_quit(simple_poll);
      return;

    case AVAHI_BROWSER_NEW:
      if (avahi_service_browser_new(
          c, interface, protocol, type, domain, 0,
          service_browser_callback, c) == NULL) {
        fprintf(stderr, "avahi_service_browser_new failed.\n");
      }
      break;

    case AVAHI_BROWSER_REMOVE:
      break;

    case AVAHI_BROWSER_ALL_FOR_NOW:
      avahi_simple_poll_quit(simple_poll);
      break;

    case AVAHI_BROWSER_CACHE_EXHAUSTED:
      break;
  }
}

static void client_callback(AvahiClient *c, AvahiClientState state,
                            void *userdata)
{
  switch(state) {
    case AVAHI_CLIENT_FAILURE:
      fprintf(stderr, "Client failure: %s\n",
              avahi_strerror(avahi_client_errno(c)));
      avahi_simple_poll_quit(simple_poll);
      break;

    case AVAHI_CLIENT_S_REGISTERING:
    case AVAHI_CLIENT_S_RUNNING:
    case AVAHI_CLIENT_S_COLLISION:
    case AVAHI_CLIENT_CONNECTING:
      break;
  }
}


int get_ifindex(const char *ifname)
{
  int fd;
  struct ifreq ifr;
  size_t nlen = strlen(ifname);

  if ((fd = socket(AF_PACKET, SOCK_DGRAM, 0)) < 0) {
    perror("socket");
    exit(1);
  }

  if (nlen >= sizeof(ifr.ifr_name)) {
    fprintf(stderr, "interface name %s is too long\n", ifname);
    exit(1);
  }

  memset(&ifr, 0, sizeof(ifr));
  strncpy(ifr.ifr_name, ifname, nlen);
  ifr.ifr_name[nlen] = '\0';

  if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
    perror("SIOCGIFINDEX");
    exit(1);
  }

  close(fd);
  return ifr.ifr_ifindex;
}  /* get_ifindex */


void usage(char *progname)
{
  fprintf(stderr, "usage: %s [-i ifname]\n", progname);
  fprintf(stderr, "\t-i ifname - interface to use (default: unspecified)\n");
  exit(1);
}


int main(int argc, char *argv[])
{
  int opt;
  AvahiIfIndex ifindex = AVAHI_IF_UNSPEC;
  AvahiClient *c = NULL;
  AvahiServiceTypeBrowser *sb = NULL;
  int error;

  while ((opt = getopt(argc, argv, "i:")) != -1) {
    switch (opt) {
      case 'i':
        ifindex = get_ifindex(optarg);
        break;
      default:
        usage(argv[0]);
        break;
    }
  }

  if ((simple_poll = avahi_simple_poll_new()) == NULL) {
    fprintf(stderr, "avahi_simple_poll_new failed.\n");
    exit(1);
  }

  if ((c = avahi_client_new(avahi_simple_poll_get(simple_poll), 0,
                            client_callback, NULL, &error)) == NULL) {
    fprintf(stderr, "avahi_client_new failed.\n");
    exit(1);
  }

  if ((sb = avahi_service_type_browser_new(
      c, ifindex, AVAHI_PROTO_UNSPEC, NULL, 0,
      service_type_browser_callback, c)) == NULL) {
    fprintf(stderr, "avahi_service_browser_new failed.\n");
    exit(1);
  }

  avahi_simple_poll_loop(simple_poll);

  exit(0);
}
