4 This file is part of avahi.
6 avahi is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 avahi is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14 Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with avahi; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <sys/socket.h>
28 #include <asm/types.h>
29 #include <linux/netlink.h>
30 #include <linux/rtnetlink.h>
35 #include <avahi-common/error.h>
36 #include <avahi-common/malloc.h>
45 #include "multicast-lookup.h"
48 static void update_address_rr(AvahiInterfaceMonitor *m, AvahiInterfaceAddress *a, int remove_rrs) {
52 if (a->interface->announcing &&
53 m->list == LIST_DONE &&
54 avahi_interface_address_relevant(a) &&
56 m->server->config.publish_addresses &&
57 (m->server->state == AVAHI_SERVER_RUNNING ||
58 m->server->state == AVAHI_SERVER_REGISTERING)) {
60 /* Fill the entry group */
62 a->entry_group = avahi_s_entry_group_new(m->server, avahi_host_rr_entry_group_callback, NULL);
64 if (!a->entry_group) /* OOM */
67 if (avahi_s_entry_group_is_empty(a->entry_group)) {
69 avahi_address_snprint(t, sizeof(t), &a->address);
71 avahi_log_info("Registering new address %s on %s.", t, a->interface->hardware->name);
73 if (avahi_server_add_address(m->server, a->entry_group, a->interface->hardware->index, a->interface->protocol, 0, NULL, &a->address) < 0) {
74 avahi_log_warn(__FILE__": avahi_server_add_address() failed: %s", avahi_strerror(m->server->error));
75 avahi_s_entry_group_free(a->entry_group);
76 a->entry_group = NULL;
80 avahi_s_entry_group_commit(a->entry_group);
84 /* Clear the entry group */
86 if (a->entry_group && !avahi_s_entry_group_is_empty(a->entry_group)) {
88 avahi_address_snprint(t, sizeof(t), &a->address);
90 if (avahi_s_entry_group_get_state(a->entry_group) == AVAHI_ENTRY_GROUP_REGISTERING &&
91 m->server->state == AVAHI_SERVER_REGISTERING)
92 avahi_server_decrease_host_rr_pending(m->server);
94 avahi_log_info("Withdrawing address %s on %s.", t, a->interface->hardware->name);
96 avahi_s_entry_group_reset(a->entry_group);
101 static void update_interface_rr(AvahiInterfaceMonitor *m, AvahiInterface *i, int remove_rrs) {
102 AvahiInterfaceAddress *a;
107 for (a = i->addresses; a; a = a->address_next)
108 update_address_rr(m, a, remove_rrs);
111 static void update_hw_interface_rr(AvahiInterfaceMonitor *m, AvahiHwInterface *hw, int remove_rrs) {
117 for (i = hw->interfaces; i; i = i->by_hardware_next)
118 update_interface_rr(m, i, remove_rrs);
120 if (m->list == LIST_DONE &&
122 m->server->config.publish_workstation &&
123 (m->server->state == AVAHI_SERVER_RUNNING ||
124 m->server->state == AVAHI_SERVER_REGISTERING)) {
126 if (!hw->entry_group)
127 hw->entry_group = avahi_s_entry_group_new(m->server, avahi_host_rr_entry_group_callback, NULL);
129 if (!hw->entry_group)
132 if (avahi_s_entry_group_is_empty(hw->entry_group)) {
136 if (!(t = avahi_format_mac_address(hw->mac_address, hw->mac_address_size)))
139 name = avahi_strdup_printf("%s [%s]", m->server->host_name, t);
145 if (avahi_server_add_service(m->server, hw->entry_group, hw->index, AVAHI_PROTO_UNSPEC, name, "_workstation._tcp", NULL, NULL, 9, NULL) < 0) {
146 avahi_log_warn(__FILE__": avahi_server_add_service() failed.");
147 avahi_s_entry_group_free(hw->entry_group);
148 hw->entry_group = NULL;
150 avahi_s_entry_group_commit(hw->entry_group);
157 if (hw->entry_group && !avahi_s_entry_group_is_empty(hw->entry_group)) {
159 if (avahi_s_entry_group_get_state(hw->entry_group) == AVAHI_ENTRY_GROUP_REGISTERING)
160 avahi_server_decrease_host_rr_pending(m->server);
162 avahi_s_entry_group_reset(hw->entry_group);
167 static void free_address(AvahiInterfaceMonitor *m, AvahiInterfaceAddress *a) {
170 assert(a->interface);
172 update_address_rr(m, a, 1);
173 AVAHI_LLIST_REMOVE(AvahiInterfaceAddress, address, a->interface->addresses, a);
176 avahi_s_entry_group_free(a->entry_group);
181 static void free_interface(AvahiInterfaceMonitor *m, AvahiInterface *i, int send_goodbye) {
185 /* Handle goodbyes and remove announcers */
186 avahi_goodbye_interface(m->server, i, send_goodbye);
187 avahi_response_scheduler_force(i->response_scheduler);
188 assert(!i->announcements);
190 /* Remove queriers */
191 avahi_querier_free_all(i);
192 avahi_hashmap_free(i->queriers_by_key);
194 /* Remove local RRs */
195 update_interface_rr(m, i, 1);
198 free_address(m, i->addresses);
200 avahi_response_scheduler_free(i->response_scheduler);
201 avahi_query_scheduler_free(i->query_scheduler);
202 avahi_probe_scheduler_free(i->probe_scheduler);
203 avahi_cache_free(i->cache);
205 AVAHI_LLIST_REMOVE(AvahiInterface, interface, m->interfaces, i);
206 AVAHI_LLIST_REMOVE(AvahiInterface, by_hardware, i->hardware->interfaces, i);
211 static void free_hw_interface(AvahiInterfaceMonitor *m, AvahiHwInterface *hw, int send_goodbye) {
215 update_hw_interface_rr(m, hw, 1);
217 while (hw->interfaces)
218 free_interface(m, hw->interfaces, send_goodbye);
221 avahi_s_entry_group_free(hw->entry_group);
223 AVAHI_LLIST_REMOVE(AvahiHwInterface, hardware, m->hw_interfaces, hw);
224 avahi_hashmap_remove(m->hashmap, &hw->index);
226 avahi_free(hw->name);
230 static AvahiInterfaceAddress* get_address(AvahiInterfaceMonitor *m, AvahiInterface *i, const AvahiAddress *raddr) {
231 AvahiInterfaceAddress *ia;
237 for (ia = i->addresses; ia; ia = ia->address_next)
238 if (avahi_address_cmp(&ia->address, raddr) == 0)
244 static int netlink_list_items(AvahiNetlink *nl, uint16_t type, unsigned *ret_seq) {
246 struct rtgenmsg *gen;
249 memset(&req, 0, sizeof(req));
250 n = (struct nlmsghdr*) req;
251 n->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
252 n->nlmsg_type = type;
253 n->nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST;
257 memset(gen, 0, sizeof(struct rtgenmsg));
258 gen->rtgen_family = AF_UNSPEC;
260 return avahi_netlink_send(nl, n, ret_seq);
263 static void new_interface(AvahiInterfaceMonitor *m, AvahiHwInterface *hw, AvahiProtocol protocol) {
268 assert(protocol != AVAHI_PROTO_UNSPEC);
270 if (!(i = avahi_new(AvahiInterface, 1)))
275 i->protocol = protocol;
278 AVAHI_LLIST_HEAD_INIT(AvahiInterfaceAddress, i->addresses);
279 AVAHI_LLIST_HEAD_INIT(AvahiAnnouncement, i->announcements);
281 AVAHI_LLIST_HEAD_INIT(AvahiQuerier, i->queriers);
282 i->queriers_by_key = avahi_hashmap_new((AvahiHashFunc) avahi_key_hash, (AvahiEqualFunc) avahi_key_equal, NULL, NULL);
284 i->cache = avahi_cache_new(m->server, i);
285 i->response_scheduler = avahi_response_scheduler_new(i);
286 i->query_scheduler = avahi_query_scheduler_new(i);
287 i->probe_scheduler = avahi_probe_scheduler_new(i);
289 if (!i->cache || !i->response_scheduler || !i->query_scheduler || !i->probe_scheduler)
292 AVAHI_LLIST_PREPEND(AvahiInterface, by_hardware, hw->interfaces, i);
293 AVAHI_LLIST_PREPEND(AvahiInterface, interface, m->interfaces, i);
300 avahi_cache_free(i->cache);
301 if (i->response_scheduler)
302 avahi_response_scheduler_free(i->response_scheduler);
303 if (i->query_scheduler)
304 avahi_query_scheduler_free(i->query_scheduler);
305 if (i->probe_scheduler)
306 avahi_probe_scheduler_free(i->probe_scheduler);
311 static void check_interface_relevant(AvahiInterfaceMonitor *m, AvahiInterface *i) {
317 b = avahi_interface_relevant(i);
319 if (m->list == LIST_DONE && b && !i->announcing) {
320 avahi_log_info("New relevant interface %s.%s.", i->hardware->name, avahi_proto_to_string(i->protocol));
322 if (i->protocol == AVAHI_PROTO_INET)
323 avahi_mdns_mcast_join_ipv4(m->server->fd_ipv4, i->hardware->index);
324 if (i->protocol == AVAHI_PROTO_INET6)
325 avahi_mdns_mcast_join_ipv6(m->server->fd_ipv6, i->hardware->index);
328 avahi_announce_interface(m->server, i);
329 avahi_multicast_lookup_engine_new_interface(m->server->multicast_lookup_engine, i);
330 } else if (!b && i->announcing) {
331 avahi_log_info("Interface %s.%s no longer relevant.", i->hardware->name, avahi_proto_to_string(i->protocol));
333 if (i->protocol == AVAHI_PROTO_INET)
334 avahi_mdns_mcast_leave_ipv4(m->server->fd_ipv4, i->hardware->index);
335 if (i->protocol == AVAHI_PROTO_INET6)
336 avahi_mdns_mcast_leave_ipv6(m->server->fd_ipv6, i->hardware->index);
338 avahi_goodbye_interface(m->server, i, 0);
339 avahi_querier_free_all(i);
341 avahi_response_scheduler_clear(i->response_scheduler);
342 avahi_query_scheduler_clear(i->query_scheduler);
343 avahi_probe_scheduler_clear(i->probe_scheduler);
344 avahi_cache_flush(i->cache);
350 static void check_hw_interface_relevant(AvahiInterfaceMonitor *m, AvahiHwInterface *hw) {
356 for (i = hw->interfaces; i; i = i->by_hardware_next)
357 check_interface_relevant(m, i);
360 static void check_all_interfaces_relevant(AvahiInterfaceMonitor *m) {
364 for (i = m->interfaces; i; i = i->interface_next)
365 check_interface_relevant(m, i);
368 static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdata) {
369 AvahiInterfaceMonitor *m = userdata;
373 assert(m->netlink == nl);
375 if (n->nlmsg_type == RTM_NEWLINK) {
376 struct ifinfomsg *ifinfomsg = NLMSG_DATA(n);
377 AvahiHwInterface *hw;
378 struct rtattr *a = NULL;
381 if (ifinfomsg->ifi_family != AF_UNSPEC)
384 if (!(hw = avahi_hashmap_lookup(m->hashmap, &ifinfomsg->ifi_index))) {
386 if (!(hw = avahi_new(AvahiHwInterface, 1)))
393 hw->index = (AvahiIfIndex) ifinfomsg->ifi_index;
394 hw->mac_address_size = 0;
395 hw->entry_group = NULL;
397 AVAHI_LLIST_HEAD_INIT(AvahiInterface, hw->interfaces);
398 AVAHI_LLIST_PREPEND(AvahiHwInterface, hardware, m->hw_interfaces, hw);
400 avahi_hashmap_insert(m->hashmap, &hw->index, hw);
402 if (m->server->fd_ipv4 >= 0)
403 new_interface(m, hw, AVAHI_PROTO_INET);
404 if (m->server->fd_ipv6 >= 0)
405 new_interface(m, hw, AVAHI_PROTO_INET6);
408 hw->flags = ifinfomsg->ifi_flags;
410 l = NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg));
411 a = IFLA_RTA(ifinfomsg);
413 while (RTA_OK(a, l)) {
414 switch(a->rta_type) {
416 avahi_free(hw->name);
417 hw->name = avahi_strndup(RTA_DATA(a), RTA_PAYLOAD(a));
421 assert(RTA_PAYLOAD(a) == sizeof(unsigned int));
422 hw->mtu = *((unsigned int*) RTA_DATA(a));
426 hw->mac_address_size = RTA_PAYLOAD(a);
427 if (hw->mac_address_size > AVAHI_MAX_MAC_ADDRESS)
428 hw->mac_address_size = AVAHI_MAX_MAC_ADDRESS;
430 memcpy(hw->mac_address, RTA_DATA(a), hw->mac_address_size);
441 check_hw_interface_relevant(m, hw);
442 update_hw_interface_rr(m, hw, 0);
444 } else if (n->nlmsg_type == RTM_DELLINK) {
445 struct ifinfomsg *ifinfomsg = NLMSG_DATA(n);
446 AvahiHwInterface *hw;
448 if (ifinfomsg->ifi_family != AF_UNSPEC)
451 if (!(hw = avahi_interface_monitor_get_hw_interface(m, (AvahiIfIndex) ifinfomsg->ifi_index)))
454 free_hw_interface(m, hw, 0);
456 } else if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
458 struct ifaddrmsg *ifaddrmsg = NLMSG_DATA(n);
460 struct rtattr *a = NULL;
465 if (ifaddrmsg->ifa_family != AF_INET && ifaddrmsg->ifa_family != AF_INET6)
468 if (!(i = (AvahiInterface*) avahi_interface_monitor_get_interface(m, (AvahiIfIndex) ifaddrmsg->ifa_index, avahi_af_to_proto(ifaddrmsg->ifa_family))))
471 raddr.proto = avahi_af_to_proto(ifaddrmsg->ifa_family);
473 l = NLMSG_PAYLOAD(n, sizeof(struct ifaddrmsg));
474 a = IFA_RTA(ifaddrmsg);
476 while (RTA_OK(a, l)) {
478 switch(a->rta_type) {
480 if ((raddr.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) ||
481 (raddr.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4))
484 memcpy(raddr.data.data, RTA_DATA(a), RTA_PAYLOAD(a));
499 if (n->nlmsg_type == RTM_NEWADDR) {
500 AvahiInterfaceAddress *addr;
502 if (!(addr = get_address(m, i, &raddr))) {
503 if (!(addr = avahi_new(AvahiInterfaceAddress, 1)))
507 addr->address = raddr;
509 addr->entry_group = NULL;
511 AVAHI_LLIST_PREPEND(AvahiInterfaceAddress, address, i->addresses, addr);
514 addr->flags = ifaddrmsg->ifa_flags;
515 addr->scope = ifaddrmsg->ifa_scope;
516 addr->prefix_len = ifaddrmsg->ifa_prefixlen;
518 AvahiInterfaceAddress *addr;
520 if (!(addr = get_address(m, i, &raddr)))
523 free_address(m, addr);
526 check_interface_relevant(m, i);
527 update_interface_rr(m, i, 0);
529 } else if (n->nlmsg_type == NLMSG_DONE) {
531 if (m->list == LIST_IFACE) {
533 if (netlink_list_items(m->netlink, RTM_GETADDR, &m->query_addr_seq) < 0) {
534 avahi_log_warn("NETLINK: Failed to list addrs: %s", strerror(errno));
543 if (m->list == LIST_DONE) {
544 check_all_interfaces_relevant(m);
545 avahi_update_host_rrs(m, 0);
546 avahi_log_info("Network interface enumeration completed.");
549 } else if (n->nlmsg_type == NLMSG_ERROR && (n->nlmsg_seq == m->query_link_seq || n->nlmsg_seq == m->query_addr_seq)) {
550 struct nlmsgerr *e = NLMSG_DATA (n);
553 avahi_log_warn("NETLINK: Failed to browse: %s", strerror(-e->error));
557 AvahiInterfaceMonitor *avahi_interface_monitor_new(AvahiServer *s) {
558 AvahiInterfaceMonitor *m = NULL;
560 if (!(m = avahi_new0(AvahiInterfaceMonitor, 1)))
561 return NULL; /* OOM */
564 if (!(m->netlink = avahi_netlink_new(s->poll_api, RTMGRP_LINK|RTMGRP_IPV4_IFADDR|RTMGRP_IPV6_IFADDR, netlink_callback, m)))
567 m->hashmap = avahi_hashmap_new(avahi_int_hash, avahi_int_equal, NULL, NULL);
569 AVAHI_LLIST_HEAD_INIT(AvahiInterface, m->interfaces);
570 AVAHI_LLIST_HEAD_INIT(AvahiHwInterface, m->hw_interfaces);
572 if (netlink_list_items(m->netlink, RTM_GETLINK, &m->query_link_seq) < 0)
575 m->list = LIST_IFACE;
580 avahi_interface_monitor_free(m);
584 void avahi_interface_monitor_sync(AvahiInterfaceMonitor *m) {
587 while (m->list != LIST_DONE) {
588 if (!avahi_netlink_work(m->netlink, 1))
593 void avahi_interface_monitor_free(AvahiInterfaceMonitor *m) {
596 while (m->hw_interfaces)
597 free_hw_interface(m, m->hw_interfaces, 1);
599 assert(!m->interfaces);
602 avahi_netlink_free(m->netlink);
605 avahi_hashmap_free(m->hashmap);
611 AvahiInterface* avahi_interface_monitor_get_interface(AvahiInterfaceMonitor *m, AvahiIfIndex idx, AvahiProtocol protocol) {
612 AvahiHwInterface *hw;
617 assert(protocol != AVAHI_PROTO_UNSPEC);
619 if (!(hw = avahi_interface_monitor_get_hw_interface(m, idx)))
622 for (i = hw->interfaces; i; i = i->by_hardware_next)
623 if (i->protocol == protocol)
629 AvahiHwInterface* avahi_interface_monitor_get_hw_interface(AvahiInterfaceMonitor *m, AvahiIfIndex idx) {
633 return avahi_hashmap_lookup(m->hashmap, &idx);
636 void avahi_interface_send_packet_unicast(AvahiInterface *i, AvahiDnsPacket *p, const AvahiAddress *a, uint16_t port) {
641 if (!avahi_interface_relevant(i))
644 assert(!a || a->proto == i->protocol);
647 /* avahi_log_debug("unicast sending on '%s.%i' to %s:%u", i->hardware->name, i->protocol, avahi_address_snprint(t, sizeof(t), a), port); */
649 /* avahi_log_debug("multicast sending on '%s.%i'", i->hardware->name, i->protocol); */
651 if (i->protocol == AVAHI_PROTO_INET && i->monitor->server->fd_ipv4 >= 0)
652 avahi_send_dns_packet_ipv4(i->monitor->server->fd_ipv4, i->hardware->index, p, a ? &a->data.ipv4 : NULL, port);
653 else if (i->protocol == AVAHI_PROTO_INET6 && i->monitor->server->fd_ipv6 >= 0)
654 avahi_send_dns_packet_ipv6(i->monitor->server->fd_ipv6, i->hardware->index, p, a ? &a->data.ipv6 : NULL, port);
657 void avahi_interface_send_packet(AvahiInterface *i, AvahiDnsPacket *p) {
661 avahi_interface_send_packet_unicast(i, p, NULL, 0);
664 int avahi_interface_post_query(AvahiInterface *i, AvahiKey *key, int immediately) {
668 if (avahi_interface_relevant(i))
669 return avahi_query_scheduler_post(i->query_scheduler, key, immediately);
674 int avahi_interface_post_response(AvahiInterface *i, AvahiRecord *record, int flush_cache, const AvahiAddress *querier, int immediately) {
678 if (avahi_interface_relevant(i))
679 return avahi_response_scheduler_post(i->response_scheduler, record, flush_cache, querier, immediately);
684 int avahi_interface_post_probe(AvahiInterface *i, AvahiRecord *record, int immediately) {
688 if (avahi_interface_relevant(i))
689 return avahi_probe_scheduler_post(i->probe_scheduler, record, immediately);
694 int avahi_dump_caches(AvahiInterfaceMonitor *m, AvahiDumpCallback callback, void* userdata) {
698 for (i = m->interfaces; i; i = i->interface_next) {
699 if (avahi_interface_relevant(i)) {
701 snprintf(ln, sizeof(ln), ";;; INTERFACE %s.%s ;;;", i->hardware->name, avahi_proto_to_string(i->protocol));
702 callback(ln, userdata);
703 if (avahi_cache_dump(i->cache, callback, userdata) < 0)
711 int avahi_interface_relevant(AvahiInterface *i) {
712 AvahiInterfaceAddress *a;
713 int relevant_address;
717 relevant_address = 0;
719 for (a = i->addresses; a; a = a->address_next)
720 if (avahi_interface_address_relevant(a)) {
721 relevant_address = 1;
725 /* avahi_log_debug("%p. iface-relevant: %i %i %i %i %i %i", i, relevant_address, */
726 /* (i->hardware->flags & IFF_UP), */
727 /* (i->hardware->flags & IFF_RUNNING), */
728 /* !(i->hardware->flags & IFF_LOOPBACK), */
729 /* (i->hardware->flags & IFF_MULTICAST), */
730 /* !(i->hardware->flags & IFF_POINTOPOINT)); */
733 (i->hardware->flags & IFF_UP) &&
734 (!i->monitor->server->config.use_iff_running || (i->hardware->flags & IFF_RUNNING)) &&
735 !(i->hardware->flags & IFF_LOOPBACK) &&
736 (i->hardware->flags & IFF_MULTICAST) &&
737 !(i->hardware->flags & IFF_POINTOPOINT) &&
741 int avahi_interface_address_relevant(AvahiInterfaceAddress *a) {
742 AvahiInterfaceAddress *b;
745 /* Publish public IP addresses */
746 if (a->scope == RT_SCOPE_UNIVERSE ||
747 a->scope == RT_SCOPE_SITE)
750 if (a->scope == RT_SCOPE_LINK) {
752 /* Publish link local IP addresses if they are the only ones on the link */
753 for (b = a->interface->addresses; b; b = b->address_next) {
757 if (b->scope == RT_SCOPE_UNIVERSE ||
758 b->scope == RT_SCOPE_SITE)
768 int avahi_interface_match(AvahiInterface *i, AvahiIfIndex idx, AvahiProtocol protocol) {
771 if (idx != AVAHI_IF_UNSPEC && idx != i->hardware->index)
774 if (protocol != AVAHI_PROTO_UNSPEC && protocol != i->protocol)
780 void avahi_interface_monitor_walk(AvahiInterfaceMonitor *m, AvahiIfIndex interface, AvahiProtocol protocol, AvahiInterfaceMonitorWalkCallback callback, void* userdata) {
784 if (interface != AVAHI_IF_UNSPEC) {
785 if (protocol != AVAHI_PROTO_UNSPEC) {
788 if ((i = avahi_interface_monitor_get_interface(m, interface, protocol)))
789 callback(m, i, userdata);
792 AvahiHwInterface *hw;
795 if ((hw = avahi_interface_monitor_get_hw_interface(m, interface)))
796 for (i = hw->interfaces; i; i = i->by_hardware_next)
797 if (avahi_interface_match(i, interface, protocol))
798 callback(m, i, userdata);
804 for (i = m->interfaces; i; i = i->interface_next)
805 if (avahi_interface_match(i, interface, protocol))
806 callback(m, i, userdata);
810 void avahi_update_host_rrs(AvahiInterfaceMonitor *m, int remove_rrs) {
811 AvahiHwInterface *hw;
815 for (hw = m->hw_interfaces; hw; hw = hw->hardware_next)
816 update_hw_interface_rr(m, hw, remove_rrs);
819 int avahi_address_is_local(AvahiInterfaceMonitor *m, const AvahiAddress *a) {
821 AvahiInterfaceAddress *ia;
825 for (i = m->interfaces; i; i = i->interface_next)
826 for (ia = i->addresses; ia; ia = ia->address_next)
827 if (avahi_address_cmp(a, &ia->address) == 0)
833 int avahi_interface_address_on_link(AvahiInterface *i, const AvahiAddress *a) {
834 AvahiInterfaceAddress *ia;
839 if (a->proto != i->protocol)
842 for (ia = i->addresses; ia; ia = ia->address_next) {
844 if (a->proto == AVAHI_PROTO_INET) {
847 m = ~(((uint32_t) -1) >> ia->prefix_len);
849 if ((ntohl(a->data.ipv4.address) & m) == (ntohl(ia->address.data.ipv4.address) & m))
854 assert(a->proto == AVAHI_PROTO_INET6);
858 for (j = 0; j < 16; j++) {
872 if ((a->data.ipv6.address[j] & m) != (ia->address.data.ipv6.address[j] & m))
881 int avahi_interface_has_address(AvahiInterfaceMonitor *m, AvahiIfIndex iface, const AvahiAddress *a) {
883 AvahiInterfaceAddress *j;
886 assert(iface != AVAHI_IF_UNSPEC);
889 if (!(i = avahi_interface_monitor_get_interface(m, iface, a->proto)))
892 for (j = i->addresses; j; j = j->address_next)
893 if (avahi_address_cmp(a, &j->address) == 0)