Af_netlink

class Socket < IO

enum Family : LibC::SaFamilyT
    UNSPEC = LibC::AF_UNSPEC
    UNIX   = LibC::AF_UNIX
    INET   = LibC::AF_INET
    INET6  = LibC::AF_INET6
end

def initialize(@family, @type, @protocol = Protocol::IP, blocking = false)

This is the list from man page:

       Name                Purpose                          Man page
       AF_UNIX, AF_LOCAL   Local communication              unix(7)
       AF_INET             IPv4 Internet protocols          ip(7)
       AF_INET6            IPv6 Internet protocols          ipv6(7)
       AF_IPX              IPX - Novell protocols
       AF_NETLINK          Kernel user interface device     netlink(7)
       AF_X25              ITU-T X.25 / ISO-8208 protocol   x25(7)
       AF_AX25             Amateur radio AX.25 protocol
       AF_ATMPVC           Access to raw ATM PVCs
       AF_APPLETALK        AppleTalk                        ddp(7)
       AF_PACKET           Low level packet interface       packet(7)
       AF_ALG              Interface to kernel crypto API

My question is: what should I do to achieve the result of this call?

socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) = 3

Is there an easy way to extend the enum with libc values?

Looking at other languages, it seems netlink isn’t provided in the standard library (maybe because it’s only a linux thing?). This is Ruby, This is Go. So my advice is to write a library for this.

However, I think the current Socket code is wrong. These things are not enums in C so they shouldn’t be enums in Crystal, exactly because their values shouldn’t be a fixed set (new types could be added in the future and we don’t want to fix the std to a fixed set).

Could you open an issue for this? And a PR would also be welcome (just turn those enum members into constants). Thank you!

(that way you could write a library and pass any Int32 as the value of @family and you could pass the one for AF_NETLINK without a problem)

Creating a PR would be a bit difficult for me, I never did this before and will have to learn how github works in this regard. I understand that it’s probably a trivial problem for you guys, maybe I will do that sometime in the future.

On a related note, I have another question. Is it possible to use C defines from Crystal? What I mean is do I have to track down the value of AF_NETLINK in header files to determine its int value (it’s 16 I think), or is there a wrapper of any type so that it gets looked up during the build?

Impossible, these aren’t exposed by C libraries, they are C compile-time values.

Maybe it would be possible using clang, but it would have to be run on each compilation… kind of. So for now we just manually copy the values.

Don’t worry about the PR, I might do it later.

1 Like

@asterite how should we proceed with this, it will be probably a compatibility break change.
How could we be solving it, the enums are being used for typing params like family : Family = Family::INET. Should we replace with family : SaFamilyT = INET)?

Yes, I don’t know. I started doing that and stumbled upon the same problem/decision-point. But I’ll do it soon, don’t worry.

1 Like

If it really needs to be hypertyped, how about something like this?

abstract struct Socket::Family
  abstract def value : LibC::SaFamilyT
end

struct Socket::Family::INET < Socket::Family
  def value
    LibC::AF_INET
  end
end