forked from Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
2.7 KiB
115 lines
2.7 KiB
// SPDX-License-Identifier: GPL-2.0-or-later |
|
/* AF_RXRPC local endpoint management |
|
* |
|
* Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. |
|
* Written by David Howells ([email protected]) |
|
*/ |
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|
|
|
#include <linux/module.h> |
|
#include <linux/net.h> |
|
#include <linux/skbuff.h> |
|
#include <linux/slab.h> |
|
#include <net/sock.h> |
|
#include <net/af_rxrpc.h> |
|
#include <generated/utsrelease.h> |
|
#include "ar-internal.h" |
|
|
|
static const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC"; |
|
|
|
/* |
|
* 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(&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_point_version_reply); |
|
else |
|
trace_rxrpc_tx_packet(local->debug_id, &whdr, |
|
rxrpc_tx_point_version_reply); |
|
|
|
_leave(""); |
|
} |
|
|
|
/* |
|
* 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_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_freed); |
|
} |
|
|
|
_leave(""); |
|
}
|
|
|