diff --git a/libctru/source/services/soc/soc_accept.c b/libctru/source/services/soc/soc_accept.c index ef8be22..d12be1f 100644 --- a/libctru/source/services/soc/soc_accept.c +++ b/libctru/source/services/soc/soc_accept.c @@ -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) { diff --git a/libctru/source/services/soc/soc_getpeername.c b/libctru/source/services/soc/soc_getpeername.c index 10ed709..d15bade 100644 --- a/libctru/source/services/soc/soc_getpeername.c +++ b/libctru/source/services/soc/soc_getpeername.c @@ -16,6 +16,8 @@ int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen) return -1; } + memset(tmpaddr, 0, ADDR_STORAGE_LEN); + cmdbuf[0] = IPC_MakeHeader(0x18,2,2); // 0x180082 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = ADDR_STORAGE_LEN; @@ -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; } diff --git a/libctru/source/services/soc/soc_getsockname.c b/libctru/source/services/soc/soc_getsockname.c index 87df82a..df75402 100644 --- a/libctru/source/services/soc/soc_getsockname.c +++ b/libctru/source/services/soc/soc_getsockname.c @@ -16,6 +16,8 @@ int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) return -1; } + memset(tmpaddr, 0, ADDR_STORAGE_LEN); + cmdbuf[0] = IPC_MakeHeader(0x17,2,2); // 0x170082 cmdbuf[1] = (u32)sockfd; cmdbuf[2] = ADDR_STORAGE_LEN; @@ -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; } diff --git a/libctru/source/services/soc/soc_recvfrom.c b/libctru/source/services/soc/soc_recvfrom.c index 047a720..eed0422 100644 --- a/libctru/source/services/soc/soc_recvfrom.c +++ b/libctru/source/services/soc/soc_recvfrom.c @@ -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; @@ -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;