X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-core%2Fiface-linux.c;h=2782697a368f73a48df940945e8163172345a183;hb=5b0187292d95c991c37efeeaf36fac9628dae5dc;hp=64bb0aec69001a529ea660dfd29f9a1007cb3d5a;hpb=d322a943be5387a539f8f3ea3a19a7e2ed5a55a2;p=catta diff --git a/avahi-core/iface-linux.c b/avahi-core/iface-linux.c index 64bb0ae..2782697 100644 --- a/avahi-core/iface-linux.c +++ b/avahi-core/iface-linux.c @@ -1,18 +1,16 @@ -/* $Id$ */ - /*** This file is 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 @@ -34,11 +32,23 @@ #include "iface.h" #include "iface-linux.h" +#ifndef IFLA_RTA +#include +#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) +#endif + +#ifndef IFA_RTA +#include +#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) +#endif + static int netlink_list_items(AvahiNetlink *nl, uint16_t type, unsigned *ret_seq) { struct nlmsghdr *n; struct rtgenmsg *gen; uint8_t req[1024]; - + + /* Issue a wild dump NETLINK request */ + memset(&req, 0, sizeof(req)); n = (struct nlmsghdr*) req; n->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)); @@ -55,17 +65,23 @@ static int netlink_list_items(AvahiNetlink *nl, uint16_t type, unsigned *ret_seq static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdata) { AvahiInterfaceMonitor *m = userdata; - + + /* This routine is called for every RTNETLINK response packet */ + assert(m); assert(n); assert(m->osdep.netlink == nl); if (n->nlmsg_type == RTM_NEWLINK) { + + /* A new interface appeared or an existing one has been modified */ + struct ifinfomsg *ifinfomsg = NLMSG_DATA(n); AvahiHwInterface *hw; struct rtattr *a = NULL; size_t l; - + + /* A (superfluous?) sanity check */ if (ifinfomsg->ifi_family != AF_UNSPEC) return; @@ -75,7 +91,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat * interface appears, but when it changes, too */ if (!(hw = avahi_interface_monitor_get_hw_interface(m, ifinfomsg->ifi_index))) - + /* No object found, so let's create a new * one. avahi_hw_interface_new() will call * avahi_interface_new() internally twice for IPv4 and @@ -90,7 +106,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat (!m->server->config.use_iff_running || (ifinfomsg->ifi_flags & IFF_RUNNING)) && !(ifinfomsg->ifi_flags & IFF_LOOPBACK) && (ifinfomsg->ifi_flags & IFF_MULTICAST) && - !(ifinfomsg->ifi_flags & IFF_POINTOPOINT); + (m->server->config.allow_point_to_point || !(ifinfomsg->ifi_flags & IFF_POINTOPOINT)); /* Handle interface attributes */ l = NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg)); @@ -116,12 +132,12 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat /* Fill in hardware (MAC) address */ hw->mac_address_size = RTA_PAYLOAD(a); - if (hw->mac_address_size > AVAHI_MAX_MAC_ADDRESS) - hw->mac_address_size = AVAHI_MAX_MAC_ADDRESS; - + if (hw->mac_address_size > AVAHI_MAC_ADDRESS_MAX) + hw->mac_address_size = AVAHI_MAC_ADDRESS_MAX; + memcpy(hw->mac_address, RTA_DATA(a), hw->mac_address_size); break; - + default: ; } @@ -138,11 +154,15 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat /* Update any associated RRs of this interface. (i.e. the * _workstation._tcp record containing the MAC address) */ avahi_hw_interface_update_rrs(hw, 0); - + } else if (n->nlmsg_type == RTM_DELLINK) { + + /* An interface has been removed */ + struct ifinfomsg *ifinfomsg = NLMSG_DATA(n); AvahiHwInterface *hw; + /* A (superfluous?) sanity check */ if (ifinfomsg->ifi_family != AF_UNSPEC) return; @@ -152,9 +172,11 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat /* Free our object */ avahi_hw_interface_free(hw, 0); - + } else if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) { + /* An address has been added, modified or removed */ + struct ifaddrmsg *ifaddrmsg = NLMSG_DATA(n); AvahiInterface *i; struct rtattr *a = NULL; @@ -183,7 +205,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat switch(a->rta_type) { case IFA_ADDRESS: /* Fill in address data */ - + if ((raddr.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) || (raddr.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4)) return; @@ -196,7 +218,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat default: ; } - + a = RTA_NEXT(a, l); } @@ -236,16 +258,16 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat /* Update any associated RRs, like A or AAAA for our new/removed address */ avahi_interface_update_rrs(i, 0); - + } else if (n->nlmsg_type == NLMSG_DONE) { /* This wild dump request ended, so let's see what we do next */ - + if (m->osdep.list == LIST_IFACE) { /* Mmmm, interfaces have been wild dumped already, so * let's go on with wild dumping the addresses */ - + if (netlink_list_items(m->osdep.netlink, RTM_GETADDR, &m->osdep.query_addr_seq) < 0) { avahi_log_warn("NETLINK: Failed to list addrs: %s", strerror(errno)); m->osdep.list = LIST_DONE; @@ -276,14 +298,14 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat /* Tell the user that the wild dump is complete */ avahi_log_info("Network interface enumeration completed."); } - + } else if (n->nlmsg_type == NLMSG_ERROR && (n->nlmsg_seq == m->osdep.query_link_seq || n->nlmsg_seq == m->osdep.query_addr_seq)) { struct nlmsgerr *e = NLMSG_DATA (n); /* Some kind of error happened. Let's just tell the user and * ignore it otherwise */ - + if (e->error) avahi_log_warn("NETLINK: Failed to browse: %s", strerror(-e->error)); } @@ -293,7 +315,7 @@ int avahi_interface_monitor_init_osdep(AvahiInterfaceMonitor *m) { assert(m); /* Initialize our own data */ - + m->osdep.netlink = NULL; m->osdep.query_addr_seq = m->osdep.query_link_seq = 0; @@ -304,13 +326,13 @@ int avahi_interface_monitor_init_osdep(AvahiInterfaceMonitor *m) { if (!(m->osdep.netlink = avahi_netlink_new(m->server->poll_api, RTMGRP_LINK|RTMGRP_IPV4_IFADDR|RTMGRP_IPV6_IFADDR, netlink_callback, m))) goto fail; + /* Set the initial state. */ + m->osdep.list = LIST_IFACE; + /* Start the wild dump for the interfaces */ if (netlink_list_items(m->osdep.netlink, RTM_GETLINK, &m->osdep.query_link_seq) < 0) goto fail; - /* Set the initial state. */ - m->osdep.list = LIST_IFACE; - return 0; fail: @@ -337,11 +359,10 @@ void avahi_interface_monitor_sync(AvahiInterfaceMonitor *m) { /* Let's handle netlink events until we are done with wild * dumping */ - - while (m->osdep.list != LIST_DONE) { + + while (!m->list_complete) if (!avahi_netlink_work(m->osdep.netlink, 1) == 0) break; - } /* At this point Avahi knows about all local interfaces and * addresses in existance. */