]> git.proxmox.com Git - mirror_frr.git/blob - ospfclient/ospfclient.c
Merge remote branch 'origin/master'
[mirror_frr.git] / ospfclient / ospfclient.c
1 /*
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.
7 */
8
9 /* The following includes are needed in all OSPF API client
10 applications. */
11
12 #include <zebra.h>
13 #include "prefix.h" /* needed by ospf_asbr.h */
14 #include "privs.h"
15 #include "log.h"
16
17 #include "ospfd/ospfd.h"
18 #include "ospfd/ospf_asbr.h"
19 #include "ospfd/ospf_lsa.h"
20 #include "ospfd/ospf_opaque.h"
21 #include "ospfd/ospf_api.h"
22 #include "ospf_apiclient.h"
23
24 /* 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 */
28 struct zebra_privs_t ospfd_privs =
29 {
30 .user = NULL,
31 .group = NULL,
32 .cap_num_p = 0,
33 .cap_num_i = 0
34 };
35
36 /* 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). */
39
40 #include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
41 #include "thread.h"
42 #include "log.h"
43
44 /* Local portnumber for async channel. Note that OSPF API library will also
45 allocate a sync channel at ASYNCPORT+1. */
46 #define ASYNCPORT 4000
47
48 /* Master thread */
49 struct thread_master *master;
50
51 /* Global variables */
52 struct ospf_apiclient *oclient;
53 char **args;
54
55 /* Our opaque LSAs have the following format. */
56 struct my_opaque_lsa
57 {
58 struct lsa_header hdr; /* include common LSA header */
59 u_char data[4]; /* our own data format then follows here */
60 };
61
62
63 /* ---------------------------------------------------------
64 * Threads for asynchronous messages and LSA update/delete
65 * ---------------------------------------------------------
66 */
67
68 static int
69 lsa_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
89 static int
90 lsa_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
101 static u_int32_t counter = 1; /* Incremented each time invoked */
102 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;
125 }
126
127
128 /* This thread handles asynchronous messages coming in from the OSPF
129 API server */
130 static int
131 lsa_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
155 /* ---------------------------------------------------------
156 * Callback functions for asynchronous events
157 * ---------------------------------------------------------
158 */
159
160 static void
161 lsa_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
170 /* 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
183 ospf_lsa_header_dump (lsa);
184 }
185
186 static void
187 lsa_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
199 static void
200 ready_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
215 static void
216 new_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
222 static void
223 del_if_callback (struct in_addr ifaddr)
224 {
225 printf ("new_if_callback: ifaddr: %s\n ", inet_ntoa (ifaddr));
226 }
227
228 static void
229 ism_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
237 static void
238 nsm_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
253 static int usage()
254 {
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
266 int
267 main (int argc, char *argv[])
268 {
269 struct thread thread;
270
271 args = argv;
272
273 /* ospfclient should be started with the following arguments:
274 *
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
280 * opaque_type: 0-255 (e.g., experimental applications use > 128)
281 * 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 {
288 usage();
289 }
290
291 /* Initialization */
292 zprivs_init (&ospfd_privs);
293 master = thread_master_create ();
294
295 /* Open connection to OSPF daemon */
296 oclient = ospf_apiclient_connect (args[1], ASYNCPORT);
297 if (!oclient)
298 {
299 printf ("Connecting to OSPF daemon on %s failed!\n",
300 args[1]);
301 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