?? ipripng.c
字號:
ipripng_send_response(ifcp, &ifcp->ifc_ripsin, 0); } /* Request a new update timeout. */ ipripng.rndtmo++; if (ipripng.rndtmo > (Ip_u32)(ipripng.update_seconds + ipripng.update_deltaseconds)) ipripng.rndtmo = ipripng.update_seconds; (void)ipcom_tmo_request(&ipripng.update, ipripng_update_timeout, IP_NULL, 1000 * ipripng.rndtmo); /* Increment the flash instance number. */ ipripng.update_inst++; /* Cancel flash update since we just had a regular one. */ (void)ipcom_tmo_cancel(&ipripng.flash); IPRIPNG_UNLOCK(); return 0;}/* *=========================================================================== * ipripng_flash_timeout *=========================================================================== * Description: Transmit a triggered RIPng update containing new and changed * routes on all interfaces that are non-silent. * Parameters: tmo NSTIME timeout structure. * Returns: . * */IP_STATIC Ip_s32ipripng_flash_timeout(Ipcom_tmo *tmo, void *cookie){ Ip_time_t next_triggertime; struct ifc *ifcp; struct Ipripng_rt *rrt; if (ripngStopFlag) return 0; IPRIPNG_LOCK(); (void)tmo; (void)cookie; IPCOM_LOG2(DEBUG2, "+++ flash timeout, %ld interfaces, %ld routes:", ipripng.nifc, ipripng.rt_num); for (ifcp = ipripng.ifc; ifcp; ifcp = ifcp->ifc_next) { if (ifcp->ifc_flags & IP_IFF_UP) ipripng_send_response(ifcp, &ifcp->ifc_ripsin, RRTF_CHANGED); } /* Reset the flag */ for (rrt = ipripng.riprt; rrt; rrt = ((Ipripng_rt *)rrt)->rrt_next) ((Ipripng_rt *)rrt)->rrt_rflags &= ~RRTF_CHANGED; /* * Set the next triggered update to between 1 and 5 seconds away. */ next_triggertime = ipripng_nexttrigger_time(); (void)ipcom_tmo_request(&ipripng.flash, ipripng_flash_timeout, IP_NULL, 1000 * next_triggertime); /* Increment the flash instance number. */ ipripng.update_inst++; IPRIPNG_UNLOCK(); return 0; /* do not request a new timeout. */}/* *=========================================================================== * ipripng_flush *=========================================================================== * Description: Transmit all RIPng routes in RIPng response packet(s) on a single * interface. * Parameters: ifcp Interface to transmit RIPng response packet(s) on. * sin6 Destination address. * Returns: * */IP_STATIC voidipripng_flush(struct ifc *ifcp, struct Ip_sockaddr_in6 *sin6){ int i; int error; char tmpString[120]; /* Our logger puts in newlines */ char * pstr; char buf[IP_INET6_ADDRSTRLEN]; if (ipcom_inet_ntop(IP_AF_INET6, &sin6->sin6_addr, buf, sizeof (buf)) == IP_NULL) buf[0] = '\0'; /* Won't display garbage */ IPCOM_LOG4(INFO, "Send(%s): info(%d) to %s.%d", ifcp ? ifcp->ifc_name : "?", priv_ripng_nrt, buf[0] ? buf : "?", ip_ntohs(sin6->sin6_port)); if (ipripng.dflag >= 2) { priv_ripng_np = ipripng.ripngbuf->rip6_nets; for (i = 0; i < priv_ripng_nrt; i++, priv_ripng_np++) { pstr = tmpString; if (ipcom_inet_ntop(IP_AF_INET6, &priv_ripng_np->rip6_dest, buf, sizeof (buf)) == IP_NULL) buf[0] = '\0'; /* So doesn't display garbage */ if (priv_ripng_np->rip6_metric == NEXTHOP_METRIC) { if (IP_IN6_IS_ADDR_UNSPECIFIED(&priv_ripng_np->rip6_dest)) { sprintf (pstr, " NextHop reset"); pstr = tmpString + strlen (tmpString); } else { sprintf (pstr, " NextHop %s", buf); pstr = tmpString + strlen (tmpString); } } else { sprintf (pstr, " %s/%d[%d]", buf, priv_ripng_np->rip6_plen, priv_ripng_np->rip6_metric); pstr = tmpString + strlen (tmpString); } if (priv_ripng_np->rip6_tag) { sprintf (pstr, " tag=0x%04x", ip_ntohs(priv_ripng_np->rip6_tag) & 0xffff); pstr = tmpString + strlen (tmpString); } IPCOM_LOG1(DEBUG, "%s", tmpString); } /* for */ } /* if */ error = ipripng_sendpacket(sin6, RIPSIZE(priv_ripng_nrt)); if (error == IP_ERRNO_EAFNOSUPPORT) { /* Protocol not supported */ if (ipcom_inet_ntop(IP_AF_INET6, &ifcp->ifc_ripsin.sin6_addr, buf, sizeof (buf)) == IP_NULL) buf[0] = '\0'; IPCOM_LOG2(INFO, "Could not send info to %s on %s", buf[0] ? buf : "?", ifcp ? ifcp->ifc_name : "?"); if (ifcp) { IPCOM_LOG1(INFO, "Cleared IFF_UP flag on %s", ifcp->ifc_name); ifcp->ifc_flags &= ~IP_IFF_UP; /* As if down for AF_INET6 */ } } priv_ripng_nrt = 0; priv_ripng_np = ipripng.ripngbuf->rip6_nets;}/* * Generate RIP6_RESPONSE packets and send them. */IP_STATIC voidipripng_send_response(struct ifc *ifcp, struct Ip_sockaddr_in6 *sin6, int flag){ Ipripng_rt *rrt; struct in6_addr *prevnh, *thisnh; /* next hop */ int maxrte; int tobeadvd; prevnh = thisnh = IP_NULL; if (ipripng.qflag) return; if (flag & RRTF_CHANGED) IPCOM_LOG1(INFO, "sending triggered update on: %s", ifcp->ifc_name); if ((flag & RRTF_SENDANYWAY) == 0 && (ipripng.qflag || (ifcp->ifc_flags & IP_IFF_LOOPBACK))) return; /* -N: no use */ if (iff_find(ifcp, 'N') != IP_NULL) return; /* -T: generate default route only */ if (iff_find(ifcp, 'T') != IP_NULL) { struct netinfo6 rrt_info[2]; memset(&rrt_info, 0, 2 * sizeof(struct netinfo6)); /* Send the Next Hop RTE first */ rrt_info[0].rip6_dest = ifcp->ifc_mylladdr; rrt_info[0].rip6_plen = 0; rrt_info[0].rip6_tag = 0; rrt_info[0].rip6_metric = NEXTHOP_METRIC; rrt_info[1].rip6_dest = ip_in6addr_any; rrt_info[1].rip6_plen = 0; rrt_info[1].rip6_metric = 1; rrt_info[1].rip6_metric += ifcp->ifc_metric; rrt_info[1].rip6_tag = ip_htons(ipripng.routetag & 0xffff); priv_ripng_np = ipripng.ripngbuf->rip6_nets; *priv_ripng_np = rrt_info[0]; priv_ripng_np++; *priv_ripng_np = rrt_info[1]; priv_ripng_nrt = 2; ipripng_flush(ifcp, sin6); return; } maxrte = (ifcp->ifc_mtu - sizeof(Ipnet_pkt_ip6) - sizeof(Ipnet_pkt_udp) - sizeof(struct rip6) + sizeof(struct netinfo6)) / sizeof(struct netinfo6); priv_ripng_nrt = 0; priv_ripng_np = ipripng.ripngbuf->rip6_nets; prevnh = IP_NULL; for (rrt = (Ipripng_rt *)ipripng.riprt; rrt; rrt = (Ipripng_rt *)rrt->rrt_next) { if (rrt->rrt_rflags & RRTF_NOADVERTISE) continue; /* Need to check filter here */ if (out_filter(rrt, ifcp) == 0) continue; /* Check split horizon / poison reverse and other conditions */ tobeadvd = tobeadv (rrt, ifcp); if (tobeadvd == 0) continue; /* * Only considers the routes with flag if specified. * Also don't send triggered updates if this route is an infinite * metric (poison reverse). */ if (flag & RRTF_CHANGED) { if (((rrt->rrt_rflags & RRTF_CHANGED) == 0) || (tobeadvd == 2)) continue; } /* Calculate Next Hop for this route */ /* We use the actual gateway for the Next Hop for: * If the route goes out over the same interface * AND the gateway address is specified. * AND The gateway address is link-local * AND this is not a Poison Reverse route */ if ((rrt->rrt_index == ifcp->ifc_index) && (!IP_IN6_IS_ADDR_UNSPECIFIED(&rrt->rrt_gw)) && (IP_IN6_IS_ADDR_LINK_LOCAL(&rrt->rrt_gw)) && ((rrt->rrt_flags & RRTF_NH_NOT_LLADDR) == 0) && (tobeadvd != 2)) { thisnh = &rrt->rrt_gw; } /* Otherwise we use our own link-local address for the Next Hop */ else { thisnh = &ifcp->ifc_mylladdr; } /* * Now check if this was the previous Next Hop or if one has * ever been sent. If not then we must send a new Next Hop RTE. */ if ((prevnh == IP_NULL) || !IP_IN6_ARE_ADDR_EQUAL(thisnh, prevnh)) { /* Flush the packet if we're out of space */ if (priv_ripng_nrt == maxrte - 2) ipripng_flush(ifcp, sin6); /* Fill out the Next Hop RTE with the address chosen above */ priv_ripng_np->rip6_dest = *thisnh; if (IP_IN6_IS_ADDR_LINK_LOCAL(&priv_ripng_np->rip6_dest)) SET_IN6_LINKLOCAL_IFINDEX(priv_ripng_np->rip6_dest, 0); priv_ripng_np->rip6_plen = 0; priv_ripng_np->rip6_tag = 0; priv_ripng_np->rip6_metric = NEXTHOP_METRIC; prevnh = thisnh; priv_ripng_np++; priv_ripng_nrt++; } /* Put the route to the buffer */ *priv_ripng_np = rrt->rrt_info; /* Poison Reverse route ? */ if (tobeadvd == 2) priv_ripng_np->rip6_metric = HOPCNT_INFINITY6; priv_ripng_np++; priv_ripng_nrt++; if (priv_ripng_nrt == maxrte) { ipripng_flush(ifcp, sin6); prevnh = IP_NULL; } } if (priv_ripng_nrt) /* Send last packet */ ipripng_flush(ifcp, sin6);}/* *=========================================================================== * ipripng_process_request *=========================================================================== * Description: Parse an incoming RIPng request packet and send a response * if applicable. * Parameters: ifc Interface RIPng request arrived on. * np RIPng packet output buffer. * sin6 destination address. * Returns: IPCOM_SUCCESS or IPCOM_ERR_BAD_PACKET. * */IP_STATIC voidipripng_process_request(struct ifc *ifcp, struct netinfo6 *np, int nn, struct Ip_sockaddr_in6 *sin6){ int i; Ipripng_rt *rrt; if (!(nn == 1 && IP_IN6_IS_ADDR_UNSPECIFIED(&np->rip6_dest) && np->rip6_plen == 0 && np->rip6_metric == HOPCNT_INFINITY6)) { /* Specific response, don't split-horizon */ IPCOM_LOG0(INFO, "\tRIPng Process Request"); for (i = 0; i < nn; i++, np++) { rrt = ipripng_rtlookup(np, IP_NULL); if (rrt) np->rip6_metric = rrt->rrt_info.rip6_metric; else np->rip6_metric = HOPCNT_INFINITY6; } (void)ipripng_sendpacket(sin6, RIPSIZE(nn)); return; } /* Whole routing table dump */ /* Used to use RRTF_SENDANYWAY to bypass qflag (listen only) * but RIPng shouldn't respond to requests either when in listen * only mode, otherwise other routers will get this router's * routes even though the user specified listen only. */ IPCOM_LOG0(INFO, "\tRIPng Request -- whole routing table"); ipripng_send_response(ifcp, sin6, 0);}/* *=========================================================================== * ipripng_neighboradd *=========================================================================== * Description: Add a line from getopt to our linked list of accepted * neighbors. * Parameters: * * Returns: * */IP_STATICvoid ipripng_neighboradd (char * optarg){ struct nb_list * plist = ipripng.nb_list_root; struct nb_list * prevp = IP_NULL; char * argptr = optarg; /* Check valid parameters */ if ((argptr == IP_NULL) || (*argptr == '\0')) IPCOM_LOG0(WARNING, "No neighbors specified"); /* Walk the list to find the last element */ while (plist) { prevp = plist; plist = plist->nb_next; } /* Parse the address list ("addr1,addr2") */ while (argptr) { char * addr; addr = argptr; /* Replace the comma by a NULL for inet_pton() */ if ((argptr = ipcom_strchr (argptr, ',')) != IP_NULL) *argptr++ = '\0'; /* Create new element for linked list */ plist = (struct nb_list *)ipcom_malloc (sizeof (struct nb_list)); if (plist == IP_NULL) { IPCOM_LOG0(ERR, "Error on neighbor list ipcom_malloc"); return; } /* Convert to in6_addr and store in element */ if (ipcom_inet_pton(IP_AF_INET6, addr, &plist->nb_addr) != 1) { IPCOM_LOG1(ERR, "Bad restricted neighbor address (%s)", addr); ipcom_free (plist); return; } plist->nb_next = IP_NULL; /* Put it to the list */ if (prevp == IP_NULL) /* First one */ ipripng.nb_list_root = plist;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -