📄 rxrpc.txt
字号:
(c) it meets a message belonging to a different call, or (d) it fills the user buffer. If recvmsg is called in blocking mode, it will keep sleeping, awaiting the reception of further data, until one of the above four conditions is met. (2) MSG_PEEK operates similarly, but will return immediately if it has put any data in the buffer rather than sleeping until it can fill the buffer. (3) If a data message is only partially consumed in filling a user buffer, then the remainder of that message will be left on the front of the queue for the next taker. MSG_TRUNC will never be flagged. (4) If there is more data to be had on a call (it hasn't copied the last byte of the last data message in that phase yet), then MSG_MORE will be flagged.================CONTROL MESSAGES================AF_RXRPC makes use of control messages in sendmsg() and recvmsg() to multiplexcalls, to invoke certain actions and to report certain conditions. These are: MESSAGE ID SRT DATA MEANING ======================= === =========== =============================== RXRPC_USER_CALL_ID sr- User ID App's call specifier RXRPC_ABORT srt Abort code Abort code to issue/received RXRPC_ACK -rt n/a Final ACK received RXRPC_NET_ERROR -rt error num Network error on call RXRPC_BUSY -rt n/a Call rejected (server busy) RXRPC_LOCAL_ERROR -rt error num Local error encountered RXRPC_NEW_CALL -r- n/a New call received RXRPC_ACCEPT s-- n/a Accept new call (SRT = usable in Sendmsg / delivered by Recvmsg / Terminal message) (*) RXRPC_USER_CALL_ID This is used to indicate the application's call ID. It's an unsigned long that the app specifies in the client by attaching it to the first data message or in the server by passing it in association with an RXRPC_ACCEPT message. recvmsg() passes it in conjunction with all messages except those of the RXRPC_NEW_CALL message. (*) RXRPC_ABORT This is can be used by an application to abort a call by passing it to sendmsg, or it can be delivered by recvmsg to indicate a remote abort was received. Either way, it must be associated with an RXRPC_USER_CALL_ID to specify the call affected. If an abort is being sent, then error EBADSLT will be returned if there is no call with that user ID. (*) RXRPC_ACK This is delivered to a server application to indicate that the final ACK of a call was received from the client. It will be associated with an RXRPC_USER_CALL_ID to indicate the call that's now complete. (*) RXRPC_NET_ERROR This is delivered to an application to indicate that an ICMP error message was encountered in the process of trying to talk to the peer. An errno-class integer value will be included in the control message data indicating the problem, and an RXRPC_USER_CALL_ID will indicate the call affected. (*) RXRPC_BUSY This is delivered to a client application to indicate that a call was rejected by the server due to the server being busy. It will be associated with an RXRPC_USER_CALL_ID to indicate the rejected call. (*) RXRPC_LOCAL_ERROR This is delivered to an application to indicate that a local error was encountered and that a call has been aborted because of it. An errno-class integer value will be included in the control message data indicating the problem, and an RXRPC_USER_CALL_ID will indicate the call affected. (*) RXRPC_NEW_CALL This is delivered to indicate to a server application that a new call has arrived and is awaiting acceptance. No user ID is associated with this, as a user ID must subsequently be assigned by doing an RXRPC_ACCEPT. (*) RXRPC_ACCEPT This is used by a server application to attempt to accept a call and assign it a user ID. It should be associated with an RXRPC_USER_CALL_ID to indicate the user ID to be assigned. If there is no call to be accepted (it may have timed out, been aborted, etc.), then sendmsg will return error ENODATA. If the user ID is already in use by another call, then error EBADSLT will be returned.==============SOCKET OPTIONS==============AF_RXRPC sockets support a few socket options at the SOL_RXRPC level: (*) RXRPC_SECURITY_KEY This is used to specify the description of the key to be used. The key is extracted from the calling process's keyrings with request_key() and should be of "rxrpc" type. The optval pointer points to the description string, and optlen indicates how long the string is, without the NUL terminator. (*) RXRPC_SECURITY_KEYRING Similar to above but specifies a keyring of server secret keys to use (key type "keyring"). See the "Security" section. (*) RXRPC_EXCLUSIVE_CONNECTION This is used to request that new connections should be used for each call made subsequently on this socket. optval should be NULL and optlen 0. (*) RXRPC_MIN_SECURITY_LEVEL This is used to specify the minimum security level required for calls on this socket. optval must point to an int containing one of the following values: (a) RXRPC_SECURITY_PLAIN Encrypted checksum only. (b) RXRPC_SECURITY_AUTH Encrypted checksum plus packet padded and first eight bytes of packet encrypted - which includes the actual packet length. (c) RXRPC_SECURITY_ENCRYPTED Encrypted checksum plus entire packet padded and encrypted, including actual packet length.========SECURITY========Currently, only the kerberos 4 equivalent protocol has been implemented(security index 2 - rxkad). This requires the rxkad module to be loaded and,on the client, tickets of the appropriate type to be obtained from the AFSkaserver or the kerberos server and installed as "rxrpc" type keys. This isnormally done using the klog program. An example simple klog program can befound at: http://people.redhat.com/~dhowells/rxrpc/klog.cThe payload provided to add_key() on the client should be of the followingform: struct rxrpc_key_sec2_v1 { uint16_t security_index; /* 2 */ uint16_t ticket_length; /* length of ticket[] */ uint32_t expiry; /* time at which expires */ uint8_t kvno; /* key version number */ uint8_t __pad[3]; uint8_t session_key[8]; /* DES session key */ uint8_t ticket[0]; /* the encrypted ticket */ };Where the ticket blob is just appended to the above structure.For the server, keys of type "rxrpc_s" must be made available to the server.They have a description of "<serviceID>:<securityIndex>" (eg: "52:2" for anrxkad key for the AFS VL service). When such a key is created, it should begiven the server's secret key as the instantiation data (see the examplebelow). add_key("rxrpc_s", "52:2", secret_key, 8, keyring);A keyring is passed to the server socket by naming it in a sockopt. The serversocket then looks the server secret keys up in this keyring when secureincoming connections are made. This can be seen in an example program that canbe found at: http://people.redhat.com/~dhowells/rxrpc/listen.c====================EXAMPLE CLIENT USAGE====================A client would issue an operation by: (1) An RxRPC socket is set up by: client = socket(AF_RXRPC, SOCK_DGRAM, PF_INET); Where the third parameter indicates the protocol family of the transport socket used - usually IPv4 but it can also be IPv6 [TODO]. (2) A local address can optionally be bound: struct sockaddr_rxrpc srx = { .srx_family = AF_RXRPC, .srx_service = 0, /* we're a client */ .transport_type = SOCK_DGRAM, /* type of transport socket */ .transport.sin_family = AF_INET, .transport.sin_port = htons(7000), /* AFS callback */ .transport.sin_address = 0, /* all local interfaces */ }; bind(client, &srx, sizeof(srx)); This specifies the local UDP port to be used. If not given, a random non-privileged port will be used. A UDP port may be shared between several unrelated RxRPC sockets. Security is handled on a basis of per-RxRPC virtual connection. (3) The security is set: const char *key = "AFS:cambridge.redhat.com"; setsockopt(client, SOL_RXRPC, RXRPC_SECURITY_KEY, key, strlen(key)); This issues a request_key() to get the key representing the security context. The minimum security level can be set: unsigned int sec = RXRPC_SECURITY_ENCRYPTED; setsockopt(client, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL, &sec, sizeof(sec)); (4) The server to be contacted can then be specified (alternatively this can be done through sendmsg): struct sockaddr_rxrpc srx = { .srx_family = AF_RXRPC, .srx_service = VL_SERVICE_ID, .transport_type = SOCK_DGRAM, /* type of transport socket */ .transport.sin_family = AF_INET, .transport.sin_port = htons(7005), /* AFS volume manager */ .transport.sin_address = ..., }; connect(client, &srx, sizeof(srx)); (5) The request data should then be posted to the server socket using a series of sendmsg() calls, each with the following control message attached: RXRPC_USER_CALL_ID - specifies the user ID for this call MSG_MORE should be set in msghdr::msg_flags on all but the last part of the request. Multiple requests may be made simultaneously. If a call is intended to go to a destination other then the default specified through connect(), then msghdr::msg_name should be set on the first request message of that call. (6) The reply data will then be posted to the server socket for recvmsg() to pick up. MSG_MORE will be flagged by recvmsg() if there's more reply data for a particular call to be read. MSG_EOR will be set on the terminal read for a call. All data will be delivered with the following control message attached: RXRPC_USER_CALL_ID - specifies the user ID for this call If an abort or error occurred, this will be returned in the control data buffer instead, and MSG_EOR will be flagged to indicate the end of that call.====================EXAMPLE SERVER USAGE====================A server would be set up to accept operations in the following manner: (1) An RxRPC socket is created by: server = socket(AF_RXRPC, SOCK_DGRAM, PF_INET); Where the third parameter indicates the address type of the transport socket used - usually IPv4. (2) Security is set up if desired by giving the socket a keyring with server secret keys in it: keyring = add_key("keyring", "AFSkeys", NULL, 0, KEY_SPEC_PROCESS_KEYRING);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -