1 /* dnsmasq is Copyright (c) 2000-2010 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifdef HAVE_LINUX_NETWORK
21 #include <linux/types.h>
22 #include <linux/netlink.h>
23 #include <linux/rtnetlink.h>
25 /* linux 2.6.19 buggers up the headers, patch it up here. */
28 ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
30 # include <linux/if_addr.h>
33 static struct iovec iov
;
34 static u32 netlink_pid
;
36 static void nl_err(struct nlmsghdr
*h
);
37 static void nl_routechange(struct nlmsghdr
*h
);
39 void netlink_init(void)
41 struct sockaddr_nl addr
;
42 socklen_t slen
= sizeof(addr
);
44 addr
.nl_family
= AF_NETLINK
;
46 addr
.nl_pid
= 0; /* autobind */
48 addr
.nl_groups
= RTMGRP_IPV4_ROUTE
| RTMGRP_IPV6_ROUTE
;
50 addr
.nl_groups
= RTMGRP_IPV4_ROUTE
;
53 /* May not be able to have permission to set multicast groups don't die in that case */
54 if ((daemon
->netlinkfd
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
)) != -1)
56 if (bind(daemon
->netlinkfd
, (struct sockaddr
*)&addr
, sizeof(addr
)) == -1)
59 if (errno
!= EPERM
|| bind(daemon
->netlinkfd
, (struct sockaddr
*)&addr
, sizeof(addr
)) == -1)
60 daemon
->netlinkfd
= -1;
64 if (daemon
->netlinkfd
== -1 ||
65 getsockname(daemon
->netlinkfd
, (struct sockaddr
*)&addr
, &slen
) == 1)
66 die(_("cannot create netlink socket: %s"), NULL
, EC_MISC
);
68 /* save pid assigned by bind() and retrieved by getsockname() */
69 netlink_pid
= addr
.nl_pid
;
72 iov
.iov_base
= safe_malloc(iov
.iov_len
);
75 static ssize_t
netlink_recv(void)
78 struct sockaddr_nl nladdr
;
83 msg
.msg_control
= NULL
;
84 msg
.msg_controllen
= 0;
85 msg
.msg_name
= &nladdr
;
86 msg
.msg_namelen
= sizeof(nladdr
);
91 while ((rc
= recvmsg(daemon
->netlinkfd
, &msg
, MSG_PEEK
| MSG_TRUNC
)) == -1 && errno
== EINTR
);
93 /* make buffer big enough */
94 if (rc
!= -1 && (msg
.msg_flags
& MSG_TRUNC
))
96 /* Very new Linux kernels return the actual size needed, older ones always return truncated size */
97 if ((size_t)rc
== iov
.iov_len
)
99 if (expand_buf(&iov
, rc
+ 100))
103 expand_buf(&iov
, rc
);
106 /* read it for real */
108 while ((rc
= recvmsg(daemon
->netlinkfd
, &msg
, 0)) == -1 && errno
== EINTR
);
110 /* Make sure this is from the kernel */
111 if (rc
== -1 || nladdr
.nl_pid
== 0)
115 /* discard stuff which is truncated at this point (expand_buf() may fail) */
116 if (msg
.msg_flags
& MSG_TRUNC
)
125 int iface_enumerate(void *parm
, int (*ipv4_callback
)(), int (*ipv6_callback
)())
127 struct sockaddr_nl addr
;
130 static unsigned int seq
= 0;
131 int family
= AF_INET
;
138 addr
.nl_family
= AF_NETLINK
;
141 addr
.nl_pid
= 0; /* address to kernel */
144 req
.nlh
.nlmsg_len
= sizeof(req
);
145 req
.nlh
.nlmsg_type
= RTM_GETADDR
;
146 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
| NLM_F_ACK
;
147 req
.nlh
.nlmsg_pid
= 0;
148 req
.nlh
.nlmsg_seq
= ++seq
;
149 req
.g
.rtgen_family
= family
;
151 /* Don't block in recvfrom if send fails */
152 while((len
= sendto(daemon
->netlinkfd
, (void *)&req
, sizeof(req
), 0,
153 (struct sockaddr
*)&addr
, sizeof(addr
))) == -1 && retry_send());
160 if ((len
= netlink_recv()) == -1)
162 if (errno
== ENOBUFS
)
170 for (h
= (struct nlmsghdr
*)iov
.iov_base
; NLMSG_OK(h
, (size_t)len
); h
= NLMSG_NEXT(h
, len
))
171 if (h
->nlmsg_seq
!= seq
|| h
->nlmsg_pid
!= netlink_pid
)
172 nl_routechange(h
); /* May be multicast arriving async */
173 else if (h
->nlmsg_type
== NLMSG_ERROR
)
175 else if (h
->nlmsg_type
== NLMSG_DONE
)
178 if (family
== AF_INET
&& ipv6_callback
)
186 else if (h
->nlmsg_type
== RTM_NEWADDR
)
188 struct ifaddrmsg
*ifa
= NLMSG_DATA(h
);
189 struct rtattr
*rta
= IFA_RTA(ifa
);
190 unsigned int len1
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof(*ifa
));
192 if (ifa
->ifa_family
== AF_INET
)
194 struct in_addr netmask
, addr
, broadcast
;
196 netmask
.s_addr
= htonl(0xffffffff << (32 - ifa
->ifa_prefixlen
));
198 broadcast
.s_addr
= 0;
200 while (RTA_OK(rta
, len1
))
202 if (rta
->rta_type
== IFA_LOCAL
)
203 addr
= *((struct in_addr
*)(rta
+1));
204 else if (rta
->rta_type
== IFA_BROADCAST
)
205 broadcast
= *((struct in_addr
*)(rta
+1));
207 rta
= RTA_NEXT(rta
, len1
);
210 if (addr
.s_addr
&& ipv4_callback
)
211 if (!((*ipv4_callback
)(addr
, ifa
->ifa_index
, netmask
, broadcast
, parm
)))
215 else if (ifa
->ifa_family
== AF_INET6
)
217 struct in6_addr
*addrp
= NULL
;
218 while (RTA_OK(rta
, len1
))
220 if (rta
->rta_type
== IFA_ADDRESS
)
221 addrp
= ((struct in6_addr
*)(rta
+1));
223 rta
= RTA_NEXT(rta
, len1
);
226 if (addrp
&& ipv6_callback
)
227 if (!((*ipv6_callback
)(addrp
, ifa
->ifa_index
, ifa
->ifa_index
, parm
)))
236 void netlink_multicast(void)
242 /* don't risk blocking reading netlink messages here. */
243 if ((flags
= fcntl(daemon
->netlinkfd
, F_GETFL
)) == -1 ||
244 fcntl(daemon
->netlinkfd
, F_SETFL
, flags
| O_NONBLOCK
) == -1)
247 if ((len
= netlink_recv()) != -1)
249 for (h
= (struct nlmsghdr
*)iov
.iov_base
; NLMSG_OK(h
, (size_t)len
); h
= NLMSG_NEXT(h
, len
))
250 if (h
->nlmsg_type
== NLMSG_ERROR
)
256 /* restore non-blocking status */
257 fcntl(daemon
->netlinkfd
, F_SETFL
, flags
);
260 static void nl_err(struct nlmsghdr
*h
)
262 struct nlmsgerr
*err
= NLMSG_DATA(h
);
265 my_syslog(LOG_ERR
, _("netlink returns error: %s"), strerror(-(err
->error
)));
268 /* We arrange to receive netlink multicast messages whenever the network route is added.
269 If this happens and we still have a DNS packet in the buffer, we re-send it.
270 This helps on DoD links, where frequently the packet which triggers dialling is
271 a DNS query, which then gets lost. By re-sending, we can avoid the lookup
272 failing. Note that we only accept these messages from the kernel (pid == 0) */
273 static void nl_routechange(struct nlmsghdr
*h
)
275 if (h
->nlmsg_pid
== 0 && h
->nlmsg_type
== RTM_NEWROUTE
)
277 struct rtmsg
*rtm
= NLMSG_DATA(h
);
280 if (rtm
->rtm_type
!= RTN_UNICAST
|| rtm
->rtm_scope
!= RT_SCOPE_LINK
)
283 /* Force re-reading resolv file right now, for luck. */
284 daemon
->last_resolv
= 0;
286 if (daemon
->srv_save
)
288 if (daemon
->srv_save
->sfd
)
289 fd
= daemon
->srv_save
->sfd
->fd
;
290 else if (daemon
->rfd_save
&& daemon
->rfd_save
->refcount
!= 0)
291 fd
= daemon
->rfd_save
->fd
;
295 while(sendto(fd
, daemon
->packet
, daemon
->packet_len
, 0,
296 &daemon
->srv_save
->addr
.sa
, sa_len(&daemon
->srv_save
->addr
)) == -1 && retry_send());