blob: 1de7644f6a3b391d0c522b405a249d6d9df129c0 [file] [log] [blame]
Paul Jakma010ebbb2014-09-16 11:53:49 +01001/* 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
paul2d33f152003-03-17 01:10:58 +000019/*
paulf894c3a2003-04-09 07:26:33 +000020 * 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.
paul2d33f152003-03-17 01:10:58 +000025 */
26
27/* The following includes are needed in all OSPF API client
paulf894c3a2003-04-09 07:26:33 +000028 applications. */
paul2d33f152003-03-17 01:10:58 +000029
30#include <zebra.h>
paulf894c3a2003-04-09 07:26:33 +000031#include "prefix.h" /* needed by ospf_asbr.h */
pauledd7c242003-06-04 13:59:38 +000032#include "privs.h"
Tomasz Pala3fc1eca2009-06-24 21:48:22 +010033#include "log.h"
pauledd7c242003-06-04 13:59:38 +000034
paul2d33f152003-03-17 01:10:58 +000035#include "ospfd/ospfd.h"
36#include "ospfd/ospf_asbr.h"
37#include "ospfd/ospf_lsa.h"
38#include "ospfd/ospf_opaque.h"
paul2d33f152003-03-17 01:10:58 +000039#include "ospfd/ospf_api.h"
40#include "ospf_apiclient.h"
41
pauledd7c242003-06-04 13:59:38 +000042/* 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 */
46struct zebra_privs_t ospfd_privs =
47{
48 .user = NULL,
49 .group = NULL,
50 .cap_num_p = 0,
51 .cap_num_i = 0
52};
53
paulf894c3a2003-04-09 07:26:33 +000054/* 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). */
paul2d33f152003-03-17 01:10:58 +000057
paulf894c3a2003-04-09 07:26:33 +000058#include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
paul2d33f152003-03-17 01:10:58 +000059#include "thread.h"
60#include "log.h"
61
paulf894c3a2003-04-09 07:26:33 +000062/* Local portnumber for async channel. Note that OSPF API library will also
63 allocate a sync channel at ASYNCPORT+1. */
paul2d33f152003-03-17 01:10:58 +000064#define ASYNCPORT 4000
65
66/* Master thread */
67struct thread_master *master;
68
69/* Global variables */
70struct ospf_apiclient *oclient;
71char **args;
72
paulf894c3a2003-04-09 07:26:33 +000073/* Our opaque LSAs have the following format. */
paul2d33f152003-03-17 01:10:58 +000074struct my_opaque_lsa
75{
paulf894c3a2003-04-09 07:26:33 +000076 struct lsa_header hdr; /* include common LSA header */
77 u_char data[4]; /* our own data format then follows here */
paul2d33f152003-03-17 01:10:58 +000078};
79
80
81/* ---------------------------------------------------------
82 * Threads for asynchronous messages and LSA update/delete
83 * ---------------------------------------------------------
84 */
85
paula0ace1e2005-11-24 12:40:39 +000086static int
paul2d33f152003-03-17 01:10:58 +000087lsa_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
paula0ace1e2005-11-24 12:40:39 +0000107static int
paul2d33f152003-03-17 01:10:58 +0000108lsa_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
paulf894c3a2003-04-09 07:26:33 +0000119 static u_int32_t counter = 1; /* Incremented each time invoked */
paul2d33f152003-03-17 01:10:58 +0000120 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;
Paul Jakma30a22312008-08-15 14:05:22 +0100143}
paul2d33f152003-03-17 01:10:58 +0000144
145
146/* This thread handles asynchronous messages coming in from the OSPF
147 API server */
paula0ace1e2005-11-24 12:40:39 +0000148static int
paul2d33f152003-03-17 01:10:58 +0000149lsa_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
paul2d33f152003-03-17 01:10:58 +0000173/* ---------------------------------------------------------
174 * Callback functions for asynchronous events
175 * ---------------------------------------------------------
176 */
177
paula0ace1e2005-11-24 12:40:39 +0000178static void
paul2d33f152003-03-17 01:10:58 +0000179lsa_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
paulf894c3a2003-04-09 07:26:33 +0000188 /* 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
paul2d33f152003-03-17 01:10:58 +0000201 ospf_lsa_header_dump (lsa);
202}
203
paula0ace1e2005-11-24 12:40:39 +0000204static void
paul2d33f152003-03-17 01:10:58 +0000205lsa_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
paula0ace1e2005-11-24 12:40:39 +0000217static void
paul2d33f152003-03-17 01:10:58 +0000218ready_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
paula0ace1e2005-11-24 12:40:39 +0000233static void
paul2d33f152003-03-17 01:10:58 +0000234new_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
paula0ace1e2005-11-24 12:40:39 +0000240static void
paul2d33f152003-03-17 01:10:58 +0000241del_if_callback (struct in_addr ifaddr)
242{
243 printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
244}
245
paula0ace1e2005-11-24 12:40:39 +0000246static void
paul2d33f152003-03-17 01:10:58 +0000247ism_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
paula0ace1e2005-11-24 12:40:39 +0000255static void
paul2d33f152003-03-17 01:10:58 +0000256nsm_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
paula0ace1e2005-11-24 12:40:39 +0000271static int usage()
paulf894c3a2003-04-09 07:26:33 +0000272{
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
paul2d33f152003-03-17 01:10:58 +0000284int
285main (int argc, char *argv[])
286{
287 struct thread thread;
288
289 args = argv;
290
paulf894c3a2003-04-09 07:26:33 +0000291 /* ospfclient should be started with the following arguments:
paul2d33f152003-03-17 01:10:58 +0000292 *
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
paulf894c3a2003-04-09 07:26:33 +0000298 * opaque_type: 0-255 (e.g., experimental applications use > 128)
paul2d33f152003-03-17 01:10:58 +0000299 * 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 {
paulf894c3a2003-04-09 07:26:33 +0000306 usage();
paul2d33f152003-03-17 01:10:58 +0000307 }
308
309 /* Initialization */
pauledd7c242003-06-04 13:59:38 +0000310 zprivs_init (&ospfd_privs);
paul2d33f152003-03-17 01:10:58 +0000311 master = thread_master_create ();
312
313 /* Open connection to OSPF daemon */
314 oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
315 if (!oclient)
316 {
paulf894c3a2003-04-09 07:26:33 +0000317 printf ("Connecting to OSPF daemon on %s failed!\n",
318 args[1]);
paul2d33f152003-03-17 01:10:58 +0000319 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