Beispiel #1
0
static void skb_clone_fraglist(struct sk_buff *skb)
{
	struct sk_buff *list;

	skb_walk_frags(skb, list)
		skb_get(list);
} 
Beispiel #2
0
int pep_write(struct sock *sk, struct sk_buff *skb)
{
	struct sk_buff *rskb, *fs;
	int flen = 0;

	if (pep_sk(sk)->aligned)
		return pipe_skb_send(sk, skb);

	rskb = alloc_skb(MAX_PNPIPE_HEADER, GFP_ATOMIC);
	if (!rskb) {
		kfree_skb(skb);
		return -ENOMEM;
	}
	skb_shinfo(rskb)->frag_list = skb;
	rskb->len += skb->len;
	rskb->data_len += rskb->len;
	rskb->truesize += rskb->len;

	/* Avoid nested fragments */
	skb_walk_frags(skb, fs)
		flen += fs->len;
	skb->next = skb_shinfo(skb)->frag_list;
	skb_frag_list_init(skb);
	skb->len -= flen;
	skb->data_len -= flen;
	skb->truesize -= flen;

	skb_reserve(rskb, MAX_PHONET_HEADER + 3);
	return pipe_skb_send(sk, rskb);
}
Beispiel #3
0
static struct sk_buff *sctp_gso_segment(struct sk_buff *skb,
					netdev_features_t features)
{
	struct sk_buff *segs = ERR_PTR(-EINVAL);
	struct sctphdr *sh;

	sh = sctp_hdr(skb);
	if (!pskb_may_pull(skb, sizeof(*sh)))
		goto out;

	__skb_pull(skb, sizeof(*sh));

	if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
		/* Packet is from an untrusted source, reset gso_segs. */
		struct skb_shared_info *pinfo = skb_shinfo(skb);
		struct sk_buff *frag_iter;

		pinfo->gso_segs = 0;
		if (skb->len != skb->data_len) {
			/* Means we have chunks in here too */
			pinfo->gso_segs++;
		}

		skb_walk_frags(skb, frag_iter)
			pinfo->gso_segs++;

		segs = NULL;
		goto out;
	}

	segs = skb_segment(skb, features | NETIF_F_HW_CSUM | NETIF_F_SG);
	if (IS_ERR(segs))
		goto out;

	/* All that is left is update SCTP CRC if necessary */
	if (!(features & NETIF_F_SCTP_CRC)) {
		for (skb = segs; skb; skb = skb->next) {
			if (skb->ip_summed == CHECKSUM_PARTIAL) {
				sh = sctp_hdr(skb);
				sh->checksum = sctp_gso_make_checksum(skb);
			}
		}
	}

out:
	return segs;
}
Beispiel #4
0
static int
mt76u_tx_build_sg(struct sk_buff *skb, struct urb *urb)
{
	int nsgs = 1 + skb_shinfo(skb)->nr_frags;
	struct sk_buff *iter;

	skb_walk_frags(skb, iter)
		nsgs += 1 + skb_shinfo(iter)->nr_frags;

	memset(urb->sg, 0, sizeof(*urb->sg) * MT_SG_MAX_SIZE);

	nsgs = min_t(int, MT_SG_MAX_SIZE, nsgs);
	sg_init_marker(urb->sg, nsgs);
	urb->num_sgs = nsgs;

	return skb_to_sgvec_nomark(skb, urb->sg, 0, skb->len);
}
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;
}
Beispiel #6
0
/* Do accounting for bytes received and hold a reference to the association
 * for each skb.
 */
static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
				       struct sctp_association *asoc)
{
	struct sk_buff *skb, *frag;

	skb = sctp_event2skb(event);
	/* Set the owner and charge rwnd for bytes received.  */
	sctp_ulpevent_set_owner(event, asoc);
	sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb));

	if (!skb->data_len)
		return;

	/* Note:  Not clearing the entire event struct as this is just a
	 * fragment of the real event.  However, we still need to do rwnd
	 * accounting.
	 * In general, the skb passed from IP can have only 1 level of
	 * fragments. But we allow multiple levels of fragments.
	 */
	skb_walk_frags(skb, frag)
		sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc);
}
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;
}