blob: 89d1dbd13687461a9d733fee566e79742a4a7f56 [file] [log] [blame]
Jeremy Kerr42dc98c2016-02-25 10:23:14 +08001/******************************************************************************
Jeremy Kerrf2101cf2016-03-03 14:49:52 +08002 * Copyright 2016 Foxconn
3 * Copyright 2016 IBM Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ******************************************************************************/
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080017
Jeremy Kerr52e24782016-03-03 14:51:35 +080018#include <errno.h>
Jeremy Kerre3f27cf2016-03-14 17:24:13 +080019#include <stdarg.h>
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080020#include <stdio.h>
Jeremy Kerrae153682016-03-14 16:59:19 +080021#include <stdbool.h>
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080022#include <stdlib.h>
23#include <string.h>
Jeremy Kerre3f27cf2016-03-14 17:24:13 +080024#include <syslog.h>
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080025#include <time.h>
26#include <unistd.h>
27
28#include <sys/ioctl.h>
Jeremy Kerrae153682016-03-14 16:59:19 +080029#include <sys/poll.h>
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080030#include <sys/socket.h>
31
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080032#include <arpa/inet.h>
Jeremy Kerr52e24782016-03-03 14:51:35 +080033#include <netinet/in.h>
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080034
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080035#include <linux/if_arp.h>
Jeremy Kerr52e24782016-03-03 14:51:35 +080036#include <linux/if_ether.h>
Jeremy Kerrae153682016-03-14 16:59:19 +080037#include <linux/if_link.h>
Jeremy Kerr52e24782016-03-03 14:51:35 +080038#include <linux/if_packet.h>
Jeremy Kerrae153682016-03-14 16:59:19 +080039#include <linux/netlink.h>
40#include <linux/rtnetlink.h>
Jeremy Kerr982b7bc2016-02-25 10:54:39 +080041
Jeremy Kerr71f385b2016-03-03 15:18:39 +080042struct eth_addr {
43 uint8_t eth_addr[ETH_ALEN];
44} __attribute__((packed));
45
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080046struct arp_packet {
Jeremy Kerrf2101cf2016-03-03 14:49:52 +080047 struct ethhdr eh;
48 struct arphdr arp;
Jeremy Kerr71f385b2016-03-03 15:18:39 +080049 struct eth_addr src_mac;
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080050 struct in_addr src_ip;
Jeremy Kerr71f385b2016-03-03 15:18:39 +080051 struct eth_addr dest_mac;
Jeremy Kerr760d6ac2016-02-25 14:45:33 +080052 struct in_addr dest_ip;
53} __attribute__((packed));
Jeremy Kerr42dc98c2016-02-25 10:23:14 +080054
Jeremy Kerr17cd0b02016-03-04 11:56:37 +080055struct interface {
Jeremy Kerre09d30d2016-03-04 11:42:03 +080056 int ifindex;
Jeremy Kerr17cd0b02016-03-04 11:56:37 +080057 char ifname[IFNAMSIZ+1];
58 struct eth_addr eth_addr;
59};
60
61struct inarp_ctx {
Jeremy Kerr84963a82016-03-14 14:46:09 +080062 int arp_sd;
Jeremy Kerrae153682016-03-14 16:59:19 +080063 int nl_sd;
Jeremy Kerr17cd0b02016-03-04 11:56:37 +080064 struct interface *interfaces;
65 unsigned int n_interfaces;
Jeremy Kerre3f27cf2016-03-14 17:24:13 +080066 bool syslog;
67 bool debug;
Jeremy Kerre09d30d2016-03-04 11:42:03 +080068};
69
Jeremy Kerre3f27cf2016-03-14 17:24:13 +080070static __attribute__((format(printf, 3, 4)))
71 void inarp_log(struct inarp_ctx *inarp,
72 int priority,
73 const char *format, ...)
74{
75 va_list ap;
76
77 if (priority > LOG_INFO && !inarp->debug)
78 return;
79
80 va_start(ap, format);
81 if (inarp->syslog) {
82 vsyslog(priority, format, ap);
83 } else {
84 vprintf(format, ap);
85 printf("\n");
86 }
87
88 va_end(ap);
89}
90
Jeremy Kerrae153682016-03-14 16:59:19 +080091/* helpers for rtnetlink message iteration */
92#define for_each_nlmsg(buf, nlmsg, len) \
93 for (nlmsg = (struct nlmsghdr *)buf; \
94 NLMSG_OK(nlmsg, len) && nlmsg->nlmsg_type != NLMSG_DONE; \
95 nlmsg = NLMSG_NEXT(nlmsg, len))
96
97#define for_each_rta(buf, rta, attrlen) \
98 for (rta = (struct rtattr *)(buf); RTA_OK(rta, attrlen); \
99 rta = RTA_NEXT(rta, attrlen))
100
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800101static int send_arp_packet(struct inarp_ctx *inarp,
Jeremy Kerrf2101cf2016-03-03 14:49:52 +0800102 int ifindex,
Jeremy Kerr71f385b2016-03-03 15:18:39 +0800103 const struct eth_addr *src_mac,
Jeremy Kerr88384bc2016-03-03 14:52:50 +0800104 const struct in_addr *src_ip,
Jeremy Kerr71f385b2016-03-03 15:18:39 +0800105 const struct eth_addr *dest_mac,
Jeremy Kerr88384bc2016-03-03 14:52:50 +0800106 const struct in_addr *dest_ip)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800107{
Jeremy Kerr89dd5142016-02-25 19:40:02 +0800108 struct sockaddr_ll addr;
Jeremy Kerr5bb869d2016-02-25 18:47:08 +0800109 struct arp_packet arp;
Jeremy Kerrd7865332016-02-25 14:52:50 +0800110 int rc;
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800111
Jeremy Kerr5bb869d2016-02-25 18:47:08 +0800112 memset(&arp, 0, sizeof(arp));
113
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800114 /* Prepare our link-layer address: raw packet interface,
115 * using the ifindex interface, receiving ARP packets
116 */
Jeremy Kerr89dd5142016-02-25 19:40:02 +0800117 addr.sll_family = PF_PACKET;
118 addr.sll_protocol = htons(ETH_P_ARP);
119 addr.sll_ifindex = ifindex;
120 addr.sll_hatype = ARPHRD_ETHER;
121 addr.sll_pkttype = PACKET_OTHERHOST;
122 addr.sll_halen = ETH_ALEN;
123 memcpy(addr.sll_addr, dest_mac, ETH_ALEN);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800124
125 /* set the frame header */
Jeremy Kerr103a9582016-02-25 19:38:52 +0800126 memcpy(arp.eh.h_dest, dest_mac, ETH_ALEN);
127 memcpy(arp.eh.h_source, src_mac, ETH_ALEN);
Jeremy Kerr5bb869d2016-02-25 18:47:08 +0800128 arp.eh.h_proto = htons(ETH_P_ARP);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800129
130 /* Fill InARP request data for ethernet + ipv4 */
Jeremy Kerr5bb869d2016-02-25 18:47:08 +0800131 arp.arp.ar_hrd = htons(ARPHRD_ETHER);
132 arp.arp.ar_pro = htons(ETH_P_ARP);
133 arp.arp.ar_hln = ETH_ALEN;
134 arp.arp.ar_pln = 4;
135 arp.arp.ar_op = htons(ARPOP_InREPLY);
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800136
137 /* fill arp ethernet mac & ipv4 info */
Jeremy Kerr5bb869d2016-02-25 18:47:08 +0800138 memcpy(&arp.src_mac, src_mac, sizeof(arp.src_mac));
139 memcpy(&arp.src_ip, src_ip, sizeof(arp.src_ip));
140 memcpy(&arp.dest_mac, dest_mac, sizeof(arp.dest_mac));
141 memcpy(&arp.dest_ip, dest_ip, sizeof(arp.dest_ip));
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800142
143 /* send the packet */
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800144 rc = sendto(inarp->arp_sd, &arp, sizeof(arp), 0,
Jeremy Kerr89dd5142016-02-25 19:40:02 +0800145 (struct sockaddr *)&addr, sizeof(addr));
Jeremy Kerrd7865332016-02-25 14:52:50 +0800146 if (rc < 0)
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800147 inarp_log(inarp, LOG_NOTICE,
148 "Failure sending ARP response: %m");
Jeremy Kerrd7865332016-02-25 14:52:50 +0800149
150 return rc;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800151}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800152
Jeremy Kerr71f385b2016-03-03 15:18:39 +0800153static const char *eth_mac_to_str(const struct eth_addr *mac_addr)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800154{
Jeremy Kerrdf046132016-03-03 15:03:22 +0800155 static char mac_str[ETH_ALEN * (sizeof("00:") - 1)];
Jeremy Kerr71f385b2016-03-03 15:18:39 +0800156 const uint8_t *addr = mac_addr->eth_addr;
Jeremy Kerrdf046132016-03-03 15:03:22 +0800157
158 snprintf(mac_str, sizeof(mac_str),
159 "%02x:%02x:%02x:%02x:%02x:%02x",
Jeremy Kerr71f385b2016-03-03 15:18:39 +0800160 addr[0], addr[1], addr[2],
161 addr[3], addr[4], addr[5]);
Jeremy Kerrdf046132016-03-03 15:03:22 +0800162
163 return mac_str;
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800164}
Jeremy Kerr5514f7b2016-02-25 12:41:44 +0800165
Jeremy Kerrf3b373f2016-02-25 19:24:59 +0800166static int do_ifreq(int fd, unsigned long type,
167 const char *ifname, struct ifreq *ifreq)
168{
169 memset(ifreq, 0, sizeof(*ifreq));
Jeremy Kerr7275d5c2016-03-03 15:30:10 +0800170 strncpy(ifreq->ifr_name, ifname, sizeof(ifreq->ifr_name));
Jeremy Kerrf3b373f2016-02-25 19:24:59 +0800171
172 return ioctl(fd, type, ifreq);
173}
174
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800175static int get_local_ipaddr(struct inarp_ctx *inarp,
176 const char *ifname, struct in_addr *addr)
Jeremy Kerre54e4832016-02-25 17:23:10 +0800177{
178 struct sockaddr_in *sa;
179 struct ifreq ifreq;
180 int rc;
181
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800182 rc = do_ifreq(inarp->arp_sd, SIOCGIFADDR, ifname, &ifreq);
Jeremy Kerre54e4832016-02-25 17:23:10 +0800183 if (rc) {
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800184 inarp_log(inarp, LOG_WARNING,
185 "Error querying local IP address for %s: %m",
186 ifname);
Jeremy Kerre54e4832016-02-25 17:23:10 +0800187 return -1;
188 }
189
190 if (ifreq.ifr_addr.sa_family != AF_INET) {
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800191 inarp_log(inarp, LOG_WARNING,
192 "Unknown address family %d in address response",
193 ifreq.ifr_addr.sa_family);
Jeremy Kerre54e4832016-02-25 17:23:10 +0800194 return -1;
195 }
196
197 sa = (struct sockaddr_in *)&ifreq.ifr_addr;
198 memcpy(addr, &sa->sin_addr, sizeof(*addr));
199 return 0;
200}
201
Jeremy Kerra7c07192016-03-04 14:18:41 +0800202static struct interface *find_interface_by_ifindex(struct inarp_ctx *inarp,
203 int ifindex)
204{
205 unsigned int i;
206
207 for (i = 0; i < inarp->n_interfaces; i++) {
208 struct interface *iface = &inarp->interfaces[i];
209 if (iface->ifindex == ifindex)
210 return iface;
211 }
212
213 return NULL;
214}
215
Jeremy Kerrae153682016-03-14 16:59:19 +0800216static int init_netlink(struct inarp_ctx *inarp)
217{
218 struct sockaddr_nl addr;
219 int rc;
220 struct {
221 struct nlmsghdr nlmsg;
222 struct rtgenmsg rtmsg;
223 } msg;
224
225 /* create our socket to listen for rtnetlink events */
226 inarp->nl_sd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
227 if (inarp->nl_sd < 0) {
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800228 inarp_log(inarp, LOG_ERR, "Error opening netlink socket: %m");
Jeremy Kerrae153682016-03-14 16:59:19 +0800229 return -1;
230 }
231
232 memset(&addr, 0, sizeof(addr));
233 addr.nl_family = AF_NETLINK;
234 addr.nl_groups = RTMGRP_LINK;
235
236 rc = bind(inarp->nl_sd, (struct sockaddr *)&addr, sizeof(addr));
237 if (rc) {
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800238 inarp_log(inarp, LOG_ERR,
239 "Error binding to netlink address: %m");
Jeremy Kerrae153682016-03-14 16:59:19 +0800240 goto err_close;
241 }
242
243 /* send a query for current interfaces */
244 memset(&msg, 0, sizeof(msg));
245
246 msg.nlmsg.nlmsg_len = sizeof(msg);
247 msg.nlmsg.nlmsg_type = RTM_GETLINK;
248 msg.nlmsg.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
249 msg.rtmsg.rtgen_family = AF_UNSPEC;
250
251 rc = send(inarp->nl_sd, &msg, sizeof(msg), MSG_NOSIGNAL);
252 if (rc != sizeof(msg)) {
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800253 inarp_log(inarp, LOG_ERR, "Failed to query current links: %m");
Jeremy Kerrae153682016-03-14 16:59:19 +0800254 goto err_close;
255 }
256
257 return 0;
258
259err_close:
260 close(inarp->nl_sd);
261 return -1;
262}
263
264static void netlink_nlmsg_dellink(struct inarp_ctx *inarp,
265 struct interface *iface)
266{
267 int i;
268
269 if (!iface)
270 return;
271
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800272 inarp_log(inarp, LOG_NOTICE, "dropping interface: %s, [%s]",
273 iface->ifname, eth_mac_to_str(&iface->eth_addr));
Jeremy Kerrae153682016-03-14 16:59:19 +0800274
275 /* find the index of the array element to remove */
276 i = iface - inarp->interfaces;
277
278 /* remove interface from our array */
279 inarp->n_interfaces--;
280 inarp->interfaces = realloc(inarp->interfaces,
281 inarp->n_interfaces * sizeof(*iface));
282 memmove(iface, iface + 1,
283 sizeof(*iface) * (inarp->n_interfaces - i));
284
285}
286static void netlink_nlmsg_newlink(struct inarp_ctx *inarp,
287 struct interface *iface, struct ifinfomsg *ifmsg, int len)
288{
289 struct rtattr *attr;
290 bool new = false;
291
292 /*
293 * We shouldn't already have an interface for this ifindex; so create
294 * one. If we do, we'll update the hwaddr and name to the new values.
295 */
296 if (!iface) {
297 inarp->n_interfaces++;
298 inarp->interfaces = realloc(inarp->interfaces,
299 inarp->n_interfaces * sizeof(*iface));
300 iface = &inarp->interfaces[inarp->n_interfaces-1];
301 new = true;
302 }
303
304 memset(iface, 0, sizeof(*iface));
305 iface->ifindex = ifmsg->ifi_index;
306
307 for_each_rta(ifmsg + 1, attr, len) {
308 void *data = RTA_DATA(attr);
309
310 switch (attr->rta_type) {
311 case IFLA_ADDRESS:
312 memcpy(&iface->eth_addr.eth_addr, data,
313 sizeof(iface->eth_addr.eth_addr));
314 break;
315
316 case IFLA_IFNAME:
317 strncpy(iface->ifname, data, IFNAMSIZ);
318 break;
319 }
320 }
321
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800322 inarp_log(inarp, LOG_NOTICE, "%s interface: %s, [%s]",
Jeremy Kerrae153682016-03-14 16:59:19 +0800323 new ? "adding" : "updating",
324 iface->ifname,
325 eth_mac_to_str(&iface->eth_addr));
Jeremy Kerrae153682016-03-14 16:59:19 +0800326}
327
328static void netlink_nlmsg(struct inarp_ctx *inarp, struct nlmsghdr *nlmsg)
329{
330 struct ifinfomsg *ifmsg;
331 struct interface *iface;
332 int len;
333
334 len = nlmsg->nlmsg_len - sizeof(*ifmsg);
335 ifmsg = NLMSG_DATA(nlmsg);
336
337 iface = find_interface_by_ifindex(inarp, ifmsg->ifi_index);
338
339 switch (nlmsg->nlmsg_type) {
340 case RTM_DELLINK:
341 netlink_nlmsg_dellink(inarp, iface);
342 break;
343 case RTM_NEWLINK:
344 netlink_nlmsg_newlink(inarp, iface, ifmsg, len);
345 break;
346 default:
347 break;
348 }
349}
350
351static void netlink_recv(struct inarp_ctx *inarp)
352{
353 struct nlmsghdr *nlmsg;
354 uint8_t buf[16384];
355 int len;
356
357 len = recv(inarp->nl_sd, &buf, sizeof(buf), 0);
358 if (len < 0) {
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800359 inarp_log(inarp, LOG_NOTICE, "Error receiving netlink msg");
Jeremy Kerrae153682016-03-14 16:59:19 +0800360 return;
361 }
362
Patrick Williams04d1f972016-06-06 15:10:04 -0500363 size_t len_unsigned = (size_t)len;
364
365 for_each_nlmsg(buf, nlmsg, len_unsigned)
Jeremy Kerrae153682016-03-14 16:59:19 +0800366 netlink_nlmsg(inarp, nlmsg);
367}
368
369static void arp_recv(struct inarp_ctx *inarp)
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800370{
Jeremy Kerr3f8a28e2016-02-25 18:56:01 +0800371 struct arp_packet inarp_req;
Jeremy Kerrae153682016-03-14 16:59:19 +0800372 struct sockaddr_ll addr;
Jeremy Kerre09d30d2016-03-04 11:42:03 +0800373 struct in_addr local_ip;
Jeremy Kerr17cd0b02016-03-04 11:56:37 +0800374 struct interface *iface;
Jeremy Kerra7c07192016-03-04 14:18:41 +0800375 socklen_t addrlen;
Jeremy Kerrae153682016-03-14 16:59:19 +0800376 int len, rc;
377
378 addrlen = sizeof(addr);
379 len = recvfrom(inarp->arp_sd, &inarp_req,
380 sizeof(inarp_req), 0,
381 (struct sockaddr *)&addr, &addrlen);
382 if (len <= 0) {
383 if (errno == EINTR)
384 return;
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800385 inarp_log(inarp, LOG_WARNING,
Gunnar Mills6e296612018-08-14 11:59:02 -0500386 "Error receiving ARP packet");
Jeremy Kerrae153682016-03-14 16:59:19 +0800387 }
388
389 /*
390 * struct sockaddr_ll allows for 8 bytes of hardware address;
391 * we only need ETH_ALEN for a full ethernet address.
392 */
393 if (addrlen < sizeof(addr) - (8 - ETH_ALEN))
394 return;
395
396 if (addr.sll_family != AF_PACKET)
397 return;
398
399 iface = find_interface_by_ifindex(inarp, addr.sll_ifindex);
400 if (!iface)
401 return;
402
403 /* Is this packet large enough for an inarp? */
404 if ((size_t)len < sizeof(inarp_req))
405 return;
406
407 /* ... is it an inarp request? */
408 if (ntohs(inarp_req.arp.ar_op) != ARPOP_InREQUEST)
409 return;
410
411 /* ... for us? */
412 if (memcmp(&iface->eth_addr, inarp_req.eh.h_dest, ETH_ALEN))
413 return;
414
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800415 inarp_log(inarp, LOG_DEBUG,
416 "request from src mac: %s",
417 eth_mac_to_str(&inarp_req.src_mac));
Jeremy Kerrae153682016-03-14 16:59:19 +0800418
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800419 rc = get_local_ipaddr(inarp, iface->ifname, &local_ip);
Jeremy Kerrae153682016-03-14 16:59:19 +0800420 /* if we don't have a local IP address to send, just drop the
421 * request */
422 if (rc)
423 return;
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800424 inarp_log(inarp, LOG_DEBUG,
425 "responding with %s ip %s",
426 eth_mac_to_str(&iface->eth_addr),
427 inet_ntoa(local_ip));
Jeremy Kerrae153682016-03-14 16:59:19 +0800428
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800429 send_arp_packet(inarp, iface->ifindex,
Jeremy Kerrae153682016-03-14 16:59:19 +0800430 &inarp_req.dest_mac,
431 &local_ip,
432 &inarp_req.src_mac,
433 &inarp_req.src_ip);
434}
435
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800436int main(int argc, char **argv)
Jeremy Kerrae153682016-03-14 16:59:19 +0800437{
438 struct inarp_ctx inarp;
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800439 int ret, i;
Jeremy Kerr115522d2016-02-25 10:24:14 +0800440
Jeremy Kerr17cd0b02016-03-04 11:56:37 +0800441 memset(&inarp, 0, sizeof(inarp));
442
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800443 inarp.syslog = true;
444
445 for (i = 1; i < argc; i++) {
446 if (!strcmp(argv[i], "--debug"))
447 inarp.debug = true;
448 else if (!strcmp(argv[i], "--no-syslog"))
449 inarp.syslog = false;
450 }
451
452 if (inarp.syslog)
453 openlog("inarp", 0, LOG_DAEMON);
454
Jeremy Kerr84963a82016-03-14 14:46:09 +0800455 inarp.arp_sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800456 if (inarp.arp_sd < 0) {
457 inarp_log(&inarp, LOG_ERR, "Error opening ARP socket");
458 exit(EXIT_FAILURE);
459 }
Jeremy Kerrc10bedb2016-02-25 14:26:38 +0800460
Jeremy Kerrae153682016-03-14 16:59:19 +0800461 ret = init_netlink(&inarp);
Jeremy Kerr86489a12016-02-25 19:14:09 +0800462 if (ret)
463 exit(EXIT_FAILURE);
Jeremy Kerrd7865332016-02-25 14:52:50 +0800464
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800465 while (1) {
Jeremy Kerrae153682016-03-14 16:59:19 +0800466 struct pollfd pollfds[2];
Jeremy Kerr77cafea2016-02-25 17:15:28 +0800467
Jeremy Kerrae153682016-03-14 16:59:19 +0800468 pollfds[0].fd = inarp.arp_sd;
469 pollfds[0].events = POLLIN;
470 pollfds[1].fd = inarp.nl_sd;
471 pollfds[1].events = POLLIN;
Jeremy Kerra7c07192016-03-04 14:18:41 +0800472
Jeremy Kerrae153682016-03-14 16:59:19 +0800473 ret = poll(pollfds, 2, -1);
Jeremy Kerre3f27cf2016-03-14 17:24:13 +0800474 if (ret < 0) {
475 inarp_log(&inarp, LOG_ERR, "poll failed, exiting");
476 break;
477 }
Jeremy Kerra7c07192016-03-04 14:18:41 +0800478
Jeremy Kerrae153682016-03-14 16:59:19 +0800479 if (pollfds[0].revents)
480 arp_recv(&inarp);
Jeremy Kerra7c07192016-03-04 14:18:41 +0800481
Jeremy Kerrae153682016-03-14 16:59:19 +0800482 if (pollfds[1].revents)
483 netlink_recv(&inarp);
Jeremy Kerr3f8a28e2016-02-25 18:56:01 +0800484
Jeremy Kerr77cafea2016-02-25 17:15:28 +0800485
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800486 }
Jeremy Kerr84963a82016-03-14 14:46:09 +0800487 close(inarp.arp_sd);
Jeremy Kerrae153682016-03-14 16:59:19 +0800488 close(inarp.nl_sd);
Jeremy Kerr42dc98c2016-02-25 10:23:14 +0800489 return 0;
490}