Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Your <code>print_socket_info</code> function is wrong. If takes a <code>struct sockaddr_in *</code> (IPv4 socket address structure) but it's meant to support both IPv4 and IPv6.</p> <p>You must declare <code>print socket_info</code> to take a generic <code>struct sockaddr *</code> (socket address of any type). For good measure: rename the <code>sin</code> argument to <code>sa</code> to indicate that it's of the generic type, not <code>struct sockaddr_in</code> type. Then, inside the function, you check <code>sin-&gt;sin_family</code> to find out what the actual family is and continue by casting <code>sin</code> to either a <code>struct sockaddr_in *</code> or <code>struct sockaddr_in6</code> as appropriate.</p> <p>What's happening in your existing function is that you're just treating it as a <code>struct sockaddr_in *</code> throughout the whole function with the following results (at least on Linux):</p> <ul> <li>Checking <code>sin_family</code> is OK because the family is guaranteed to be at the same offset into the structure for all types of sockaddrs, whether it is <code>struct sockaddr_in</code> or <code>struct sockaddr_in6</code> or even <code>struct sockaddr_un</code> for UNIX domain sockets or the sockaddr structures for all the other obscure address families too.</li> <li>You are lucky to get away with it when checking <code>sin_port</code> because <code>sin_port</code> in <code>struct sockaddr_in</code> happens to lie at the same offset in the structure as <code>sin6_port</code> in <code>struct sockaddr_in6</code>.</li> <li>If doesn't work for <code>sin_addr</code> because for IPv4, <code>sin_addr</code> comes right after <code>sin_port</code> in the structure, but for IPv6, some other field is found at that location (namely, <code>sin6_flowinfo</code>). <code>sin6_addr</code> is somewhere else.</li> </ul> <p>Another thing that's wrong with <code>print_socket_info</code> is that your string buffer only has enough space for an IPv4 address string because it is declared with length <code>INET_ADDRSTRLEN</code> which is too short for IPv6 (for IPv6 you need <code>INET6_ADDRSTRLEN</code>. And the function does not need to take a parameter <code>protocol</code>. This information is already embedded in the sockaddr.</p> <pre><code>int print_socket_info(int sock_fd, struct sockaddr *sa){ char dbg[INET6_ADDRSTRLEN]; /* the larger of the two sizes */ char *famstr; unsigned short port; switch (sa-&gt;sa_family): case AF_INET4: inet_ntop(AF_INET4, &amp;(((struct sockaddr_in *)sa)-&gt;sin_addr), dbg, sizeof(dbg)); port = ((struct sockaddr_in *)sa)-&gt;sin_port; break; case AF_INET6: inet_ntop(AF_INET6, &amp;(((struct sockaddr_in6 *)sa)-&gt;sin6_addr), dbg, sizeof(dbg)); port = ((struct sockaddr_in6 *)sa)-&gt;sin6_port; break; default: strcpy(dst, "UNKNOWN"); port = 0; } printf("============ SOCKET INFORMATION =============\n"); printf("!** socket: %d\n", sock_fd); printf("!** info-&gt;ai_addr: sockaddr_in(\n"); famstr = fam2str(sa-&gt;sa_family); printf("!** sa_family: %s\n", famstr); printf("!** sin[6]_port: %d\n", ntohs(port)); printf("!** sin[6]_addr: in_addr( s_addr : '%s' )\n", dbg); printf("!**)\n"); printf("=============================================\n"); return 1; } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload