static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb)
{
- if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
+ if ((raw6_sk(sk)->checksum || sk->sk_filter) &&
+ skb->ip_summed != CHECKSUM_UNNECESSARY) {
if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) {
/* FIXME: increment a raw6 drops counter here */
kfree_skb(skb);
ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
sin6->sin6_flowinfo = 0;
sin6->sin6_scope_id = 0;
- if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) {
- struct inet6_skb_parm *opt = (struct inet6_skb_parm *) skb->cb;
- sin6->sin6_scope_id = opt->iif;
- }
+ if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
+ sin6->sin6_scope_id = IP6CB(skb)->iif;
}
sock_recv_timestamp(msg, sk, skb);
struct sk_buff *skb;
int err = 0;
u16 *csum;
+ u32 tmp_csum;
+
+ if (!opt->checksum)
+ goto send;
if ((skb = skb_peek(&sk->sk_write_queue)) == NULL)
goto out;
goto out;
}
+ /* should be check HW csum miyazawa */
if (skb_queue_len(&sk->sk_write_queue) == 1) {
/*
* Only one fragment on the socket.
*/
- /* should be check HW csum miyazawa */
- *csum = csum_ipv6_magic(&fl->fl6_src,
- &fl->fl6_dst,
- len, fl->proto, skb->csum);
+ tmp_csum = skb->csum;
} else {
- u32 tmp_csum = 0;
+ tmp_csum = 0;
skb_queue_walk(&sk->sk_write_queue, skb) {
tmp_csum = csum_add(tmp_csum, skb->csum);
}
-
- tmp_csum = csum_ipv6_magic(&fl->fl6_src,
- &fl->fl6_dst,
- len, fl->proto, tmp_csum);
- *csum = tmp_csum;
}
+
+ /* in case cksum was not initialized */
+ if (unlikely(*csum))
+ tmp_csum = csum_sub(tmp_csum, *csum);
+
+ *csum = csum_ipv6_magic(&fl->fl6_src,
+ &fl->fl6_dst,
+ len, fl->proto, tmp_csum);
+
if (*csum == 0)
*csum = -1;
- ip6_push_pending_frames(sk);
+send:
+ err = ip6_push_pending_frames(sk);
out:
return err;
}
if (err)
goto error_fault;
- IP6_INC_STATS(Ip6OutRequests);
+ IP6_INC_STATS(OutRequests);
err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
dst_output);
if (err > 0)
err = -EFAULT;
kfree_skb(skb);
error:
- IP6_INC_STATS(Ip6OutDiscards);
+ IP6_INC_STATS(OutDiscards);
return err;
}
static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
if (err)
ip6_flush_pending_frames(sk);
- else if (!(msg->msg_flags & MSG_MORE)) {
- if (raw_opt->checksum) {
- err = rawv6_push_pending_frames(sk, &fl, raw_opt, len);
- } else {
- err = ip6_push_pending_frames(sk);
- }
- }
+ else if (!(msg->msg_flags & MSG_MORE))
+ err = rawv6_push_pending_frames(sk, &fl, raw_opt, len);
}
done:
ip6_dst_store(sk, dst,
}
static int rawv6_seticmpfilter(struct sock *sk, int level, int optname,
- char *optval, int optlen)
+ char __user *optval, int optlen)
{
switch (optname) {
case ICMPV6_FILTER:
}
static int rawv6_geticmpfilter(struct sock *sk, int level, int optname,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
int len;
static int rawv6_setsockopt(struct sock *sk, int level, int optname,
- char *optval, int optlen)
+ char __user *optval, int optlen)
{
struct raw6_opt *opt = raw6_sk(sk);
int val;
optlen);
};
- if (get_user(val, (int *)optval))
+ if (get_user(val, (int __user *)optval))
return -EFAULT;
switch (optname) {
}
static int rawv6_getsockopt(struct sock *sk, int level, int optname,
- char *optval, int *optlen)
+ char __user *optval, int __user *optlen)
{
struct raw6_opt *opt = raw6_sk(sk);
int val, len;
case SIOCOUTQ:
{
int amount = atomic_read(&sk->sk_wmem_alloc);
- return put_user(amount, (int *)arg);
+ return put_user(amount, (int __user *)arg);
}
case SIOCINQ:
{
if (skb != NULL)
amount = skb->tail - skb->h.raw;
spin_unlock_irq(&sk->sk_receive_queue.lock);
- return put_user(amount, (int *)arg);
+ return put_user(amount, (int __user *)arg);
}
default: