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