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