| 420 | } |
| 421 | |
| 422 | void |
| 423 | gif_input(struct mbuf *m, struct ifnet *ifp, int proto, uint8_t ecn) |
| 424 | { |
| 425 | struct etherip_header *eip; |
| 426 | #ifdef INET |
| 427 | struct ip *ip; |
| 428 | #endif |
| 429 | #ifdef INET6 |
| 430 | struct ip6_hdr *ip6; |
| 431 | uint32_t t; |
| 432 | #endif |
| 433 | struct ether_header *eh; |
| 434 | struct ifnet *oldifp; |
| 435 | int isr, n, af; |
| 436 | |
| 437 | NET_EPOCH_ASSERT(); |
| 438 | |
| 439 | if (ifp == NULL) { |
| 440 | /* just in case */ |
| 441 | m_freem(m); |
| 442 | return; |
| 443 | } |
| 444 | m->m_pkthdr.rcvif = ifp; |
| 445 | m_clrprotoflags(m); |
| 446 | switch (proto) { |
| 447 | #ifdef INET |
| 448 | case IPPROTO_IPV4: |
| 449 | af = AF_INET; |
| 450 | if (m->m_len < sizeof(struct ip)) |
| 451 | m = m_pullup(m, sizeof(struct ip)); |
| 452 | if (m == NULL) |
| 453 | goto drop; |
| 454 | ip = mtod(m, struct ip *); |
| 455 | if (ip_ecn_egress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED: |
| 456 | ECN_NOCARE, &ecn, &ip->ip_tos) == 0) { |
| 457 | m_freem(m); |
| 458 | goto drop; |
| 459 | } |
| 460 | break; |
| 461 | #endif |
| 462 | #ifdef INET6 |
| 463 | case IPPROTO_IPV6: |
| 464 | af = AF_INET6; |
| 465 | if (m->m_len < sizeof(struct ip6_hdr)) |
| 466 | m = m_pullup(m, sizeof(struct ip6_hdr)); |
| 467 | if (m == NULL) |
| 468 | goto drop; |
| 469 | t = htonl((uint32_t)ecn << 20); |
| 470 | ip6 = mtod(m, struct ip6_hdr *); |
| 471 | if (ip6_ecn_egress((ifp->if_flags & IFF_LINK1) ? ECN_ALLOWED: |
| 472 | ECN_NOCARE, &t, &ip6->ip6_flow) == 0) { |
| 473 | m_freem(m); |
| 474 | goto drop; |
| 475 | } |
| 476 | break; |
| 477 | #endif |
| 478 | case IPPROTO_ETHERIP: |
| 479 | af = AF_LINK; |
no test coverage detected