back to topotato report
topotato coverage report
Current view: top level - ospfd - ospf_api.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 19 288 6.6 %
Date: 2023-02-24 14:41:08 Functions: 3 31 9.7 %

          Line data    Source code
       1             : /*
       2             :  * API message handling module for OSPF daemon and client.
       3             :  * Copyright (C) 2001, 2002 Ralph Keller
       4             :  * Copyright (c) 2022, LabN Consulting, L.L.C.
       5             :  *
       6             :  * This file is part of GNU Zebra.
       7             :  *
       8             :  * GNU Zebra is free software; you can redistribute it and/or modify
       9             :  * it under the terms of the GNU General Public License as published
      10             :  * by the Free Software Foundation; either version 2, or (at your
      11             :  * option) any later version.
      12             :  *
      13             :  * GNU Zebra is distributed in the hope that it will be useful, but
      14             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU General Public License along
      19             :  * with this program; see the file COPYING; if not, write to the Free Software
      20             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      21             :  */
      22             : 
      23             : #include <zebra.h>
      24             : 
      25             : #ifdef SUPPORT_OSPF_API
      26             : 
      27             : #include "linklist.h"
      28             : #include "prefix.h"
      29             : #include "if.h"
      30             : #include "table.h"
      31             : #include "memory.h"
      32             : #include "command.h"
      33             : #include "vty.h"
      34             : #include "stream.h"
      35             : #include "log.h"
      36             : #include "thread.h"
      37             : #include "hash.h"
      38             : #include "sockunion.h" /* for inet_aton() */
      39             : #include "buffer.h"
      40             : #include "network.h"
      41             : 
      42             : #include "ospfd/ospfd.h"
      43             : #include "ospfd/ospf_interface.h"
      44             : #include "ospfd/ospf_ism.h"
      45             : #include "ospfd/ospf_asbr.h"
      46             : #include "ospfd/ospf_lsa.h"
      47             : #include "ospfd/ospf_lsdb.h"
      48             : #include "ospfd/ospf_neighbor.h"
      49             : #include "ospfd/ospf_nsm.h"
      50             : #include "ospfd/ospf_flood.h"
      51             : #include "ospfd/ospf_packet.h"
      52             : #include "ospfd/ospf_spf.h"
      53             : #include "ospfd/ospf_dump.h"
      54             : #include "ospfd/ospf_route.h"
      55             : #include "ospfd/ospf_ase.h"
      56             : #include "ospfd/ospf_zebra.h"
      57             : 
      58             : #include "ospfd/ospf_api.h"
      59             : 
      60             : 
      61             : /* For debugging only, will be removed */
      62           0 : void api_opaque_lsa_print(struct ospf_lsa *lsa)
      63             : {
      64           0 :         struct opaque_lsa {
      65             :                 struct lsa_header header;
      66             :                 uint8_t mydata[];
      67             :         };
      68             : 
      69           0 :         struct opaque_lsa *olsa;
      70           0 :         int opaquelen;
      71           0 :         int i;
      72             : 
      73           0 :         ospf_lsa_header_dump(lsa->data);
      74             : 
      75           0 :         olsa = (struct opaque_lsa *)lsa->data;
      76             : 
      77           0 :         opaquelen = lsa->size - OSPF_LSA_HEADER_SIZE;
      78           0 :         zlog_debug("apiserver_lsa_print: opaquelen=%d", opaquelen);
      79             : 
      80           0 :         for (i = 0; i < opaquelen; i++) {
      81           0 :                 zlog_debug("0x%x ", olsa->mydata[i]);
      82             :         }
      83           0 :         zlog_debug(" ");
      84           0 : }
      85             : 
      86             : /* -----------------------------------------------------------
      87             :  * Generic messages
      88             :  * -----------------------------------------------------------
      89             :  */
      90             : 
      91           4 : struct msg *msg_new(uint8_t msgtype, void *msgbody, uint32_t seqnum,
      92             :                     uint16_t msglen)
      93             : {
      94           4 :         struct msg *new;
      95             : 
      96           4 :         new = XCALLOC(MTYPE_OSPF_API_MSG, sizeof(struct msg));
      97             : 
      98           4 :         new->hdr.version = OSPF_API_VERSION;
      99           4 :         new->hdr.msgtype = msgtype;
     100           4 :         new->hdr.msglen = htons(msglen);
     101           4 :         new->hdr.msgseq = htonl(seqnum);
     102             : 
     103           4 :         new->s = stream_new(msglen);
     104           4 :         assert(new->s);
     105           4 :         stream_put(new->s, msgbody, msglen);
     106             : 
     107           4 :         return new;
     108             : }
     109             : 
     110             : 
     111             : /* Duplicate a message by copying content. */
     112           0 : struct msg *msg_dup(struct msg *msg)
     113             : {
     114           0 :         struct msg *new;
     115           0 :         size_t size;
     116             : 
     117           0 :         assert(msg);
     118             : 
     119           0 :         size = ntohs(msg->hdr.msglen);
     120           0 :         if (size > OSPF_MAX_LSA_SIZE)
     121             :                 return NULL;
     122             : 
     123           0 :         new = msg_new(msg->hdr.msgtype, STREAM_DATA(msg->s),
     124             :                       ntohl(msg->hdr.msgseq), size);
     125           0 :         return new;
     126             : }
     127             : 
     128             : 
     129             : /* XXX only for testing, will be removed */
     130             : 
     131             : struct nametab {
     132             :         int value;
     133             :         const char *name;
     134             : };
     135             : 
     136           0 : const char *ospf_api_typename(int msgtype)
     137             : {
     138           0 :         struct nametab NameTab[] = {
     139             :                 {
     140             :                         MSG_REGISTER_OPAQUETYPE, "Register opaque-type",
     141             :                 },
     142             :                 {
     143             :                         MSG_UNREGISTER_OPAQUETYPE, "Unregister opaque-type",
     144             :                 },
     145             :                 {
     146             :                         MSG_REGISTER_EVENT, "Register event",
     147             :                 },
     148             :                 {
     149             :                         MSG_SYNC_LSDB, "Sync LSDB",
     150             :                 },
     151             :                 {
     152             :                         MSG_ORIGINATE_REQUEST, "Originate request",
     153             :                 },
     154             :                 {
     155             :                         MSG_DELETE_REQUEST, "Delete request",
     156             :                 },
     157             :                 {
     158             :                         MSG_REPLY, "Reply",
     159             :                 },
     160             :                 {
     161             :                         MSG_READY_NOTIFY, "Ready notify",
     162             :                 },
     163             :                 {
     164             :                         MSG_LSA_UPDATE_NOTIFY, "LSA update notify",
     165             :                 },
     166             :                 {
     167             :                         MSG_LSA_DELETE_NOTIFY, "LSA delete notify",
     168             :                 },
     169             :                 {
     170             :                         MSG_NEW_IF, "New interface",
     171             :                 },
     172             :                 {
     173             :                         MSG_DEL_IF, "Del interface",
     174             :                 },
     175             :                 {
     176             :                         MSG_ISM_CHANGE, "ISM change",
     177             :                 },
     178             :                 {
     179             :                         MSG_NSM_CHANGE, "NSM change",
     180             :                 },
     181             :                 {
     182             :                         MSG_REACHABLE_CHANGE,
     183             :                         "Reachable change",
     184             :                 },
     185             :         };
     186             : 
     187           0 :         int i, n = array_size(NameTab);
     188           0 :         const char *name = NULL;
     189             : 
     190           0 :         for (i = 0; i < n; i++) {
     191           0 :                 if (NameTab[i].value == msgtype) {
     192           0 :                         name = NameTab[i].name;
     193           0 :                         break;
     194             :                 }
     195             :         }
     196             : 
     197           0 :         return name ? name : "?";
     198             : }
     199             : 
     200           0 : const char *ospf_api_errname(int errcode)
     201             : {
     202           0 :         struct nametab NameTab[] = {
     203             :                 {
     204             :                         OSPF_API_OK, "OK",
     205             :                 },
     206             :                 {
     207             :                         OSPF_API_NOSUCHINTERFACE, "No such interface",
     208             :                 },
     209             :                 {
     210             :                         OSPF_API_NOSUCHAREA, "No such area",
     211             :                 },
     212             :                 {
     213             :                         OSPF_API_NOSUCHLSA, "No such LSA",
     214             :                 },
     215             :                 {
     216             :                         OSPF_API_ILLEGALLSATYPE, "Illegal LSA type",
     217             :                 },
     218             :                 {
     219             :                         OSPF_API_OPAQUETYPEINUSE, "Opaque type in use",
     220             :                 },
     221             :                 {
     222             :                         OSPF_API_OPAQUETYPENOTREGISTERED,
     223             :                         "Opaque type not registered",
     224             :                 },
     225             :                 {
     226             :                         OSPF_API_NOTREADY, "Not ready",
     227             :                 },
     228             :                 {
     229             :                         OSPF_API_NOMEMORY, "No memory",
     230             :                 },
     231             :                 {
     232             :                         OSPF_API_ERROR, "Other error",
     233             :                 },
     234             :                 {
     235             :                         OSPF_API_UNDEF, "Undefined",
     236             :                 },
     237             :         };
     238             : 
     239           0 :         int i, n = array_size(NameTab);
     240           0 :         const char *name = NULL;
     241             : 
     242           0 :         for (i = 0; i < n; i++) {
     243           0 :                 if (NameTab[i].value == errcode) {
     244           0 :                         name = NameTab[i].name;
     245           0 :                         break;
     246             :                 }
     247             :         }
     248             : 
     249           0 :         return name ? name : "?";
     250             : }
     251             : 
     252           0 : void msg_print(struct msg *msg)
     253             : {
     254           0 :         if (!msg) {
     255           0 :                 zlog_debug("msg_print msg=NULL!");
     256           0 :                 return;
     257             :         }
     258             : 
     259             :         /* API message common header part. */
     260           0 :         zlog_debug("API-msg [%s]: type(%d),len(%d),seq(%lu),data(%p),size(%zd)",
     261             :                    ospf_api_typename(msg->hdr.msgtype), msg->hdr.msgtype,
     262             :                    ntohs(msg->hdr.msglen),
     263             :                    (unsigned long)ntohl(msg->hdr.msgseq), STREAM_DATA(msg->s),
     264             :                    STREAM_SIZE(msg->s));
     265             : 
     266           0 :         return;
     267             : }
     268             : 
     269           4 : void msg_free(struct msg *msg)
     270             : {
     271           4 :         if (msg->s)
     272           4 :                 stream_free(msg->s);
     273             : 
     274           4 :         XFREE(MTYPE_OSPF_API_MSG, msg);
     275           4 : }
     276             : 
     277             : 
     278             : /* Set sequence number of message */
     279           0 : void msg_set_seq(struct msg *msg, uint32_t seqnr)
     280             : {
     281           0 :         assert(msg);
     282           0 :         msg->hdr.msgseq = htonl(seqnr);
     283           0 : }
     284             : 
     285             : /* Get sequence number of message */
     286           0 : uint32_t msg_get_seq(struct msg *msg)
     287             : {
     288           0 :         assert(msg);
     289           0 :         return ntohl(msg->hdr.msgseq);
     290             : }
     291             : 
     292             : /* -----------------------------------------------------------
     293             :  * Message fifo queues
     294             :  * -----------------------------------------------------------
     295             :  */
     296             : 
     297           0 : struct msg_fifo *msg_fifo_new(void)
     298             : {
     299           0 :         return XCALLOC(MTYPE_OSPF_API_FIFO, sizeof(struct msg_fifo));
     300             : }
     301             : 
     302             : /* Add new message to fifo. */
     303           0 : void msg_fifo_push(struct msg_fifo *fifo, struct msg *msg)
     304             : {
     305           0 :         if (fifo->tail)
     306           0 :                 fifo->tail->next = msg;
     307             :         else
     308           0 :                 fifo->head = msg;
     309             : 
     310           0 :         fifo->tail = msg;
     311           0 :         fifo->count++;
     312           0 : }
     313             : 
     314             : 
     315             : /* Remove first message from fifo. */
     316           0 : struct msg *msg_fifo_pop(struct msg_fifo *fifo)
     317             : {
     318           0 :         struct msg *msg;
     319             : 
     320           0 :         msg = fifo->head;
     321           0 :         if (msg) {
     322           0 :                 fifo->head = msg->next;
     323             : 
     324           0 :                 if (fifo->head == NULL)
     325           0 :                         fifo->tail = NULL;
     326             : 
     327           0 :                 fifo->count--;
     328             :         }
     329           0 :         return msg;
     330             : }
     331             : 
     332             : /* Return first fifo entry but do not remove it. */
     333           0 : struct msg *msg_fifo_head(struct msg_fifo *fifo)
     334             : {
     335           0 :         return fifo->head;
     336             : }
     337             : 
     338             : /* Flush message fifo. */
     339           0 : void msg_fifo_flush(struct msg_fifo *fifo)
     340             : {
     341           0 :         struct msg *op;
     342           0 :         struct msg *next;
     343             : 
     344           0 :         for (op = fifo->head; op; op = next) {
     345           0 :                 next = op->next;
     346           0 :                 msg_free(op);
     347             :         }
     348             : 
     349           0 :         fifo->head = fifo->tail = NULL;
     350           0 :         fifo->count = 0;
     351           0 : }
     352             : 
     353             : /* Free API message fifo. */
     354           0 : void msg_fifo_free(struct msg_fifo *fifo)
     355             : {
     356           0 :         msg_fifo_flush(fifo);
     357             : 
     358           0 :         XFREE(MTYPE_OSPF_API_FIFO, fifo);
     359           0 : }
     360             : 
     361           0 : struct msg *msg_read(int fd)
     362             : {
     363           0 :         struct msg *msg;
     364           0 :         struct apimsghdr hdr;
     365           0 :         uint8_t buf[OSPF_API_MAX_MSG_SIZE];
     366           0 :         ssize_t bodylen;
     367           0 :         ssize_t rlen;
     368             : 
     369             :         /* Read message header */
     370           0 :         rlen = readn(fd, (uint8_t *)&hdr, sizeof(struct apimsghdr));
     371             : 
     372           0 :         if (rlen < 0) {
     373           0 :                 zlog_warn("msg_read: readn %s", safe_strerror(errno));
     374           0 :                 return NULL;
     375           0 :         } else if (rlen == 0) {
     376           0 :                 zlog_warn("msg_read: Connection closed by peer");
     377           0 :                 return NULL;
     378           0 :         } else if (rlen != sizeof(struct apimsghdr)) {
     379           0 :                 zlog_warn("msg_read: Cannot read message header!");
     380           0 :                 return NULL;
     381             :         }
     382             : 
     383             :         /* Check version of API protocol */
     384           0 :         if (hdr.version != OSPF_API_VERSION) {
     385           0 :                 zlog_warn("msg_read: OSPF API protocol version mismatch");
     386           0 :                 return NULL;
     387             :         }
     388             : 
     389             :         /* Determine body length. */
     390           0 :         bodylen = ntohs(hdr.msglen);
     391           0 :         if (bodylen > (ssize_t)sizeof(buf)) {
     392             :                 zlog_warn("%s: Body Length of message greater than what we can read",
     393             :                           __func__);
     394             :                 return NULL;
     395             :         }
     396             : 
     397           0 :         if (bodylen > 0) {
     398             :                 /* Read message body */
     399           0 :                 rlen = readn(fd, buf, bodylen);
     400           0 :                 if (rlen < 0) {
     401           0 :                         zlog_warn("msg_read: readn %s", safe_strerror(errno));
     402           0 :                         return NULL;
     403           0 :                 } else if (rlen == 0) {
     404           0 :                         zlog_warn("msg_read: Connection closed by peer");
     405           0 :                         return NULL;
     406           0 :                 } else if (rlen != bodylen) {
     407           0 :                         zlog_warn("msg_read: Cannot read message body!");
     408           0 :                         return NULL;
     409             :                 }
     410             :         }
     411             : 
     412             :         /* Allocate new message */
     413           0 :         msg = msg_new(hdr.msgtype, buf, ntohl(hdr.msgseq), bodylen);
     414             : 
     415           0 :         return msg;
     416             : }
     417             : 
     418           0 : int msg_write(int fd, struct msg *msg)
     419             : {
     420           0 :         uint8_t buf[OSPF_API_MAX_MSG_SIZE];
     421           0 :         uint16_t l;
     422           0 :         int wlen;
     423             : 
     424           0 :         assert(msg);
     425           0 :         assert(msg->s);
     426             : 
     427             :         /* Length of OSPF LSA payload */
     428           0 :         l = ntohs(msg->hdr.msglen);
     429           0 :         if (l > OSPF_MAX_LSA_SIZE) {
     430           0 :                 zlog_warn("%s: wrong LSA size %d", __func__, l);
     431           0 :                 return -1;
     432             :         }
     433             : 
     434             :         /* Make contiguous memory buffer for message */
     435           0 :         memcpy(buf, &msg->hdr, sizeof(struct apimsghdr));
     436           0 :         memcpy(buf + sizeof(struct apimsghdr), STREAM_DATA(msg->s), l);
     437             : 
     438             :         /* Total length of OSPF API Message */
     439           0 :         l += sizeof(struct apimsghdr);
     440           0 :         wlen = writen(fd, buf, l);
     441           0 :         if (wlen < 0) {
     442           0 :                 zlog_warn("%s: writen %s", __func__, safe_strerror(errno));
     443           0 :                 return -1;
     444           0 :         } else if (wlen == 0) {
     445           0 :                 zlog_warn("%s: Connection closed by peer", __func__);
     446           0 :                 return -1;
     447           0 :         } else if (wlen != l) {
     448           0 :                 zlog_warn("%s: Cannot write API message", __func__);
     449           0 :                 return -1;
     450             :         }
     451             :         return 0;
     452             : }
     453             : 
     454             : /* -----------------------------------------------------------
     455             :  * Specific messages
     456             :  * -----------------------------------------------------------
     457             :  */
     458             : 
     459           0 : struct msg *new_msg_register_opaque_type(uint32_t seqnum, uint8_t ltype,
     460             :                                          uint8_t otype)
     461             : {
     462           0 :         struct msg_register_opaque_type rmsg;
     463             : 
     464           0 :         rmsg.lsatype = ltype;
     465           0 :         rmsg.opaquetype = otype;
     466           0 :         memset(&rmsg.pad, 0, sizeof(rmsg.pad));
     467             : 
     468           0 :         return msg_new(MSG_REGISTER_OPAQUETYPE, &rmsg, seqnum,
     469             :                        sizeof(struct msg_register_opaque_type));
     470             : }
     471             : 
     472           0 : struct msg *new_msg_register_event(uint32_t seqnum,
     473             :                                    struct lsa_filter_type *filter)
     474             : {
     475           0 :         uint8_t buf[OSPF_API_MAX_MSG_SIZE];
     476           0 :         struct msg_register_event *emsg;
     477           0 :         unsigned int len;
     478             : 
     479           0 :         emsg = (struct msg_register_event *)buf;
     480           0 :         len = sizeof(struct msg_register_event)
     481           0 :               + filter->num_areas * sizeof(struct in_addr);
     482           0 :         emsg->filter.typemask = htons(filter->typemask);
     483           0 :         emsg->filter.origin = filter->origin;
     484           0 :         emsg->filter.num_areas = filter->num_areas;
     485           0 :         if (len > sizeof(buf))
     486             :                 len = sizeof(buf);
     487             :         /* API broken - missing memcpy to fill data */
     488           0 :         return msg_new(MSG_REGISTER_EVENT, emsg, seqnum, len);
     489             : }
     490             : 
     491           0 : struct msg *new_msg_sync_lsdb(uint32_t seqnum, struct lsa_filter_type *filter)
     492             : {
     493           0 :         uint8_t buf[OSPF_API_MAX_MSG_SIZE];
     494           0 :         struct msg_sync_lsdb *smsg;
     495           0 :         unsigned int len;
     496             : 
     497           0 :         smsg = (struct msg_sync_lsdb *)buf;
     498           0 :         len = sizeof(struct msg_sync_lsdb)
     499           0 :               + filter->num_areas * sizeof(struct in_addr);
     500           0 :         smsg->filter.typemask = htons(filter->typemask);
     501           0 :         smsg->filter.origin = filter->origin;
     502           0 :         smsg->filter.num_areas = filter->num_areas;
     503           0 :         if (len > sizeof(buf))
     504             :                 len = sizeof(buf);
     505             :         /* API broken - missing memcpy to fill data */
     506           0 :         return msg_new(MSG_SYNC_LSDB, smsg, seqnum, len);
     507             : }
     508             : 
     509             : 
     510           0 : struct msg *new_msg_originate_request(uint32_t seqnum, struct in_addr ifaddr,
     511             :                                       struct in_addr area_id,
     512             :                                       struct lsa_header *data)
     513             : {
     514           0 :         struct msg_originate_request *omsg;
     515           0 :         unsigned int omsglen;
     516           0 :         char buf[OSPF_API_MAX_MSG_SIZE];
     517           0 :         size_t off_data = offsetof(struct msg_originate_request, data);
     518           0 :         size_t data_maxs = sizeof(buf) - off_data;
     519           0 :         struct lsa_header *omsg_data = (struct lsa_header *)&buf[off_data];
     520             : 
     521           0 :         omsg = (struct msg_originate_request *)buf;
     522           0 :         omsg->ifaddr = ifaddr;
     523           0 :         omsg->area_id = area_id;
     524             : 
     525           0 :         omsglen = ntohs(data->length);
     526           0 :         if (omsglen > data_maxs)
     527             :                 omsglen = data_maxs;
     528           0 :         memcpy(omsg_data, data, omsglen);
     529           0 :         omsglen += sizeof(struct msg_originate_request)
     530             :                    - sizeof(struct lsa_header);
     531             : 
     532           0 :         return msg_new(MSG_ORIGINATE_REQUEST, omsg, seqnum, omsglen);
     533             : }
     534             : 
     535           0 : struct msg *new_msg_delete_request(uint32_t seqnum, struct in_addr addr,
     536             :                                    uint8_t lsa_type, uint8_t opaque_type,
     537             :                                    uint32_t opaque_id, uint8_t flags)
     538             : {
     539           0 :         struct msg_delete_request dmsg;
     540           0 :         dmsg.addr = addr;
     541           0 :         dmsg.lsa_type = lsa_type;
     542           0 :         dmsg.opaque_type = opaque_type;
     543           0 :         dmsg.opaque_id = htonl(opaque_id);
     544           0 :         memset(&dmsg.pad, 0, sizeof(dmsg.pad));
     545           0 :         dmsg.flags = flags;
     546             : 
     547           0 :         return msg_new(MSG_DELETE_REQUEST, &dmsg, seqnum,
     548             :                        sizeof(struct msg_delete_request));
     549             : }
     550             : 
     551             : 
     552           0 : struct msg *new_msg_reply(uint32_t seqnr, uint8_t rc)
     553             : {
     554           0 :         struct msg *msg;
     555           0 :         struct msg_reply rmsg;
     556             : 
     557             :         /* Set return code */
     558           0 :         rmsg.errcode = rc;
     559           0 :         memset(&rmsg.pad, 0, sizeof(rmsg.pad));
     560             : 
     561           0 :         msg = msg_new(MSG_REPLY, &rmsg, seqnr, sizeof(struct msg_reply));
     562             : 
     563           0 :         return msg;
     564             : }
     565             : 
     566           0 : struct msg *new_msg_ready_notify(uint32_t seqnr, uint8_t lsa_type,
     567             :                                  uint8_t opaque_type, struct in_addr addr)
     568             : {
     569           0 :         struct msg_ready_notify rmsg;
     570             : 
     571           0 :         rmsg.lsa_type = lsa_type;
     572           0 :         rmsg.opaque_type = opaque_type;
     573           0 :         memset(&rmsg.pad, 0, sizeof(rmsg.pad));
     574           0 :         rmsg.addr = addr;
     575             : 
     576           0 :         return msg_new(MSG_READY_NOTIFY, &rmsg, seqnr,
     577             :                        sizeof(struct msg_ready_notify));
     578             : }
     579             : 
     580           0 : struct msg *new_msg_new_if(uint32_t seqnr, struct in_addr ifaddr,
     581             :                            struct in_addr area_id)
     582             : {
     583           0 :         struct msg_new_if nmsg;
     584             : 
     585           0 :         nmsg.ifaddr = ifaddr;
     586           0 :         nmsg.area_id = area_id;
     587             : 
     588           0 :         return msg_new(MSG_NEW_IF, &nmsg, seqnr, sizeof(struct msg_new_if));
     589             : }
     590             : 
     591           0 : struct msg *new_msg_del_if(uint32_t seqnr, struct in_addr ifaddr)
     592             : {
     593           0 :         struct msg_del_if dmsg;
     594             : 
     595           0 :         dmsg.ifaddr = ifaddr;
     596             : 
     597           0 :         return msg_new(MSG_DEL_IF, &dmsg, seqnr, sizeof(struct msg_del_if));
     598             : }
     599             : 
     600           0 : struct msg *new_msg_ism_change(uint32_t seqnr, struct in_addr ifaddr,
     601             :                                struct in_addr area_id, uint8_t status)
     602             : {
     603           0 :         struct msg_ism_change imsg;
     604             : 
     605           0 :         imsg.ifaddr = ifaddr;
     606           0 :         imsg.area_id = area_id;
     607           0 :         imsg.status = status;
     608           0 :         memset(&imsg.pad, 0, sizeof(imsg.pad));
     609             : 
     610           0 :         return msg_new(MSG_ISM_CHANGE, &imsg, seqnr,
     611             :                        sizeof(struct msg_ism_change));
     612             : }
     613             : 
     614           0 : struct msg *new_msg_nsm_change(uint32_t seqnr, struct in_addr ifaddr,
     615             :                                struct in_addr nbraddr, struct in_addr router_id,
     616             :                                uint8_t status)
     617             : {
     618           0 :         struct msg_nsm_change nmsg;
     619             : 
     620           0 :         nmsg.ifaddr = ifaddr;
     621           0 :         nmsg.nbraddr = nbraddr;
     622           0 :         nmsg.router_id = router_id;
     623           0 :         nmsg.status = status;
     624           0 :         memset(&nmsg.pad, 0, sizeof(nmsg.pad));
     625             : 
     626           0 :         return msg_new(MSG_NSM_CHANGE, &nmsg, seqnr,
     627             :                        sizeof(struct msg_nsm_change));
     628             : }
     629             : 
     630           0 : struct msg *new_msg_lsa_change_notify(uint8_t msgtype, uint32_t seqnum,
     631             :                                       struct in_addr ifaddr,
     632             :                                       struct in_addr area_id,
     633             :                                       uint8_t is_self_originated,
     634             :                                       struct lsa_header *data)
     635             : {
     636           0 :         uint8_t buf[OSPF_API_MAX_MSG_SIZE];
     637           0 :         struct msg_lsa_change_notify *nmsg;
     638           0 :         unsigned int len;
     639           0 :         size_t off_data = offsetof(struct msg_lsa_change_notify, data);
     640           0 :         size_t data_maxs = sizeof(buf) - off_data;
     641           0 :         struct lsa_header *nmsg_data = (struct lsa_header *)&buf[off_data];
     642             : 
     643           0 :         assert(data);
     644             : 
     645           0 :         nmsg = (struct msg_lsa_change_notify *)buf;
     646           0 :         nmsg->ifaddr = ifaddr;
     647           0 :         nmsg->area_id = area_id;
     648           0 :         nmsg->is_self_originated = is_self_originated;
     649           0 :         memset(&nmsg->pad, 0, sizeof(nmsg->pad));
     650             : 
     651           0 :         len = ntohs(data->length);
     652           0 :         if (len > data_maxs)
     653             :                 len = data_maxs;
     654           0 :         memcpy(nmsg_data, data, len);
     655           0 :         len += sizeof(struct msg_lsa_change_notify) - sizeof(struct lsa_header);
     656             : 
     657           0 :         return msg_new(msgtype, nmsg, seqnum, len);
     658             : }
     659             : 
     660           0 : struct msg *new_msg_reachable_change(uint32_t seqnum, uint16_t nadd,
     661             :                                      struct in_addr *add, uint16_t nremove,
     662             :                                      struct in_addr *remove)
     663             : {
     664           0 :         uint8_t buf[OSPF_API_MAX_MSG_SIZE];
     665           0 :         struct msg_reachable_change *nmsg = (void *)buf;
     666           0 :         const uint insz = sizeof(*nmsg->router_ids);
     667           0 :         const uint nmax = (sizeof(buf) - sizeof(*nmsg)) / insz;
     668           0 :         uint len;
     669             : 
     670           0 :         if (nadd > nmax)
     671             :                 nadd = nmax;
     672           0 :         if (nremove > (nmax - nadd))
     673           0 :                 nremove = (nmax - nadd);
     674             : 
     675           0 :         if (nadd)
     676           0 :                 memcpy(nmsg->router_ids, add, nadd * insz);
     677           0 :         if (nremove)
     678           0 :                 memcpy(&nmsg->router_ids[nadd], remove, nremove * insz);
     679             : 
     680           0 :         nmsg->nadd = htons(nadd);
     681           0 :         nmsg->nremove = htons(nremove);
     682           0 :         len = sizeof(*nmsg) + insz * (nadd + nremove);
     683             : 
     684           0 :         return msg_new(MSG_REACHABLE_CHANGE, nmsg, seqnum, len);
     685             : }
     686             : 
     687           4 : struct msg *new_msg_router_id_change(uint32_t seqnum, struct in_addr router_id)
     688             : {
     689           4 :         struct msg_router_id_change rmsg = {.router_id = router_id};
     690             : 
     691           4 :         return msg_new(MSG_ROUTER_ID_CHANGE, &rmsg, seqnum,
     692             :                        sizeof(struct msg_router_id_change));
     693             : }
     694             : 
     695             : #endif /* SUPPORT_OSPF_API */

Generated by: LCOV version v1.16-topotato