📄 ospf_packet.c
字号:
if (listcount (oi->ls_ack) > 0) ospf_ls_ack_send_delayed (oi); /* Set LS Ack timer. */ OSPF_ISM_TIMER_ON (oi->t_ls_ack, ospf_ls_ack_timer, oi->v_ls_ack); return 0;}intospf_write (struct thread *thread){ struct ospf *ospf = THREAD_ARG (thread); struct ospf_interface *oi; struct ospf_packet *op; struct sockaddr_in sa_dst; struct ip iph; struct msghdr msg; struct iovec iov[2]; u_char type; int ret; int flags = 0; listnode node; ospf->t_write = NULL; node = listhead (ospf->oi_write_q); assert (node); oi = getdata (node); assert (oi); /* Get one packet from queue. */ op = ospf_fifo_head (oi->obuf); assert (op); assert (op->length >= OSPF_HEADER_SIZE); if (op->dst.s_addr == htonl (OSPF_ALLSPFROUTERS) || op->dst.s_addr == htonl (OSPF_ALLDROUTERS)) ospf_if_ipmulticast (ospf, oi->address, oi->ifp->ifindex); /* Rewrite the md5 signature & update the seq */ ospf_make_md5_digest (oi, op); memset (&sa_dst, 0, sizeof (sa_dst)); sa_dst.sin_family = AF_INET;#ifdef HAVE_SIN_LEN sa_dst.sin_len = sizeof(sa_dst);#endif /* HAVE_SIN_LEN */ sa_dst.sin_addr = op->dst; sa_dst.sin_port = htons (0); /* Set DONTROUTE flag if dst is unicast. */ if (oi->type != OSPF_IFTYPE_VIRTUALLINK) if (!IN_MULTICAST (htonl (op->dst.s_addr))) flags = MSG_DONTROUTE; iph.ip_hl = sizeof (struct ip) >> 2; iph.ip_v = IPVERSION; iph.ip_tos = IPTOS_PREC_INTERNETCONTROL;#if defined(__NetBSD__) || defined(__FreeBSD__) iph.ip_len = iph.ip_hl*4 + op->length;#else iph.ip_len = htons (iph.ip_hl*4 + op->length);#endif iph.ip_id = 0; iph.ip_off = 0; if (oi->type == OSPF_IFTYPE_VIRTUALLINK) iph.ip_ttl = OSPF_VL_IP_TTL; else iph.ip_ttl = OSPF_IP_TTL; iph.ip_p = IPPROTO_OSPFIGP; iph.ip_sum = 0; iph.ip_src.s_addr = oi->address->u.prefix4.s_addr; iph.ip_dst.s_addr = op->dst.s_addr; memset (&msg, 0, sizeof (msg)); msg.msg_name = &sa_dst; msg.msg_namelen = sizeof (sa_dst); msg.msg_iov = iov; msg.msg_iovlen = 2; iov[0].iov_base = (char*)&iph; iov[0].iov_len = iph.ip_hl*4; iov[1].iov_base = STREAM_DATA (op->s); iov[1].iov_len = op->length; ret = sendmsg (ospf->fd, &msg, flags); if (ret < 0) zlog_warn ("*** sendmsg in ospf_write failed with %s", strerror (errno)); /* Retrieve OSPF packet type. */ stream_set_getp (op->s, 1); type = stream_getc (op->s); /* Show debug sending packet. */ if (IS_DEBUG_OSPF_PACKET (type - 1, SEND)) { if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) { zlog_info ("-----------------------------------------------------"); stream_set_getp (op->s, 0); ospf_packet_dump (op->s); } zlog_info ("%s sent to [%s] via [%s].", ospf_packet_type_str[type], inet_ntoa (op->dst), IF_NAME (oi)); if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL)) zlog_info ("-----------------------------------------------------"); } /* Now delete packet from queue. */ ospf_packet_delete (oi); if (ospf_fifo_head (oi->obuf) == NULL) { oi->on_write_q = 0; list_delete_node (ospf->oi_write_q, node); } /* If packets still remain in queue, call write thread. */ if (!list_isempty (ospf->oi_write_q)) ospf->t_write = thread_add_write (master, ospf_write, ospf, ospf->fd); return 0;}/* OSPF Hello message read -- RFC2328 Section 10.5. */voidospf_hello (struct ip *iph, struct ospf_header *ospfh, struct stream * s, struct ospf_interface *oi, int size){ struct ospf_hello *hello; struct ospf_neighbor *nbr; struct route_node *rn; struct prefix p, key; int old_state; /* increment statistics. */ oi->hello_in++; hello = (struct ospf_hello *) STREAM_PNT (s); /* If Hello is myself, silently discard. */ if (IPV4_ADDR_SAME (&ospfh->router_id, &oi->ospf->router_id)) return; /* If incoming interface is passive one, ignore Hello. */ if (OSPF_IF_PARAM (oi, passive_interface) == OSPF_IF_PASSIVE) return; /* get neighbor prefix. */ p.family = AF_INET; p.prefixlen = ip_masklen (hello->network_mask); p.u.prefix4 = iph->ip_src; /* Compare network mask. */ /* Checking is ignored for Point-to-Point and Virtual link. */ if (oi->type != OSPF_IFTYPE_POINTOPOINT && oi->type != OSPF_IFTYPE_VIRTUALLINK) if (oi->address->prefixlen != p.prefixlen) { zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch.", inet_ntoa (ospfh->router_id)); return; } /* Compare Hello Interval. */ if (OSPF_IF_PARAM (oi, v_hello) != ntohs (hello->hello_interval)) { zlog_warn ("Packet %s [Hello:RECV]: HelloInterval mismatch.", inet_ntoa (ospfh->router_id)); return; } /* Compare Router Dead Interval. */ if (OSPF_IF_PARAM (oi, v_wait) != ntohl (hello->dead_interval)) { zlog_warn ("Packet %s [Hello:RECV]: RouterDeadInterval mismatch.", inet_ntoa (ospfh->router_id)); return; } if (IS_DEBUG_OSPF_EVENT) zlog_info ("Packet %s [Hello:RECV]: Options %s", inet_ntoa (ospfh->router_id), ospf_options_dump (hello->options)); /* Compare options. */#define REJECT_IF_TBIT_ON 1 /* XXX */#ifdef REJECT_IF_TBIT_ON if (CHECK_FLAG (hello->options, OSPF_OPTION_T)) { /* * This router does not support non-zero TOS. * Drop this Hello packet not to establish neighbor relationship. */ zlog_warn ("Packet %s [Hello:RECV]: T-bit on, drop it.", inet_ntoa (ospfh->router_id)); return; }#endif /* REJECT_IF_TBIT_ON */#ifdef HAVE_OPAQUE_LSA if (CHECK_FLAG (oi->ospf->config, OSPF_OPAQUE_CAPABLE) && CHECK_FLAG (hello->options, OSPF_OPTION_O)) { /* * This router does know the correct usage of O-bit * the bit should be set in DD packet only. */ zlog_warn ("Packet %s [Hello:RECV]: O-bit abuse?", inet_ntoa (ospfh->router_id));#ifdef STRICT_OBIT_USAGE_CHECK return; /* Reject this packet. */#else /* STRICT_OBIT_USAGE_CHECK */ UNSET_FLAG (hello->options, OSPF_OPTION_O); /* Ignore O-bit. */#endif /* STRICT_OBIT_USAGE_CHECK */ }#endif /* HAVE_OPAQUE_LSA */ /* new for NSSA is to ensure that NP is on and E is off */#ifdef HAVE_NSSA if (oi->area->external_routing == OSPF_AREA_NSSA) { if (! (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_NP) && CHECK_FLAG (hello->options, OSPF_OPTION_NP) && ! CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) && ! CHECK_FLAG (hello->options, OSPF_OPTION_E))) { zlog_warn ("NSSA-Packet-%s[Hello:RECV]: my options: %x, his options %x", inet_ntoa (ospfh->router_id), OPTIONS (oi), hello->options); return; } if (IS_DEBUG_OSPF_NSSA) zlog_info ("NSSA-Hello:RECV:Packet from %s:", inet_ntoa(ospfh->router_id)); } else #endif /* HAVE_NSSA */ /* The setting of the E-bit found in the Hello Packet's Options field must match this area's ExternalRoutingCapability A mismatch causes processing to stop and the packet to be dropped. The setting of the rest of the bits in the Hello Packet's Options field should be ignored. */ if (CHECK_FLAG (OPTIONS (oi), OSPF_OPTION_E) != CHECK_FLAG (hello->options, OSPF_OPTION_E)) { zlog_warn ("Packet[Hello:RECV]: my options: %x, his options %x", OPTIONS (oi), hello->options); return; } /* Get neighbor information from table. */ key.family = AF_INET; key.prefixlen = IPV4_MAX_BITLEN; key.u.prefix4 = iph->ip_src; rn = route_node_get (oi->nbrs, &key); if (rn->info) { route_unlock_node (rn); nbr = rn->info; if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) { nbr->src = iph->ip_src; nbr->address = p; } } else { /* Create new OSPF Neighbor structure. */ nbr = ospf_nbr_new (oi); nbr->state = NSM_Down; nbr->src = iph->ip_src; nbr->address = p; rn->info = nbr; nbr->nbr_nbma = NULL; if (oi->type == OSPF_IFTYPE_NBMA) { struct ospf_nbr_nbma *nbr_nbma; listnode node; for (node = listhead (oi->nbr_nbma); node; nextnode (node)) { nbr_nbma = getdata (node); assert (nbr_nbma); if (IPV4_ADDR_SAME(&nbr_nbma->addr, &iph->ip_src)) { nbr_nbma->nbr = nbr; nbr->nbr_nbma = nbr_nbma; if (nbr_nbma->t_poll) OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll); nbr->state_change = nbr_nbma->state_change + 1; } } } /* New nbr, save the crypto sequence number if necessary */ if (ntohs (ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC) nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum; if (IS_DEBUG_OSPF_EVENT) zlog_info ("NSM[%s:%s]: start", IF_NAME (nbr->oi), inet_ntoa (nbr->router_id)); } nbr->router_id = ospfh->router_id; old_state = nbr->state; /* Add event to thread. */ OSPF_NSM_EVENT_EXECUTE (nbr, NSM_HelloReceived); /* RFC2328 Section 9.5.1 If the router is not eligible to become Designated Router, (snip) It must also send an Hello Packet in reply to an Hello Packet received from any eligible neighbor (other than the current Designated Router and Backup Designated Router). */ if (oi->type == OSPF_IFTYPE_NBMA) if (PRIORITY(oi) == 0 && hello->priority > 0 && IPV4_ADDR_CMP(&DR(oi), &iph->ip_src) && IPV4_ADDR_CMP(&BDR(oi), &iph->ip_src)) OSPF_NSM_TIMER_ON (nbr->t_hello_reply, ospf_hello_reply_timer, OSPF_HELLO_REPLY_DELAY); /* on NBMA network type, it happens to receive bidirectional Hello packet without advance 1-Way Received event. To avoid incorrect DR-seletion, raise 1-Way Received event.*/ if (oi->type == OSPF_IFTYPE_NBMA && (old_state == NSM_Down || old_state == NSM_Attempt)) { OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived); nbr->priority = hello->priority; nbr->d_router = hello->d_router; nbr->bd_router = hello->bd_router; return; } if (ospf_nbr_bidirectional (&oi->ospf->router_id, hello->neighbors, size - OSPF_HELLO_MIN_SIZE)) { OSPF_NSM_EVENT_EXECUTE (nbr, NSM_TwoWayReceived); nbr->options |= hello->options; } else { OSPF_NSM_EVENT_EXECUTE (nbr, NSM_OneWayReceived); /* Set neighbor information. */ nbr->priority = hello->priority; nbr->d_router = hello->d_router; nbr->bd_router = hello->bd_router; return; } /* If neighbor itself declares DR and no BDR exists, cause event BackupSeen */ if (IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router)) if (hello->bd_router.s_addr == 0 && oi->state == ISM_Waiting) OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); /* neighbor itself declares BDR. */ if (oi->state == ISM_Waiting && IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router)) OSPF_ISM_EVENT_SCHEDULE (oi, ISM_BackupSeen); /* had not previously. */ if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->d_router) && IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->d_router)) || (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->d_router) && IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->d_router))) OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); /* had not previously. */ if ((IPV4_ADDR_SAME (&nbr->address.u.prefix4, &hello->bd_router) && IPV4_ADDR_CMP (&nbr->address.u.prefix4, &nbr->bd_router)) || (IPV4_ADDR_CMP (&nbr->address.u.prefix4, &hello->bd_router) && IPV4_ADDR_SAME (&nbr->address.u.prefix4, &nbr->bd_router))) OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); /* Neighbor priority check. */ if (nbr->priority >= 0 && nbr->priority != hello->priority) OSPF_ISM_EVENT_SCHEDULE (oi, ISM_NeighborChange); /* Set neighbor information. */ nbr->priority = hello->priority; nbr->d_router = hello->d_router; nbr->bd_router = hello->bd_router;}/* Save DD flags/options/Seqnum received. */voidospf_db_desc_save_current (struct ospf_neighbor *nbr, struct ospf_db_desc *dd){ nbr->last_recv.flags = dd->flags; nbr->last_recv.options = dd->options; nbr->last_recv.dd_seqnum = ntohl (dd->dd_seqnum);}/* Process rest of DD packet. */static voidospf_db_desc_proc (struct stream *s, struct ospf_interface *oi, struct ospf_neighbor *nbr, struct ospf_db_desc *dd, u_int16_t size){ struct ospf_lsa *new, *find; struct lsa_header *lsah; stream_forward (s, OSPF_DB_DESC_MIN_SIZE); for (size -= OSPF_DB_DESC_MIN_SIZE; size >= OSPF_LSA_HEADER_SIZE; size -= OSPF_LSA_HEADER_SIZE) { lsah = (struct lsa_header *) STREAM_PNT (s); stream_forward (s, OSPF_LSA_HEADER_SIZE); /* Unknown LS type. */ if (lsah->type < OSPF_MIN_LSA || lsah->type >= OSPF_MAX_LSA) { zlog_warn ("Pakcet [DD:RECV]: Unknown LS type %d.", lsah->type); OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); return; }#ifdef HAVE_OPAQUE_LSA if (IS_OPAQUE_LSA (lsah->type) && ! CHECK_FLAG (nbr->options, OSPF_OPTION_O)) { zlog_warn ("LSA[Type%d:%s]: Opaque capability mismatch?", lsah->type, inet_ntoa (lsah->id)); OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); return; }#endif /* HAVE_OPAQUE_LSA */ switch (lsah->type) { case OSPF_AS_EXTERNAL_LSA:#ifdef HAVE_OPAQUE_LSA case OSPF_OPAQUE_AS_LSA:#endif /* HAVE_OPAQUE_LSA */#ifdef HAVE_NSSA /* Check for stub area. Reject if AS-External from stub but allow if from NSSA. */ if (oi->area->external_routing == OSPF_AREA_STUB)#else /* ! HAVE_NSSA */ if (oi->area->external_routing != OSPF_AREA_DEFAULT)#endif /* HAVE_NSSA */ { zlog_warn ("Packet [DD:RECV]: LSA[Type%d:%s] from %s area.", lsah->type, inet_ntoa (lsah->id), (oi->area->external_routing == OSPF_AREA_STUB) ?\ "STUB" : "NSSA"); OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch); return; } break; default: break; } /* Create LS-request object. */ new = ospf_ls_request_new (lsah);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -