1 /* NHRP routing functions
2 * Copyright (c) 2014-2015 Timo Teräs
3 *
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include "nhrpd.h"
15 #include "table.h"
16 #include "memory.h"
17 #include "stream.h"
18 #include "log.h"
19 #include "zclient.h"
20
21 DEFINE_MTYPE_STATIC(NHRPD, NHRP_ROUTE, "NHRP routing entry")
22
23 static struct zclient *zclient;
24 static struct route_table *zebra_rib[AFI_MAX];
25
26 struct route_info {
27 union sockunion via;
28 struct interface *ifp;
29 struct interface *nhrp_ifp;
30 };
31
nhrp_route_update_get(const struct prefix * p,int create)32 static struct route_node *nhrp_route_update_get(const struct prefix *p,
33 int create)
34 {
35 struct route_node *rn;
36 afi_t afi = family2afi(PREFIX_FAMILY(p));
37
38 if (!zebra_rib[afi])
39 return NULL;
40
41 if (create) {
42 rn = route_node_get(zebra_rib[afi], p);
43 if (!rn->info) {
44 rn->info = XCALLOC(MTYPE_NHRP_ROUTE,
45 sizeof(struct route_info));
46 route_lock_node(rn);
47 }
48 return rn;
49 } else {
50 return route_node_lookup(zebra_rib[afi], p);
51 }
52 }
53
nhrp_route_update_put(struct route_node * rn)54 static void nhrp_route_update_put(struct route_node *rn)
55 {
56 struct route_info *ri = rn->info;
57
58 if (!ri->ifp && !ri->nhrp_ifp
59 && sockunion_family(&ri->via) == AF_UNSPEC) {
60 XFREE(MTYPE_NHRP_ROUTE, rn->info);
61 route_unlock_node(rn);
62 }
63 route_unlock_node(rn);
64 }
65
nhrp_route_update_zebra(const struct prefix * p,union sockunion * nexthop,struct interface * ifp)66 static void nhrp_route_update_zebra(const struct prefix *p,
67 union sockunion *nexthop,
68 struct interface *ifp)
69 {
70 struct route_node *rn;
71 struct route_info *ri;
72
73 rn = nhrp_route_update_get(
74 p, (sockunion_family(nexthop) != AF_UNSPEC) || ifp);
75 if (rn) {
76 ri = rn->info;
77 ri->via = *nexthop;
78 ri->ifp = ifp;
79 nhrp_route_update_put(rn);
80 }
81 }
82
nhrp_route_update_nhrp(const struct prefix * p,struct interface * ifp)83 void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp)
84 {
85 struct route_node *rn;
86 struct route_info *ri;
87
88 rn = nhrp_route_update_get(p, ifp != NULL);
89 if (rn) {
90 ri = rn->info;
91 ri->nhrp_ifp = ifp;
92 nhrp_route_update_put(rn);
93 }
94 }
95
nhrp_route_announce(int add,enum nhrp_cache_type type,const struct prefix * p,struct interface * ifp,const union sockunion * nexthop,uint32_t mtu)96 void nhrp_route_announce(int add, enum nhrp_cache_type type,
97 const struct prefix *p, struct interface *ifp,
98 const union sockunion *nexthop, uint32_t mtu)
99 {
100 struct zapi_route api;
101 struct zapi_nexthop *api_nh;
102 union sockunion *nexthop_ref = (union sockunion *)nexthop;
103
104 if (zclient->sock < 0)
105 return;
106
107 memset(&api, 0, sizeof(api));
108 api.type = ZEBRA_ROUTE_NHRP;
109 api.safi = SAFI_UNICAST;
110 api.vrf_id = VRF_DEFAULT;
111 api.prefix = *p;
112
113 switch (type) {
114 case NHRP_CACHE_NEGATIVE:
115 zapi_route_set_blackhole(&api, BLACKHOLE_REJECT);
116 ifp = NULL;
117 nexthop = NULL;
118 break;
119 case NHRP_CACHE_DYNAMIC:
120 case NHRP_CACHE_NHS:
121 case NHRP_CACHE_STATIC:
122 /* Regular route, so these are announced
123 * to other routing daemons */
124 break;
125 default:
126 SET_FLAG(api.flags, ZEBRA_FLAG_FIB_OVERRIDE);
127 break;
128 }
129 SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
130
131 SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
132 api.nexthop_num = 1;
133 api_nh = &api.nexthops[0];
134 api_nh->vrf_id = VRF_DEFAULT;
135
136 switch (api.prefix.family) {
137 case AF_INET:
138 if (api.prefix.prefixlen == IPV4_MAX_BITLEN &&
139 nexthop_ref &&
140 memcmp(&nexthop_ref->sin.sin_addr, &api.prefix.u.prefix4,
141 sizeof(struct in_addr)) == 0) {
142 nexthop_ref = NULL;
143 }
144 if (nexthop_ref) {
145 api_nh->gate.ipv4 = nexthop_ref->sin.sin_addr;
146 api_nh->type = NEXTHOP_TYPE_IPV4;
147 }
148 if (ifp) {
149 api_nh->ifindex = ifp->ifindex;
150 if (api_nh->type == NEXTHOP_TYPE_IPV4)
151 api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;
152 else
153 api_nh->type = NEXTHOP_TYPE_IFINDEX;
154 }
155 break;
156 case AF_INET6:
157 if (api.prefix.prefixlen == IPV6_MAX_BITLEN &&
158 nexthop_ref &&
159 memcmp(&nexthop_ref->sin6.sin6_addr, &api.prefix.u.prefix6,
160 sizeof(struct in6_addr)) == 0) {
161 nexthop_ref = NULL;
162 }
163 if (nexthop_ref) {
164 api_nh->gate.ipv6 = nexthop_ref->sin6.sin6_addr;
165 api_nh->type = NEXTHOP_TYPE_IPV6;
166 }
167 if (ifp) {
168 api_nh->ifindex = ifp->ifindex;
169 if (api_nh->type == NEXTHOP_TYPE_IPV6)
170 api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
171 else
172 api_nh->type = NEXTHOP_TYPE_IFINDEX;
173 }
174 break;
175 }
176 if (mtu) {
177 SET_FLAG(api.message, ZAPI_MESSAGE_MTU);
178 api.mtu = mtu;
179 }
180
181 if (unlikely(debug_flags & NHRP_DEBUG_ROUTE)) {
182 char buf[2][PREFIX_STRLEN];
183
184 prefix2str(&api.prefix, buf[0], sizeof(buf[0]));
185 zlog_debug(
186 "Zebra send: route %s %s nexthop %s metric %u count %d dev %s",
187 add ? "add" : "del", buf[0],
188 nexthop_ref ? inet_ntop(api.prefix.family,
189 &api_nh->gate,
190 buf[1], sizeof(buf[1]))
191 : "<onlink>",
192 api.metric, api.nexthop_num, ifp ? ifp->name : "none");
193 }
194
195 zclient_route_send(add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE, zclient,
196 &api);
197 }
198
nhrp_route_read(ZAPI_CALLBACK_ARGS)199 int nhrp_route_read(ZAPI_CALLBACK_ARGS)
200 {
201 struct zapi_route api;
202 struct zapi_nexthop *api_nh;
203 struct interface *ifp = NULL;
204 union sockunion nexthop_addr;
205 char buf[2][PREFIX_STRLEN];
206 int added;
207
208 if (zapi_route_decode(zclient->ibuf, &api) < 0)
209 return -1;
210
211 /* we completely ignore srcdest routes for now. */
212 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_SRCPFX))
213 return 0;
214
215 /* ignore our routes */
216 if (api.type == ZEBRA_ROUTE_NHRP)
217 return 0;
218
219 sockunion_family(&nexthop_addr) = AF_UNSPEC;
220 if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)) {
221 api_nh = &api.nexthops[0];
222
223 nexthop_addr.sa.sa_family = api.prefix.family;
224 switch (nexthop_addr.sa.sa_family) {
225 case AF_INET:
226 nexthop_addr.sin.sin_addr = api_nh->gate.ipv4;
227 break;
228 case AF_INET6:
229 nexthop_addr.sin6.sin6_addr = api_nh->gate.ipv6;
230 break;
231 }
232
233 if (api_nh->ifindex != IFINDEX_INTERNAL)
234 ifp = if_lookup_by_index(api_nh->ifindex, VRF_DEFAULT);
235 }
236
237 added = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
238 debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %s via %s dev %s",
239 added ? "add" : "del",
240 prefix2str(&api.prefix, buf[0], sizeof(buf[0])),
241 sockunion2str(&nexthop_addr, buf[1], sizeof(buf[1])),
242 ifp ? ifp->name : "(none)");
243
244 nhrp_route_update_zebra(&api.prefix, &nexthop_addr, ifp);
245 nhrp_shortcut_prefix_change(&api.prefix, !added);
246
247 return 0;
248 }
249
nhrp_route_get_nexthop(const union sockunion * addr,struct prefix * p,union sockunion * via,struct interface ** ifp)250 int nhrp_route_get_nexthop(const union sockunion *addr, struct prefix *p,
251 union sockunion *via, struct interface **ifp)
252 {
253 struct route_node *rn;
254 struct route_info *ri;
255 struct prefix lookup;
256 afi_t afi = family2afi(sockunion_family(addr));
257 char buf[PREFIX_STRLEN];
258
259 sockunion2hostprefix(addr, &lookup);
260
261 rn = route_node_match(zebra_rib[afi], &lookup);
262 if (!rn)
263 return 0;
264
265 ri = rn->info;
266 if (ri->nhrp_ifp) {
267 debugf(NHRP_DEBUG_ROUTE, "lookup %s: nhrp_if=%s",
268 prefix2str(&lookup, buf, sizeof(buf)),
269 ri->nhrp_ifp->name);
270
271 if (via)
272 sockunion_family(via) = AF_UNSPEC;
273 if (ifp)
274 *ifp = ri->nhrp_ifp;
275 } else {
276 debugf(NHRP_DEBUG_ROUTE, "lookup %s: zebra route dev %s",
277 prefix2str(&lookup, buf, sizeof(buf)),
278 ri->ifp ? ri->ifp->name : "(none)");
279
280 if (via)
281 *via = ri->via;
282 if (ifp)
283 *ifp = ri->ifp;
284 }
285 if (p)
286 *p = rn->p;
287 route_unlock_node(rn);
288 return 1;
289 }
290
nhrp_route_address(struct interface * in_ifp,union sockunion * addr,struct prefix * p,struct nhrp_peer ** peer)291 enum nhrp_route_type nhrp_route_address(struct interface *in_ifp,
292 union sockunion *addr, struct prefix *p,
293 struct nhrp_peer **peer)
294 {
295 struct interface *ifp = in_ifp;
296 struct nhrp_interface *nifp;
297 struct nhrp_cache *c;
298 union sockunion via[4];
299 uint32_t network_id = 0;
300 afi_t afi = family2afi(sockunion_family(addr));
301 int i;
302
303 if (ifp) {
304 nifp = ifp->info;
305 network_id = nifp->afi[afi].network_id;
306
307 c = nhrp_cache_get(ifp, addr, 0);
308 if (c && c->cur.type == NHRP_CACHE_LOCAL) {
309 if (p)
310 memset(p, 0, sizeof(*p));
311 return NHRP_ROUTE_LOCAL;
312 }
313 }
314
315 for (i = 0; i < 4; i++) {
316 if (!nhrp_route_get_nexthop(addr, p, &via[i], &ifp))
317 return NHRP_ROUTE_BLACKHOLE;
318 if (ifp) {
319 /* Departing from nbma network? */
320 nifp = ifp->info;
321 if (network_id
322 && network_id != nifp->afi[afi].network_id)
323 return NHRP_ROUTE_OFF_NBMA;
324 }
325 if (sockunion_family(&via[i]) == AF_UNSPEC)
326 break;
327 /* Resolve via node, but return the prefix of first match */
328 addr = &via[i];
329 p = NULL;
330 }
331
332 if (ifp) {
333 c = nhrp_cache_get(ifp, addr, 0);
334 if (c && c->cur.type >= NHRP_CACHE_DYNAMIC) {
335 if (p)
336 memset(p, 0, sizeof(*p));
337 if (c->cur.type == NHRP_CACHE_LOCAL)
338 return NHRP_ROUTE_LOCAL;
339 if (peer)
340 *peer = nhrp_peer_ref(c->cur.peer);
341 return NHRP_ROUTE_NBMA_NEXTHOP;
342 }
343 }
344
345 return NHRP_ROUTE_BLACKHOLE;
346 }
347
nhrp_zebra_connected(struct zclient * zclient)348 static void nhrp_zebra_connected(struct zclient *zclient)
349 {
350 zclient_send_reg_requests(zclient, VRF_DEFAULT);
351 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
352 ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
353 zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6,
354 ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
355 }
356
nhrp_zebra_init(void)357 void nhrp_zebra_init(void)
358 {
359 zebra_rib[AFI_IP] = route_table_init();
360 zebra_rib[AFI_IP6] = route_table_init();
361
362 zclient = zclient_new(master, &zclient_options_default);
363 zclient->zebra_connected = nhrp_zebra_connected;
364 zclient->interface_address_add = nhrp_interface_address_add;
365 zclient->interface_address_delete = nhrp_interface_address_delete;
366 zclient->redistribute_route_add = nhrp_route_read;
367 zclient->redistribute_route_del = nhrp_route_read;
368
369 zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs);
370 }
371
nhrp_table_node_cleanup(struct route_table * table,struct route_node * node)372 static void nhrp_table_node_cleanup(struct route_table *table,
373 struct route_node *node)
374 {
375 if (!node->info)
376 return;
377
378 XFREE(MTYPE_NHRP_ROUTE, node->info);
379 }
380
nhrp_zebra_terminate(void)381 void nhrp_zebra_terminate(void)
382 {
383 zclient_stop(zclient);
384 zclient_free(zclient);
385
386 zebra_rib[AFI_IP]->cleanup = nhrp_table_node_cleanup;
387 zebra_rib[AFI_IP6]->cleanup = nhrp_table_node_cleanup;
388 route_table_finish(zebra_rib[AFI_IP]);
389 route_table_finish(zebra_rib[AFI_IP6]);
390 }
391