| 547 | |
| 548 | #define MTAG_ME 1414491977 |
| 549 | static int |
| 550 | me_transmit(struct ifnet *ifp, struct mbuf *m) |
| 551 | { |
| 552 | ME_RLOCK_TRACKER; |
| 553 | struct mobhdr mh; |
| 554 | struct me_softc *sc; |
| 555 | struct ip *ip; |
| 556 | uint32_t af; |
| 557 | int error, hlen, plen; |
| 558 | |
| 559 | ME_RLOCK(); |
| 560 | #ifdef MAC |
| 561 | error = mac_ifnet_check_transmit(ifp, m); |
| 562 | if (error != 0) |
| 563 | goto drop; |
| 564 | #endif |
| 565 | error = ENETDOWN; |
| 566 | sc = ifp->if_softc; |
| 567 | if (sc == NULL || !ME_READY(sc) || |
| 568 | (ifp->if_flags & IFF_MONITOR) != 0 || |
| 569 | (ifp->if_flags & IFF_UP) == 0 || |
| 570 | (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || |
| 571 | (error = if_tunnel_check_nesting(ifp, m, MTAG_ME, |
| 572 | V_max_me_nesting)) != 0) { |
| 573 | m_freem(m); |
| 574 | goto drop; |
| 575 | } |
| 576 | af = m->m_pkthdr.csum_data; |
| 577 | if (af != AF_INET) { |
| 578 | error = EAFNOSUPPORT; |
| 579 | m_freem(m); |
| 580 | goto drop; |
| 581 | } |
| 582 | if (m->m_len < sizeof(struct ip)) |
| 583 | m = m_pullup(m, sizeof(struct ip)); |
| 584 | if (m == NULL) { |
| 585 | error = ENOBUFS; |
| 586 | goto drop; |
| 587 | } |
| 588 | ip = mtod(m, struct ip *); |
| 589 | /* Fragmented datagramms shouldn't be encapsulated */ |
| 590 | if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) { |
| 591 | error = EINVAL; |
| 592 | m_freem(m); |
| 593 | goto drop; |
| 594 | } |
| 595 | mh.mob_proto = ip->ip_p; |
| 596 | mh.mob_src = ip->ip_src; |
| 597 | mh.mob_dst = ip->ip_dst; |
| 598 | if (in_hosteq(sc->me_src, ip->ip_src)) { |
| 599 | hlen = sizeof(struct mobhdr) - sizeof(struct in_addr); |
| 600 | mh.mob_flags = 0; |
| 601 | } else { |
| 602 | hlen = sizeof(struct mobhdr); |
| 603 | mh.mob_flags = MOB_FLAGS_SP; |
| 604 | } |
| 605 | BPF_MTAP2(ifp, &af, sizeof(af), m); |
| 606 | plen = m->m_pkthdr.len; |
nothing calls this directly
no test coverage detected