]> git.proxmox.com Git - mirror_frr.git/blob - ospfclient/ospfclient.c
Merge remote-tracking branch 'origin/stable/2.0'
[mirror_frr.git] / ospfclient / ospfclient.c
1 /* This file is part of Quagga.
2 *
3 * Quagga is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by the
5 * Free Software Foundation; either version 2, or (at your option) any
6 * later version.
7 *
8 * Quagga is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; see the file COPYING; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 /*
19 * Simple program to demonstrate how OSPF API can be used. This
20 * application retrieves the LSDB from the OSPF daemon and then
21 * originates, updates and finally deletes an application-specific
22 * opaque LSA. You can use this application as a template when writing
23 * your own application.
24 */
25
26 /* The following includes are needed in all OSPF API client
27 applications. */
28
29 #include <zebra.h>
30 #include "prefix.h" /* needed by ospf_asbr.h */
31 #include "privs.h"
32 #include "log.h"
33
34 /* work around gcc bug 69981, disable MTYPEs in libospf */
35 #define _QUAGGA_OSPF_MEMORY_H
36
37 #include "ospfd/ospfd.h"
38 #include "ospfd/ospf_asbr.h"
39 #include "ospfd/ospf_lsa.h"
40 #include "ospfd/ospf_opaque.h"
41 #include "ospfd/ospf_api.h"
42 #include "ospf_apiclient.h"
43
44 /* privileges struct.
45 * set cap_num_* and uid/gid to nothing to use NULL privs
46 * as ospfapiclient links in libospf.a which uses privs.
47 */
48 struct zebra_privs_t ospfd_privs =
49 {
50 .user = NULL,
51 .group = NULL,
52 .cap_num_p = 0,
53 .cap_num_i = 0
54 };
55
56 /* The following includes are specific to this application. For
57 example it uses threads from libfrr, however your application is
58 free to use any thread library (like pthreads). */
59
60 #include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
61 #include "thread.h"
62 #include "log.h"
63
64 /* Local portnumber for async channel. Note that OSPF API library will also
65 allocate a sync channel at ASYNCPORT+1. */
66 #define ASYNCPORT 4000
67
68 /* Master thread */
69 struct thread_master *master;
70
71 /* Global variables */
72 struct ospf_apiclient *oclient;
73 char **args;
74
75 /* Our opaque LSAs have the following format. */
76 struct my_opaque_lsa
77 {
78 struct lsa_header hdr; /* include common LSA header */
79 u_char data[4]; /* our own data format then follows here */
80 };
81
82
83 /* ---------------------------------------------------------
84 * Threads for asynchronous messages and LSA update/delete
85 * ---------------------------------------------------------
86 */
87
88 static int
89 lsa_delete (struct thread *t)
90 {
91 struct ospf_apiclient *oclient;
92 struct in_addr area_id;
93 int rc;
94
95 oclient = THREAD_ARG (t);
96
97 inet_aton (args[6], &area_id);
98
99 printf ("Deleting LSA... ");
100 rc = ospf_apiclient_lsa_delete (oclient,
101 area_id,
102 atoi (args[2]), /* lsa type */
103 atoi (args[3]), /* opaque type */
104 atoi (args[4])); /* opaque ID */
105 printf ("done, return code is = %d\n", rc);
106 return rc;
107 }
108
109 static int
110 lsa_inject (struct thread *t)
111 {
112 struct ospf_apiclient *cl;
113 struct in_addr ifaddr;
114 struct in_addr area_id;
115 u_char lsa_type;
116 u_char opaque_type;
117 u_int32_t opaque_id;
118 void *opaquedata;
119 int opaquelen;
120
121 static u_int32_t counter = 1; /* Incremented each time invoked */
122 int rc;
123
124 cl = THREAD_ARG (t);
125
126 inet_aton (args[5], &ifaddr);
127 inet_aton (args[6], &area_id);
128 lsa_type = atoi (args[2]);
129 opaque_type = atoi (args[3]);
130 opaque_id = atoi (args[4]);
131 opaquedata = &counter;
132 opaquelen = sizeof (u_int32_t);
133
134 printf ("Originating/updating LSA with counter=%d... ", counter);
135 rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id,
136 lsa_type,
137 opaque_type, opaque_id,
138 opaquedata, opaquelen);
139
140 printf ("done, return code is %d\n", rc);
141
142 counter++;
143
144 return 0;
145 }
146
147
148 /* This thread handles asynchronous messages coming in from the OSPF
149 API server */
150 static int
151 lsa_read (struct thread *thread)
152 {
153 struct ospf_apiclient *oclient;
154 int fd;
155 int ret;
156
157 printf ("lsa_read called\n");
158
159 oclient = THREAD_ARG (thread);
160 fd = THREAD_FD (thread);
161
162 /* Handle asynchronous message */
163 ret = ospf_apiclient_handle_async (oclient);
164 if (ret < 0) {
165 printf ("Connection closed, exiting...");
166 exit(0);
167 }
168
169 /* Reschedule read thread */
170 thread_add_read(master, lsa_read, oclient, fd, NULL);
171
172 return 0;
173 }
174
175 /* ---------------------------------------------------------
176 * Callback functions for asynchronous events
177 * ---------------------------------------------------------
178 */
179
180 static void
181 lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id,
182 u_char is_self_originated,
183 struct lsa_header *lsa)
184 {
185 printf ("lsa_update_callback: ");
186 printf ("ifaddr: %s ", inet_ntoa (ifaddr));
187 printf ("area: %s\n", inet_ntoa (area_id));
188 printf ("is_self_origin: %u\n", is_self_originated);
189
190 /* It is important to note that lsa_header does indeed include the
191 header and the LSA payload. To access the payload, first check
192 the LSA type and then typecast lsa into the corresponding type,
193 e.g.:
194
195 if (lsa->type == OSPF_ROUTER_LSA) {
196 struct router_lsa *rl = (struct router_lsa) lsa;
197 ...
198 u_int16_t links = rl->links;
199 ...
200 }
201 */
202
203 ospf_lsa_header_dump (lsa);
204 }
205
206 static void
207 lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id,
208 u_char is_self_originated,
209 struct lsa_header *lsa)
210 {
211 printf ("lsa_delete_callback: ");
212 printf ("ifaddr: %s ", inet_ntoa (ifaddr));
213 printf ("area: %s\n", inet_ntoa (area_id));
214 printf ("is_self_origin: %u\n", is_self_originated);
215
216 ospf_lsa_header_dump (lsa);
217 }
218
219 static void
220 ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr)
221 {
222 printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
223 lsa_type, opaque_type, inet_ntoa (addr));
224
225 /* Schedule opaque LSA originate in 5 secs */
226 thread_add_timer(master, lsa_inject, oclient, 5, NULL);
227
228 /* Schedule opaque LSA update with new value */
229 thread_add_timer(master, lsa_inject, oclient, 10, NULL);
230
231 /* Schedule delete */
232 thread_add_timer(master, lsa_delete, oclient, 30, NULL);
233 }
234
235 static void
236 new_if_callback (struct in_addr ifaddr, struct in_addr area_id)
237 {
238 printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr));
239 printf ("area_id: %s\n", inet_ntoa (area_id));
240 }
241
242 static void
243 del_if_callback (struct in_addr ifaddr)
244 {
245 printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
246 }
247
248 static void
249 ism_change_callback (struct in_addr ifaddr, struct in_addr area_id,
250 u_char state)
251 {
252 printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr));
253 printf ("area_id: %s\n", inet_ntoa (area_id));
254 printf ("state: %d [%s]\n", state, LOOKUP (ospf_ism_state_msg, state));
255 }
256
257 static void
258 nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr,
259 struct in_addr router_id, u_char state)
260 {
261 printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr));
262 printf ("nbraddr: %s\n", inet_ntoa (nbraddr));
263 printf ("router_id: %s\n", inet_ntoa (router_id));
264 printf ("state: %d [%s]\n", state, LOOKUP (ospf_nsm_state_msg, state));
265 }
266
267
268 /* ---------------------------------------------------------
269 * Main program
270 * ---------------------------------------------------------
271 */
272
273 static int usage(void)
274 {
275 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
276 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
277 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
278 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
279 printf(" opaqueid : arbitrary application instance (24 bits)\n");
280 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
281 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
282
283 exit(1);
284 }
285
286 int
287 main (int argc, char *argv[])
288 {
289 struct thread thread;
290
291 args = argv;
292
293 /* ospfclient should be started with the following arguments:
294 *
295 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
296 * (6) area_id
297 *
298 * host: name or IP of host where ospfd is running
299 * lsa_type: 9, 10, or 11
300 * opaque_type: 0-255 (e.g., experimental applications use > 128)
301 * opaque_id: arbitrary application instance (24 bits)
302 * if_addr: interface IP address (for type 9) otherwise ignored
303 * area_id: area in IP address format (for type 10) otherwise ignored
304 */
305
306 if (argc != 7)
307 {
308 usage();
309 }
310
311 /* Initialization */
312 zprivs_init (&ospfd_privs);
313 master = thread_master_create ();
314
315 /* Open connection to OSPF daemon */
316 oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
317 if (!oclient)
318 {
319 printf ("Connecting to OSPF daemon on %s failed!\n",
320 args[1]);
321 exit (1);
322 }
323
324 /* Register callback functions. */
325 ospf_apiclient_register_callback (oclient,
326 ready_callback,
327 new_if_callback,
328 del_if_callback,
329 ism_change_callback,
330 nsm_change_callback,
331 lsa_update_callback,
332 lsa_delete_callback);
333
334 /* Register LSA type and opaque type. */
335 ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
336 atoi (args[3]));
337
338 /* Synchronize database with OSPF daemon. */
339 ospf_apiclient_sync_lsdb (oclient);
340
341 /* Schedule thread that handles asynchronous messages */
342 thread_add_read(master, lsa_read, oclient, oclient->fd_async, NULL);
343
344 /* Now connection is established, run loop */
345 while (1)
346 {
347 thread_fetch (master, &thread);
348 thread_call (&thread);
349 }
350
351 /* Never reached */
352 return 0;
353 }
354