/src/frr/ospfd/ospf_zebra.c
Line  | Count  | Source  | 
1  |  | // SPDX-License-Identifier: GPL-2.0-or-later  | 
2  |  | /*  | 
3  |  |  * Zebra connect library for OSPFd  | 
4  |  |  * Copyright (C) 1997, 98, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada  | 
5  |  |  */  | 
6  |  |  | 
7  |  | #include <zebra.h>  | 
8  |  |  | 
9  |  | #include "frrevent.h"  | 
10  |  | #include "command.h"  | 
11  |  | #include "network.h"  | 
12  |  | #include "prefix.h"  | 
13  |  | #include "routemap.h"  | 
14  |  | #include "table.h"  | 
15  |  | #include "stream.h"  | 
16  |  | #include "memory.h"  | 
17  |  | #include "zclient.h"  | 
18  |  | #include "filter.h"  | 
19  |  | #include "plist.h"  | 
20  |  | #include "log.h"  | 
21  |  | #include "route_opaque.h"  | 
22  |  | #include "lib/bfd.h"  | 
23  |  | #include "lib/lib_errors.h"  | 
24  |  | #include "nexthop.h"  | 
25  |  |  | 
26  |  | #include "ospfd/ospfd.h"  | 
27  |  | #include "ospfd/ospf_interface.h"  | 
28  |  | #include "ospfd/ospf_ism.h"  | 
29  |  | #include "ospfd/ospf_asbr.h"  | 
30  |  | #include "ospfd/ospf_asbr.h"  | 
31  |  | #include "ospfd/ospf_abr.h"  | 
32  |  | #include "ospfd/ospf_lsa.h"  | 
33  |  | #include "ospfd/ospf_dump.h"  | 
34  |  | #include "ospfd/ospf_route.h"  | 
35  |  | #include "ospfd/ospf_lsdb.h"  | 
36  |  | #include "ospfd/ospf_neighbor.h"  | 
37  |  | #include "ospfd/ospf_nsm.h"  | 
38  |  | #include "ospfd/ospf_zebra.h"  | 
39  |  | #include "ospfd/ospf_te.h"  | 
40  |  | #include "ospfd/ospf_sr.h"  | 
41  |  | #include "ospfd/ospf_ldp_sync.h"  | 
42  |  |  | 
43  | 2  | DEFINE_MTYPE_STATIC(OSPFD, OSPF_EXTERNAL, "OSPF External route table");  | 
44  | 2  | DEFINE_MTYPE_STATIC(OSPFD, OSPF_REDISTRIBUTE, "OSPF Redistriute");  | 
45  | 2  |  | 
46  | 2  |  | 
47  | 2  | /* Zebra structure to hold current status. */  | 
48  | 2  | struct zclient *zclient = NULL;  | 
49  | 2  | /* and for the Synchronous connection to the Label Manager */  | 
50  | 2  | static struct zclient *zclient_sync;  | 
51  | 2  |  | 
52  | 2  | /* For registering threads. */  | 
53  | 2  | extern struct event_loop *master;  | 
54  | 2  |  | 
55  | 2  | /* Router-id update message from zebra. */  | 
56  | 2  | static int ospf_router_id_update_zebra(ZAPI_CALLBACK_ARGS)  | 
57  | 2  | { | 
58  | 0  |   struct ospf *ospf = NULL;  | 
59  | 0  |   struct prefix router_id;  | 
60  | 0  |   zebra_router_id_update_read(zclient->ibuf, &router_id);  | 
61  |  | 
  | 
62  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))  | 
63  | 0  |     zlog_debug("Zebra rcvd: router id update %pFX vrf %s id %u", | 
64  | 0  |          &router_id, ospf_vrf_id_to_name(vrf_id), vrf_id);  | 
65  |  | 
  | 
66  | 0  |   ospf = ospf_lookup_by_vrf_id(vrf_id);  | 
67  |  | 
  | 
68  | 0  |   if (ospf != NULL) { | 
69  | 0  |     ospf->router_id_zebra = router_id.u.prefix4;  | 
70  | 0  |     ospf_router_id_update(ospf);  | 
71  | 0  |   } else { | 
72  | 0  |     if (IS_DEBUG_OSPF_EVENT)  | 
73  | 0  |       zlog_debug(  | 
74  | 0  |         "%s: ospf instance not found for vrf %s id %u router_id %pFX",  | 
75  | 0  |         __func__, ospf_vrf_id_to_name(vrf_id), vrf_id,  | 
76  | 0  |         &router_id);  | 
77  | 0  |   }  | 
78  | 0  |   return 0;  | 
79  | 0  | }  | 
80  |  |  | 
81  |  | static int ospf_interface_address_add(ZAPI_CALLBACK_ARGS)  | 
82  | 0  | { | 
83  | 0  |   struct connected *c;  | 
84  | 0  |   struct ospf *ospf = NULL;  | 
85  |  |  | 
86  |  | 
  | 
87  | 0  |   c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);  | 
88  |  | 
  | 
89  | 0  |   if (c == NULL)  | 
90  | 0  |     return 0;  | 
91  |  |  | 
92  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))  | 
93  | 0  |     zlog_debug("Zebra: interface %s address add %pFX vrf %s id %u", | 
94  | 0  |          c->ifp->name, c->address,  | 
95  | 0  |          ospf_vrf_id_to_name(vrf_id), vrf_id);  | 
96  |  | 
  | 
97  | 0  |   ospf = ospf_lookup_by_vrf_id(vrf_id);  | 
98  | 0  |   if (!ospf)  | 
99  | 0  |     return 0;  | 
100  |  |  | 
101  | 0  |   ospf_if_update(ospf, c->ifp);  | 
102  |  | 
  | 
103  | 0  |   ospf_if_interface(c->ifp);  | 
104  |  | 
  | 
105  | 0  |   return 0;  | 
106  | 0  | }  | 
107  |  |  | 
108  |  | static int ospf_interface_address_delete(ZAPI_CALLBACK_ARGS)  | 
109  | 0  | { | 
110  | 0  |   struct connected *c;  | 
111  | 0  |   struct interface *ifp;  | 
112  | 0  |   struct ospf_interface *oi;  | 
113  | 0  |   struct route_node *rn;  | 
114  | 0  |   struct prefix p;  | 
115  |  | 
  | 
116  | 0  |   c = zebra_interface_address_read(cmd, zclient->ibuf, vrf_id);  | 
117  |  | 
  | 
118  | 0  |   if (c == NULL)  | 
119  | 0  |     return 0;  | 
120  |  |  | 
121  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))  | 
122  | 0  |     zlog_debug("Zebra: interface %s address delete %pFX", | 
123  | 0  |          c->ifp->name, c->address);  | 
124  |  | 
  | 
125  | 0  |   ifp = c->ifp;  | 
126  | 0  |   p = *c->address;  | 
127  | 0  |   p.prefixlen = IPV4_MAX_BITLEN;  | 
128  |  | 
  | 
129  | 0  |   rn = route_node_lookup(IF_OIFS(ifp), &p);  | 
130  | 0  |   if (!rn) { | 
131  | 0  |     connected_free(&c);  | 
132  | 0  |     return 0;  | 
133  | 0  |   }  | 
134  |  |  | 
135  | 0  |   assert(rn->info);  | 
136  | 0  |   oi = rn->info;  | 
137  | 0  |   route_unlock_node(rn);  | 
138  |  |  | 
139  |  |   /* Call interface hook functions to clean up */  | 
140  | 0  |   ospf_if_free(oi);  | 
141  |  | 
  | 
142  | 0  |   ospf_if_interface(c->ifp);  | 
143  |  | 
  | 
144  | 0  |   connected_free(&c);  | 
145  |  | 
  | 
146  | 0  |   return 0;  | 
147  | 0  | }  | 
148  |  |  | 
149  |  | static int ospf_interface_link_params(ZAPI_CALLBACK_ARGS)  | 
150  | 0  | { | 
151  | 0  |   struct interface *ifp;  | 
152  | 0  |   bool changed = false;  | 
153  |  | 
  | 
154  | 0  |   ifp = zebra_interface_link_params_read(zclient->ibuf, vrf_id, &changed);  | 
155  |  | 
  | 
156  | 0  |   if (ifp == NULL || !changed)  | 
157  | 0  |     return 0;  | 
158  |  |  | 
159  |  |   /* Update TE TLV */  | 
160  | 0  |   ospf_mpls_te_update_if(ifp);  | 
161  |  | 
  | 
162  | 0  |   return 0;  | 
163  | 0  | }  | 
164  |  |  | 
165  |  | /* VRF update for an interface. */  | 
166  |  | static int ospf_interface_vrf_update(ZAPI_CALLBACK_ARGS)  | 
167  | 0  | { | 
168  | 0  |   struct interface *ifp = NULL;  | 
169  | 0  |   vrf_id_t new_vrf_id;  | 
170  |  | 
  | 
171  | 0  |   ifp = zebra_interface_vrf_update_read(zclient->ibuf, vrf_id,  | 
172  | 0  |                 &new_vrf_id);  | 
173  | 0  |   if (!ifp)  | 
174  | 0  |     return 0;  | 
175  |  |  | 
176  | 0  |   if (IS_DEBUG_OSPF_EVENT)  | 
177  | 0  |     zlog_debug(  | 
178  | 0  |       "%s: Rx Interface %s VRF change vrf_id %u New vrf %s id %u",  | 
179  | 0  |       __func__, ifp->name, vrf_id,  | 
180  | 0  |       ospf_vrf_id_to_name(new_vrf_id), new_vrf_id);  | 
181  |  |  | 
182  |  |   /*if_update(ifp, ifp->name, strlen(ifp->name), new_vrf_id);*/  | 
183  | 0  |   if_update_to_new_vrf(ifp, new_vrf_id);  | 
184  |  | 
  | 
185  | 0  |   return 0;  | 
186  | 0  | }  | 
187  |  |  | 
188  |  | /* Nexthop, ifindex, distance and metric information. */  | 
189  |  | static void ospf_zebra_add_nexthop(struct ospf *ospf, struct ospf_path *path,  | 
190  |  |            struct zapi_route *api)  | 
191  | 0  | { | 
192  | 0  |   struct zapi_nexthop *api_nh;  | 
193  | 0  |   struct zapi_nexthop *api_nh_backup;  | 
194  |  |  | 
195  |  |   /* TI-LFA backup path label stack comes first, if present */  | 
196  | 0  |   if (path->srni.backup_label_stack) { | 
197  | 0  |     api_nh_backup = &api->backup_nexthops[api->backup_nexthop_num];  | 
198  | 0  |     api_nh_backup->vrf_id = ospf->vrf_id;  | 
199  |  | 
  | 
200  | 0  |     api_nh_backup->type = NEXTHOP_TYPE_IPV4;  | 
201  | 0  |     api_nh_backup->gate.ipv4 = path->srni.backup_nexthop;  | 
202  |  | 
  | 
203  | 0  |     api_nh_backup->label_num =  | 
204  | 0  |       path->srni.backup_label_stack->num_labels;  | 
205  | 0  |     memcpy(api_nh_backup->labels,  | 
206  | 0  |            path->srni.backup_label_stack->label,  | 
207  | 0  |            sizeof(mpls_label_t) * api_nh_backup->label_num);  | 
208  |  | 
  | 
209  | 0  |     api->backup_nexthop_num++;  | 
210  | 0  |   }  | 
211  |  |  | 
212  |  |   /* And here comes the primary nexthop */  | 
213  | 0  |   api_nh = &api->nexthops[api->nexthop_num];  | 
214  | 0  | #ifdef HAVE_NETLINK  | 
215  | 0  |   if (path->unnumbered  | 
216  | 0  |       || (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0)) { | 
217  |  | #else  /* HAVE_NETLINK */  | 
218  |  |   if (path->nexthop.s_addr != INADDR_ANY && path->ifindex != 0) { | 
219  |  | #endif /* HAVE_NETLINK */  | 
220  | 0  |     api_nh->gate.ipv4 = path->nexthop;  | 
221  | 0  |     api_nh->ifindex = path->ifindex;  | 
222  | 0  |     api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX;  | 
223  | 0  |   } else if (path->nexthop.s_addr != INADDR_ANY) { | 
224  | 0  |     api_nh->gate.ipv4 = path->nexthop;  | 
225  | 0  |     api_nh->type = NEXTHOP_TYPE_IPV4;  | 
226  | 0  |   } else { | 
227  | 0  |     api_nh->ifindex = path->ifindex;  | 
228  | 0  |     api_nh->type = NEXTHOP_TYPE_IFINDEX;  | 
229  | 0  |   }  | 
230  | 0  |   api_nh->vrf_id = ospf->vrf_id;  | 
231  |  |  | 
232  |  |   /* Set TI-LFA backup nexthop info if present */  | 
233  | 0  |   if (path->srni.backup_label_stack) { | 
234  | 0  |     SET_FLAG(api->message, ZAPI_MESSAGE_BACKUP_NEXTHOPS);  | 
235  | 0  |     SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_HAS_BACKUP);  | 
236  |  |  | 
237  |  |     /* Just care about a single TI-LFA backup path for now */  | 
238  | 0  |     api_nh->backup_num = 1;  | 
239  | 0  |     api_nh->backup_idx[0] = api->backup_nexthop_num - 1;  | 
240  | 0  |   }  | 
241  |  | 
  | 
242  | 0  |   api->nexthop_num++;  | 
243  | 0  | }  | 
244  |  |  | 
245  |  | static void ospf_zebra_append_opaque_attr(struct ospf_route *or,  | 
246  |  |             struct zapi_route *api)  | 
247  | 0  | { | 
248  | 0  |   struct ospf_zebra_opaque ospf_opaque = {}; | 
249  |  |  | 
250  |  |   /* OSPF path type */  | 
251  | 0  |   snprintf(ospf_opaque.path_type, sizeof(ospf_opaque.path_type), "%s",  | 
252  | 0  |      ospf_path_type_name(or->path_type));  | 
253  |  | 
  | 
254  | 0  |   switch (or->path_type) { | 
255  | 0  |   case OSPF_PATH_INTRA_AREA:  | 
256  | 0  |   case OSPF_PATH_INTER_AREA:  | 
257  |  |     /* OSPF area ID */  | 
258  | 0  |     (void)inet_ntop(AF_INET, &or->u.std.area_id,  | 
259  | 0  |         ospf_opaque.area_id,  | 
260  | 0  |         sizeof(ospf_opaque.area_id));  | 
261  | 0  |     break;  | 
262  | 0  |   case OSPF_PATH_TYPE1_EXTERNAL:  | 
263  | 0  |   case OSPF_PATH_TYPE2_EXTERNAL:  | 
264  |  |     /* OSPF route tag */  | 
265  | 0  |     snprintf(ospf_opaque.tag, sizeof(ospf_opaque.tag), "%u",  | 
266  | 0  |        or->u.ext.tag);  | 
267  | 0  |     break;  | 
268  | 0  |   default:  | 
269  | 0  |     break;  | 
270  | 0  |   }  | 
271  |  |  | 
272  | 0  |   SET_FLAG(api->message, ZAPI_MESSAGE_OPAQUE);  | 
273  | 0  |   api->opaque.length = sizeof(struct ospf_zebra_opaque);  | 
274  | 0  |   memcpy(api->opaque.data, &ospf_opaque, api->opaque.length);  | 
275  | 0  | }  | 
276  |  |  | 
277  |  | void ospf_zebra_add(struct ospf *ospf, struct prefix_ipv4 *p,  | 
278  |  |         struct ospf_route * or)  | 
279  | 0  | { | 
280  | 0  |   struct zapi_route api;  | 
281  | 0  |   uint8_t distance;  | 
282  | 0  |   struct ospf_path *path;  | 
283  | 0  |   struct listnode *node;  | 
284  |  | 
  | 
285  | 0  |   if (ospf->gr_info.restart_in_progress) { | 
286  | 0  |     if (IS_DEBUG_OSPF_GR)  | 
287  | 0  |       zlog_debug(  | 
288  | 0  |         "Zebra: Graceful Restart in progress -- not installing %pFX",  | 
289  | 0  |         p);  | 
290  | 0  |     return;  | 
291  | 0  |   }  | 
292  |  |  | 
293  | 0  |   memset(&api, 0, sizeof(api));  | 
294  | 0  |   api.vrf_id = ospf->vrf_id;  | 
295  | 0  |   api.type = ZEBRA_ROUTE_OSPF;  | 
296  | 0  |   api.instance = ospf->instance;  | 
297  | 0  |   api.safi = SAFI_UNICAST;  | 
298  |  | 
  | 
299  | 0  |   memcpy(&api.prefix, p, sizeof(*p));  | 
300  | 0  |   SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);  | 
301  |  |  | 
302  |  |   /* Metric value. */  | 
303  | 0  |   SET_FLAG(api.message, ZAPI_MESSAGE_METRIC);  | 
304  | 0  |   if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL)  | 
305  | 0  |     api.metric = or->cost + or->u.ext.type2_cost;  | 
306  | 0  |   else if (or->path_type == OSPF_PATH_TYPE2_EXTERNAL)  | 
307  | 0  |     api.metric = or->u.ext.type2_cost;  | 
308  | 0  |   else  | 
309  | 0  |     api.metric = or->cost;  | 
310  |  |  | 
311  |  |   /* Check if path type is ASE */  | 
312  | 0  |   if (((or->path_type == OSPF_PATH_TYPE1_EXTERNAL)  | 
313  | 0  |        || (or->path_type == OSPF_PATH_TYPE2_EXTERNAL))  | 
314  | 0  |       && (or->u.ext.tag > 0) && (or->u.ext.tag <= ROUTE_TAG_MAX)) { | 
315  | 0  |     SET_FLAG(api.message, ZAPI_MESSAGE_TAG);  | 
316  | 0  |     api.tag = or->u.ext.tag;  | 
317  | 0  |   }  | 
318  |  |  | 
319  |  |   /* Distance value. */  | 
320  | 0  |   distance = ospf_distance_apply(ospf, p, or);  | 
321  | 0  |   if (distance) { | 
322  | 0  |     SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);  | 
323  | 0  |     api.distance = distance;  | 
324  | 0  |   }  | 
325  |  | 
  | 
326  | 0  |   for (ALL_LIST_ELEMENTS_RO(or->paths, node, path)) { | 
327  | 0  |     if (api.nexthop_num >= ospf->max_multipath)  | 
328  | 0  |       break;  | 
329  |  |  | 
330  | 0  |     ospf_zebra_add_nexthop(ospf, path, &api);  | 
331  |  | 
  | 
332  | 0  |     if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { | 
333  | 0  |       struct interface *ifp;  | 
334  |  | 
  | 
335  | 0  |       ifp = if_lookup_by_index(path->ifindex, ospf->vrf_id);  | 
336  |  | 
  | 
337  | 0  |       zlog_debug(  | 
338  | 0  |         "Zebra: Route add %pFX nexthop %pI4, ifindex=%d %s",  | 
339  | 0  |         p, &path->nexthop, path->ifindex,  | 
340  | 0  |         ifp ? ifp->name : " ");  | 
341  | 0  |     }  | 
342  | 0  |   }  | 
343  |  | 
  | 
344  | 0  |   if (CHECK_FLAG(ospf->config, OSPF_SEND_EXTRA_DATA_TO_ZEBRA))  | 
345  | 0  |     ospf_zebra_append_opaque_attr(or, &api);  | 
346  |  | 
  | 
347  | 0  |   zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);  | 
348  | 0  | }  | 
349  |  |  | 
350  |  | void ospf_zebra_delete(struct ospf *ospf, struct prefix_ipv4 *p,  | 
351  |  |            struct ospf_route * or)  | 
352  | 0  | { | 
353  | 0  |   struct zapi_route api;  | 
354  |  | 
  | 
355  | 0  |   if (ospf->gr_info.restart_in_progress) { | 
356  | 0  |     if (IS_DEBUG_OSPF_GR)  | 
357  | 0  |       zlog_debug(  | 
358  | 0  |         "Zebra: Graceful Restart in progress -- not uninstalling %pFX",  | 
359  | 0  |         p);  | 
360  | 0  |     return;  | 
361  | 0  |   }  | 
362  |  |  | 
363  | 0  |   memset(&api, 0, sizeof(api));  | 
364  | 0  |   api.vrf_id = ospf->vrf_id;  | 
365  | 0  |   api.type = ZEBRA_ROUTE_OSPF;  | 
366  | 0  |   api.instance = ospf->instance;  | 
367  | 0  |   api.safi = SAFI_UNICAST;  | 
368  | 0  |   memcpy(&api.prefix, p, sizeof(*p));  | 
369  |  | 
  | 
370  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
371  | 0  |     zlog_debug("Zebra: Route delete %pFX", p); | 
372  |  | 
  | 
373  | 0  |   zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);  | 
374  | 0  | }  | 
375  |  |  | 
376  |  | void ospf_zebra_add_discard(struct ospf *ospf, struct prefix_ipv4 *p)  | 
377  | 0  | { | 
378  | 0  |   struct zapi_route api;  | 
379  |  | 
  | 
380  | 0  |   if (ospf->gr_info.restart_in_progress) { | 
381  | 0  |     if (IS_DEBUG_OSPF_GR)  | 
382  | 0  |       zlog_debug(  | 
383  | 0  |         "Zebra: Graceful Restart in progress -- not installing %pFX",  | 
384  | 0  |         p);  | 
385  | 0  |     return;  | 
386  | 0  |   }  | 
387  |  |  | 
388  | 0  |   memset(&api, 0, sizeof(api));  | 
389  | 0  |   api.vrf_id = ospf->vrf_id;  | 
390  | 0  |   api.type = ZEBRA_ROUTE_OSPF;  | 
391  | 0  |   api.instance = ospf->instance;  | 
392  | 0  |   api.safi = SAFI_UNICAST;  | 
393  | 0  |   memcpy(&api.prefix, p, sizeof(*p));  | 
394  | 0  |   zapi_route_set_blackhole(&api, BLACKHOLE_NULL);  | 
395  |  | 
  | 
396  | 0  |   zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);  | 
397  |  | 
  | 
398  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
399  | 0  |     zlog_debug("Zebra: Route add discard %pFX", p); | 
400  | 0  | }  | 
401  |  |  | 
402  |  | void ospf_zebra_delete_discard(struct ospf *ospf, struct prefix_ipv4 *p)  | 
403  | 0  | { | 
404  | 0  |   struct zapi_route api;  | 
405  |  | 
  | 
406  | 0  |   if (ospf->gr_info.restart_in_progress) { | 
407  | 0  |     if (IS_DEBUG_OSPF_GR)  | 
408  | 0  |       zlog_debug(  | 
409  | 0  |         "Zebra: Graceful Restart in progress -- not uninstalling %pFX",  | 
410  | 0  |         p);  | 
411  | 0  |     return;  | 
412  | 0  |   }  | 
413  |  |  | 
414  | 0  |   memset(&api, 0, sizeof(api));  | 
415  | 0  |   api.vrf_id = ospf->vrf_id;  | 
416  | 0  |   api.type = ZEBRA_ROUTE_OSPF;  | 
417  | 0  |   api.instance = ospf->instance;  | 
418  | 0  |   api.safi = SAFI_UNICAST;  | 
419  | 0  |   memcpy(&api.prefix, p, sizeof(*p));  | 
420  | 0  |   zapi_route_set_blackhole(&api, BLACKHOLE_NULL);  | 
421  |  | 
  | 
422  | 0  |   zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);  | 
423  |  | 
  | 
424  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
425  | 0  |     zlog_debug("Zebra: Route delete discard %pFX", p); | 
426  | 0  | }  | 
427  |  |  | 
428  |  | struct ospf_external *ospf_external_lookup(struct ospf *ospf, uint8_t type,  | 
429  |  |              unsigned short instance)  | 
430  | 0  | { | 
431  | 0  |   struct list *ext_list;  | 
432  | 0  |   struct listnode *node;  | 
433  | 0  |   struct ospf_external *ext;  | 
434  |  | 
  | 
435  | 0  |   ext_list = ospf->external[type];  | 
436  | 0  |   if (!ext_list)  | 
437  | 0  |     return (NULL);  | 
438  |  |  | 
439  | 0  |   for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext))  | 
440  | 0  |     if (ext->instance == instance)  | 
441  | 0  |       return ext;  | 
442  |  |  | 
443  | 0  |   return NULL;  | 
444  | 0  | }  | 
445  |  |  | 
446  |  | struct ospf_external *ospf_external_add(struct ospf *ospf, uint8_t type,  | 
447  |  |           unsigned short instance)  | 
448  | 0  | { | 
449  | 0  |   struct list *ext_list;  | 
450  | 0  |   struct ospf_external *ext;  | 
451  |  | 
  | 
452  | 0  |   ext = ospf_external_lookup(ospf, type, instance);  | 
453  | 0  |   if (ext)  | 
454  | 0  |     return ext;  | 
455  |  |  | 
456  | 0  |   if (!ospf->external[type])  | 
457  | 0  |     ospf->external[type] = list_new();  | 
458  |  | 
  | 
459  | 0  |   ext_list = ospf->external[type];  | 
460  | 0  |   ext = XCALLOC(MTYPE_OSPF_EXTERNAL, sizeof(struct ospf_external));  | 
461  | 0  |   ext->instance = instance;  | 
462  | 0  |   EXTERNAL_INFO(ext) = route_table_init();  | 
463  |  | 
  | 
464  | 0  |   listnode_add(ext_list, ext);  | 
465  |  | 
  | 
466  | 0  |   return ext;  | 
467  | 0  | }  | 
468  |  |  | 
469  |  | /*  | 
470  |  |  * Walk all the ei received from zebra for a route type and apply  | 
471  |  |  * default route-map.  | 
472  |  |  */  | 
473  |  | bool ospf_external_default_routemap_apply_walk(struct ospf *ospf,  | 
474  |  |                  struct list *ext_list,  | 
475  |  |                  struct external_info *default_ei)  | 
476  | 0  | { | 
477  | 0  |   struct listnode *node;  | 
478  | 0  |   struct ospf_external *ext;  | 
479  | 0  |   struct route_node *rn;  | 
480  | 0  |   struct external_info *ei = NULL;  | 
481  | 0  |   int ret = 0;  | 
482  |  | 
  | 
483  | 0  |   for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { | 
484  | 0  |     if (!ext->external_info)  | 
485  | 0  |       continue;  | 
486  |  |  | 
487  | 0  |     for (rn = route_top(ext->external_info); rn;  | 
488  | 0  |          rn = route_next(rn)) { | 
489  | 0  |       ei = rn->info;  | 
490  | 0  |       if (!ei)  | 
491  | 0  |         continue;  | 
492  | 0  |       ret = ospf_external_info_apply_default_routemap(  | 
493  | 0  |         ospf, ei, default_ei);  | 
494  | 0  |       if (ret)  | 
495  | 0  |         break;  | 
496  | 0  |     }  | 
497  | 0  |   }  | 
498  |  | 
  | 
499  | 0  |   if (ret && ei) { | 
500  | 0  |     if (IS_DEBUG_OSPF_DEFAULT_INFO)  | 
501  | 0  |       zlog_debug("Default originate routemap permit ei: %pI4", | 
502  | 0  |            &ei->p.prefix);  | 
503  | 0  |     return true;  | 
504  | 0  |   }  | 
505  |  |  | 
506  | 0  |   return false;  | 
507  | 0  | }  | 
508  |  |  | 
509  |  | /*  | 
510  |  |  * Function to originate or flush default after applying  | 
511  |  |  * route-map on all ei.  | 
512  |  |  */  | 
513  |  | static void ospf_external_lsa_default_routemap_timer(struct event *thread)  | 
514  | 0  | { | 
515  | 0  |   struct list *ext_list;  | 
516  | 0  |   struct ospf *ospf = EVENT_ARG(thread);  | 
517  | 0  |   struct prefix_ipv4 p;  | 
518  | 0  |   int type;  | 
519  | 0  |   int ret = 0;  | 
520  | 0  |   struct ospf_lsa *lsa;  | 
521  | 0  |   struct external_info *default_ei;  | 
522  | 0  | 
  | 
523  | 0  |   p.family = AF_INET;  | 
524  | 0  |   p.prefixlen = 0;  | 
525  | 0  |   p.prefix.s_addr = INADDR_ANY;  | 
526  | 0  | 
  | 
527  | 0  |   /* Get the default extenal info. */  | 
528  | 0  |   default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE,  | 
529  | 0  |                  ospf->instance, &p);  | 
530  | 0  |   if (!default_ei) { | 
531  | 0  |     /* Nothing to be done here. */  | 
532  | 0  |     if (IS_DEBUG_OSPF_DEFAULT_INFO)  | 
533  | 0  |       zlog_debug("Default originate info not present"); | 
534  | 0  |     return;  | 
535  | 0  |   }  | 
536  | 0  | 
  | 
537  | 0  |   /* For all the ei apply route-map */  | 
538  | 0  |   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { | 
539  | 0  |     ext_list = ospf->external[type];  | 
540  | 0  |     if (!ext_list || type == ZEBRA_ROUTE_OSPF)  | 
541  | 0  |       continue;  | 
542  | 0  | 
  | 
543  | 0  |     ret = ospf_external_default_routemap_apply_walk(ospf, ext_list,  | 
544  | 0  |                 default_ei);  | 
545  | 0  |     if (ret)  | 
546  | 0  |       break;  | 
547  | 0  |   }  | 
548  | 0  | 
  | 
549  | 0  |   /* Get the default LSA. */  | 
550  | 0  |   lsa = ospf_external_info_find_lsa(ospf, &p);  | 
551  | 0  | 
  | 
552  | 0  |   /* If permit then originate default. */  | 
553  | 0  |   if (ret && !lsa)  | 
554  | 0  |     ospf_external_lsa_originate(ospf, default_ei);  | 
555  | 0  |   else if (ret && lsa && IS_LSA_MAXAGE(lsa))  | 
556  | 0  |     ospf_external_lsa_refresh(ospf, lsa, default_ei, true, false);  | 
557  | 0  |   else if (!ret && lsa)  | 
558  | 0  |     ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &default_ei->p, 0);  | 
559  | 0  | }  | 
560  |  |  | 
561  |  |  | 
562  |  | void ospf_external_del(struct ospf *ospf, uint8_t type, unsigned short instance)  | 
563  | 0  | { | 
564  | 0  |   struct ospf_external *ext;  | 
565  |  | 
  | 
566  | 0  |   ext = ospf_external_lookup(ospf, type, instance);  | 
567  |  | 
  | 
568  | 0  |   if (ext) { | 
569  | 0  |     if (EXTERNAL_INFO(ext))  | 
570  | 0  |       route_table_finish(EXTERNAL_INFO(ext));  | 
571  |  | 
  | 
572  | 0  |     listnode_delete(ospf->external[type], ext);  | 
573  |  | 
  | 
574  | 0  |     if (!ospf->external[type]->count)  | 
575  | 0  |       list_delete(&ospf->external[type]);  | 
576  |  | 
  | 
577  | 0  |     XFREE(MTYPE_OSPF_EXTERNAL, ext);  | 
578  | 0  |   }  | 
579  |  |  | 
580  |  |   /*  | 
581  |  |    * Check if default needs to be flushed too.  | 
582  |  |    */  | 
583  | 0  |   event_add_event(master, ospf_external_lsa_default_routemap_timer, ospf,  | 
584  | 0  |       0, &ospf->t_default_routemap_timer);  | 
585  | 0  | }  | 
586  |  |  | 
587  |  | /* Update NHLFE for Prefix SID */  | 
588  |  | void ospf_zebra_update_prefix_sid(const struct sr_prefix *srp)  | 
589  | 0  | { | 
590  | 0  |   struct zapi_labels zl;  | 
591  | 0  |   struct zapi_nexthop *znh;  | 
592  | 0  |   struct zapi_nexthop *znh_backup;  | 
593  | 0  |   struct listnode *node;  | 
594  | 0  |   struct ospf_path *path;  | 
595  |  |  | 
596  |  |   /* Prepare message. */  | 
597  | 0  |   memset(&zl, 0, sizeof(zl));  | 
598  | 0  |   zl.type = ZEBRA_LSP_OSPF_SR;  | 
599  | 0  |   zl.local_label = srp->label_in;  | 
600  |  | 
  | 
601  | 0  |   switch (srp->type) { | 
602  | 0  |   case LOCAL_SID:  | 
603  |  |     /* Set Label for local Prefix */  | 
604  | 0  |     znh = &zl.nexthops[zl.nexthop_num++];  | 
605  | 0  |     znh->type = NEXTHOP_TYPE_IFINDEX;  | 
606  | 0  |     znh->ifindex = srp->nhlfe.ifindex;  | 
607  | 0  |     znh->label_num = 1;  | 
608  | 0  |     znh->labels[0] = srp->nhlfe.label_out;  | 
609  |  | 
  | 
610  | 0  |     osr_debug("SR (%s): Configure Prefix %pFX with labels %u/%u", | 
611  | 0  |         __func__, (struct prefix *)&srp->prefv4,  | 
612  | 0  |         srp->label_in, srp->nhlfe.label_out);  | 
613  |  | 
  | 
614  | 0  |     break;  | 
615  |  |  | 
616  | 0  |   case PREF_SID:  | 
617  |  |     /* Update route in the RIB too. */  | 
618  | 0  |     SET_FLAG(zl.message, ZAPI_LABELS_FTN);  | 
619  | 0  |     zl.route.prefix.u.prefix4 = srp->prefv4.prefix;  | 
620  | 0  |     zl.route.prefix.prefixlen = srp->prefv4.prefixlen;  | 
621  | 0  |     zl.route.prefix.family = srp->prefv4.family;  | 
622  | 0  |     zl.route.type = ZEBRA_ROUTE_OSPF;  | 
623  | 0  |     zl.route.instance = 0;  | 
624  |  |  | 
625  |  |     /* Check that SRP contains at least one valid path */  | 
626  | 0  |     if (srp->route == NULL) { | 
627  | 0  |       return;  | 
628  | 0  |     }  | 
629  |  |  | 
630  | 0  |     osr_debug("SR (%s): Configure Prefix %pFX with", | 
631  | 0  |         __func__, (struct prefix *)&srp->prefv4);  | 
632  |  | 
  | 
633  | 0  |     for (ALL_LIST_ELEMENTS_RO(srp->route->paths, node, path)) { | 
634  | 0  |       if (path->srni.label_out == MPLS_INVALID_LABEL)  | 
635  | 0  |         continue;  | 
636  |  |  | 
637  | 0  |       if (zl.nexthop_num >= MULTIPATH_NUM)  | 
638  | 0  |         break;  | 
639  |  |  | 
640  |  |       /*  | 
641  |  |        * TI-LFA backup path label stack comes first, if  | 
642  |  |        * present.  | 
643  |  |        */  | 
644  | 0  |       if (path->srni.backup_label_stack) { | 
645  | 0  |         znh_backup = &zl.backup_nexthops  | 
646  | 0  |                   [zl.backup_nexthop_num++];  | 
647  | 0  |         znh_backup->type = NEXTHOP_TYPE_IPV4;  | 
648  | 0  |         znh_backup->gate.ipv4 =  | 
649  | 0  |           path->srni.backup_nexthop;  | 
650  |  | 
  | 
651  | 0  |         memcpy(znh_backup->labels,  | 
652  | 0  |                path->srni.backup_label_stack->label,  | 
653  | 0  |                sizeof(mpls_label_t)  | 
654  | 0  |                  * path->srni.backup_label_stack  | 
655  | 0  |                ->num_labels);  | 
656  |  | 
  | 
657  | 0  |         znh_backup->label_num =  | 
658  | 0  |           path->srni.backup_label_stack  | 
659  | 0  |             ->num_labels;  | 
660  | 0  |         if (path->srni.label_out  | 
661  | 0  |               != MPLS_LABEL_IPV4_EXPLICIT_NULL  | 
662  | 0  |             && path->srni.label_out  | 
663  | 0  |                  != MPLS_LABEL_IMPLICIT_NULL)  | 
664  | 0  |           znh_backup->labels  | 
665  | 0  |             [znh_backup->label_num++] =  | 
666  | 0  |             path->srni.label_out;  | 
667  | 0  |       }  | 
668  |  | 
  | 
669  | 0  |       znh = &zl.nexthops[zl.nexthop_num++];  | 
670  | 0  |       znh->type = NEXTHOP_TYPE_IPV4_IFINDEX;  | 
671  | 0  |       znh->gate.ipv4 = path->nexthop;  | 
672  | 0  |       znh->ifindex = path->ifindex;  | 
673  | 0  |       znh->label_num = 1;  | 
674  | 0  |       znh->labels[0] = path->srni.label_out;  | 
675  |  | 
  | 
676  | 0  |       osr_debug("  |- labels %u/%u", srp->label_in, | 
677  | 0  |           path->srni.label_out);  | 
678  |  |  | 
679  |  |       /* Set TI-LFA backup nexthop info if present */  | 
680  | 0  |       if (path->srni.backup_label_stack) { | 
681  | 0  |         SET_FLAG(zl.message, ZAPI_LABELS_HAS_BACKUPS);  | 
682  | 0  |         SET_FLAG(znh->flags,  | 
683  | 0  |            ZAPI_NEXTHOP_FLAG_HAS_BACKUP);  | 
684  |  |  | 
685  |  |         /* Just care about a single TI-LFA backup path  | 
686  |  |          * for now */  | 
687  | 0  |         znh->backup_num = 1;  | 
688  | 0  |         znh->backup_idx[0] = zl.backup_nexthop_num - 1;  | 
689  | 0  |       }  | 
690  | 0  |     }  | 
691  | 0  |     break;  | 
692  | 0  |   case ADJ_SID:  | 
693  | 0  |   case LAN_ADJ_SID:  | 
694  | 0  |     return;  | 
695  | 0  |   }  | 
696  |  |  | 
697  |  |   /* Finally, send message to zebra. */  | 
698  | 0  |   (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_REPLACE, &zl);  | 
699  | 0  | }  | 
700  |  |  | 
701  |  | /* Remove NHLFE for Prefix-SID */  | 
702  |  | void ospf_zebra_delete_prefix_sid(const struct sr_prefix *srp)  | 
703  | 0  | { | 
704  | 0  |   struct zapi_labels zl;  | 
705  |  | 
  | 
706  | 0  |   osr_debug("SR (%s): Delete Labels %u for Prefix %pFX", __func__, | 
707  | 0  |       srp->label_in, (struct prefix *)&srp->prefv4);  | 
708  |  |  | 
709  |  |   /* Prepare message. */  | 
710  | 0  |   memset(&zl, 0, sizeof(zl));  | 
711  | 0  |   zl.type = ZEBRA_LSP_OSPF_SR;  | 
712  | 0  |   zl.local_label = srp->label_in;  | 
713  |  | 
  | 
714  | 0  |   if (srp->type == PREF_SID) { | 
715  |  |     /* Update route in the RIB too */  | 
716  | 0  |     SET_FLAG(zl.message, ZAPI_LABELS_FTN);  | 
717  | 0  |     zl.route.prefix.u.prefix4 = srp->prefv4.prefix;  | 
718  | 0  |     zl.route.prefix.prefixlen = srp->prefv4.prefixlen;  | 
719  | 0  |     zl.route.prefix.family = srp->prefv4.family;  | 
720  | 0  |     zl.route.type = ZEBRA_ROUTE_OSPF;  | 
721  | 0  |     zl.route.instance = 0;  | 
722  | 0  |   }  | 
723  |  |  | 
724  |  |   /* Send message to zebra. */  | 
725  | 0  |   (void)zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, &zl);  | 
726  | 0  | }  | 
727  |  |  | 
728  |  | /* Send MPLS Label entry to Zebra for installation or deletion */  | 
729  |  | void ospf_zebra_send_adjacency_sid(int cmd, struct sr_nhlfe nhlfe)  | 
730  | 0  | { | 
731  | 0  |   struct zapi_labels zl;  | 
732  | 0  |   struct zapi_nexthop *znh;  | 
733  |  | 
  | 
734  | 0  |   osr_debug("SR (%s): %s Labels %u/%u for Adjacency via %u", __func__, | 
735  | 0  |       cmd == ZEBRA_MPLS_LABELS_ADD ? "Add" : "Delete",  | 
736  | 0  |       nhlfe.label_in, nhlfe.label_out, nhlfe.ifindex);  | 
737  |  | 
  | 
738  | 0  |   memset(&zl, 0, sizeof(zl));  | 
739  | 0  |   zl.type = ZEBRA_LSP_OSPF_SR;  | 
740  | 0  |   zl.local_label = nhlfe.label_in;  | 
741  | 0  |   zl.nexthop_num = 1;  | 
742  | 0  |   znh = &zl.nexthops[0];  | 
743  | 0  |   znh->type = NEXTHOP_TYPE_IPV4_IFINDEX;  | 
744  | 0  |   znh->gate.ipv4 = nhlfe.nexthop;  | 
745  | 0  |   znh->ifindex = nhlfe.ifindex;  | 
746  | 0  |   znh->label_num = 1;  | 
747  | 0  |   znh->labels[0] = nhlfe.label_out;  | 
748  |  | 
  | 
749  | 0  |   (void)zebra_send_mpls_labels(zclient, cmd, &zl);  | 
750  | 0  | }  | 
751  |  |  | 
752  |  | struct ospf_redist *ospf_redist_lookup(struct ospf *ospf, uint8_t type,  | 
753  |  |                unsigned short instance)  | 
754  | 0  | { | 
755  | 0  |   struct list *red_list;  | 
756  | 0  |   struct listnode *node;  | 
757  | 0  |   struct ospf_redist *red;  | 
758  |  | 
  | 
759  | 0  |   red_list = ospf->redist[type];  | 
760  | 0  |   if (!red_list)  | 
761  | 0  |     return (NULL);  | 
762  |  |  | 
763  | 0  |   for (ALL_LIST_ELEMENTS_RO(red_list, node, red))  | 
764  | 0  |     if (red->instance == instance)  | 
765  | 0  |       return red;  | 
766  |  |  | 
767  | 0  |   return NULL;  | 
768  | 0  | }  | 
769  |  |  | 
770  |  | struct ospf_redist *ospf_redist_add(struct ospf *ospf, uint8_t type,  | 
771  |  |             unsigned short instance)  | 
772  | 0  | { | 
773  | 0  |   struct list *red_list;  | 
774  | 0  |   struct ospf_redist *red;  | 
775  |  | 
  | 
776  | 0  |   red = ospf_redist_lookup(ospf, type, instance);  | 
777  | 0  |   if (red)  | 
778  | 0  |     return red;  | 
779  |  |  | 
780  | 0  |   if (!ospf->redist[type])  | 
781  | 0  |     ospf->redist[type] = list_new();  | 
782  |  | 
  | 
783  | 0  |   red_list = ospf->redist[type];  | 
784  | 0  |   red = XCALLOC(MTYPE_OSPF_REDISTRIBUTE, sizeof(struct ospf_redist));  | 
785  | 0  |   red->instance = instance;  | 
786  | 0  |   red->dmetric.type = -1;  | 
787  | 0  |   red->dmetric.value = -1;  | 
788  | 0  |   ROUTEMAP_NAME(red) = NULL;  | 
789  | 0  |   ROUTEMAP(red) = NULL;  | 
790  |  | 
  | 
791  | 0  |   listnode_add(red_list, red);  | 
792  |  | 
  | 
793  | 0  |   return red;  | 
794  | 0  | }  | 
795  |  |  | 
796  |  | void ospf_redist_del(struct ospf *ospf, uint8_t type, unsigned short instance)  | 
797  | 0  | { | 
798  | 0  |   struct ospf_redist *red;  | 
799  |  | 
  | 
800  | 0  |   red = ospf_redist_lookup(ospf, type, instance);  | 
801  |  | 
  | 
802  | 0  |   if (red) { | 
803  | 0  |     listnode_delete(ospf->redist[type], red);  | 
804  | 0  |     if (!ospf->redist[type]->count) { | 
805  | 0  |       list_delete(&ospf->redist[type]);  | 
806  | 0  |     }  | 
807  | 0  |     ospf_routemap_unset(red);  | 
808  | 0  |     XFREE(MTYPE_OSPF_REDISTRIBUTE, red);  | 
809  | 0  |   }  | 
810  | 0  | }  | 
811  |  |  | 
812  |  |  | 
813  |  | int ospf_is_type_redistributed(struct ospf *ospf, int type,  | 
814  |  |              unsigned short instance)  | 
815  | 0  | { | 
816  | 0  |   return (DEFAULT_ROUTE_TYPE(type)  | 
817  | 0  |       ? vrf_bitmap_check(zclient->default_information[AFI_IP],  | 
818  | 0  |              ospf->vrf_id)  | 
819  | 0  |       : ((instance  | 
820  | 0  |           && redist_check_instance(  | 
821  | 0  |             &zclient->mi_redist[AFI_IP][type],  | 
822  | 0  |             instance))  | 
823  | 0  |          || (!instance  | 
824  | 0  |              && vrf_bitmap_check(  | 
825  | 0  |                zclient->redist[AFI_IP][type],  | 
826  | 0  |                ospf->vrf_id))));  | 
827  | 0  | }  | 
828  |  |  | 
829  |  | int ospf_redistribute_update(struct ospf *ospf, struct ospf_redist *red,  | 
830  |  |            int type, unsigned short instance, int mtype,  | 
831  |  |            int mvalue)  | 
832  | 0  | { | 
833  | 0  |   int force = 0;  | 
834  |  | 
  | 
835  | 0  |   if (mtype != red->dmetric.type) { | 
836  | 0  |     red->dmetric.type = mtype;  | 
837  | 0  |     force = LSA_REFRESH_FORCE;  | 
838  | 0  |   }  | 
839  | 0  |   if (mvalue != red->dmetric.value) { | 
840  | 0  |     red->dmetric.value = mvalue;  | 
841  | 0  |     force = LSA_REFRESH_FORCE;  | 
842  | 0  |   }  | 
843  |  | 
  | 
844  | 0  |   ospf_external_lsa_refresh_type(ospf, type, instance, force);  | 
845  |  | 
  | 
846  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
847  | 0  |     zlog_debug(  | 
848  | 0  |       "Redistribute[%s][%d]: Refresh  Type[%d], Metric[%d]",  | 
849  | 0  |       ospf_redist_string(type), instance,  | 
850  | 0  |       metric_type(ospf, type, instance),  | 
851  | 0  |       metric_value(ospf, type, instance));  | 
852  |  | 
  | 
853  | 0  |   return CMD_SUCCESS;  | 
854  | 0  | }  | 
855  |  |  | 
856  |  | int ospf_redistribute_set(struct ospf *ospf, struct ospf_redist *red, int type,  | 
857  |  |         unsigned short instance, int mtype, int mvalue)  | 
858  | 0  | { | 
859  | 0  |   red->dmetric.type = mtype;  | 
860  | 0  |   red->dmetric.value = mvalue;  | 
861  |  | 
  | 
862  | 0  |   ospf_external_add(ospf, type, instance);  | 
863  |  | 
  | 
864  | 0  |   zclient_redistribute(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,  | 
865  | 0  |            instance, ospf->vrf_id);  | 
866  |  | 
  | 
867  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
868  | 0  |     zlog_debug(  | 
869  | 0  |       "Redistribute[%s][%d] vrf id %u: Start  Type[%d], Metric[%d]",  | 
870  | 0  |       ospf_redist_string(type), instance, ospf->vrf_id,  | 
871  | 0  |       metric_type(ospf, type, instance),  | 
872  | 0  |       metric_value(ospf, type, instance));  | 
873  |  | 
  | 
874  | 0  |   ospf_asbr_status_update(ospf, ++ospf->redistribute);  | 
875  |  | 
  | 
876  | 0  |   return CMD_SUCCESS;  | 
877  | 0  | }  | 
878  |  |  | 
879  |  | int ospf_redistribute_unset(struct ospf *ospf, int type,  | 
880  |  |           unsigned short instance)  | 
881  | 0  | { | 
882  | 0  |   if (type == zclient->redist_default && instance == zclient->instance)  | 
883  | 0  |     return CMD_SUCCESS;  | 
884  |  |  | 
885  | 0  |   zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type,  | 
886  | 0  |            instance, ospf->vrf_id);  | 
887  |  | 
  | 
888  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
889  | 0  |     zlog_debug("Redistribute[%s][%d] vrf id %u: Stop", | 
890  | 0  |          ospf_redist_string(type), instance, ospf->vrf_id);  | 
891  |  |  | 
892  |  |   /* Remove the routes from OSPF table. */  | 
893  | 0  |   ospf_redistribute_withdraw(ospf, type, instance);  | 
894  |  | 
  | 
895  | 0  |   ospf_external_del(ospf, type, instance);  | 
896  |  | 
  | 
897  | 0  |   ospf_asbr_status_update(ospf, --ospf->redistribute);  | 
898  |  | 
  | 
899  | 0  |   return CMD_SUCCESS;  | 
900  | 0  | }  | 
901  |  |  | 
902  |  | int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype,  | 
903  |  |           int mvalue)  | 
904  | 0  | { | 
905  | 0  |   struct prefix_ipv4 p;  | 
906  | 0  |   struct in_addr nexthop;  | 
907  | 0  |   int cur_originate = ospf->default_originate;  | 
908  | 0  |   const char *type_str = NULL;  | 
909  |  | 
  | 
910  | 0  |   nexthop.s_addr = INADDR_ANY;  | 
911  | 0  |   p.family = AF_INET;  | 
912  | 0  |   p.prefix.s_addr = INADDR_ANY;  | 
913  | 0  |   p.prefixlen = 0;  | 
914  |  | 
  | 
915  | 0  |   ospf->default_originate = originate;  | 
916  |  | 
  | 
917  | 0  |   if (cur_originate == originate) { | 
918  |  |     /* Refresh the lsa since metric might different */  | 
919  | 0  |     if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
920  | 0  |       zlog_debug(  | 
921  | 0  |         "Redistribute[%s]: Refresh  Type[%d], Metric[%d]",  | 
922  | 0  |         ospf_redist_string(DEFAULT_ROUTE),  | 
923  | 0  |         metric_type(ospf, DEFAULT_ROUTE, 0),  | 
924  | 0  |         metric_value(ospf, DEFAULT_ROUTE, 0));  | 
925  |  | 
  | 
926  | 0  |     ospf_external_lsa_refresh_default(ospf);  | 
927  | 0  |     return CMD_SUCCESS;  | 
928  | 0  |   }  | 
929  |  |  | 
930  | 0  |   switch (cur_originate) { | 
931  | 0  |   case DEFAULT_ORIGINATE_NONE:  | 
932  | 0  |     break;  | 
933  | 0  |   case DEFAULT_ORIGINATE_ZEBRA:  | 
934  | 0  |     zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE,  | 
935  | 0  |          zclient, AFI_IP, ospf->vrf_id);  | 
936  | 0  |     ospf->redistribute--;  | 
937  | 0  |     break;  | 
938  | 0  |   case DEFAULT_ORIGINATE_ALWAYS:  | 
939  | 0  |     ospf_external_info_delete(ospf, DEFAULT_ROUTE, 0, p);  | 
940  | 0  |     ospf_external_del(ospf, DEFAULT_ROUTE, 0);  | 
941  | 0  |     ospf->redistribute--;  | 
942  | 0  |     break;  | 
943  | 0  |   }  | 
944  |  |  | 
945  | 0  |   switch (originate) { | 
946  | 0  |   case DEFAULT_ORIGINATE_NONE:  | 
947  | 0  |     type_str = "none";  | 
948  | 0  |     break;  | 
949  | 0  |   case DEFAULT_ORIGINATE_ZEBRA:  | 
950  | 0  |     type_str = "normal";  | 
951  | 0  |     ospf->redistribute++;  | 
952  | 0  |     zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD,  | 
953  | 0  |                zclient, AFI_IP, ospf->vrf_id);  | 
954  | 0  |     break;  | 
955  | 0  |   case DEFAULT_ORIGINATE_ALWAYS:  | 
956  | 0  |     type_str = "always";  | 
957  | 0  |     ospf->redistribute++;  | 
958  | 0  |     ospf_external_add(ospf, DEFAULT_ROUTE, 0);  | 
959  | 0  |     ospf_external_info_add(ospf, DEFAULT_ROUTE, 0, p, 0, nexthop, 0,  | 
960  | 0  |                DEFAULT_DEFAULT_METRIC);  | 
961  | 0  |     break;  | 
962  | 0  |   }  | 
963  |  |  | 
964  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
965  | 0  |     zlog_debug("Redistribute[DEFAULT]: %s Type[%d], Metric[%d]", | 
966  | 0  |     type_str,  | 
967  | 0  |     metric_type(ospf, DEFAULT_ROUTE, 0),  | 
968  | 0  |     metric_value(ospf, DEFAULT_ROUTE, 0));  | 
969  |  | 
  | 
970  | 0  |   ospf_external_lsa_refresh_default(ospf);  | 
971  | 0  |   ospf_asbr_status_update(ospf, ospf->redistribute);  | 
972  | 0  |   return CMD_SUCCESS;  | 
973  | 0  | }  | 
974  |  |  | 
975  |  | static int ospf_external_lsa_originate_check(struct ospf *ospf,  | 
976  |  |                struct external_info *ei)  | 
977  | 0  | { | 
978  |  |   /* If prefix is multicast, then do not originate LSA. */  | 
979  | 0  |   if (IN_MULTICAST(htonl(ei->p.prefix.s_addr))) { | 
980  | 0  |     zlog_info(  | 
981  | 0  |       "LSA[Type5:%pI4]: Not originate AS-external-LSA, Prefix belongs multicast",  | 
982  | 0  |       &ei->p.prefix);  | 
983  | 0  |     return 0;  | 
984  | 0  |   }  | 
985  |  |  | 
986  |  |   /* Take care of default-originate. */  | 
987  | 0  |   if (is_default_prefix4(&ei->p))  | 
988  | 0  |     if (ospf->default_originate == DEFAULT_ORIGINATE_NONE) { | 
989  | 0  |       zlog_info(  | 
990  | 0  |         "LSA[Type5:0.0.0.0]: Not originate AS-external-LSA for default");  | 
991  | 0  |       return 0;  | 
992  | 0  |     }  | 
993  |  |  | 
994  | 0  |   return 1;  | 
995  | 0  | }  | 
996  |  |  | 
997  |  | /* If connected prefix is OSPF enable interface, then do not announce. */  | 
998  |  | int ospf_distribute_check_connected(struct ospf *ospf, struct external_info *ei)  | 
999  | 0  | { | 
1000  | 0  |   struct listnode *node;  | 
1001  | 0  |   struct ospf_interface *oi;  | 
1002  |  |  | 
1003  |  | 
  | 
1004  | 0  |   for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi))  | 
1005  | 0  |     if (prefix_match(oi->address, (struct prefix *)&ei->p))  | 
1006  | 0  |       return 0;  | 
1007  | 0  |   return 1;  | 
1008  | 0  | }  | 
1009  |  |  | 
1010  |  |  | 
1011  |  | /* Apply default route-map on ei received. */  | 
1012  |  | int ospf_external_info_apply_default_routemap(struct ospf *ospf,  | 
1013  |  |                 struct external_info *ei,  | 
1014  |  |                 struct external_info *default_ei)  | 
1015  | 0  | { | 
1016  | 0  |   struct ospf_redist *red;  | 
1017  | 0  |   int type = default_ei->type;  | 
1018  | 0  |   struct prefix_ipv4 *p = &ei->p;  | 
1019  | 0  |   struct route_map_set_values save_values;  | 
1020  |  |  | 
1021  |  | 
  | 
1022  | 0  |   if (!ospf_external_lsa_originate_check(ospf, default_ei))  | 
1023  | 0  |     return 0;  | 
1024  |  |  | 
1025  | 0  |   save_values = default_ei->route_map_set;  | 
1026  | 0  |   ospf_reset_route_map_set_values(&default_ei->route_map_set);  | 
1027  |  |  | 
1028  |  |   /* apply route-map if needed */  | 
1029  | 0  |   red = ospf_redist_lookup(ospf, type, ospf->instance);  | 
1030  | 0  |   if (red && ROUTEMAP_NAME(red)) { | 
1031  | 0  |     route_map_result_t ret;  | 
1032  |  | 
  | 
1033  | 0  |     ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei);  | 
1034  |  | 
  | 
1035  | 0  |     if (ret == RMAP_DENYMATCH) { | 
1036  | 0  |       ei->route_map_set = save_values;  | 
1037  | 0  |       return 0;  | 
1038  | 0  |     }  | 
1039  | 0  |   }  | 
1040  |  |  | 
1041  | 0  |   return 1;  | 
1042  | 0  | }  | 
1043  |  |  | 
1044  |  |  | 
1045  |  | /*  | 
1046  |  |  * Default originated is based on route-map condition then  | 
1047  |  |  * apply route-map on received external info. Originate or  | 
1048  |  |  * flush based on route-map condition.  | 
1049  |  |  */  | 
1050  |  | static bool ospf_external_lsa_default_routemap_apply(struct ospf *ospf,  | 
1051  |  |                  struct external_info *ei,  | 
1052  |  |                  int cmd)  | 
1053  | 0  | { | 
1054  | 0  |   struct external_info *default_ei;  | 
1055  | 0  |   struct prefix_ipv4 p;  | 
1056  | 0  |   struct ospf_lsa *lsa;  | 
1057  | 0  |   int ret;  | 
1058  |  | 
  | 
1059  | 0  |   p.family = AF_INET;  | 
1060  | 0  |   p.prefixlen = 0;  | 
1061  | 0  |   p.prefix.s_addr = INADDR_ANY;  | 
1062  |  |  | 
1063  |  |  | 
1064  |  |   /* Get the default extenal info. */  | 
1065  | 0  |   default_ei = ospf_external_info_lookup(ospf, DEFAULT_ROUTE,  | 
1066  | 0  |                  ospf->instance, &p);  | 
1067  | 0  |   if (!default_ei) { | 
1068  |  |     /* Nothing to be done here. */  | 
1069  | 0  |     return false;  | 
1070  | 0  |   }  | 
1071  |  |  | 
1072  | 0  |   if (IS_DEBUG_OSPF_DEFAULT_INFO)  | 
1073  | 0  |     zlog_debug("Apply default originate routemap on ei: %pI4 cmd: %d", | 
1074  | 0  |          &ei->p.prefix, cmd);  | 
1075  |  | 
  | 
1076  | 0  |   ret = ospf_external_info_apply_default_routemap(ospf, ei, default_ei);  | 
1077  |  |  | 
1078  |  |   /* If deny then nothing to be done both in add and del case. */  | 
1079  | 0  |   if (!ret) { | 
1080  | 0  |     if (IS_DEBUG_OSPF_DEFAULT_INFO)  | 
1081  | 0  |       zlog_debug("Default originte routemap deny for ei: %pI4", | 
1082  | 0  |            &ei->p.prefix);  | 
1083  | 0  |     return false;  | 
1084  | 0  |   }  | 
1085  |  |  | 
1086  |  |   /* Get the default LSA. */  | 
1087  | 0  |   lsa = ospf_external_info_find_lsa(ospf, &p);  | 
1088  |  |  | 
1089  |  |   /* If this is add route and permit then ooriginate default. */  | 
1090  | 0  |   if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { | 
1091  |  |     /* If permit and default already advertise then return. */  | 
1092  | 0  |     if (lsa && !IS_LSA_MAXAGE(lsa)) { | 
1093  | 0  |       if (IS_DEBUG_OSPF_DEFAULT_INFO)  | 
1094  | 0  |         zlog_debug("Default lsa already originated"); | 
1095  | 0  |       return true;  | 
1096  | 0  |     }  | 
1097  |  |  | 
1098  | 0  |     if (IS_DEBUG_OSPF_DEFAULT_INFO)  | 
1099  | 0  |       zlog_debug("Originating/Refreshing default lsa"); | 
1100  |  | 
  | 
1101  | 0  |     if (lsa && IS_LSA_MAXAGE(lsa))  | 
1102  |  |       /* Refresh lsa.*/  | 
1103  | 0  |       ospf_external_lsa_refresh(ospf, lsa, default_ei, true,  | 
1104  | 0  |               false);  | 
1105  | 0  |     else  | 
1106  |  |       /* If permit and default not advertised then advertise.  | 
1107  |  |        */  | 
1108  | 0  |       ospf_external_lsa_originate(ospf, default_ei);  | 
1109  |  | 
  | 
1110  | 0  |   } else if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) { | 
1111  |  |     /* If deny and lsa is not originated then nothing to be done.*/  | 
1112  | 0  |     if (!lsa) { | 
1113  | 0  |       if (IS_DEBUG_OSPF_DEFAULT_INFO)  | 
1114  | 0  |         zlog_debug(  | 
1115  | 0  |           "Default lsa not originated, not flushing");  | 
1116  | 0  |       return true;  | 
1117  | 0  |     }  | 
1118  |  |  | 
1119  | 0  |     if (IS_DEBUG_OSPF_DEFAULT_INFO)  | 
1120  | 0  |       zlog_debug(  | 
1121  | 0  |         "Running default route-map again as ei: %pI4 deleted",  | 
1122  | 0  |         &ei->p.prefix);  | 
1123  |  |     /*  | 
1124  |  |      * if this route delete was permitted then we need to check  | 
1125  |  |      * there are any other external info which can still trigger  | 
1126  |  |      * default route origination else flush it.  | 
1127  |  |      */  | 
1128  | 0  |     event_add_event(master,  | 
1129  | 0  |         ospf_external_lsa_default_routemap_timer, ospf,  | 
1130  | 0  |         0, &ospf->t_default_routemap_timer);  | 
1131  | 0  |   }  | 
1132  |  |  | 
1133  | 0  |   return true;  | 
1134  | 0  | }  | 
1135  |  |  | 
1136  |  | /* return 1 if external LSA must be originated, 0 otherwise */  | 
1137  |  | int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei,  | 
1138  |  |           int *changed)  | 
1139  | 0  | { | 
1140  | 0  |   struct route_map_set_values save_values;  | 
1141  | 0  |   struct prefix_ipv4 *p = &ei->p;  | 
1142  | 0  |   struct ospf_redist *red;  | 
1143  | 0  |   uint8_t type = is_default_prefix4(&ei->p) ? DEFAULT_ROUTE : ei->type;  | 
1144  | 0  |   unsigned short instance = is_default_prefix4(&ei->p) ? 0 : ei->instance;  | 
1145  | 0  |   route_tag_t saved_tag = 0;  | 
1146  |  |  | 
1147  |  |   /* Default is handled differently. */  | 
1148  | 0  |   if (type == DEFAULT_ROUTE)  | 
1149  | 0  |     return 1;  | 
1150  |  |  | 
1151  | 0  |   if (changed)  | 
1152  | 0  |     *changed = 0;  | 
1153  |  | 
  | 
1154  | 0  |   if (!ospf_external_lsa_originate_check(ospf, ei))  | 
1155  | 0  |     return 0;  | 
1156  |  |  | 
1157  |  |   /* Take care connected route. */  | 
1158  | 0  |   if (type == ZEBRA_ROUTE_CONNECT  | 
1159  | 0  |       && !ospf_distribute_check_connected(ospf, ei))  | 
1160  | 0  |     return 0;  | 
1161  |  |  | 
1162  | 0  |   if (!DEFAULT_ROUTE_TYPE(type) && DISTRIBUTE_NAME(ospf, type))  | 
1163  |  |     /* distirbute-list exists, but access-list may not? */  | 
1164  | 0  |     if (DISTRIBUTE_LIST(ospf, type))  | 
1165  | 0  |       if (access_list_apply(DISTRIBUTE_LIST(ospf, type), p)  | 
1166  | 0  |           == FILTER_DENY) { | 
1167  | 0  |         if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
1168  | 0  |           zlog_debug(  | 
1169  | 0  |             "Redistribute[%s]: %pFX filtered by distribute-list.",  | 
1170  | 0  |             ospf_redist_string(type), p);  | 
1171  | 0  |         return 0;  | 
1172  | 0  |       }  | 
1173  |  |  | 
1174  | 0  |   save_values = ei->route_map_set;  | 
1175  | 0  |   ospf_reset_route_map_set_values(&ei->route_map_set);  | 
1176  |  | 
  | 
1177  | 0  |   saved_tag = ei->tag;  | 
1178  |  |   /* Resetting with original route tag */  | 
1179  | 0  |   ei->tag = ei->orig_tag;  | 
1180  |  |  | 
1181  |  |   /* apply route-map if needed */  | 
1182  | 0  |   red = ospf_redist_lookup(ospf, type, instance);  | 
1183  | 0  |   if (red && ROUTEMAP_NAME(red)) { | 
1184  | 0  |     route_map_result_t ret;  | 
1185  |  | 
  | 
1186  | 0  |     ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei);  | 
1187  |  | 
  | 
1188  | 0  |     if (ret == RMAP_DENYMATCH) { | 
1189  | 0  |       ei->route_map_set = save_values;  | 
1190  | 0  |       if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
1191  | 0  |         zlog_debug(  | 
1192  | 0  |           "Redistribute[%s]: %pFX filtered by route-map.",  | 
1193  | 0  |           ospf_redist_string(type), p);  | 
1194  | 0  |       return 0;  | 
1195  | 0  |     }  | 
1196  |  |  | 
1197  |  |     /* check if 'route-map set' changed something */  | 
1198  | 0  |     if (changed) { | 
1199  | 0  |       *changed = !ospf_route_map_set_compare(  | 
1200  | 0  |         &ei->route_map_set, &save_values);  | 
1201  |  |  | 
1202  |  |       /* check if tag is modified */  | 
1203  | 0  |       *changed |= (saved_tag != ei->tag);  | 
1204  | 0  |     }  | 
1205  | 0  |   }  | 
1206  |  |  | 
1207  | 0  |   return 1;  | 
1208  | 0  | }  | 
1209  |  |  | 
1210  |  | /* OSPF route-map set for redistribution */  | 
1211  |  | void ospf_routemap_set(struct ospf_redist *red, const char *name)  | 
1212  | 0  | { | 
1213  | 0  |   if (ROUTEMAP_NAME(red)) { | 
1214  | 0  |     route_map_counter_decrement(ROUTEMAP(red));  | 
1215  | 0  |     free(ROUTEMAP_NAME(red));  | 
1216  | 0  |   }  | 
1217  |  | 
  | 
1218  | 0  |   ROUTEMAP_NAME(red) = strdup(name);  | 
1219  | 0  |   ROUTEMAP(red) = route_map_lookup_by_name(name);  | 
1220  | 0  |   route_map_counter_increment(ROUTEMAP(red));  | 
1221  | 0  | }  | 
1222  |  |  | 
1223  |  | void ospf_routemap_unset(struct ospf_redist *red)  | 
1224  | 0  | { | 
1225  | 0  |   if (ROUTEMAP_NAME(red)) { | 
1226  | 0  |     route_map_counter_decrement(ROUTEMAP(red));  | 
1227  | 0  |     free(ROUTEMAP_NAME(red));  | 
1228  | 0  |   }  | 
1229  |  | 
  | 
1230  | 0  |   ROUTEMAP_NAME(red) = NULL;  | 
1231  | 0  |   ROUTEMAP(red) = NULL;  | 
1232  | 0  | }  | 
1233  |  |  | 
1234  |  | static int ospf_zebra_gr_update(struct ospf *ospf, int command,  | 
1235  |  |         uint32_t stale_time)  | 
1236  | 0  | { | 
1237  | 0  |   struct zapi_cap api;  | 
1238  |  | 
  | 
1239  | 0  |   if (!zclient || zclient->sock < 0 || !ospf)  | 
1240  | 0  |     return 1;  | 
1241  |  |  | 
1242  | 0  |   memset(&api, 0, sizeof(api));  | 
1243  | 0  |   api.cap = command;  | 
1244  | 0  |   api.stale_removal_time = stale_time;  | 
1245  | 0  |   api.vrf_id = ospf->vrf_id;  | 
1246  |  | 
  | 
1247  | 0  |   (void)zclient_capabilities_send(ZEBRA_CLIENT_CAPABILITIES, zclient,  | 
1248  | 0  |           &api);  | 
1249  |  | 
  | 
1250  | 0  |   return 0;  | 
1251  | 0  | }  | 
1252  |  |  | 
1253  |  | int ospf_zebra_gr_enable(struct ospf *ospf, uint32_t stale_time)  | 
1254  | 0  | { | 
1255  | 0  |   if (IS_DEBUG_OSPF_GR)  | 
1256  | 0  |     zlog_debug("Zebra enable GR [stale time %u]", stale_time); | 
1257  |  | 
  | 
1258  | 0  |   return ospf_zebra_gr_update(ospf, ZEBRA_CLIENT_GR_CAPABILITIES,  | 
1259  | 0  |             stale_time);  | 
1260  | 0  | }  | 
1261  |  |  | 
1262  |  | int ospf_zebra_gr_disable(struct ospf *ospf)  | 
1263  | 0  | { | 
1264  | 0  |   if (IS_DEBUG_OSPF_GR)  | 
1265  | 0  |     zlog_debug("Zebra disable GR"); | 
1266  |  | 
  | 
1267  | 0  |   return ospf_zebra_gr_update(ospf, ZEBRA_CLIENT_GR_DISABLE, 0);  | 
1268  | 0  | }  | 
1269  |  |  | 
1270  |  | /* Zebra route add and delete treatment. */  | 
1271  |  | static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)  | 
1272  | 0  | { | 
1273  | 0  |   struct zapi_route api;  | 
1274  | 0  |   struct prefix_ipv4 p;  | 
1275  | 0  |   struct prefix pgen;  | 
1276  | 0  |   unsigned long ifindex;  | 
1277  | 0  |   struct in_addr nexthop;  | 
1278  | 0  |   struct external_info *ei;  | 
1279  | 0  |   struct ospf *ospf;  | 
1280  | 0  |   int i;  | 
1281  | 0  |   uint8_t rt_type;  | 
1282  |  | 
  | 
1283  | 0  |   ospf = ospf_lookup_by_vrf_id(vrf_id);  | 
1284  | 0  |   if (ospf == NULL)  | 
1285  | 0  |     return 0;  | 
1286  |  |  | 
1287  | 0  |   if (zapi_route_decode(zclient->ibuf, &api) < 0)  | 
1288  | 0  |     return -1;  | 
1289  |  |  | 
1290  | 0  |   ifindex = api.nexthops[0].ifindex;  | 
1291  | 0  |   nexthop = api.nexthops[0].gate.ipv4;  | 
1292  | 0  |   rt_type = api.type;  | 
1293  |  | 
  | 
1294  | 0  |   memcpy(&p, &api.prefix, sizeof(p));  | 
1295  | 0  |   if (IPV4_NET127(ntohl(p.prefix.s_addr)))  | 
1296  | 0  |     return 0;  | 
1297  |  |  | 
1298  | 0  |   pgen.family = p.family;  | 
1299  | 0  |   pgen.prefixlen = p.prefixlen;  | 
1300  | 0  |   pgen.u.prefix4 = p.prefix;  | 
1301  |  |  | 
1302  |  |   /* Re-destributed route is default route.  | 
1303  |  |    * Here, route type is used as 'ZEBRA_ROUTE_KERNEL' for  | 
1304  |  |    * updating ex-info. But in resetting (no default-info  | 
1305  |  |    * originate)ZEBRA_ROUTE_MAX is used to delete the ex-info.  | 
1306  |  |    * Resolved this inconsistency by maintaining same route type.  | 
1307  |  |    */  | 
1308  | 0  |   if ((is_default_prefix(&pgen)) && (api.type != ZEBRA_ROUTE_OSPF))  | 
1309  | 0  |     rt_type = DEFAULT_ROUTE;  | 
1310  |  | 
  | 
1311  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))  | 
1312  | 0  |     zlog_debug(  | 
1313  | 0  |       "%s: cmd %s from client %s: vrf_id %d, p %pFX, metric %d",  | 
1314  | 0  |       __func__, zserv_command_string(cmd),  | 
1315  | 0  |       zebra_route_string(api.type), vrf_id, &api.prefix,  | 
1316  | 0  |       api.metric);  | 
1317  |  | 
  | 
1318  | 0  |   if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD) { | 
1319  |  |     /* XXX|HACK|TODO|FIXME:  | 
1320  |  |      * Maybe we should ignore reject/blackhole routes? Testing  | 
1321  |  |      * shows that there is no problems though and this is only way  | 
1322  |  |      * to "summarize" routes in ASBR at the moment. Maybe we need  | 
1323  |  |      * just a better generalised solution for these types?  | 
1324  |  |      */  | 
1325  |  |  | 
1326  |  |     /* Protocol tag overwrites all other tag value sent by zebra */  | 
1327  | 0  |     if (ospf->dtag[rt_type] > 0)  | 
1328  | 0  |       api.tag = ospf->dtag[rt_type];  | 
1329  |  |  | 
1330  |  |     /*  | 
1331  |  |      * Given zebra sends update for a prefix via ADD message, it  | 
1332  |  |      * should  | 
1333  |  |      * be considered as an implicit DEL for that prefix with other  | 
1334  |  |      * source  | 
1335  |  |      * types.  | 
1336  |  |      */  | 
1337  | 0  |     for (i = 0; i <= ZEBRA_ROUTE_MAX; i++)  | 
1338  | 0  |       if (i != rt_type)  | 
1339  | 0  |         ospf_external_info_delete(ospf, i, api.instance,  | 
1340  | 0  |                 p);  | 
1341  |  | 
  | 
1342  | 0  |     ei = ospf_external_info_add(ospf, rt_type, api.instance, p,  | 
1343  | 0  |               ifindex, nexthop, api.tag,  | 
1344  | 0  |               api.metric);  | 
1345  | 0  |     if (ei == NULL) { | 
1346  |  |       /* Nothing has changed, so nothing to do; return */  | 
1347  | 0  |       return 0;  | 
1348  | 0  |     }  | 
1349  | 0  |     if (ospf->router_id.s_addr != INADDR_ANY) { | 
1350  | 0  |       if (is_default_prefix4(&p))  | 
1351  | 0  |         ospf_external_lsa_refresh_default(ospf);  | 
1352  | 0  |       else { | 
1353  | 0  |         struct ospf_external_aggr_rt *aggr;  | 
1354  | 0  |         struct as_external_lsa *al;  | 
1355  | 0  |         struct ospf_lsa *lsa = NULL;  | 
1356  | 0  |         struct in_addr mask;  | 
1357  |  | 
  | 
1358  | 0  |         aggr = ospf_external_aggr_match(ospf, &ei->p);  | 
1359  |  | 
  | 
1360  | 0  |         if (aggr) { | 
1361  |  |           /* Check the AS-external-LSA  | 
1362  |  |            * should be originated.  | 
1363  |  |            */  | 
1364  | 0  |           if (!ospf_redistribute_check(ospf, ei,  | 
1365  | 0  |                      NULL))  | 
1366  | 0  |             return 0;  | 
1367  |  |  | 
1368  | 0  |           if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))  | 
1369  | 0  |             zlog_debug(  | 
1370  | 0  |               "%s: Send Aggreate LSA (%pI4/%d)",  | 
1371  | 0  |               __func__,  | 
1372  | 0  |               &aggr->p.prefix,  | 
1373  | 0  |               aggr->p.prefixlen);  | 
1374  |  | 
  | 
1375  | 0  |           ospf_originate_summary_lsa(ospf, aggr,  | 
1376  | 0  |                    ei);  | 
1377  |  |  | 
1378  |  |           /* Handling the case where the  | 
1379  |  |            * external route prefix  | 
1380  |  |            * and aggegate prefix is same  | 
1381  |  |            * If same don't flush the  | 
1382  |  |            * originated  | 
1383  |  |            * external LSA.  | 
1384  |  |            */  | 
1385  | 0  |           if (prefix_same(  | 
1386  | 0  |                 (struct prefix *)&aggr->p,  | 
1387  | 0  |                 (struct prefix *)&ei->p))  | 
1388  | 0  |             return 0;  | 
1389  |  |  | 
1390  | 0  |           lsa = ospf_external_info_find_lsa(  | 
1391  | 0  |             ospf, &ei->p);  | 
1392  |  | 
  | 
1393  | 0  |           if (lsa) { | 
1394  | 0  |             al = (struct as_external_lsa *)  | 
1395  | 0  |                    lsa->data;  | 
1396  | 0  |             masklen2ip(ei->p.prefixlen,  | 
1397  | 0  |                  &mask);  | 
1398  |  | 
  | 
1399  | 0  |             if (mask.s_addr  | 
1400  | 0  |                 != al->mask.s_addr)  | 
1401  | 0  |               return 0;  | 
1402  |  |  | 
1403  | 0  |             ospf_external_lsa_flush(  | 
1404  | 0  |               ospf, ei->type, &ei->p,  | 
1405  | 0  |               0);  | 
1406  | 0  |           }  | 
1407  | 0  |         } else { | 
1408  | 0  |           struct ospf_lsa *current;  | 
1409  |  | 
  | 
1410  | 0  |           current = ospf_external_info_find_lsa(  | 
1411  | 0  |             ospf, &ei->p);  | 
1412  | 0  |           if (!current) { | 
1413  |  |             /* Check the  | 
1414  |  |              * AS-external-LSA  | 
1415  |  |              * should be  | 
1416  |  |              * originated.  | 
1417  |  |              */  | 
1418  | 0  |             if (!ospf_redistribute_check(  | 
1419  | 0  |                   ospf, ei, NULL))  | 
1420  | 0  |               return 0;  | 
1421  |  |  | 
1422  | 0  |             ospf_external_lsa_originate(  | 
1423  | 0  |               ospf, ei);  | 
1424  | 0  |           } else { | 
1425  | 0  |             if (IS_DEBUG_OSPF(  | 
1426  | 0  |                   zebra,  | 
1427  | 0  |                   ZEBRA_REDISTRIBUTE))  | 
1428  | 0  |               zlog_debug(  | 
1429  | 0  |                 "%s: %pI4 refreshing LSA",  | 
1430  | 0  |                 __func__,  | 
1431  | 0  |                 &p.prefix);  | 
1432  | 0  |             ospf_external_lsa_refresh(  | 
1433  | 0  |               ospf, current, ei,  | 
1434  | 0  |               LSA_REFRESH_FORCE,  | 
1435  | 0  |               false);  | 
1436  | 0  |           }  | 
1437  | 0  |         }  | 
1438  | 0  |       }  | 
1439  | 0  |     }  | 
1440  |  |  | 
1441  |  |     /*  | 
1442  |  |      * Check if default-information originate is  | 
1443  |  |      * with some routemap prefix/access list match.  | 
1444  |  |      */  | 
1445  | 0  |     ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);  | 
1446  |  | 
  | 
1447  | 0  |   } else { /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ | 
1448  | 0  |     struct ospf_external_aggr_rt *aggr;  | 
1449  |  | 
  | 
1450  | 0  |     ei = ospf_external_info_lookup(ospf, rt_type, api.instance, &p);  | 
1451  | 0  |     if (ei == NULL)  | 
1452  | 0  |       return 0;  | 
1453  |  |  | 
1454  |  |     /*  | 
1455  |  |      * Check if default-information originate i  | 
1456  |  |      * with some routemap prefix/access list match.  | 
1457  |  |      * Apply before ei is deleted.  | 
1458  |  |      */  | 
1459  | 0  |     ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);  | 
1460  |  | 
  | 
1461  | 0  |     aggr = ospf_external_aggr_match(ospf, &ei->p);  | 
1462  |  | 
  | 
1463  | 0  |     if (aggr && (ei->aggr_route == aggr)) { | 
1464  | 0  |       ospf_unlink_ei_from_aggr(ospf, aggr, ei);  | 
1465  |  | 
  | 
1466  | 0  |       ospf_external_info_delete(ospf, rt_type, api.instance,  | 
1467  | 0  |               p);  | 
1468  | 0  |     } else { | 
1469  | 0  |       ospf_external_info_delete(ospf, rt_type, api.instance,  | 
1470  | 0  |               p);  | 
1471  |  | 
  | 
1472  | 0  |       if (is_default_prefix4(&p))  | 
1473  | 0  |         ospf_external_lsa_refresh_default(ospf);  | 
1474  | 0  |       else  | 
1475  | 0  |         ospf_external_lsa_flush(ospf, rt_type, &p,  | 
1476  | 0  |               ifindex /*, nexthop */);  | 
1477  | 0  |     }  | 
1478  | 0  |   }  | 
1479  |  |  | 
1480  | 0  |   return 0;  | 
1481  | 0  | }  | 
1482  |  |  | 
1483  |  | void ospf_zebra_import_default_route(struct ospf *ospf, bool unreg)  | 
1484  | 0  | { | 
1485  | 0  |   struct prefix prefix = {}; | 
1486  | 0  |   int command;  | 
1487  |  | 
  | 
1488  | 0  |   if (zclient->sock < 0) { | 
1489  | 0  |     if (IS_DEBUG_OSPF(zebra, ZEBRA))  | 
1490  | 0  |       zlog_debug("  Not connected to Zebra"); | 
1491  | 0  |     return;  | 
1492  | 0  |   }  | 
1493  |  |  | 
1494  | 0  |   prefix.family = AF_INET;  | 
1495  | 0  |   prefix.prefixlen = 0;  | 
1496  |  | 
  | 
1497  | 0  |   if (unreg)  | 
1498  | 0  |     command = ZEBRA_NEXTHOP_UNREGISTER;  | 
1499  | 0  |   else  | 
1500  | 0  |     command = ZEBRA_NEXTHOP_REGISTER;  | 
1501  |  | 
  | 
1502  | 0  |   if (IS_DEBUG_OSPF(zebra, ZEBRA))  | 
1503  | 0  |     zlog_debug("%s: sending cmd %s for %pFX (vrf %u)", __func__, | 
1504  | 0  |          zserv_command_string(command), &prefix,  | 
1505  | 0  |          ospf->vrf_id);  | 
1506  |  | 
  | 
1507  | 0  |   if (zclient_send_rnh(zclient, command, &prefix, SAFI_UNICAST, false,  | 
1508  | 0  |            true, ospf->vrf_id) == ZCLIENT_SEND_FAILURE)  | 
1509  | 0  |     flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_send_rnh() failed",  | 
1510  | 0  |        __func__);  | 
1511  | 0  | }  | 
1512  |  |  | 
1513  |  | static int ospf_zebra_import_check_update(ZAPI_CALLBACK_ARGS)  | 
1514  | 0  | { | 
1515  | 0  |   struct ospf *ospf;  | 
1516  | 0  |   struct zapi_route nhr;  | 
1517  | 0  |   struct prefix matched;  | 
1518  |  | 
  | 
1519  | 0  |   ospf = ospf_lookup_by_vrf_id(vrf_id);  | 
1520  | 0  |   if (ospf == NULL || !IS_OSPF_ASBR(ospf))  | 
1521  | 0  |     return 0;  | 
1522  |  |  | 
1523  | 0  |   if (!zapi_nexthop_update_decode(zclient->ibuf, &matched, &nhr)) { | 
1524  | 0  |     zlog_err("%s[%u]: Failure to decode route", __func__, | 
1525  | 0  |        ospf->vrf_id);  | 
1526  | 0  |     return -1;  | 
1527  | 0  |   }  | 
1528  |  |  | 
1529  | 0  |   if (matched.family != AF_INET || matched.prefixlen != 0 ||  | 
1530  | 0  |       nhr.type == ZEBRA_ROUTE_OSPF)  | 
1531  | 0  |     return 0;  | 
1532  |  |  | 
1533  | 0  |   ospf->nssa_default_import_check.status = !!nhr.nexthop_num;  | 
1534  | 0  |   ospf_abr_nssa_type7_defaults(ospf);  | 
1535  |  | 
  | 
1536  | 0  |   return 0;  | 
1537  | 0  | }  | 
1538  |  |  | 
1539  |  | int ospf_distribute_list_out_set(struct ospf *ospf, int type, const char *name)  | 
1540  | 0  | { | 
1541  |  |   /* Lookup access-list for distribute-list. */  | 
1542  | 0  |   DISTRIBUTE_LIST(ospf, type) = access_list_lookup(AFI_IP, name);  | 
1543  |  |  | 
1544  |  |   /* Clear previous distribute-name. */  | 
1545  | 0  |   if (DISTRIBUTE_NAME(ospf, type))  | 
1546  | 0  |     free(DISTRIBUTE_NAME(ospf, type));  | 
1547  |  |  | 
1548  |  |   /* Set distribute-name. */  | 
1549  | 0  |   DISTRIBUTE_NAME(ospf, type) = strdup(name);  | 
1550  |  |  | 
1551  |  |   /* If access-list have been set, schedule update timer. */  | 
1552  | 0  |   if (DISTRIBUTE_LIST(ospf, type))  | 
1553  | 0  |     ospf_distribute_list_update(ospf, type, 0);  | 
1554  |  | 
  | 
1555  | 0  |   return CMD_SUCCESS;  | 
1556  | 0  | }  | 
1557  |  |  | 
1558  |  | int ospf_distribute_list_out_unset(struct ospf *ospf, int type,  | 
1559  |  |            const char *name)  | 
1560  | 0  | { | 
1561  |  |   /* Schedule update timer. */  | 
1562  | 0  |   if (DISTRIBUTE_LIST(ospf, type))  | 
1563  | 0  |     ospf_distribute_list_update(ospf, type, 0);  | 
1564  |  |  | 
1565  |  |   /* Unset distribute-list. */  | 
1566  | 0  |   DISTRIBUTE_LIST(ospf, type) = NULL;  | 
1567  |  |  | 
1568  |  |   /* Clear distribute-name. */  | 
1569  | 0  |   if (DISTRIBUTE_NAME(ospf, type))  | 
1570  | 0  |     free(DISTRIBUTE_NAME(ospf, type));  | 
1571  |  | 
  | 
1572  | 0  |   DISTRIBUTE_NAME(ospf, type) = NULL;  | 
1573  |  | 
  | 
1574  | 0  |   return CMD_SUCCESS;  | 
1575  | 0  | }  | 
1576  |  |  | 
1577  |  | /* distribute-list update timer. */  | 
1578  |  | static void ospf_distribute_list_update_timer(struct event *thread)  | 
1579  | 0  | { | 
1580  | 0  |   struct route_node *rn;  | 
1581  | 0  |   struct external_info *ei;  | 
1582  | 0  |   struct route_table *rt;  | 
1583  | 0  |   struct ospf_lsa *lsa;  | 
1584  | 0  |   int type, default_refresh = 0;  | 
1585  | 0  |   struct ospf *ospf = EVENT_ARG(thread);  | 
1586  | 0  | 
  | 
1587  | 0  |   if (ospf == NULL)  | 
1588  | 0  |     return;  | 
1589  | 0  | 
  | 
1590  | 0  |   ospf->t_distribute_update = NULL;  | 
1591  | 0  | 
  | 
1592  | 0  |   zlog_info("Zebra[Redistribute]: distribute-list update timer fired!"); | 
1593  | 0  | 
  | 
1594  | 0  |   if (IS_DEBUG_OSPF_EVENT) { | 
1595  | 0  |     zlog_debug("%s: ospf distribute-list update vrf %s id %d", | 
1596  | 0  |          __func__, ospf_vrf_id_to_name(ospf->vrf_id),  | 
1597  | 0  |          ospf->vrf_id);  | 
1598  | 0  |   }  | 
1599  | 0  | 
  | 
1600  | 0  |   /* foreach all external info. */  | 
1601  | 0  |   for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { | 
1602  | 0  |     struct list *ext_list;  | 
1603  | 0  |     struct listnode *node;  | 
1604  | 0  |     struct ospf_external *ext;  | 
1605  | 0  | 
  | 
1606  | 0  |     ext_list = ospf->external[type];  | 
1607  | 0  |     if (!ext_list)  | 
1608  | 0  |       continue;  | 
1609  | 0  | 
  | 
1610  | 0  |     for (ALL_LIST_ELEMENTS_RO(ext_list, node, ext)) { | 
1611  | 0  |       rt = ext->external_info;  | 
1612  | 0  |       if (!rt)  | 
1613  | 0  |         continue;  | 
1614  | 0  |       for (rn = route_top(rt); rn; rn = route_next(rn)) { | 
1615  | 0  |         ei = rn->info;  | 
1616  | 0  |         if (!ei)  | 
1617  | 0  |           continue;  | 
1618  | 0  | 
  | 
1619  | 0  |         if (is_default_prefix4(&ei->p))  | 
1620  | 0  |           default_refresh = 1;  | 
1621  | 0  |         else { | 
1622  | 0  |           struct ospf_external_aggr_rt *aggr;  | 
1623  | 0  | 
  | 
1624  | 0  |           aggr = ospf_external_aggr_match(ospf,  | 
1625  | 0  |                   &ei->p);  | 
1626  | 0  |           if (aggr) { | 
1627  | 0  |             /* Check the  | 
1628  | 0  |              * AS-external-LSA  | 
1629  | 0  |              * should be originated.  | 
1630  | 0  |              */  | 
1631  | 0  |             if (!ospf_redistribute_check(  | 
1632  | 0  |                   ospf, ei, NULL)) { | 
1633  | 0  | 
  | 
1634  | 0  |               ospf_unlink_ei_from_aggr(  | 
1635  | 0  |                 ospf, aggr, ei);  | 
1636  | 0  |               continue;  | 
1637  | 0  |             }  | 
1638  | 0  | 
  | 
1639  | 0  |             if (IS_DEBUG_OSPF(  | 
1640  | 0  |                   lsa,  | 
1641  | 0  |                   EXTNL_LSA_AGGR))  | 
1642  | 0  |               zlog_debug(  | 
1643  | 0  |                 "%s: Send Aggregate LSA (%pI4/%d)",  | 
1644  | 0  |                 __func__,  | 
1645  | 0  |                 &aggr->p.prefix,  | 
1646  | 0  |                 aggr->p.prefixlen);  | 
1647  | 0  | 
  | 
1648  | 0  |             /* Originate Aggregate  | 
1649  | 0  |              * LSA  | 
1650  | 0  |              */  | 
1651  | 0  |             ospf_originate_summary_lsa(  | 
1652  | 0  |               ospf, aggr, ei);  | 
1653  | 0  |           } else if (  | 
1654  | 0  |             (lsa = ospf_external_info_find_lsa(  | 
1655  | 0  |                ospf, &ei->p))) { | 
1656  | 0  |             int force =  | 
1657  | 0  |               LSA_REFRESH_IF_CHANGED;  | 
1658  | 0  |             /* If this is a MaxAge  | 
1659  | 0  |              * LSA, we need to  | 
1660  | 0  |              * force refresh it  | 
1661  | 0  |              * because distribute  | 
1662  | 0  |              * settings might have  | 
1663  | 0  |              * changed and now,  | 
1664  | 0  |              * this LSA needs to be  | 
1665  | 0  |              * originated, not be  | 
1666  | 0  |              * removed.  | 
1667  | 0  |              * If we don't force  | 
1668  | 0  |              * refresh it, it will  | 
1669  | 0  |              * remain a MaxAge LSA  | 
1670  | 0  |              * because it will look  | 
1671  | 0  |              * like it hasn't  | 
1672  | 0  |              * changed. Neighbors  | 
1673  | 0  |              * will not receive  | 
1674  | 0  |              * updates for this LSA.  | 
1675  | 0  |              */  | 
1676  | 0  |             if (IS_LSA_MAXAGE(lsa))  | 
1677  | 0  |               force = LSA_REFRESH_FORCE;  | 
1678  | 0  | 
  | 
1679  | 0  |             ospf_external_lsa_refresh(  | 
1680  | 0  |               ospf, lsa, ei, force,  | 
1681  | 0  |               false);  | 
1682  | 0  |           } else { | 
1683  | 0  |             if (!ospf_redistribute_check(  | 
1684  | 0  |                   ospf, ei, NULL))  | 
1685  | 0  |               continue;  | 
1686  | 0  |             ospf_external_lsa_originate(  | 
1687  | 0  |               ospf, ei);  | 
1688  | 0  |           }  | 
1689  | 0  |         }  | 
1690  | 0  |       }  | 
1691  | 0  |     }  | 
1692  | 0  |   }  | 
1693  | 0  |   if (default_refresh)  | 
1694  | 0  |     ospf_external_lsa_refresh_default(ospf);  | 
1695  | 0  | }  | 
1696  |  |  | 
1697  |  | /* Update distribute-list and set timer to apply access-list. */  | 
1698  |  | void ospf_distribute_list_update(struct ospf *ospf, int type,  | 
1699  |  |          unsigned short instance)  | 
1700  | 0  | { | 
1701  | 0  |   struct ospf_external *ext;  | 
1702  |  |  | 
1703  |  |   /* External info does not exist. */  | 
1704  | 0  |   ext = ospf_external_lookup(ospf, type, instance);  | 
1705  | 0  |   if (!ext || !EXTERNAL_INFO(ext))  | 
1706  | 0  |     return;  | 
1707  |  |  | 
1708  |  |   /* Set timer. If timer is already started, this call does nothing. */  | 
1709  | 0  |   event_add_timer_msec(master, ospf_distribute_list_update_timer, ospf,  | 
1710  | 0  |            ospf->min_ls_interval, &ospf->t_distribute_update);  | 
1711  | 0  | }  | 
1712  |  |  | 
1713  |  | /* If access-list is updated, apply some check. */  | 
1714  |  | static void ospf_filter_update(struct access_list *access)  | 
1715  | 0  | { | 
1716  | 0  |   struct ospf *ospf;  | 
1717  | 0  |   int type;  | 
1718  | 0  |   int abr_inv = 0;  | 
1719  | 0  |   struct ospf_area *area;  | 
1720  | 0  |   struct listnode *node, *n1;  | 
1721  |  |  | 
1722  |  |   /* If OSPF instance does not exist, return right now. */  | 
1723  | 0  |   if (listcount(om->ospf) == 0)  | 
1724  | 0  |     return;  | 
1725  |  |  | 
1726  |  |   /* Iterate all ospf [VRF] instances */  | 
1727  | 0  |   for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { | 
1728  |  |     /* Update distribute-list, and apply filter. */  | 
1729  | 0  |     for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { | 
1730  | 0  |       struct list *red_list;  | 
1731  | 0  |       struct ospf_redist *red;  | 
1732  |  | 
  | 
1733  | 0  |       red_list = ospf->redist[type];  | 
1734  | 0  |       if (red_list)  | 
1735  | 0  |         for (ALL_LIST_ELEMENTS_RO(red_list, node,  | 
1736  | 0  |                 red)) { | 
1737  | 0  |           if (ROUTEMAP(red)) { | 
1738  |  |             /* if route-map is not NULL it  | 
1739  |  |              * may be  | 
1740  |  |              * using this access list */  | 
1741  | 0  |             ospf_distribute_list_update(  | 
1742  | 0  |               ospf, type,  | 
1743  | 0  |               red->instance);  | 
1744  | 0  |           }  | 
1745  | 0  |         }  | 
1746  |  |  | 
1747  |  |       /* There is place for route-map for default-information  | 
1748  |  |        * (ZEBRA_ROUTE_MAX),  | 
1749  |  |        * but no distribute list. */  | 
1750  | 0  |       if (type == ZEBRA_ROUTE_MAX)  | 
1751  | 0  |         break;  | 
1752  |  |  | 
1753  | 0  |       if (DISTRIBUTE_NAME(ospf, type)) { | 
1754  |  |         /* Keep old access-list for distribute-list. */  | 
1755  | 0  |         struct access_list *old =  | 
1756  | 0  |           DISTRIBUTE_LIST(ospf, type);  | 
1757  |  |  | 
1758  |  |         /* Update access-list for distribute-list. */  | 
1759  | 0  |         DISTRIBUTE_LIST(ospf, type) =  | 
1760  | 0  |           access_list_lookup(  | 
1761  | 0  |             AFI_IP,  | 
1762  | 0  |             DISTRIBUTE_NAME(ospf, type));  | 
1763  |  |  | 
1764  |  |         /* No update for this distribute type. */  | 
1765  | 0  |         if (old == NULL  | 
1766  | 0  |             && DISTRIBUTE_LIST(ospf, type) == NULL)  | 
1767  | 0  |           continue;  | 
1768  |  |  | 
1769  |  |         /* Schedule distribute-list update timer. */  | 
1770  | 0  |         if (DISTRIBUTE_LIST(ospf, type) == NULL  | 
1771  | 0  |             || strcmp(DISTRIBUTE_NAME(ospf, type),  | 
1772  | 0  |                 access->name)  | 
1773  | 0  |                  == 0)  | 
1774  | 0  |           ospf_distribute_list_update(ospf, type,  | 
1775  | 0  |                     0);  | 
1776  | 0  |       }  | 
1777  | 0  |     }  | 
1778  |  |  | 
1779  |  |     /* Update Area access-list. */  | 
1780  | 0  |     for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { | 
1781  | 0  |       if (EXPORT_NAME(area)) { | 
1782  | 0  |         EXPORT_LIST(area) = NULL;  | 
1783  | 0  |         abr_inv++;  | 
1784  | 0  |       }  | 
1785  |  | 
  | 
1786  | 0  |       if (IMPORT_NAME(area)) { | 
1787  | 0  |         IMPORT_LIST(area) = NULL;  | 
1788  | 0  |         abr_inv++;  | 
1789  | 0  |       }  | 
1790  | 0  |     }  | 
1791  |  |  | 
1792  |  |     /* Schedule ABR tasks -- this will be changed -- takada. */  | 
1793  | 0  |     if (IS_OSPF_ABR(ospf) && abr_inv)  | 
1794  | 0  |       ospf_schedule_abr_task(ospf);  | 
1795  | 0  |   }  | 
1796  | 0  | }  | 
1797  |  |  | 
1798  |  | /* If prefix-list is updated, do some updates. */  | 
1799  |  | static void ospf_prefix_list_update(struct prefix_list *plist)  | 
1800  | 0  | { | 
1801  | 0  |   struct ospf *ospf = NULL;  | 
1802  | 0  |   int type;  | 
1803  | 0  |   int abr_inv = 0;  | 
1804  | 0  |   struct ospf_area *area;  | 
1805  | 0  |   struct listnode *node, *n1;  | 
1806  |  |  | 
1807  |  |   /* If OSPF instatnce does not exist, return right now. */  | 
1808  | 0  |   if (listcount(om->ospf) == 0)  | 
1809  | 0  |     return;  | 
1810  |  |  | 
1811  |  |   /* Iterate all ospf [VRF] instances */  | 
1812  | 0  |   for (ALL_LIST_ELEMENTS_RO(om->ospf, n1, ospf)) { | 
1813  |  |  | 
1814  |  |     /* Update all route-maps which are used  | 
1815  |  |      * as redistribution filters.  | 
1816  |  |      * They might use prefix-list.  | 
1817  |  |      */  | 
1818  | 0  |     for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { | 
1819  | 0  |       struct list *red_list;  | 
1820  | 0  |       struct ospf_redist *red;  | 
1821  |  | 
  | 
1822  | 0  |       red_list = ospf->redist[type];  | 
1823  | 0  |       if (!red_list)  | 
1824  | 0  |         continue;  | 
1825  |  |  | 
1826  | 0  |       for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) { | 
1827  | 0  |         if (ROUTEMAP(red)) { | 
1828  |  |           /* if route-map is not NULL  | 
1829  |  |            * it may be using  | 
1830  |  |            * this prefix list */  | 
1831  | 0  |           ospf_distribute_list_update(  | 
1832  | 0  |             ospf, type, red->instance);  | 
1833  | 0  |         }  | 
1834  | 0  |       }  | 
1835  | 0  |     }  | 
1836  |  |  | 
1837  |  |     /* Update area filter-lists. */  | 
1838  | 0  |     for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) { | 
1839  |  |       /* Update filter-list in. */  | 
1840  | 0  |       if (PREFIX_NAME_IN(area)  | 
1841  | 0  |           && strcmp(PREFIX_NAME_IN(area),  | 
1842  | 0  |               prefix_list_name(plist))  | 
1843  | 0  |                == 0) { | 
1844  | 0  |         PREFIX_LIST_IN(area) = prefix_list_lookup(  | 
1845  | 0  |           AFI_IP, PREFIX_NAME_IN(area));  | 
1846  | 0  |         abr_inv++;  | 
1847  | 0  |       }  | 
1848  |  |  | 
1849  |  |       /* Update filter-list out. */  | 
1850  | 0  |       if (PREFIX_NAME_OUT(area)  | 
1851  | 0  |           && strcmp(PREFIX_NAME_OUT(area),  | 
1852  | 0  |               prefix_list_name(plist))  | 
1853  | 0  |                == 0) { | 
1854  | 0  |         PREFIX_LIST_OUT(area) = prefix_list_lookup(  | 
1855  | 0  |           AFI_IP, PREFIX_NAME_OUT(area));  | 
1856  | 0  |         abr_inv++;  | 
1857  | 0  |       }  | 
1858  | 0  |     }  | 
1859  |  |  | 
1860  |  |     /* Schedule ABR task. */  | 
1861  | 0  |     if (IS_OSPF_ABR(ospf) && abr_inv)  | 
1862  | 0  |       ospf_schedule_abr_task(ospf);  | 
1863  | 0  |   }  | 
1864  | 0  | }  | 
1865  |  |  | 
1866  |  | static struct ospf_distance *ospf_distance_new(void)  | 
1867  | 0  | { | 
1868  | 0  |   return XCALLOC(MTYPE_OSPF_DISTANCE, sizeof(struct ospf_distance));  | 
1869  | 0  | }  | 
1870  |  |  | 
1871  |  | static void ospf_distance_free(struct ospf_distance *odistance)  | 
1872  | 0  | { | 
1873  | 0  |   XFREE(MTYPE_OSPF_DISTANCE, odistance);  | 
1874  | 0  | }  | 
1875  |  |  | 
1876  |  | int ospf_distance_set(struct vty *vty, struct ospf *ospf,  | 
1877  |  |           const char *distance_str, const char *ip_str,  | 
1878  |  |           const char *access_list_str)  | 
1879  | 0  | { | 
1880  | 0  |   int ret;  | 
1881  | 0  |   struct prefix_ipv4 p;  | 
1882  | 0  |   uint8_t distance;  | 
1883  | 0  |   struct route_node *rn;  | 
1884  | 0  |   struct ospf_distance *odistance;  | 
1885  |  | 
  | 
1886  | 0  |   ret = str2prefix_ipv4(ip_str, &p);  | 
1887  | 0  |   if (ret == 0) { | 
1888  | 0  |     vty_out(vty, "Malformed prefix\n");  | 
1889  | 0  |     return CMD_WARNING_CONFIG_FAILED;  | 
1890  | 0  |   }  | 
1891  |  |  | 
1892  | 0  |   distance = atoi(distance_str);  | 
1893  |  |  | 
1894  |  |   /* Get OSPF distance node. */  | 
1895  | 0  |   rn = route_node_get(ospf->distance_table, (struct prefix *)&p);  | 
1896  | 0  |   if (rn->info) { | 
1897  | 0  |     odistance = rn->info;  | 
1898  | 0  |     route_unlock_node(rn);  | 
1899  | 0  |   } else { | 
1900  | 0  |     odistance = ospf_distance_new();  | 
1901  | 0  |     rn->info = odistance;  | 
1902  | 0  |   }  | 
1903  |  |  | 
1904  |  |   /* Set distance value. */  | 
1905  | 0  |   odistance->distance = distance;  | 
1906  |  |  | 
1907  |  |   /* Reset access-list configuration. */  | 
1908  | 0  |   if (odistance->access_list) { | 
1909  | 0  |     free(odistance->access_list);  | 
1910  | 0  |     odistance->access_list = NULL;  | 
1911  | 0  |   }  | 
1912  | 0  |   if (access_list_str)  | 
1913  | 0  |     odistance->access_list = strdup(access_list_str);  | 
1914  |  | 
  | 
1915  | 0  |   return CMD_SUCCESS;  | 
1916  | 0  | }  | 
1917  |  |  | 
1918  |  | int ospf_distance_unset(struct vty *vty, struct ospf *ospf,  | 
1919  |  |       const char *distance_str, const char *ip_str,  | 
1920  |  |       char const *access_list_str)  | 
1921  | 0  | { | 
1922  | 0  |   int ret;  | 
1923  | 0  |   struct prefix_ipv4 p;  | 
1924  | 0  |   struct route_node *rn;  | 
1925  | 0  |   struct ospf_distance *odistance;  | 
1926  |  | 
  | 
1927  | 0  |   ret = str2prefix_ipv4(ip_str, &p);  | 
1928  | 0  |   if (ret == 0) { | 
1929  | 0  |     vty_out(vty, "Malformed prefix\n");  | 
1930  | 0  |     return CMD_WARNING_CONFIG_FAILED;  | 
1931  | 0  |   }  | 
1932  |  |  | 
1933  | 0  |   rn = route_node_lookup(ospf->distance_table, (struct prefix *)&p);  | 
1934  | 0  |   if (!rn) { | 
1935  | 0  |     vty_out(vty, "Can't find specified prefix\n");  | 
1936  | 0  |     return CMD_WARNING_CONFIG_FAILED;  | 
1937  | 0  |   }  | 
1938  |  |  | 
1939  | 0  |   odistance = rn->info;  | 
1940  |  | 
  | 
1941  | 0  |   if (odistance->access_list)  | 
1942  | 0  |     free(odistance->access_list);  | 
1943  | 0  |   ospf_distance_free(odistance);  | 
1944  |  | 
  | 
1945  | 0  |   rn->info = NULL;  | 
1946  | 0  |   route_unlock_node(rn);  | 
1947  | 0  |   route_unlock_node(rn);  | 
1948  |  | 
  | 
1949  | 0  |   return CMD_SUCCESS;  | 
1950  | 0  | }  | 
1951  |  |  | 
1952  |  | void ospf_distance_reset(struct ospf *ospf)  | 
1953  | 0  | { | 
1954  | 0  |   struct route_node *rn;  | 
1955  | 0  |   struct ospf_distance *odistance;  | 
1956  |  | 
  | 
1957  | 0  |   for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) { | 
1958  | 0  |     odistance = rn->info;  | 
1959  | 0  |     if (!odistance)  | 
1960  | 0  |       continue;  | 
1961  |  |  | 
1962  | 0  |     if (odistance->access_list)  | 
1963  | 0  |       free(odistance->access_list);  | 
1964  | 0  |     ospf_distance_free(odistance);  | 
1965  | 0  |     rn->info = NULL;  | 
1966  | 0  |     route_unlock_node(rn);  | 
1967  | 0  |   }  | 
1968  | 0  | }  | 
1969  |  |  | 
1970  |  | uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *p,  | 
1971  |  |           struct ospf_route * or)  | 
1972  | 0  | { | 
1973  |  | 
  | 
1974  | 0  |   if (ospf == NULL)  | 
1975  | 0  |     return 0;  | 
1976  |  |  | 
1977  | 0  |   if (ospf->distance_intra && or->path_type == OSPF_PATH_INTRA_AREA)  | 
1978  | 0  |     return ospf->distance_intra;  | 
1979  |  |  | 
1980  | 0  |   if (ospf->distance_inter && or->path_type == OSPF_PATH_INTER_AREA)  | 
1981  | 0  |     return ospf->distance_inter;  | 
1982  |  |  | 
1983  | 0  |   if (ospf->distance_external  | 
1984  | 0  |       && (or->path_type == OSPF_PATH_TYPE1_EXTERNAL ||  | 
1985  | 0  |     or->path_type == OSPF_PATH_TYPE2_EXTERNAL))  | 
1986  | 0  |     return ospf->distance_external;  | 
1987  |  |  | 
1988  | 0  |   if (ospf->distance_all)  | 
1989  | 0  |     return ospf->distance_all;  | 
1990  |  |  | 
1991  | 0  |   return 0;  | 
1992  | 0  | }  | 
1993  |  |  | 
1994  |  | void ospf_zebra_vrf_register(struct ospf *ospf)  | 
1995  | 1  | { | 
1996  | 1  |   if (!zclient || zclient->sock < 0 || !ospf)  | 
1997  | 1  |     return;  | 
1998  |  |  | 
1999  | 0  |   if (ospf->vrf_id != VRF_UNKNOWN) { | 
2000  | 0  |     if (IS_DEBUG_OSPF_EVENT)  | 
2001  | 0  |       zlog_debug("%s: Register VRF %s id %u", __func__, | 
2002  | 0  |            ospf_vrf_id_to_name(ospf->vrf_id),  | 
2003  | 0  |            ospf->vrf_id);  | 
2004  | 0  |     zclient_send_reg_requests(zclient, ospf->vrf_id);  | 
2005  | 0  |   }  | 
2006  | 0  | }  | 
2007  |  |  | 
2008  |  | void ospf_zebra_vrf_deregister(struct ospf *ospf)  | 
2009  | 0  | { | 
2010  | 0  |   if (!zclient || zclient->sock < 0 || !ospf)  | 
2011  | 0  |     return;  | 
2012  |  |  | 
2013  | 0  |   if (ospf->vrf_id != VRF_DEFAULT && ospf->vrf_id != VRF_UNKNOWN) { | 
2014  | 0  |     if (IS_DEBUG_OSPF_EVENT)  | 
2015  | 0  |       zlog_debug("%s: De-Register VRF %s id %u to Zebra.", | 
2016  | 0  |            __func__, ospf_vrf_id_to_name(ospf->vrf_id),  | 
2017  | 0  |            ospf->vrf_id);  | 
2018  |  |     /* Deregister for router-id, interfaces,  | 
2019  |  |      * redistributed routes. */  | 
2020  | 0  |     zclient_send_dereg_requests(zclient, ospf->vrf_id);  | 
2021  | 0  |   }  | 
2022  | 0  | }  | 
2023  |  |  | 
2024  |  | /* Label Manager Functions */  | 
2025  |  |  | 
2026  |  | /**  | 
2027  |  |  * Check if Label Manager is Ready or not.  | 
2028  |  |  *  | 
2029  |  |  * @return  True if Label Manager is ready, False otherwise  | 
2030  |  |  */  | 
2031  |  | bool ospf_zebra_label_manager_ready(void)  | 
2032  | 0  | { | 
2033  | 0  |   return (zclient_sync->sock > 0);  | 
2034  | 0  | }  | 
2035  |  |  | 
2036  |  | /**  | 
2037  |  |  * Request Label Range to the Label Manager.  | 
2038  |  |  *  | 
2039  |  |  * @param base    base label of the label range to request  | 
2040  |  |  * @param chunk_size  size of the label range to request  | 
2041  |  |  *  | 
2042  |  |  * @return  0 on success, -1 on failure  | 
2043  |  |  */  | 
2044  |  | int ospf_zebra_request_label_range(uint32_t base, uint32_t chunk_size)  | 
2045  | 0  | { | 
2046  | 0  |   int ret;  | 
2047  | 0  |   uint32_t start, end;  | 
2048  |  | 
  | 
2049  | 0  |   if (zclient_sync->sock < 0)  | 
2050  | 0  |     return -1;  | 
2051  |  |  | 
2052  | 0  |   ret = lm_get_label_chunk(zclient_sync, 0, base, chunk_size, &start,  | 
2053  | 0  |          &end);  | 
2054  | 0  |   if (ret < 0) { | 
2055  | 0  |     zlog_warn("%s: error getting label range!", __func__); | 
2056  | 0  |     return -1;  | 
2057  | 0  |   }  | 
2058  |  |  | 
2059  | 0  |   return 0;  | 
2060  | 0  | }  | 
2061  |  |  | 
2062  |  | /**  | 
2063  |  |  * Release Label Range to the Label Manager.  | 
2064  |  |  *  | 
2065  |  |  * @param start   start of label range to release  | 
2066  |  |  * @param end   end of label range to release  | 
2067  |  |  *  | 
2068  |  |  * @return    0 on success, -1 otherwise  | 
2069  |  |  */  | 
2070  |  | int ospf_zebra_release_label_range(uint32_t start, uint32_t end)  | 
2071  | 0  | { | 
2072  | 0  |   int ret;  | 
2073  |  | 
  | 
2074  | 0  |   if (zclient_sync->sock < 0)  | 
2075  | 0  |     return -1;  | 
2076  |  |  | 
2077  | 0  |   ret = lm_release_label_chunk(zclient_sync, start, end);  | 
2078  | 0  |   if (ret < 0) { | 
2079  | 0  |     zlog_warn("%s: error releasing label range!", __func__); | 
2080  | 0  |     return -1;  | 
2081  | 0  |   }  | 
2082  |  |  | 
2083  | 0  |   return 0;  | 
2084  | 0  | }  | 
2085  |  |  | 
2086  |  | /**  | 
2087  |  |  * Connect to the Label Manager.  | 
2088  |  |  *  | 
2089  |  |  * @return  0 on success, -1 otherwise  | 
2090  |  |  */  | 
2091  |  | int ospf_zebra_label_manager_connect(void)  | 
2092  | 0  | { | 
2093  |  |   /* Connect to label manager. */  | 
2094  | 0  |   if (zclient_socket_connect(zclient_sync) < 0) { | 
2095  | 0  |     zlog_warn("%s: failed connecting synchronous zclient!", | 
2096  | 0  |         __func__);  | 
2097  | 0  |     return -1;  | 
2098  | 0  |   }  | 
2099  |  |   /* make socket non-blocking */  | 
2100  | 0  |   set_nonblocking(zclient_sync->sock);  | 
2101  |  |  | 
2102  |  |   /* Send hello to notify zebra this is a synchronous client */  | 
2103  | 0  |   if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) { | 
2104  | 0  |     zlog_warn("%s: failed sending hello for synchronous zclient!", | 
2105  | 0  |         __func__);  | 
2106  | 0  |     close(zclient_sync->sock);  | 
2107  | 0  |     zclient_sync->sock = -1;  | 
2108  | 0  |     return -1;  | 
2109  | 0  |   }  | 
2110  |  |  | 
2111  |  |   /* Connect to label manager */  | 
2112  | 0  |   if (lm_label_manager_connect(zclient_sync, 0) != 0) { | 
2113  | 0  |     zlog_warn("%s: failed connecting to label manager!", __func__); | 
2114  | 0  |     if (zclient_sync->sock > 0) { | 
2115  | 0  |       close(zclient_sync->sock);  | 
2116  | 0  |       zclient_sync->sock = -1;  | 
2117  | 0  |     }  | 
2118  | 0  |     return -1;  | 
2119  | 0  |   }  | 
2120  |  |  | 
2121  | 0  |   osr_debug("SR (%s): Successfully connected to the Label Manager", | 
2122  | 0  |       __func__);  | 
2123  |  | 
  | 
2124  | 0  |   return 0;  | 
2125  | 0  | }  | 
2126  |  |  | 
2127  |  | static void ospf_zebra_connected(struct zclient *zclient)  | 
2128  | 0  | { | 
2129  | 0  |   struct ospf *ospf;  | 
2130  | 0  |   struct listnode *node;  | 
2131  |  |  | 
2132  |  |   /* Send the client registration */  | 
2133  | 0  |   bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, VRF_DEFAULT);  | 
2134  |  | 
  | 
2135  | 0  |   zclient_send_reg_requests(zclient, VRF_DEFAULT);  | 
2136  |  |  | 
2137  |  |   /* Activate graceful restart if configured. */  | 
2138  | 0  |   for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) { | 
2139  | 0  |     if (!ospf->gr_info.restart_support)  | 
2140  | 0  |       continue;  | 
2141  | 0  |     (void)ospf_zebra_gr_enable(ospf, ospf->gr_info.grace_period);  | 
2142  | 0  |   }  | 
2143  | 0  | }  | 
2144  |  |  | 
2145  |  | /*  | 
2146  |  |  * opaque messages between processes  | 
2147  |  |  */  | 
2148  |  | static int ospf_opaque_msg_handler(ZAPI_CALLBACK_ARGS)  | 
2149  | 0  | { | 
2150  | 0  |   struct stream *s;  | 
2151  | 0  |   struct zapi_opaque_msg info;  | 
2152  | 0  |   struct ldp_igp_sync_if_state state;  | 
2153  | 0  |   struct ldp_igp_sync_announce announce;  | 
2154  | 0  |   struct zapi_opaque_reg_info dst;  | 
2155  | 0  |   int ret = 0;  | 
2156  |  | 
  | 
2157  | 0  |   s = zclient->ibuf;  | 
2158  |  | 
  | 
2159  | 0  |   if (zclient_opaque_decode(s, &info) != 0)  | 
2160  | 0  |     return -1;  | 
2161  |  |  | 
2162  | 0  |   switch (info.type) { | 
2163  | 0  |   case LINK_STATE_SYNC:  | 
2164  | 0  |     STREAM_GETC(s, dst.proto);  | 
2165  | 0  |     STREAM_GETW(s, dst.instance);  | 
2166  | 0  |     STREAM_GETL(s, dst.session_id);  | 
2167  | 0  |     dst.type = LINK_STATE_SYNC;  | 
2168  | 0  |     ret = ospf_te_sync_ted(dst);  | 
2169  | 0  |     break;  | 
2170  | 0  |   case LDP_IGP_SYNC_IF_STATE_UPDATE:  | 
2171  | 0  |     STREAM_GET(&state, s, sizeof(state));  | 
2172  | 0  |     ret = ospf_ldp_sync_state_update(state);  | 
2173  | 0  |     break;  | 
2174  | 0  |   case LDP_IGP_SYNC_ANNOUNCE_UPDATE:  | 
2175  | 0  |     STREAM_GET(&announce, s, sizeof(announce));  | 
2176  | 0  |     ret = ospf_ldp_sync_announce_update(announce);  | 
2177  | 0  |     break;  | 
2178  | 0  |   default:  | 
2179  | 0  |     break;  | 
2180  | 0  |   }  | 
2181  |  |  | 
2182  | 0  | stream_failure:  | 
2183  |  | 
  | 
2184  | 0  |   return ret;  | 
2185  | 0  | }  | 
2186  |  |  | 
2187  |  | static int ospf_zebra_client_close_notify(ZAPI_CALLBACK_ARGS)  | 
2188  | 0  | { | 
2189  | 0  |   int ret = 0;  | 
2190  |  | 
  | 
2191  | 0  |   struct zapi_client_close_info info;  | 
2192  |  | 
  | 
2193  | 0  |   if (zapi_client_close_notify_decode(zclient->ibuf, &info) < 0)  | 
2194  | 0  |     return -1;  | 
2195  |  |  | 
2196  | 0  |   ospf_ldp_sync_handle_client_close(&info);  | 
2197  |  | 
  | 
2198  | 0  |   return ret;  | 
2199  | 0  | }  | 
2200  |  |  | 
2201  |  | static zclient_handler *const ospf_handlers[] = { | 
2202  |  |   [ZEBRA_ROUTER_ID_UPDATE] = ospf_router_id_update_zebra,  | 
2203  |  |   [ZEBRA_INTERFACE_ADDRESS_ADD] = ospf_interface_address_add,  | 
2204  |  |   [ZEBRA_INTERFACE_ADDRESS_DELETE] = ospf_interface_address_delete,  | 
2205  |  |   [ZEBRA_INTERFACE_LINK_PARAMS] = ospf_interface_link_params,  | 
2206  |  |   [ZEBRA_INTERFACE_VRF_UPDATE] = ospf_interface_vrf_update,  | 
2207  |  |  | 
2208  |  |   [ZEBRA_REDISTRIBUTE_ROUTE_ADD] = ospf_zebra_read_route,  | 
2209  |  |   [ZEBRA_REDISTRIBUTE_ROUTE_DEL] = ospf_zebra_read_route,  | 
2210  |  |   [ZEBRA_NEXTHOP_UPDATE] = ospf_zebra_import_check_update,  | 
2211  |  |  | 
2212  |  |   [ZEBRA_OPAQUE_MESSAGE] = ospf_opaque_msg_handler,  | 
2213  |  |  | 
2214  |  |   [ZEBRA_CLIENT_CLOSE_NOTIFY] = ospf_zebra_client_close_notify,  | 
2215  |  | };  | 
2216  |  |  | 
2217  |  | void ospf_zebra_init(struct event_loop *master, unsigned short instance)  | 
2218  | 1  | { | 
2219  |  |   /* Allocate zebra structure. */  | 
2220  | 1  |   zclient = zclient_new(master, &zclient_options_default, ospf_handlers,  | 
2221  | 1  |             array_size(ospf_handlers));  | 
2222  | 1  |   zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs);  | 
2223  | 1  |   zclient->zebra_connected = ospf_zebra_connected;  | 
2224  |  |  | 
2225  |  |   /* Initialize special zclient for synchronous message exchanges. */  | 
2226  | 1  |   struct zclient_options options = zclient_options_default;  | 
2227  | 1  |   options.synchronous = true;  | 
2228  | 1  |   zclient_sync = zclient_new(master, &options, NULL, 0);  | 
2229  | 1  |   zclient_sync->sock = -1;  | 
2230  | 1  |   zclient_sync->redist_default = ZEBRA_ROUTE_OSPF;  | 
2231  | 1  |   zclient_sync->instance = instance;  | 
2232  |  |   /*  | 
2233  |  |    * session_id must be different from default value (0) to distinguish  | 
2234  |  |    * the asynchronous socket from the synchronous one  | 
2235  |  |    */  | 
2236  | 1  |   zclient_sync->session_id = 1;  | 
2237  | 1  |   zclient_sync->privs = &ospfd_privs;  | 
2238  |  |  | 
2239  | 1  |   access_list_add_hook(ospf_filter_update);  | 
2240  | 1  |   access_list_delete_hook(ospf_filter_update);  | 
2241  | 1  |   prefix_list_add_hook(ospf_prefix_list_update);  | 
2242  | 1  |   prefix_list_delete_hook(ospf_prefix_list_update);  | 
2243  | 1  | }  | 
2244  |  |  | 
2245  |  | void ospf_zebra_send_arp(const struct interface *ifp, const struct prefix *p)  | 
2246  | 0  | { | 
2247  | 0  |   zclient_send_neigh_discovery_req(zclient, ifp, p);  | 
2248  | 0  | }  |