1/*
2 * Client side of OSPF API.
3 * Copyright (C) 2001, 2002, 2003 Ralph Keller
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING.  If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include <lib/version.h>
26#include "getopt.h"
27#include "thread.h"
28#include "prefix.h"
29#include "linklist.h"
30#include "if.h"
31#include "vector.h"
32#include "vty.h"
33#include "command.h"
34#include "filter.h"
35#include "stream.h"
36#include "log.h"
37#include "memory.h"
38
39#include "ospfd/ospfd.h"
40#include "ospfd/ospf_interface.h"
41#include "ospfd/ospf_asbr.h"
42#include "ospfd/ospf_lsa.h"
43#include "ospfd/ospf_opaque.h"
44#include "ospfd/ospf_lsdb.h"
45#include "ospfd/ospf_neighbor.h"
46#include "ospfd/ospf_dump.h"
47#include "ospfd/ospf_zebra.h"
48#include "ospfd/ospf_api.h"
49
50#include "ospf_apiclient.h"
51
52/* Backlog for listen */
53#define BACKLOG 5
54
55/* -----------------------------------------------------------
56 * Forward declarations
57 * -----------------------------------------------------------
58 */
59
60void ospf_apiclient_handle_reply (struct ospf_apiclient *oclient,
61				  struct msg *msg);
62void ospf_apiclient_handle_update_notify (struct ospf_apiclient *oclient,
63					  struct msg *msg);
64void ospf_apiclient_handle_delete_notify (struct ospf_apiclient *oclient,
65					  struct msg *msg);
66
67/* -----------------------------------------------------------
68 * Initialization
69 * -----------------------------------------------------------
70 */
71
72static unsigned short
73ospf_apiclient_getport (void)
74{
75  struct servent *sp = getservbyname ("ospfapi", "tcp");
76
77  return sp ? ntohs (sp->s_port) : OSPF_API_SYNC_PORT;
78}
79
80/* -----------------------------------------------------------
81 * Followings are functions for connection management
82 * -----------------------------------------------------------
83 */
84
85struct ospf_apiclient *
86ospf_apiclient_connect (char *host, int syncport)
87{
88  struct sockaddr_in myaddr_sync;
89  struct sockaddr_in myaddr_async;
90  struct sockaddr_in peeraddr;
91  struct hostent *hp;
92  struct ospf_apiclient *new;
93  int size = 0;
94  unsigned int peeraddrlen;
95  int async_server_sock;
96  int fd1, fd2;
97  int ret;
98  int on = 1;
99
100  /* There are two connections between the client and the server.
101     First the client opens a connection for synchronous requests/replies
102     to the server. The server will accept this connection and
103     as a reaction open a reverse connection channel for
104     asynchronous messages. */
105
106  async_server_sock = socket (AF_INET, SOCK_STREAM, 0);
107  if (async_server_sock < 0)
108    {
109      fprintf (stderr,
110	       "ospf_apiclient_connect: creating async socket failed\n");
111      return NULL;
112    }
113
114  /* Prepare socket for asynchronous messages */
115  /* Initialize async address structure */
116  memset (&myaddr_async, 0, sizeof (struct sockaddr_in));
117  myaddr_async.sin_family = AF_INET;
118  myaddr_async.sin_addr.s_addr = htonl (INADDR_ANY);
119  myaddr_async.sin_port = htons (syncport+1);
120  size = sizeof (struct sockaddr_in);
121#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
122  myaddr_async.sin_len = size;
123#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
124
125  /* This is a server socket, reuse addr and port */
126  ret = setsockopt (async_server_sock, SOL_SOCKET,
127		    SO_REUSEADDR, (void *) &on, sizeof (on));
128  if (ret < 0)
129    {
130      fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n");
131      close (async_server_sock);
132      return NULL;
133    }
134
135#ifdef SO_REUSEPORT
136  ret = setsockopt (async_server_sock, SOL_SOCKET, SO_REUSEPORT,
137		    (void *) &on, sizeof (on));
138  if (ret < 0)
139    {
140      fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n");
141      close (async_server_sock);
142      return NULL;
143    }
144#endif /* SO_REUSEPORT */
145
146  /* Bind socket to address structure */
147  ret = bind (async_server_sock, (struct sockaddr *) &myaddr_async, size);
148  if (ret < 0)
149    {
150      fprintf (stderr, "ospf_apiclient_connect: bind async socket failed\n");
151      close (async_server_sock);
152      return NULL;
153    }
154
155  /* Wait for reverse channel connection establishment from server */
156  ret = listen (async_server_sock, BACKLOG);
157  if (ret < 0)
158    {
159      fprintf (stderr, "ospf_apiclient_connect: listen: %s\n", safe_strerror (errno));
160      close (async_server_sock);
161      return NULL;
162    }
163
164  /* Make connection for synchronous requests and connect to server */
165  /* Resolve address of server */
166  hp = gethostbyname (host);
167  if (!hp)
168    {
169      fprintf (stderr, "ospf_apiclient_connect: no such host %s\n", host);
170      close (async_server_sock);
171      return NULL;
172    }
173
174  fd1 = socket (AF_INET, SOCK_STREAM, 0);
175  if (fd1 < 0)
176    {
177      fprintf (stderr,
178	       "ospf_apiclient_connect: creating sync socket failed\n");
179      return NULL;
180    }
181
182
183  /* Reuse addr and port */
184  ret = setsockopt (fd1, SOL_SOCKET,
185                    SO_REUSEADDR, (void *) &on, sizeof (on));
186  if (ret < 0)
187    {
188      fprintf (stderr, "ospf_apiclient_connect: SO_REUSEADDR failed\n");
189      close (fd1);
190      return NULL;
191    }
192
193#ifdef SO_REUSEPORT
194  ret = setsockopt (fd1, SOL_SOCKET, SO_REUSEPORT,
195                    (void *) &on, sizeof (on));
196  if (ret < 0)
197    {
198      fprintf (stderr, "ospf_apiclient_connect: SO_REUSEPORT failed\n");
199      close (fd1);
200      return NULL;
201    }
202#endif /* SO_REUSEPORT */
203
204
205  /* Bind sync socket to address structure. This is needed since we
206     want the sync port number on a fixed port number. The reverse
207     async channel will be at this port+1 */
208
209  memset (&myaddr_sync, 0, sizeof (struct sockaddr_in));
210  myaddr_sync.sin_family = AF_INET;
211  myaddr_sync.sin_port = htons (syncport);
212#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
213  myaddr_sync.sin_len = sizeof (struct sockaddr_in);
214#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
215
216  ret = bind (fd1, (struct sockaddr *) &myaddr_sync, size);
217  if (ret < 0)
218    {
219      fprintf (stderr, "ospf_apiclient_connect: bind sync socket failed\n");
220      close (fd1);
221      return NULL;
222    }
223
224  /* Prepare address structure for connect */
225  memcpy (&myaddr_sync.sin_addr, hp->h_addr, hp->h_length);
226  myaddr_sync.sin_family = AF_INET;
227  myaddr_sync.sin_port = htons(ospf_apiclient_getport ());
228#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
229  myaddr_sync.sin_len = sizeof (struct sockaddr_in);
230#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
231
232  /* Now establish synchronous channel with OSPF daemon */
233  ret = connect (fd1, (struct sockaddr *) &myaddr_sync,
234		 sizeof (struct sockaddr_in));
235  if (ret < 0)
236    {
237      fprintf (stderr, "ospf_apiclient_connect: sync connect failed\n");
238      close (async_server_sock);
239      close (fd1);
240      return NULL;
241    }
242
243  /* Accept reverse connection */
244  peeraddrlen = sizeof (struct sockaddr_in);
245  memset (&peeraddr, 0, peeraddrlen);
246
247  fd2 =
248    accept (async_server_sock, (struct sockaddr *) &peeraddr, &peeraddrlen);
249  if (fd2 < 0)
250    {
251      fprintf (stderr, "ospf_apiclient_connect: accept async failed\n");
252      close (async_server_sock);
253      close (fd1);
254      return NULL;
255    }
256
257  /* Server socket is not needed anymore since we are not accepting more
258     connections */
259  close (async_server_sock);
260
261  /* Create new client-side instance */
262  new = XCALLOC (MTYPE_OSPF_APICLIENT, sizeof (struct ospf_apiclient));
263
264  /* Initialize socket descriptors for sync and async channels */
265  new->fd_sync = fd1;
266  new->fd_async = fd2;
267
268  return new;
269}
270
271int
272ospf_apiclient_close (struct ospf_apiclient *oclient)
273{
274
275  if (oclient->fd_sync >= 0)
276    {
277      close (oclient->fd_sync);
278    }
279
280  if (oclient->fd_async >= 0)
281    {
282      close (oclient->fd_async);
283    }
284
285  /* Free client structure */
286  XFREE (MTYPE_OSPF_APICLIENT, oclient);
287  return 0;
288}
289
290/* -----------------------------------------------------------
291 * Followings are functions to send a request to OSPFd
292 * -----------------------------------------------------------
293 */
294
295/* Send synchronous request, wait for reply */
296static int
297ospf_apiclient_send_request (struct ospf_apiclient *oclient, struct msg *msg)
298{
299  u_int32_t reqseq;
300  struct msg_reply *msgreply;
301  int rc;
302
303  /* NB: Given "msg" is freed inside this function. */
304
305  /* Remember the sequence number of the request */
306  reqseq = ntohl (msg->hdr.msgseq);
307
308  /* Write message to OSPFd */
309  rc = msg_write (oclient->fd_sync, msg);
310  msg_free (msg);
311
312  if (rc < 0)
313    {
314      return -1;
315    }
316
317  /* Wait for reply *//* NB: New "msg" is allocated by "msg_read()". */
318  msg = msg_read (oclient->fd_sync);
319  if (!msg)
320    return -1;
321
322  assert (msg->hdr.msgtype == MSG_REPLY);
323  assert (ntohl (msg->hdr.msgseq) == reqseq);
324
325  msgreply = (struct msg_reply *) STREAM_DATA (msg->s);
326  rc = msgreply->errcode;
327  msg_free (msg);
328
329  return rc;
330}
331
332
333/* -----------------------------------------------------------
334 * Helper functions
335 * -----------------------------------------------------------
336 */
337
338static u_int32_t
339ospf_apiclient_get_seqnr (void)
340{
341  static u_int32_t seqnr = MIN_SEQ;
342  u_int32_t tmp;
343
344  tmp = seqnr;
345  /* Increment sequence number */
346  if (seqnr < MAX_SEQ)
347    {
348      seqnr++;
349    }
350  else
351    {
352      seqnr = MIN_SEQ;
353    }
354  return tmp;
355}
356
357/* -----------------------------------------------------------
358 * API to access OSPF daemon by client applications.
359 * -----------------------------------------------------------
360 */
361
362/*
363 * Synchronous request to register opaque type.
364 */
365int
366ospf_apiclient_register_opaque_type (struct ospf_apiclient *cl,
367				     u_char ltype, u_char otype)
368{
369  struct msg *msg;
370  int rc;
371
372  /* just put 1 as a sequence number. */
373  msg = new_msg_register_opaque_type (ospf_apiclient_get_seqnr (),
374				      ltype, otype);
375  if (!msg)
376    {
377      fprintf (stderr, "new_msg_register_opaque_type failed\n");
378      return -1;
379    }
380
381  rc = ospf_apiclient_send_request (cl, msg);
382  return rc;
383}
384
385/*
386 * Synchronous request to synchronize with OSPF's LSDB.
387 * Two steps required: register_event in order to get
388 * dynamic updates and LSDB_Sync.
389 */
390int
391ospf_apiclient_sync_lsdb (struct ospf_apiclient *oclient)
392{
393  struct msg *msg;
394  int rc;
395  struct lsa_filter_type filter;
396
397  filter.typemask = 0xFFFF;	/* all LSAs */
398  filter.origin = ANY_ORIGIN;
399  filter.num_areas = 0;		/* all Areas. */
400
401  msg = new_msg_register_event (ospf_apiclient_get_seqnr (), &filter);
402  if (!msg)
403    {
404      fprintf (stderr, "new_msg_register_event failed\n");
405      return -1;
406    }
407  rc = ospf_apiclient_send_request (oclient, msg);
408
409  if (rc != 0)
410    goto out;
411
412  msg = new_msg_sync_lsdb (ospf_apiclient_get_seqnr (), &filter);
413  if (!msg)
414    {
415      fprintf (stderr, "new_msg_sync_lsdb failed\n");
416      return -1;
417    }
418  rc = ospf_apiclient_send_request (oclient, msg);
419
420out:
421  return rc;
422}
423
424/*
425 * Synchronous request to originate or update an LSA.
426 */
427
428int
429ospf_apiclient_lsa_originate (struct ospf_apiclient *oclient,
430			      struct in_addr ifaddr,
431			      struct in_addr area_id,
432			      u_char lsa_type,
433			      u_char opaque_type, u_int32_t opaque_id,
434			      void *opaquedata, int opaquelen)
435{
436  struct msg *msg;
437  int rc;
438  u_char buf[OSPF_MAX_LSA_SIZE];
439  struct lsa_header *lsah;
440  u_int32_t tmp;
441
442
443  /* We can only originate opaque LSAs */
444  if (!IS_OPAQUE_LSA (lsa_type))
445    {
446      fprintf (stderr, "Cannot originate non-opaque LSA type %d\n", lsa_type);
447      return OSPF_API_ILLEGALLSATYPE;
448    }
449
450  /* Make a new LSA from parameters */
451  lsah = (struct lsa_header *) buf;
452  lsah->ls_age = 0;
453  lsah->options = 0;
454  lsah->type = lsa_type;
455
456  tmp = SET_OPAQUE_LSID (opaque_type, opaque_id);
457  lsah->id.s_addr = htonl (tmp);
458  lsah->adv_router.s_addr = 0;
459  lsah->ls_seqnum = 0;
460  lsah->checksum = 0;
461  lsah->length = htons (sizeof (struct lsa_header) + opaquelen);
462
463  memcpy (((u_char *) lsah) + sizeof (struct lsa_header), opaquedata,
464	  opaquelen);
465
466  msg = new_msg_originate_request (ospf_apiclient_get_seqnr (),
467				   ifaddr, area_id, lsah);
468  if (!msg)
469    {
470      fprintf (stderr, "new_msg_originate_request failed\n");
471      return OSPF_API_NOMEMORY;
472    }
473
474  rc = ospf_apiclient_send_request (oclient, msg);
475  return rc;
476}
477
478int
479ospf_apiclient_lsa_delete (struct ospf_apiclient *oclient,
480			   struct in_addr area_id, u_char lsa_type,
481			   u_char opaque_type, u_int32_t opaque_id)
482{
483  struct msg *msg;
484  int rc;
485
486  /* Only opaque LSA can be deleted */
487  if (!IS_OPAQUE_LSA (lsa_type))
488    {
489      fprintf (stderr, "Cannot delete non-opaque LSA type %d\n", lsa_type);
490      return OSPF_API_ILLEGALLSATYPE;
491    }
492
493  /* opaque_id is in host byte order and will be converted
494   * to network byte order by new_msg_delete_request */
495  msg = new_msg_delete_request (ospf_apiclient_get_seqnr (),
496				area_id, lsa_type, opaque_type, opaque_id);
497
498  rc = ospf_apiclient_send_request (oclient, msg);
499  return rc;
500}
501
502/* -----------------------------------------------------------
503 * Followings are handlers for messages from OSPF daemon
504 * -----------------------------------------------------------
505 */
506
507static void
508ospf_apiclient_handle_ready (struct ospf_apiclient *oclient, struct msg *msg)
509{
510  struct msg_ready_notify *r;
511  r = (struct msg_ready_notify *) STREAM_DATA (msg->s);
512
513  /* Invoke registered callback function. */
514  if (oclient->ready_notify)
515    {
516      (oclient->ready_notify) (r->lsa_type, r->opaque_type, r->addr);
517    }
518}
519
520static void
521ospf_apiclient_handle_new_if (struct ospf_apiclient *oclient, struct msg *msg)
522{
523  struct msg_new_if *n;
524  n = (struct msg_new_if *) STREAM_DATA (msg->s);
525
526  /* Invoke registered callback function. */
527  if (oclient->new_if)
528    {
529      (oclient->new_if) (n->ifaddr, n->area_id);
530    }
531}
532
533static void
534ospf_apiclient_handle_del_if (struct ospf_apiclient *oclient, struct msg *msg)
535{
536  struct msg_del_if *d;
537  d = (struct msg_del_if *) STREAM_DATA (msg->s);
538
539  /* Invoke registered callback function. */
540  if (oclient->del_if)
541    {
542      (oclient->del_if) (d->ifaddr);
543    }
544}
545
546static void
547ospf_apiclient_handle_ism_change (struct ospf_apiclient *oclient,
548				  struct msg *msg)
549{
550  struct msg_ism_change *m;
551  m = (struct msg_ism_change *) STREAM_DATA (msg->s);
552
553  /* Invoke registered callback function. */
554  if (oclient->ism_change)
555    {
556      (oclient->ism_change) (m->ifaddr, m->area_id, m->status);
557    }
558
559}
560
561static void
562ospf_apiclient_handle_nsm_change (struct ospf_apiclient *oclient,
563				  struct msg *msg)
564{
565  struct msg_nsm_change *m;
566  m = (struct msg_nsm_change *) STREAM_DATA (msg->s);
567
568  /* Invoke registered callback function. */
569  if (oclient->nsm_change)
570    {
571      (oclient->nsm_change) (m->ifaddr, m->nbraddr, m->router_id, m->status);
572    }
573}
574
575static void
576ospf_apiclient_handle_lsa_update (struct ospf_apiclient *oclient,
577				  struct msg *msg)
578{
579  struct msg_lsa_change_notify *cn;
580  struct lsa_header *lsa;
581  int lsalen;
582
583  cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s);
584
585  /* Extract LSA from message */
586  lsalen = ntohs (cn->data.length);
587  lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen);
588  if (!lsa)
589    {
590      fprintf (stderr, "LSA update: Cannot allocate memory for LSA\n");
591      return;
592    }
593  memcpy (lsa, &(cn->data), lsalen);
594
595  /* Invoke registered update callback function */
596  if (oclient->update_notify)
597    {
598      (oclient->update_notify) (cn->ifaddr, cn->area_id,
599				cn->is_self_originated, lsa);
600    }
601
602  /* free memory allocated by ospf apiclient library */
603  XFREE (MTYPE_OSPF_APICLIENT, lsa);
604}
605
606static void
607ospf_apiclient_handle_lsa_delete (struct ospf_apiclient *oclient,
608				  struct msg *msg)
609{
610  struct msg_lsa_change_notify *cn;
611  struct lsa_header *lsa;
612  int lsalen;
613
614  cn = (struct msg_lsa_change_notify *) STREAM_DATA (msg->s);
615
616  /* Extract LSA from message */
617  lsalen = ntohs (cn->data.length);
618  lsa = XMALLOC (MTYPE_OSPF_APICLIENT, lsalen);
619  if (!lsa)
620    {
621      fprintf (stderr, "LSA delete: Cannot allocate memory for LSA\n");
622      return;
623    }
624  memcpy (lsa, &(cn->data), lsalen);
625
626  /* Invoke registered update callback function */
627  if (oclient->delete_notify)
628    {
629      (oclient->delete_notify) (cn->ifaddr, cn->area_id,
630				cn->is_self_originated, lsa);
631    }
632
633  /* free memory allocated by ospf apiclient library */
634  XFREE (MTYPE_OSPF_APICLIENT, lsa);
635}
636
637static void
638ospf_apiclient_msghandle (struct ospf_apiclient *oclient, struct msg *msg)
639{
640  /* Call message handler function. */
641  switch (msg->hdr.msgtype)
642    {
643    case MSG_READY_NOTIFY:
644      ospf_apiclient_handle_ready (oclient, msg);
645      break;
646    case MSG_NEW_IF:
647      ospf_apiclient_handle_new_if (oclient, msg);
648      break;
649    case MSG_DEL_IF:
650      ospf_apiclient_handle_del_if (oclient, msg);
651      break;
652    case MSG_ISM_CHANGE:
653      ospf_apiclient_handle_ism_change (oclient, msg);
654      break;
655    case MSG_NSM_CHANGE:
656      ospf_apiclient_handle_nsm_change (oclient, msg);
657      break;
658    case MSG_LSA_UPDATE_NOTIFY:
659      ospf_apiclient_handle_lsa_update (oclient, msg);
660      break;
661    case MSG_LSA_DELETE_NOTIFY:
662      ospf_apiclient_handle_lsa_delete (oclient, msg);
663      break;
664    default:
665      fprintf (stderr, "ospf_apiclient_read: Unknown message type: %d\n",
666	       msg->hdr.msgtype);
667      break;
668    }
669}
670
671/* -----------------------------------------------------------
672 * Callback handler registration
673 * -----------------------------------------------------------
674 */
675
676void
677ospf_apiclient_register_callback (struct ospf_apiclient *oclient,
678				  void (*ready_notify) (u_char lsa_type,
679							u_char opaque_type,
680							struct in_addr addr),
681				  void (*new_if) (struct in_addr ifaddr,
682						  struct in_addr area_id),
683				  void (*del_if) (struct in_addr ifaddr),
684				  void (*ism_change) (struct in_addr ifaddr,
685						      struct in_addr area_id,
686						      u_char status),
687				  void (*nsm_change) (struct in_addr ifaddr,
688						      struct in_addr nbraddr,
689						      struct in_addr
690						      router_id,
691						      u_char status),
692				  void (*update_notify) (struct in_addr
693							 ifaddr,
694							 struct in_addr
695							 area_id,
696							 u_char self_origin,
697							 struct lsa_header *
698							 lsa),
699				  void (*delete_notify) (struct in_addr
700							 ifaddr,
701							 struct in_addr
702							 area_id,
703							 u_char self_origin,
704							 struct lsa_header *
705							 lsa))
706{
707  assert (oclient);
708  assert (update_notify);
709
710  /* Register callback function */
711  oclient->ready_notify = ready_notify;
712  oclient->new_if = new_if;
713  oclient->del_if = del_if;
714  oclient->ism_change = ism_change;
715  oclient->nsm_change = nsm_change;
716  oclient->update_notify = update_notify;
717  oclient->delete_notify = delete_notify;
718}
719
720/* -----------------------------------------------------------
721 * Asynchronous message handling
722 * -----------------------------------------------------------
723 */
724
725int
726ospf_apiclient_handle_async (struct ospf_apiclient *oclient)
727{
728  struct msg *msg;
729
730  /* Get a message */
731  msg = msg_read (oclient->fd_async);
732
733  if (!msg)
734    {
735      /* Connection broke down */
736      return -1;
737    }
738
739  /* Handle message */
740  ospf_apiclient_msghandle (oclient, msg);
741
742  /* Don't forget to free this message */
743  msg_free (msg);
744
745  return 0;
746}
747