To be fair, the recvmsg system call may be older than me
And that's the key. Existing ecosystem, existing ABIs and library interfaces are the real enemy. This is also why we see very few C++ libraries; no standardized ABI, so library calls have to be in C. Unless one writes complete operating systems and libraries from scratch, Rust will face all the same issues; it will have to interact with recvmsg().
Now one could (and has to) write a sane wrapper for recvmsg() in Rust, but on the other hand one could do the wrapper in C as well! If nothing else, replace those void pointers with actual types. If you have more than one possible type, you can use a union to limit the choices in much more sustainable way than casting void pointers to anything.
The problem is, no one has bothered to write those wrappers, or if they have, they are lost in the noise of the Internet. I also hate the fact every project on POSIX starts with writing a wrapper for write() and read() which gives the desired blocking/nonblocking behavior and always return exact count or error. That is what users want. Yet you have to do it yourself every time.
For completely self-contained embedded projects (with no dependencies on libraries at all), one can easily use any language they wish. On the other hand, in such case, one can also write modern and decent C, then, so advantages are smaller as the worst pain points are always in existing libraries and their interfaces, as shown by your recvmsg() example. (I also had a first stack corruption case
in years because I used DNS code written by WIZnet, where they strcpy() a hostname to a fixed 24-length buffer. Go ****ing figure.)