📄 hello.c
字号:
bzero((caddr_t) &rtparms, sizeof (rtparms)); rtparms.rtp_n_gw = 1; rtparms.rtp_router = task_recv_srcaddr; rtparms.rtp_gwp = gw_timestamp(&hello_gw_list, tp->task_rtproto, tp, (as_t) 0, (as_t) 0, rtparms.rtp_router, GWF_NEEDHOLD); rtparms.rtp_gwp->gw_rtd_dump = hello_rt_dump; rtparms.rtp_gwp->gw_rtd_free = hello_rt_free; rtparms.rtp_state = (flag_t) 0; /* If we have a list of trusted gateways, verify that this gateway is trusted */ if (hello_n_trusted && !BIT_TEST(rtparms.rtp_gwp->gw_flags, GWF_TRUSTED)) { BIT_SET(rtparms.rtp_gwp->gw_flags, GWF_REJECT); continue; } /* Do we share a net with the sender? */ if (!(ifap = if_withdst(rtparms.rtp_router))) { trace_log_tp(tp, 0, LOG_WARNING, ("hello_recv: gw %A no shared net?", rtparms.rtp_router)); BIT_SET(rtparms.rtp_gwp->gw_flags, GWF_REJECT); continue; } if (sockaddrcmp_in(rtparms.rtp_router, ifap->ifa_addr_local)) { /* A packet from us */ if (!BIT_TEST(ifap->ifa_state, IFS_SIMPLEX)) { /* If this interface is not simplex, indicate that the media */ /* is functioning */ if_rtupdate(ifap); } /* Ignore the packet */ continue; } /* update the interface timer on interface the packet came in on. */ if_rtupdate(ifap); /* Ignore this packet */ if (BIT_TEST(ifap->ifa_ps[tp->task_rtproto].ips_state, IFPS_NOIN)) { continue; } /* check the hello checksum */ if (inet_cksum((void_t) hello, hello_len)) { trace_log_tp(tp, 0, LOG_WARNING, ("hello_recv: bad HELLO checksum from %A", rtparms.rtp_router)); BIT_SET(rtparms.rtp_gwp->gw_flags, GWF_CHECKSUM); continue; } rt_open(tp); /* message is made up of one or more sub messages */ hello += Size_hellohdr; while (hello < end) { PickUp_hm_hdr(hello, hm_hdr); switch (hm_hdr.hm_type) { case 0: hello += Size_type0pair * hm_hdr.hm_count; /* not interested in type 0 messages */ break; case 1: for (i = 0; i < hm_hdr.hm_count; i++) { register rt_entry *rt; struct type1pair type1pair; PickUp_type1pair(hello, type1pair); rtparms.rtp_dest = sockbuild_in(0, type1pair.d1_dst); if (!inet_class_valid(rtparms.rtp_dest)) { continue; } rtparms.rtp_preference = hello_preference; rtparms.rtp_metric = type1pair.d1_delay; /* Force delay to be valid */ if (rtparms.rtp_metric > HELLO_UNREACHABLE) { rtparms.rtp_metric = HELLO_UNREACHABLE; } /* * Add the interface metric converted to a HELLO delay. */ rtparms.rtp_metric += ifap->ifa_ps[tp->task_rtproto].ips_metric_in; rtparms.rtp_state = RTS_INTERIOR; rtparms.rtp_dest_mask = inet_mask_withif(rtparms.rtp_dest, ifap, &rtparms.rtp_state); if (!rtparms.rtp_dest_mask) { /* Ignore zero subnet */ continue; } if (if_myaddr(ifap, rtparms.rtp_dest, rtparms.rtp_dest_mask)) { /* Ignore route to interface or whole network */ continue; } rt = rt_locate(rtparms.rtp_state, rtparms.rtp_dest, rtparms.rtp_dest_mask, RTPROTO_BIT(tp->task_rtproto)); if (!rt) { rt_head *rth; /* No route installed. See if we are announcing another route */ rt = rt_locate(RTS_NETROUTE, rtparms.rtp_dest, rtparms.rtp_dest_mask, RTPROTO_BIT_ANY); if (rt && (rth = rt->rt_head) && rth->rth_n_announce && (rt == rth->rth_active || rt == rth->rth_holddown)) { /* We are announcing this route */ register target *tlp; /* HELLO won't announce an active route if one in holddown */ /* so check the holddown route first */ rt = rth->rth_holddown; if (!rt) { rt = rth->rth_active; } TARGET_LIST(tlp, &hello_targets) { if (BIT_TEST(tlp->target_flags, TARGETF_SUPPLY) && rtbit_isset(rt, tlp->target_rtbit)) { /* We are sending to this target */ td_entry *tdp; TD_TSI_GET(tlp, rth, tdp); if (BIT_TEST(tdp->td_flags, TDF_HOLDDOWN|TDF_POISON) || tdp->td_metric < rtparms.rtp_metric) { /* We are announcing this route from another protocol */ break; } } } TARGET_LIST_END(tlp, &hello_targets) ; if (tlp) { /* Announced via another protocol, ignore this route */ continue; } } /* New route */ if (rtparms.rtp_metric < HELLO_UNREACHABLE && import(rtparms.rtp_dest, rtparms.rtp_dest_mask, hello_import_list, ifap->ifa_ps[tp->task_rtproto].ips_import, rtparms.rtp_gwp->gw_import, &rtparms.rtp_preference, ifap, (void_t) 0)) { /* Allocate space for the hysterisis */ rtparms.rtp_rtd = task_block_alloc(hello_win_block_index); hello_win_init(rtparms.rtp_rtd, rtparms.rtp_metric); /* Add new route */ rt = rt_add(&rtparms); if (!rt) { task_block_free(hello_win_block_index, rtparms.rtp_rtd); rtparms.rtp_rtd = (void_t) 0; } } else { BIT_SET(rtparms.rtp_gwp->gw_flags, GWF_IMPORT); } } else if (sockaddrcmp_in(RT_ROUTER(rt), rtparms.rtp_router)) { /* same route */ if (rtparms.rtp_metric >= HELLO_UNREACHABLE) { /* Now unreachable - Delete route */ hello_win_add(rt->rt_data, HELLO_UNREACHABLE); rt_delete(rt); } else if (METRIC_DIFF(rt->rt_metric, rtparms.rtp_metric) >= HELLO_HYST(rt->rt_metric)) { /* Better metric */ if ((rt = rt_change(rt, rtparms.rtp_metric, rtparms.rtp_metric2, rtparms.rtp_tag, rt->rt_preference, rt->rt_preference2, rt->rt_n_gw, rt->rt_routers))) { hello_win_add(rt->rt_data, (metric_t) rtparms.rtp_metric); rt_refresh(rt); } } else { /* No change */ rt_refresh(rt); } } else if (((rtparms.rtp_metric < rt->rt_metric && METRIC_DIFF(rtparms.rtp_metric, rt->rt_metric) >= HELLO_HYST(rt->rt_metric)) || (rt_age(rt) > (HELLO_T_EXPIRE / 2) && rt->rt_metric == rtparms.rtp_metric)) && import(rtparms.rtp_dest, rtparms.rtp_dest_mask, hello_import_list, ifap->ifa_ps[tp->task_rtproto].ips_import, rtparms.rtp_gwp->gw_import, &rtparms.rtp_preference, ifap, (void_t) 0)) { /* Better metric or same metric and old route has */ /* not been refreshed */ hello_win_add(rt->rt_data, HELLO_UNREACHABLE); rt_delete(rt); /* Allocate space for the hysterisis */ rtparms.rtp_rtd = task_block_alloc(hello_win_block_index); hello_win_init(rtparms.rtp_rtd, rtparms.rtp_metric); /* Add new route */ rt = rt_add(&rtparms); if (!rt) { task_block_free(hello_win_block_index, rtparms.rtp_rtd); rtparms.rtp_rtd = (void_t) 0; } } } /* for each advertized net */ break; default: trace_log_tp(tp, 0, LOG_ERR, ("hello_recv: invalid type %d", hm_hdr.hm_type)); BIT_SET(rtparms.rtp_gwp->gw_flags, GWF_FORMAT); /* Force end of packet */ hello = end; } /* switch (mh->hm_type) */ } /* while not end of packet */ rt_close(tp, rtparms.rtp_gwp, (int) hm_hdr.hm_count, NULL); }}/* Send HELLO updates to all targets on the list *//*ARGSUSED*/static voidhello_supply __PF2(tlp, target *, flash_update, int){ byte *packet = task_get_send_buffer(byte *); byte *start = packet + Size_hellohdr + Size_hm_hdr; byte *fillp = start; register td_entry *tdp; size_t maxsize = 0; int changes = 0; /* Open the routing table in case a holddown is over */ rt_open(tlp->target_task); TD_LIST(tdp, &tlp->target_td) { int cleanup = 0; struct type1pair type1pair; if (flash_update) { if (!BIT_TEST(tdp->td_flags, TDF_CHANGED)) { /* End of changes for this target */ break; } } else { if (BIT_TEST(tdp->td_flags, TDF_HOLDDOWN|TDF_POISON) && !--tdp->td_metric) { /* Holddown is over - queue it to be released */ cleanup++; } } if (BIT_TEST(tdp->td_flags, TDF_CHANGED)) { BIT_RESET(tdp->td_flags, TDF_CHANGED); } if (fillp > Size_type1pair + packet + tlp->target_ifap->ifa_mtu) { hello_send(tlp, packet, fillp, &maxsize); fillp = start; } /* Put this entry in the packet */ type1pair.d1_delay = BIT_TEST(tdp->td_flags, TDF_HOLDDOWN|TDF_POISON) ? HELLO_UNREACHABLE : tdp->td_metric; type1pair.d1_offset = 0; /* should be signed clock offset */ type1pair.d1_dst = sock2ip(tdp->td_rt->rt_dest); /* struct copy */ PutDown_type1pair(fillp, type1pair); if (cleanup) { if (TRACE_TP(tlp->target_task, TR_POLICY)) { if (!changes) { trace_only_tp(tlp->target_task, TRC_NL_BEFORE, ("hello_supply: Policy for target %A", *tlp->target_dst)); } trace_only_tp(tlp->target_task, 0, ("\t%A/%A %s ended", tdp->td_rt->rt_dest, tdp->td_rt->rt_dest_mask, BIT_TEST(tdp->td_flags, TDF_POISON) ? "poison" : "holddown")); } changes++; TD_CLEANUP(tlp, tdp, TRUE); } } TD_LIST_END(tdp, &tlp->target_td) ; /* Send any packets with data remaining in them */ if (fillp > start) { hello_send(tlp, packet, fillp, &maxsize); fillp = start; } if (TRACE_TP(tlp->target_task, TR_POLICY) || changes) { trace_only_tp(tlp->target_task, 0, (NULL)); } rt_close(tlp->target_task, (gw_entry *) 0, 0, NULL);}/* * send HELLO packets *//*ARGSUSED*/static voidhello_job __PF2(tip, task_timer *, interval, time_t){ target *tlp; TARGET_LIST(tlp, &hello_targets) { if (BIT_TEST(tlp->target_flags, TARGETF_SUPPLY)) { hello_supply(tlp, FALSE); } } TARGET_LIST_END(tlp, &hello_targets); /* Indicate that flash updates are possible as soon as the timer fires */ task_timer_set(hello_timer_flash, HELLO_T_FLASH, (time_t) 0); BIT_RESET(hello_flags, HELLOF_NOFLASH|HELLOF_FLASHDUE);}/* * send a flash update packet *//*ARGSUSED*/static voidhello_do_flash __PF2(tip, task_timer *, interval, time_t){ task *tp = tip->task_timer_task; if (BIT_TEST(hello_flags, HELLOF_FLASHDUE)) { target *tlp; /* Do a flash update */ trace_tp(tp, TR_TASK, 0, ("hello_do_flash: Doing flash update for HELLO")); TARGET_LIST(tlp, &hello_targets) { if (BIT_TEST(tlp->target_flags, TARGETF_SUPPLY)) { hello_supply(tlp, TRUE); } } TARGET_LIST_END(tlp, &hello_targets); trace_tp(tp, TR_TASK, 0, ("hello_do_flash: Flash update done")); /* Indicate no flash update is due */ BIT_RESET(hello_flags, HELLOF_FLASHDUE); /* Schedule the next flash update */ if (time_sec + HELLO_T_MIN + HELLO_T_MAX < hello_timer_update->task_timer_next_time) { /* We can squeeze another flash update in before the full update */ task_timer_set(tip, HELLO_T_FLASH, (time_t) 0); } else { /* The next flash update will be scheduled after the full update */ task_timer_reset(tip); BIT_SET(hello_flags, HELLOF_NOFLASH); } } else { /* The next flash update can happen immediately */ task_timer_reset(tip); }}/* * Schedule or do a flash update */static voidhello_need_flash __PF1(tp, task *){ task_timer *tip = hello_timer_flash; if (!tip) { BIT_RESET(hello_flags, HELLOF_FLASHDUE); return; } /* Indicate we need a flash update */ BIT_SET(hello_flags, HELLOF_FLASHDUE); /* And see if we can do it now */ if (!tip->task_timer_next_time && !BIT_TEST(hello_flags, HELLOF_NOFLASH)) { /* Do it now */ hello_do_flash(tip, (time_t) 0); }}/* * Evaluate policy for changed routes. */static inthello_policy __PF3(tp, task *, tlp, target *, change_list, rt_list *){ if_addr *ifap = tlp->target_ifap; u_long if_net = inet_net_natural(ifap->ifa_addr); int same_net = if_net == inet_net_natural(ifap->ifa_addr_local); int changes = 0; int logged = 0; rt_head *rth; RT_LIST(rth, change_list, rt_head) { register rt_entry *new_rt = rth->rth_active; adv_results result; td_entry *tdp; int exportable = FALSE; int changed = 0; int move_bit = 0; int holddown = 0; int poison = 0; int set_metric = 0; TD_TSI_GET(tlp, rth, tdp); /* See if there is a new route and if it can be announced */ if ((new_rt = rth->rth_active)) { if (socktype(new_rt->rt_dest) != AF_INET) { goto no_export; } if (BIT_TEST(new_rt->rt_state, RTS_NOADVISE|RTS_PENDING|RTS_GROUP)) { /* Absolutely not */ goto no_export; } if (RT_IFAP(new_rt) == ifap && new_rt->rt_gwp->gw_proto == RTPROTO_DIRECT) { /* Do not send interface routes back to the same interface */ goto no_export; } /* Host routes go everywhere, subnets and nets may need to be restricted */ if (new_rt->rt_dest_mask != inet_mask_host) { sockaddr_un *natural_mask = inet_mask_natural(new_rt->rt_dest); if (new_rt->rt_dest_mask > natural_mask) { /* This is a subnet */ if (!same_net || (sock2ip(rth->rth_dest) & sock2ip(natural_mask)) != if_net) { /* Only send subnets to interfaces of the same network */ goto no_export; } if (rth->rth_dest_mask != ifap->ifa_netmask) { /* Only send subnets that have the same mask */ goto no_export; } } else if (sock2ip(rth->rth_dest) == if_net) { /* Do not send the whole net to a subnet */ goto no_export; } } if ((new_rt->rt_gwp->gw_proto == tp->task_rtproto) && (ifap == RT_IFAP(new_rt))) { /* Split horizon */ goto no_export; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -