]> git.proxmox.com Git - mirror_frr.git/blame - nhrpd/netlink_arp.c
*: Convert thread_cancelXXX to event_cancelXXX
[mirror_frr.git] / nhrpd / netlink_arp.c
CommitLineData
acddc0ed 1// SPDX-License-Identifier: GPL-2.0-or-later
2fb975da
TT
2/* NHRP netlink/neighbor table arpd code
3 * Copyright (c) 2014-2016 Timo Teräs
2fb975da
TT
4 */
5
b45ac5f5
DL
6#ifdef HAVE_CONFIG_H
7#include "config.h"
8#endif
9
2fb975da
TT
10#include <fcntl.h>
11#include <net/if.h>
12#include <netinet/if_ether.h>
13#include <linux/netlink.h>
14#include <linux/neighbour.h>
15#include <linux/netfilter/nfnetlink_log.h>
16
cb37cb33 17#include "event.h"
b3b75104
PG
18#include "stream.h"
19#include "prefix.h"
2fb975da
TT
20#include "nhrpd.h"
21#include "netlink.h"
22#include "znl.h"
23
2fb975da
TT
24int netlink_nflog_group;
25static int netlink_log_fd = -1;
e6685141 26static struct event *netlink_log_thread;
2fb975da 27
996c9314
LB
28void netlink_update_binding(struct interface *ifp, union sockunion *proto,
29 union sockunion *nbma)
2fb975da 30{
05657ec2 31 nhrp_send_zebra_nbr(proto, nbma, ifp);
2fb975da
TT
32}
33
2fb975da
TT
34static void netlink_log_register(int fd, int group)
35{
36 struct nlmsghdr *n;
37 struct nfgenmsg *nf;
38 struct nfulnl_msg_config_cmd cmd;
39 struct zbuf *zb = zbuf_alloc(512);
40
996c9314
LB
41 n = znl_nlmsg_push(zb, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG,
42 NLM_F_REQUEST | NLM_F_ACK);
2fb975da 43 nf = znl_push(zb, sizeof(*nf));
996c9314 44 *nf = (struct nfgenmsg){
2fb975da
TT
45 .nfgen_family = AF_UNSPEC,
46 .version = NFNETLINK_V0,
47 .res_id = htons(group),
48 };
49 cmd.command = NFULNL_CFG_CMD_BIND;
50 znl_rta_push(zb, NFULA_CFG_CMD, &cmd, sizeof(cmd));
51 znl_nlmsg_complete(zb, n);
52
53 zbuf_send(zb, fd);
54 zbuf_free(zb);
55}
56
57static void netlink_log_indication(struct nlmsghdr *msg, struct zbuf *zb)
58{
59 struct nfgenmsg *nf;
60 struct rtattr *rta;
61 struct zbuf rtapl, pktpl;
62 struct interface *ifp;
63 struct nfulnl_msg_packet_hdr *pkthdr = NULL;
64 uint32_t *in_ndx = NULL;
65
66 nf = znl_pull(zb, sizeof(*nf));
996c9314
LB
67 if (!nf)
68 return;
2fb975da
TT
69
70 memset(&pktpl, 0, sizeof(pktpl));
71 while ((rta = znl_rta_pull(zb, &rtapl)) != NULL) {
72 switch (rta->rta_type) {
73 case NFULA_PACKET_HDR:
74 pkthdr = znl_pull(&rtapl, sizeof(*pkthdr));
75 break;
76 case NFULA_IFINDEX_INDEV:
77 in_ndx = znl_pull(&rtapl, sizeof(*in_ndx));
78 break;
79 case NFULA_PAYLOAD:
80 pktpl = rtapl;
81 break;
996c9314
LB
82 /* NFULA_HWHDR exists and is supposed to contain source
83 * hardware address. However, for ip_gre it seems to be
84 * the nexthop destination address if the packet matches
85 * route. */
2fb975da
TT
86 }
87 }
88
89 if (!pkthdr || !in_ndx || !zbuf_used(&pktpl))
90 return;
91
7e2b7603 92 ifp = if_lookup_by_index(htonl(*in_ndx), VRF_DEFAULT);
2fb975da
TT
93 if (!ifp)
94 return;
95
96 nhrp_peer_send_indication(ifp, htons(pkthdr->hw_protocol), &pktpl);
97}
98
e6685141 99static void netlink_log_recv(struct event *t)
2fb975da
TT
100{
101 uint8_t buf[ZNL_BUFFER_SIZE];
102 int fd = THREAD_FD(t);
103 struct zbuf payload, zb;
104 struct nlmsghdr *n;
105
2fb975da
TT
106
107 zbuf_init(&zb, buf, sizeof(buf), 0);
108 while (zbuf_recv(&zb, fd) > 0) {
831600c3 109 while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
996c9314
LB
110 debugf(NHRP_DEBUG_KERNEL,
111 "Netlink-log: Received msg_type %u, msg_flags %u",
112 n->nlmsg_type, n->nlmsg_flags);
2fb975da 113 switch (n->nlmsg_type) {
996c9314 114 case (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_PACKET:
2fb975da
TT
115 netlink_log_indication(n, &payload);
116 break;
117 }
118 }
119 }
120
907a2395
DS
121 event_add_read(master, netlink_log_recv, 0, netlink_log_fd,
122 &netlink_log_thread);
2fb975da
TT
123}
124
125void netlink_set_nflog_group(int nlgroup)
126{
127 if (netlink_log_fd >= 0) {
332beb64 128 event_cancel(&netlink_log_thread);
2fb975da
TT
129 close(netlink_log_fd);
130 netlink_log_fd = -1;
131 }
132 netlink_nflog_group = nlgroup;
133 if (nlgroup) {
996c9314 134 netlink_log_fd = znl_open(NETLINK_NETFILTER, 0);
6c8ca260
JB
135 if (netlink_log_fd < 0)
136 return;
137
2fb975da 138 netlink_log_register(netlink_log_fd, nlgroup);
907a2395
DS
139 event_add_read(master, netlink_log_recv, 0, netlink_log_fd,
140 &netlink_log_thread);
2fb975da
TT
141 }
142}
143
a243d1db 144int nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
b3b75104
PG
145{
146 union sockunion addr = {}, lladdr = {};
147 struct interface *ifp;
b3b75104
PG
148 int state, ndm_state;
149 struct nhrp_cache *c;
d603c077
PG
150 struct zapi_neigh_ip api = {};
151
152 zclient_neigh_ip_decode(zclient->ibuf, &api);
153 if (api.ip_in.ipa_type == AF_UNSPEC)
a243d1db 154 return 0;
d603c077
PG
155 sockunion_family(&addr) = api.ip_in.ipa_type;
156 memcpy((uint8_t *)sockunion_get_addr(&addr), &api.ip_in.ip.addr,
157 family2addrsize(api.ip_in.ipa_type));
158
159 sockunion_family(&lladdr) = api.ip_out.ipa_type;
160 if (api.ip_out.ipa_type != AF_UNSPEC)
161 memcpy((uint8_t *)sockunion_get_addr(&lladdr),
162 &api.ip_out.ip.addr,
163 family2addrsize(api.ip_out.ipa_type));
164
165 ifp = if_lookup_by_index(api.index, vrf_id);
166 ndm_state = api.ndm_state;
167
b3b75104 168 if (!ifp)
a243d1db 169 return 0;
b3b75104
PG
170 c = nhrp_cache_get(ifp, &addr, 0);
171 if (!c)
a243d1db 172 return 0;
b3b75104
PG
173 debugf(NHRP_DEBUG_KERNEL,
174 "Netlink: %s %pSU dev %s lladdr %pSU nud 0x%x cache used %u type %u",
175 (cmd == ZEBRA_NHRP_NEIGH_GET)
176 ? "who-has"
177 : (cmd == ZEBRA_NHRP_NEIGH_ADDED) ? "new-neigh"
178 : "del-neigh",
179 &addr, ifp->name, &lladdr, ndm_state, c->used, c->cur.type);
180 if (cmd == ZEBRA_NHRP_NEIGH_GET) {
181 if (c->cur.type >= NHRP_CACHE_CACHED) {
182 nhrp_cache_set_used(c, 1);
183 debugf(NHRP_DEBUG_KERNEL,
184 "Netlink: update binding for %pSU dev %s from c %pSU peer.vc.nbma %pSU to lladdr %pSU",
185 &addr, ifp->name, &c->cur.remote_nbma_natoa,
186 &c->cur.peer->vc->remote.nbma, &lladdr);
187 /* In case of shortcuts, nbma is given by lladdr, not
188 * vc->remote.nbma.
189 */
190 netlink_update_binding(ifp, &addr, &lladdr);
191 }
192 } else {
193 state = (cmd == ZEBRA_NHRP_NEIGH_ADDED) ? ndm_state
d603c077
PG
194 : ZEBRA_NEIGH_STATE_FAILED;
195 nhrp_cache_set_used(c, state == ZEBRA_NEIGH_STATE_REACHABLE);
b3b75104 196 }
a243d1db 197 return 0;
b3b75104 198}