#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;arpa/inet.h&gt;
#include &lt;errno.h&gt;
#include &#34;sys/socket.h&#34;
#include &lt;string.h&gt;

/**
 * Creates and returns socket of AF_INET6 domain and SOCK_DGRAM type
 * @return
 */
int create_inet6_dgram_socket();

/**
 * Binds the passed socket file descriptor to a IPv4-mapped IPv6 address, representing
 * the loopback address (::ffff:127.0.0.1) and port 0.
 * @param socket_desc socket file descriptor
 * @return Returns the bound address with the port resolved to the bound address&#39;s port
 */
struct sockaddr_in6 bind_to_loopback(int socket_desc);

/**
 * Creates and returns a socket address with the address representing an IPv4-mapped IPv6 address for the loopback address
 * (::ffff:127.0.0.1) and the port corresponding to the passed port
 * @param port The port
 * @return
 */
struct sockaddr_in6 create_ipv6_ipv4_mapped_loopback_sockaddr(int port);

/**
 * Prints the inet address, port and the family, represented by the passed socket address
 * @param msg_prefix The prefix for the message that gets printed
 * @param sa6
 */
void print_addr(const char *msg_prefix, struct sockaddr_in6 sa6);

int main() {
    int s1 = create_inet6_dgram_socket();
    printf(&#34;created a socket, descriptor=%d\n&#34;, s1);
    struct sockaddr_in6 bound_addr = bind_to_loopback(s1);
    // create another datagram socket
    int s2 = create_inet6_dgram_socket();
    printf(&#34;created another socket, descriptor=%d\n&#34;, s2);
    // connect s2 to s1
    print_addr(&#34;connecting to &#34;, bound_addr);
    int rv = connect(s2, (struct sockaddr *) &amp;bound_addr, sizeof(struct sockaddr_in6));
    if (rv != 0) {
        printf(&#34;Error no %d\n&#34;, errno);
        perror(&#34;Socket connect failed&#34;);
        exit(EXIT_FAILURE);
    }
    printf(&#34;successfully connected\n&#34;);
    // now disconnect the connected datagram socket, by calling connect and passing it
    // all &#34;zeroed&#34; instance of sockaddr_in6 (which is called a null address and is allowed as per the &#34;man connect&#34;
    // for disconnecting)
    struct sockaddr_in6 null_addr;
    memset(&amp;null_addr, 0, sizeof(struct sockaddr_in6));
    null_addr.sin6_family = AF_INET6;
    print_addr(&#34;Disconnecting using addr &#34;, null_addr);
    rv = connect(s2, (const struct sockaddr *) &amp;null_addr, sizeof(struct sockaddr_in6));
    if (rv &lt; 0) {
        // EADDRNOTAVAIL is OK
        if (errno == EADDRNOTAVAIL) {
            printf(&#34;got errno %d, which is considered OK for a connect to null address (a.k.a disconnect)\n&#34;, errno);
            // this is a successful disconnect
            rv = errno = 0;
        } else {
            printf(&#34;Got unexpected errno %d\n&#34;, errno);
            perror(&#34;disconnect failed&#34;);
            exit(EXIT_FAILURE);
        }
    }
    printf(&#34;Successfully disconnected\n&#34;);
    return 0;
}

int create_inet6_dgram_socket() {
    int s = socket(AF_INET6, SOCK_DGRAM, 0);
    if (s &lt; 0) {
        perror(&#34;Socket creation failed&#34;);
        exit(EXIT_FAILURE);
    }
    return s;
}

struct sockaddr_in6 bind_to_loopback(int socket_desc) {
    struct sockaddr_in6 sa6 = create_ipv6_ipv4_mapped_loopback_sockaddr(0);
    print_addr(&#34;trying to bind to addr &#34;, sa6);
    // bind to loopback
    int rv = bind(socket_desc, (const struct sockaddr *) &amp;sa6, sizeof(struct sockaddr_in6));
    if (rv != 0) {
        perror(&#34;Failed to bind&#34;);
        exit(EXIT_FAILURE);
    }
    // get the bound address
    socklen_t len = sizeof(struct sockaddr_in6);
    struct sockaddr_in6 bound_addr;
    rv = getsockname(socket_desc, (struct sockaddr *) &amp;bound_addr, &amp;len);
    if (rv != 0) {
        perror(&#34;Failed to get bound address&#34;);
        exit(EXIT_FAILURE);
    }
    print_addr(&#34;Bound socket to &#34;, bound_addr);
    sa6.sin6_port = bound_addr.sin6_port;
    return sa6;
}

struct sockaddr_in6 create_ipv6_ipv4_mapped_loopback_sockaddr(int port) {
    struct sockaddr_in6 sa6;
    memset((char *) &amp;sa6, 0, sizeof(struct sockaddr_in6));
    // convert to IPv4-mapped address
    signed char loopback_addr[16];
    memset((signed char *) loopback_addr, 0, 16);
    loopback_addr[10] = -1; // 0xff
    loopback_addr[11] = -1; // 0xff
    loopback_addr[12] = 127;
    loopback_addr[13] = 0;
    loopback_addr[14] = 0;
    loopback_addr[15] = 1;
    memcpy((void *) &amp;sa6.sin6_addr, loopback_addr, sizeof(struct in6_addr));
    sa6.sin6_port = htons(port);
    sa6.sin6_family = AF_INET6;
    return sa6;
}

void print_addr(const char *msg_prefix, struct sockaddr_in6 sa6) {
    char addr_text[INET6_ADDRSTRLEN] = {0};
    printf(&#34;%s%s:%d, addr family=%u\n&#34;,
           msg_prefix,
           inet_ntop(AF_INET6, &amp;sa6.sin6_addr, (char *) &amp;addr_text, INET6_ADDRSTRLEN),
           sa6.sin6_port,
           sa6.sin6_family);
}