| /* |
| * 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); |
| } |