I am trying to bind a ipv6 port to a ipv6 socket. But the port binded is different than the one I specified.
#include <netdb.h>
#include <netinet/tcp.h>
#include <poll.h>
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int unconnected_sock_ =
socket(PF_INET6, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
struct sockaddr_in6 addr = {0};
addr.sin6_family = AF_INET6;
addr.sin6_port = atoi(argv[1]);
addr.sin6_addr = in6addr_any;
if (bind(unconnected_sock_,
(struct sockaddr*)(&addr),
sizeof(addr)) != 0) {
fprintf(stderr, " error : %s\n", strerror(errno));
}
struct sockaddr_in6 sin;
socklen_t len = sizeof(sin);
getsockname(unconnected_sock_, (struct sockaddr *)&sin, &len);
fprintf(stderr, "port number %d\n", ntohs(sin.sin6_port));
}
output:
ubun - main: ~/socket.exe 54682
port number 39637
CodePudding user response:
Please note that 54682 is 0xd59a, while 39637 is 0x9ad5. This is the same value, but written in different byte orders.
From man ipv6
:
sin6_port is the protocol port (see sin_port in ip(7));
From man 7 ip
:
sin_port contains the port in network byte order.
In the line that prints the port that is bind to the socket, you convert the network byte order to the local one:
fprintf(stderr, "port number %d\n", ntohs(sin.sin6_port));
In the line, that sets the requested port number, you are not converting the byte order from native to the network one:
addr.sin6_port = atoi(argv[1]);
To get expected behavior you should amend it to:
addr.sin6_port = htons(atoi(argv[1]));