| 889 | } |
| 890 | |
| 891 | static int |
| 892 | ipsec_encap(struct mbuf **mp, struct secasindex *saidx) |
| 893 | { |
| 894 | #ifdef INET6 |
| 895 | struct ip6_hdr *ip6; |
| 896 | #endif |
| 897 | struct ip *ip; |
| 898 | int setdf; |
| 899 | uint8_t itos, proto; |
| 900 | |
| 901 | ip = mtod(*mp, struct ip *); |
| 902 | switch (ip->ip_v) { |
| 903 | #ifdef INET |
| 904 | case IPVERSION: |
| 905 | proto = IPPROTO_IPIP; |
| 906 | /* |
| 907 | * Collect IP_DF state from the inner header |
| 908 | * and honor system-wide control of how to handle it. |
| 909 | */ |
| 910 | switch (V_ip4_ipsec_dfbit) { |
| 911 | case 0: /* clear in outer header */ |
| 912 | case 1: /* set in outer header */ |
| 913 | setdf = V_ip4_ipsec_dfbit; |
| 914 | break; |
| 915 | default:/* propagate to outer header */ |
| 916 | setdf = (ip->ip_off & htons(IP_DF)) != 0; |
| 917 | } |
| 918 | itos = ip->ip_tos; |
| 919 | break; |
| 920 | #endif |
| 921 | #ifdef INET6 |
| 922 | case (IPV6_VERSION >> 4): |
| 923 | proto = IPPROTO_IPV6; |
| 924 | ip6 = mtod(*mp, struct ip6_hdr *); |
| 925 | itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; |
| 926 | setdf = V_ip4_ipsec_dfbit ? 1: 0; |
| 927 | /* scoped address handling */ |
| 928 | in6_clearscope(&ip6->ip6_src); |
| 929 | in6_clearscope(&ip6->ip6_dst); |
| 930 | break; |
| 931 | #endif |
| 932 | default: |
| 933 | return (EAFNOSUPPORT); |
| 934 | } |
| 935 | switch (saidx->dst.sa.sa_family) { |
| 936 | #ifdef INET |
| 937 | case AF_INET: |
| 938 | if (saidx->src.sa.sa_family != AF_INET || |
| 939 | saidx->src.sin.sin_addr.s_addr == INADDR_ANY || |
| 940 | saidx->dst.sin.sin_addr.s_addr == INADDR_ANY) |
| 941 | return (EINVAL); |
| 942 | *mp = ipsec_prepend(*mp, sizeof(struct ip), M_NOWAIT); |
| 943 | if (*mp == NULL) |
| 944 | return (ENOBUFS); |
| 945 | ip = mtod(*mp, struct ip *); |
| 946 | ip->ip_v = IPVERSION; |
| 947 | ip->ip_hl = sizeof(struct ip) >> 2; |
| 948 | ip->ip_p = proto; |
no test coverage detected