📄 ospf6_message.c
字号:
OSPF6_MESSAGE_ATTACH (response, lsa->header, ntohs (lsa->header->length)); lsanum++; } /* send response LSUpdate to this request */ if (lsanum) { lsupdate.lsupdate_num = htonl (lsanum); ospf6_message_send (OSPF6_MESSAGE_TYPE_LSUPDATE, response, &o6n->hisaddr, o6i->if_id); } /* statistics */ o6n->lsa_receive[OSPF6_MESSAGE_TYPE_LSREQ] += length / sizeof (struct ospf6_lsreq);}voidospf6_process_lsupdate (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_lsupdate *lsupdate; struct ospf6_neighbor *o6n; unsigned long lsanum; struct ospf6_lsa_header *lsa_header; /* 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_LSUPDATE) 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; } /* if neighbor state less than ExChange, reject this message */ if (o6n->state < NBS_EXCHANGE) { if (IS_OSPF6_DUMP_LSUPDATE) zlog_info (" neighbor state less than Exchange, reject"); return; } /* set linkstate update pointer */ lsupdate = (struct ospf6_lsupdate *) message[1].iov_base; /* save linkstate update info */ lsanum = ntohl (lsupdate->lsupdate_num); /* statistics */ o6n->ospf6_stat_received_lsa += lsanum; o6n->ospf6_stat_received_lsupdate++; /* RFC2328 Section 10.9: When the neighbor responds to these requests with the proper Link State Update packet(s), the Link state request list is truncated and a new Link State Request packet is sent. */ /* process LSAs */ for (lsa_header = (struct ospf6_lsa_header *) (lsupdate + 1); lsanum && (char *)lsa_header < (char *)lsupdate + length; lsanum--) { ospf6_dbex_receive_lsa (lsa_header, o6n); lsa_header = OSPF6_LSA_NEXT (lsa_header); } /* send new Link State Request packet if this LS Update packet can be recognized as a response to our previous LS request */ if (! IN6_IS_ADDR_MULTICAST(dst) && (o6n->state == NBS_EXCHANGE || o6n->state == NBS_LOADING)) thread_add_event (master, ospf6_send_lsreq, o6n, 0); return;}voidospf6_process_lsack (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_lsa_header *lsa_header; struct ospf6_lsa *lsa, *copy, *rem; /* 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_LSACK) zlog_info ("LSACK: neighbor not found, reject"); return; } if (memcmp (src, &o6n->hisaddr, sizeof (struct in6_addr))) { if (IS_OSPF6_DUMP_LSACK) zlog_info ("LSACK: From Secondary I/F of the neighbor: ignore"); return; } /* if neighbor state less than ExChange, reject this message */ if (o6n->state < NBS_EXCHANGE) { if (IS_OSPF6_DUMP_LSACK) zlog_info ("LSACK: neighbor state less than Exchange, reject"); return; } /* process each LSA header */ for (lsa_header = (struct ospf6_lsa_header *) message[1].iov_base; (char *)(lsa_header + 1) <= (char *)(message[1].iov_base + length); lsa_header++) { /* find database copy */ copy = ospf6_lsdb_lookup (lsa_header->type, lsa_header->ls_id, lsa_header->advrtr, ospf6_lsa_get_scope (lsa_header->type, o6i)); /* if no database copy */ if (!copy) { if (IS_OSPF6_DUMP_LSACK) zlog_info ("LSACK: no database copy, ignore"); continue; } /* if not on his retrans list */ rem = ospf6_lsdb_lookup_lsdb (copy->header->type, copy->header->id, copy->header->adv_router, o6n->retrans_list); if (rem == NULL) { if (IS_OSPF6_DUMP_LSACK) zlog_info ("LSACK: not on %s's retranslist, ignore", o6n->str); continue; } /* create temporary LSA from Ack message */ lsa = ospf6_lsa_summary_create ((struct ospf6_lsa_header__ *) lsa_header); /* if the same instance, remove from retrans list. else, log and ignore */ if (ospf6_lsa_check_recent (lsa, copy) == 0) ospf6_neighbor_retrans_remove (rem, o6n); else { /* Log the questionable acknowledgement, and examine the next one. */ zlog_info ("LSACK: questionable acknowledge: %s", copy->str); zlog_info ("LSACK: received: seq: %#x age: %hu", ntohl (lsa->header->seqnum), ntohs (lsa->header->age)); zlog_info ("LSACK: instance: seq: %#x age: %hu", ntohl (copy->header->seqnum), ospf6_lsa_age_current (copy)); } /* release temporary LSA from Ack message */ ospf6_lsa_delete (lsa); } ospf6_maxage_remover (); return;}struct { void (*process) (struct iovec *, struct in6_addr *, struct in6_addr *, struct ospf6_interface *, u_int32_t);} ospf6_message_process_type [] ={ {ospf6_process_unknown}, {ospf6_process_hello}, {ospf6_process_dbdesc}, {ospf6_process_lsreq}, {ospf6_process_lsupdate}, {ospf6_process_lsack}};/* process ospf6 protocol header. then, call next process function for each message type */static void ospf6_message_process (struct iovec *message, struct in6_addr *src, struct in6_addr *dst, struct ospf6_interface *o6i){ struct ospf6_header *ospf6_header = NULL; u_char type; u_int32_t router_id; char srcname[64]; assert (o6i); assert (src); assert (dst); /* set ospf6_hdr pointer to head of buffer */ ospf6_header = (struct ospf6_header *) message[0].iov_base; /* version check */ if (ospf6_header->version != OSPF6_VERSION) { if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) zlog_info ("version mismatch, drop"); return; } /* area id check */ if (ospf6_header->area_id != o6i->area->area_id) { if (ospf6_header->area_id == 0) { if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) zlog_info ("virtual link not yet, drop"); return; } if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) zlog_info ("area id mismatch, drop"); return; } /* instance id check */ if (ospf6_header->instance_id != o6i->instance_id) { if (IS_OSPF6_DUMP_MESSAGE (ospf6_header->type)) zlog_info ("instance id mismatch, drop"); return; } /* message type check */ type = (ospf6_header->type >= OSPF6_MESSAGE_TYPE_MAX ? OSPF6_MESSAGE_TYPE_UNKNOWN : ospf6_header->type); /* log */ if (IS_OSPF6_DUMP_MESSAGE (type)) { char srcname[64], dstname[64]; inet_ntop (AF_INET6, dst, dstname, sizeof (dstname)); inet_ntop (AF_INET6, src, srcname, sizeof (srcname)); zlog_info ("Receive %s on %s", ospf6_message_type_string[type], o6i->interface->name); zlog_info (" %s -> %s", srcname, dstname); ospf6_message_log (message); } /* router id check */ router_id = ospf6_header->router_id; if (ospf6_header->router_id == o6i->area->ospf6->router_id) { inet_ntop (AF_INET6, src, srcname, sizeof (srcname)); zlog_warn ("*** Router-ID mismatch: from %s on %s", srcname, o6i->interface->name); return; } /* octet statistics relies on some asumption: on ethernet, no IPv6 Extention header, etc */#define OSPF6_IP6_HEADER_SIZE 40#define OSPF6_ETHER_HEADER_SIZE 14 o6i->message_stat[type].recv++; o6i->message_stat[type].recv_octet += ntohs (ospf6_header->len) + OSPF6_IP6_HEADER_SIZE + OSPF6_ETHER_HEADER_SIZE; /* futher process */ (*ospf6_message_process_type[type].process) (&message[0], src, dst, o6i, router_id); return;}intospf6_receive (struct thread *thread){ int sockfd; struct in6_addr src, dst; unsigned int ifindex; struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_header ospf6_header; char buffer[OSPF6_MESSAGE_RECEIVE_BUFSIZE]; struct ospf6_interface *o6i; unsigned char type; /* get socket */ sockfd = THREAD_FD (thread); /* add next read thread */ thread_add_read (master, ospf6_receive, NULL, sockfd); /* initialize */ OSPF6_MESSAGE_CLEAR (message); memset (&ospf6_header, 0, sizeof (struct ospf6_header)); OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header)); OSPF6_MESSAGE_ATTACH (message, buffer, OSPF6_MESSAGE_RECEIVE_BUFSIZE); /* receive message */ ospf6_recvmsg (&src, &dst, &ifindex, message); type = (OSPF6_MESSAGE_TYPE_UNKNOWN < ospf6_header.type && ospf6_header.type <= OSPF6_MESSAGE_TYPE_LSACK ? ospf6_header.type : OSPF6_MESSAGE_TYPE_UNKNOWN); o6i = ospf6_interface_lookup_by_index (ifindex); if (!o6i || !o6i->area) { //zlog_warn ("*** received interface ospf6 disabled"); return 0; } /* if not passive, process message */ if (! CHECK_FLAG (o6i->flag, OSPF6_INTERFACE_FLAG_PASSIVE)) ospf6_message_process (message, &src, &dst, o6i); else if (IS_OSPF6_DUMP_MESSAGE (type)) zlog_info ("Ignore message on passive interface %s", o6i->interface->name); return 0;}/* send section */intospf6_message_length (struct iovec *message){ int i, length = 0; for (i = 0; i < OSPF6_MESSAGE_IOVEC_SIZE; i++) { if (message[i].iov_base == NULL && message[i].iov_len == 0) break; length += message[i].iov_len; } return length;}#define OSPF6_MESSAGE_LENGTH(msg) \(ospf6_message_length (msg))voidospf6_message_send (unsigned char type, struct iovec *msg, struct in6_addr *dst, u_int ifindex){ struct ospf6_interface *o6i; struct ospf6_header ospf6_header; char dst_name[64], src_name[64]; struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; int msg_len; /* ospf6 interface lookup */ o6i = ospf6_interface_lookup_by_index (ifindex); assert (o6i); msg_len = OSPF6_MESSAGE_LENGTH (msg); /* I/F MTU check */#if 0 if (msg_len + sizeof (struct ospf6_header) >= o6i->interface->mtu)#else if (msg_len + sizeof (struct ospf6_header) >= o6i->ifmtu)#endif { /* If Interface MTU is 0, save the case since zebra had been failed to get MTU from Kernel */ if (o6i->interface->mtu != 0) { zlog_warn ("Message: Send failed on %s: exceeds I/F MTU", o6i->interface->name); zlog_warn ("Message: while sending %s: Len:%d MTU:%d", ospf6_message_type_string[type], msg_len + sizeof (struct ospf6_header), o6i->ifmtu); return; } else { zlog_warn ("Message: I/F MTU check ignored on %s", o6i->interface->name); } } /* Initialize */ OSPF6_MESSAGE_CLEAR (message); /* set OSPF header */ memset (&ospf6_header, 0, sizeof (ospf6_header)); ospf6_header.version = OSPF6_VERSION; ospf6_header.type = type; ospf6_header.len = htons (msg_len + sizeof (struct ospf6_header)); ospf6_header.router_id = ospf6->router_id; ospf6_header.area_id = o6i->area->area_id; /* checksum is calculated by kernel */ ospf6_header.instance_id = o6i->instance_id; ospf6_header.reserved = 0; OSPF6_MESSAGE_ATTACH (message, &ospf6_header, sizeof (struct ospf6_header)); /* Attach rest to message */ OSPF6_MESSAGE_JOIN (message, msg); /* statistics */ if (type >= OSPF6_MESSAGE_TYPE_MAX) type = OSPF6_MESSAGE_TYPE_UNKNOWN; o6i->message_stat[type].send++; o6i->message_stat[type].send_octet += ntohs (ospf6_header.len); /* log */ if (IS_OSPF6_DUMP_MESSAGE (type)) { inet_ntop (AF_INET6, dst, dst_name, sizeof (dst_name)); if (o6i->lladdr) inet_ntop (AF_INET6, o6i->lladdr, src_name, sizeof (src_name)); else memcpy (src_name, "Unknown", sizeof (src_name)); zlog_info ("Send %s on %s", ospf6_message_type_string[type], o6i->interface->name); zlog_info (" %s -> %s", src_name, dst_name); ospf6_message_log (message); } /* send message */ ospf6_sendmsg (o6i->lladdr, dst, &ifindex, message);}intospf6_send_hello (struct thread *thread){ listnode n; struct ospf6_interface *o6i; struct ospf6_neighbor *o6n; struct in6_addr dst; struct iovec message[OSPF6_MESSAGE_IOVEC_SIZE]; struct ospf6_hello hello; char router_buffer[1024]; /* xxx */ u_int router_size; /* which ospf6 interface to send */ o6i = (struct ospf6_interface *) THREAD_ARG (thread); o6i->thread_send_hello = (struct thread *) NULL; /* assure interface is up */ if (o6i->state <= IFS_DOWN) { if (IS_OSPF6_DUMP_HELLO) zlog_warn ("Send HELLO Failed: Interface not enabled: %s", o6i->interface->name); return 0; } /* clear message buffer */ OSPF6_MESSAGE_CLEAR (message); /* set Hello fields */ hello.interface_id = htonl (o6i->if_id); hello.rtr_pri = o6i->priority; memcpy (hello.options, o6i->area->options, sizeof (hello.options)); hello.hello_interval = htons (o6i->hello_interval); hello.router_dead_interval = htons (o6i->dead_interval); hello.dr = o6i->dr; hello.bdr = o6i->bdr; OSPF6_MESSAGE_ATTACH (message, &hello, sizeof (struct ospf6_hello)); /* set neighbor router id */ router_size = 0; for (n = listhead (o6i->neighbor_list); n; nextnode (n)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -