Annotation of embedaddon/quagga/ospfclient/ospf_apiclient.c, revision 1.1.1.1

1.1       misho       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: 
                     60: void ospf_apiclient_handle_reply (struct ospf_apiclient *oclient,
                     61:                                  struct msg *msg);
                     62: void ospf_apiclient_handle_update_notify (struct ospf_apiclient *oclient,
                     63:                                          struct msg *msg);
                     64: void ospf_apiclient_handle_delete_notify (struct ospf_apiclient *oclient,
                     65:                                          struct msg *msg);
                     66: 
                     67: /* -----------------------------------------------------------
                     68:  * Initialization
                     69:  * -----------------------------------------------------------
                     70:  */
                     71: 
                     72: static unsigned short
                     73: ospf_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: 
                     85: struct ospf_apiclient *
                     86: ospf_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: 
                    271: int
                    272: ospf_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 */
                    296: static int
                    297: ospf_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: 
                    338: static u_int32_t
                    339: ospf_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:  */
                    365: int
                    366: ospf_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:  */
                    390: int
                    391: ospf_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: 
                    420: out:
                    421:   return rc;
                    422: }
                    423: 
                    424: /* 
                    425:  * Synchronous request to originate or update an LSA.
                    426:  */
                    427: 
                    428: int
                    429: ospf_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: 
                    478: int
                    479: ospf_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: 
                    507: static void
                    508: ospf_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: 
                    520: static void
                    521: ospf_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: 
                    533: static void
                    534: ospf_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: 
                    546: static void
                    547: ospf_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: 
                    561: static void
                    562: ospf_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: 
                    575: static void
                    576: ospf_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: 
                    606: static void
                    607: ospf_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: 
                    637: static void
                    638: ospf_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: 
                    676: void
                    677: ospf_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: 
                    725: int
                    726: ospf_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: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>