📄 rsrr.c
字号:
case NET_ADDR_IPv4: /* * IPv4 Unicast */ if (!IN_IS_ADDR_MULTICAST(&(NET_GET_ADDR_IPv4(net_addr_ip(dst))))) { if (NoUnicast) return -1; if (src == 0) { /* correct, go on */ rv = unicast_route(dst); if (rv == -1) { /* * Error occurred */ return (-1); }#if defined(PF_ROUTE) && !defined(sgi_53) && !defined(linux) else if (rv == 0 && asynchronous == 1) { /* * Asynchronous reply, * return sequence number */ return seq; }#endif /* PF_ROUTE */ else { /* * Synchronous reply, * set up bitmap then return */ bmp_set(bmp, rv); asynchronous = 1; return (0); } } else { log(LOG_ERR,errno,"Invalid IPv4 unicast address for query",0); return (-1); } } /* * IPv4 Multicast */ else { if (NoV4Mroute) return -1; /* * Make sure src is not null, and it's not multicast * address */ if (src != 0 && !IN_IS_ADDR_MULTICAST(&(NET_GET_ADDR_IPv4(net_addr_ip(src))))) {#ifdef HOST_ONLY assert(0);#else /* !HOST_ONLY */ /* * send out the route query if this route query is not * intended to delete the route change notification * cache in the routing daemon or if it is, make sure * RSRRv2 is the one used by IPv4 multicast routing * daemon, since the current implementation of RSRR * stub in mrouted uses RSRRv1 and it has no processing * for route change notification cache delete request * from rsvpd. * rv is either -1 for error or query_id */ if (note || rsrr_use_v2_ipv4) rv = rsrr_send_rq(psb, ses, AF_INET, src, dst, note); return rv;#endif /* !HOST_ONLY */ } else { log(LOG_ERR,errno,"Invalid IPv4 multicast address for query",0); return (-1); } } break;#ifdef USE_IPV6 case NET_ADDR_IPv6: /* * IPv6 Unicast */ if (!IN6_IS_ADDR_MULTICAST(&NET_GET_ADDR_IPv6(net_addr_ip(dst)))) { if (NoUnicast) return -1; if (src == 0) { /* correct, go on */ rv = unicast_route(dst); if (rv == -1) { /* * Error occurred */ return (-1); }#if defined(PF_ROUTE) && !defined(sgi_53) && !defined(linux) else if (rv == 0 && asynchronous == 1) { /* * Asynchronous reply */ return seq; }#endif /* PF_ROUTE */ else { /* * Synchronous reply */ bmp_set(bmp, rv); asynchronous = 1; return (0); } } else { log(LOG_ERR,errno,"Incorrect address for query",0); return (-1); } } /* * IPv6 Multicast */ else { if (NoV6Mroute) return -1; /* * Make sure src is not null, and it's not multicast * address */ if (src != 0 && !IN6_IS_ADDR_MULTICAST(&NET_GET_ADDR_IPv6(net_addr_ip(src)))) { if (NoV6Mroute) return -1;#ifdef HOST_ONLY assert(0);#else /* !HOST_ONLY */ /* * send out route query * rv is either -1 for error or query_id */ rv = rsrr_send_rq(psb, ses, AF_INET6, src, dst, note); return rv;#endif /* !HOST_ONLY */ } } break;#endif /* USE_IPV6 */ default: log(LOG_ERR,errno,"No such type exists",0); return (-1); } /* * if here, must be an error */ return -1;}#endif /* HOST_ONLY *//* * The corresponding upcall for rsrr_route_query() after a route_query * or for notification of route changes * * Argument: qid - query ID. Could be PSB address in multicast case, * or rtm_seq in routing socket case. * src - source address * dst - destination address * iif - incoming interface * bmp - outgoing interface bitmap * tree_type - type of tree for this route * * Returns: 0 if succeed. */int rsrr_route_reply(u_long qid, net_addr *src, net_addr *dst, int iif, bitmap *bmp, int note, u_char tree_type){ struct rsrr_query_table *qt; Session *dp; PSB *sp; int i; /* * Unicast case */ if (src == (net_addr *)0 && dst != (net_addr *)0) { /* * Unicast routing reply, result is stored in bmp, * which should be the global variable bmp_unicast. */ if (unicast_query_waiting == 1) { /* * Asynchronous route reply */ unicast_result_ready = 1; return 0; } else { /* * route change notification */ for (i= 0; i < SESS_HASH_SIZE; i++) { for (dp = session_hash[i]; dp != NULL; dp = dp->d_next) { switch (NET_GET_TYPE(net_addr_ip(dst))) { case NET_ADDR_IPv4: /* * IPv4 unicast case */ if (dp->d_session->sess4_addr.s_addr == NET_GET_ADDR_IPv4(net_addr_ip(dst)).s_addr) { /* * Found session with same group/dest address. */ for (sp=dp->d_PSB_list; sp != NULL; sp=sp->ps_next) { SetNotifyBit(sp, note); rsrr_update(dp, sp, iif, bmp); } } break;#ifdef USE_IPV6 case NET_ADDR_IPv6: /* * IPv6 unicast case */ if (IN6_ARE_ADDR_EQUAL(&dp->d_session->sess6_addr, &NET_GET_ADDR_IPv6(net_addr_ip(dst)))) { /* * Found session with same group/dest address. */ for (sp=dp->d_PSB_list; sp != NULL; sp=sp->ps_next) { SetNotifyBit(sp, note); rsrr_update(dp, sp, iif, bmp); } } break;#endif /* USE_IPV6 */ default: break; } } } } return 0; } /* * Multicast case */ /* * Check if query id is cached. */ qt = rsrr_qt_lookup(qid); if (qt != NULL) { SetNotifyBit((PSB *)(qt->ptrP), note); /* * Update PSB with new route info, then complete process of * path info with any needed refreshes. */ rsrr_update((Session *)(qt->ptrS), (PSB *)(qt->ptrP), iif, bmp); /* * Delete the query entry from the table. We only use the * table for pending queries. Route change notification * queries can suffer a longer lookup because they are rare. */ rsrr_qt_delete(qt->query_id); return 0; } /* * None cached. Must scan entire state list looking for * affected sessions and senders. */ for (i= 0; i < SESS_HASH_SIZE; i++) { for (dp = session_hash[i]; dp != NULL; dp = dp->d_next) { switch (NET_GET_TYPE(net_addr_ip(dst))) { case NET_ADDR_IPv4: /* * IPv4 multicast case */ if (dp->d_session->sess4_addr.s_addr == NET_GET_ADDR_IPv4(net_addr_ip(dst)).s_addr) { /* * Found session with same group/dest address. */ /* * Find matching senders. If sender in RSRR is zero, * the tree is a shared tree, so match all senders. */ for (sp = dp->d_PSB_list; sp != NULL; sp = sp->ps_next) { if ((NET_GET_ADDR_IPv4(net_addr_ip(src)).s_addr == 0) || (sp->ps_templ->filt4_srcaddr.s_addr == NET_GET_ADDR_IPv4(net_addr_ip(src)).s_addr)) { SetNotifyBit(sp, note); rsrr_update(dp, sp, iif, bmp); } } } break;#ifdef USE_IPV6 case NET_ADDR_IPv6: /* * IPv6 multicast case */ if (IN6_ARE_ADDR_EQUAL(&dp->d_session->sess6_addr, &NET_GET_ADDR_IPv6(net_addr_ip(dst)))) { /* * Found session with same group/dest address. */ /* * Find matching senders. If sender in RSRR is zero, * the tree is a shared tree, so match all senders. */ for (sp = dp->d_PSB_list; sp != NULL; sp = sp->ps_next) { if (IN6_ARE_ADDR_EQUAL(&NET_GET_ADDR_IPv6(net_addr_ip(src)), &in6addr_any) || (IN6_ARE_ADDR_EQUAL(&sp->ps_templ->filt6_srcaddr, &NET_GET_ADDR_IPv6(net_addr_ip(src))))) { SetNotifyBit(sp, note); rsrr_update(dp, sp, iif, bmp); } } } break;#endif /* USE_IPV6 */ default: break; } } } return 0;}/* * Update path state using route reply */voidrsrr_update(dp, sp, inif, bmp) Session *dp; PSB *sp; int inif; bitmap *bmp;{ net_addr *addr = net_addr_ip(session_addr(dp->d_session)); /* * Remember that the multicast forwarding entry doesn't include * the vif over which data originates if the sender is local to * the router. Set the bit now. */ if (session_multicast(dp->d_session)) { if (IsHopAPI(&sp->ps_phop)) { switch (addr->type) { case NET_ADDR_IPv4: if (!NoV4Mroute) bmp_set(bmp, if_vec[sp->ps_originvif].if_index - if_vec[0].if_index +1 + api_num); else bmp_set(bmp, sp->ps_originvif); break;#ifdef USE_IPV6 case NET_ADDR_IPv6: bmp_set(bmp, sp->ps_originvif); break;#endif /* USE_IPV6 */ default: break; } } } /* * Call common routine to update the state. */ route_update(dp, sp, inif, *bmp); finish_path(dp, sp);}/* * bmptoif() searches through the bitmap, finds the bit which is set, * confirm it is the only bit which is set, then return that number. * - Argument: bitmap with one-bit set (bitmap*) * - Returns: interface number (int) */int bmptoif(bitmap *bmp){ int i; char s[100]; bitmap y; /* * No bit is set */ if (bmp_zero(bmp)) return -1; /* * Search from the right-most bit of the bitmap */ for (i=0; i < BMP_SIZE*NBBY; i++) { if (bmp_tst(bmp, i)) { y = *bmp; bmp_clr(&y, i); /* * make sure only 1 bit is set */ if (bmp_zero(&y)) { return i; } else { log(LOG_DEBUG,0,"RSRR: bmp = %d",bm_expand(bmp,s)); return -1; } } } return -1;}/* * Convert IPv6 address to printable (loggable) representation. */#ifdef USE_IPV6static char digits[] = "0123456789abcdef";static int ipv6round = 0;char *ip6_sprintf(addr) register struct in6_addr *addr;{ static char ipv6buf[8][46]; register int i; register char *cp; register u_int16_t *a = (u_int16_t *)addr; register u_int8_t *d; int dcolon = 0; ipv6round = (ipv6round + 1) & 7; cp = ipv6buf[ipv6round]; for (i = 0; i < 8; i++) { if (dcolon == 1) { if (*a == 0) { if (i == 7) *cp++ = ':'; a++; continue; } else dcolon = 2; } if (*a == 0) { if (dcolon == 0 && i == 7) { *cp++ = '0'; *cp++ = '0'; break; } if (dcolon == 0 && *(a + 1) == 0) { if (i == 0) *cp++ = ':'; *cp++ = ':'; dcolon = 1; } else { *cp++ = '0'; *cp++ = ':'; } a++; continue; } d = (u_int8_t *)a; *cp++ = digits[*d >> 4]; *cp++ = digits[*d++ & 0xf]; *cp++ = digits[*d >> 4]; *cp++ = digits[*d & 0xf]; *cp++ = ':'; a++; } *--cp = 0; return (ipv6buf[ipv6round]);}#endif /* USE_IPV6 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -