LWN: Comments on "The trouble with struct sockaddr's fake flexible array" https://lwn.net/Articles/997094/ This is a special feed containing comments posted to the individual LWN article titled "The trouble with struct sockaddr's fake flexible array". en-us Fri, 29 Aug 2025 09:52:35 +0000 Fri, 29 Aug 2025 09:52:35 +0000 https://www.rssboard.org/rss-specification lwn@lwn.net Backwards compatibility at any cost? https://lwn.net/Articles/999329/ https://lwn.net/Articles/999329/ anton <blockquote> How would you do one better? </blockquote> By looking at what Ken Thompson did, i.e. Plan 9. The Berkeley socket API appears totally alien to Unix, and was probably designed to have as little to do with the rest of the kernel as possible. E.g., send() instead of write() and recv() instead of read(); at least that was corrected later, but we still have send() and recv(). Sat, 23 Nov 2024 18:15:06 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/998497/ https://lwn.net/Articles/998497/ smurf <div class="FormattedComment"> Streams are *way* cool when you do them The Right Way.<br> They can also eat your machine's performance for breakfast (and have room left over) when you do them naïvely.<br> <p> </div> Mon, 18 Nov 2024 06:18:38 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/998484/ https://lwn.net/Articles/998484/ smurf <div class="FormattedComment"> <span class="QuotedText">&gt; The IETF is working on a "successor to the sockets API":</span><br> <p> Well. Eight people have written 26 RFC drafts, during the last 6 years, for this one.<br> That's four people, five years, and 20 drafts too many IMHO.<br> Also, the latest of those drafts expired two months ago, but at least it's in Approved state and in the RFC editor queue by now.<br> <p> <span class="QuotedText">&gt; Although who knows who will actually implement it.</span><br> <p> IMHO the comment by Roman Danyliw (see the RFC history) is telling:<br> <p> <span class="QuotedText">&gt; […] I am abstaining on this document because there is a degree of specificity in the abstract API in this document that I cannot reconcile with proposed standard status. […]</span><br> <p> … meaning that it's way not specific enough that, given this RFC, somebody'd be able to write a program that's expected to work with any specific implementation. Thus, more RFCs and system-specific (thus mostly-incompatible) scaffolding will be needed.<br> <p> Thus, again IMHO, this will not replace the Socket API any time soon.<br> </div> Sun, 17 Nov 2024 21:13:38 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/998486/ https://lwn.net/Articles/998486/ Cyberax <div class="FormattedComment"> STREAMS, but different!<br> </div> Sun, 17 Nov 2024 21:05:08 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/998477/ https://lwn.net/Articles/998477/ skissane <div class="FormattedComment"> <span class="QuotedText">&gt; the socket API is not a great by modern standards.</span><br> <p> The IETF is working on a "successor to the sockets API": <a href="https://datatracker.ietf.org/doc/draft-ietf-taps-interface/">https://datatracker.ietf.org/doc/draft-ietf-taps-interface/</a><br> <p> Although who knows who will actually implement it.<br> </div> Sun, 17 Nov 2024 19:35:01 +0000 Interesting problem https://lwn.net/Articles/998475/ https://lwn.net/Articles/998475/ skissane <div class="FormattedComment"> <span class="QuotedText">&gt; the Naval Research Lab's library for dealing with struct sockaddr </span><br> <p> Is that available somewhere still? Would be an interesting bit of history to look at.<br> </div> Sun, 17 Nov 2024 19:24:47 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/998216/ https://lwn.net/Articles/998216/ Cyberax <div class="FormattedComment"> It kinda is...<br> <p> A lot of the sockets API needs to be rewritten. It needs to support Happy Eyeballs, it needs to expose the DNS data explicitly (TXT queries, etc.), it needs to be able to deal with changing/multiple addresses for the bound sockets, etc.<br> </div> Thu, 14 Nov 2024 21:29:44 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/998107/ https://lwn.net/Articles/998107/ smurf <div class="FormattedComment"> The Sockets API isn't the problem. It happens not to embed a sockaddr in anything, much less in the middle of another struct.<br> </div> Thu, 14 Nov 2024 07:01:49 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/998106/ https://lwn.net/Articles/998106/ dvdeug <div class="FormattedComment"> You can always have a BSD sockets API translation layer. It could be constrained to libc, but the kernel would probably support those system calls indefinitely. But that wouldn't stop a new set of system calls and the old system calls being wrappers around the new system calls.<br> </div> Thu, 14 Nov 2024 05:40:49 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997702/ https://lwn.net/Articles/997702/ johill <div class="FormattedComment"> Well, no, as I said - I'm removing that part too now for WiFi7 hardware. There are some technical reasons for that even.<br> <p> As for the question about why it "must" be coupled with changes in the CLI, well ... it doesn't really need to be, but when writing a completely new tool that for the most part has completely new semantics, keeping the CLI intact really isn't the first priority.<br> <p> If you want to submit patches to make 'iw' have a mode where it behaves like iwconfig/iwlist for a subset of functionality, I guess I'd even apply them if they're reasonably well implemented.<br> <p> But you can keep using it for eternity, for all I care, just don't expect new hardware support etc., and then you can just keep using an old kernel version too.<br> </div> Mon, 11 Nov 2024 12:34:26 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997690/ https://lwn.net/Articles/997690/ mb <div class="FormattedComment"> cfg80211 has always included a wireless-extensions API emulation to keep iwconfig and lwlist working.<br> So it's exactly the opposite of what you say: The fundamental API has changed, but the obsolete CLI and its obsolete API have not.<br> So, if almost two decades is not enough for you to adapt to the "new" iw CLI, then you can keep using iwconfig/iwlist.<br> </div> Mon, 11 Nov 2024 10:36:11 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997684/ https://lwn.net/Articles/997684/ Sesse <div class="FormattedComment"> I'd happily switch to iw, except… I really like the output of iwconfig and iwlist? I don't understand why we need to couple API changes with how a CLI works (especially when said CLI moves more towards the needs of low-level expert users).<br> </div> Mon, 11 Nov 2024 09:21:31 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/997672/ https://lwn.net/Articles/997672/ smurf <div class="FormattedComment"> While the Berkeley socket API is in fact not that great by today's standard, it's also not interesting WRT this discussion because it does *not* have sockaddr structs embedded somewhere in the middle of other objects.<br> </div> Sun, 10 Nov 2024 21:35:38 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997673/ https://lwn.net/Articles/997673/ johill <div class="FormattedComment"> A surprisingly large number of tools still use(d) wext, but I'm kicking them out - WiFi7 hardware no longer supports wext in any way. Let's see if I can win that fight ...<br> </div> Sun, 10 Nov 2024 21:32:49 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/997671/ https://lwn.net/Articles/997671/ intelfx <div class="FormattedComment"> <span class="QuotedText">&gt; If we go that way we might just as well deprecate the entire socket API right away and invent an entirely new networking API, because frankly, the socket API is not a great by modern standards. </span><br> <p> How would you do one better? (Architecturally, not just minor C technicalities like the one discussed in the article.)<br> </div> Sun, 10 Nov 2024 21:31:16 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997670/ https://lwn.net/Articles/997670/ smurf <div class="FormattedComment"> Ah, so ioctls for the IPv4 ARP table, legacy routing, and similar stuff that frankly I'd deprecate in a heartbeat. Does anybody (except /sbin/arp AFAICT) still not use netlink for that, these days?<br> <p> Oh well.<br> </div> Sun, 10 Nov 2024 21:18:37 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997667/ https://lwn.net/Articles/997667/ johill <div class="FormattedComment"> Yeah, it's just you? ;-)<br> <p> You can take a look at <a href="https://lore.kernel.org/netdev/cover.1729802213.git.gustavoars@kernel.org/">https://lore.kernel.org/netdev/cover.1729802213.git.gusta...</a> for probably most/all of the APIs affected.<br> </div> Sun, 10 Nov 2024 19:20:49 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/997661/ https://lwn.net/Articles/997661/ lunaryorn <div class="FormattedComment"> If we go that way we might just as well deprecate the entire socket API right away and invent an entirely new networking API, because frankly, the socket API is not a great by modern standards. <br> </div> Sun, 10 Nov 2024 18:33:18 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997649/ https://lwn.net/Articles/997649/ smurf <div class="FormattedComment"> Exactly which API are we talking about here? (Presumably one that doesn't support IPv6 …)<br> <p> I'm not aware of any system call that embeds a sockaddr in some other data structure, but maybe that's just me.<br> </div> Sun, 10 Nov 2024 09:17:29 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997638/ https://lwn.net/Articles/997638/ johill <div class="FormattedComment"> None requires 16 bytes, probably?<br> <p> But for some APIs the address is _embedded_ into other structures (which is what most of the article is about), and changing the size now would change the position of everything that comes after it, breaking the ABI.<br> </div> Sat, 09 Nov 2024 23:15:49 +0000 Interesting problem https://lwn.net/Articles/997614/ https://lwn.net/Articles/997614/ jd <div class="FormattedComment"> The non-existent uptake of the Naval Research Lab's library for dealing with struct sockaddr (IIRC, it provided a portable replacement structure and hid all the fine details) suggests that, at least in the mid 90s, there wasn't much interest in reliable memory handling.<br> <p> It would have required a fair bit of work for legacy code, yes, but you might have expected new code to use it as IPv6 was quite difficult to handle.<br> <p> This suggests that there's a degree of conservatism in programming, a preference for The Old Ways. This is going to complicate efforts to do anything new that is visible.<br> </div> Sat, 09 Nov 2024 13:08:34 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/997600/ https://lwn.net/Articles/997600/ smurf <div class="FormattedComment"> IMHO the only incompatibility is that for addresses smaller than 16 bytes the kernel will no longer zero out the padding when it copies an address to userspace / require the padding to even exist when it reads an address.<br> <p> Everything else should literally stay the same. I have no idea how many programs go splat because their address padding is no longer overwritten but if the number is nonzero then a compatibility mode can be added to the place where the address is copied to userspace. Not spread across the whole of the kernel.<br> </div> Sat, 09 Nov 2024 08:38:00 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997599/ https://lwn.net/Articles/997599/ smurf <div class="FormattedComment"> Exactly which userspace API requires a 16-byte sockaddr? Using that type always requires a socket type. Some addresses are larger than the traditional sockaddr_t (Unix, IPv6, …) some are smaller (IPv4); there's nothing that requires zeroing out the padding in the latter.<br> <p> So why does the kernel really need padded addresses anywhere? Just use / copy however many bytes the address's type requires and be done with it.<br> </div> Sat, 09 Nov 2024 08:33:38 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997567/ https://lwn.net/Articles/997567/ magfr <div class="FormattedComment"> I am actually also curious about why the padding is needed?<br> <p> Would it be confirming if the kernel returned a size of 8 and only filled in the sin_family, sin_port, and sin_addr fields?<br> <p> I suppose the kernel does nothing with the padding as it is today so beeing explicit about it should be ok.<br> <p> It should be noted that posix says sa_data must exist but it says nothing about it's size.<br> <p> Then there is the issue that all the sockaddr_xx types must have the same alignment.<br> <p> What I am going for is if the following is standards conforming:<br> <p> typedef alignas(16) int16_t sa_family_t;<br> struct sockaddr { sa_family_t sa_family; char sa_data[]; };<br> struct sockaddr_in { sa_family_t sin_family; uint16_t sin_port; struct inaddr sin_addr; };<br> <p> with an obvious caveat for what the alignment of sa_family_t should be.<br> <p> In particular this makes sizeof(struct sockaddr) == 2 and sizeof(struct sockaddr_in) == 8 but note that <br> sizeof(struct sockaddr[2]) == 32 due to the alignment.<br> </div> Fri, 08 Nov 2024 21:31:42 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/997564/ https://lwn.net/Articles/997564/ rweikusat2 <div class="FormattedComment"> The chances that people will modify all existing software ever developed for the BSD sockets API just because someone thinks he has a better idea for representing network addresses are - politely put - not very great.<br> <p> :-)<br> </div> Fri, 08 Nov 2024 20:25:44 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/997560/ https://lwn.net/Articles/997560/ jeremyhetzler <div class="FormattedComment"> I would love to read a book about the history of API backward compatibility in OSes, and how we got to where we are today.<br> <p> Because intuitively I see your point, but demonstrably Linux is very *very* committed to the concept. MS maybe less so, but still more than I imagine is convenient for them.<br> </div> Fri, 08 Nov 2024 19:48:08 +0000 minimum size for flexible arrays https://lwn.net/Articles/997454/ https://lwn.net/Articles/997454/ magnus <div class="FormattedComment"> I learned something today! Thanks..<br> </div> Fri, 08 Nov 2024 13:19:40 +0000 minimum size for flexible arrays https://lwn.net/Articles/997446/ https://lwn.net/Articles/997446/ jengelh <div class="FormattedComment"> Common, but not required. It's not the size that is mandated, but the bit width/value range. Think sizeof(long long)=1 with CHAR_BIT=64.<br> </div> Fri, 08 Nov 2024 10:20:31 +0000 Backwards compatibility at any cost? https://lwn.net/Articles/997442/ https://lwn.net/Articles/997442/ taladar <div class="FormattedComment"> Sounds to me like a good example why backwards compatibility should sometimes be broken even if it causes great pain once so we won't be stuck with bad design decisions from literally decades ago forever.<br> </div> Fri, 08 Nov 2024 08:57:50 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997441/ https://lwn.net/Articles/997441/ johill <div class="FormattedComment"> Because ... history. The API to userspace was defined that way (some of it perhaps even back when 14 "was enough for everyone"), so it cannot be changed now.<br> <p> Sure, wireless extensions wouldn't need 14 bytes for a MAC address there, only ever 6. But now it's stuck with 14 and can't use 6, and shouldn't use "14 or variable" either because it's embedded in other types.<br> </div> Fri, 08 Nov 2024 07:58:43 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997438/ https://lwn.net/Articles/997438/ smurf <div class="FormattedComment"> Well. But several addresses are longer anyway, so presumably the called functions restrict themselves to the sa_family-specified length.<br> <p> So why do the short variants need padding up to an arbitrary 14, which happens to not match *any* actual address type's length?<br> </div> Fri, 08 Nov 2024 07:02:33 +0000 minimum size for flexible arrays https://lwn.net/Articles/997437/ https://lwn.net/Articles/997437/ intelfx <div class="FormattedComment"> <span class="QuotedText">&gt; on older archs where short is 2 bytes long</span><br> <p> Isn't short more-or-less always 2 bytes long? (Checked x86-64, aarch64, mips64 and ppc64, what did I miss?)<br> </div> Fri, 08 Nov 2024 06:57:26 +0000 minimum size for flexible arrays https://lwn.net/Articles/997436/ https://lwn.net/Articles/997436/ magnus <div class="FormattedComment"> I guess the data length of 14 in the sockaddr was also chosen to get a nice even size of 16 bytes on older archs where short is 2 bytes long. <br> <p> Beside legacy issues, could it make sense to have a minimum size for flex arrays in some cases, like to know you can always use a bigger access to fetch it or use the first n bytes as a hash or something (provided the unused bytes are always 0)? <br> <p> </div> Fri, 08 Nov 2024 06:23:27 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997431/ https://lwn.net/Articles/997431/ iabervon <div class="FormattedComment"> I was wondering the same thing, so I looked at some of the patches. The answer is that it's an address from a specific family. E.g., your wireless card's MAC address is always a MAC address, not an IPv6 address. However, storing those 6 bytes next to the right 2 bytes and 8 unused bytes allows it to be passed in situ to functions that can take all sorts of addresses, without needing a ton of MAC-address-specific functions or using two function arguments per address in all of the functions.<br> </div> Fri, 08 Nov 2024 03:41:50 +0000 sockaddr used in the kernel? https://lwn.net/Articles/997430/ https://lwn.net/Articles/997430/ clugstj <div class="FormattedComment"> "There are many places in the kernel where struct sockaddr is embedded within another structure"<br> <p> How can this be anything but a bug? It's not big enough for many address formats.<br> </div> Fri, 08 Nov 2024 02:59:27 +0000 sockaddr API design https://lwn.net/Articles/997426/ https://lwn.net/Articles/997426/ wahern <div class="FormattedComment"> <span class="QuotedText">&gt; In fact, we could have limitness AF_UNIX paths already if we did not constrain ourselves to using sockaddr_un (in both userland and kernelspace):</span><br> <p> Some systems, like macOS, do allow providing a path larger than sizeof .sun_path (104 on my laptop). On those systems, when querying an address using getsockname or getpeername, you should check the returned addrlen and try again if it's larger than the provided buffer. Though in the case of macOS the path length isn't limitless, but 252 characters (address structure size of 255, including a trailing NUL character).<br> <p> </div> Fri, 08 Nov 2024 01:37:59 +0000 sockaddr API design https://lwn.net/Articles/997415/ https://lwn.net/Articles/997415/ jengelh <div class="FormattedComment"> <span class="QuotedText">&gt;struct sockaddr_storage [...] is now what is often allocated, but it never appears explicitly in the system-call interface. </span><br> <p> I am surprised no one has mentioned that the sockaddr struct family essentially forms a class hierarchy. Think of it like so:<br> <p> struct sockaddr { sa_family_t family; } struct sockaddr_in6 : public sockaddr { uint16_t port; ... } struct sockaddr_storage : public sockaddr { char moarroom[126]; };<br> <p> And then it's obvious why bind() and connect() take a struct sockaddr. It works with any sockaddr type, and in that sense, userland should have no need to care about the size of sockaddr::sa_data, or that this member even exists. sockaddr::sa_data (as well as sockaddr_storage) may help code reduction, fewer casts, or performance optimizations, but it is not needed conceptually.<br> <p> <span class="QuotedText">&gt;Code dealing with network addresses can allocate a [sockaddr_storage] and be sure of having enough space to store any address</span><br> <p> sockaddrs are inherently variable-length (as evidenced by the length argument to bind/connect/accept), and sockaddr_storage does not fix that. It's just a conveniently-sized buffer for "this operating system's most common sockaddrs at the time of compilation", but it is not completely future-proof.<br> <p> In fact, we could have limitness AF_UNIX paths already if we did not constrain ourselves to using sockaddr_un (in both userland and kernelspace):<br> <p> const char *path = argv[1];<br> socklen_t addrlen = offsetof(struct sockaddr, sa_data) + strlen(path) + 1;<br> char *addr = malloc(addrlen);<br> ((struct sockaddr *)addr)-&gt;sa_family = AF_UNIX;<br> strcpy(&amp;addr[2], argv[1]);<br> int ret = bind(sk, (struct sockaddr *)addr, addrlen);<br> <p> </div> Thu, 07 Nov 2024 23:52:59 +0000 BSD didn't even save a size_t by doing this https://lwn.net/Articles/997411/ https://lwn.net/Articles/997411/ khim <font class="QuotedText">&gt; I think the more plausible explanation is that somebody didn't feel like writing the extra code to initialize the size field.</font> <p>The simple explanation is that was 1983. Time where backward compatibility started becoming <b>important</b> but no one really felt it would become <b>critical</b>.</p> <p>Just five years before that FORTRAN removed some pieces from standard without anyone batting an eye!</p> <p>Surely it's a <b>soft</b>ware, it's malleable, people would just fix it later, when requirements would change?</p> <p>It's only when people started dragging feet with upgrade to FORTRAN 77, when people essentially boycotted MS-DOS 4.0 (in 1988!) because it changed some internal data structures which “programs were not supposed to ever touch”, only when OS/2 completely imploded because someone decided to “improve” Presentation Manager API… only then developers of operation systems realized that keeping ABI stable would make or break them (and even after that moment Linux developers denied the obvious for decades, but that's another thing).</p> <p>I would bet that <b>no one</b> expected to see <code>sockaddr</code>, casually introduced in 1983 just for the “large-scale experiment” (as Vint Cerf attests <code>IPv4</code> was envisioned as large-scale experiment, no one expected it to be used outside of academy and there were expectation that <a href="https://en.wikipedia.org/wiki/OSI_protocols">another thing</a> or <a href="https://en.wikipedia.org/wiki/STREAMS">yet another thing</a> would be used by everyone else) – would still be in use 40 years later and would affect hundreds of <b>billions</b> devices… if they have heard about it they would have assumed you have lost all your marbles.</p> Thu, 07 Nov 2024 20:53:04 +0000 Why oh why …? https://lwn.net/Articles/997409/ https://lwn.net/Articles/997409/ smurf <div class="FormattedComment"> <span class="QuotedText">&gt; places in the kernel where struct sockaddr is embedded within another structure, usually not at the end</span><br> <p> Well since the subtype of "struct sockaddr" that's actually used in these places is not and never was 14+2 bytes long, why was the option to replace these with the sockaddr type that's actually used there not considered?<br> <p> Seems like a no-brainer to me.<br> </div> Thu, 07 Nov 2024 20:19:10 +0000 BSD didn't even save a size_t by doing this https://lwn.net/Articles/997403/ https://lwn.net/Articles/997403/ NYKevin <div class="FormattedComment"> As I read this, it looks like this comes down to a poor design decision in the initial API, namely the choice to use a statically-sized array instead of a dynamic array. It's easy to claim that this would have made sense at the time because it saves a size_t... but that's not actually true:<br> <p> <span class="QuotedText">&gt; The sa_family field describes which address family is in use — AF_INET for an IPv4 address, for example. sa_data holds the actual address, the format of which will vary depending on the family. The implementation notes say that: "the size of the data field, 14 bytes, was selected based on a study of current address formats". In other words, 14 bytes — much longer than the four needed for an IPv4 address — should really be enough for anybody.</span><br> <p> A size_t (or the moral equivalent in pre-standards C) has never been 10+ bytes on any real platform that people have used for serious purposes, with the possible exception of a small handful of natively 128-bit supercomputers. If you're willing to waste 10 bytes in the extremely common case of IPv4, you should be willing to spend 4 bytes on a size_t/long/whatnot (or however many bytes a size_t-ish was in 1983), since that would net out to 6 bytes saved in the case of IPv4. I think the more plausible explanation is that somebody didn't feel like writing the extra code to initialize the size field.<br> <p> (And no, using something other than a size_t due to its lack of standardization would not have caused problems today. Unless there's some weird networking protocol I don't know about that requires addresses bigger than 64K, a 16-bit size field would still be more than adequate even if it would be a bit nonstandard.)<br> </div> Thu, 07 Nov 2024 19:37:11 +0000