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