* PIM-SMv2 and PIM-DM messages processing. * Receives and verifies the PIM control messages, and passes them * up to the listening socket, using rip_input(). * The only message with special processing is the PIM_REGISTER message * (used by PIM-SM): the PIM header is stripped off, and the inner packet * is passed to if_simloop(). */
| 2553 | * is passed to if_simloop(). |
| 2554 | */ |
| 2555 | static int |
| 2556 | pim_input(struct mbuf *m, int off, int proto, void *arg __unused) |
| 2557 | { |
| 2558 | struct ip *ip = mtod(m, struct ip *); |
| 2559 | struct pim *pim; |
| 2560 | int iphlen = off; |
| 2561 | int minlen; |
| 2562 | int datalen = ntohs(ip->ip_len) - iphlen; |
| 2563 | int ip_tos; |
| 2564 | |
| 2565 | /* Keep statistics */ |
| 2566 | PIMSTAT_INC(pims_rcv_total_msgs); |
| 2567 | PIMSTAT_ADD(pims_rcv_total_bytes, datalen); |
| 2568 | |
| 2569 | /* |
| 2570 | * Validate lengths |
| 2571 | */ |
| 2572 | if (datalen < PIM_MINLEN) { |
| 2573 | PIMSTAT_INC(pims_rcv_tooshort); |
| 2574 | CTR3(KTR_IPMF, "%s: short packet (%d) from 0x%08x", |
| 2575 | __func__, datalen, ntohl(ip->ip_src.s_addr)); |
| 2576 | m_freem(m); |
| 2577 | return (IPPROTO_DONE); |
| 2578 | } |
| 2579 | |
| 2580 | /* |
| 2581 | * If the packet is at least as big as a REGISTER, go agead |
| 2582 | * and grab the PIM REGISTER header size, to avoid another |
| 2583 | * possible m_pullup() later. |
| 2584 | * |
| 2585 | * PIM_MINLEN == pimhdr + u_int32_t == 4 + 4 = 8 |
| 2586 | * PIM_REG_MINLEN == pimhdr + reghdr + encap_iphdr == 4 + 4 + 20 = 28 |
| 2587 | */ |
| 2588 | minlen = iphlen + (datalen >= PIM_REG_MINLEN ? PIM_REG_MINLEN : PIM_MINLEN); |
| 2589 | /* |
| 2590 | * Get the IP and PIM headers in contiguous memory, and |
| 2591 | * possibly the PIM REGISTER header. |
| 2592 | */ |
| 2593 | if (m->m_len < minlen && (m = m_pullup(m, minlen)) == NULL) { |
| 2594 | CTR1(KTR_IPMF, "%s: m_pullup() failed", __func__); |
| 2595 | return (IPPROTO_DONE); |
| 2596 | } |
| 2597 | |
| 2598 | /* m_pullup() may have given us a new mbuf so reset ip. */ |
| 2599 | ip = mtod(m, struct ip *); |
| 2600 | ip_tos = ip->ip_tos; |
| 2601 | |
| 2602 | /* adjust mbuf to point to the PIM header */ |
| 2603 | m->m_data += iphlen; |
| 2604 | m->m_len -= iphlen; |
| 2605 | pim = mtod(m, struct pim *); |
| 2606 | |
| 2607 | /* |
| 2608 | * Validate checksum. If PIM REGISTER, exclude the data packet. |
| 2609 | * |
| 2610 | * XXX: some older PIMv2 implementations don't make this distinction, |
| 2611 | * so for compatibility reason perform the checksum over part of the |
| 2612 | * message, and if error, then over the whole message. |