static int getsockopt(struct socket *sock, int lvl, int opt, char __user *ov, int __user *ol) { struct sock *sk = sock->sk; struct tipc_port *tport = tipc_sk_port(sk); int len; u32 value; int res; if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) return put_user(0, ol); if (lvl != SOL_TIPC) return -ENOPROTOOPT; if ((res = get_user(len, ol))) return res; lock_sock(sk); switch (opt) { case TIPC_IMPORTANCE: res = tipc_portimportance(tport->ref, &value); break; case TIPC_SRC_DROPPABLE: res = tipc_portunreliable(tport->ref, &value); break; case TIPC_DEST_DROPPABLE: res = tipc_portunreturnable(tport->ref, &value); break; case TIPC_CONN_TIMEOUT: value = jiffies_to_msecs(tipc_sk(sk)->conn_timeout); /* no need to set "res", since already 0 at this point */ break; case TIPC_NODE_RECVQ_DEPTH: value = (u32)atomic_read(&tipc_queue_size); break; case TIPC_SOCK_RECVQ_DEPTH: value = skb_queue_len(&sk->sk_receive_queue); break; default: res = -EINVAL; } release_sock(sk); if (res) { /* "get" failed */ } else if (len < sizeof(value)) { res = -EINVAL; } else if (copy_to_user(ov, &value, sizeof(value))) { res = -EFAULT; } else { res = put_user(sizeof(value), ol); } return res; }
static int getsockopt(struct socket *sock, int lvl, int opt, char __user *ov, int __user *ol) { struct tipc_sock *tsock = tipc_sk(sock->sk); int len; u32 value; int res; if ((lvl == IPPROTO_TCP) && (sock->type == SOCK_STREAM)) return put_user(0, ol); if (lvl != SOL_TIPC) return -ENOPROTOOPT; if ((res = get_user(len, ol))) return res; if (down_interruptible(&tsock->sem)) return -ERESTARTSYS; switch (opt) { case TIPC_IMPORTANCE: res = tipc_portimportance(tsock->p->ref, &value); break; case TIPC_SRC_DROPPABLE: res = tipc_portunreliable(tsock->p->ref, &value); break; case TIPC_DEST_DROPPABLE: res = tipc_portunreturnable(tsock->p->ref, &value); break; case TIPC_CONN_TIMEOUT: value = (sock->sk->sk_rcvtimeo * 1000) / HZ; break; default: res = -EINVAL; } if (res) { /* "get" failed */ } else if (len < sizeof(value)) { res = -EINVAL; } else if ((res = copy_to_user(ov, &value, sizeof(value)))) { /* couldn't return value */ } else { res = put_user(sizeof(value), ol); } up(&tsock->sem); return res; }