ospfclient.c 8.7 KB

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