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