Example #1
0
static int
sctp_snat_handler(struct sk_buff *skb,
                  struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
{
    sctp_sctphdr_t *sctph;
    unsigned int sctphoff;
    struct sk_buff *iter;
    __be32 crc32;

#ifdef CONFIG_IP_VS_IPV6
    if (cp->af == AF_INET6)
        sctphoff = sizeof(struct ipv6hdr);
    else
#endif
        sctphoff = ip_hdrlen(skb);

    /* csum_check requires unshared skb */
    if (!skb_make_writable(skb, sctphoff + sizeof(*sctph)))
        return 0;

    if (unlikely(cp->app != NULL)) {
        /* Some checks before mangling */
        if (pp->csum_check && !pp->csum_check(cp->af, skb, pp))
            return 0;

        /* Call application helper if needed */
        if (!ip_vs_app_pkt_out(cp, skb))
            return 0;
    }

    sctph = (void *) skb_network_header(skb) + sctphoff;
    sctph->source = cp->vport;

    /* Calculate the checksum */
    crc32 = sctp_start_cksum((u8 *) sctph, skb_headlen(skb) - sctphoff);
    skb_walk_frags(skb, iter)
    crc32 = sctp_update_cksum((u8 *) iter->data, skb_headlen(iter),
                              crc32);
    crc32 = sctp_end_cksum(crc32);
    sctph->checksum = crc32;

    return 1;
}
Example #2
0
static bool
sctp_manip_pkt(struct sk_buff *skb,
           unsigned int iphdroff,
           const struct nf_conntrack_tuple *tuple,
           enum nf_nat_manip_type maniptype)
{
    const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
    sctp_sctphdr_t *hdr;
    unsigned int hdroff = iphdroff + iph->ihl*4;
    __be32 oldip, newip;
    u32 crc32;

    if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
        return false;

    iph = (struct iphdr *)(skb->data + iphdroff);
    hdr = (struct sctphdr *)(skb->data + hdroff);

    if (maniptype == IP_NAT_MANIP_SRC) {
        /* Get rid of src ip and src pt */
        oldip = iph->saddr;
        newip = tuple->src.u3.ip;
        hdr->source = tuple->src.u.sctp.port;
    } else {
        /* Get rid of dst ip and dst pt */
        oldip = iph->daddr;
        newip = tuple->dst.u3.ip;
        hdr->dest = tuple->dst.u.sctp.port;
    }

    crc32 = sctp_start_cksum((u8 *)hdr, skb_headlen(skb) - hdroff);
    for (skb = skb_shinfo(skb)->frag_list; skb; skb = skb->next)
        crc32 = sctp_update_cksum((u8 *)skb->data, skb_headlen(skb),
                      crc32);
    crc32 = sctp_end_cksum(crc32);
    hdr->checksum = htonl(crc32);

    return true;
}
Example #3
0
static int
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)
{
    unsigned int sctphoff;
    struct sctphdr *sh, _sctph;
    struct sk_buff *iter;
    __le32 cmp;
    __le32 val;
    __u32 tmp;

#ifdef CONFIG_IP_VS_IPV6
    if (af == AF_INET6)
        sctphoff = sizeof(struct ipv6hdr);
    else
#endif
        sctphoff = ip_hdrlen(skb);

    sh = skb_header_pointer(skb, sctphoff, sizeof(_sctph), &_sctph);
    if (sh == NULL)
        return 0;

    cmp = sh->checksum;

    tmp = sctp_start_cksum((__u8 *) sh, skb_headlen(skb));
    skb_walk_frags(skb, iter)
    tmp = sctp_update_cksum((__u8 *) iter->data,
                            skb_headlen(iter), tmp);

    val = sctp_end_cksum(tmp);

    if (val != cmp) {
        /* CRC failure, dump it. */
        IP_VS_DBG_RL_PKT(0, af, pp, skb, 0,
                         "Failed checksum for");
        return 0;
    }
    return 1;
}