* Check for the presence of the IP Router Alert option [RFC2113] * in the header of an IPv4 datagram. * * This call is not intended for use from the forwarding path; it is here * so that protocol domains may check for the presence of the option. * Given how FreeBSD's IPv4 stack is currently structured, the Router Alert * option does not have much relevance to the implementation, though this
| 715 | * Return zero if not present or options are invalid, non-zero if present. |
| 716 | */ |
| 717 | int |
| 718 | ip_checkrouteralert(struct mbuf *m) |
| 719 | { |
| 720 | struct ip *ip = mtod(m, struct ip *); |
| 721 | u_char *cp; |
| 722 | int opt, optlen, cnt, found_ra; |
| 723 | |
| 724 | found_ra = 0; |
| 725 | cp = (u_char *)(ip + 1); |
| 726 | cnt = (ip->ip_hl << 2) - sizeof (struct ip); |
| 727 | for (; cnt > 0; cnt -= optlen, cp += optlen) { |
| 728 | opt = cp[IPOPT_OPTVAL]; |
| 729 | if (opt == IPOPT_EOL) |
| 730 | break; |
| 731 | if (opt == IPOPT_NOP) |
| 732 | optlen = 1; |
| 733 | else { |
| 734 | #ifdef INVARIANTS |
| 735 | if (cnt < IPOPT_OLEN + sizeof(*cp)) |
| 736 | break; |
| 737 | #endif |
| 738 | optlen = cp[IPOPT_OLEN]; |
| 739 | #ifdef INVARIANTS |
| 740 | if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt) |
| 741 | break; |
| 742 | #endif |
| 743 | } |
| 744 | switch (opt) { |
| 745 | case IPOPT_RA: |
| 746 | #ifdef INVARIANTS |
| 747 | if (optlen != IPOPT_OFFSET + sizeof(uint16_t) || |
| 748 | (*((uint16_t *)&cp[IPOPT_OFFSET]) != 0)) |
| 749 | break; |
| 750 | else |
| 751 | #endif |
| 752 | found_ra = 1; |
| 753 | break; |
| 754 | default: |
| 755 | break; |
| 756 | } |
| 757 | } |
| 758 | |
| 759 | return (found_ra); |
| 760 | } |