コード例 #1
0
/**
 *	llc_ui_accept - accept a new incoming connection.
 *	@sock: Socket which connections arrive on.
 *	@newsock: Socket to move incoming connection to.
 *	@flags: User specified operational flags.
 *
 *	Accept a new incoming connection.
 *	Returns 0 upon success, negative otherwise.
 */
static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
{
	struct sock *sk = sock->sk, *newsk;
	struct llc_opt *llc, *newllc;
	struct sk_buff *skb;
	int rc = -EOPNOTSUPP;

	dprintk("%s: accepting on %02X\n", __FUNCTION__,
	        llc_sk(sk)->laddr.lsap);
	lock_sock(sk);
	if (sk->sk_type != SOCK_STREAM)
		goto out;
	rc = -EINVAL;
	if (sock->state != SS_UNCONNECTED || sk->sk_state != TCP_LISTEN)
		goto out;
	/* wait for a connection to arrive. */
	rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo);
	if (rc)
		goto out;
	dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
	        llc_sk(sk)->laddr.lsap);
	skb = skb_dequeue(&sk->sk_receive_queue);
	rc = -EINVAL;
	if (!skb->sk)
		goto frees;
	rc = 0;
	newsk = skb->sk;
	/* attach connection to a new socket. */
	llc_ui_sk_init(newsock, newsk);
	newsk->sk_pair		= NULL;
	newsk->sk_zapped	= 0;
	newsk->sk_state		= TCP_ESTABLISHED;
	newsock->state		= SS_CONNECTED;
	llc			= llc_sk(sk);
	newllc			= llc_sk(newsk);
	memcpy(&newllc->addr, &llc->addr, sizeof(newllc->addr));
	newllc->link = llc_ui_next_link_no(newllc->laddr.lsap);

	/* put original socket back into a clean listen state. */
	sk->sk_state = TCP_LISTEN;
	sk->sk_ack_backlog--;
	skb->sk = NULL;
	dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,
		llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
frees:
	kfree_skb(skb);
out:
	release_sock(sk);
	return rc;
}
コード例 #2
0
ファイル: af_llc.c プロジェクト: Dronevery/JetsonTK1-kernel
/**
 *	llc_ui_recvmsg - copy received data to the socket user.
 *	@sock: Socket to copy data from.
 *	@msg: Various user space related information.
 *	@size: Size of user buffer.
 *	@flags: User specified flags.
 *
 *	Copy received data to the socket user.
 *	Returns non-negative upon success, negative otherwise.
 */
static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
			  struct msghdr *msg, size_t size, int flags)
{
	struct sock *sk = sock->sk;
	struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;
	struct sk_buff *skb;
	size_t copied = 0;
	int rc = -ENOMEM, timeout;
	int noblock = flags & MSG_DONTWAIT;

	dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__,
		llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
	lock_sock(sk);
	timeout = sock_rcvtimeo(sk, noblock);
	rc = llc_ui_wait_for_data(sk, timeout);
	if (rc) {
		dprintk("%s: llc_ui_wait_for_data failed recv "
			"in %02X from %02X\n", __FUNCTION__,
			llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
		goto out;
	}
	skb = skb_dequeue(&sk->sk_receive_queue);
	if (!skb) /* shutdown */
		goto out;
	copied = skb->len;
	if (copied > size)
		copied = size;
	rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
	if (rc)
		goto dgram_free;
	if (skb->len > copied) {
		skb_pull(skb, copied);
		skb_queue_head(&sk->sk_receive_queue, skb);
	}
	if (uaddr)
		memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
	msg->msg_namelen = sizeof(*uaddr);
	if (!skb->list) {
dgram_free:
		kfree_skb(skb);
	}
out:
	release_sock(sk);
	return rc ? : copied;
}