* Deliver packet back into the IP processing machinery. * * If no address specified, or address is 0.0.0.0, send to ip_output(); * otherwise, send to ip_input() and mark as having been received on * the interface with that address. */
| 308 | * the interface with that address. |
| 309 | */ |
| 310 | static int |
| 311 | div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, |
| 312 | struct mbuf *control) |
| 313 | { |
| 314 | struct epoch_tracker et; |
| 315 | const struct ip *ip; |
| 316 | struct m_tag *mtag; |
| 317 | struct ipfw_rule_ref *dt; |
| 318 | int error, family; |
| 319 | |
| 320 | /* |
| 321 | * An mbuf may hasn't come from userland, but we pretend |
| 322 | * that it has. |
| 323 | */ |
| 324 | m->m_pkthdr.rcvif = NULL; |
| 325 | m->m_nextpkt = NULL; |
| 326 | M_SETFIB(m, so->so_fibnum); |
| 327 | |
| 328 | if (control) |
| 329 | m_freem(control); /* XXX */ |
| 330 | |
| 331 | mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL); |
| 332 | if (mtag == NULL) { |
| 333 | /* this should be normal */ |
| 334 | mtag = m_tag_alloc(MTAG_IPFW_RULE, 0, |
| 335 | sizeof(struct ipfw_rule_ref), M_NOWAIT | M_ZERO); |
| 336 | if (mtag == NULL) { |
| 337 | m_freem(m); |
| 338 | return (ENOBUFS); |
| 339 | } |
| 340 | m_tag_prepend(m, mtag); |
| 341 | } |
| 342 | dt = (struct ipfw_rule_ref *)(mtag+1); |
| 343 | |
| 344 | /* Loopback avoidance and state recovery */ |
| 345 | if (sin) { |
| 346 | int i; |
| 347 | |
| 348 | /* set the starting point. We provide a non-zero slot, |
| 349 | * but a non_matching chain_id to skip that info and use |
| 350 | * the rulenum/rule_id. |
| 351 | */ |
| 352 | dt->slot = 1; /* dummy, chain_id is invalid */ |
| 353 | dt->chain_id = 0; |
| 354 | dt->rulenum = sin->sin_port+1; /* host format ? */ |
| 355 | dt->rule_id = 0; |
| 356 | /* XXX: broken for IPv6 */ |
| 357 | /* |
| 358 | * Find receive interface with the given name, stuffed |
| 359 | * (if it exists) in the sin_zero[] field. |
| 360 | * The name is user supplied data so don't trust its size |
| 361 | * or that it is zero terminated. |
| 362 | */ |
| 363 | for (i = 0; i < sizeof(sin->sin_zero) && sin->sin_zero[i]; i++) |
| 364 | ; |
| 365 | if ( i > 0 && i < sizeof(sin->sin_zero)) |
| 366 | m->m_pkthdr.rcvif = ifunit(sin->sin_zero); |
| 367 | } |
no test coverage detected