]> git.proxmox.com Git - mirror_frr.git/blame - ospfclient/ospfclient.c
build: add --enable-static-bin option
[mirror_frr.git] / ospfclient / ospfclient.c
CommitLineData
46f4a4d2
PJ
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 *
896014f4
DL
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
46f4a4d2
PJ
16 */
17
d62a17ae 18/*
f894c3ad 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.
2d33f157 24 */
25
26/* The following includes are needed in all OSPF API client
f894c3ad 27 applications. */
2d33f157 28
29#include <zebra.h>
f894c3ad 30#include "prefix.h" /* needed by ospf_asbr.h */
edd7c245 31#include "privs.h"
3fc1eca9 32#include "log.h"
edd7c245 33
5c088023
DL
34/* work around gcc bug 69981, disable MTYPEs in libospf */
35#define _QUAGGA_OSPF_MEMORY_H
36
2d33f157 37#include "ospfd/ospfd.h"
38#include "ospfd/ospf_asbr.h"
39#include "ospfd/ospf_lsa.h"
40#include "ospfd/ospf_opaque.h"
2d33f157 41#include "ospfd/ospf_api.h"
42#include "ospf_apiclient.h"
43
d62a17ae 44/* privileges struct.
edd7c245 45 * set cap_num_* and uid/gid to nothing to use NULL privs
46 * as ospfapiclient links in libospf.a which uses privs.
47 */
d62a17ae 48struct zebra_privs_t ospfd_privs = {.user = NULL,
49 .group = NULL,
50 .cap_num_p = 0,
51 .cap_num_i = 0};
edd7c245 52
f894c3ad 53/* The following includes are specific to this application. For
55c72803 54 example it uses threads from libfrr, however your application is
f894c3ad 55 free to use any thread library (like pthreads). */
2d33f157 56
f894c3ad 57#include "ospfd/ospf_dump.h" /* for ospf_lsa_header_dump */
2d33f157 58#include "thread.h"
59#include "log.h"
60
f894c3ad 61/* Local portnumber for async channel. Note that OSPF API library will also
62 allocate a sync channel at ASYNCPORT+1. */
2d33f157 63#define ASYNCPORT 4000
64
65/* Master thread */
66struct thread_master *master;
67
68/* Global variables */
69struct ospf_apiclient *oclient;
70char **args;
71
f894c3ad 72/* Our opaque LSAs have the following format. */
d62a17ae 73struct my_opaque_lsa {
74 struct lsa_header hdr; /* include common LSA header */
d7c0a89a 75 uint8_t data[4]; /* our own data format then follows here */
2d33f157 76};
77
78
79/* ---------------------------------------------------------
d62a17ae 80 * Threads for asynchronous messages and LSA update/delete
2d33f157 81 * ---------------------------------------------------------
82 */
83
d62a17ae 84static int lsa_delete(struct thread *t)
2d33f157 85{
d62a17ae 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;
2d33f157 105}
106
d62a17ae 107static int lsa_inject(struct thread *t)
2d33f157 108{
d62a17ae 109 struct ospf_apiclient *cl;
110 struct in_addr ifaddr;
111 struct in_addr area_id;
d7c0a89a
QY
112 uint8_t lsa_type;
113 uint8_t opaque_type;
114 uint32_t opaque_id;
d62a17ae 115 void *opaquedata;
116 int opaquelen;
117
d7c0a89a 118 static uint32_t counter = 1; /* Incremented each time invoked */
d62a17ae 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;
d7c0a89a 138 opaquelen = sizeof(uint32_t);
d62a17ae 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;
30a2231a 150}
2d33f157 151
152
153/* This thread handles asynchronous messages coming in from the OSPF
154 API server */
d62a17ae 155static int lsa_read(struct thread *thread)
2d33f157 156{
d62a17ae 157 struct ospf_apiclient *oclient;
158 int fd;
159 int ret;
2d33f157 160
d62a17ae 161 printf("lsa_read called\n");
2d33f157 162
d62a17ae 163 oclient = THREAD_ARG(thread);
164 fd = THREAD_FD(thread);
2d33f157 165
d62a17ae 166 /* Handle asynchronous message */
167 ret = ospf_apiclient_handle_async(oclient);
168 if (ret < 0) {
169 printf("Connection closed, exiting...");
170 exit(0);
171 }
2d33f157 172
d62a17ae 173 /* Reschedule read thread */
174 thread_add_read(master, lsa_read, oclient, fd, NULL);
2d33f157 175
d62a17ae 176 return 0;
2d33f157 177}
178
2d33f157 179/* ---------------------------------------------------------
d62a17ae 180 * Callback functions for asynchronous events
2d33f157 181 * ---------------------------------------------------------
182 */
183
d62a17ae 184static void lsa_update_callback(struct in_addr ifaddr, struct in_addr area_id,
d7c0a89a 185 uint8_t is_self_originated,
d62a17ae 186 struct lsa_header *lsa)
2d33f157 187{
d62a17ae 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 ...
d7c0a89a 201 uint16_t links = rl->links;
d62a17ae 202 ...
203 }
204 */
205
206 ospf_lsa_header_dump(lsa);
2d33f157 207}
208
d62a17ae 209static void lsa_delete_callback(struct in_addr ifaddr, struct in_addr area_id,
d7c0a89a 210 uint8_t is_self_originated,
d62a17ae 211 struct lsa_header *lsa)
2d33f157 212{
d62a17ae 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);
2d33f157 217
d62a17ae 218 ospf_lsa_header_dump(lsa);
2d33f157 219}
220
d7c0a89a 221static void ready_callback(uint8_t lsa_type, uint8_t opaque_type,
d62a17ae 222 struct in_addr addr)
2d33f157 223{
d62a17ae 224 printf("ready_callback: lsa_type: %d opaque_type: %d addr=%s\n",
225 lsa_type, opaque_type, inet_ntoa(addr));
2d33f157 226
d62a17ae 227 /* Schedule opaque LSA originate in 5 secs */
228 thread_add_timer(master, lsa_inject, oclient, 5, NULL);
2d33f157 229
d62a17ae 230 /* Schedule opaque LSA update with new value */
231 thread_add_timer(master, lsa_inject, oclient, 10, NULL);
2d33f157 232
d62a17ae 233 /* Schedule delete */
234 thread_add_timer(master, lsa_delete, oclient, 30, NULL);
2d33f157 235}
236
d62a17ae 237static void new_if_callback(struct in_addr ifaddr, struct in_addr area_id)
2d33f157 238{
d62a17ae 239 printf("new_if_callback: ifaddr: %s ", inet_ntoa(ifaddr));
240 printf("area_id: %s\n", inet_ntoa(area_id));
2d33f157 241}
242
d62a17ae 243static void del_if_callback(struct in_addr ifaddr)
2d33f157 244{
d62a17ae 245 printf("new_if_callback: ifaddr: %s\n ", inet_ntoa(ifaddr));
2d33f157 246}
247
d62a17ae 248static void ism_change_callback(struct in_addr ifaddr, struct in_addr area_id,
d7c0a89a 249 uint8_t state)
2d33f157 250{
d62a17ae 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));
2d33f157 255}
256
d62a17ae 257static void nsm_change_callback(struct in_addr ifaddr, struct in_addr nbraddr,
d7c0a89a 258 struct in_addr router_id, uint8_t state)
2d33f157 259{
d62a17ae 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));
2d33f157 265}
266
267
268/* ---------------------------------------------------------
d62a17ae 269 * Main program
2d33f157 270 * ---------------------------------------------------------
271 */
272
35dece84 273static int usage(void)
f894c3ad 274{
d62a17ae 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);
f894c3ad 284}
285
d62a17ae 286int main(int argc, char *argv[])
2d33f157 287{
d62a17ae 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 */
37a1f2fb 310 zprivs_preinit(&ospfd_privs);
d62a17ae 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;
2d33f157 345}