mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-14 15:54:15 +08:00
987db9f7cd
Use the previously-added transmit-phase skbuff private flag to simplify the socket buffer tracing a bit. Which phase the skbuff comes from can now be divined from the skb rather than having to be guessed from the call state. We can also reduce the number of rxrpc_skb_trace values by eliminating the difference between Tx and Rx in the symbols. Signed-off-by: David Howells <dhowells@redhat.com>
116 lines
2.7 KiB
C
116 lines
2.7 KiB
C
// 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 (dhowells@redhat.com)
|
|
*/
|
|
|
|
#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("");
|
|
}
|