blob: b8aac0f7cde0e9589fba724559ef0ed38be320c4 [file] [log] [blame]
Simon Kelley0a852542005-03-23 20:28:59 +00001/* dnsmasq is Copyright (c) 2000-2005 Simon Kelley
2
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.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11*/
12
13/* Author's email: simon@thekelleys.org.uk */
14
15#include "dnsmasq.h"
16
17#ifdef HAVE_RTNETLINK
18
Simon Kelley91dccd02005-03-31 17:48:32 +010019#include <linux/types.h>
Simon Kelley0a852542005-03-23 20:28:59 +000020#include <linux/netlink.h>
21#include <linux/rtnetlink.h>
22
23int netlink_init(void)
24{
25 struct sockaddr_nl addr;
26 int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
27
28 if (sock < 0)
29 return -1; /* no kernel support */
30
31 addr.nl_family = AF_NETLINK;
32 addr.nl_pad = 0;
33 addr.nl_pid = getpid();
34 addr.nl_groups = 0;
35
36 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
37 die("cannot bind netlink socket: %s", NULL);
38
39 return sock;
40}
41
42
43/* We borrow the DNS packet buffer here. (The DHCP one already has a packet in it)
44 Since it's used only within this routine, that's fine, just remember
45 that calling icmp_echo() will trash it */
46int netlink_process(struct daemon *daemon, int index, struct in_addr relay,
47 struct in_addr primary, struct dhcp_context **retp)
48{
49 struct sockaddr_nl addr;
50 struct nlmsghdr *h;
51 int len, found_primary = 0;
52 struct dhcp_context *ret = NULL;
53 static unsigned int seq = 0;
54
55 struct {
56 struct nlmsghdr nlh;
57 struct rtgenmsg g;
58 } req;
59
60 if (daemon->netlinkfd == -1)
61 return 0;
62
63 addr.nl_family = AF_NETLINK;
64 addr.nl_pad = 0;
65 addr.nl_groups = 0;
66 addr.nl_pid = 0; /* address to kernel */
67
68 req.nlh.nlmsg_len = sizeof(req);
69 req.nlh.nlmsg_type = RTM_GETADDR;
70 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
71 req.nlh.nlmsg_pid = 0;
72 req.nlh.nlmsg_seq = ++seq;
73 req.g.rtgen_family = AF_INET;
74
75 /* Don't block in recvfrom if send fails */
76 while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
77 (struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());
78
79 if (len == -1)
80 {
81 /* if RTnetlink not configured in the kernel, don't keep trying. */
82 if (errno == ECONNREFUSED)
83 {
84 close(daemon->netlinkfd);
85 daemon->netlinkfd = -1;
86 }
87 return 0;
88 }
89
90 get_next:
91 while((len = recvfrom(daemon->netlinkfd, daemon->packet, daemon->packet_buff_sz,
92 MSG_WAITALL, NULL, 0)) == -1 && retry_send());
93
94 if (len == -1)
95 return 0;
96
97 h = (struct nlmsghdr *)daemon->packet;
98
99 while (NLMSG_OK(h, (unsigned int)len))
100 {
101
102 if (h->nlmsg_seq != seq)
103 goto get_next;
104
105 if (h->nlmsg_type == NLMSG_DONE)
106 break;
107
108 if (h->nlmsg_type == NLMSG_ERROR)
109 return 0;
110
111 if (h->nlmsg_type == RTM_NEWADDR)
112 {
113 struct ifaddrmsg *ifa = NLMSG_DATA(h);
114
115 if (ifa->ifa_index == index && ifa->ifa_family == AF_INET)
116 {
117 struct rtattr *rta = IFA_RTA(ifa);
118 unsigned int len1 = h->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa));
119 struct in_addr netmask, addr, broadcast;
120
121 netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
122 addr.s_addr = 0;
123 broadcast.s_addr = 0;
124
125 while (RTA_OK(rta, len1))
126 {
127 if (rta->rta_type == IFA_LOCAL)
128 addr = *((struct in_addr *)(rta+1));
129 else if (rta->rta_type == IFA_BROADCAST)
130 broadcast = *((struct in_addr *)(rta+1));
131
132 rta = RTA_NEXT(rta, len1);
133 }
134
135 if (addr.s_addr && broadcast.s_addr)
136 {
137 ret = complete_context(daemon, addr, ret, netmask, broadcast, relay, primary);
138 if (addr.s_addr == primary.s_addr)
139 found_primary = 1;
140 }
141 }
142 }
143
144 h = NLMSG_NEXT(h, len);
145 }
146
147 *retp = ret;
148
149 return found_primary;
150}
151
152#endif
153
154