📄 ospf6_message.c
字号:
if (memcmp (received->options, last_received->options, 3) != 0) return 0; if (received->ifmtu != last_received->ifmtu) return 0; if (received->bits != last_received->bits) return 0; if (received->seqnum != last_received->seqnum) return 0; return 1;}voidospf6_process_dbdesc_master (struct iovec *message, struct ospf6_neighbor *o6n){ struct ospf6_header *ospf6_header; u_int16_t length, lsa_count; struct ospf6_dbdesc *dbdesc; struct ospf6_lsa_header *lsa_header; /* 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 database description pointer */ dbdesc = (struct ospf6_dbdesc *) message[1].iov_base; switch (o6n->state) { case NBS_DOWN: case NBS_ATTEMPT: case NBS_TWOWAY: if (IS_OSPF6_DUMP_DBDESC) zlog_info ("DbDesc from %s Ignored: state less than Init", o6n->str); return; case NBS_INIT: thread_execute (master, twoway_received, o6n, 0); if (o6n->state != NBS_EXSTART) { if (IS_OSPF6_DUMP_DBDESC) zlog_info ("DbDesc from %s Ignored: state less than ExStart", o6n->str); return; } /* else fall through to ExStart */ case NBS_EXSTART: if (DDBIT_IS_SLAVE (dbdesc->bits) && !DDBIT_IS_INITIAL (dbdesc->bits) && ntohl (dbdesc->seqnum) == o6n->dbdesc_seqnum) { ospf6_neighbor_dbex_init (o6n); if (o6n->thread_rxmt_dbdesc) thread_cancel (o6n->thread_rxmt_dbdesc); o6n->thread_rxmt_dbdesc = (struct thread *) NULL; thread_add_event (master, negotiation_done, o6n, 0); } else { if (IS_OSPF6_DUMP_DBDESC) zlog_info (" negotiation failed with %s", o6n->str); return; } break; case NBS_EXCHANGE: /* duplicate dbdesc dropped by master */ if (!memcmp (dbdesc, &o6n->last_dd, sizeof (struct ospf6_dbdesc))) { if (IS_OSPF6_DUMP_DBDESC) zlog_info (" duplicate dbdesc, drop"); return; } /* check Initialize bit and Master/Slave bit */ if (DDBIT_IS_INITIAL (dbdesc->bits)) { if (IS_OSPF6_DUMP_DBDESC) zlog_info ("Initialize bit mismatch"); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } if (DDBIT_IS_MASTER (dbdesc->bits)) { if (IS_OSPF6_DUMP_DBDESC) zlog_info ("Master/Slave bit mismatch"); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } /* dbdesc option check */ if (memcmp (dbdesc->options, o6n->last_dd.options, sizeof (dbdesc->options))) { if (IS_OSPF6_DUMP_DBDESC) zlog_info ("dbdesc option field changed"); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } /* dbdesc sequence number check */ if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum) { if (IS_OSPF6_DUMP_DBDESC) zlog_warn ("*** dbdesc seqnumber mismatch: %d expected", o6n->dbdesc_seqnum); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } break; case NBS_LOADING: case NBS_FULL: /* duplicate dbdesc dropped by master */ if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd)) { if (IS_OSPF6_DUMP_DBDESC) zlog_info (" duplicate dbdesc, drop"); return; } else { if (IS_OSPF6_DUMP_DBDESC) zlog_info (" not duplicate dbdesc in state %s", ospf6_neighbor_state_string[o6n->state]); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } break; /* not reached */ default: assert (0); break; /* not reached */ } /* process LSA headers */ lsa_count = 0; for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1); (char *)(lsa_header + 1) <= (char *)dbdesc + length; lsa_header++) { if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0) { thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } lsa_count ++; } /* increment dbdesc seqnum */ o6n->dbdesc_seqnum++; /* cancel transmission/retransmission thread */ if (o6n->thread_send_dbdesc) thread_cancel (o6n->thread_send_dbdesc); o6n->thread_send_dbdesc = (struct thread *) NULL; if (o6n->thread_rxmt_dbdesc) thread_cancel (o6n->thread_rxmt_dbdesc); o6n->thread_rxmt_dbdesc = (struct thread *) NULL; /* more bit check */ if (!DD_IS_MBIT_SET (dbdesc->bits) && !DD_IS_MBIT_SET (o6n->dbdesc_bits)) thread_add_event (master, exchange_done, o6n, 0); else o6n->thread_send_dbdesc = thread_add_event (master, ospf6_send_dbdesc, o6n, 0); /* save last received dbdesc */ memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc)); /* statistics */ o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count; return;}voidospf6_process_dbdesc_slave (struct iovec *message, struct ospf6_neighbor *o6n){ struct ospf6_header *ospf6_header; u_int16_t length, lsa_count; struct ospf6_dbdesc *dbdesc; struct ospf6_lsa_header *lsa_header; /* 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 database description pointer */ dbdesc = (struct ospf6_dbdesc *) message[1].iov_base; switch (o6n->state) { case NBS_DOWN: case NBS_ATTEMPT: case NBS_TWOWAY: return; case NBS_INIT: thread_execute (master, twoway_received, o6n, 0); if (o6n->state != NBS_EXSTART) { return; } /* else fall through to ExStart */ case NBS_EXSTART: if (DD_IS_IBIT_SET (dbdesc->bits) && DD_IS_MBIT_SET (dbdesc->bits) && DD_IS_MSBIT_SET (dbdesc->bits)) { /* Master/Slave bit set to slave */ DD_MSBIT_CLEAR (o6n->dbdesc_bits); /* Initialize bit clear */ DD_IBIT_CLEAR (o6n->dbdesc_bits); /* sequence number set to master's */ o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum); ospf6_neighbor_dbex_init (o6n); if (o6n->thread_rxmt_dbdesc) thread_cancel (o6n->thread_rxmt_dbdesc); o6n->thread_rxmt_dbdesc = (struct thread *) NULL; thread_add_event (master, negotiation_done, o6n, 0); } else { if (IS_OSPF6_DUMP_DBDESC) zlog_info ("negotiation failed"); return; } break; case NBS_EXCHANGE: /* duplicate dbdesc dropped by master */ if (!memcmp (dbdesc, &o6n->last_dd, sizeof (struct ospf6_dbdesc))) { if (IS_OSPF6_DUMP_DBDESC) zlog_info (" duplicate dbdesc, retransmit dbdesc"); if (o6n->thread_rxmt_dbdesc) thread_cancel (o6n->thread_rxmt_dbdesc); o6n->thread_rxmt_dbdesc = thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0); return; } /* check Initialize bit and Master/Slave bit */ if (DDBIT_IS_INITIAL (dbdesc->bits)) { if (IS_OSPF6_DUMP_DBDESC) zlog_info ("Initialize bit mismatch"); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } if (DDBIT_IS_SLAVE (dbdesc->bits)) { if (IS_OSPF6_DUMP_DBDESC) zlog_info ("Master/Slave bit mismatch"); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } /* dbdesc option check */ if (memcmp (dbdesc->options, o6n->last_dd.options, sizeof (dbdesc->options))) { if (IS_OSPF6_DUMP_DBDESC) zlog_info ("dbdesc option field changed"); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } /* dbdesc sequence number check */ if (ntohl (dbdesc->seqnum) != o6n->dbdesc_seqnum + 1) { if (IS_OSPF6_DUMP_DBDESC) zlog_warn ("*** dbdesc seqnumber mismatch: %d expected", o6n->dbdesc_seqnum + 1); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } break; case NBS_LOADING: case NBS_FULL: /* duplicate dbdesc cause slave to retransmit */ if (ospf6_dbdesc_is_duplicate (dbdesc, &o6n->last_dd)) { if (IS_OSPF6_DUMP_DBDESC) zlog_info (" duplicate dbdesc, retransmit"); if (o6n->thread_rxmt_dbdesc) thread_cancel (o6n->thread_rxmt_dbdesc); o6n->thread_rxmt_dbdesc = thread_add_event (master, ospf6_send_dbdesc_rxmt, o6n, 0); return; } else { if (IS_OSPF6_DUMP_DBDESC) zlog_info (" not duplicate dbdesc in state %s", ospf6_neighbor_state_string[o6n->state]); thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } break; /* not reached */ default: assert (0); break; /* not reached */ } /* process LSA headers */ lsa_count = 0; for (lsa_header = (struct ospf6_lsa_header *) (dbdesc + 1); (char *)(lsa_header + 1) <= (char *)dbdesc + length; lsa_header++) { if (ospf6_dbex_check_dbdesc_lsa_header (lsa_header, o6n) < 0) { thread_add_event (master, seqnumber_mismatch, o6n, 0); return; } lsa_count ++; } /* set dbdesc seqnum to master's */ o6n->dbdesc_seqnum = ntohl (dbdesc->seqnum); if (o6n->thread_send_dbdesc) thread_cancel (o6n->thread_send_dbdesc); o6n->thread_send_dbdesc = thread_add_event (master, ospf6_send_dbdesc, o6n, 0); /* save last received dbdesc */ memcpy (&o6n->last_dd, dbdesc, sizeof (struct ospf6_dbdesc)); /* statistics */ o6n->lsa_receive[OSPF6_MESSAGE_TYPE_DBDESC] += lsa_count; return;}voidospf6_process_dbdesc (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_neighbor *o6n; struct ospf6_dbdesc *dbdesc; int Im_master = 0; /* 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 database description pointer */ dbdesc = (struct ospf6_dbdesc *) message[1].iov_base; /* find neighbor. if cannot be found, reject this message */ o6n = ospf6_neighbor_lookup (router_id, o6i); if (!o6n) { if (IS_OSPF6_DUMP_DBDESC) zlog_info ("neighbor not found, reject"); return; } if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) { if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) zlog_info ("From Secondary I/F of the neighbor: ignore"); return; } /* interface mtu check */ /* xxx */ /* check am I master */ Im_master = ospf6_dbdesc_is_master (o6n); if (Im_master < 0) { return; /* can't decide which is master, return */ } if (Im_master) ospf6_process_dbdesc_master (message, o6n); else ospf6_process_dbdesc_slave (message, o6n); return;}voidospf6_process_lsreq (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_neighbor *o6n; struct ospf6_lsreq *lsreq; struct iovec response[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_lsa *lsa; unsigned long lsanum = 0; struct ospf6_lsupdate lsupdate; char buf_id[16], buf_router[16], buf_type[16]; /* 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); /* find neighbor. if cannot be found, reject this message */ o6n = ospf6_neighbor_lookup (router_id, o6i); if (!o6n) { if (IS_OSPF6_DUMP_LSREQ) zlog_info (" neighbor not found, reject"); return; } if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) { if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) zlog_info ("From Secondary I/F of the neighbor: ignore"); return; } /* In states other than ExChange, Loading, or Full, the packet should be ignored. */ if (o6n->state != NBS_EXCHANGE && o6n->state != NBS_LOADING && o6n->state != NBS_FULL) { if (IS_OSPF6_DUMP_LSREQ) zlog_info (" neighbor state less than Exchange, reject"); return; } /* Initialize response LSUpdate packet */ OSPF6_MESSAGE_CLEAR (response); memset (&lsupdate, 0, sizeof (struct ospf6_lsupdate)); OSPF6_MESSAGE_ATTACH (response, &lsupdate, sizeof (struct ospf6_lsupdate)); /* process each request */ lsanum = 0; for (lsreq = (struct ospf6_lsreq *) message[1].iov_base; (char *)(lsreq + 1) <= (char *)(message[1].iov_base + length); lsreq++) { inet_ntop (AF_INET, &lsreq->adv_router, buf_router, sizeof (buf_router)); inet_ntop (AF_INET, &lsreq->id, buf_id, sizeof (buf_id)); /* find instance of database copy */ lsa = ospf6_lsdb_lookup (lsreq->type, lsreq->id, lsreq->adv_router, ospf6_lsa_get_scope (lsreq->type, o6i)); if (!lsa) { if (IS_OSPF6_DUMP_LSREQ) zlog_info ("BadLSReq: %s requests [%s ID=%s Adv=%s] not found", o6n->str, ospf6_lsa_type_string (lsreq->type, buf_type, sizeof (buf_type)), buf_id, buf_router); thread_add_event (master, bad_lsreq, o6n, 0); return; } /* I/F MTU check */ if (sizeof (struct ospf6_header) + sizeof (struct ospf6_lsupdate) + iov_totallen (response) + ntohs (lsa->header->length) > o6i->ifmtu) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -