* Divert a packet by passing it up to the divert socket at port 'port'. * * Setup generic address and protocol structures for div_input routine, * then pass them along with mbuf chain. */
| 188 | * then pass them along with mbuf chain. |
| 189 | */ |
| 190 | static void |
| 191 | divert_packet(struct mbuf *m, bool incoming) |
| 192 | { |
| 193 | struct ip *ip; |
| 194 | struct inpcb *inp; |
| 195 | struct socket *sa; |
| 196 | u_int16_t nport; |
| 197 | struct sockaddr_in divsrc; |
| 198 | struct m_tag *mtag; |
| 199 | |
| 200 | NET_EPOCH_ASSERT(); |
| 201 | |
| 202 | mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL); |
| 203 | if (mtag == NULL) { |
| 204 | m_freem(m); |
| 205 | return; |
| 206 | } |
| 207 | /* Assure header */ |
| 208 | if (m->m_len < sizeof(struct ip) && |
| 209 | (m = m_pullup(m, sizeof(struct ip))) == NULL) |
| 210 | return; |
| 211 | ip = mtod(m, struct ip *); |
| 212 | |
| 213 | /* Delayed checksums are currently not compatible with divert. */ |
| 214 | if (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA) { |
| 215 | in_delayed_cksum(m); |
| 216 | m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; |
| 217 | } |
| 218 | #if defined(SCTP) || defined(SCTP_SUPPORT) |
| 219 | if (m->m_pkthdr.csum_flags & CSUM_SCTP) { |
| 220 | sctp_delayed_cksum(m, (uint32_t)(ip->ip_hl << 2)); |
| 221 | m->m_pkthdr.csum_flags &= ~CSUM_SCTP; |
| 222 | } |
| 223 | #endif |
| 224 | bzero(&divsrc, sizeof(divsrc)); |
| 225 | divsrc.sin_len = sizeof(divsrc); |
| 226 | divsrc.sin_family = AF_INET; |
| 227 | /* record matching rule, in host format */ |
| 228 | divsrc.sin_port = ((struct ipfw_rule_ref *)(mtag+1))->rulenum; |
| 229 | /* |
| 230 | * Record receive interface address, if any. |
| 231 | * But only for incoming packets. |
| 232 | */ |
| 233 | if (incoming) { |
| 234 | struct ifaddr *ifa; |
| 235 | struct ifnet *ifp; |
| 236 | |
| 237 | /* Sanity check */ |
| 238 | M_ASSERTPKTHDR(m); |
| 239 | |
| 240 | /* Find IP address for receive interface */ |
| 241 | ifp = m->m_pkthdr.rcvif; |
| 242 | CK_STAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { |
| 243 | if (ifa->ifa_addr->sa_family != AF_INET) |
| 244 | continue; |
| 245 | divsrc.sin_addr = |
| 246 | ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; |
| 247 | break; |
nothing calls this directly
no test coverage detected