📄 ospf6_message.c
字号:
/* * Copyright (C) 1999 Yasuhiro Ohara * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING. If not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include "ospf6d.h"intis_ospf6_message_dump (u_char type){ if (type > OSPF6_MESSAGE_TYPE_LSACK) type = OSPF6_MESSAGE_TYPE_UNKNOWN; switch (type) { case OSPF6_MESSAGE_TYPE_UNKNOWN: return 1; break; case OSPF6_MESSAGE_TYPE_HELLO: if (IS_OSPF6_DUMP_HELLO) return 1; break; case OSPF6_MESSAGE_TYPE_DBDESC: if (IS_OSPF6_DUMP_DBDESC) return 1; break; case OSPF6_MESSAGE_TYPE_LSREQ: if (IS_OSPF6_DUMP_LSREQ) return 1; break; case OSPF6_MESSAGE_TYPE_LSUPDATE: if (IS_OSPF6_DUMP_LSUPDATE) return 1; break; case OSPF6_MESSAGE_TYPE_LSACK: if (IS_OSPF6_DUMP_LSACK) return 1; break; default: break; } return 0;}#define IS_OSPF6_DUMP_MESSAGE(x) (is_ospf6_message_dump(x))char *ospf6_message_type_string[] ={ "Unknown", "Hello", "DbDesc", "LSReq", "LSUpdate", "LSAck", NULL};voidospf6_message_log_lsa_header (struct ospf6_lsa_header *lsa_header){ char buf_id[16], buf_router[16], typebuf[32]; inet_ntop (AF_INET, &lsa_header->advrtr, buf_router, sizeof (buf_router)); inet_ntop (AF_INET, &lsa_header->ls_id, buf_id, sizeof (buf_id)); zlog_info (" [%s ID=%s Adv=%s]", ospf6_lsa_type_string (lsa_header->type, typebuf, sizeof (typebuf)), buf_id, buf_router); zlog_info (" Age=%hu SeqNum=%#lx Cksum=%#hx Len=%hu", ntohs (lsa_header->age), (u_long)ntohl (lsa_header->seqnum), ntohs (lsa_header->checksum), ntohs (lsa_header->length));}static voidospf6_message_log_unknown (struct iovec *message){ zlog_info ("Message: Unknown");}static voidospf6_message_log_hello (struct iovec *message){ struct ospf6_header *ospf6_header; u_int16_t length_left; struct ospf6_hello *hello; char dr_str[16], bdr_str[16]; char *start, *end, *current; /* calculate length */ ospf6_header = (struct ospf6_header *) message[0].iov_base; length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? length_left : iov_totallen (message) - sizeof (struct ospf6_header)); hello = (struct ospf6_hello *) message[1].iov_base; inet_ntop (AF_INET, &hello->dr, dr_str, sizeof (dr_str)); inet_ntop (AF_INET, &hello->bdr, bdr_str, sizeof (bdr_str)); zlog_info (" IFID:%ld Priority:%d Option:%s", (u_long)ntohl (hello->interface_id), hello->rtr_pri, "xxx"); zlog_info (" HelloInterval:%hu Deadinterval:%hu", ntohs (hello->hello_interval), ntohs (hello->router_dead_interval)); zlog_info (" DR:%s BDR:%s", dr_str, bdr_str); start = (char *) (hello + 1); if (start >= (char *) message[1].iov_base + message[1].iov_len) start = message[2].iov_base; end = (char *) start + (length_left - sizeof (struct ospf6_hello)); for (current = start; current < end; current += sizeof (u_int32_t)) { char neighbor[16]; inet_ntop (AF_INET, current, neighbor, sizeof (neighbor)); zlog_info (" Neighbor: %s", neighbor); }}static voidospf6_message_log_dbdesc (struct iovec *message){ struct ospf6_header *ospf6_header; u_int16_t length_left; struct ospf6_dbdesc *dbdesc; int i; char buffer[16]; struct ospf6_lsa_header *lsa_header; /* calculate length */ ospf6_header = (struct ospf6_header *) message[0].iov_base; length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? length_left : iov_totallen (message) - sizeof (struct ospf6_header)); dbdesc = (struct ospf6_dbdesc *) message[1].iov_base; ospf6_options_string (dbdesc->options, buffer, sizeof (buffer)); zlog_info (" Option:%s IFMTU:%hu", buffer, ntohs (dbdesc->ifmtu)); zlog_info (" Bits:%s%s%s SeqNum:%#lx", (DD_IS_IBIT_SET (dbdesc->bits) ? "I" : "-"), (DD_IS_MBIT_SET (dbdesc->bits) ? "M" : "-"), (DD_IS_MSBIT_SET (dbdesc->bits) ? "m" : "s"), (u_long)ntohl (dbdesc->seqnum)); for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1); (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + message[1].iov_len) && (char *)(lsa_header + 1) <= (char *)dbdesc + length_left; lsa_header++) ospf6_message_log_lsa_header (lsa_header); length_left -= message[1].iov_len; for (i = 2; message[i].iov_base; i++) { for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base; (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + message[i].iov_len) && (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left); lsa_header++) ospf6_message_log_lsa_header (lsa_header); length_left -= message[i].iov_len; }}static voidospf6_message_log_lsreq (struct iovec *message){ struct ospf6_header *ospf6_header; u_int16_t length_left; int i; struct ospf6_lsreq *lsreq; char buf_router[16], buf_id[16], buf_type[16]; /* calculate length */ ospf6_header = (struct ospf6_header *) message[0].iov_base; length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? length_left : iov_totallen (message) - sizeof (struct ospf6_header)); for (i = 1; message[i].iov_base; i++) { for (lsreq = (struct ospf6_lsreq *) message[i].iov_base; (char *)(lsreq + 1) <= (char *) (message[i].iov_base + message[i].iov_len) && (char *)(lsreq + 1) <= (char *) (message[i].iov_base + length_left); lsreq++) { inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router)); inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id)); zlog_info (" [%s ID=%s Adv=%s]", ospf6_lsa_type_string (lsreq->type, buf_type, sizeof (buf_type)), buf_id, buf_router); } length_left -= message[i].iov_len; }}static voidospf6_message_log_lsupdate (struct iovec *message){ struct ospf6_header *ospf6_header; u_int16_t length_left; int i, lsanum; struct ospf6_lsupdate *lsupdate; struct ospf6_lsa_header *lsa_header; /* calculate length */ ospf6_header = (struct ospf6_header *) message[0].iov_base; length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? length_left : iov_totallen (message) - sizeof (struct ospf6_header)); lsupdate = (struct ospf6_lsupdate *) message[1].iov_base; lsanum = ntohl (lsupdate->lsupdate_num); zlog_info (" Number of LSA: #%d", lsanum); for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1); (char *)lsa_header < (char *)(message[1].iov_base + message[1].iov_len) && (char *)lsa_header < (char *)(message[1].iov_base + length_left); lsa_header = OSPF6_LSA_NEXT (lsa_header)) ospf6_message_log_lsa_header (lsa_header); length_left -= message[1].iov_len; for (i = 2; message[i].iov_base; i++) { for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base; (char *)lsa_header < (char *) (message[i].iov_base + message[i].iov_len) && (char *)lsa_header < (char *) (message[i].iov_base + length_left); lsa_header = OSPF6_LSA_NEXT (lsa_header)) ospf6_message_log_lsa_header (lsa_header); length_left -= message[i].iov_len; }}static voidospf6_message_log_lsack (struct iovec *message){ struct ospf6_header *ospf6_header; u_int16_t length_left; struct ospf6_lsa_header *lsa_header; int i; /* calculate length */ ospf6_header = (struct ospf6_header *) message[0].iov_base; length_left = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); length_left = (length_left < iov_totallen (message) - sizeof (struct ospf6_header) ? length_left : iov_totallen (message) - sizeof (struct ospf6_header)); for (i = 1; message[i].iov_base; i++) { for (lsa_header = (struct ospf6_lsa_header *) message[i].iov_base; (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + message[i].iov_len) && (char *)(lsa_header + 1) <= (char *) (message[i].iov_base + length_left); lsa_header++) ospf6_message_log_lsa_header (lsa_header); length_left -= message[i].iov_len; }}struct { void (*message_log) (struct iovec *);} ospf6_message_log_body [] ={ {ospf6_message_log_unknown}, {ospf6_message_log_hello}, {ospf6_message_log_dbdesc}, {ospf6_message_log_lsreq}, {ospf6_message_log_lsupdate}, {ospf6_message_log_lsack},};static voidospf6_message_log (struct iovec *message){ struct ospf6_header *o6h; char router_id[16], area_id[16]; u_char type; assert (message[0].iov_len == sizeof (struct ospf6_header)); o6h = (struct ospf6_header *) message[0].iov_base; inet_ntop (AF_INET, &o6h->router_id, router_id, sizeof (router_id)); inet_ntop (AF_INET, &o6h->area_id, area_id, sizeof (area_id)); zlog_info (" OSPFv%d Type:%d Len:%hu RouterID:%s", o6h->version, o6h->type, ntohs (o6h->len), router_id); zlog_info (" AreaID:%s Cksum:%hx InstanceID:%d", area_id, ntohs (o6h->cksum), o6h->instance_id); type = (OSPF6_MESSAGE_TYPE_UNKNOWN < o6h->type && o6h->type <= OSPF6_MESSAGE_TYPE_LSACK ? o6h->type : OSPF6_MESSAGE_TYPE_UNKNOWN); (* ospf6_message_log_body[type].message_log) (&message[0]);}intospf6_opt_is_mismatch (unsigned char opt, char *options1, char *options2){ return (OSPF6_OPT_ISSET (options1, opt) ^ OSPF6_OPT_ISSET (options2, opt));}voidospf6_process_unknown (struct iovec *message, struct in6_addr *src, struct in6_addr *dst, struct ospf6_interface *o6i, u_int32_t router_id){ zlog_warn ("unknown message type, drop");}voidospf6_process_hello (struct iovec *message, struct in6_addr *src, struct in6_addr *dst, struct ospf6_interface *o6i, u_int32_t router_id){ struct ospf6_header *ospf6_header; u_int16_t length; struct ospf6_hello *hello; char changes = 0;#define CHANGE_RTRPRI (1 << 0)#define CHANGE_DR (1 << 1)#define CHANGE_BDR (1 << 2) int twoway = 0, backupseen = 0, nbchange = 0; u_int32_t *router_id_ptr; int i, seenrtrnum = 0, router_id_space = 0; char strbuf[64]; struct ospf6_neighbor *o6n = NULL; /* assert interface */ assert (o6i); /* caluculate length */ ospf6_header = (struct ospf6_header *) message[0].iov_base; length = ntohs (ospf6_header->len) - sizeof (struct ospf6_header); length = (length < message[1].iov_len ? length : message[1].iov_len); /* set hello pointer */ hello = (struct ospf6_hello *) message[1].iov_base; /* find neighbor. if cannot be found, create */ o6n = ospf6_neighbor_lookup (router_id, o6i); if (!o6n) { o6n = ospf6_neighbor_create (router_id, o6i); o6n->ifid = ntohl (hello->interface_id); o6n->prevdr = o6n->dr = hello->dr; o6n->prevbdr = o6n->bdr = hello->bdr; o6n->priority = hello->rtr_pri; memcpy (&o6n->hisaddr, src, sizeof (struct in6_addr)); } /* HelloInterval check */ if (ntohs (hello->hello_interval) != o6i->hello_interval) { zlog_warn ("HelloInterval mismatch with %s", o6n->str); return; } /* RouterDeadInterval check */ if (ntohs (hello->router_dead_interval) != o6i->dead_interval) { zlog_warn ("RouterDeadInterval mismatch with %s", o6n->str); return; } /* check options */ /* Ebit */ if (ospf6_opt_is_mismatch (OSPF6_OPT_E, hello->options, o6i->area->options)) { zlog_warn ("Ebit mismatch with %s", o6n->str); return; } /* RouterPriority set */ if (o6n->priority != hello->rtr_pri) { o6n->priority = hello->rtr_pri; if (IS_OSPF6_DUMP_HELLO) zlog_info ("%s: RouterPriority changed", o6n->str); changes |= CHANGE_RTRPRI; } /* DR set */ if (o6n->dr != hello->dr) { /* save previous dr, set current */ o6n->prevdr = o6n->dr; o6n->dr = hello->dr; inet_ntop (AF_INET, &o6n->dr, strbuf, sizeof (strbuf)); if (IS_OSPF6_DUMP_HELLO) zlog_info ("%s declare %s as DR", o6n->str, strbuf); changes |= CHANGE_DR; } /* BDR set */ if (o6n->bdr != hello->bdr) { /* save previous bdr, set current */ o6n->prevbdr = o6n->bdr; o6n->bdr = hello->bdr; inet_ntop (AF_INET, &o6n->bdr, strbuf, sizeof (strbuf)); if (IS_OSPF6_DUMP_HELLO) zlog_info ("%s declare %s as BDR", o6n->str, strbuf); changes |= CHANGE_BDR; } /* TwoWay check */ router_id_space = length - sizeof (struct ospf6_hello); seenrtrnum = router_id_space / sizeof (u_int32_t); router_id_ptr = (u_int32_t *) (hello + 1); for (i = 0; i < seenrtrnum; i++) { if (*router_id_ptr == o6i->area->ospf6->router_id) twoway++; router_id_ptr++; } /* execute neighbor events */ thread_execute (master, hello_received, o6n, 0); if (twoway) thread_execute (master, twoway_received, o6n, 0); else thread_execute (master, oneway_received, o6n, 0); /* BackupSeen check */ if (o6i->state == IFS_WAITING) { if (hello->dr == hello->bdr && hello->dr == o6n->router_id) zlog_warn ("*** DR Election of %s is illegal", o6n->str); if (hello->bdr == o6n->router_id) backupseen++; else if (hello->dr == o6n->router_id && hello->bdr == 0) backupseen++; } /* NeighborChange check */ if (changes & CHANGE_RTRPRI) nbchange++; if (changes & CHANGE_DR) if (o6n->prevdr == o6n->router_id || o6n->dr == o6n->router_id) nbchange++; if (changes & CHANGE_BDR) if (o6n->prevbdr == o6n->router_id || o6n->bdr == o6n->router_id) nbchange++; /* schedule interface events */ if (backupseen) thread_add_event (master, backup_seen, o6i, 0); if (nbchange) thread_add_event (master, neighbor_change, o6i, 0); return;}intospf6_dbdesc_is_master (struct ospf6_neighbor *o6n){ char buf[128]; if (o6n->router_id == ospf6->router_id) { inet_ntop (AF_INET6, &o6n->hisaddr, buf, sizeof (buf)); zlog_warn ("Message: Neighbor router-id conflicts: %s: %s", o6n->str, buf); return -1; } else if (ntohl (o6n->router_id) > ntohl (ospf6->router_id)) return 0; return 1;}intospf6_dbdesc_is_duplicate (struct ospf6_dbdesc *received, struct ospf6_dbdesc *last_received){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -