18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* AF_RXRPC local endpoint management
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci#include <linux/net.h>
128c2ecf20Sopenharmony_ci#include <linux/skbuff.h>
138c2ecf20Sopenharmony_ci#include <linux/slab.h>
148c2ecf20Sopenharmony_ci#include <net/sock.h>
158c2ecf20Sopenharmony_ci#include <net/af_rxrpc.h>
168c2ecf20Sopenharmony_ci#include <generated/utsrelease.h>
178c2ecf20Sopenharmony_ci#include "ar-internal.h"
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC";
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/*
228c2ecf20Sopenharmony_ci * Reply to a version request
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_cistatic void rxrpc_send_version_request(struct rxrpc_local *local,
258c2ecf20Sopenharmony_ci				       struct rxrpc_host_header *hdr,
268c2ecf20Sopenharmony_ci				       struct sk_buff *skb)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	struct rxrpc_wire_header whdr;
298c2ecf20Sopenharmony_ci	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
308c2ecf20Sopenharmony_ci	struct sockaddr_rxrpc srx;
318c2ecf20Sopenharmony_ci	struct msghdr msg;
328c2ecf20Sopenharmony_ci	struct kvec iov[2];
338c2ecf20Sopenharmony_ci	size_t len;
348c2ecf20Sopenharmony_ci	int ret;
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci	_enter("");
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	if (rxrpc_extract_addr_from_skb(&srx, skb) < 0)
398c2ecf20Sopenharmony_ci		return;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	msg.msg_name	= &srx.transport;
428c2ecf20Sopenharmony_ci	msg.msg_namelen	= srx.transport_len;
438c2ecf20Sopenharmony_ci	msg.msg_control	= NULL;
448c2ecf20Sopenharmony_ci	msg.msg_controllen = 0;
458c2ecf20Sopenharmony_ci	msg.msg_flags	= 0;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	whdr.epoch	= htonl(sp->hdr.epoch);
488c2ecf20Sopenharmony_ci	whdr.cid	= htonl(sp->hdr.cid);
498c2ecf20Sopenharmony_ci	whdr.callNumber	= htonl(sp->hdr.callNumber);
508c2ecf20Sopenharmony_ci	whdr.seq	= 0;
518c2ecf20Sopenharmony_ci	whdr.serial	= 0;
528c2ecf20Sopenharmony_ci	whdr.type	= RXRPC_PACKET_TYPE_VERSION;
538c2ecf20Sopenharmony_ci	whdr.flags	= RXRPC_LAST_PACKET | (~hdr->flags & RXRPC_CLIENT_INITIATED);
548c2ecf20Sopenharmony_ci	whdr.userStatus	= 0;
558c2ecf20Sopenharmony_ci	whdr.securityIndex = 0;
568c2ecf20Sopenharmony_ci	whdr._rsvd	= 0;
578c2ecf20Sopenharmony_ci	whdr.serviceId	= htons(sp->hdr.serviceId);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	iov[0].iov_base	= &whdr;
608c2ecf20Sopenharmony_ci	iov[0].iov_len	= sizeof(whdr);
618c2ecf20Sopenharmony_ci	iov[1].iov_base	= (char *)rxrpc_version_string;
628c2ecf20Sopenharmony_ci	iov[1].iov_len	= sizeof(rxrpc_version_string);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	len = iov[0].iov_len + iov[1].iov_len;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	_proto("Tx VERSION (reply)");
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	ret = kernel_sendmsg(local->socket, &msg, iov, 2, len);
698c2ecf20Sopenharmony_ci	if (ret < 0)
708c2ecf20Sopenharmony_ci		trace_rxrpc_tx_fail(local->debug_id, 0, ret,
718c2ecf20Sopenharmony_ci				    rxrpc_tx_point_version_reply);
728c2ecf20Sopenharmony_ci	else
738c2ecf20Sopenharmony_ci		trace_rxrpc_tx_packet(local->debug_id, &whdr,
748c2ecf20Sopenharmony_ci				      rxrpc_tx_point_version_reply);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	_leave("");
778c2ecf20Sopenharmony_ci}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/*
808c2ecf20Sopenharmony_ci * Process event packets targetted at a local endpoint.
818c2ecf20Sopenharmony_ci */
828c2ecf20Sopenharmony_civoid rxrpc_process_local_events(struct rxrpc_local *local)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	struct sk_buff *skb;
858c2ecf20Sopenharmony_ci	char v;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	_enter("");
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	skb = skb_dequeue(&local->event_queue);
908c2ecf20Sopenharmony_ci	if (skb) {
918c2ecf20Sopenharmony_ci		struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci		rxrpc_see_skb(skb, rxrpc_skb_seen);
948c2ecf20Sopenharmony_ci		_debug("{%d},{%u}", local->debug_id, sp->hdr.type);
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci		switch (sp->hdr.type) {
978c2ecf20Sopenharmony_ci		case RXRPC_PACKET_TYPE_VERSION:
988c2ecf20Sopenharmony_ci			if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
998c2ecf20Sopenharmony_ci					  &v, 1) < 0)
1008c2ecf20Sopenharmony_ci				return;
1018c2ecf20Sopenharmony_ci			_proto("Rx VERSION { %02x }", v);
1028c2ecf20Sopenharmony_ci			if (v == 0)
1038c2ecf20Sopenharmony_ci				rxrpc_send_version_request(local, &sp->hdr, skb);
1048c2ecf20Sopenharmony_ci			break;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci		default:
1078c2ecf20Sopenharmony_ci			/* Just ignore anything we don't understand */
1088c2ecf20Sopenharmony_ci			break;
1098c2ecf20Sopenharmony_ci		}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci		rxrpc_free_skb(skb, rxrpc_skb_freed);
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	_leave("");
1158c2ecf20Sopenharmony_ci}
116