1 /* AF_RXRPC local endpoint management 2 * 3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 9 * 2 of the License, or (at your option) any later version. 10 */ 11 12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13 14 #include <linux/module.h> 15 #include <linux/net.h> 16 #include <linux/skbuff.h> 17 #include <linux/slab.h> 18 #include <linux/udp.h> 19 #include <linux/ip.h> 20 #include <net/sock.h> 21 #include <net/af_rxrpc.h> 22 #include <generated/utsrelease.h> 23 #include "ar-internal.h" 24 25 static const char rxrpc_version_string[65] = "linux-" UTS_RELEASE " AF_RXRPC"; 26 27 /* 28 * Reply to a version request 29 */ 30 static void rxrpc_send_version_request(struct rxrpc_local *local, 31 struct rxrpc_host_header *hdr, 32 struct sk_buff *skb) 33 { 34 struct rxrpc_wire_header whdr; 35 struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 36 struct sockaddr_in sin; 37 struct msghdr msg; 38 struct kvec iov[2]; 39 size_t len; 40 int ret; 41 42 _enter(""); 43 44 sin.sin_family = AF_INET; 45 sin.sin_port = udp_hdr(skb)->source; 46 sin.sin_addr.s_addr = ip_hdr(skb)->saddr; 47 48 msg.msg_name = &sin; 49 msg.msg_namelen = sizeof(sin); 50 msg.msg_control = NULL; 51 msg.msg_controllen = 0; 52 msg.msg_flags = 0; 53 54 whdr.epoch = htonl(sp->hdr.epoch); 55 whdr.cid = htonl(sp->hdr.cid); 56 whdr.callNumber = htonl(sp->hdr.callNumber); 57 whdr.seq = 0; 58 whdr.serial = 0; 59 whdr.type = RXRPC_PACKET_TYPE_VERSION; 60 whdr.flags = RXRPC_LAST_PACKET | (~hdr->flags & RXRPC_CLIENT_INITIATED); 61 whdr.userStatus = 0; 62 whdr.securityIndex = 0; 63 whdr._rsvd = 0; 64 whdr.serviceId = htons(sp->hdr.serviceId); 65 66 iov[0].iov_base = &whdr; 67 iov[0].iov_len = sizeof(whdr); 68 iov[1].iov_base = (char *)rxrpc_version_string; 69 iov[1].iov_len = sizeof(rxrpc_version_string); 70 71 len = iov[0].iov_len + iov[1].iov_len; 72 73 _proto("Tx VERSION (reply)"); 74 75 ret = kernel_sendmsg(local->socket, &msg, iov, 2, len); 76 if (ret < 0) 77 _debug("sendmsg failed: %d", ret); 78 79 _leave(""); 80 } 81 82 /* 83 * Process event packets targetted at a local endpoint. 84 */ 85 void rxrpc_process_local_events(struct rxrpc_local *local) 86 { 87 struct sk_buff *skb; 88 char v; 89 90 _enter(""); 91 92 skb = skb_dequeue(&local->event_queue); 93 if (skb) { 94 struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 95 96 _debug("{%d},{%u}", local->debug_id, sp->hdr.type); 97 98 switch (sp->hdr.type) { 99 case RXRPC_PACKET_TYPE_VERSION: 100 if (skb_copy_bits(skb, 0, &v, 1) < 0) 101 return; 102 _proto("Rx VERSION { %02x }", v); 103 if (v == 0) 104 rxrpc_send_version_request(local, &sp->hdr, skb); 105 break; 106 107 default: 108 /* Just ignore anything we don't understand */ 109 break; 110 } 111 112 rxrpc_free_skb(skb); 113 } 114 115 _leave(""); 116 } 117