blob: 3608ebaca3e0db3e10a3cf8d0465fa20e0583666 [file] [log] [blame]
paul2d33f152003-03-17 01:10:58 +00001/*
paulf894c3a2003-04-09 07:26:33 +00002 * Simple program to demonstrate how OSPF API can be used. This
3 * application retrieves the LSDB from the OSPF daemon and then
4 * originates, updates and finally deletes an application-specific
5 * opaque LSA. You can use this application as a template when writing
6 * your own application.
paul2d33f152003-03-17 01:10:58 +00007 */
8
9/* The following includes are needed in all OSPF API client
paulf894c3a2003-04-09 07:26:33 +000010 applications. */
paul2d33f152003-03-17 01:10:58 +000011
12#include <zebra.h>
paulf894c3a2003-04-09 07:26:33 +000013#include "prefix.h" /* needed by ospf_asbr.h */
pauledd7c242003-06-04 13:59:38 +000014#include "privs.h"
Tomasz Pala3fc1eca2009-06-24 21:48:22 +010015#include "log.h"
pauledd7c242003-06-04 13:59:38 +000016
paul2d33f152003-03-17 01:10:58 +000017#include "ospfd/ospfd.h"
18#include "ospfd/ospf_asbr.h"
19#include "ospfd/ospf_lsa.h"
20#include "ospfd/ospf_opaque.h"
paul2d33f152003-03-17 01:10:58 +000021#include "ospfd/ospf_api.h"
22#include "ospf_apiclient.h"
23
pauledd7c242003-06-04 13:59:38 +000024/* privileges struct.
25 * set cap_num_* and uid/gid to nothing to use NULL privs
26 * as ospfapiclient links in libospf.a which uses privs.
27 */
28struct zebra_privs_t ospfd_privs =
29{
30 .user = NULL,
31 .group = NULL,
32 .cap_num_p = 0,
33 .cap_num_i = 0
34};
35
paulf894c3a2003-04-09 07:26:33 +000036/* The following includes are specific to this application. For
37 example it uses threads from libzebra, however your application is
38 free to use any thread library (like pthreads). */
paul2d33f152003-03-17 01:10:58 +000039
paulf894c3a2003-04-09 07:26:33 +000040#include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
paul2d33f152003-03-17 01:10:58 +000041#include "thread.h"
42#include "log.h"
43
paulf894c3a2003-04-09 07:26:33 +000044/* Local portnumber for async channel. Note that OSPF API library will also
45 allocate a sync channel at ASYNCPORT+1. */
paul2d33f152003-03-17 01:10:58 +000046#define ASYNCPORT 4000
47
48/* Master thread */
49struct thread_master *master;
50
51/* Global variables */
52struct ospf_apiclient *oclient;
53char **args;
54
paulf894c3a2003-04-09 07:26:33 +000055/* Our opaque LSAs have the following format. */
paul2d33f152003-03-17 01:10:58 +000056struct my_opaque_lsa
57{
paulf894c3a2003-04-09 07:26:33 +000058 struct lsa_header hdr; /* include common LSA header */
59 u_char data[4]; /* our own data format then follows here */
paul2d33f152003-03-17 01:10:58 +000060};
61
62
63/* ---------------------------------------------------------
64 * Threads for asynchronous messages and LSA update/delete
65 * ---------------------------------------------------------
66 */
67
paula0ace1e2005-11-24 12:40:39 +000068static int
paul2d33f152003-03-17 01:10:58 +000069lsa_delete (struct thread *t)
70{
71 struct ospf_apiclient *oclient;
72 struct in_addr area_id;
73 int rc;
74
75 oclient = THREAD_ARG (t);
76
77 inet_aton (args[6], &area_id);
78
79 printf ("Deleting LSA... ");
80 rc = ospf_apiclient_lsa_delete (oclient,
81 area_id,
82 atoi (args[2]), /* lsa type */
83 atoi (args[3]), /* opaque type */
84 atoi (args[4])); /* opaque ID */
85 printf ("done, return code is = %d\n", rc);
86 return rc;
87}
88
paula0ace1e2005-11-24 12:40:39 +000089static int
paul2d33f152003-03-17 01:10:58 +000090lsa_inject (struct thread *t)
91{
92 struct ospf_apiclient *cl;
93 struct in_addr ifaddr;
94 struct in_addr area_id;
95 u_char lsa_type;
96 u_char opaque_type;
97 u_int32_t opaque_id;
98 void *opaquedata;
99 int opaquelen;
100
paulf894c3a2003-04-09 07:26:33 +0000101 static u_int32_t counter = 1; /* Incremented each time invoked */
paul2d33f152003-03-17 01:10:58 +0000102 int rc;
103
104 cl = THREAD_ARG (t);
105
106 inet_aton (args[5], &ifaddr);
107 inet_aton (args[6], &area_id);
108 lsa_type = atoi (args[2]);
109 opaque_type = atoi (args[3]);
110 opaque_id = atoi (args[4]);
111 opaquedata = &counter;
112 opaquelen = sizeof (u_int32_t);
113
114 printf ("Originating/updating LSA with counter=%d... ", counter);
115 rc = ospf_apiclient_lsa_originate(cl, ifaddr, area_id,
116 lsa_type,
117 opaque_type, opaque_id,
118 opaquedata, opaquelen);
119
120 printf ("done, return code is %d\n", rc);
121
122 counter++;
123
124 return 0;
Paul Jakma30a22312008-08-15 14:05:22 +0100125}
paul2d33f152003-03-17 01:10:58 +0000126
127
128/* This thread handles asynchronous messages coming in from the OSPF
129 API server */
paula0ace1e2005-11-24 12:40:39 +0000130static int
paul2d33f152003-03-17 01:10:58 +0000131lsa_read (struct thread *thread)
132{
133 struct ospf_apiclient *oclient;
134 int fd;
135 int ret;
136
137 printf ("lsa_read called\n");
138
139 oclient = THREAD_ARG (thread);
140 fd = THREAD_FD (thread);
141
142 /* Handle asynchronous message */
143 ret = ospf_apiclient_handle_async (oclient);
144 if (ret < 0) {
145 printf ("Connection closed, exiting...");
146 exit(0);
147 }
148
149 /* Reschedule read thread */
150 thread_add_read (master, lsa_read, oclient, fd);
151
152 return 0;
153}
154
paul2d33f152003-03-17 01:10:58 +0000155/* ---------------------------------------------------------
156 * Callback functions for asynchronous events
157 * ---------------------------------------------------------
158 */
159
paula0ace1e2005-11-24 12:40:39 +0000160static void
paul2d33f152003-03-17 01:10:58 +0000161lsa_update_callback (struct in_addr ifaddr, struct in_addr area_id,
162 u_char is_self_originated,
163 struct lsa_header *lsa)
164{
165 printf ("lsa_update_callback: ");
166 printf ("ifaddr: %s ", inet_ntoa (ifaddr));
167 printf ("area: %s\n", inet_ntoa (area_id));
168 printf ("is_self_origin: %u\n", is_self_originated);
169
paulf894c3a2003-04-09 07:26:33 +0000170 /* It is important to note that lsa_header does indeed include the
171 header and the LSA payload. To access the payload, first check
172 the LSA type and then typecast lsa into the corresponding type,
173 e.g.:
174
175 if (lsa->type == OSPF_ROUTER_LSA) {
176 struct router_lsa *rl = (struct router_lsa) lsa;
177 ...
178 u_int16_t links = rl->links;
179 ...
180 }
181 */
182
paul2d33f152003-03-17 01:10:58 +0000183 ospf_lsa_header_dump (lsa);
184}
185
paula0ace1e2005-11-24 12:40:39 +0000186static void
paul2d33f152003-03-17 01:10:58 +0000187lsa_delete_callback (struct in_addr ifaddr, struct in_addr area_id,
188 u_char is_self_originated,
189 struct lsa_header *lsa)
190{
191 printf ("lsa_delete_callback: ");
192 printf ("ifaddr: %s ", inet_ntoa (ifaddr));
193 printf ("area: %s\n", inet_ntoa (area_id));
194 printf ("is_self_origin: %u\n", is_self_originated);
195
196 ospf_lsa_header_dump (lsa);
197}
198
paula0ace1e2005-11-24 12:40:39 +0000199static void
paul2d33f152003-03-17 01:10:58 +0000200ready_callback (u_char lsa_type, u_char opaque_type, struct in_addr addr)
201{
202 printf ("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
203 lsa_type, opaque_type, inet_ntoa (addr));
204
205 /* Schedule opaque LSA originate in 5 secs */
206 thread_add_timer (master, lsa_inject, oclient, 5);
207
208 /* Schedule opaque LSA update with new value */
209 thread_add_timer (master, lsa_inject, oclient, 10);
210
211 /* Schedule delete */
212 thread_add_timer (master, lsa_delete, oclient, 30);
213}
214
paula0ace1e2005-11-24 12:40:39 +0000215static void
paul2d33f152003-03-17 01:10:58 +0000216new_if_callback (struct in_addr ifaddr, struct in_addr area_id)
217{
218 printf ("new_if_callback: ifaddr: %s ", inet_ntoa (ifaddr));
219 printf ("area_id: %s\n", inet_ntoa (area_id));
220}
221
paula0ace1e2005-11-24 12:40:39 +0000222static void
paul2d33f152003-03-17 01:10:58 +0000223del_if_callback (struct in_addr ifaddr)
224{
225 printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
226}
227
paula0ace1e2005-11-24 12:40:39 +0000228static void
paul2d33f152003-03-17 01:10:58 +0000229ism_change_callback (struct in_addr ifaddr, struct in_addr area_id,
230 u_char state)
231{
232 printf ("ism_change: ifaddr: %s ", inet_ntoa (ifaddr));
233 printf ("area_id: %s\n", inet_ntoa (area_id));
234 printf ("state: %d [%s]\n", state, LOOKUP (ospf_ism_state_msg, state));
235}
236
paula0ace1e2005-11-24 12:40:39 +0000237static void
paul2d33f152003-03-17 01:10:58 +0000238nsm_change_callback (struct in_addr ifaddr, struct in_addr nbraddr,
239 struct in_addr router_id, u_char state)
240{
241 printf ("nsm_change: ifaddr: %s ", inet_ntoa (ifaddr));
242 printf ("nbraddr: %s\n", inet_ntoa (nbraddr));
243 printf ("router_id: %s\n", inet_ntoa (router_id));
244 printf ("state: %d [%s]\n", state, LOOKUP (ospf_nsm_state_msg, state));
245}
246
247
248/* ---------------------------------------------------------
249 * Main program
250 * ---------------------------------------------------------
251 */
252
paula0ace1e2005-11-24 12:40:39 +0000253static int usage()
paulf894c3a2003-04-09 07:26:33 +0000254{
255 printf("Usage: ospfclient <ospfd> <lsatype> <opaquetype> <opaqueid> <ifaddr> <areaid>\n");
256 printf("where ospfd : router where API-enabled OSPF daemon is running\n");
257 printf(" lsatype : either 9, 10, or 11 depending on flooding scope\n");
258 printf(" opaquetype: 0-255 (e.g., experimental applications use > 128)\n");
259 printf(" opaqueid : arbitrary application instance (24 bits)\n");
260 printf(" ifaddr : interface IP address (for type 9) otherwise ignored\n");
261 printf(" areaid : area in IP address format (for type 10) otherwise ignored\n");
262
263 exit(1);
264}
265
paul2d33f152003-03-17 01:10:58 +0000266int
267main (int argc, char *argv[])
268{
269 struct thread thread;
270
271 args = argv;
272
paulf894c3a2003-04-09 07:26:33 +0000273 /* ospfclient should be started with the following arguments:
paul2d33f152003-03-17 01:10:58 +0000274 *
275 * (1) host (2) lsa_type (3) opaque_type (4) opaque_id (5) if_addr
276 * (6) area_id
277 *
278 * host: name or IP of host where ospfd is running
279 * lsa_type: 9, 10, or 11
paulf894c3a2003-04-09 07:26:33 +0000280 * opaque_type: 0-255 (e.g., experimental applications use > 128)
paul2d33f152003-03-17 01:10:58 +0000281 * opaque_id: arbitrary application instance (24 bits)
282 * if_addr: interface IP address (for type 9) otherwise ignored
283 * area_id: area in IP address format (for type 10) otherwise ignored
284 */
285
286 if (argc != 7)
287 {
paulf894c3a2003-04-09 07:26:33 +0000288 usage();
paul2d33f152003-03-17 01:10:58 +0000289 }
290
291 /* Initialization */
pauledd7c242003-06-04 13:59:38 +0000292 zprivs_init (&ospfd_privs);
paul2d33f152003-03-17 01:10:58 +0000293 master = thread_master_create ();
294
295 /* Open connection to OSPF daemon */
296 oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
297 if (!oclient)
298 {
paulf894c3a2003-04-09 07:26:33 +0000299 printf ("Connecting to OSPF daemon on %s failed!\n",
300 args[1]);
paul2d33f152003-03-17 01:10:58 +0000301 exit (1);
302 }
303
304 /* Register callback functions. */
305 ospf_apiclient_register_callback (oclient,
306 ready_callback,
307 new_if_callback,
308 del_if_callback,
309 ism_change_callback,
310 nsm_change_callback,
311 lsa_update_callback,
312 lsa_delete_callback);
313
314 /* Register LSA type and opaque type. */
315 ospf_apiclient_register_opaque_type (oclient, atoi (args[2]),
316 atoi (args[3]));
317
318 /* Synchronize database with OSPF daemon. */
319 ospf_apiclient_sync_lsdb (oclient);
320
321 /* Schedule thread that handles asynchronous messages */
322 thread_add_read (master, lsa_read, oclient, oclient->fd_async);
323
324 /* Now connection is established, run loop */
325 while (1)
326 {
327 thread_fetch (master, &thread);
328 thread_call (&thread);
329 }
330
331 /* Never reached */
332 return 0;
333}
334