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