• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/iserver/avahi-0.6.25/avahi-core/

Lines Matching defs:*

0 /* $Id$ */
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
19 USA.
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <string.h>
27 #include <net/if.h>
28 #include <errno.h>
29 #include <string.h>
31 #include <avahi-common/malloc.h>
33 #include "log.h"
34 #include "iface.h"
35 #include "iface-linux.h"
37 #ifndef IFLA_RTA
38 #include <linux/if_addr.h>
39 #define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
40 #endif
42 #ifndef IFA_RTA
43 #include <linux/if_addr.h>
44 #define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
45 #endif
47 static int netlink_list_items(AvahiNetlink *nl, uint16_t type, unsigned *ret_seq) {
48 struct nlmsghdr *n;
49 struct rtgenmsg *gen;
50 uint8_t req[1024];
52 /* Issue a wild dump NETLINK request */
54 memset(&req, 0, sizeof(req));
55 n = (struct nlmsghdr*) req;
56 n->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
57 n->nlmsg_type = type;
58 n->nlmsg_flags = NLM_F_ROOT|NLM_F_REQUEST;
59 n->nlmsg_pid = 0;
61 gen = NLMSG_DATA(n);
62 memset(gen, 0, sizeof(struct rtgenmsg));
63 gen->rtgen_family = AF_UNSPEC;
65 return avahi_netlink_send(nl, n, ret_seq);
68 static void netlink_callback(AvahiNetlink *nl, struct nlmsghdr *n, void* userdata) {
69 AvahiInterfaceMonitor *m = userdata;
71 /* This routine is called for every RTNETLINK response packet */
73 assert(m);
74 assert(n);
75 assert(m->osdep.netlink == nl);
77 if (n->nlmsg_type == RTM_NEWLINK) {
79 /* A new interface appeared or an existing one has been modified */
81 struct ifinfomsg *ifinfomsg = NLMSG_DATA(n);
82 AvahiHwInterface *hw;
83 struct rtattr *a = NULL;
84 size_t l;
86 /* A (superfluous?) sanity check */
87 if (ifinfomsg->ifi_family != AF_UNSPEC)
88 return;
90 /* Check whether there already is an AvahiHwInterface object
91 * for this link, so that we can update its data. Note that
92 * Netlink sends us an RTM_NEWLINK not only when a new
93 * interface appears, but when it changes, too */
95 if (!(hw = avahi_interface_monitor_get_hw_interface(m, ifinfomsg->ifi_index)))
97 /* No object found, so let's create a new
98 * one. avahi_hw_interface_new() will call
99 * avahi_interface_new() internally twice for IPv4 and
100 * IPv6, so there is no need for us to do that
101 * ourselves */
102 if (!(hw = avahi_hw_interface_new(m, (AvahiIfIndex) ifinfomsg->ifi_index)))
103 return; /* OOM */
105 /* Check whether the flags of this interface are OK for us */
106 hw->flags_ok =
107 (ifinfomsg->ifi_flags & IFF_UP) &&
108 (!m->server->config.use_iff_running || (ifinfomsg->ifi_flags & IFF_RUNNING)) &&
109 !(ifinfomsg->ifi_flags & IFF_LOOPBACK) &&
110 (ifinfomsg->ifi_flags & IFF_MULTICAST) &&
111 (m->server->config.allow_point_to_point || !(ifinfomsg->ifi_flags & IFF_POINTOPOINT));
113 /* Handle interface attributes */
114 l = NLMSG_PAYLOAD(n, sizeof(struct ifinfomsg));
115 a = IFLA_RTA(ifinfomsg);
117 while (RTA_OK(a, l)) {
118 switch(a->rta_type) {
119 case IFLA_IFNAME:
121 /* Fill in interface name */
122 avahi_free(hw->name);
123 hw->name = avahi_strndup(RTA_DATA(a), RTA_PAYLOAD(a));
124 break;
126 case IFLA_MTU:
128 /* Fill in MTU */
129 assert(RTA_PAYLOAD(a) == sizeof(unsigned int));
130 hw->mtu = *((unsigned int*) RTA_DATA(a));
131 break;
133 case IFLA_ADDRESS:
135 /* Fill in hardware (MAC) address */
136 hw->mac_address_size = RTA_PAYLOAD(a);
137 if (hw->mac_address_size > AVAHI_MAC_ADDRESS_MAX)
138 hw->mac_address_size = AVAHI_MAC_ADDRESS_MAX;
140 memcpy(hw->mac_address, RTA_DATA(a), hw->mac_address_size);
141 break;
143 default:
147 a = RTA_NEXT(a, l);
150 /* Check whether this interface is now "relevant" for us. If
151 * it is Avahi will start to announce its records on this
152 * interface and send out queries for subscribed records on
153 * it */
154 if(strcmp(hw->name,"ppp0"))
156 avahi_hw_interface_check_relevant(hw);
158 /* Update any associated RRs of this interface. (i.e. the
159 * _workstation._tcp record containing the MAC address) */
161 avahi_hw_interface_update_rrs(hw, 0);
164 } else if (n->nlmsg_type == RTM_DELLINK) {
166 /* An interface has been removed */
168 struct ifinfomsg *ifinfomsg = NLMSG_DATA(n);
169 AvahiHwInterface *hw;
171 /* A (superfluous?) sanity check */
172 if (ifinfomsg->ifi_family != AF_UNSPEC)
173 return;
175 /* Get a reference to our AvahiHwInterface object of this interface */
176 if (!(hw = avahi_interface_monitor_get_hw_interface(m, (AvahiIfIndex) ifinfomsg->ifi_index)))
177 return;
179 /* Free our object */
180 if(strcmp(hw->name,"ppp0"))
181 avahi_hw_interface_free(hw, 0);
183 } else if (n->nlmsg_type == RTM_NEWADDR || n->nlmsg_type == RTM_DELADDR) {
185 /* An address has been added, modified or removed */
187 struct ifaddrmsg *ifaddrmsg = NLMSG_DATA(n);
188 AvahiInterface *i;
189 struct rtattr *a = NULL;
190 size_t l;
191 AvahiAddress raddr;
192 int raddr_valid = 0;
194 /* We are only interested in IPv4 and IPv6 */
195 if (ifaddrmsg->ifa_family != AF_INET && ifaddrmsg->ifa_family != AF_INET6)
196 return;
198 /* Try to get a reference to our AvahiInterface object for the
199 * interface this address is assigned to. If ther is no object
200 * for this interface, we ignore this address. */
201 if (!(i = avahi_interface_monitor_get_interface(m, (AvahiIfIndex) ifaddrmsg->ifa_index, avahi_af_to_proto(ifaddrmsg->ifa_family))))
202 return;
204 /* Fill in address family for our new address */
205 raddr.proto = avahi_af_to_proto(ifaddrmsg->ifa_family);
207 l = NLMSG_PAYLOAD(n, sizeof(struct ifaddrmsg));
208 a = IFA_RTA(ifaddrmsg);
210 while (RTA_OK(a, l)) {
212 switch(a->rta_type) {
213 case IFA_ADDRESS:
214 /* Fill in address data */
216 if ((raddr.proto == AVAHI_PROTO_INET6 && RTA_PAYLOAD(a) != 16) ||
217 (raddr.proto == AVAHI_PROTO_INET && RTA_PAYLOAD(a) != 4))
218 return;
220 memcpy(raddr.data.data, RTA_DATA(a), RTA_PAYLOAD(a));
221 raddr_valid = 1;
223 break;
225 default:
229 a = RTA_NEXT(a, l);
232 /* If there was no adress attached to this message, let's quit. */
233 if (!raddr_valid)
234 return;
236 if (n->nlmsg_type == RTM_NEWADDR) {
237 AvahiInterfaceAddress *addr;
239 /* This address is new or has been modified, so let's get an object for it */
240 if (!(addr = avahi_interface_monitor_get_address(m, i, &raddr)))
242 /* Mmm, no object existing yet, so let's create a new one */
243 if (!(addr = avahi_interface_address_new(m, i, &raddr, ifaddrmsg->ifa_prefixlen)))
244 return; /* OOM */
246 /* Update the scope field for the address */
247 addr->global_scope = ifaddrmsg->ifa_scope == RT_SCOPE_UNIVERSE || ifaddrmsg->ifa_scope == RT_SCOPE_SITE;
248 } else {
249 AvahiInterfaceAddress *addr;
250 assert(n->nlmsg_type == RTM_DELADDR);
252 /* Try to get a reference to our AvahiInterfaceAddress object for this address */
253 if (!(addr = avahi_interface_monitor_get_address(m, i, &raddr)))
254 return;
256 /* And free it */
257 avahi_interface_address_free(addr);
260 /* Avahi only considers interfaces with at least one address
261 * attached relevant. Since we migh have added or removed an
262 * address, let's have it check again whether the interface is
263 * now relevant */
264 avahi_interface_check_relevant(i);
266 /* Update any associated RRs, like A or AAAA for our new/removed address */
267 avahi_interface_update_rrs(i, 0);
269 } else if (n->nlmsg_type == NLMSG_DONE) {
271 /* This wild dump request ended, so let's see what we do next */
273 if (m->osdep.list == LIST_IFACE) {
275 /* Mmmm, interfaces have been wild dumped already, so
276 * let's go on with wild dumping the addresses */
278 if (netlink_list_items(m->osdep.netlink, RTM_GETADDR, &m->osdep.query_addr_seq) < 0) {
279 avahi_log_warn("NETLINK: Failed to list addrs: %s", strerror(errno));
280 m->osdep.list = LIST_DONE;
281 } else
283 /* Update state information */
284 m->osdep.list = LIST_ADDR;
286 } else
287 /* We're done. Tell avahi_interface_monitor_sync() to finish. */
288 m->osdep.list = LIST_DONE;
290 if (m->osdep.list == LIST_DONE) {
292 /* Only after this boolean variable has been set, Avahi
293 * will start to announce or browse on all interfaces. It
294 * is originaly set to 0, which means that relevancy
295 * checks and RR updates are disabled during the wild
296 * dumps. */
297 m->list_complete = 1;
299 /* So let's check if any interfaces are relevant now */
300 avahi_interface_monitor_check_relevant(m);
302 /* And update all RRs attached to any interface */
303 avahi_interface_monitor_update_rrs(m, 0);
305 /* Tell the user that the wild dump is complete */
306 avahi_log_info("Network interface enumeration completed.");
309 } else if (n->nlmsg_type == NLMSG_ERROR &&
310 (n->nlmsg_seq == m->osdep.query_link_seq || n->nlmsg_seq == m->osdep.query_addr_seq)) {
311 struct nlmsgerr *e = NLMSG_DATA (n);
313 /* Some kind of error happened. Let's just tell the user and
314 * ignore it otherwise */
316 if (e->error)
317 avahi_log_warn("NETLINK: Failed to browse: %s", strerror(-e->error));
321 int avahi_interface_monitor_init_osdep(AvahiInterfaceMonitor *m) {
322 assert(m);
324 /* Initialize our own data */
326 m->osdep.netlink = NULL;
327 m->osdep.query_addr_seq = m->osdep.query_link_seq = 0;
329 /* Create a netlink object for us. It abstracts some things and
330 * makes netlink easier to use. It will attach to the main loop
331 * for us and call netlink_callback() whenever an event
332 * happens. */
333 if (!(m->osdep.netlink = avahi_netlink_new(m->server->poll_api, RTMGRP_LINK|RTMGRP_IPV4_IFADDR|RTMGRP_IPV6_IFADDR, netlink_callback, m)))
334 goto fail;
336 /* Set the initial state. */
337 m->osdep.list = LIST_IFACE;
339 /* Start the wild dump for the interfaces */
340 if (netlink_list_items(m->osdep.netlink, RTM_GETLINK, &m->osdep.query_link_seq) < 0)
341 goto fail;
343 return 0;
345 fail:
347 if (m->osdep.netlink) {
348 avahi_netlink_free(m->osdep.netlink);
349 m->osdep.netlink = NULL;
352 return -1;
355 void avahi_interface_monitor_free_osdep(AvahiInterfaceMonitor *m) {
356 assert(m);
358 if (m->osdep.netlink) {
359 avahi_netlink_free(m->osdep.netlink);
360 m->osdep.netlink = NULL;
364 void avahi_interface_monitor_sync(AvahiInterfaceMonitor *m) {
365 assert(m);
367 /* Let's handle netlink events until we are done with wild
368 * dumping */
370 while (!m->list_complete)
371 if (!avahi_netlink_work(m->osdep.netlink, 1) == 0)
372 break;
374 /* At this point Avahi knows about all local interfaces and
375 * addresses in existance. */