X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-core%2Fiface-linux.c;h=da497bc4dcbadb4816d5dc301acb25d3fd55e135;hb=9c0f9c65093cfa53d45f9b68782321eb8063a032;hp=c8ed9e05c6e913a58b7a9e9c30f4690b4c513a05;hpb=fc2fc59b512cddcd54448144222de1d4e286e32e;p=catta diff --git a/avahi-core/iface-linux.c b/avahi-core/iface-linux.c index c8ed9e0..da497bc 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 @@ -50,12 +48,12 @@ static int netlink_list_items(AvahiNetlink *nl, uint16_t type, unsigned *ret_seq 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)); n->nlmsg_type = type; - n->nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST; + n->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP; n->nlmsg_pid = 0; gen = NLMSG_DATA(n); @@ -69,7 +67,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat AvahiInterfaceMonitor *m = userdata; /* This routine is called for every RTNETLINK response packet */ - + assert(m); assert(n); assert(m->osdep.netlink == nl); @@ -77,7 +75,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat 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; @@ -93,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 @@ -136,10 +134,10 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat hw->mac_address_size = RTA_PAYLOAD(a); 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: ; } @@ -156,7 +154,7 @@ 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 */ @@ -174,17 +172,17 @@ 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; size_t l; - AvahiAddress raddr; - int raddr_valid = 0; + AvahiAddress raddr, rlocal, *r; + int raddr_valid = 0, rlocal_valid = 0; /* We are only interested in IPv4 and IPv6 */ if (ifaddrmsg->ifa_family != AF_INET && ifaddrmsg->ifa_family != AF_INET6) @@ -197,7 +195,7 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat return; /* Fill in address family for our new address */ - raddr.proto = avahi_af_to_proto(ifaddrmsg->ifa_family); + rlocal.proto = raddr.proto = avahi_af_to_proto(ifaddrmsg->ifa_family); l = NLMSG_PAYLOAD(n, sizeof(struct ifaddrmsg)); a = IFA_RTA(ifaddrmsg); @@ -205,9 +203,26 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat while (RTA_OK(a, l)) { switch(a->rta_type) { + case IFA_ADDRESS: - /* Fill in address data */ - + + if ((rlocal.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) || + (rlocal.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4)) + return; + + memcpy(rlocal.data.data, RTA_DATA(a), RTA_PAYLOAD(a)); + rlocal_valid = 1; + + break; + + case IFA_LOCAL: + + /* Fill in local address data. Usually this is + * preferable over IFA_ADDRESS if both are set, + * since this refers to the local address of a PPP + * link while IFA_ADDRESS refers to the other + * end. */ + if ((raddr.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) || (raddr.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4)) return; @@ -220,32 +235,37 @@ static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdat default: ; } - + a = RTA_NEXT(a, l); } /* If there was no adress attached to this message, let's quit. */ - if (!raddr_valid) + if (rlocal_valid) + r = &rlocal; + else if (raddr_valid) + r = &raddr; + else return; if (n->nlmsg_type == RTM_NEWADDR) { AvahiInterfaceAddress *addr; /* This address is new or has been modified, so let's get an object for it */ - if (!(addr = avahi_interface_monitor_get_address(m, i, &raddr))) + if (!(addr = avahi_interface_monitor_get_address(m, i, r))) /* Mmm, no object existing yet, so let's create a new one */ - if (!(addr = avahi_interface_address_new(m, i, &raddr, ifaddrmsg->ifa_prefixlen))) + if (!(addr = avahi_interface_address_new(m, i, r, ifaddrmsg->ifa_prefixlen))) return; /* OOM */ /* Update the scope field for the address */ addr->global_scope = ifaddrmsg->ifa_scope == RT_SCOPE_UNIVERSE || ifaddrmsg->ifa_scope == RT_SCOPE_SITE; + addr->deprecated = !!(ifaddrmsg->ifa_flags & IFA_F_DEPRECATED); } else { AvahiInterfaceAddress *addr; assert(n->nlmsg_type == RTM_DELADDR); /* Try to get a reference to our AvahiInterfaceAddress object for this address */ - if (!(addr = avahi_interface_monitor_get_address(m, i, &raddr))) + if (!(addr = avahi_interface_monitor_get_address(m, i, r))) return; /* And free it */ @@ -260,16 +280,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; @@ -300,14 +320,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)); } @@ -317,7 +337,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; @@ -361,7 +381,7 @@ void avahi_interface_monitor_sync(AvahiInterfaceMonitor *m) { /* Let's handle netlink events until we are done with wild * dumping */ - + while (!m->list_complete) if (!avahi_netlink_work(m->osdep.netlink, 1) == 0) break;