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