-
-
Notifications
You must be signed in to change notification settings - Fork 169
fix(net): udp getsockname/getpeername #1460
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,7 +69,6 @@ impl UnboundUdp { | |
| Ok(BoundUdp { | ||
| inner, | ||
| remote: SpinLock::new(None), | ||
| local_endpoint: smoltcp::wire::IpEndpoint::new(bind_addr, bind_port), | ||
| }) | ||
| } | ||
|
|
||
|
|
@@ -85,7 +84,6 @@ impl UnboundUdp { | |
| Ok(BoundUdp { | ||
| inner, | ||
| remote: SpinLock::new(Some(endpoint)), | ||
| local_endpoint: endpoint, | ||
| }) | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: getsockname returns wrong data after implicit bindThe Additional Locations (1) |
||
| } | ||
|
|
@@ -94,7 +92,6 @@ impl UnboundUdp { | |
| pub struct BoundUdp { | ||
| inner: BoundInner, | ||
| remote: SpinLock<Option<smoltcp::wire::IpEndpoint>>, | ||
| local_endpoint: smoltcp::wire::IpEndpoint, | ||
| } | ||
|
|
||
| impl BoundUdp { | ||
|
|
@@ -117,6 +114,14 @@ impl BoundUdp { | |
| .with::<SmolUdpSocket, _, _>(|socket| socket.endpoint()) | ||
| } | ||
|
|
||
| pub fn remote_endpoint(&self) -> Result<smoltcp::wire::IpEndpoint, SystemError> { | ||
| self.remote | ||
| .lock() | ||
| .as_ref() | ||
| .cloned() | ||
| .ok_or(SystemError::ENOTCONN) | ||
| } | ||
|
|
||
| pub fn connect(&self, remote: smoltcp::wire::IpEndpoint) { | ||
| self.remote.lock().replace(remote); | ||
| } | ||
|
|
@@ -165,10 +170,6 @@ impl BoundUdp { | |
| socket.close(); | ||
| }); | ||
| } | ||
|
|
||
| pub fn local_endpoint(&self) -> smoltcp::wire::IpEndpoint { | ||
| self.local_endpoint | ||
| } | ||
| } | ||
|
|
||
| // Udp Inner 负责其内部资源管理 | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -128,9 +128,10 @@ impl UdpSocket { | |||||
| { | ||||||
| let mut inner_guard = self.inner.write(); | ||||||
| let inner = match inner_guard.take().expect("Udp Inner is None") { | ||||||
| // TODO: 此处会为空,需要DEBUG | ||||||
| UdpInner::Bound(bound) => bound, | ||||||
| UdpInner::Unbound(unbound) => unbound | ||||||
| .bind_ephemeral(to.ok_or(SystemError::EADDRNOTAVAIL)?.addr, self.netns())?, | ||||||
| .bind_ephemeral(to.ok_or(SystemError::EDESTADDRREQ)?.addr, self.netns())?, | ||||||
| }; | ||||||
| // size = inner.try_send(buf, to)?; | ||||||
| inner_guard.replace(UdpInner::Bound(inner)); | ||||||
|
|
@@ -263,13 +264,25 @@ impl Socket for UdpSocket { | |||||
| } | ||||||
|
|
||||||
| fn remote_endpoint(&self) -> Result<Endpoint, SystemError> { | ||||||
| todo!() | ||||||
| match self.inner.read().as_ref().unwrap() { | ||||||
|
||||||
| match self.inner.read().as_ref().unwrap() { | |
| match self.inner.read().as_ref().ok_or(SystemError::EBADF)? { |
Copilot
AI
Dec 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of unwrap() here could panic if the inner Option is None. While the inner field is initialized as Some(UdpInner::Unbound(...)) in new(), it can be set to None via take() in the close() method (line 93). If local_endpoint() is called after the socket is closed, this will panic. Consider using a more explicit error handling approach, such as ok_or(SystemError::EBADF)? to return an appropriate error when the socket is closed.
| match self.inner.read().as_ref().unwrap() { | |
| match self.inner.read().as_ref().ok_or(SystemError::EBADF)? { |
Copilot
AI
Dec 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hardcoded IPv4 address [0, 0, 0, 0] and port 0 create magic numbers. Consider using a named constant like UNSPECIFIED_LOCAL_ENDPOINT_V4 (defined at kernel/src/net/socket/inet/mod.rs:32-33) for better maintainability and consistency with the TCP implementation.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| SocketTest.UnixSocketPairProtocol | ||
| # SocketTest.ProtocolInet # Only Inet sockets are enabled | ||
| SocketTest.ProtocolUnix | ||
| SocketTest.UnixSocketStat | ||
| SocketTest.UnixSocketStatFS | ||
| SocketTest.UnixSCMRightsOnlyPassedOnce | ||
| SocketTest.Permission | ||
| OpenModes/*.Unix/* |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| **/1 | ||
| **/2 | ||
| UdpInet6SocketTest.ConnectInet4Sockaddr | ||
| # **.Creation | ||
| # **.Getsockname | ||
| # **.Getpeername | ||
| **.SendNotConnected/** | ||
| **.ConnectBinds/** | ||
| **.ReceiveNotBound/** | ||
| **.Bind/** | ||
| **.BindInUse/** | ||
| **.ConnectWriteToInvalidPort/** | ||
| **.ConnectSimultaneousWriteToInvalidPort/** | ||
| **.ReceiveAfterConnect/** | ||
| **.ReceiveAfterDisconnect/** | ||
| **.Connect/** | ||
| **.ConnectAnyZero/** | ||
| **.ConnectAnyWithPort/** | ||
| **.DisconnectAfterConnectAny/** | ||
| **.DisconnectAfterConnectAnyWithPort/** | ||
| **.DisconnectAfterBind/** | ||
| **.DisconnectAfterBindToUnspecAndConnect/** | ||
| **.DisconnectAfterConnectWithoutBind/** | ||
| **.BindToAnyConnnectToLocalhost/** | ||
| **.DisconnectAfterBindToAny/** | ||
| **.Disconnect/** | ||
| **.ConnectBadAddress/** | ||
| **.SendToAddressOtherThanConnected/** | ||
| **.ConnectAndSendNoReceiver/** | ||
| **.RecvErrorConnRefusedOtherAFSockOpt/** | ||
| **.RecvErrorConnRefused/** | ||
| **.ZerolengthWriteAllowed/** | ||
| **.ZerolengthWriteAllowedNonBlockRead/** | ||
| **.SendAndReceiveNotConnected/** | ||
| **.SendAndReceiveConnected/** | ||
| **.ReceiveFromNotConnected/** | ||
| **.ReceiveBeforeConnect/** | ||
| **.ReceiveFrom/** | ||
| **.Listen/** | ||
| **.Accept/** | ||
| **.ReadShutdownNonblockPendingData/** | ||
| **.ReadShutdownSameSocketResetsShutdownState/** | ||
| **.ReadShutdown/** | ||
| **.ReadShutdownDifferentThread/** | ||
| **.WriteShutdown/** | ||
| **.SynchronousReceive/** | ||
| **.BoundaryPreserved_SendRecv/** | ||
| **.BoundaryPreserved_WritevReadv/** | ||
| **.BoundaryPreserved_SendMsgRecvMsg/** | ||
| **.FIONREADShutdown/** | ||
| **.FIONREADWriteShutdown/** | ||
| **.Fionread/** | ||
| **.FIONREADZeroLengthPacket/** | ||
| **.FIONREADZeroLengthWriteShutdown/** | ||
| **.SoNoCheckOffByDefault/** | ||
| **.SoNoCheck/** | ||
| **.ErrorQueue/** | ||
| **.SoTimestampOffByDefault/** | ||
| **.SoTimestamp/** | ||
| **.WriteShutdownNotConnected/** | ||
| **.TimestampIoctl/** | ||
| **.TimestampIoctlNothingRead/** | ||
| **.TimestampIoctlPersistence/** | ||
| **.RecvBufLimitsEmptyRcvBuf/** | ||
| **.RecvBufLimits/** | ||
| **.SetSocketDetachFilter/** | ||
| **.SetSocketDetachFilterNoInstalledFilter/** | ||
| **.GetSocketDetachFilter/** | ||
| **.SendToZeroPort/** | ||
| **.ConnectToZeroPortUnbound/** | ||
| **.ConnectToZeroPortBound/** | ||
| **.ConnectToZeroPortConnected/** | ||
| **.SetAndReceiveTOSOrTClass/** | ||
| **.SendAndReceiveTOSorTClass/** | ||
| **.SetAndReceiveTTLOrHopLimit/** | ||
| **.SendAndReceiveTTLOrHopLimit/** | ||
| **.SetAndReceivePktInfo/** | ||
| **.SendPacketLargerThanSendBufOnNonBlockingSocket/** | ||
| **.ReadShutdownOnBoundSocket/** | ||
| **.ReconnectDoesNotClearReadShutdown/** | ||
| **.ReconnectDoesNotClearWriteShutdown/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: bind_ephemeral stores local endpoint in remote field
In
bind_ephemeral, theendpointvariable is constructed from the localaddressand localbound_port, making it the local endpoint. However, this is stored in theremotefield. The newly implementedremote_endpoint()method returns this value, sogetpeername()would return the local endpoint instead of the remote endpoint for sockets that went throughbind_ephemeral. While this existed in the old code, it's now exposed sinceremote_endpoint()was changed fromtodo!()to an actual implementation.Additional Locations (1)
kernel/src/net/socket/inet/datagram/mod.rs#L265-L271