hc
2025-02-14 bbb9540dc49f70f6b703d1c8d1b85fa5f602d86e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 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("");
}