]>
Commit | Line | Data |
---|---|---|
58ef912c MM |
1 | /* |
2 | * BIRD Internet Routing Daemon -- Protocols | |
3 | * | |
7293c5dd | 4 | * (c) 1998--2000 Martin Mares <mj@ucw.cz> |
58ef912c MM |
5 | * |
6 | * Can be freely distributed and used under the terms of the GNU GPL. | |
7 | */ | |
8 | ||
9 | #ifndef _BIRD_PROTOCOL_H_ | |
10 | #define _BIRD_PROTOCOL_H_ | |
11 | ||
2326b001 | 12 | #include "lib/lists.h" |
1feea03e | 13 | #include "lib/resource.h" |
9685deb9 | 14 | #include "lib/timer.h" |
4cdd0784 | 15 | #include "conf/conf.h" |
58ef912c | 16 | |
2326b001 | 17 | struct iface; |
9a158361 | 18 | struct ifa; |
dca75fd7 | 19 | struct rtable; |
2326b001 MM |
20 | struct rte; |
21 | struct neighbor; | |
1b769b08 | 22 | struct rta; |
8c43696d | 23 | struct network; |
31b3e1bb MM |
24 | struct proto_config; |
25 | struct config; | |
26 | struct proto; | |
64011f89 | 27 | struct event; |
bb027be1 | 28 | struct ea_list; |
3991d84e | 29 | struct eattr; |
ae97b946 | 30 | struct symbol; |
2326b001 | 31 | |
58ef912c MM |
32 | /* |
33 | * Routing Protocol | |
34 | */ | |
35 | ||
36 | struct protocol { | |
a5f1a60e | 37 | node n; |
58ef912c | 38 | char *name; |
d272fe22 | 39 | char *template; /* Template for automatic generation of names */ |
4ba84ebc | 40 | int name_counter; /* Counter for automatic name generation */ |
3991d84e | 41 | int attr_class; /* Attribute class known to this protocol */ |
c0adf7e9 | 42 | int multitable; /* Protocol handles all announce hooks itself */ |
39c028e9 | 43 | unsigned preference; /* Default protocol preference */ |
58ef912c | 44 | |
31b3e1bb MM |
45 | void (*preconfig)(struct protocol *, struct config *); /* Just before configuring */ |
46 | void (*postconfig)(struct proto_config *); /* After configuring each instance */ | |
47 | struct proto * (*init)(struct proto_config *); /* Create new instance */ | |
50fe90ed | 48 | int (*reconfigure)(struct proto *, struct proto_config *); /* Try to reconfigure instance, returns success */ |
31b3e1bb | 49 | void (*dump)(struct proto *); /* Debugging dump */ |
69ec9087 | 50 | void (*dump_attrs)(struct rte *); /* Dump protocol-dependent attributes */ |
31b3e1bb MM |
51 | int (*start)(struct proto *); /* Start the instance */ |
52 | int (*shutdown)(struct proto *); /* Stop the instance */ | |
cfe34a31 | 53 | void (*cleanup)(struct proto *); /* Called after shutdown when protocol became hungry/down */ |
9685deb9 | 54 | void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */ |
ce1da96e | 55 | void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */ |
aebe06b4 | 56 | int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */ |
b8113a5e | 57 | void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */ |
a7f23f58 | 58 | void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */ |
58ef912c MM |
59 | }; |
60 | ||
0432c017 | 61 | void protos_build(void); |
3991d84e | 62 | void proto_build(struct protocol *); |
31b3e1bb MM |
63 | void protos_preconfig(struct config *); |
64 | void protos_postconfig(struct config *); | |
bf1aec97 | 65 | void protos_commit(struct config *new, struct config *old, int force_restart, int type); |
87d2be86 | 66 | void protos_dump_all(void); |
a5f1a60e | 67 | |
3991d84e MM |
68 | #define GA_UNKNOWN 0 /* Attribute not recognized */ |
69 | #define GA_NAME 1 /* Result = name */ | |
70 | #define GA_FULL 2 /* Result = both name and value */ | |
58ef912c MM |
71 | |
72 | /* | |
73 | * Known protocols | |
74 | */ | |
75 | ||
2638249d | 76 | extern struct protocol |
93e868c7 | 77 | proto_device, proto_radv, proto_rip, proto_static, |
2638249d | 78 | proto_ospf, proto_pipe, proto_bgp; |
58ef912c MM |
79 | |
80 | /* | |
81 | * Routing Protocol Instance | |
82 | */ | |
83 | ||
31b3e1bb MM |
84 | struct proto_config { |
85 | node n; | |
86 | struct config *global; /* Global configuration data */ | |
1d2664a4 MM |
87 | struct protocol *protocol; /* Protocol */ |
88 | struct proto *proto; /* Instance we've created */ | |
31b3e1bb | 89 | char *name; |
e04555c0 | 90 | char *dsc; |
a7f23f58 | 91 | int class; /* SYM_PROTO or SYM_TEMPLATE */ |
cf31112f OZ |
92 | u32 debug, mrtdump; /* Debugging bitfields, both use D_* constants */ |
93 | unsigned preference, disabled; /* Generic parameters */ | |
15550957 | 94 | int in_keep_filtered; /* Routes rejected in import filter are kept */ |
4cdd0784 | 95 | u32 router_id; /* Protocol specific router ID */ |
0e02abfd | 96 | struct rtable_config *table; /* Table we're attached to */ |
529c4149 | 97 | struct filter *in_filter, *out_filter; /* Attached filters */ |
ebecb6f6 | 98 | struct proto_limit *in_limit; /* Limit for importing routes from protocol */ |
d9b77cc2 | 99 | struct proto_limit *out_limit; /* Limit for exporting routes to protocol */ |
31b3e1bb | 100 | |
a7f23f58 OZ |
101 | /* Check proto_reconfigure() and proto_copy_config() after changing struct proto_config */ |
102 | ||
31b3e1bb MM |
103 | /* Protocol-specific data follow... */ |
104 | }; | |
105 | ||
ebecb6f6 | 106 | /* Protocol statistics */ |
925fe2d3 OZ |
107 | struct proto_stats { |
108 | /* Import - from protocol to core */ | |
109 | u32 imp_routes; /* Number of routes successfully imported to the (adjacent) routing table */ | |
15550957 | 110 | u32 filt_routes; /* Number of routes rejected in import filter but kept in the routing table */ |
cf98be7b | 111 | u32 pref_routes; /* Number of routes that are preferred, sum over all routing tables */ |
925fe2d3 OZ |
112 | u32 imp_updates_received; /* Number of route updates received */ |
113 | u32 imp_updates_invalid; /* Number of route updates rejected as invalid */ | |
114 | u32 imp_updates_filtered; /* Number of route updates rejected by filters */ | |
115 | u32 imp_updates_ignored; /* Number of route updates rejected as already in route table */ | |
116 | u32 imp_updates_accepted; /* Number of route updates accepted and imported */ | |
117 | u32 imp_withdraws_received; /* Number of route withdraws received */ | |
118 | u32 imp_withdraws_invalid; /* Number of route withdraws rejected as invalid */ | |
119 | u32 imp_withdraws_ignored; /* Number of route withdraws rejected as already not in route table */ | |
120 | u32 imp_withdraws_accepted; /* Number of route withdraws accepted and processed */ | |
121 | ||
122 | /* Export - from core to protocol */ | |
123 | u32 exp_routes; /* Number of routes successfully exported to the protocol */ | |
124 | u32 exp_updates_received; /* Number of route updates received */ | |
125 | u32 exp_updates_rejected; /* Number of route updates rejected by protocol */ | |
126 | u32 exp_updates_filtered; /* Number of route updates rejected by filters */ | |
127 | u32 exp_updates_accepted; /* Number of route updates accepted and exported */ | |
128 | u32 exp_withdraws_received; /* Number of route withdraws received */ | |
129 | u32 exp_withdraws_accepted; /* Number of route withdraws accepted and processed */ | |
130 | }; | |
131 | ||
58ef912c | 132 | struct proto { |
f14a4bec MM |
133 | node n; /* Node in *_proto_list */ |
134 | node glob_node; /* Node in global proto_list */ | |
58ef912c | 135 | struct protocol *proto; /* Protocol */ |
31b3e1bb | 136 | struct proto_config *cf; /* Configuration data */ |
50fe90ed | 137 | struct proto_config *cf_new; /* Configuration we want to switch to after shutdown (NULL=delete) */ |
31b3e1bb | 138 | pool *pool; /* Pool containing local objects */ |
64011f89 | 139 | struct event *attn; /* "Pay attention" event */ |
31b3e1bb | 140 | |
64011f89 | 141 | char *name; /* Name of this instance (== cf->name) */ |
cf31112f OZ |
142 | u32 debug; /* Debugging flags */ |
143 | u32 mrtdump; /* MRTDump flags */ | |
58ef912c | 144 | unsigned preference; /* Default route preference */ |
ebecb6f6 OZ |
145 | byte accept_ra_types; /* Which types of route announcements are accepted (RA_OPTIMAL or RA_ANY) */ |
146 | byte disabled; /* Manually disabled */ | |
147 | byte proto_state; /* Protocol state machine (PS_*, see below) */ | |
148 | byte core_state; /* Core state machine (FS_*, see below) */ | |
149 | byte core_goal; /* State we want to reach (FS_*, see below) */ | |
150 | byte reconfiguring; /* We're shutting down due to reconfiguration */ | |
151 | byte refeeding; /* We are refeeding (valid only if core_state == FS_FEEDING) */ | |
152 | byte flushing; /* Protocol is flushed in current flush loop round */ | |
153 | byte down_sched; /* Shutdown is scheduled for later (PDS_*) */ | |
154 | byte down_code; /* Reason for shutdown (PDC_* codes) */ | |
7293c5dd | 155 | u32 hash_key; /* Random key used for hashing of neighbors */ |
9685deb9 | 156 | bird_clock_t last_state_change; /* Time of last state transition */ |
df9f0fb3 | 157 | char *last_state_name_announced; /* Last state name we've announced to the user */ |
925fe2d3 | 158 | struct proto_stats stats; /* Current protocol statistics */ |
58ef912c | 159 | |
9e0e485e MM |
160 | /* |
161 | * General protocol hooks: | |
162 | * | |
163 | * if_notify Notify protocol about interface state changes. | |
9a158361 | 164 | * ifa_notify Notify protocol about interface address changes. |
9e0e485e MM |
165 | * rt_notify Notify protocol about routing table updates. |
166 | * neigh_notify Notify protocol about neighbor cache events. | |
167 | * make_tmp_attrs Construct ea_list from private attrs stored in rte. | |
168 | * store_tmp_attrs Store private attrs back to the rte. | |
169 | * import_control Called as the first step of the route importing process. | |
170 | * It can construct a new rte, add private attributes and | |
171 | * decide whether the route shall be imported: 1=yes, -1=no, | |
172 | * 0=process it through the import filter set by the user. | |
bf47fe4b OZ |
173 | * reload_routes Request protocol to reload all its routes to the core |
174 | * (using rte_update()). Returns: 0=reload cannot be done, | |
175 | * 1= reload is scheduled and will happen (asynchronously). | |
9e0e485e MM |
176 | */ |
177 | ||
9a158361 MM |
178 | void (*if_notify)(struct proto *, unsigned flags, struct iface *i); |
179 | void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a); | |
dca75fd7 | 180 | void (*rt_notify)(struct proto *, struct rtable *table, struct network *net, struct rte *new, struct rte *old, struct ea_list *attrs); |
4cc78c50 | 181 | void (*neigh_notify)(struct neighbor *neigh); |
9e0e485e MM |
182 | struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool); |
183 | void (*store_tmp_attrs)(struct rte *rt, struct ea_list *attrs); | |
184 | int (*import_control)(struct proto *, struct rte **rt, struct ea_list **attrs, struct linpool *pool); | |
bf47fe4b | 185 | int (*reload_routes)(struct proto *); |
9e0e485e MM |
186 | |
187 | /* | |
188 | * Routing entry hooks (called only for rte's belonging to this protocol): | |
189 | * | |
be4cd99a | 190 | * rte_recalculate Called at the beginning of the best route selection |
9e0e485e | 191 | * rte_better Compare two rte's and decide which one is better (1=first, 0=second). |
67be5b23 | 192 | * rte_same Compare two rte's and decide whether they are identical (1=yes, 0=no). |
9e0e485e MM |
193 | * rte_insert Called whenever a rte is inserted to a routing table. |
194 | * rte_remove Called whenever a rte is removed from the routing table. | |
195 | */ | |
58ef912c | 196 | |
be4cd99a | 197 | int (*rte_recalculate)(struct rtable *, struct network *, struct rte *, struct rte *, struct rte *); |
2326b001 | 198 | int (*rte_better)(struct rte *, struct rte *); |
67be5b23 | 199 | int (*rte_same)(struct rte *, struct rte *); |
acc62f5e MM |
200 | void (*rte_insert)(struct network *, struct rte *); |
201 | void (*rte_remove)(struct network *, struct rte *); | |
2326b001 | 202 | |
0e02abfd | 203 | struct rtable *table; /* Our primary routing table */ |
c0adf7e9 | 204 | struct announce_hook *main_ahook; /* Primary announcement hook */ |
0e02abfd | 205 | struct announce_hook *ahooks; /* Announcement hooks for this protocol */ |
529c4149 | 206 | |
ac5d8012 MM |
207 | struct fib_iterator *feed_iterator; /* Routing table iterator used during protocol feeding */ |
208 | struct announce_hook *feed_ahook; /* Announce hook we currently feed */ | |
209 | ||
58ef912c MM |
210 | /* Hic sunt protocol-specific data */ |
211 | }; | |
212 | ||
e304fd4b OZ |
213 | struct proto_spec { |
214 | void *ptr; | |
215 | int patt; | |
216 | }; | |
217 | ||
218 | ||
ebecb6f6 OZ |
219 | #define PDS_DISABLE 1 /* Proto disable scheduled */ |
220 | #define PDS_RESTART 2 /* Proto restart scheduled */ | |
221 | ||
222 | #define PDC_CF_REMOVE 0x01 /* Removed in new config */ | |
223 | #define PDC_CF_DISABLE 0x02 /* Disabled in new config */ | |
224 | #define PDC_CF_RESTART 0x03 /* Restart due to reconfiguration */ | |
225 | #define PDC_CMD_DISABLE 0x11 /* Result of disable command */ | |
226 | #define PDC_CMD_RESTART 0x12 /* Result of restart command */ | |
5400c0e7 | 227 | #define PDC_CMD_SHUTDOWN 0x13 /* Result of global shutdown */ |
ebecb6f6 | 228 | #define PDC_IN_LIMIT_HIT 0x21 /* Route import limit reached */ |
5400c0e7 | 229 | #define PDC_OUT_LIMIT_HIT 0x22 /* Route export limit reached */ |
ebecb6f6 OZ |
230 | |
231 | ||
31b3e1bb | 232 | void *proto_new(struct proto_config *, unsigned size); |
a7f23f58 OZ |
233 | void *proto_config_new(struct protocol *, unsigned size, int class); |
234 | void proto_copy_config(struct proto_config *dest, struct proto_config *src); | |
bf47fe4b | 235 | void proto_request_feeding(struct proto *p); |
e304fd4b | 236 | |
a7f23f58 OZ |
237 | static inline void |
238 | proto_copy_rest(struct proto_config *dest, struct proto_config *src, unsigned size) | |
239 | { memcpy(dest + 1, src + 1, size - sizeof(struct proto_config)); } | |
240 | ||
c0adf7e9 | 241 | |
ebecb6f6 | 242 | void proto_show_limit(struct proto_limit *l, const char *dsc); |
c0adf7e9 OZ |
243 | void proto_show_basic_info(struct proto *p); |
244 | ||
e304fd4b OZ |
245 | void proto_cmd_show(struct proto *, unsigned int, int); |
246 | void proto_cmd_disable(struct proto *, unsigned int, int); | |
247 | void proto_cmd_enable(struct proto *, unsigned int, int); | |
248 | void proto_cmd_restart(struct proto *, unsigned int, int); | |
249 | void proto_cmd_reload(struct proto *, unsigned int, int); | |
250 | void proto_cmd_debug(struct proto *, unsigned int, int); | |
251 | void proto_cmd_mrtdump(struct proto *, unsigned int, int); | |
252 | ||
e0a45fb4 | 253 | void proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int), int restricted, unsigned int arg); |
02c1fbdd | 254 | struct proto *proto_get_named(struct symbol *, struct protocol *); |
e304fd4b OZ |
255 | |
256 | #define CMD_RELOAD 0 | |
257 | #define CMD_RELOAD_IN 1 | |
258 | #define CMD_RELOAD_OUT 2 | |
8a7fb885 | 259 | |
4cdd0784 OZ |
260 | static inline u32 |
261 | proto_get_router_id(struct proto_config *pc) | |
262 | { | |
263 | return pc->router_id ? pc->router_id : pc->global->router_id; | |
264 | } | |
265 | ||
f14a4bec | 266 | extern list active_proto_list; |
2326b001 | 267 | |
31b3e1bb MM |
268 | /* |
269 | * Each protocol instance runs two different state machines: | |
270 | * | |
271 | * [P] The protocol machine: (implemented inside protocol) | |
272 | * | |
273 | * DOWN ----> START | |
274 | * ^ | | |
275 | * | V | |
276 | * STOP <---- UP | |
277 | * | |
278 | * States: DOWN Protocol is down and it's waiting for the core | |
279 | * requesting protocol start. | |
280 | * START Protocol is waiting for connection with the rest | |
281 | * of the network and it's not willing to accept | |
282 | * packets. When it connects, it goes to UP state. | |
283 | * UP Protocol is up and running. When the network | |
284 | * connection breaks down or the core requests | |
285 | * protocol to be terminated, it goes to STOP state. | |
286 | * STOP Protocol is disconnecting from the network. | |
287 | * After it disconnects, it returns to DOWN state. | |
288 | * | |
289 | * In: start() Called in DOWN state to request protocol startup. | |
290 | * Returns new state: either UP or START (in this | |
291 | * case, the protocol will notify the core when it | |
292 | * finally comes UP). | |
293 | * stop() Called in START, UP or STOP state to request | |
294 | * protocol shutdown. Returns new state: either | |
295 | * DOWN or STOP (in this case, the protocol will | |
296 | * notify the core when it finally comes DOWN). | |
297 | * | |
298 | * Out: proto_notify_state() -- called by protocol instance when | |
299 | * it does any state transition not covered by | |
300 | * return values of start() and stop(). This includes | |
301 | * START->UP (delayed protocol startup), UP->STOP | |
302 | * (spontaneous shutdown) and STOP->DOWN (delayed | |
303 | * shutdown). | |
304 | */ | |
305 | ||
306 | #define PS_DOWN 0 | |
307 | #define PS_START 1 | |
308 | #define PS_UP 2 | |
309 | #define PS_STOP 3 | |
310 | ||
311 | void proto_notify_state(struct proto *p, unsigned state); | |
312 | ||
313 | /* | |
314 | * [F] The feeder machine: (implemented in core routines) | |
315 | * | |
316 | * HUNGRY ----> FEEDING | |
317 | * ^ | | |
318 | * | V | |
319 | * FLUSHING <---- HAPPY | |
320 | * | |
321 | * States: HUNGRY Protocol either administratively down (i.e., | |
322 | * disabled by the user) or temporarily down | |
323 | * (i.e., [P] is not UP) | |
324 | * FEEDING The protocol came up and we're feeding it | |
325 | * initial routes. [P] is UP. | |
326 | * HAPPY The protocol is up and it's receiving normal | |
327 | * routing updates. [P] is UP. | |
328 | * FLUSHING The protocol is down and we're removing its | |
329 | * routes from the table. [P] is STOP or DOWN. | |
330 | * | |
331 | * Normal lifecycle of a protocol looks like: | |
332 | * | |
333 | * HUNGRY/DOWN --> HUNGRY/START --> HUNGRY/UP --> | |
334 | * FEEDING/UP --> HAPPY/UP --> FLUSHING/STOP|DOWN --> | |
335 | * HUNGRY/STOP|DOWN --> HUNGRY/DOWN | |
bf47fe4b OZ |
336 | * |
337 | * Sometimes, protocol might switch from HAPPY/UP to FEEDING/UP | |
338 | * if it wants to refeed the routes (for example BGP does so | |
339 | * as a result of received ROUTE-REFRESH request). | |
31b3e1bb MM |
340 | */ |
341 | ||
342 | #define FS_HUNGRY 0 | |
343 | #define FS_FEEDING 1 | |
344 | #define FS_HAPPY 2 | |
345 | #define FS_FLUSHING 3 | |
346 | ||
96d8e3bf MM |
347 | /* |
348 | * Debugging flags | |
349 | */ | |
350 | ||
351 | #define D_STATES 1 /* [core] State transitions */ | |
352 | #define D_ROUTES 2 /* [core] Routes passed by the filters */ | |
6a9f28b0 MM |
353 | #define D_FILTERS 4 /* [core] Routes rejected by the filters */ |
354 | #define D_IFACES 8 /* [core] Interface events */ | |
355 | #define D_EVENTS 16 /* Protocol events */ | |
356 | #define D_PACKETS 32 /* Packets sent/received */ | |
96d8e3bf | 357 | |
cf31112f OZ |
358 | /* |
359 | * MRTDump flags | |
360 | */ | |
361 | ||
362 | #define MD_STATES 1 /* Protocol state changes (BGP4MP_MESSAGE_AS4) */ | |
363 | #define MD_MESSAGES 2 /* Protocol packets (BGP4MP_MESSAGE_AS4) */ | |
364 | ||
50d8424a MM |
365 | /* |
366 | * Known unique protocol instances as referenced by config routines | |
367 | */ | |
368 | ||
31b3e1bb | 369 | extern struct proto_config *cf_dev_proto; |
50d8424a | 370 | |
ebecb6f6 OZ |
371 | |
372 | /* | |
373 | * Protocol limits | |
374 | */ | |
375 | ||
376 | #define PLA_WARN 1 /* Issue log warning */ | |
377 | #define PLA_BLOCK 2 /* Block new routes */ | |
378 | #define PLA_RESTART 4 /* Force protocol restart */ | |
379 | #define PLA_DISABLE 5 /* Shutdown and disable protocol */ | |
380 | ||
7d0a31de OZ |
381 | #define PLS_INITIAL 0 /* Initial limit state after protocol start */ |
382 | #define PLS_ACTIVE 1 /* Limit was hit */ | |
383 | #define PLS_BLOCKED 2 /* Limit is active and blocking new routes */ | |
384 | ||
ebecb6f6 OZ |
385 | struct proto_limit { |
386 | u32 limit; /* Maximum number of prefixes */ | |
387 | byte action; /* Action to take (PLA_*) */ | |
7d0a31de | 388 | byte state; /* State of limit (PLS_*) */ |
ebecb6f6 OZ |
389 | }; |
390 | ||
7d0a31de OZ |
391 | void proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count); |
392 | ||
ab758e4f OZ |
393 | static inline void |
394 | proto_reset_limit(struct proto_limit *l) | |
7d0a31de OZ |
395 | { |
396 | if (l) | |
397 | l->state = PLS_INITIAL; | |
398 | } | |
399 | ||
ebecb6f6 | 400 | |
0e02abfd MM |
401 | /* |
402 | * Route Announcement Hook | |
403 | */ | |
404 | ||
405 | struct announce_hook { | |
406 | node n; | |
407 | struct rtable *table; | |
408 | struct proto *proto; | |
c0adf7e9 OZ |
409 | struct filter *in_filter; /* Input filter */ |
410 | struct filter *out_filter; /* Output filter */ | |
ebecb6f6 | 411 | struct proto_limit *in_limit; /* Input limit */ |
d9b77cc2 | 412 | struct proto_limit *out_limit; /* Output limit */ |
c0adf7e9 | 413 | struct proto_stats *stats; /* Per-table protocol statistics */ |
0e02abfd | 414 | struct announce_hook *next; /* Next hook for the same protocol */ |
15550957 | 415 | int in_keep_filtered; /* Routes rejected in import filter are kept */ |
0e02abfd MM |
416 | }; |
417 | ||
ebecb6f6 | 418 | struct announce_hook *proto_add_announce_hook(struct proto *p, struct rtable *t, struct proto_stats *stats); |
c0adf7e9 | 419 | struct announce_hook *proto_find_announce_hook(struct proto *p, struct rtable *t); |
c8387626 | 420 | |
58ef912c | 421 | #endif |