RFC 3678 筆記

Kola (Yan-Hao Wang)
8 min readAug 20, 2024

--

簡介

RFC 3493 定義了 IPv6 的 socket interface extension,有各種 protocol-independent functions 可以用,像是 getaddrinfo(),但在面對 multicast 時,我們沒有這種 function 可以用,我們想要加入 multicast ip 時,IPv4 要使用 IP_ADD_MEMBERSHIP 而 IPv6 要使用 IPV6_JOIN_GROUP,不符合我們的設計概念 (protocol independent),所以 RFC 3678 就是針對 multicast 新增了各種 protocol independent API,又叫做 filter。

RFC 3678 不只針對設定 multicast group (destination) 弄了新的 API,還增加了在使用 multicast 可以對來源設定白名單/黑名單的功能,所以 RFC 3678 主要是在講 filter source 的功能,我們可以把 API 分成兩類

  1. Basic (Delta-based) API: 主要用於增加或刪減與某個多播群組相關的 source address,這些 API 適用於當應用程式只跟一個人溝通時,像是 video/audio,此類 API 又有兩種 mode:

a. Any-source multicast, 一般來說應用程式會接受所有的流量,可以指定哪些 IP 不要接收,也就是加到 exclusion filter,又叫做 exclude mode。

b. Source-Specific Multicast: 又稱為 include mode,也就是指定某些 IP 能接收。

2. Advanced (Full-state): 用來替換 filter,可以用來切換 exclude/include mode 而不影響到多播群組的設定。

透過 IGMPv3 and MLDv2 協定跟 router 溝通可以達到 filter 的效果,但假如 router 不支援還是有可能透過 OS 本身 filter 掉東西。

而在此文件中又把 API 分成 IPv4-only API 跟 protocol-independent API,前者是為了讓 IPv4-only application 更好改。

IPv4

基本資料結構:

#include <netinet/in.h>

struct ip_mreq {
struct in_addr imr_multiaddr; /* IP address of group */
struct in_addr imr_interface; /* IP address of interface */
};

struct ip_mreq_source {
struct in_addr imr_multiaddr; /* IP address of group */
struct in_addr imr_sourceaddr; /* IP address of source */
struct in_addr imr_interface; /* IP address of interface */

以下 options 都是透過 setsockopt 函式來設定

  1. IPv4 Any-Source Multicast API
Socket option             Argument type
IP_ADD_MEMBERSHIP struct ip_mreq
IP_BLOCK_SOURCE struct ip_mreq_source
IP_UNBLOCK_SOURCE struct ip_mreq_source
IP_DROP_MEMBERSHIP struct ip_mreq

2. IPv4 Source-Specific Multicast API

Socket option             Argument type
IP_ADD_SOURCE_MEMBERSHIP struct ip_mreq_source
IP_DROP_SOURCE_MEMBERSHIP struct ip_mreq_source
IP_DROP_MEMBERSHIP struct ip_mreq

3. Advanced (Full-state) API for IPv4

#include <netinet/in.h>
int setipv4sourcefilter(int s, struct in_addr interface,
struct in_addr group, uint32_t fmode,
uint32_t numsrc, struct in_addr *slist);

int getipv4sourcefilter(int s, struct in_addr interface,
struct in_addr group, uint32_t *fmode,
uint32_t *numsrc, struct in_addr *slist);

Protocol-Independent Multicast Source Filter APIs

此類 API 使用 sockaddr_storage 當作參數來設定 multicast options,基本資料結構如下,使用情況像是 resolve DNS name to a multicast address, 這樣有可能會有 IPv4/6 address

struct group_req {
uint32_t gr_interface; /* interface index */
struct sockaddr_storage gr_group; /* group address */
};

struct group_source_req {
uint32_t gsr_interface; /* interface index */
struct sockaddr_storage gsr_group; /* group address */
struct sockaddr_storage gsr_source; /* source address */
};
  1. Any-Source Multicast API
Socket option               Argument type
MCAST_JOIN_GROUP struct group_req
MCAST_BLOCK_SOURCE struct group_source_req
MCAST_UNBLOCK_SOURCE struct group_source_req
MCAST_LEAVE_GROUP struct group_req

// join 是加入某個 source, leave 則是相反
// block 是擋特定 IP, unblock 則是相反

2. Source-Specific Multicast API

Socket option               Argument type
MCAST_JOIN_SOURCE_GROUP struct group_source_req
MCAST_LEAVE_SOURCE_GROUP struct group_source_req
MCAST_LEAVE_GROUP struct group_req

// 前兩個是加入跟刪除,而第三個則是刪除所有 group

3. Advanced (Full-state) API

#include <netinet/in.h>
int setsourcefilter(int s, uint32_t interface,
struct sockaddr *group, socklen_t grouplen,
uint32_t fmode, uint_t numsrc,
struct sockaddr_storage *slist);
/*
成功回傳 0 反之回傳 -1, 並且 set errno
s: socket
interface: interface index
group: 指向我們想要的 multicast group
grouplen: group 長度
fmode: 指定模式,不是 MCAST_INCLUDE 就是 MCAST_EXCLUDE
numsrc: slist 的數量, 根據 OS 會有不同最大值
slist: IP 陣列,根據 fmode 決定是黑名單還是白名單
*/

int getsourcefilter(int s, uint32_t interface,
struct sockaddr *group, socklen_t grouplen,
uint32_t fmode, uint_t *numsrc,
struct sockaddr_storage *slist);
/*
成功回傳 0 反之回傳 -1, 並且 set errno
s: socket
interface: local ip address of interface
group: 指向我們想要的 multicast group
fmode: 指定模式,不是 MCAST_INCLUDE 就是 MCAST_EXCLUDE
numsrc: slist 的數量, output 時會重新設定成 slist 的數量
slist: output 時會重新設定,假如 numsrc 是 0, 則會變成 NULL

假如一開始不知道 numsrc,則可以設成 0,獲得到 numsrc 的數字,在跑一次函式
*/

Appendix A

以前 ioctl 會用來代替 getsockopt 管理 multicast group,appendix 則討論 ioctl 的使用方式,目前只有比較舊的系統會看…

Reference

  1. https://www.ibm.com/docs/en/zos/3.1.0?topic=functions-setsockopt 此 doc 詳細介紹了 setsockopt function

--

--

Kola (Yan-Hao Wang)
Kola (Yan-Hao Wang)

Written by Kola (Yan-Hao Wang)

在系統軟體跟資安領域學習的學生

No responses yet