ruby-changes:10573
From: akr <ko1@a...>
Date: Sun, 8 Feb 2009 21:56:04 +0900 (JST)
Subject: [ruby-changes:10573] Ruby:r22129 (trunk): * ext/socket/extconf.rb: check struct cmsgcred.
akr 2009-02-08 21:53:55 +0900 (Sun, 08 Feb 2009) New Revision: 22129 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=22129 Log: * ext/socket/extconf.rb: check struct cmsgcred. * ext/socket/ancdata.c (anc_inspect_passcred_credentials): add "(ucred)". (anc_inspect_socket_creds): show struct cmsgcred too, for FreeBSD. Modified files: trunk/ChangeLog trunk/ext/socket/ancdata.c trunk/ext/socket/extconf.rb trunk/test/socket/test_unix.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 22128) +++ ChangeLog (revision 22129) @@ -1,3 +1,11 @@ +Sun Feb 8 21:47:50 2009 Tanaka Akira <akr@f...> + + * ext/socket/extconf.rb: check struct cmsgcred. + + * ext/socket/ancdata.c (anc_inspect_passcred_credentials): add + "(ucred)". + (anc_inspect_socket_creds): show struct cmsgcred too, for FreeBSD. + Sun Feb 8 21:05:35 2009 Tanaka Akira <akr@f...> * lib/drb/extservm.rb (DRb::ExtServManager#invoke_service_command): Index: ext/socket/extconf.rb =================================================================== --- ext/socket/extconf.rb (revision 22128) +++ ext/socket/extconf.rb (revision 22129) @@ -309,6 +309,7 @@ } have_type("struct sockcred", headers) +have_type("struct cmsgcred", headers) $distcleanfiles << "constants.h" << "constdefs.*" Index: ext/socket/ancdata.c =================================================================== --- ext/socket/ancdata.c (revision 22128) +++ ext/socket/ancdata.c (revision 22129) @@ -385,6 +385,7 @@ struct ucred cred; memcpy(&cred, RSTRING_PTR(data), sizeof(struct ucred)); rb_str_catf(ret, " pid=%u uid=%u gid=%u", cred.pid, cred.uid, cred.gid); + rb_str_cat2(ret, " (ucred)"); return 0; } else { @@ -393,38 +394,71 @@ } #endif -#if defined(SCM_CREDS) && defined(HAVE_TYPE_STRUCT_SOCKCRED) /* NetBSD */ +#if defined(SCM_CREDS) #define INSPECT_SCM_CREDS static int anc_inspect_socket_creds(int level, int type, VALUE data, VALUE ret) { int i; - if (level == SOL_SOCKET && type == SCM_CREDS && - RSTRING_LEN(data) >= SOCKCREDSIZE(0)) { - struct sockcred cred0, *cred; - memcpy(&cred0, RSTRING_PTR(data), SOCKCREDSIZE(0)); - if (RSTRING_LEN(data) != SOCKCREDSIZE(cred0.sc_ngroups)) { - return -1; - } - cred = (struct sockcred *)ALLOCA_N(char, SOCKCREDSIZE(cred0.sc_ngroups)); - memcpy(cred, RSTRING_PTR(data), SOCKCREDSIZE(cred0.sc_ngroups)); - rb_str_catf(ret, " uid=%u", cred->sc_uid); - rb_str_catf(ret, " euid=%u", cred->sc_euid); - rb_str_catf(ret, " gid=%u", cred->sc_gid); - rb_str_catf(ret, " egid=%u", cred->sc_egid); - if (cred0.sc_ngroups) { + if (level != SOL_SOCKET && type != SCM_CREDS) + return -1; + + /* + * FreeBSD has struct cmsgcred and struct sockcred. + * They use both SOL_SOCKET/SCM_CREDS in the ancillary message. + * They are not ambiguous from the view of the caller + * because struct sockcred is sent if and only if the caller sets LOCAL_CREDS socket option. + * But inspect method doesn't know it. + * So they are ambiguous from the view of inspect. + * This function distinguish them by the size of the ancillary message. + * This heuristics works well except when sc_ngroups == CMGROUP_MAX. + */ + +#if defined(HAVE_TYPE_STRUCT_CMSGCRED) /* FreeBSD */ + if (RSTRING_LEN(data) == sizeof(struct cmsgcred)) { + struct cmsgcred cred; + memcpy(&cred, RSTRING_PTR(data), sizeof(struct cmsgcred)); + rb_str_catf(ret, " pid=%u", cred.cmcred_pid); + rb_str_catf(ret, " uid=%u", cred.cmcred_uid); + rb_str_catf(ret, " euid=%u", cred.cmcred_euid); + rb_str_catf(ret, " gid=%u", cred.cmcred_gid); + if (cred.cmcred_ngroups) { char *sep = "="; rb_str_cat2(ret, " groups"); - for (i = 0; i < cred0.sc_ngroups; i++) { - rb_str_catf(ret, "%s%u", sep, cred->sc_groups[i]); + for (i = 0; i < cred.cmcred_ngroups; i++) { + rb_str_catf(ret, "%s%u", sep, cred.cmcred_groups[i]); sep = ","; } } + rb_str_cat2(ret, " (cmsgcred)"); return 0; } - else { - return -1; +#endif +#if defined(HAVE_TYPE_STRUCT_SOCKCRED) /* FreeBSD, NetBSD */ + if (RSTRING_LEN(data) >= SOCKCREDSIZE(0)) { + struct sockcred cred0, *cred; + memcpy(&cred0, RSTRING_PTR(data), SOCKCREDSIZE(0)); + if (RSTRING_LEN(data) == SOCKCREDSIZE(cred0.sc_ngroups)) { + cred = (struct sockcred *)ALLOCA_N(char, SOCKCREDSIZE(cred0.sc_ngroups)); + memcpy(cred, RSTRING_PTR(data), SOCKCREDSIZE(cred0.sc_ngroups)); + rb_str_catf(ret, " uid=%u", cred->sc_uid); + rb_str_catf(ret, " euid=%u", cred->sc_euid); + rb_str_catf(ret, " gid=%u", cred->sc_gid); + rb_str_catf(ret, " egid=%u", cred->sc_egid); + if (cred0.sc_ngroups) { + char *sep = "="; + rb_str_cat2(ret, " groups"); + for (i = 0; i < cred0.sc_ngroups; i++) { + rb_str_catf(ret, "%s%u", sep, cred->sc_groups[i]); + sep = ","; + } + } + rb_str_cat2(ret, " (sockcred)"); + return 0; + } } +#endif + return -1; } #endif Index: test/socket/test_unix.rb =================================================================== --- test/socket/test_unix.rb (revision 22128) +++ test/socket/test_unix.rb (revision 22129) @@ -296,7 +296,7 @@ } end - def test_cred_linux + def test_cred_ucred return if /linux/ !~ RUBY_PLATFORM Dir.mktmpdir {|d| sockpath = "#{d}/sock" @@ -306,15 +306,17 @@ s.setsockopt(:SOCKET, :PASSCRED, 1) c.print "a" msg, cliend_ai, rflags, cred = s.recvmsg + inspect = cred.inspect assert_equal("a", msg) - assert_match(/ pid=#{$$} /, cred.inspect) - assert_match(/ uid=#{Process.uid} /, cred.inspect) - assert_match(/ gid=#{Process.gid}>/, cred.inspect) + assert_match(/ pid=#{$$} /, inspect) + assert_match(/ uid=#{Process.uid} /, inspect) + assert_match(/ gid=#{Process.gid}>/, inspect) + assert_match(/ \(ucred\)/, inspect) } end - def test_cred_netbsd - return if /netbsd/ !~ RUBY_PLATFORM + def test_cred_sockcred + return if /netbsd|freebsd/ !~ RUBY_PLATFORM Dir.mktmpdir {|d| sockpath = "#{d}/sock" serv = Socket.unix_server_socket(sockpath) @@ -324,11 +326,34 @@ c.print "a" msg, cliend_ai, rflags, cred = s.recvmsg assert_equal("a", msg) - assert_match(/ uid=#{Process.uid} /, cred.inspect) - assert_match(/ euid=#{Process.euid} /, cred.inspect) - assert_match(/ gid=#{Process.gid} /, cred.inspect) - assert_match(/ egid=#{Process.egid} /, cred.inspect) + inspect = cred.inspect + p inspect + assert_match(/ uid=#{Process.uid} /, inspect) + assert_match(/ euid=#{Process.euid} /, inspect) + assert_match(/ gid=#{Process.gid} /, inspect) + assert_match(/ egid=#{Process.egid} /, inspect) + assert_match(/ \(sockcred\)/, inspect) } end + def test_cred_cmsgcred + return if /freebsd/ !~ RUBY_PLATFORM + Dir.mktmpdir {|d| + sockpath = "#{d}/sock" + serv = Socket.unix_server_socket(sockpath) + c = Socket.unix(sockpath) + s, = serv.accept + c.sendmsg("a", 0, nil, [:SOCKET, Socket::SCM_CREDS, ""]) + msg, cliend_ai, rflags, cred = s.recvmsg + assert_equal("a", msg) + inspect = cred.inspect + p inspect + assert_match(/ pid=#{$$} /, inspect) + assert_match(/ uid=#{Process.uid} /, inspect) + assert_match(/ euid=#{Process.euid} /, inspect) + assert_match(/ gid=#{Process.gid} /, inspect) + assert_match(/ \(cmsgcred\)/, inspect) + } + end + end if defined?(UNIXSocket) && /cygwin/ !~ RUBY_PLATFORM -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/