Exemplo n.º 1
0
/*
 * Process event packets targetted at a local endpoint.
 */
void rxrpc_process_local_events(struct rxrpc_local *local)
{
	struct sk_buff *skb;
	char v;

	_enter("");

	skb = skb_dequeue(&local->event_queue);
	if (skb) {
		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

		rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
		_debug("{%d},{%u}", local->debug_id, sp->hdr.type);

		switch (sp->hdr.type) {
		case RXRPC_PACKET_TYPE_VERSION:
			if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
					  &v, 1) < 0)
				return;
			_proto("Rx VERSION { %02x }", v);
			if (v == 0)
				rxrpc_send_version_request(local, &sp->hdr, skb);
			break;

		default:
			/* Just ignore anything we don't understand */
			break;
		}

		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
	}

	_leave("");
}
Exemplo n.º 2
0
/*
 * queue a packet for recvmsg to pass to userspace
 * - the caller must hold a lock on call->lock
 * - must not be called with interrupts disabled (sk_filter() disables BH's)
 * - eats the packet whether successful or not
 * - there must be just one reference to the packet, which the caller passes to
 *   this function
 */
int rxrpc_queue_rcv_skb(struct rxrpc_call *call, struct sk_buff *skb,
			bool force, bool terminal)
{
	struct rxrpc_skb_priv *sp;
	struct rxrpc_sock *rx = call->socket;
	struct sock *sk;
	int ret;

	_enter(",,%d,%d", force, terminal);

	ASSERT(!irqs_disabled());

	sp = rxrpc_skb(skb);
	ASSERTCMP(sp->call, ==, call);

	/* if we've already posted the terminal message for a call, then we
	 * don't post any more */
	if (test_bit(RXRPC_CALL_TERMINAL_MSG, &call->flags)) {
		_debug("already terminated");
		ASSERTCMP(call->state, >=, RXRPC_CALL_COMPLETE);
		skb->destructor = NULL;
		sp->call = NULL;
		rxrpc_put_call(call);
		rxrpc_free_skb(skb);
		return 0;
	}
Exemplo n.º 3
0
/*
 * connection-level Rx packet processor
 */
static int rxrpc_process_event(struct rxrpc_connection *conn,
			       struct sk_buff *skb,
			       u32 *_abort_code)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	__be32 wtmp;
	u32 abort_code;
	int loop, ret;

	if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) {
		kleave(" = -ECONNABORTED [%u]", conn->state);
		return -ECONNABORTED;
	}

	_enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial);

	switch (sp->hdr.type) {
	case RXRPC_PACKET_TYPE_ABORT:
		if (skb_copy_bits(skb, 0, &wtmp, sizeof(wtmp)) < 0)
			return -EPROTO;
		abort_code = ntohl(wtmp);
		_proto("Rx ABORT %%%u { ac=%d }", sp->hdr.serial, abort_code);

		conn->state = RXRPC_CONN_REMOTELY_ABORTED;
		rxrpc_abort_calls(conn, RXRPC_CALL_REMOTELY_ABORTED,
				  abort_code);
		return -ECONNABORTED;

	case RXRPC_PACKET_TYPE_CHALLENGE:
		return conn->security->respond_to_challenge(conn, skb,
							    _abort_code);

	case RXRPC_PACKET_TYPE_RESPONSE:
		ret = conn->security->verify_response(conn, skb, _abort_code);
		if (ret < 0)
			return ret;

		ret = conn->security->init_connection_security(conn);
		if (ret < 0)
			return ret;

		conn->security->prime_packet_security(conn);
		read_lock_bh(&conn->lock);
		spin_lock(&conn->state_lock);

		if (conn->state == RXRPC_CONN_SERVER_CHALLENGING) {
			conn->state = RXRPC_CONN_SERVER;
			for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
				rxrpc_call_is_secure(conn->channels[loop]);
		}

		spin_unlock(&conn->state_lock);
		read_unlock_bh(&conn->lock);
		return 0;

	default:
		_leave(" = -EPROTO [%u]", sp->hdr.type);
		return -EPROTO;
	}
}
Exemplo n.º 4
0
/**
 * rxrpc_kernel_is_data_last - Determine if data message is last one
 * @skb: Message holding data
 *
 * Determine if data message is last one for the parent call.
 */
bool rxrpc_kernel_is_data_last(struct sk_buff *skb)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	ASSERTCMP(skb->mark, ==, RXRPC_SKB_MARK_DATA);

	return sp->hdr.flags & RXRPC_LAST_PACKET;
}
Exemplo n.º 5
0
/**
 * rxrpc_kernel_get_abort_code - Get the abort code from an RxRPC abort message
 * @skb: Message indicating an abort
 *
 * Get the abort code from an RxRPC abort message.
 */
u32 rxrpc_kernel_get_abort_code(struct sk_buff *skb)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	ASSERTCMP(skb->mark, ==, RXRPC_SKB_MARK_REMOTE_ABORT);

	return sp->call->abort_code;
}
Exemplo n.º 6
0
void rxrpc_process_connection(struct work_struct *work)
{
	struct rxrpc_connection *conn =
		container_of(work, struct rxrpc_connection, processor);
	struct rxrpc_skb_priv *sp;
	struct sk_buff *skb;
	u32 abort_code = RX_PROTOCOL_ERROR;
	int ret;

	_enter("{%d}", conn->debug_id);

	atomic_inc(&conn->usage);

	if (test_and_clear_bit(RXRPC_CONN_CHALLENGE, &conn->events)) {
		rxrpc_secure_connection(conn);
		rxrpc_put_connection(conn);
	}

	/* go through the conn-level event packets, releasing the ref on this
	 * connection that each one has when we've finished with it */
	while ((skb = skb_dequeue(&conn->rx_queue))) {
		sp = rxrpc_skb(skb);

		ret = rxrpc_process_event(conn, skb, &abort_code);
		switch (ret) {
		case -EPROTO:
		case -EKEYEXPIRED:
		case -EKEYREJECTED:
			goto protocol_error;
		case -EAGAIN:
			goto requeue_and_leave;
		case -ECONNABORTED:
		default:
			rxrpc_put_connection(conn);
			rxrpc_free_skb(skb);
			break;
		}
	}

out:
	rxrpc_put_connection(conn);
	_leave("");
	return;

requeue_and_leave:
	skb_queue_head(&conn->rx_queue, skb);
	goto out;

protocol_error:
	if (rxrpc_abort_connection(conn, -ret, abort_code) < 0)
		goto requeue_and_leave;
	rxrpc_put_connection(conn);
	rxrpc_free_skb(skb);
	_leave(" [EPROTO]");
	goto out;
}
Exemplo n.º 7
0
static int none_verify_response(struct rxrpc_connection *conn,
				struct sk_buff *skb,
				u32 *_abort_code)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
			      tracepoint_string("resp_none"));
	return -EPROTO;
}
Exemplo n.º 8
0
/**
 * rxrpc_kernel_data_delivered - Record delivery of data message
 * @skb: Message holding data
 *
 * Record the delivery of a data message.  This permits RxRPC to keep its
 * tracking correct.  The socket buffer will be deleted.
 */
void rxrpc_kernel_data_delivered(struct sk_buff *skb)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	struct rxrpc_call *call = sp->call;

	ASSERTCMP(ntohl(sp->hdr.seq), >=, call->rx_data_recv);
	ASSERTCMP(ntohl(sp->hdr.seq), <=, call->rx_data_recv + 1);
	call->rx_data_recv = ntohl(sp->hdr.seq);

	ASSERTCMP(ntohl(sp->hdr.seq), >, call->rx_data_eaten);
	rxrpc_free_skb(skb);
}
Exemplo n.º 9
0
/*
 * reject packets through the local endpoint
 */
void rxrpc_reject_packets(struct rxrpc_local *local)
{
	struct sockaddr_rxrpc srx;
	struct rxrpc_skb_priv *sp;
	struct rxrpc_wire_header whdr;
	struct sk_buff *skb;
	struct msghdr msg;
	struct kvec iov[2];
	size_t size;
	__be32 code;

	_enter("%d", local->debug_id);

	iov[0].iov_base = &whdr;
	iov[0].iov_len = sizeof(whdr);
	iov[1].iov_base = &code;
	iov[1].iov_len = sizeof(code);
	size = sizeof(whdr) + sizeof(code);

	msg.msg_name = &srx.transport;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = 0;

	memset(&whdr, 0, sizeof(whdr));
	whdr.type = RXRPC_PACKET_TYPE_ABORT;

	while ((skb = skb_dequeue(&local->reject_queue))) {
		rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
		sp = rxrpc_skb(skb);

		if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) {
			msg.msg_namelen = srx.transport_len;

			code = htonl(skb->priority);

			whdr.epoch	= htonl(sp->hdr.epoch);
			whdr.cid	= htonl(sp->hdr.cid);
			whdr.callNumber	= htonl(sp->hdr.callNumber);
			whdr.serviceId	= htons(sp->hdr.serviceId);
			whdr.flags	= sp->hdr.flags;
			whdr.flags	^= RXRPC_CLIENT_INITIATED;
			whdr.flags	&= RXRPC_CLIENT_INITIATED;

			kernel_sendmsg(local->socket, &msg, iov, 2, size);
		}

		rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
	}

	_leave("");
}
Exemplo n.º 10
0
/**
 * rxrpc_kernel_get_abort_code - Get the abort code from an RxRPC abort message
 * @skb: Message indicating an abort
 *
 * Get the abort code from an RxRPC abort message.
 */
u32 rxrpc_kernel_get_abort_code(struct sk_buff *skb)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	switch (skb->mark) {
	case RXRPC_SKB_MARK_REMOTE_ABORT:
		return sp->call->remote_abort;
	case RXRPC_SKB_MARK_LOCAL_ABORT:
		return sp->call->local_abort;
	default:
		BUG();
	}
}
Exemplo n.º 11
0
/*
 * Reply to a version request
 */
static void rxrpc_send_version_request(struct rxrpc_local *local,
				       struct rxrpc_host_header *hdr,
				       struct sk_buff *skb)
{
	struct rxrpc_wire_header whdr;
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	struct sockaddr_rxrpc srx;
	struct msghdr msg;
	struct kvec iov[2];
	size_t len;
	int ret;

	_enter("");

	if (rxrpc_extract_addr_from_skb(local, &srx, skb) < 0)
		return;

	msg.msg_name	= &srx.transport;
	msg.msg_namelen	= srx.transport_len;
	msg.msg_control	= NULL;
	msg.msg_controllen = 0;
	msg.msg_flags	= 0;

	whdr.epoch	= htonl(sp->hdr.epoch);
	whdr.cid	= htonl(sp->hdr.cid);
	whdr.callNumber	= htonl(sp->hdr.callNumber);
	whdr.seq	= 0;
	whdr.serial	= 0;
	whdr.type	= RXRPC_PACKET_TYPE_VERSION;
	whdr.flags	= RXRPC_LAST_PACKET | (~hdr->flags & RXRPC_CLIENT_INITIATED);
	whdr.userStatus	= 0;
	whdr.securityIndex = 0;
	whdr._rsvd	= 0;
	whdr.serviceId	= htons(sp->hdr.serviceId);

	iov[0].iov_base	= &whdr;
	iov[0].iov_len	= sizeof(whdr);
	iov[1].iov_base	= (char *)rxrpc_version_string;
	iov[1].iov_len	= sizeof(rxrpc_version_string);

	len = iov[0].iov_len + iov[1].iov_len;

	_proto("Tx VERSION (reply)");

	ret = kernel_sendmsg(local->socket, &msg, iov, 2, len);
	if (ret < 0)
		trace_rxrpc_tx_fail(local->debug_id, 0, ret,
				    rxrpc_tx_fail_version_reply);

	_leave("");
}
Exemplo n.º 12
0
/*
 * Discard a packet we've used up and advance the Rx window by one.
 */
static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
{
    struct rxrpc_skb_priv *sp;
    struct sk_buff *skb;
    rxrpc_serial_t serial;
    rxrpc_seq_t hard_ack, top;
    u8 flags;
    int ix;

    _enter("%d", call->debug_id);

    hard_ack = call->rx_hard_ack;
    top = smp_load_acquire(&call->rx_top);
    ASSERT(before(hard_ack, top));

    hard_ack++;
    ix = hard_ack & RXRPC_RXTX_BUFF_MASK;
    skb = call->rxtx_buffer[ix];
    rxrpc_see_skb(skb, rxrpc_skb_rx_rotated);
    sp = rxrpc_skb(skb);
    flags = sp->hdr.flags;
    serial = sp->hdr.serial;
    if (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO)
        serial += (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO) - 1;

    call->rxtx_buffer[ix] = NULL;
    call->rxtx_annotations[ix] = 0;
    /* Barrier against rxrpc_input_data(). */
    smp_store_release(&call->rx_hard_ack, hard_ack);

    rxrpc_free_skb(skb, rxrpc_skb_rx_freed);

    _debug("%u,%u,%02x", hard_ack, top, flags);
    trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
    if (flags & RXRPC_LAST_PACKET) {
        rxrpc_end_rx_phase(call, serial);
    } else {
        /* Check to see if there's an ACK that needs sending. */
        if (after_eq(hard_ack, call->ackr_consumed + 2) ||
                after_eq(top, call->ackr_seen + 2) ||
                (hard_ack == top && after(hard_ack, call->ackr_consumed)))
            rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial,
                              true, false,
                              rxrpc_propose_ack_rotate_rx);
        if (call->ackr_reason)
            rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ACK);
    }
}
Exemplo n.º 13
0
/*
 * Set up an incoming connection.  This is called in BH context with the RCU
 * read lock held.
 */
void rxrpc_new_incoming_connection(struct rxrpc_connection *conn,
				   struct sk_buff *skb)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	_enter("");

	conn->proto.epoch	= sp->hdr.epoch;
	conn->proto.cid		= sp->hdr.cid & RXRPC_CIDMASK;
	conn->params.service_id	= sp->hdr.serviceId;
	conn->security_ix	= sp->hdr.securityIndex;
	conn->out_clientflag	= 0;
	if (conn->security_ix)
		conn->state	= RXRPC_CONN_SERVICE_UNSECURED;
	else
		conn->state	= RXRPC_CONN_SERVICE;

	/* Make the connection a target for incoming packets. */
	rxrpc_publish_service_conn(conn->params.peer, conn);

	_net("CONNECTION new %d {%x}", conn->debug_id, conn->proto.cid);
}
Exemplo n.º 14
0
/*
 * Find a service connection under RCU conditions.
 *
 * We could use a hash table, but that is subject to bucket stuffing by an
 * attacker as the client gets to pick the epoch and cid values and would know
 * the hash function.  So, instead, we use a hash table for the peer and from
 * that an rbtree to find the service connection.  Under ordinary circumstances
 * it might be slower than a large hash table, but it is at least limited in
 * depth.
 */
struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *peer,
						     struct sk_buff *skb)
{
	struct rxrpc_connection *conn = NULL;
	struct rxrpc_conn_proto k;
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	struct rb_node *p;
	unsigned int seq = 0;

	k.epoch	= sp->hdr.epoch;
	k.cid	= sp->hdr.cid & RXRPC_CIDMASK;

	do {
		/* Unfortunately, rbtree walking doesn't give reliable results
		 * under just the RCU read lock, so we have to check for
		 * changes.
		 */
		read_seqbegin_or_lock(&peer->service_conn_lock, &seq);

		p = rcu_dereference_raw(peer->service_conns.rb_node);
		while (p) {
			conn = rb_entry(p, struct rxrpc_connection, service_node);

			if (conn->proto.index_key < k.index_key)
				p = rcu_dereference_raw(p->rb_left);
			else if (conn->proto.index_key > k.index_key)
				p = rcu_dereference_raw(p->rb_right);
			else
				goto done;
			conn = NULL;
		}
	} while (need_seqretry(&peer->service_conn_lock, seq));

done:
	done_seqretry(&peer->service_conn_lock, seq);
	_leave(" = %d", conn ? conn->debug_id : -1);
	return conn;
}
Exemplo n.º 15
0
/*
 * Decrypt and verify a (sub)packet.  The packet's length may be changed due to
 * padding, but if this is the case, the packet length will be resident in the
 * socket buffer.  Note that we can't modify the master skb info as the skb may
 * be the home to multiple subpackets.
 */
static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
                               u8 annotation,
                               unsigned int offset, unsigned int len)
{
    struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
    rxrpc_seq_t seq = sp->hdr.seq;
    u16 cksum = sp->hdr.cksum;

    _enter("");

    /* For all but the head jumbo subpacket, the security checksum is in a
     * jumbo header immediately prior to the data.
     */
    if ((annotation & RXRPC_RX_ANNO_JUMBO) > 1) {
        __be16 tmp;
        if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0)
            BUG();
        cksum = ntohs(tmp);
        seq += (annotation & RXRPC_RX_ANNO_JUMBO) - 1;
    }

    return call->conn->security->verify_packet(call, skb, offset, len,
            seq, cksum);
}
Exemplo n.º 16
0
/**
 * rxrpc_kernel_get_error - Get the error number from an RxRPC error message
 * @skb: Message indicating an error
 *
 * Get the error number from an RxRPC error message.
 */
int rxrpc_kernel_get_error_number(struct sk_buff *skb)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);

	return sp->error;
}
Exemplo n.º 17
0
/*
 * send a packet through the transport endpoint
 */
int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
			   bool retrans)
{
	struct rxrpc_connection *conn = call->conn;
	struct rxrpc_wire_header whdr;
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	struct msghdr msg;
	struct kvec iov[2];
	rxrpc_serial_t serial;
	size_t len;
	bool lost = false;
	int ret, opt;

	_enter(",{%d}", skb->len);

	/* Each transmission of a Tx packet needs a new serial number */
	serial = atomic_inc_return(&conn->serial);

	whdr.epoch	= htonl(conn->proto.epoch);
	whdr.cid	= htonl(call->cid);
	whdr.callNumber	= htonl(call->call_id);
	whdr.seq	= htonl(sp->hdr.seq);
	whdr.serial	= htonl(serial);
	whdr.type	= RXRPC_PACKET_TYPE_DATA;
	whdr.flags	= sp->hdr.flags;
	whdr.userStatus	= 0;
	whdr.securityIndex = call->security_ix;
	whdr._rsvd	= htons(sp->hdr._rsvd);
	whdr.serviceId	= htons(call->service_id);

	iov[0].iov_base = &whdr;
	iov[0].iov_len = sizeof(whdr);
	iov[1].iov_base = skb->head;
	iov[1].iov_len = skb->len;
	len = iov[0].iov_len + iov[1].iov_len;

	msg.msg_name = &call->peer->srx.transport;
	msg.msg_namelen = call->peer->srx.transport_len;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = 0;

	/* If our RTT cache needs working on, request an ACK.  Also request
	 * ACKs if a DATA packet appears to have been lost.
	 */
	if (!(sp->hdr.flags & RXRPC_LAST_PACKET) &&
	    (retrans ||
	     call->cong_mode == RXRPC_CALL_SLOW_START ||
	     (call->peer->rtt_usage < 3 && sp->hdr.seq & 1) ||
	     ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000),
			  ktime_get_real())))
		whdr.flags |= RXRPC_REQUEST_ACK;

	if (IS_ENABLED(CONFIG_AF_RXRPC_INJECT_LOSS)) {
		static int lose;
		if ((lose++ & 7) == 7) {
			ret = 0;
			lost = true;
			goto done;
		}
	}

	_proto("Tx DATA %%%u { #%u }", serial, sp->hdr.seq);

	/* send the packet with the don't fragment bit set if we currently
	 * think it's small enough */
	if (iov[1].iov_len >= call->peer->maxdata)
		goto send_fragmentable;

	down_read(&conn->params.local->defrag_sem);
	/* send the packet by UDP
	 * - returns -EMSGSIZE if UDP would have to fragment the packet
	 *   to go out of the interface
	 *   - in which case, we'll have processed the ICMP error
	 *     message and update the peer record
	 */
	ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);

	up_read(&conn->params.local->defrag_sem);
	if (ret == -EMSGSIZE)
		goto send_fragmentable;

done:
	trace_rxrpc_tx_data(call, sp->hdr.seq, serial, whdr.flags,
			    retrans, lost);
	if (ret >= 0) {
		ktime_t now = ktime_get_real();
		skb->tstamp = now;
		smp_wmb();
		sp->hdr.serial = serial;
		if (whdr.flags & RXRPC_REQUEST_ACK) {
			call->peer->rtt_last_req = now;
			trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_data, serial);
		}
	}
	_leave(" = %d [%u]", ret, call->peer->maxdata);
	return ret;

send_fragmentable:
	/* attempt to send this message with fragmentation enabled */
	_debug("send fragment");

	down_write(&conn->params.local->defrag_sem);

	switch (conn->params.local->srx.transport.family) {
	case AF_INET:
		opt = IP_PMTUDISC_DONT;
		ret = kernel_setsockopt(conn->params.local->socket,
					SOL_IP, IP_MTU_DISCOVER,
					(char *)&opt, sizeof(opt));
		if (ret == 0) {
			ret = kernel_sendmsg(conn->params.local->socket, &msg,
					     iov, 2, len);

			opt = IP_PMTUDISC_DO;
			kernel_setsockopt(conn->params.local->socket, SOL_IP,
					  IP_MTU_DISCOVER,
					  (char *)&opt, sizeof(opt));
		}
		break;

#ifdef CONFIG_AF_RXRPC_IPV6
	case AF_INET6:
		opt = IPV6_PMTUDISC_DONT;
		ret = kernel_setsockopt(conn->params.local->socket,
					SOL_IPV6, IPV6_MTU_DISCOVER,
					(char *)&opt, sizeof(opt));
		if (ret == 0) {
			ret = kernel_sendmsg(conn->params.local->socket, &msg,
					     iov, 1, iov[0].iov_len);

			opt = IPV6_PMTUDISC_DO;
			kernel_setsockopt(conn->params.local->socket,
					  SOL_IPV6, IPV6_MTU_DISCOVER,
					  (char *)&opt, sizeof(opt));
		}
		break;
#endif
	}

	up_write(&conn->params.local->defrag_sem);
	goto done;
}
Exemplo n.º 18
0
/*
 * Set up a new incoming call.  Called in BH context with the RCU read lock
 * held.
 *
 * If this is for a kernel service, when we allocate the call, it will have
 * three refs on it: (1) the kernel service, (2) the user_call_ID tree, (3) the
 * retainer ref obtained from the backlog buffer.  Prealloc calls for userspace
 * services only have the ref from the backlog buffer.  We want to pass this
 * ref to non-BH context to dispose of.
 *
 * If we want to report an error, we mark the skb with the packet type and
 * abort code and return NULL.
 *
 * The call is returned with the user access mutex held.
 */
struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
					   struct rxrpc_connection *conn,
					   struct sk_buff *skb)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	struct rxrpc_sock *rx;
	struct rxrpc_call *call;
	u16 service_id = sp->hdr.serviceId;

	_enter("");

	/* Get the socket providing the service */
	rx = rcu_dereference(local->service);
	if (rx && (service_id == rx->srx.srx_service ||
		   service_id == rx->second_service))
		goto found_service;

	trace_rxrpc_abort("INV", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
			  RX_INVALID_OPERATION, EOPNOTSUPP);
	skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT;
	skb->priority = RX_INVALID_OPERATION;
	_leave(" = NULL [service]");
	return NULL;

found_service:
	spin_lock(&rx->incoming_lock);
	if (rx->sk.sk_state == RXRPC_SERVER_LISTEN_DISABLED ||
	    rx->sk.sk_state == RXRPC_CLOSE) {
		trace_rxrpc_abort("CLS", sp->hdr.cid, sp->hdr.callNumber,
				  sp->hdr.seq, RX_INVALID_OPERATION, ESHUTDOWN);
		skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT;
		skb->priority = RX_INVALID_OPERATION;
		_leave(" = NULL [close]");
		call = NULL;
		goto out;
	}

	call = rxrpc_alloc_incoming_call(rx, local, conn, skb);
	if (!call) {
		skb->mark = RXRPC_SKB_MARK_BUSY;
		_leave(" = NULL [busy]");
		call = NULL;
		goto out;
	}

	trace_rxrpc_receive(call, rxrpc_receive_incoming,
			    sp->hdr.serial, sp->hdr.seq);

	/* Lock the call to prevent rxrpc_kernel_send/recv_data() and
	 * sendmsg()/recvmsg() inconveniently stealing the mutex once the
	 * notification is generated.
	 *
	 * The BUG should never happen because the kernel should be well
	 * behaved enough not to access the call before the first notification
	 * event and userspace is prevented from doing so until the state is
	 * appropriate.
	 */
	if (!mutex_trylock(&call->user_mutex))
		BUG();

	/* Make the call live. */
	rxrpc_incoming_call(rx, call, skb);
	conn = call->conn;

	if (rx->notify_new_call)
		rx->notify_new_call(&rx->sk, call, call->user_call_ID);
	else
		sk_acceptq_added(&rx->sk);

	spin_lock(&conn->state_lock);
	switch (conn->state) {
	case RXRPC_CONN_SERVICE_UNSECURED:
		conn->state = RXRPC_CONN_SERVICE_CHALLENGING;
		set_bit(RXRPC_CONN_EV_CHALLENGE, &call->conn->events);
		rxrpc_queue_conn(call->conn);
		break;

	case RXRPC_CONN_SERVICE:
		write_lock(&call->state_lock);
		if (rx->discard_new_call)
			call->state = RXRPC_CALL_SERVER_RECV_REQUEST;
		else
			call->state = RXRPC_CALL_SERVER_ACCEPTING;
		write_unlock(&call->state_lock);
		break;

	case RXRPC_CONN_REMOTELY_ABORTED:
		rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED,
					  conn->remote_abort, -ECONNABORTED);
		break;
	case RXRPC_CONN_LOCALLY_ABORTED:
		rxrpc_abort_call("CON", call, sp->hdr.seq,
				 conn->local_abort, -ECONNABORTED);
		break;
	default:
		BUG();
	}
	spin_unlock(&conn->state_lock);

	if (call->state == RXRPC_CALL_SERVER_ACCEPTING)
		rxrpc_notify_socket(call);

	/* We have to discard the prealloc queue's ref here and rely on a
	 * combination of the RCU read lock and refs held either by the socket
	 * (recvmsg queue, to-be-accepted queue or user ID tree) or the kernel
	 * service to prevent the call from being deallocated too early.
	 */
	rxrpc_put_call(call, rxrpc_call_put);

	_leave(" = %p{%d}", call, call->debug_id);
out:
	spin_unlock(&rx->incoming_lock);
	return call;
}
Exemplo n.º 19
0
/*
 * connection-level Rx packet processor
 */
static int rxrpc_process_event(struct rxrpc_connection *conn,
			       struct sk_buff *skb,
			       u32 *_abort_code)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	__be32 wtmp;
	u32 abort_code;
	int loop, ret;

	if (conn->state >= RXRPC_CONN_REMOTELY_ABORTED) {
		_leave(" = -ECONNABORTED [%u]", conn->state);
		return -ECONNABORTED;
	}

	_enter("{%d},{%u,%%%u},", conn->debug_id, sp->hdr.type, sp->hdr.serial);

	switch (sp->hdr.type) {
	case RXRPC_PACKET_TYPE_DATA:
	case RXRPC_PACKET_TYPE_ACK:
		rxrpc_conn_retransmit_call(conn, skb,
					   sp->hdr.cid & RXRPC_CHANNELMASK);
		return 0;

	case RXRPC_PACKET_TYPE_BUSY:
		/* Just ignore BUSY packets for now. */
		return 0;

	case RXRPC_PACKET_TYPE_ABORT:
		if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
				  &wtmp, sizeof(wtmp)) < 0) {
			trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
					      tracepoint_string("bad_abort"));
			return -EPROTO;
		}
		abort_code = ntohl(wtmp);
		_proto("Rx ABORT %%%u { ac=%d }", sp->hdr.serial, abort_code);

		conn->state = RXRPC_CONN_REMOTELY_ABORTED;
		rxrpc_abort_calls(conn, RXRPC_CALL_REMOTELY_ABORTED,
				  abort_code, -ECONNABORTED);
		return -ECONNABORTED;

	case RXRPC_PACKET_TYPE_CHALLENGE:
		return conn->security->respond_to_challenge(conn, skb,
							    _abort_code);

	case RXRPC_PACKET_TYPE_RESPONSE:
		ret = conn->security->verify_response(conn, skb, _abort_code);
		if (ret < 0)
			return ret;

		ret = conn->security->init_connection_security(conn);
		if (ret < 0)
			return ret;

		ret = conn->security->prime_packet_security(conn);
		if (ret < 0)
			return ret;

		spin_lock(&conn->channel_lock);
		spin_lock(&conn->state_lock);

		if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
			conn->state = RXRPC_CONN_SERVICE;
			spin_unlock(&conn->state_lock);
			for (loop = 0; loop < RXRPC_MAXCALLS; loop++)
				rxrpc_call_is_secure(
					rcu_dereference_protected(
						conn->channels[loop].call,
						lockdep_is_held(&conn->channel_lock)));
		} else {
			spin_unlock(&conn->state_lock);
		}

		spin_unlock(&conn->channel_lock);
		return 0;

	default:
		trace_rxrpc_rx_eproto(NULL, sp->hdr.serial,
				      tracepoint_string("bad_conn_pkt"));
		return -EPROTO;
	}
}
Exemplo n.º 20
0
/*
 * Retransmit terminal ACK or ABORT of the previous call.
 */
static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
				       struct sk_buff *skb,
				       unsigned int channel)
{
	struct rxrpc_skb_priv *sp = skb ? rxrpc_skb(skb) : NULL;
	struct rxrpc_channel *chan;
	struct msghdr msg;
	struct kvec iov[3];
	struct {
		struct rxrpc_wire_header whdr;
		union {
			__be32 abort_code;
			struct rxrpc_ackpacket ack;
		};
	} __attribute__((packed)) pkt;
	struct rxrpc_ackinfo ack_info;
	size_t len;
	int ret, ioc;
	u32 serial, mtu, call_id, padding;

	_enter("%d", conn->debug_id);

	chan = &conn->channels[channel];

	/* If the last call got moved on whilst we were waiting to run, just
	 * ignore this packet.
	 */
	call_id = READ_ONCE(chan->last_call);
	/* Sync with __rxrpc_disconnect_call() */
	smp_rmb();
	if (skb && call_id != sp->hdr.callNumber)
		return;

	msg.msg_name	= &conn->params.peer->srx.transport;
	msg.msg_namelen	= conn->params.peer->srx.transport_len;
	msg.msg_control	= NULL;
	msg.msg_controllen = 0;
	msg.msg_flags	= 0;

	iov[0].iov_base	= &pkt;
	iov[0].iov_len	= sizeof(pkt.whdr);
	iov[1].iov_base	= &padding;
	iov[1].iov_len	= 3;
	iov[2].iov_base	= &ack_info;
	iov[2].iov_len	= sizeof(ack_info);

	pkt.whdr.epoch		= htonl(conn->proto.epoch);
	pkt.whdr.cid		= htonl(conn->proto.cid | channel);
	pkt.whdr.callNumber	= htonl(call_id);
	pkt.whdr.seq		= 0;
	pkt.whdr.type		= chan->last_type;
	pkt.whdr.flags		= conn->out_clientflag;
	pkt.whdr.userStatus	= 0;
	pkt.whdr.securityIndex	= conn->security_ix;
	pkt.whdr._rsvd		= 0;
	pkt.whdr.serviceId	= htons(conn->service_id);

	len = sizeof(pkt.whdr);
	switch (chan->last_type) {
	case RXRPC_PACKET_TYPE_ABORT:
		pkt.abort_code	= htonl(chan->last_abort);
		iov[0].iov_len += sizeof(pkt.abort_code);
		len += sizeof(pkt.abort_code);
		ioc = 1;
		break;

	case RXRPC_PACKET_TYPE_ACK:
		mtu = conn->params.peer->if_mtu;
		mtu -= conn->params.peer->hdrsize;
		pkt.ack.bufferSpace	= 0;
		pkt.ack.maxSkew		= htons(skb ? skb->priority : 0);
		pkt.ack.firstPacket	= htonl(chan->last_seq + 1);
		pkt.ack.previousPacket	= htonl(chan->last_seq);
		pkt.ack.serial		= htonl(skb ? sp->hdr.serial : 0);
		pkt.ack.reason		= skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE;
		pkt.ack.nAcks		= 0;
		ack_info.rxMTU		= htonl(rxrpc_rx_mtu);
		ack_info.maxMTU		= htonl(mtu);
		ack_info.rwind		= htonl(rxrpc_rx_window_size);
		ack_info.jumbo_max	= htonl(rxrpc_rx_jumbo_max);
		pkt.whdr.flags		|= RXRPC_SLOW_START_OK;
		padding			= 0;
		iov[0].iov_len += sizeof(pkt.ack);
		len += sizeof(pkt.ack) + 3 + sizeof(ack_info);
		ioc = 3;
		break;

	default:
		return;
	}

	/* Resync with __rxrpc_disconnect_call() and check that the last call
	 * didn't get advanced whilst we were filling out the packets.
	 */
	smp_rmb();
	if (READ_ONCE(chan->last_call) != call_id)
		return;

	serial = atomic_inc_return(&conn->serial);
	pkt.whdr.serial = htonl(serial);

	switch (chan->last_type) {
	case RXRPC_PACKET_TYPE_ABORT:
		_proto("Tx ABORT %%%u { %d } [re]", serial, conn->local_abort);
		break;
	case RXRPC_PACKET_TYPE_ACK:
		trace_rxrpc_tx_ack(chan->call_debug_id, serial,
				   ntohl(pkt.ack.firstPacket),
				   ntohl(pkt.ack.serial),
				   pkt.ack.reason, 0);
		_proto("Tx ACK %%%u [re]", serial);
		break;
	}

	ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, ioc, len);
	conn->params.peer->last_tx_at = ktime_get_seconds();
	if (ret < 0)
		trace_rxrpc_tx_fail(chan->call_debug_id, serial, ret,
				    rxrpc_tx_point_call_final_resend);
	else
		trace_rxrpc_tx_packet(chan->call_debug_id, &pkt.whdr,
				      rxrpc_tx_point_call_final_resend);

	_leave("");
}
int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
		  struct msghdr *msg, size_t len, int flags)
{
	struct rxrpc_skb_priv *sp;
	struct rxrpc_call *call = NULL, *continue_call = NULL;
	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
	struct sk_buff *skb;
	long timeo;
	int copy, ret, ullen, offset, copied = 0;
	u32 abort_code;

	DEFINE_WAIT(wait);

	_enter(",,,%zu,%d", len, flags);

	if (flags & (MSG_OOB | MSG_TRUNC))
		return -EOPNOTSUPP;

	ullen = msg->msg_flags & MSG_CMSG_COMPAT ? 4 : sizeof(unsigned long);

	timeo = sock_rcvtimeo(&rx->sk, flags & MSG_DONTWAIT);
	msg->msg_flags |= MSG_MORE;

	lock_sock(&rx->sk);

	for (;;) {
		if (RB_EMPTY_ROOT(&rx->calls)) {
			if (copied)
				goto out;
			if (rx->sk.sk_state != RXRPC_SERVER_LISTENING) {
				release_sock(&rx->sk);
				if (continue_call)
					rxrpc_put_call(continue_call);
				return -ENODATA;
			}
		}

		
		skb = skb_peek(&rx->sk.sk_receive_queue);
		if (!skb) {
			
			if (copied &&
			    (msg->msg_flags & MSG_PEEK || timeo == 0))
				goto out;

			
			release_sock(&rx->sk);
			prepare_to_wait_exclusive(sk_sleep(&rx->sk), &wait,
						  TASK_INTERRUPTIBLE);
			ret = sock_error(&rx->sk);
			if (ret)
				goto wait_error;

			if (skb_queue_empty(&rx->sk.sk_receive_queue)) {
				if (signal_pending(current))
					goto wait_interrupted;
				timeo = schedule_timeout(timeo);
			}
			finish_wait(sk_sleep(&rx->sk), &wait);
			lock_sock(&rx->sk);
			continue;
		}

	peek_next_packet:
		sp = rxrpc_skb(skb);
		call = sp->call;
		ASSERT(call != NULL);

		_debug("next pkt %s", rxrpc_pkts[sp->hdr.type]);

		
		spin_lock_bh(&call->lock);
		spin_unlock_bh(&call->lock);

		if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
			_debug("packet from released call");
			if (skb_dequeue(&rx->sk.sk_receive_queue) != skb)
				BUG();
			rxrpc_free_skb(skb);
			continue;
		}

		
		if (continue_call) {
			_debug("maybe cont");
			if (call != continue_call ||
			    skb->mark != RXRPC_SKB_MARK_DATA) {
				release_sock(&rx->sk);
				rxrpc_put_call(continue_call);
				_leave(" = %d [noncont]", copied);
				return copied;
			}
		}

		rxrpc_get_call(call);

		
		if (!continue_call) {
			if (msg->msg_name && msg->msg_namelen > 0)
				memcpy(msg->msg_name,
				       &call->conn->trans->peer->srx,
				       sizeof(call->conn->trans->peer->srx));
			sock_recv_ts_and_drops(msg, &rx->sk, skb);
		}

		
		if (skb->mark != RXRPC_SKB_MARK_DATA)
			goto receive_non_data_message;

		_debug("recvmsg DATA #%u { %d, %d }",
		       ntohl(sp->hdr.seq), skb->len, sp->offset);

		if (!continue_call) {
			
			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID,
				       ullen, &call->user_call_ID);
			if (ret < 0)
				goto copy_error;
			ASSERT(test_bit(RXRPC_CALL_HAS_USERID, &call->flags));
		}

		ASSERTCMP(ntohl(sp->hdr.seq), >=, call->rx_data_recv);
		ASSERTCMP(ntohl(sp->hdr.seq), <=, call->rx_data_recv + 1);
		call->rx_data_recv = ntohl(sp->hdr.seq);

		ASSERTCMP(ntohl(sp->hdr.seq), >, call->rx_data_eaten);

		offset = sp->offset;
		copy = skb->len - offset;
		if (copy > len - copied)
			copy = len - copied;

		if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
			ret = skb_copy_datagram_iovec(skb, offset,
						      msg->msg_iov, copy);
		} else {
			ret = skb_copy_and_csum_datagram_iovec(skb, offset,
							       msg->msg_iov);
			if (ret == -EINVAL)
				goto csum_copy_error;
		}

		if (ret < 0)
			goto copy_error;

		
		_debug("copied %d+%d", copy, copied);

		offset += copy;
		copied += copy;

		if (!(flags & MSG_PEEK))
			sp->offset = offset;

		if (sp->offset < skb->len) {
			_debug("buffer full");
			ASSERTCMP(copied, ==, len);
			break;
		}

		
		if (sp->hdr.flags & RXRPC_LAST_PACKET) {
			_debug("last");
			if (call->conn->out_clientflag) {
				 
				ret = copied;
				goto terminal_message;
			}

			
			if (!(flags & MSG_PEEK)) {
				_debug("eat packet");
				if (skb_dequeue(&rx->sk.sk_receive_queue) !=
				    skb)
					BUG();
				rxrpc_free_skb(skb);
			}
			msg->msg_flags &= ~MSG_MORE;
			break;
		}

		
		_debug("next");
		if (!continue_call)
			continue_call = sp->call;
		else
			rxrpc_put_call(call);
		call = NULL;

		if (flags & MSG_PEEK) {
			_debug("peek next");
			skb = skb->next;
			if (skb == (struct sk_buff *) &rx->sk.sk_receive_queue)
				break;
			goto peek_next_packet;
		}

		_debug("eat packet");
		if (skb_dequeue(&rx->sk.sk_receive_queue) != skb)
			BUG();
		rxrpc_free_skb(skb);
	}
Exemplo n.º 22
0
/*
 * send data through a socket
 * - must be called in process context
 * - caller holds the socket locked
 */
static int rxrpc_send_data(struct kiocb *iocb,
			   struct rxrpc_sock *rx,
			   struct rxrpc_call *call,
			   struct msghdr *msg, size_t len)
{
	struct rxrpc_skb_priv *sp;
	unsigned char __user *from;
	struct sk_buff *skb;
	struct iovec *iov;
	struct sock *sk = &rx->sk;
	long timeo;
	bool more;
	int ret, ioc, segment, copied;

	_enter(",,,{%zu},%zu", msg->msg_iovlen, len);

	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);

	/* this should be in poll */
	clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);

	if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN))
		return -EPIPE;

	iov = msg->msg_iov;
	ioc = msg->msg_iovlen - 1;
	from = iov->iov_base;
	segment = iov->iov_len;
	iov++;
	more = msg->msg_flags & MSG_MORE;

	skb = call->tx_pending;
	call->tx_pending = NULL;

	copied = 0;
	do {
		int copy;

		if (segment > len)
			segment = len;

		_debug("SEGMENT %d @%p", segment, from);

		if (!skb) {
			size_t size, chunk, max, space;

			_debug("alloc");

			if (CIRC_SPACE(call->acks_head, call->acks_tail,
				       call->acks_winsz) <= 0) {
				ret = -EAGAIN;
				if (msg->msg_flags & MSG_DONTWAIT)
					goto maybe_error;
				ret = rxrpc_wait_for_tx_window(rx, call,
							       &timeo);
				if (ret < 0)
					goto maybe_error;
			}

			max = call->conn->trans->peer->maxdata;
			max -= call->conn->security_size;
			max &= ~(call->conn->size_align - 1UL);

			chunk = max;
			if (chunk > len && !more)
				chunk = len;

			space = chunk + call->conn->size_align;
			space &= ~(call->conn->size_align - 1UL);

			size = space + call->conn->header_size;

			_debug("SIZE: %zu/%zu/%zu", chunk, space, size);

			/* create a buffer that we can retain until it's ACK'd */
			skb = sock_alloc_send_skb(
				sk, size, msg->msg_flags & MSG_DONTWAIT, &ret);
			if (!skb)
				goto maybe_error;

			rxrpc_new_skb(skb);

			_debug("ALLOC SEND %p", skb);

			ASSERTCMP(skb->mark, ==, 0);

			_debug("HS: %u", call->conn->header_size);
			skb_reserve(skb, call->conn->header_size);
			skb->len += call->conn->header_size;

			sp = rxrpc_skb(skb);
			sp->remain = chunk;
			if (sp->remain > skb_tailroom(skb))
				sp->remain = skb_tailroom(skb);

			_net("skb: hr %d, tr %d, hl %d, rm %d",
			       skb_headroom(skb),
			       skb_tailroom(skb),
			       skb_headlen(skb),
			       sp->remain);

			skb->ip_summed = CHECKSUM_UNNECESSARY;
		}

		_debug("append");
		sp = rxrpc_skb(skb);

		/* append next segment of data to the current buffer */
		copy = skb_tailroom(skb);
		ASSERTCMP(copy, >, 0);
		if (copy > segment)
			copy = segment;
		if (copy > sp->remain)
			copy = sp->remain;

		_debug("add");
		ret = skb_add_data(skb, from, copy);
		_debug("added");
		if (ret < 0)
			goto efault;
		sp->remain -= copy;
		skb->mark += copy;
		copied += copy;

		len -= copy;
		segment -= copy;
		from += copy;
		while (segment == 0 && ioc > 0) {
			from = iov->iov_base;
			segment = iov->iov_len;
			iov++;
			ioc--;
		}
		if (len == 0) {
			segment = 0;
			ioc = 0;
		}

		/* check for the far side aborting the call or a network error
		 * occurring */
		if (call->state > RXRPC_CALL_COMPLETE)
			goto call_aborted;

		/* add the packet to the send queue if it's now full */
		if (sp->remain <= 0 || (segment == 0 && !more)) {
			struct rxrpc_connection *conn = call->conn;
			size_t pad;

			/* pad out if we're using security */
			if (conn->security) {
				pad = conn->security_size + skb->mark;
				pad = conn->size_align - pad;
				pad &= conn->size_align - 1;
				_debug("pad %zu", pad);
				if (pad)
					memset(skb_put(skb, pad), 0, pad);
			}

			sp->hdr.epoch = conn->epoch;
			sp->hdr.cid = call->cid;
			sp->hdr.callNumber = call->call_id;
			sp->hdr.seq =
				htonl(atomic_inc_return(&call->sequence));
			sp->hdr.serial =
				htonl(atomic_inc_return(&conn->serial));
			sp->hdr.type = RXRPC_PACKET_TYPE_DATA;
			sp->hdr.userStatus = 0;
			sp->hdr.securityIndex = conn->security_ix;
			sp->hdr._rsvd = 0;
			sp->hdr.serviceId = conn->service_id;

			sp->hdr.flags = conn->out_clientflag;
			if (len == 0 && !more)
				sp->hdr.flags |= RXRPC_LAST_PACKET;
			else if (CIRC_SPACE(call->acks_head, call->acks_tail,
					    call->acks_winsz) > 1)
				sp->hdr.flags |= RXRPC_MORE_PACKETS;

			ret = rxrpc_secure_packet(
				call, skb, skb->mark,
				skb->head + sizeof(struct rxrpc_header));
			if (ret < 0)
				goto out;

			memcpy(skb->head, &sp->hdr,
			       sizeof(struct rxrpc_header));
			rxrpc_queue_packet(call, skb, segment == 0 && !more);
			skb = NULL;
		}

	} while (segment > 0);
Exemplo n.º 23
0
/*
 * queue a packet for transmission, set the resend timer and attempt
 * to send the packet immediately
 */
static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb,
			       bool last)
{
	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
	int ret;

	_net("queue skb %p [%d]", skb, call->acks_head);

	ASSERT(call->acks_window != NULL);
	call->acks_window[call->acks_head] = (unsigned long) skb;
	smp_wmb();
	call->acks_head = (call->acks_head + 1) & (call->acks_winsz - 1);

	if (last || call->state == RXRPC_CALL_SERVER_ACK_REQUEST) {
		_debug("________awaiting reply/ACK__________");
		write_lock_bh(&call->state_lock);
		switch (call->state) {
		case RXRPC_CALL_CLIENT_SEND_REQUEST:
			call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY;
			break;
		case RXRPC_CALL_SERVER_ACK_REQUEST:
			call->state = RXRPC_CALL_SERVER_SEND_REPLY;
			if (!last)
				break;
		case RXRPC_CALL_SERVER_SEND_REPLY:
			call->state = RXRPC_CALL_SERVER_AWAIT_ACK;
			break;
		default:
			break;
		}
		write_unlock_bh(&call->state_lock);
	}

	_proto("Tx DATA %%%u { #%u }",
	       ntohl(sp->hdr.serial), ntohl(sp->hdr.seq));

	sp->need_resend = 0;
	sp->resend_at = jiffies + rxrpc_resend_timeout * HZ;
	if (!test_and_set_bit(RXRPC_CALL_RUN_RTIMER, &call->flags)) {
		_debug("run timer");
		call->resend_timer.expires = sp->resend_at;
		add_timer(&call->resend_timer);
	}

	/* attempt to cancel the rx-ACK timer, deferring reply transmission if
	 * we're ACK'ing the request phase of an incoming call */
	ret = -EAGAIN;
	if (try_to_del_timer_sync(&call->ack_timer) >= 0) {
		/* the packet may be freed by rxrpc_process_call() before this
		 * returns */
		ret = rxrpc_send_packet(call->conn->trans, skb);
		_net("sent skb %p", skb);
	} else {
		_debug("failed to delete ACK timer");
	}

	if (ret < 0) {
		_debug("need instant resend %d", ret);
		sp->need_resend = 1;
		rxrpc_instant_resend(call);
	}

	_leave("");
}
Exemplo n.º 24
0
void rxrpc_reject_packets(struct work_struct *work)
{
	union {
		struct sockaddr sa;
		struct sockaddr_in sin;
	} sa;
	struct rxrpc_skb_priv *sp;
	struct rxrpc_header hdr;
	struct rxrpc_local *local;
	struct sk_buff *skb;
	struct msghdr msg;
	struct kvec iov[2];
	size_t size;
	__be32 code;

	local = container_of(work, struct rxrpc_local, rejecter);
	rxrpc_get_local(local);

	_enter("%d", local->debug_id);

	iov[0].iov_base = &hdr;
	iov[0].iov_len = sizeof(hdr);
	iov[1].iov_base = &code;
	iov[1].iov_len = sizeof(code);
	size = sizeof(hdr) + sizeof(code);

	msg.msg_name = &sa;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = 0;

	memset(&sa, 0, sizeof(sa));
	sa.sa.sa_family = local->srx.transport.family;
	switch (sa.sa.sa_family) {
	case AF_INET:
		msg.msg_namelen = sizeof(sa.sin);
		break;
	default:
		msg.msg_namelen = 0;
		break;
	}

	memset(&hdr, 0, sizeof(hdr));
	hdr.type = RXRPC_PACKET_TYPE_ABORT;

	while ((skb = skb_dequeue(&local->reject_queue))) {
		sp = rxrpc_skb(skb);
		switch (sa.sa.sa_family) {
		case AF_INET:
			sa.sin.sin_port = udp_hdr(skb)->source;
			sa.sin.sin_addr.s_addr = ip_hdr(skb)->saddr;
			code = htonl(skb->priority);

			hdr.epoch = sp->hdr.epoch;
			hdr.cid = sp->hdr.cid;
			hdr.callNumber = sp->hdr.callNumber;
			hdr.serviceId = sp->hdr.serviceId;
			hdr.flags = sp->hdr.flags;
			hdr.flags ^= RXRPC_CLIENT_INITIATED;
			hdr.flags &= RXRPC_CLIENT_INITIATED;

			kernel_sendmsg(local->socket, &msg, iov, 2, size);
			break;

		default:
			break;
		}

		rxrpc_free_skb(skb);
		rxrpc_put_local(local);
	}

	rxrpc_put_local(local);
	_leave("");
}
Exemplo n.º 25
0
/*
 * Deliver messages to a call.  This keeps processing packets until the buffer
 * is filled and we find either more DATA (returns 0) or the end of the DATA
 * (returns 1).  If more packets are required, it returns -EAGAIN.
 */
static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
                              struct msghdr *msg, struct iov_iter *iter,
                              size_t len, int flags, size_t *_offset)
{
    struct rxrpc_skb_priv *sp;
    struct sk_buff *skb;
    rxrpc_seq_t hard_ack, top, seq;
    size_t remain;
    bool last;
    unsigned int rx_pkt_offset, rx_pkt_len;
    int ix, copy, ret = -EAGAIN, ret2;

    rx_pkt_offset = call->rx_pkt_offset;
    rx_pkt_len = call->rx_pkt_len;

    if (call->state >= RXRPC_CALL_SERVER_ACK_REQUEST) {
        seq = call->rx_hard_ack;
        ret = 1;
        goto done;
    }

    /* Barriers against rxrpc_input_data(). */
    hard_ack = call->rx_hard_ack;
    top = smp_load_acquire(&call->rx_top);
    for (seq = hard_ack + 1; before_eq(seq, top); seq++) {
        ix = seq & RXRPC_RXTX_BUFF_MASK;
        skb = call->rxtx_buffer[ix];
        if (!skb) {
            trace_rxrpc_recvmsg(call, rxrpc_recvmsg_hole, seq,
                                rx_pkt_offset, rx_pkt_len, 0);
            break;
        }
        smp_rmb();
        rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
        sp = rxrpc_skb(skb);

        if (!(flags & MSG_PEEK))
            trace_rxrpc_receive(call, rxrpc_receive_front,
                                sp->hdr.serial, seq);

        if (msg)
            sock_recv_timestamp(msg, sock->sk, skb);

        if (rx_pkt_offset == 0) {
            ret2 = rxrpc_locate_data(call, skb,
                                     &call->rxtx_annotations[ix],
                                     &rx_pkt_offset, &rx_pkt_len);
            trace_rxrpc_recvmsg(call, rxrpc_recvmsg_next, seq,
                                rx_pkt_offset, rx_pkt_len, ret2);
            if (ret2 < 0) {
                ret = ret2;
                goto out;
            }
        } else {
            trace_rxrpc_recvmsg(call, rxrpc_recvmsg_cont, seq,
                                rx_pkt_offset, rx_pkt_len, 0);
        }

        /* We have to handle short, empty and used-up DATA packets. */
        remain = len - *_offset;
        copy = rx_pkt_len;
        if (copy > remain)
            copy = remain;
        if (copy > 0) {
            ret2 = skb_copy_datagram_iter(skb, rx_pkt_offset, iter,
                                          copy);
            if (ret2 < 0) {
                ret = ret2;
                goto out;
            }

            /* handle piecemeal consumption of data packets */
            rx_pkt_offset += copy;
            rx_pkt_len -= copy;
            *_offset += copy;
        }

        if (rx_pkt_len > 0) {
            trace_rxrpc_recvmsg(call, rxrpc_recvmsg_full, seq,
                                rx_pkt_offset, rx_pkt_len, 0);
            ASSERTCMP(*_offset, ==, len);
            ret = 0;
            break;
        }

        /* The whole packet has been transferred. */
        last = sp->hdr.flags & RXRPC_LAST_PACKET;
        if (!(flags & MSG_PEEK))
            rxrpc_rotate_rx_window(call);
        rx_pkt_offset = 0;
        rx_pkt_len = 0;

        if (last) {
            ASSERTCMP(seq, ==, READ_ONCE(call->rx_top));
            ret = 1;
            goto out;
        }
    }
Exemplo n.º 26
0
/*
 * receive a message from an RxRPC socket
 * - we need to be careful about two or more threads calling recvmsg
 *   simultaneously
 */
int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock,
		  struct msghdr *msg, size_t len, int flags)
{
	struct rxrpc_skb_priv *sp;
	struct rxrpc_call *call = NULL, *continue_call = NULL;
	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
	struct sk_buff *skb;
	long timeo;
	int copy, ret, ullen, offset, copied = 0;
	u32 abort_code;

	DEFINE_WAIT(wait);

	_enter(",,,%zu,%d", len, flags);

	if (flags & (MSG_OOB | MSG_TRUNC))
		return -EOPNOTSUPP;

	ullen = msg->msg_flags & MSG_CMSG_COMPAT ? 4 : sizeof(unsigned long);

	timeo = sock_rcvtimeo(&rx->sk, flags & MSG_DONTWAIT);
	msg->msg_flags |= MSG_MORE;

	lock_sock(&rx->sk);

	for (;;) {
		/* return immediately if a client socket has no outstanding
		 * calls */
		if (RB_EMPTY_ROOT(&rx->calls)) {
			if (copied)
				goto out;
			if (rx->sk.sk_state != RXRPC_SERVER_LISTENING) {
				release_sock(&rx->sk);
				if (continue_call)
					rxrpc_put_call(continue_call);
				return -ENODATA;
			}
		}

		/* get the next message on the Rx queue */
		skb = skb_peek(&rx->sk.sk_receive_queue);
		if (!skb) {
			/* nothing remains on the queue */
			if (copied &&
			    (msg->msg_flags & MSG_PEEK || timeo == 0))
				goto out;

			/* wait for a message to turn up */
			release_sock(&rx->sk);
			prepare_to_wait_exclusive(sk_sleep(&rx->sk), &wait,
						  TASK_INTERRUPTIBLE);
			ret = sock_error(&rx->sk);
			if (ret)
				goto wait_error;

			if (skb_queue_empty(&rx->sk.sk_receive_queue)) {
				if (signal_pending(current))
					goto wait_interrupted;
				timeo = schedule_timeout(timeo);
			}
			finish_wait(sk_sleep(&rx->sk), &wait);
			lock_sock(&rx->sk);
			continue;
		}

	peek_next_packet:
		sp = rxrpc_skb(skb);
		call = sp->call;
		ASSERT(call != NULL);

		_debug("next pkt %s", rxrpc_pkts[sp->hdr.type]);

		/* make sure we wait for the state to be updated in this call */
		spin_lock_bh(&call->lock);
		spin_unlock_bh(&call->lock);

		if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
			_debug("packet from released call");
			if (skb_dequeue(&rx->sk.sk_receive_queue) != skb)
				BUG();
			rxrpc_free_skb(skb);
			continue;
		}

		/* determine whether to continue last data receive */
		if (continue_call) {
			_debug("maybe cont");
			if (call != continue_call ||
			    skb->mark != RXRPC_SKB_MARK_DATA) {
				release_sock(&rx->sk);
				rxrpc_put_call(continue_call);
				_leave(" = %d [noncont]", copied);
				return copied;
			}
		}

		rxrpc_get_call(call);

		/* copy the peer address and timestamp */
		if (!continue_call) {
			if (msg->msg_name) {
				size_t len =
					sizeof(call->conn->trans->peer->srx);
				memcpy(msg->msg_name,
				       &call->conn->trans->peer->srx, len);
				msg->msg_namelen = len;
			}
			sock_recv_ts_and_drops(msg, &rx->sk, skb);
		}

		/* receive the message */
		if (skb->mark != RXRPC_SKB_MARK_DATA)
			goto receive_non_data_message;

		_debug("recvmsg DATA #%u { %d, %d }",
		       ntohl(sp->hdr.seq), skb->len, sp->offset);

		if (!continue_call) {
			/* only set the control data once per recvmsg() */
			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID,
				       ullen, &call->user_call_ID);
			if (ret < 0)
				goto copy_error;
			ASSERT(test_bit(RXRPC_CALL_HAS_USERID, &call->flags));
		}

		ASSERTCMP(ntohl(sp->hdr.seq), >=, call->rx_data_recv);
		ASSERTCMP(ntohl(sp->hdr.seq), <=, call->rx_data_recv + 1);
		call->rx_data_recv = ntohl(sp->hdr.seq);

		ASSERTCMP(ntohl(sp->hdr.seq), >, call->rx_data_eaten);

		offset = sp->offset;
		copy = skb->len - offset;
		if (copy > len - copied)
			copy = len - copied;

		ret = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copy);

		if (ret < 0)
			goto copy_error;

		/* handle piecemeal consumption of data packets */
		_debug("copied %d+%d", copy, copied);

		offset += copy;
		copied += copy;

		if (!(flags & MSG_PEEK))
			sp->offset = offset;

		if (sp->offset < skb->len) {
			_debug("buffer full");
			ASSERTCMP(copied, ==, len);
			break;
		}

		/* we transferred the whole data packet */
		if (sp->hdr.flags & RXRPC_LAST_PACKET) {
			_debug("last");
			if (call->conn->out_clientflag) {
				 /* last byte of reply received */
				ret = copied;
				goto terminal_message;
			}

			/* last bit of request received */
			if (!(flags & MSG_PEEK)) {
				_debug("eat packet");
				if (skb_dequeue(&rx->sk.sk_receive_queue) !=
				    skb)
					BUG();
				rxrpc_free_skb(skb);
			}
			msg->msg_flags &= ~MSG_MORE;
			break;
		}

		/* move on to the next data message */
		_debug("next");
		if (!continue_call)
			continue_call = sp->call;
		else
			rxrpc_put_call(call);
		call = NULL;

		if (flags & MSG_PEEK) {
			_debug("peek next");
			skb = skb->next;
			if (skb == (struct sk_buff *) &rx->sk.sk_receive_queue)
				break;
			goto peek_next_packet;
		}

		_debug("eat packet");
		if (skb_dequeue(&rx->sk.sk_receive_queue) != skb)
			BUG();
		rxrpc_free_skb(skb);
	}
Exemplo n.º 27
0
/*
 * accept an incoming call that needs peer, transport and/or connection setting
 * up
 */
static int rxrpc_accept_incoming_call(struct rxrpc_local *local,
				      struct rxrpc_sock *rx,
				      struct sk_buff *skb,
				      struct sockaddr_rxrpc *srx)
{
	struct rxrpc_connection *conn;
	struct rxrpc_skb_priv *sp, *nsp;
	struct rxrpc_call *call;
	struct sk_buff *notification;
	int ret;

	_enter("");

	sp = rxrpc_skb(skb);

	/* get a notification message to send to the server app */
	notification = alloc_skb(0, GFP_NOFS);
	if (!notification) {
		_debug("no memory");
		ret = -ENOMEM;
		goto error_nofree;
	}
	rxrpc_new_skb(notification);
	notification->mark = RXRPC_SKB_MARK_NEW_CALL;

	conn = rxrpc_incoming_connection(local, srx, skb);
	if (IS_ERR(conn)) {
		_debug("no conn");
		ret = PTR_ERR(conn);
		goto error;
	}

	call = rxrpc_incoming_call(rx, conn, skb);
	rxrpc_put_connection(conn);
	if (IS_ERR(call)) {
		_debug("no call");
		ret = PTR_ERR(call);
		goto error;
	}

	/* attach the call to the socket */
	read_lock_bh(&local->services_lock);
	if (rx->sk.sk_state == RXRPC_CLOSE)
		goto invalid_service;

	write_lock(&rx->call_lock);
	if (!test_and_set_bit(RXRPC_CALL_INIT_ACCEPT, &call->flags)) {
		rxrpc_get_call(call);

		spin_lock(&call->conn->state_lock);
		if (sp->hdr.securityIndex > 0 &&
		    call->conn->state == RXRPC_CONN_SERVICE_UNSECURED) {
			_debug("await conn sec");
			list_add_tail(&call->accept_link, &rx->secureq);
			call->conn->state = RXRPC_CONN_SERVICE_CHALLENGING;
			set_bit(RXRPC_CONN_EV_CHALLENGE, &call->conn->events);
			rxrpc_queue_conn(call->conn);
		} else {
			_debug("conn ready");
			call->state = RXRPC_CALL_SERVER_ACCEPTING;
			list_add_tail(&call->accept_link, &rx->acceptq);
			rxrpc_get_call(call);
			atomic_inc(&call->skb_count);
			nsp = rxrpc_skb(notification);
			nsp->call = call;

			ASSERTCMP(atomic_read(&call->usage), >=, 3);

			_debug("notify");
			spin_lock(&call->lock);
			ret = rxrpc_queue_rcv_skb(call, notification, true,
						  false);
			spin_unlock(&call->lock);
			notification = NULL;
			BUG_ON(ret < 0);
		}
		spin_unlock(&call->conn->state_lock);

		_debug("queued");
	}
Exemplo n.º 28
0
/*
 * Perform retransmission of NAK'd and unack'd packets.
 */
static void rxrpc_resend(struct rxrpc_call *call, ktime_t now)
{
	struct rxrpc_skb_priv *sp;
	struct sk_buff *skb;
	rxrpc_seq_t cursor, seq, top;
	ktime_t max_age, oldest, ack_ts;
	int ix;
	u8 annotation, anno_type, retrans = 0, unacked = 0;

	_enter("{%d,%d}", call->tx_hard_ack, call->tx_top);

	max_age = ktime_sub_ms(now, rxrpc_resend_timeout);

	spin_lock_bh(&call->lock);

	cursor = call->tx_hard_ack;
	top = call->tx_top;
	ASSERT(before_eq(cursor, top));
	if (cursor == top)
		goto out_unlock;

	/* Scan the packet list without dropping the lock and decide which of
	 * the packets in the Tx buffer we're going to resend and what the new
	 * resend timeout will be.
	 */
	oldest = now;
	for (seq = cursor + 1; before_eq(seq, top); seq++) {
		ix = seq & RXRPC_RXTX_BUFF_MASK;
		annotation = call->rxtx_annotations[ix];
		anno_type = annotation & RXRPC_TX_ANNO_MASK;
		annotation &= ~RXRPC_TX_ANNO_MASK;
		if (anno_type == RXRPC_TX_ANNO_ACK)
			continue;

		skb = call->rxtx_buffer[ix];
		rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
		sp = rxrpc_skb(skb);

		if (anno_type == RXRPC_TX_ANNO_UNACK) {
			if (ktime_after(skb->tstamp, max_age)) {
				if (ktime_before(skb->tstamp, oldest))
					oldest = skb->tstamp;
				continue;
			}
			if (!(annotation & RXRPC_TX_ANNO_RESENT))
				unacked++;
		}

		/* Okay, we need to retransmit a packet. */
		call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation;
		retrans++;
		trace_rxrpc_retransmit(call, seq, annotation | anno_type,
				       ktime_to_ns(ktime_sub(skb->tstamp, max_age)));
	}

	call->resend_at = ktime_add_ms(oldest, rxrpc_resend_timeout);

	if (unacked)
		rxrpc_congestion_timeout(call);

	/* If there was nothing that needed retransmission then it's likely
	 * that an ACK got lost somewhere.  Send a ping to find out instead of
	 * retransmitting data.
	 */
	if (!retrans) {
		rxrpc_set_timer(call, rxrpc_timer_set_for_resend, now);
		spin_unlock_bh(&call->lock);
		ack_ts = ktime_sub(now, call->acks_latest_ts);
		if (ktime_to_ns(ack_ts) < call->peer->rtt)
			goto out;
		rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false,
				  rxrpc_propose_ack_ping_for_lost_ack);
		rxrpc_send_ack_packet(call, true);
		goto out;
	}

	/* Now go through the Tx window and perform the retransmissions.  We
	 * have to drop the lock for each send.  If an ACK comes in whilst the
	 * lock is dropped, it may clear some of the retransmission markers for
	 * packets that it soft-ACKs.
	 */
	for (seq = cursor + 1; before_eq(seq, top); seq++) {
		ix = seq & RXRPC_RXTX_BUFF_MASK;
		annotation = call->rxtx_annotations[ix];
		anno_type = annotation & RXRPC_TX_ANNO_MASK;
		if (anno_type != RXRPC_TX_ANNO_RETRANS)
			continue;

		skb = call->rxtx_buffer[ix];
		rxrpc_get_skb(skb, rxrpc_skb_tx_got);
		spin_unlock_bh(&call->lock);

		if (rxrpc_send_data_packet(call, skb, true) < 0) {
			rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
			return;
		}

		if (rxrpc_is_client_call(call))
			rxrpc_expose_client_call(call);

		rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
		spin_lock_bh(&call->lock);

		/* We need to clear the retransmit state, but there are two
		 * things we need to be aware of: A new ACK/NAK might have been
		 * received and the packet might have been hard-ACK'd (in which
		 * case it will no longer be in the buffer).
		 */
		if (after(seq, call->tx_hard_ack)) {
			annotation = call->rxtx_annotations[ix];
			anno_type = annotation & RXRPC_TX_ANNO_MASK;
			if (anno_type == RXRPC_TX_ANNO_RETRANS ||
			    anno_type == RXRPC_TX_ANNO_NAK) {
				annotation &= ~RXRPC_TX_ANNO_MASK;
				annotation |= RXRPC_TX_ANNO_UNACK;
			}
			annotation |= RXRPC_TX_ANNO_RESENT;
			call->rxtx_annotations[ix] = annotation;
		}

		if (after(call->tx_hard_ack, seq))
			seq = call->tx_hard_ack;
	}

out_unlock:
	spin_unlock_bh(&call->lock);
out:
	_leave("");
}