mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 06:58:11 +00:00
Kernel: Implement IP multicast support
An IP socket can now join a multicast group by using the IP_ADD_MEMBERSHIP sockopt, which will cause it to start receiving packets sent to the multicast address, even though this address does not belong to this host.
This commit is contained in:
parent
b9c367e13b
commit
78459b92d5
5 changed files with 77 additions and 7 deletions
|
@ -466,6 +466,42 @@ KResult IPv4Socket::setsockopt(int level, int option, Userspace<const void*> use
|
|||
m_ttl = value;
|
||||
return KSuccess;
|
||||
}
|
||||
case IP_MULTICAST_LOOP: {
|
||||
if (user_value_size != 1)
|
||||
return EINVAL;
|
||||
u8 value;
|
||||
if (!copy_from_user(&value, static_ptr_cast<const u8*>(user_value)))
|
||||
return EFAULT;
|
||||
if (value != 0 && value != 1)
|
||||
return EINVAL;
|
||||
m_multicast_loop = value;
|
||||
return KSuccess;
|
||||
}
|
||||
case IP_ADD_MEMBERSHIP: {
|
||||
if (user_value_size != sizeof(ip_mreq))
|
||||
return EINVAL;
|
||||
ip_mreq mreq;
|
||||
if (!copy_from_user(&mreq, static_ptr_cast<const ip_mreq*>(user_value)))
|
||||
return EFAULT;
|
||||
if (mreq.imr_interface.s_addr != INADDR_ANY)
|
||||
return ENOTSUP;
|
||||
IPv4Address address { (const u8*)&mreq.imr_multiaddr.s_addr };
|
||||
if (!m_multicast_memberships.contains_slow(address))
|
||||
m_multicast_memberships.append(address);
|
||||
return KSuccess;
|
||||
}
|
||||
case IP_DROP_MEMBERSHIP: {
|
||||
if (user_value_size != sizeof(ip_mreq))
|
||||
return EINVAL;
|
||||
ip_mreq mreq;
|
||||
if (!copy_from_user(&mreq, static_ptr_cast<const ip_mreq*>(user_value)))
|
||||
return EFAULT;
|
||||
if (mreq.imr_interface.s_addr != INADDR_ANY)
|
||||
return ENOTSUP;
|
||||
IPv4Address address { (const u8*)&mreq.imr_multiaddr.s_addr };
|
||||
m_multicast_memberships.remove_first_matching([&address](auto& a) { return a == address; });
|
||||
return KSuccess;
|
||||
}
|
||||
default:
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
|
@ -490,6 +526,16 @@ KResult IPv4Socket::getsockopt(FileDescription& description, int level, int opti
|
|||
if (!copy_to_user(value_size, &size))
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
case IP_MULTICAST_LOOP: {
|
||||
if (size < 1)
|
||||
return EINVAL;
|
||||
if (!copy_to_user(static_ptr_cast<u8*>(value), (const u8*)&m_multicast_loop))
|
||||
return EFAULT;
|
||||
size = 1;
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
}
|
||||
default:
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue