mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 21:42:43 +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
	
	 Sergey Bugaev
						Sergey Bugaev