RxRPC 網路協議¶
RxRPC 協議驅動程式提供了一種基於 UDP 的可靠的兩階段傳輸,可用於執行 RxRPC 遠端操作。這是透過 AF_RXRPC 族的套接字完成的,使用 sendmsg() 和 recvmsg() 以及控制資料來發送和接收資料、中止和錯誤。
本文件內容
概述。
RxRPC 協議概要。
AF_RXRPC 驅動程式模型。
控制訊息。
套接字選項。
安全性。
客戶端使用示例。
伺服器使用示例。
AF_RXRPC 核心介面。
可配置引數。
概述¶
RxRPC 是一個雙層協議。有一個會話層,它使用基於 IPv4(或 IPv6)的 UDP 作為傳輸層來提供可靠的虛擬連線,但實現了一個真正的網路協議;還有一個表示層,它使用 XDR 將結構化資料渲染成二進位制 blob 並再次渲染回去(SunRPC 也是如此)
+-------------+
| Application |
+-------------+
| XDR | Presentation
+-------------+
| RxRPC | Session
+-------------+
| UDP | Transport
+-------------+
AF_RXRPC 提供
RxRPC 功能的一部分,適用於核心和使用者空間應用程式,方法是將其會話部分設為 Linux 網路協議 (AF_RXRPC)。
一個兩階段協議。客戶端傳輸一個 blob(請求),然後接收一個 blob(回覆),伺服器接收請求,然後傳輸回覆。
保留為一個呼叫設定的可重用傳輸系統位,以加速後續呼叫。
一種安全協議,使用 Linux 核心的金鑰保留功能來管理客戶端的安全。伺服器端必須更積極地參與安全協商。
AF_RXRPC 不提供 XDR 編組/表示功能。這留給應用程式。 AF_RXRPC 只處理 blob。即使是操作 ID 也只是請求 blob 的前四個位元組,因此超出了核心的興趣範圍。
AF_RXRPC 族的套接字是
建立為 SOCK_DGRAM 型別;
提供其將要使用的底層傳輸型別的協議 - 目前僅支援 PF_INET。
Andrew 檔案系統 (AFS) 是一個使用此功能的應用程式示例,並且具有核心(檔案系統)和使用者空間(實用程式)元件。
RxRPC 協議概要¶
RxRPC 協議的概述
RxRPC 位於另一個網路協議之上(目前唯一選擇是 UDP),並使用它來提供網路傳輸。例如,UDP 埠提供傳輸端點。
RxRPC 支援來自任何給定傳輸端點的多個虛擬“連線”,從而允許共享端點,即使到相同的遠端端點。
每個連線都連線到特定的“服務”。一個連線可能無法連線到多個服務。可以將服務視為 RxRPC 等效的埠號。 AF_RXRPC 允許多個服務共享一個端點。
客戶端發起的包被標記,因此傳輸端點可以在客戶端和伺服器連線之間共享(連線具有方向)。
在一個本地傳輸端點和一個遠端端點上的一個服務之間,最多可以同時支援十億個連線。 RxRPC 連線由七個數字描述
Local address } Local port } Transport (UDP) address Remote address } Remote port } Direction Connection ID Service ID每個 RxRPC 操作都是一個“呼叫”。一個連線可以進行多達 40 億次呼叫,但在任何給定時間,一個連線上最多可以進行 4 次呼叫。
呼叫是雙階段的並且是不對稱的:客戶端傳送其請求資料,服務接收該資料;然後服務傳輸客戶端接收的回覆資料。
資料 blob 的大小不確定,階段的結束由資料包中的標誌標記。但是,組成一個 blob 的資料包數量不得超過 40 億個,因為這會導致序列號換行。
請求資料的前四個位元組是服務操作 ID。
安全性是在每個連線的基礎上協商的。連線由到達的第一個資料包啟動。如果請求了安全性,則伺服器會發出“質詢”,然後客戶端以“響應”進行回覆。如果響應成功,則為該連線的生命週期設定安全性,並且所有後續呼叫都使用相同的安全性。如果伺服器在客戶端之前讓連線失效,則如果客戶端再次使用該連線,將重新協商安全性。
呼叫使用 ACK 資料包來處理可靠性。資料包也按每個呼叫顯式排序。
有兩種型別的肯定確認:硬 ACK 和軟 ACK。硬 ACK 向遠端指示已接收並處理到某個點的所有資料;軟 ACK 指示已接收到資料,但可能仍會被丟棄並重新請求。在傳送方硬 ACK 之前,傳送方不得丟棄任何可傳輸的資料包。
接收到回覆資料包隱式硬 ACK 了組成請求的所有資料包。
當請求已傳送、回覆已接收並且回覆的最後一個數據包上的最終硬 ACK 已到達伺服器時,呼叫完成。
在完成之前,任何一端都可以隨時中止呼叫。
AF_RXRPC 驅動程式模型¶
關於 AF_RXRPC 驅動程式
AF_RXRPC 協議透明地使用傳輸協議的內部套接字來表示傳輸端點。
AF_RXRPC 套接字對映到 RxRPC 連線捆綁包。實際的 RxRPC 連線以透明方式處理。一個客戶端套接字可用於對同一服務進行多次併發呼叫。一個伺服器套接字可以處理來自多個客戶端的呼叫。
將啟動額外的並行客戶端連線以支援額外的併發呼叫,直到可調整的限制。
每個連線在當前使用它的最後一個呼叫完成後的某個時間段內 [可調整] 保留,以防進行可以重用它的新呼叫。
每個內部 UDP 套接字在上次使用它的連線丟棄後的某個時間段內 [可調整] 保留 [可調整],以防進行可以使用它的新連線。
僅當客戶端具有描述其安全性的相同金鑰結構時,客戶端連線才會在呼叫之間共享(並假設呼叫否則會共享連線)。未受保護的呼叫也可以相互共享連線。
如果客戶端表示它在,則伺服器端連線將被共享。
ACK 由協議驅動程式自動處理,包括 ping 回覆。
SO_KEEPALIVE 自動 ping 另一端以保持連線活動 [TODO]。
如果收到 ICMP 錯誤,則受該錯誤影響的所有呼叫都將被中止,並且適當的網路錯誤將透過 recvmsg() 傳遞。
與 RxRPC 套接字使用者的互動
透過繫結具有非零服務 ID 的地址,將套接字設為伺服器套接字。
在客戶端中,傳送請求是透過一個或多個 sendmsgs 來實現的,然後透過一個或多個 recvmsgs 接收回復。
要從客戶端傳送的請求的第一個 sendmsg 包含一個標籤,該標籤將用於與該呼叫關聯的所有其他 sendmsgs 或 recvmsgs 中。該標籤在控制資料中攜帶。
connect() 用於為客戶端套接字提供預設目標地址。這可能會被提供給呼叫的第一個 sendmsg() 的備用地址覆蓋(struct msghdr::msg_name)。
如果在未繫結的客戶端上呼叫 connect(),則在操作發生之前將繫結一個隨機的本地埠。
伺服器套接字也可以用於進行客戶端呼叫。為此,呼叫的第一個 sendmsg() 必須指定目標地址。伺服器的傳輸端點用於傳送資料包。
一旦應用程式收到與呼叫關聯的最後一個訊息,則保證不會再次看到該標籤,因此可以使用它來固定客戶端資源。然後可以使用相同的標籤啟動新呼叫,而不用擔心干擾。
在伺服器中,使用一個或多個 recvmsgs 接收請求,然後使用一個或多個 sendmsgs 傳輸回覆,然後使用最後一個 recvmsg 接收最終 ACK。
當傳送呼叫的資料時,如果該呼叫還有更多資料要傳送,則為 sendmsg 提供 MSG_MORE。
當接收呼叫的資料時,如果該呼叫還有更多資料要接收,則 recvmsg 標記 MSG_MORE。
當接收呼叫的資料或訊息時,recvmsg 標記 MSG_EOR 以指示該呼叫的終端訊息。
可以透過將中止控制訊息新增到控制資料來中止呼叫。發出中止會終止核心對該呼叫標籤的使用。該呼叫的接收佇列中等待的所有訊息都將被丟棄。
中止、繁忙通知和質詢資料包透過 recvmsg 傳遞,並且將設定控制資料訊息以指示上下文。接收中止或繁忙訊息會終止核心對該呼叫標籤的使用。
msghdr struct 的控制資料部分用於多種用途
預期或受影響呼叫的標籤。
傳送或接收錯誤、中止和繁忙通知。
傳入呼叫的通知。
傳送除錯請求和接收除錯回覆 [TODO]。
當核心接收並設定傳入呼叫時,它會向伺服器應用程式傳送一條訊息,以告知它有一個新的呼叫正在等待其接受 [recvmsg 報告一個特殊的控制訊息]。然後,伺服器應用程式使用 sendmsg 為新呼叫分配標籤。完成後,請求資料的第一部分將由 recvmsg 傳遞。
伺服器應用程式必須為伺服器套接字提供一個金鑰環,其中包含與它允許的安全型別相對應的金鑰。在設定安全連線時,核心會在金鑰環中查詢適當的金鑰,然後向客戶端傳送一個質詢資料包並接收一個響應資料包。然後,核心檢查資料包的授權,並中止連線或設定安全性。
客戶端將用於保護其通訊的金鑰的名稱由套接字選項指定。
關於 sendmsg 的說明
可以設定 MSG_WAITALL 以告訴 sendmsg 忽略訊號,如果對等方在合理的時間內接受資料包,以便我們設法將所有資料排隊以進行傳輸。這要求客戶端在每個 2*RTT 時間段內至少接受一個數據包。
如果未設定,則 sendmsg() 將立即返回,如果未消耗任何內容,則返回 EINTR/ERESTARTSYS,否則返回已消耗的資料量。
關於 recvmsg 的說明
如果接收佇列中存在屬於特定呼叫的一系列資料訊息,則 recvmsg 將繼續處理它們,直到
它遇到該呼叫已接收資料的末尾,
它遇到非資料訊息,
它遇到屬於不同調用的訊息,或者
它填滿使用者緩衝區。
如果在阻塞模式下呼叫 recvmsg,它將繼續休眠,等待接收更多資料,直到滿足上述四個條件之一。
MSG_PEEK 的操作類似,但是如果它在緩衝區中放入了任何資料,它將立即返回,而不是休眠直到它可以填滿緩衝區。
如果資料訊息僅部分消耗在填充使用者緩衝區中,則該訊息的剩餘部分將保留在佇列的前面供下一個使用者使用。永遠不會標記 MSG_TRUNC。
如果呼叫中有更多資料要讀取(它尚未複製該階段中最後一個數據訊息的最後一個位元組),則將標記 MSG_MORE。
控制訊息¶
AF_RXRPC 使用 sendmsg() 和 recvmsg() 中的控制訊息來複用呼叫、呼叫某些操作和報告某些條件。這些是
訊息 ID
SRT
資料
含義
RXRPC_USER_CALL_ID
sr-
使用者 ID
應用程式的呼叫說明符
RXRPC_ABORT
srt
中止程式碼
要發出/接收的中止程式碼
RXRPC_ACK
-rt
不適用
收到最終 ACK
RXRPC_NET_ERROR
-rt
錯誤編號
呼叫中的網路錯誤
RXRPC_BUSY
-rt
不適用
呼叫被拒絕(伺服器繁忙)
RXRPC_LOCAL_ERROR
-rt
錯誤編號
遇到本地錯誤
RXRPC_NEW_CALL
-r-
不適用
收到新呼叫
RXRPC_ACCEPT
s--
不適用
接受新呼叫
RXRPC_EXCLUSIVE_CALL
s--
不適用
進行獨佔客戶端呼叫
RXRPC_UPGRADE_SERVICE
s--
不適用
客戶端呼叫可以升級
RXRPC_TX_LENGTH
s--
資料長度
Tx 資料的總長度
(SRT = 可在 Sendmsg 中使用 / 由 Recvmsg 傳遞 / 終端訊息)
RXRPC_USER_CALL_ID
這用於指示應用程式的呼叫 ID。這是一個無符號長整型,應用程式透過將其附加到第一個資料訊息來在客戶端中指定它,或者透過將其與 RXRPC_ACCEPT 訊息關聯來在伺服器中傳遞它。 recvmsg() 將其與除 RXRPC_NEW_CALL 訊息之外的所有訊息一起傳遞。
RXRPC_ABORT
應用程式可以使用它透過將其傳遞給 sendmsg 來中止呼叫,或者它可以透過 recvmsg 傳遞以指示接收到遠端中止。無論哪種方式,它都必須與 RXRPC_USER_CALL_ID 關聯以指定受影響的呼叫。如果要傳送中止,則如果不存在具有該使用者 ID 的呼叫,將返回錯誤 EBADSLT。
RXRPC_ACK
這被傳遞到伺服器應用程式,以指示從客戶端接收到呼叫的最終 ACK。它將與 RXRPC_USER_CALL_ID 關聯,以指示現在已完成的呼叫。
RXRPC_NET_ERROR
這被傳遞到應用程式,以指示在嘗試與對等方通訊的過程中遇到了 ICMP 錯誤訊息。一個 errno 類整數值將包含在指示問題的控制訊息資料中,並且 RXRPC_USER_CALL_ID 將指示受影響的呼叫。
RXRPC_BUSY
這被傳遞到客戶端應用程式,以指示由於伺服器繁忙,該呼叫已被伺服器拒絕。它將與 RXRPC_USER_CALL_ID 關聯,以指示被拒絕的呼叫。
RXRPC_LOCAL_ERROR
這被傳遞到應用程式,以指示遇到了本地錯誤,並且由於該錯誤而中止了呼叫。一個 errno 類整數值將包含在指示問題的控制訊息資料中,並且 RXRPC_USER_CALL_ID 將指示受影響的呼叫。
RXRPC_NEW_CALL
這被傳遞以指示伺服器應用程式已收到新呼叫並且正在等待接受。沒有使用者 ID 與此關聯,因為必須透過執行 RXRPC_ACCEPT 來隨後分配使用者 ID。
RXRPC_ACCEPT
這被伺服器應用程式用於嘗試接受呼叫併為其分配使用者 ID。它應與 RXRPC_USER_CALL_ID 關聯以指示要分配的使用者 ID。如果沒有要接受的呼叫(它可能已超時、中止等),則 sendmsg 將返回錯誤 ENODATA。如果使用者 ID 已被另一個呼叫使用,則將返回錯誤 EBADSLT。
RXRPC_EXCLUSIVE_CALL
這用於指示應在一次性連線上進行客戶端呼叫。一旦呼叫終止,連線將被丟棄。
RXRPC_UPGRADE_SERVICE
這用於進行客戶端呼叫以探測指定的服務 ID 是否可以由伺服器升級。呼叫方必須檢查返回到 recvmsg() 的 msg_name 以瞭解實際使用的服務 ID。探測的操作必須是在兩個服務中都採用相同引數的操作。
一旦使用它建立了伺服器的升級能力(或缺乏該能力),則返回的服務 ID 應用於與該伺服器的所有未來通訊,並且不應再設定 RXRPC_UPGRADE_SERVICE。
RXRPC_TX_LENGTH
這用於通知核心將由呼叫傳輸的資料總量(無論是在客戶端請求中還是在服務響應中)。如果給定,它允許核心直接從使用者空間緩衝區加密到資料包緩衝區,而不是複製到緩衝區然後在原地加密。這隻能與提供呼叫資料的第一個 sendmsg() 一起給出。如果實際給定的資料量不同,則將生成 EMSGSIZE。
這採用 __s64 型別的引數,該引數指示將傳輸多少資料。這可能不小於零。
符號 RXRPC__SUPPORTED 被定義為比支援的最高控制訊息型別多一個。在執行時,可以透過 RXRPC_SUPPORTED_CMSG 套接字選項查詢(參見下文)。
套接字選項¶
AF_RXRPC 套接字在 SOL_RXRPC 級別支援一些套接字選項
RXRPC_SECURITY_KEY
這用於指定要使用的金鑰的描述。使用 request_key() 從呼叫程序的金鑰環中提取金鑰,並且應為“rxrpc”型別。
optval 指標指向描述字串,optlen 指示字串的長度,不包括 NUL 終止符。
RXRPC_SECURITY_KEYRING
與上述類似,但指定要使用的伺服器金鑰環(金鑰型別“keyring”)。請參閱“安全性”部分。
RXRPC_EXCLUSIVE_CONNECTION
這用於請求為隨後在該套接字上進行的每個呼叫使用新連線。 optval 應為 NULL,optlen 應為 0。
RXRPC_MIN_SECURITY_LEVEL
這用於指定此套接字上的呼叫所需的最低安全級別。 optval 必須指向一個 int,其中包含以下值之一
RXRPC_SECURITY_PLAIN
僅加密校驗和。
RXRPC_SECURITY_AUTH
加密校驗和加上資料包填充和資料包的前八個位元組加密 - 其中包括實際資料包長度。
RXRPC_SECURITY_ENCRYPT
加密校驗和加上整個資料包填充和加密,包括實際資料包長度。
RXRPC_UPGRADEABLE_SERVICE
這用於指示具有兩個繫結的服務套接字可以根據客戶端的請求將一個繫結服務升級到另一個繫結服務。 optval 必須指向一個由兩個無符號短整型組成的陣列。第一個是要從中升級的服務 ID,第二個是要升級到的服務 ID。
RXRPC_SUPPORTED_CMSG
這是一個只讀選項,它將一個 int 寫入緩衝區,指示支援的最高控制訊息型別。
安全性¶
目前,僅實現了 Kerberos 4 等效協議(安全索引 2 - rxkad)。這要求載入 rxkad 模組,並且在客戶端上,從 AFS kaserver 或 Kerberos 伺服器獲取適當型別的票證,並將其安裝為“rxrpc”型別金鑰。這通常使用 klog 程式完成。可以在以下位置找到一個簡單的 klog 程式示例:
提供給客戶端上的 add_key() 的有效負載應採用以下形式
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 */
};
其中票證 blob 只是附加到上述結構。
對於伺服器,必須向伺服器提供型別為“rxrpc_s”的金鑰。它們具有“<serviceID>:<securityIndex>”的描述(例如:“52:2”表示 AFS VL 服務的 rxkad 金鑰)。建立此類金鑰時,應將伺服器的金鑰作為例項化資料提供(參見下面的示例)。
add_key(“rxrpc_s”, “52:2”, secret_key, 8, keyring);
透過在 sockopt 中命名金鑰環,將其傳遞給伺服器套接字。然後,伺服器套接字在進行安全傳入連線時,在該金鑰環中查詢伺服器金鑰。這可以在以下位置找到的示例程式中看到:
客戶端使用示例¶
客戶端將透過以下方式發出操作:
透過以下方式設定 RxRPC 套接字:
client = socket(AF_RXRPC, SOCK_DGRAM, PF_INET);其中第三個引數指示所使用的傳輸套接字的協議族 - 通常為 IPv4,但也可以為 IPv6 [TODO]。
可以選擇繫結本地地址
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));這指定要使用的本地 UDP 埠。如果未給定,將使用隨機的非特權埠。可以在多個不相關的 RxRPC 套接字之間共享 UDP 埠。安全處理基於每個 RxRPC 虛擬連線。
設定安全性
const char *key = "AFS:cambridge.redhat.com"; setsockopt(client, SOL_RXRPC, RXRPC_SECURITY_KEY, key, strlen(key));這會發出 request_key() 以獲取表示安全上下文的金鑰。可以設定最低安全級別
unsigned int sec = RXRPC_SECURITY_ENCRYPT; setsockopt(client, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL, &sec, sizeof(sec));然後可以指定要聯絡的伺服器(或者可以透過 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));然後應使用一系列 sendmsg() 呼叫將請求資料釋出到伺服器套接字,每個呼叫都附加了以下控制訊息
RXRPC_USER_CALL_ID
指定此呼叫的使用者 ID
除了請求的最後一部分之外,應在 msghdr::msg_flags 中設定 MSG_MORE。可以同時發出多個請求。
還可以在第一個 sendmsg() 呼叫上指定 RXRPC_TX_LENGTH 控制訊息。
如果打算將呼叫傳送到透過 connect() 指定的預設目標以外的目標,則應在該呼叫的第一個請求訊息上設定 msghdr::msg_name。
然後將回複數據釋出到伺服器套接字,以供 recvmsg() 拾取。如果某個特定呼叫有更多回複數據要讀取,則 recvmsg() 將標記 MSG_MORE。將在呼叫的終端讀取上設定 MSG_EOR。
所有資料都將隨附加的以下控制訊息一起傳遞
RXRPC_USER_CALL_ID - 指定此呼叫的使用者 ID
如果發生中止或錯誤,則將改為在控制資料緩衝區中返回此資訊,並且將標記 MSG_EOR 以指示該呼叫的結束。
客戶端可以請求它知道的服務 ID,並請求如果伺服器提供更好的服務,則將該服務升級為更好的服務,方法是在呼叫的第一個 sendmsg() 上提供 RXRPC_UPGRADE_SERVICE。然後,客戶端應在收集結果時檢查 recvmsg() 填寫的 msg_name 中的 srx_service。如果服務忽略了升級請求,則 srx_service 將保持與提供給 sendmsg() 相同的值 - 否則將被更改以指示伺服器升級到的服務 ID。請注意,升級後的服務 ID 由伺服器選擇。在傳送任何更多呼叫之前,呼叫方必須等到它在回覆中看到服務 ID(在探針結束之前,將阻止對同一目標的進一步呼叫)。
伺服器使用示例¶
將按以下方式設定伺服器以接受操作:
透過以下方式建立 RxRPC 套接字:
server = socket(AF_RXRPC, SOCK_DGRAM, PF_INET);其中第三個引數指示所使用的傳輸套接字的地址型別 - 通常為 IPv4。
如果需要,可以透過向套接字提供一個包含伺服器金鑰的金鑰環來設定安全性
keyring = add_key("keyring", "AFSkeys", NULL, 0, KEY_SPEC_PROCESS_KEYRING); const char secret_key[8] = { 0xa7, 0x83, 0x8a, 0xcb, 0xc7, 0x83, 0xec, 0x94 }; add_key("rxrpc_s", "52:2", secret_key, 8, keyring); setsockopt(server, SOL_RXRPC, RXRPC_SECURITY_KEYRING, "AFSkeys", 7);在將其提供給套接字後,可以操作金鑰環。這允許伺服器在執行時新增更多金鑰、替換金鑰等。
然後必須繫結本地地址
struct sockaddr_rxrpc srx = { .srx_family = AF_RXRPC, .srx_service = VL_SERVICE_ID, /* RxRPC service ID */ .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(server, &srx, sizeof(srx));如果傳輸引數相同,則可以將多個服務 ID 繫結到一個套接字。限制目前為兩個。為此,應呼叫 bind() 兩次。
如果需要服務升級,首先必須繫結兩個服務 ID,然後必須設定以下選項
unsigned short service_ids[2] = { from_ID, to_ID }; setsockopt(server, SOL_RXRPC, RXRPC_UPGRADEABLE_SERVICE, service_ids, sizeof(service_ids));如果客戶端請求,這將自動將服務 from_ID 上的連線升級到服務 to_ID。當將請求資料傳遞到使用者空間時,這將反映在透過 recvmsg() 獲得的 msg_name 中。
然後將伺服器設定為偵聽傳入呼叫
listen(server, 100);核心透過為每個傳入連線傳送一條訊息來通知伺服器掛起的傳入連線。這是透過伺服器套接字上的 recvmsg() 接收的。它沒有資料,並且附加了單個無資料控制訊息
RXRPC_NEW_CALL此時可以由 recvmsg() 傳遞迴的地址應被忽略,因為釋出訊息的呼叫可能在接受時已過期 - 在這種情況下,將接受佇列中仍在的第一個呼叫。
然後,伺服器透過發出帶有兩段控制資料且沒有實際資料的 sendmsg() 來接受新呼叫
RXRPC_ACCEPT
指示連線接受
RXRPC_USER_CALL_ID
指定此呼叫的使用者 ID
然後,第一個請求資料包將釋出到伺服器套接字,以供 recvmsg() 拾取。此時,可以從 msghdr struct 中的地址欄位讀取呼叫的 RxRPC 地址。
隨後的請求資料將釋出到伺服器套接字,以供 recvmsg() 隨著它的到達而收集。除了請求的最後一部分之外,所有請求資料都將標記 MSG_MORE。
所有資料都將隨附加的以下控制訊息一起傳遞
RXRPC_USER_CALL_ID
指定此呼叫的使用者 ID
然後應使用一系列 sendmsg() 呼叫將回複數據釋出到伺服器套接字,每個呼叫都附加了以下控制訊息
RXRPC_USER_CALL_ID
指定此呼叫的使用者 ID
除了特定呼叫的最後一條訊息之外,應在 msghdr::msg_flags 中設定 MSG_MORE。
客戶端的最終 ACK 將在收到後釋出以供 recvmsg() 檢索。它將採用帶有兩個附加控制訊息的無資料訊息的形式
RXRPC_USER_CALL_ID
指定此呼叫的使用者 ID
RXRPC_ACK
指示最終 ACK(無資料)
將標記 MSG_EOR 以指示這是此呼叫的最終訊息。
在傳送回覆資料的最後一個數據包之前,可以透過呼叫帶有帶有以下附加控制訊息的無資料訊息的 sendmsg() 來中止呼叫
RXRPC_USER_CALL_ID
指定此呼叫的使用者 ID
RXRPC_ABORT
指示中止程式碼(4 位元組資料)
如果發出此命令,則套接字接收佇列中等待的任何資料包都將被丟棄。
請注意,特定服務的所有通訊都透過一個伺服器套接字進行,使用 sendmsg() 和 recvmsg() 上的控制訊息來確定受影響的呼叫。
AF_RXRPC 核心介面¶
AF_RXRPC 模組還提供了一個介面,供核心實用程式(例如 AFS 檔案系統)使用。這允許此類實用程式
直接在一個套接字上的單個客戶端呼叫上使用不同的金鑰,而不是必須開啟大量套接字,每個金鑰可能想要使用一個套接字。
避免在發出呼叫或開啟套接字時呼叫 RxRPC 的 request_key()。相反,實用程式負責在適當的時候請求金鑰。例如,AFS 會在諸如 open() 或 unlink() 之類的 VFS 操作期間執行此操作。然後在發起呼叫時傳遞金鑰。
請求使用 GFP_KERNEL 之外的其他東西來分配記憶體。
避免使用 recvmsg() 呼叫的開銷。 RxRPC 訊息可以在進入套接字 Rx 佇列之前被攔截,並且可以直接操作套接字緩衝區。
要使用 RxRPC 功能,核心實用程式仍然必須開啟一個 AF_RXRPC 套接字,根據需要繫結地址,如果它是一個伺服器套接字,則進行監聽,然後將其傳遞給核心介面函式。
核心介面函式如下
開始一個新的客戶端呼叫
struct rxrpc_call * rxrpc_kernel_begin_call(struct socket *sock, struct sockaddr_rxrpc *srx, struct key *key, unsigned long user_call_ID, s64 tx_total_len, gfp_t gfp, rxrpc_notify_rx_t notify_rx, bool upgrade, bool intr, unsigned int debug_id);這會分配用於發起新 RxRPC 呼叫的基礎結構,並分配呼叫和連線號。呼叫將在套接字繫結到的 UDP 埠上進行。除非提供了替代地址(srx 為非 NULL),否則該呼叫將轉到已連線客戶端套接字的目標地址。
如果提供了金鑰,那麼將使用它來保護呼叫,而不是使用 RXRPC_SECURITY_KEY sockopt 繫結到套接字的金鑰。以這種方式保護的呼叫仍然會盡可能地共享連線。
user_call_ID 等同於在控制資料緩衝區中提供給 sendmsg() 的 ID。完全可以使用它來指向核心資料結構。
tx_total_len 是呼叫者打算透過此呼叫傳輸的資料量(如果此時未知,則為 -1)。設定資料大小允許核心直接加密到資料包緩衝區,從而節省複製。該值不能小於 -1。
notify_rx 是指向函式的指標,該函式在發生諸如傳入資料包或遠端中止之類的事件時被呼叫。
如果客戶端操作應請求伺服器將服務升級到更好的服務,則應將 upgrade 設定為 true。生成的服務 ID 由
rxrpc_kernel_recv_data()返回。如果該呼叫應可中斷,則應將 intr 設定為 true。如果未設定此項,則此函式可能不會返回,直到分配了一個通道;如果設定了此項,該函式可能會返回 -ERESTARTSYS。
debug_id 是用於跟蹤的呼叫除錯 ID。可以透過原子方式遞增 rxrpc_debug_id 來獲得此 ID。
如果此函式成功,則返回對 RxRPC 呼叫的不透明引用。呼叫者現在持有此引用,並且必須正確結束它。
關閉客戶端呼叫
void rxrpc_kernel_shutdown_call(struct socket *sock, struct rxrpc_call *call);用於關閉先前開始的呼叫。 user_call_ID 從 AF_RXRPC 的知識中刪除,並且不會再次與指定的呼叫關聯。
釋放對客戶端呼叫的引用
void rxrpc_kernel_put_call(struct socket *sock, struct rxrpc_call *call);用於釋放呼叫者對 rxrpc 呼叫的引用。
透過呼叫傳送資料
typedef void (*rxrpc_notify_end_tx_t)(struct sock *sk, unsigned long user_call_ID, struct sk_buff *skb); int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call, struct msghdr *msg, size_t len, rxrpc_notify_end_tx_t notify_end_rx);用於提供客戶端呼叫的請求部分或伺服器呼叫的回覆部分。 msg.msg_iovlen 和 msg.msg_iov 指定要使用的資料緩衝區。 msg_iov 不得為 NULL,並且必須專門指向核心虛擬地址。如果此呼叫將有後續資料傳送,則可以給出 msg.msg_flags MSG_MORE。
msg 不得指定目標地址、控制資料或 MSG_MORE 之外的任何標誌。 len 是要傳輸的資料總量。
notify_end_rx 可以為 NULL,也可以用於指定當呼叫狀態更改為結束 Tx 階段時要呼叫的函式。呼叫此函式時會持有一個自旋鎖,以防止在函式返回之前傳輸最後一個 DATA 資料包。
從呼叫接收資料
int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call, void *buf, size_t size, size_t *_offset, bool want_more, u32 *_abort, u16 *_service) This is used to receive data from either the reply part of a client call or the request part of a service call. buf and size specify how much data is desired and where to store it. *_offset is added on to buf and subtracted from size internally; the amount copied into the buffer is added to *_offset before returning. want_more should be true if further data will be required after this is satisfied and false if this is the last item of the receive phase. There are three normal returns: 0 if the buffer was filled and want_more was true; 1 if the buffer was filled, the last DATA packet has been emptied and want_more was false; and -EAGAIN if the function needs to be called again. If the last DATA packet is processed but the buffer contains less than the amount requested, EBADMSG is returned. If want_more wasn't set, but more data was available, EMSGSIZE is returned. If a remote ABORT is detected, the abort code received will be stored in ``*_abort`` and ECONNABORTED will be returned. The service ID that the call ended up with is returned into *_service. This can be used to see if a call got a service upgrade.中止呼叫??
void rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call, u32 abort_code);如果呼叫仍處於可中止狀態,則可以使用此函式中止呼叫。指定的中止程式碼將放置在傳送的 ABORT 訊息中。
攔截接收到的 RxRPC 訊息
typedef void (*rxrpc_interceptor_t)(struct sock *sk, unsigned long user_call_ID, struct sk_buff *skb); void rxrpc_kernel_intercept_rx_messages(struct socket *sock, rxrpc_interceptor_t interceptor);這將在指定的 AF_RXRPC 套接字上安裝一個攔截器函式。所有原本會進入套接字 Rx 佇列的訊息都會被轉移到此函式。請注意,必須小心地按正確的順序處理訊息,以保持 DATA 訊息的順序性。
攔截器函式本身會獲得套接字的地址和處理傳入訊息、核心實用程式分配給呼叫的 ID 以及包含該訊息的套接字緩衝區。
skb->mark 欄位指示訊息的型別
標記
含義
RXRPC_SKB_MARK_DATA
資料訊息
RXRPC_SKB_MARK_FINAL_ACK
收到的傳入呼叫的最終 ACK
RXRPC_SKB_MARK_BUSY
客戶端呼叫被拒絕,因為伺服器繁忙
RXRPC_SKB_MARK_REMOTE_ABORT
呼叫被對等方中止
RXRPC_SKB_MARK_NET_ERROR
檢測到網路錯誤
RXRPC_SKB_MARK_LOCAL_ERROR
遇到本地錯誤
RXRPC_SKB_MARK_NEW_CALL
等待接受的新傳入呼叫
可以使用 rxrpc_kernel_get_abort_code() 探測遠端中止訊息。可以使用 rxrpc_kernel_get_error_number() 探測兩條錯誤訊息。可以使用 rxrpc_kernel_accept_call() 接受新的呼叫。
可以使用通常的套接字緩衝區操作函式提取資料訊息的內容。可以使用 rxrpc_kernel_is_data_last() 確定資料訊息是否是序列中的最後一個訊息。當資料訊息被用完時,應該在其上呼叫 rxrpc_kernel_data_consumed()。
應將訊息處理為 rxrpc_kernel_free_skb() 以進行處置。可以獲得所有型別的訊息的額外引用以供以後釋放,但這可能會固定呼叫的狀態,直到最終釋放該訊息。
接受傳入呼叫
struct rxrpc_call * rxrpc_kernel_accept_call(struct socket *sock, unsigned long user_call_ID);用於接受傳入呼叫併為其分配呼叫 ID。此函式類似於
rxrpc_kernel_begin_call(),並且接受的呼叫必須以相同的方式結束。如果此函式成功,則返回對 RxRPC 呼叫的不透明引用。呼叫者現在持有此引用,並且必須正確結束它。
拒絕傳入呼叫
int rxrpc_kernel_reject_call(struct socket *sock);用於拒絕套接字佇列中的第一個傳入呼叫,並顯示 BUSY 訊息。如果沒有傳入呼叫,則返回 -ENODATA。如果呼叫已被中止 (-ECONNABORTED) 或已超時 (-ETIME),則可能會返回其他錯誤。
分配一個空金鑰以進行匿名安全
struct key *rxrpc_get_null_key(const char *keyname);用於分配一個空 RxRPC 金鑰,該金鑰可用於指示特定域的匿名安全。
獲取呼叫的對等地址
void rxrpc_kernel_get_peer(struct socket *sock, struct rxrpc_call *call, struct sockaddr_rxrpc *_srx);用於查詢呼叫的遠端對等地址。
設定呼叫中的總傳輸資料大小
void rxrpc_kernel_set_tx_length(struct socket *sock, struct rxrpc_call *call, s64 tx_total_len);設定呼叫者打算在呼叫中傳輸的資料量。它旨在用於設定回覆大小,因為請求大小應在呼叫開始時設定。 tx_total_len 不得小於零。
獲取呼叫 RTT
u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call);獲取呼叫正在使用的對等方的 RTT 時間。返回的值以納秒為單位。
檢查呼叫是否仍然有效
bool rxrpc_kernel_check_life(struct socket *sock, struct rxrpc_call *call, u32 *_life); void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call);第一個函式在
*_life中傳遞迴一個數字,該數字在收到來自對等方的 ACK 時更新(特別包括我們可以透過傳送 PING ACK 來引出的 PING RESPONSE ACK,以檢視呼叫是否仍然存在於伺服器上)。呼叫者應比較兩個呼叫的數字,以檢視在等待適當的間隔後呼叫是否仍然有效。只要呼叫尚未達到完成狀態,它也會返回 true。這允許呼叫者在等待伺服器處理客戶端操作時確定伺服器是否仍然可連線以及呼叫是否仍然在伺服器上有效。
第二個函式會導致傳輸一個 ping ACK 以嘗試刺激對等方進行響應,這將導致第一個函式返回的值發生更改。請注意,必須在 TASK_RUNNING 狀態下呼叫此函式。
從核心內部將 RXRPC_MIN_SECURITY_LEVEL sockopt 應用於套接字
int rxrpc_sock_set_min_security_level(struct sock *sk, unsigned int val);這指定了此套接字上的呼叫所需的最低安全級別。
可配置引數¶
RxRPC 協議驅動程式具有許多可透過 /proc/net/rxrpc/ 中的 sysctl 進行調整的可配置引數。
req_ack_delay
在我們收到設定了 request-ack 標誌的資料包後,在實際響應標誌並實際傳送所請求的 ack 之前的毫秒數。
通常,另一方在通告的接收視窗已滿(最多 255 個數據包)之前不會停止傳送資料包,因此延遲 ACK 允許一次 ACK 多個數據包。
soft_ack_delay
在我們收到一個新資料包後,在我們生成一個 soft-ACK 以告知傳送者它不需要重新發送之前的毫秒數。
idle_ack_delay
在我們使用完接收佇列中當前的所有資料包之後,在我們生成一個 hard-ACK 以告知傳送者它可以釋放其緩衝區之前的毫秒數,假設沒有發生我們會發送 ACK 的其他原因。
resend_timeout
在我們傳輸一個數據包之後,在我們再次傳輸它之前的毫秒數,假設我們沒有收到來自接收者的 ACK 告知我們他們收到了該資料包。
max_call_lifetime
在我們搶先終止呼叫之前,呼叫可能進行的以秒為單位的最長時間。
dead_call_expiry
在我們從呼叫列表中刪除已死呼叫之前的以秒為單位的時間量。已死呼叫會保留一段時間,目的是重複 ACK 和 ABORT 資料包。
connection_expiry
在我們從連線列表中刪除連線之前,連線上次使用的以秒為單位的時間量。當連線存在時,它可以作為協商的安全的佔位符;當它被刪除時,必須重新協商安全。
transport_expiry
在我們從傳輸列表中刪除傳輸之前,傳輸上次使用的以秒為單位的時間量。當傳輸存在時,它可以作為對等資料和保持連線 ID 計數器的錨點。
rxrpc_rx_window_size
接收視窗的大小(以資料包為單位)。這是我們願意為任何特定呼叫在記憶體中儲存的未使用的接收資料包的最大數量。
rxrpc_rx_mtu
我們願意接收的最大的資料包 MTU 大小(以位元組為單位)。這向對等方表明我們是否願意接受巨型資料包。
rxrpc_rx_jumbo_max
我們願意在巨型資料包中接受的資料包的最大數量。巨型資料包中的非終端資料包必須包含一個四位元組標頭加上恰好 1412 位元組的資料。終端資料包必須包含一個四位元組標頭加上任意數量的資料。在任何情況下,巨型資料包的大小都不得超過 rxrpc_rx_mtu。
API 函式參考¶
-
struct rxrpc_peer *rxrpc_kernel_lookup_peer(struct socket *sock, struct sockaddr_rxrpc *srx, gfp_t gfp)¶
獲取地址的遠端傳輸端點
引數
struct socket *sock將透過其訪問的套接字
struct sockaddr_rxrpc *srx網路地址
gfp_t gfp分配標誌
描述
查詢或建立指定地址的遠端傳輸端點記錄。
返回
找到的帶有引用的對等記錄,如果找不到記錄,則返回 NULL;如果地址無效或不受支援,則返回負錯誤程式碼。
-
struct rxrpc_peer *rxrpc_kernel_get_peer(struct rxrpc_peer *peer)¶
獲取對等方的引用
引數
struct rxrpc_peer *peer要獲取引用的對等方(可以為 NULL)。
描述
獲取遠端對等記錄的引用(如果不是 NULL)。
返回
peer 引數。
-
void rxrpc_kernel_put_peer(struct rxrpc_peer *peer)¶
允許核心應用程式刪除對等引用
引數
struct rxrpc_peer *peer要刪除引用的對等方
描述
刪除對等記錄的引用。
-
struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, struct rxrpc_peer *peer, struct key *key, unsigned long user_call_ID, s64 tx_total_len, u32 hard_timeout, gfp_t gfp, rxrpc_notify_rx_t notify_rx, u16 service_id, bool upgrade, enum rxrpc_interruptibility interruptibility, unsigned int debug_id)¶
允許核心服務開始呼叫
引數
struct socket *sock要在其上進行呼叫的套接字
struct rxrpc_peer *peer要聯絡的對等方
struct key *key要使用的安全上下文(預設為套接字設定)
unsigned long user_call_ID要使用的 ID
s64 tx_total_len在呼叫期間要傳輸的資料的總長度(或 -1)
u32 hard_timeout呼叫最長的生存期(以秒為單位)
gfp_t gfp分配約束
rxrpc_notify_rx_t notify_rx將通知傳送到何處而不是傳送到套接字佇列
u16 service_id要聯絡的服務的 ID
bool upgrade請求呼叫的服務升級
enum rxrpc_interruptibility interruptibility呼叫可中斷,或者可以取消。
unsigned int debug_id要分配給呼叫的跟蹤的除錯 ID
描述
允許核心服務在指定的套接字上開始呼叫。這只是設定所有內部跟蹤結構,並根據需要分配連線和呼叫 ID。
可以透過提供 srx 和 key 來覆蓋預設的套接字目標地址和安全性。
返回
新呼叫或錯誤程式碼。
引數
struct socket *sock呼叫所在的套接字
struct rxrpc_call *call要結束的呼叫
描述
允許核心服務關閉其正在使用的呼叫。必須先完成呼叫才能呼叫此函式(如有必要,應中止呼叫)。
引數
struct socket *sock呼叫所在的套接字
struct rxrpc_call *call要放置的呼叫
描述
刪除應用程式對 rxrpc 呼叫的引用。
引數
const struct socket *sock呼叫所在的套接字
const struct rxrpc_call *call要檢查的呼叫
描述
允許核心服務找出呼叫是否仍然有效 - 它是否已成功完成並且是否已使用所有收到的資料。
返回
如果呼叫仍在進行中,則為 true;如果已完成,則為 false。
-
void rxrpc_kernel_set_notifications(struct socket *sock, const struct rxrpc_kernel_ops *app_ops)¶
設定回撥操作表
引數
struct socket *sock要在其上安裝表的套接字
const struct rxrpc_kernel_ops *app_ops要設定的回撥操作表
描述
允許核心服務在套接字上設定事件通知表。
-
u8 rxrpc_kernel_query_call_security(struct rxrpc_call *call, u16 *_service_id, u32 *_enctype)¶
查詢呼叫的安全引數
引數
struct rxrpc_call *call要查詢的呼叫
u16 *_service_id在何處返回服務 ID
u32 *_enctype在何處返回“編碼型別”
描述
這將查詢呼叫的安全引數,設定 *_service_id 和 *_enctype 並返回安全類。
返回
安全類協議號。
-
struct key *rxrpc_get_null_key(const char *keyname)¶
生成一個空的 RxRPC 金鑰
引數
const char *keyname用於指定金鑰的名稱。
描述
生成一個空的 RxRPC 金鑰,可用於指示特定域需要匿名安全。
返回
新金鑰或負錯誤程式碼。
-
enum rxrpc_oob_type rxrpc_kernel_query_oob(struct sk_buff *oob, struct rxrpc_peer **_peer, unsigned long *_peer_appdata)¶
查詢帶外訊息的引數
引數
struct sk_buff *oob要查詢的訊息
struct rxrpc_peer **_peer用於返回對等體記錄的位置
unsigned long *_peer_appdata附加到對等體記錄的應用程式資料
描述
從帶外訊息中提取有用的引數。源對等體引數透過引數列表返回,訊息型別也被返回。
返回
RXRPC_OOB_CHALLENGE- 需要響應的挑戰。
-
struct sk_buff *rxrpc_kernel_dequeue_oob(struct socket *sock, enum rxrpc_oob_type *_type)¶
出列並返回最前面的 OOB 訊息
引數
struct socket *sock要查詢的套接字
enum rxrpc_oob_type *_type用於返回訊息型別的位置
描述
出列最前面的 OOB 訊息(如果存在),並返回它及其型別。
返回
表示 OOB 訊息的 sk_buff 或 NULL (如果佇列為空)。
引數
struct sk_buff *oob要釋放的 OOB 訊息
描述
釋放 OOB 訊息以及它所擁有的任何資源。
-
void rxrpc_kernel_query_challenge(struct sk_buff *challenge, struct rxrpc_peer **_peer, unsigned long *_peer_appdata, u16 *_service_id, u8 *_security_index)¶
查詢挑戰的引數
引數
struct sk_buff *challenge要查詢的挑戰
struct rxrpc_peer **_peer用於返回對等體記錄的位置
unsigned long *_peer_appdata附加到對等體記錄的應用程式資料
u16 *_service_id用於返回連線服務 ID 的位置
u8 *_security_index用於返回連線安全索引的位置
描述
從 CHALLENGE 訊息中提取有用的引數。
-
int rxrpc_kernel_reject_challenge(struct sk_buff *challenge, u32 abort_code, int error, enum rxrpc_abort_reason why)¶
允許核心服務拒絕挑戰
引數
struct sk_buff *challenge要拒絕的挑戰
u32 abort_code要放入 ABORT 資料包中的中止程式碼
int error本地錯誤值
enum rxrpc_abort_reason why指示原因。
描述
允許核心服務透過中止連線(如果它仍處於可中止狀態)來拒絕挑戰。返回錯誤,以便可以將此函式與 return 語句一起使用。
返回
The error parameter.
-
struct rxrpc_peer *rxrpc_kernel_get_call_peer(struct socket *sock, struct rxrpc_call *call)¶
獲取呼叫的對等地址
引數
struct socket *sock呼叫正在進行的套接字。
struct rxrpc_call *call要查詢的呼叫
描述
獲取呼叫中遠端對等體的記錄。
返回
呼叫的對等體記錄。
-
unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *peer)¶
獲取呼叫的對等體平滑 RTT
引數
const struct rxrpc_peer *peer要查詢的對等體
描述
獲取呼叫的對等體平滑 RTT。
返回
以 uS 為單位的 RTT,或者如果沒有樣本,則為 UINT_MAX。
-
const struct sockaddr_rxrpc *rxrpc_kernel_remote_srx(const struct rxrpc_peer *peer)¶
獲取對等體的地址
引數
const struct rxrpc_peer *peer要查詢的對等體
描述
從對等體記錄獲取指向地址的指標。呼叫方負責確保地址未被釋放。如果 peer 為 NULL,則將替換為偽造地址。
返回
rxrpc 地址記錄或偽造記錄。
-
const struct sockaddr *rxrpc_kernel_remote_addr(const struct rxrpc_peer *peer)¶
獲取呼叫的對等體傳輸地址
引數
const struct rxrpc_peer *peer要查詢的對等體
描述
從對等體記錄獲取指向傳輸地址的指標。呼叫方負責確保地址未被釋放。如果 peer 為 NULL,則將替換為偽造地址。
返回
傳輸地址記錄或偽造記錄。
-
unsigned long rxrpc_kernel_set_peer_data(struct rxrpc_peer *peer, unsigned long app_data)¶
在對等體上設定應用程式特定的資料。
引數
struct rxrpc_peer *peer要更改的對等體
unsigned long app_data要設定的資料
描述
在對等體上設定應用程式特定的資料。AF_RXRPC 不會盡力保留資料可能引用的任何內容。
返回
先前的 app_data。
-
unsigned long rxrpc_kernel_get_peer_data(const struct rxrpc_peer *peer)¶
從對等體獲取應用程式特定的資料。
引數
const struct rxrpc_peer *peer要查詢的對等體
描述
從對等體檢索應用程式特定的資料。
返回
對等體的應用程式資料。
-
int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call, struct iov_iter *iter, size_t *_len, bool want_more, u32 *_abort, u16 *_service)¶
允許核心服務接收資料/資訊
引數
struct socket *sock呼叫存在的套接字
struct rxrpc_call *call用於傳送資料的呼叫
struct iov_iter *iter要接收到的緩衝區
size_t *_len我們要接收的資料量(在返回時減少)
bool want_more如果期望讀取更多資料,則為 True
u32 *_abort如果返回 -ECONNABORTED,則中止程式碼的儲存位置
u16 *_service實際服務 ID 的儲存位置(可能會升級)
描述
允許核心服務接收資料並獲取有關呼叫狀態的資訊。請注意,*_abort 也應初始化為 0。
請注意,即使我們已經複製了請求的資料,我們也可以返回 -EAGAIN 以在資料末尾耗盡空資料包。
返回
如果獲得了所請求的內容並且有更多可用內容,則為 0;如果獲得了所請求的內容並且我們位於資料末尾,則為 1;如果我們需要更多資料,則為 -EAGAIN。
引數
struct sk_buff *challenge要查詢的挑戰資料包
返回
被挑戰連線的 Kerberos 5 編碼型別。
-
int rxgk_kernel_respond_to_challenge(struct sk_buff *challenge, struct krb5_buffer *appdata)¶
使用 appdata 響應挑戰
引數
struct sk_buff *challenge要響應的挑戰
struct krb5_buffer *appdata要包含在 RESPONSE 驗證器中的應用程式資料
描述
允許核心應用程式使用要包含在 RxGK RESPONSE 驗證器中的應用程式資料來響應 CHALLENGE。
返回
如果成功,則為 0,否則為負錯誤程式碼。
引數
struct sk_buff *challenge要響應的挑戰
描述
允許核心應用程式響應 CHALLENGE。
返回
如果成功,則為 0,否則為負錯誤程式碼。
-
int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call, struct msghdr *msg, size_t len, rxrpc_notify_end_tx_t notify_end_tx)¶
允許核心服務在呼叫上傳送資料
引數
struct socket *sock呼叫所在的套接字
struct rxrpc_call *call用於傳送資料的呼叫
struct msghdr *msg要傳送的資料
size_t len要傳送的資料量
rxrpc_notify_end_tx_t notify_end_tx最後一個數據包已排隊的通知。
描述
允許核心服務在呼叫上傳送資料。呼叫必須處於適合傳送資料的狀態。不應在 msg 中提供控制資料,也不應提供地址。如果還有更多資料要傳送,則應標記 MSG_MORE,否則此資料將結束傳輸階段。
返回
如果成功,則為 0,否則為負錯誤程式碼。
-
bool rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call, u32 abort_code, int error, enum rxrpc_abort_reason why)¶
允許核心服務中止一個呼叫
引數
struct socket *sock呼叫所在的套接字
struct rxrpc_call *call要中止的呼叫
u32 abort_code要放入 ABORT 資料包中的中止程式碼
int error本地錯誤值
enum rxrpc_abort_reason why指示原因。
描述
允許核心服務在呼叫仍處於可中止狀態時中止它。
返回
如果呼叫已中止,則為true,如果呼叫已經完成,則為false。
-
void rxrpc_kernel_set_tx_length(struct socket *sock, struct rxrpc_call *call, s64 tx_total_len)¶
設定呼叫上的總 Tx 長度
引數
struct socket *sock呼叫所在的套接字
struct rxrpc_call *call要通知的呼叫
s64 tx_total_len此呼叫要傳輸的資料量
描述
允許核心服務設定呼叫上的總傳輸長度。這允許執行 buffer-to-packet encrypt-and-copy。
此函式主要用於設定回覆長度,因為可以在開始呼叫時設定請求長度。
引數
struct sock *sk要在其上設定金鑰環的套接字
struct key *keyring要設定的金鑰環
描述
在 rxrpc 套接字上設定伺服器安全金鑰環。這用於為核心服務提供加密金鑰。
返回
如果成功,則為 0,否則為負錯誤程式碼。
引數
struct sock *sk要在其上設定金鑰環的套接字
bool setTrue 設定,false 清除標誌
描述
在 rxrpc 套接字上設定標誌,以表明呼叫者想要管理 RESPONSE 資料包及其可能包含的使用者定義資料。 設定此標誌意味著 recvmsg() 將返回控制訊息緩衝區中包含 RXRPC_CHALLENGED 的訊息,其中包含有關挑戰的資訊。
使用者應該透過使用 sendmsg() 向同一個呼叫傳遞帶有 RXRPC_RESPOND 或 RXRPC_RESPOND_ABORT 控制訊息來響應挑戰。 可以包含補充控制訊息,例如 RXRPC_RESP_RXGK_APPDATA,以指示使用者想要提供的部分。
當伺服器從每個呼叫中獲取第一個資料時,將使用 RXRPC_RESPONDED 控制訊息將響應資料傳遞給伺服器。
請注意,這僅適用於需要輔助資料的安全類(例如 RxGK)。 那些不提供該功能的(例如 RxKAD)會在不諮詢使用者空間的情況下做出響應。
返回
先前的設定。