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