-#define SKIPRTA(rtmsgp, rta, sa) \
- do { \
- if ((rtmsgp)->rtm_addrs & (rta)) \
- (sa) = next_sa((sa)); \
- } while (0)
-
- rtm = (void *)di->di_buf;
-
- assert(rtm->rtm.rtm_type == RTM_NEWADDR ||
- rtm->rtm.rtm_type == RTM_DELADDR);
-
- if (rtm->rtm.rtm_index != ifindex)
- return (0);
-
- if (!(rtm->rtm.rtm_addrs & RTA_IFA)) {
- daemon_log(LOG_ERR, "ifa msg has no RTA_IFA.");
- return (0);
- }
-
- /* skip over rtmsg padding correctly */
- sa = (struct sockaddr *)((&rtm->ifam) + 1);
- SKIPRTA(&rtm->rtm, RTA_DST, sa);
- SKIPRTA(&rtm->rtm, RTA_GATEWAY, sa);
- SKIPRTA(&rtm->rtm, RTA_NETMASK, sa);
- SKIPRTA(&rtm->rtm, RTA_GENMASK, sa);
- SKIPRTA(&rtm->rtm, RTA_IFP, sa);
-
- /*
- * sa now points to RTA_IFA sockaddr; we are only interested
- * in updates for link-local addresses.
- */
- if (sa->sa_family != AF_INET)
- return (0);
- sin = (struct sockaddr_in *)sa;
- if (!IN_LINKLOCAL(ntohl(sin->sin_addr.s_addr)))
- return (0);
-
- for (ap = addresses; ap; ap = ap->addresses_next) {
- if (ap->address == sin->sin_addr.s_addr)
- break;
- }
- if (rtm->rtm.rtm_type == RTM_DELADDR && ap != NULL) {
- AVAHI_LLIST_REMOVE(Address, addresses, addresses, ap);
- avahi_free(ap);
- }
- if (rtm->rtm.rtm_type == RTM_NEWADDR && ap == NULL) {
- ap = avahi_new(Address, 1);
- ap->address = sin->sin_addr.s_addr;
- AVAHI_LLIST_PREPEND(Address, addresses, addresses, ap);
- }
-
- return (0);
+#define SKIPRTA(ifamsgp, rta, sa) \
+ do { \
+ if ((ifamsgp)->ifam_addrs & (rta)) \
+ (sa) = next_sa((sa)); \
+ } while (0)
+
+ ifam = &((rtmunion_t *)di->di_buf)->ifam;
+
+ assert(ifam->ifam_type == RTM_NEWADDR ||
+ ifam->ifam_type == RTM_DELADDR);
+
+ daemon_log(LOG_DEBUG, "%s: %s for iface %d (%s)", __func__,
+ ifam->ifam_type == RTM_NEWADDR ? "NEWADDR" : "DELADDR",
+ ifam->ifam_index, (ifam->ifam_index == ifindex) ? "ours" : "not ours");
+
+ if (ifam->ifam_index != ifindex)
+ return (0);
+
+ if (!(ifam->ifam_addrs & RTA_IFA)) {
+ daemon_log(LOG_ERR, "ifa msg has no RTA_IFA.");
+ return (0);
+ }
+
+ /* skip over rtmsg padding correctly */
+ sa = (struct sockaddr *)(ifam + 1);
+ SKIPRTA(ifam, RTA_DST, sa);
+ SKIPRTA(ifam, RTA_GATEWAY, sa);
+ SKIPRTA(ifam, RTA_NETMASK, sa);
+ SKIPRTA(ifam, RTA_GENMASK, sa);
+ SKIPRTA(ifam, RTA_IFP, sa);
+
+ /*
+ * sa now points to RTA_IFA sockaddr; we are only interested
+ * in updates for routable addresses.
+ */
+ if (sa->sa_family != AF_INET) {
+ daemon_log(LOG_DEBUG, "%s: RTA_IFA family not AF_INET (=%d)", __func__, sa->sa_family);
+ return (0);
+ }
+
+ sin = (struct sockaddr_in *)sa;
+ link_local = IN_LINKLOCAL(ntohl(sin->sin_addr.s_addr));
+
+ daemon_log(LOG_DEBUG, "%s: %s for %s (%s)", __func__,
+ ifam->ifam_type == RTM_NEWADDR ? "NEWADDR" : "DELADDR",
+ inet_ntoa(sin->sin_addr), link_local ? "link local" : "routable");
+
+ if (link_local)
+ return (0);
+
+ for (ap = addresses; ap; ap = ap->addresses_next) {
+ if (ap->address == sin->sin_addr.s_addr)
+ break;
+ }
+ if (ifam->ifam_type == RTM_DELADDR && ap != NULL) {
+ AVAHI_LLIST_REMOVE(Address, addresses, addresses, ap);
+ avahi_free(ap);
+ }
+ if (ifam->ifam_type == RTM_NEWADDR && ap == NULL) {
+ ap = avahi_new(Address, 1);
+ ap->address = sin->sin_addr.s_addr;
+ AVAHI_LLIST_PREPEND(Address, addresses, addresses, ap);
+ }
+
+ return (0);