Skip to content
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

Return the full length of sockaddr_in in socket functions with in/out addrlen #550

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions libctru/source/services/soc/soc_accept.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
{
int ret = 0;
int tmp_addrlen = 0x1c;
int tmp_addrlen = ADDR_STORAGE_LEN;
int fd, dev;
u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[0x1c];
u8 tmpaddr[ADDR_STORAGE_LEN];
u32 saved_threadstorage[2];

sockfd = soc_get_fd(sockfd);
Expand All @@ -27,7 +27,7 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
fd = __alloc_handle(dev);
if(fd < 0) return fd;

memset(tmpaddr, 0, 0x1c);
memset(tmpaddr, 0, ADDR_STORAGE_LEN);

cmdbuf[0] = IPC_MakeHeader(0x4,2,2); // 0x40082
cmdbuf[1] = (u32)sockfd;
Expand Down Expand Up @@ -61,9 +61,14 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)

if(ret >= 0 && addr != NULL) {
addr->sa_family = tmpaddr[1];
if(*addrlen > tmpaddr[0])
*addrlen = tmpaddr[0];
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);

socklen_t user_addrlen = tmpaddr[0];
if(addr->sa_family == AF_INET)
user_addrlen += 8; // Accounting for the 8 bytes of sin_zero padding, which must be written for compatibility.

if(*addrlen > user_addrlen)
*addrlen = user_addrlen;
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - sizeof(addr->sa_family));
}

if(ret < 0) {
Expand Down
6 changes: 3 additions & 3 deletions libctru/source/services/soc/soc_bind.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
int ret = 0;
int tmp_addrlen = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[0x1c];
u8 tmpaddr[ADDR_STORAGE_LEN];

sockfd = soc_get_fd(sockfd);
if(sockfd < 0) {
errno = -sockfd;
return -1;
}

memset(tmpaddr, 0, 0x1c);
memset(tmpaddr, 0, ADDR_STORAGE_LEN);

if(addr->sa_family == AF_INET)
tmp_addrlen = 8;
else
tmp_addrlen = 0x1c;
tmp_addrlen = ADDR_STORAGE_LEN;

if(addrlen < tmp_addrlen) {
errno = EINVAL;
Expand Down
1 change: 1 addition & 0 deletions libctru/source/services/soc/soc_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <3ds/services/soc.h>

#define SYNC_ERROR ENODEV
#define ADDR_STORAGE_LEN sizeof(struct sockaddr_storage)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should have a _Static_assert(ADDR_STORAGE_LEN == 0x1c);

Copy link
Author

@Meziu Meziu Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea was to not hardcode the size to any particular value (this PR is of the intent to revise the size of sockaddr after all, and I remember that the 3DS doesn’t have IPv6 support). It could be a helpful test though, I’ll see whether to add it if I have to make any changes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc you get an error with any other value


extern Handle SOCU_handle;
extern Handle socMemhandle;
Expand Down
6 changes: 3 additions & 3 deletions libctru/source/services/soc/soc_connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
int ret = 0;
int tmp_addrlen = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u8 tmpaddr[0x1c];
u8 tmpaddr[ADDR_STORAGE_LEN];

sockfd = soc_get_fd(sockfd);
if(sockfd < 0) {
errno = -sockfd;
return -1;
}

memset(tmpaddr, 0, 0x1c);
memset(tmpaddr, 0, ADDR_STORAGE_LEN);

if(addr->sa_family == AF_INET)
tmp_addrlen = 8;
else
tmp_addrlen = 0x1c;
tmp_addrlen = ADDR_STORAGE_LEN;

if(addrlen < tmp_addrlen) {
errno = EINVAL;
Expand Down
4 changes: 2 additions & 2 deletions libctru/source/services/soc/soc_getnameinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_
int i,tmp_addrlen;
u32 *cmdbuf = getThreadCommandBuffer();
u32 saved_threadstorage[4];
u8 tmpaddr[0x1c]; // sockaddr size for the kernel is 0x1C (sockaddr_in6?)
u8 tmpaddr[ADDR_STORAGE_LEN]; // sockaddr size for the kernel is 0x1C (sockaddr_in6?)

if((host == NULL || hostlen == 0) && (serv == NULL || servlen == 0))
{
Expand All @@ -18,7 +18,7 @@ int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_
if(sa->sa_family == AF_INET)
tmp_addrlen = 8;
else
tmp_addrlen = 0x1c;
tmp_addrlen = ADDR_STORAGE_LEN;

if(salen < tmp_addrlen) {
errno = EINVAL;
Expand Down
20 changes: 13 additions & 7 deletions libctru/source/services/soc/soc_getpeername.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,26 @@ int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 saved_threadstorage[2];
u8 tmpaddr[0x1c];
u8 tmpaddr[ADDR_STORAGE_LEN];

sockfd = soc_get_fd(sockfd);
if(sockfd < 0) {
errno = -sockfd;
return -1;
}

memset(tmpaddr, 0, ADDR_STORAGE_LEN);

cmdbuf[0] = IPC_MakeHeader(0x18,2,2); // 0x180082
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = 0x1c;
cmdbuf[2] = ADDR_STORAGE_LEN;
cmdbuf[3] = IPC_Desc_CurProcessId();

u32 * staticbufs = getThreadStaticBuffers();
saved_threadstorage[0] = staticbufs[0];
saved_threadstorage[1] = staticbufs[1];

staticbufs[0] = IPC_Desc_StaticBuffer(0x1c,0);
staticbufs[0] = IPC_Desc_StaticBuffer(ADDR_STORAGE_LEN,0);
staticbufs[1] = (u32)tmpaddr;

ret = svcSendSyncRequest(SOCU_handle);
Expand All @@ -47,11 +49,15 @@ int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
return -1;
}

if(*addrlen > tmpaddr[0])
*addrlen = tmpaddr[0];
memset(addr, 0, sizeof(struct sockaddr));
addr->sa_family = tmpaddr[1];
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);

socklen_t user_addrlen = tmpaddr[0];
if(addr->sa_family == AF_INET)
user_addrlen += 8;

if(*addrlen > user_addrlen)
*addrlen = user_addrlen;
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - sizeof(addr->sa_family));

return ret;
}
20 changes: 13 additions & 7 deletions libctru/source/services/soc/soc_getsockname.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,26 @@ int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 saved_threadstorage[2];
u8 tmpaddr[0x1c];
u8 tmpaddr[ADDR_STORAGE_LEN];

sockfd = soc_get_fd(sockfd);
if(sockfd < 0) {
errno = -sockfd;
return -1;
}

memset(tmpaddr, 0, ADDR_STORAGE_LEN);

cmdbuf[0] = IPC_MakeHeader(0x17,2,2); // 0x170082
cmdbuf[1] = (u32)sockfd;
cmdbuf[2] = 0x1c;
cmdbuf[2] = ADDR_STORAGE_LEN;
cmdbuf[3] = IPC_Desc_CurProcessId();

u32 * staticbufs = getThreadStaticBuffers();
saved_threadstorage[0] = staticbufs[0];
saved_threadstorage[1] = staticbufs[1];

staticbufs[0] = IPC_Desc_StaticBuffer(0x1c,0);
staticbufs[0] = IPC_Desc_StaticBuffer(ADDR_STORAGE_LEN,0);
staticbufs[1] = (u32)tmpaddr;

ret = svcSendSyncRequest(SOCU_handle);
Expand All @@ -47,11 +49,15 @@ int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
return -1;
}

if(*addrlen > tmpaddr[0])
*addrlen = tmpaddr[0];
memset(addr, 0, sizeof(struct sockaddr));
addr->sa_family = tmpaddr[1];
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - 2);

socklen_t user_addrlen = tmpaddr[0];
if(addr->sa_family == AF_INET)
user_addrlen += 8;

if(*addrlen > user_addrlen)
*addrlen = user_addrlen;
memcpy(addr->sa_data, &tmpaddr[2], *addrlen - sizeof(addr->sa_family));

return ret;
}
34 changes: 22 additions & 12 deletions libctru/source/services/soc/soc_recvfrom.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ ssize_t socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockad
int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 tmp_addrlen = 0;
u8 tmpaddr[0x1c];
u8 tmpaddr[ADDR_STORAGE_LEN];
u32 saved_threadstorage[2];

memset(tmpaddr, 0, 0x1c);
memset(tmpaddr, 0, ADDR_STORAGE_LEN);

if(src_addr)
tmp_addrlen = 0x1c;
tmp_addrlen = ADDR_STORAGE_LEN;

cmdbuf[0] = IPC_MakeHeader(0x7,4,4); // 0x70104
cmdbuf[1] = (u32)sockfd;
Expand Down Expand Up @@ -53,9 +53,14 @@ ssize_t socuipc_cmd7(int sockfd, void *buf, size_t len, int flags, struct sockad

if(src_addr != NULL) {
src_addr->sa_family = tmpaddr[1];
if(*addrlen > tmpaddr[0])
*addrlen = tmpaddr[0];
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);

socklen_t user_addrlen = tmpaddr[0];
if(src_addr->sa_family == AF_INET)
user_addrlen += 8;

if(*addrlen > user_addrlen)
*addrlen = user_addrlen;
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - sizeof(src_addr->sa_family));
}

return ret;
Expand All @@ -66,13 +71,13 @@ ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockad
int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 tmp_addrlen = 0;
u8 tmpaddr[0x1c];
u8 tmpaddr[ADDR_STORAGE_LEN];
u32 saved_threadstorage[4];

if(src_addr)
tmp_addrlen = 0x1c;
tmp_addrlen = ADDR_STORAGE_LEN;

memset(tmpaddr, 0, 0x1c);
memset(tmpaddr, 0, ADDR_STORAGE_LEN);

cmdbuf[0] = 0x00080102;
cmdbuf[1] = (u32)sockfd;
Expand Down Expand Up @@ -113,9 +118,14 @@ ssize_t socuipc_cmd8(int sockfd, void *buf, size_t len, int flags, struct sockad

if(src_addr != NULL) {
src_addr->sa_family = tmpaddr[1];
if(*addrlen > tmpaddr[0])
*addrlen = tmpaddr[0];
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - 2);

socklen_t user_addrlen = tmpaddr[0];
if(src_addr->sa_family == AF_INET)
user_addrlen += 8;

if(*addrlen > user_addrlen)
*addrlen = user_addrlen;
memcpy(src_addr->sa_data, &tmpaddr[2], *addrlen - sizeof(src_addr->sa_family));
}

return ret;
Expand Down
12 changes: 6 additions & 6 deletions libctru/source/services/soc/soc_sendto.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ ssize_t socuipc_cmd9(int sockfd, const void *buf, size_t len, int flags, const s
int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 tmp_addrlen = 0;
u8 tmpaddr[0x1c];
u8 tmpaddr[ADDR_STORAGE_LEN];

memset(tmpaddr, 0, 0x1c);
memset(tmpaddr, 0, ADDR_STORAGE_LEN);

if(dest_addr) {
if(dest_addr->sa_family == AF_INET)
tmp_addrlen = 8;
else
tmp_addrlen = 0x1c;
tmp_addrlen = ADDR_STORAGE_LEN;

if(addrlen < tmp_addrlen) {
errno = EINVAL;
Expand Down Expand Up @@ -62,15 +62,15 @@ ssize_t socuipc_cmda(int sockfd, const void *buf, size_t len, int flags, const s
int ret = 0;
u32 *cmdbuf = getThreadCommandBuffer();
u32 tmp_addrlen = 0;
u8 tmpaddr[0x1c];
u8 tmpaddr[ADDR_STORAGE_LEN];

memset(tmpaddr, 0, 0x1c);
memset(tmpaddr, 0, ADDR_STORAGE_LEN);

if(dest_addr) {
if(dest_addr->sa_family == AF_INET)
tmp_addrlen = 8;
else
tmp_addrlen = 0x1c;
tmp_addrlen = ADDR_STORAGE_LEN;

if(addrlen < tmp_addrlen) {
errno = EINVAL;
Expand Down