* Forward a packet. If some error occurs return the sender * an icmp packet. Note we can't always generate a meaningful * icmp message because icmp doesn't have a large enough repertoire * of codes and types. * * If not forwarding, just drop the packet. This could be confusing * if ipforwarding was zero but some routing protocol was advancing * us as a gateway to somewhere. However, we
| 89 | * |
| 90 | */ |
| 91 | void |
| 92 | ip6_forward(struct mbuf *m, int srcrt) |
| 93 | { |
| 94 | struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); |
| 95 | struct sockaddr_in6 dst; |
| 96 | struct nhop_object *nh = NULL; |
| 97 | int error, type = 0, code = 0; |
| 98 | struct mbuf *mcopy = NULL; |
| 99 | struct ifnet *origifp; /* maybe unnecessary */ |
| 100 | u_int32_t inzone, outzone; |
| 101 | struct in6_addr odst; |
| 102 | struct m_tag *fwd_tag; |
| 103 | char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN]; |
| 104 | |
| 105 | /* |
| 106 | * Do not forward packets to multicast destination (should be handled |
| 107 | * by ip6_mforward(). |
| 108 | * Do not forward packets with unspecified source. It was discussed |
| 109 | * in July 2000, on the ipngwg mailing list. |
| 110 | */ |
| 111 | if ((m->m_flags & (M_BCAST|M_MCAST)) != 0 || |
| 112 | IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) || |
| 113 | IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { |
| 114 | IP6STAT_INC(ip6s_cantforward); |
| 115 | /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */ |
| 116 | if (V_ip6_log_time + V_ip6_log_interval < time_uptime) { |
| 117 | V_ip6_log_time = time_uptime; |
| 118 | log(LOG_DEBUG, |
| 119 | "cannot forward " |
| 120 | "from %s to %s nxt %d received on %s\n", |
| 121 | ip6_sprintf(ip6bufs, &ip6->ip6_src), |
| 122 | ip6_sprintf(ip6bufd, &ip6->ip6_dst), |
| 123 | ip6->ip6_nxt, |
| 124 | if_name(m->m_pkthdr.rcvif)); |
| 125 | } |
| 126 | m_freem(m); |
| 127 | return; |
| 128 | } |
| 129 | |
| 130 | if ( |
| 131 | #ifdef IPSTEALTH |
| 132 | V_ip6stealth == 0 && |
| 133 | #endif |
| 134 | ip6->ip6_hlim <= IPV6_HLIMDEC) { |
| 135 | /* XXX in6_ifstat_inc(rt->rt_ifp, ifs6_in_discard) */ |
| 136 | icmp6_error(m, ICMP6_TIME_EXCEEDED, |
| 137 | ICMP6_TIME_EXCEED_TRANSIT, 0); |
| 138 | return; |
| 139 | } |
| 140 | |
| 141 | /* |
| 142 | * Save at most ICMPV6_PLD_MAXLEN (= the min IPv6 MTU - |
| 143 | * size of IPv6 + ICMPv6 headers) bytes of the packet in case |
| 144 | * we need to generate an ICMP6 message to the src. |
| 145 | * Thanks to M_EXT, in most cases copy will not occur. |
| 146 | * |
| 147 | * It is important to save it before IPsec processing as IPsec |
| 148 | * processing may modify the mbuf. |
no test coverage detected