On Thu, Feb 15, 2007 at 01:41:26PM +0900, Yukihiro Matsumoto wrote:
> I need more info to merge this in.  What should NUL in sun_path should
> behave?  Is that in any spec?

- Spec is just unix(7) on linux, I guess:

  http://www.cl.cam.ac.uk/cgi-bin/manpage?7+unix

- If you semi-manually pack the sockaddr, you can use abstract sockets
  on linux right now with ruby:

  ruby -r socket -e 's = Socket.new(Socket::AF_UNIX, Socket::SOCK_STREAM, 0); a = Socket.sockaddr_un("@@"); a.sub!(/@@\0+/,"\0/dbus/hello!\0"); s.bind(a); p s.getsockname'
  "\001\000\000/dbus/hello!\000"

  So original reporter has a workaround.

> What should NUL in sun_path should behave?

Maybe it is not our problem. Socket provides the pack methods, the
programmer packs her address, the kernel interprets the address, and
whatever happens, happens. On a system other than linux, I assume that
bind would fail, on linux, you get an abstract unix socket, whatever
that means.

ruby doesn't need to support linux specific socket names more than it
already does, but I really like that ruby's Socket methods impose as few
restrictions as possible.  I think the effort that pack/unpack goes
through to error-check paths for UNIX domain sockets is unnecessarily
limiting, I would suggest:

- pack accepted any path string ("\0aa\0bb\0\0", even), and returned a
  sockaddr_un with no more than 1 trailing NUL in the sun_path
  ("\1\0\0aa\0bb\0", for the above on my system).

- unpack checks the address family is AF_UNIX, and returned the sun_path
  with all trailing NULs removed, "\0aa\0bb" for above example.

- UNIXServer and UNIXSocket continue to fail if path is not a valid
  C-string. If you want system-specific functionality, you must use the
  low-level methods.


Also, I notice:

- There is a spelling error in unix_peeraddr(), it raises a string with
  getsockname() in it:

  ruby -r socket -e 's=UNIXServer.new("/tmp/u"); p s.peeraddr'   
  -e:1:in `peeraddr': Transport endpoint is not connected - getsockname(2) (Errno::ENOTCONN)

- sock_s_unpack_sockaddr_[un/in]() don't check input string is at least
  sizeof(sockaddr) before accessing struct sockaddr.sa_family, so will
  over-read memory on invalid input, it seems.

- sockadd_un() always returns a large NUL-padded string, its not
  necessary, sockaddr_un returned by the kernel don't return more than
  one terminating NUL.

I can post patches for any of these changes, seperate or together, as
you wish.

Cheers,
Sam