]> granicus.if.org Git - python/commitdiff
SF Patch #1062014: AF_UNIX sockets under Linux have a special
authorArmin Rigo <arigo@tunes.org>
Wed, 19 Apr 2006 11:50:27 +0000 (11:50 +0000)
committerArmin Rigo <arigo@tunes.org>
Wed, 19 Apr 2006 11:50:27 +0000 (11:50 +0000)
abstract namespace that is now fully supported.

Lib/test/test_socket.py
Misc/NEWS
Modules/socketmodule.c

index 46468a63c5bac7bc3e622882a91a57f941dace37..6943080a71c00abf9dfb624add3deabcc1e4e5a1 100644 (file)
@@ -825,6 +825,32 @@ class TestExceptions(unittest.TestCase):
         self.assert_(issubclass(socket.gaierror, socket.error))
         self.assert_(issubclass(socket.timeout, socket.error))
 
+class TestLinuxAbstractNamespace(unittest.TestCase):
+
+    UNIX_PATH_MAX = 108
+
+    def testLinuxAbstractNamespace(self):
+        address = "\x00python-test-hello\x00\xff"
+        s1 = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        s1.bind(address)
+        s1.listen(1)
+        s2 = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        s2.connect(s1.getsockname())
+        s1.accept()
+        self.assertEqual(s1.getsockname(), address)
+        self.assertEqual(s2.getpeername(), address)
+
+    def testMaxName(self):
+        address = "\x00" + "h" * (self.UNIX_PATH_MAX - 1)
+        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        s.bind(address)
+        self.assertEqual(s.getsockname(), address)
+
+    def testNameOverflow(self):
+        address = "\x00" + "h" * self.UNIX_PATH_MAX
+        s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+        self.assertRaises(socket.error, s.bind, address)
+
 
 def test_main():
     tests = [GeneralModuleTests, BasicTCPTest, TCPTimeoutTest, TestExceptions]
@@ -840,6 +866,8 @@ def test_main():
     ])
     if hasattr(socket, "socketpair"):
         tests.append(BasicSocketPairTest)
+    if sys.platform == 'linux2':
+        tests.append(TestLinuxAbstractNamespace)
     test_support.run_unittest(*tests)
 
 if __name__ == "__main__":
index 3ccd81b326e3a24be94c24825c4e98f53eaa7905..493c9e4a6a67a0fbc9134f78574efc09ea7ebd4a 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -80,6 +80,9 @@ Extension Modules
 - Bug #1332852: bsddb module minimum BerkeleyDB version raised to 3.3
   as older versions cause excessive test failures.
 
+- Patch #1062014: AF_UNIX sockets under Linux have a special
+  abstract namespace that is now fully supported.
+
 Library
 -------
 
index 93cb8e08840f5fcb60a46858a90d6c3431a76504..c9dd4a3a395490b3bb7f2857d9a2412085bc2bf1 100644 (file)
@@ -968,7 +968,18 @@ makesockaddr(int sockfd, struct sockaddr *addr, int addrlen, int proto)
        case AF_UNIX:
        {
                struct sockaddr_un *a = (struct sockaddr_un *) addr;
-               return PyString_FromString(a->sun_path);
+#ifdef linux
+               if (a->sun_path[0] == 0) {  /* Linux abstract namespace */
+                       addrlen -= (sizeof(*a) - sizeof(a->sun_path));
+                       return PyString_FromStringAndSize(a->sun_path,
+                                                         addrlen);
+               }
+               else
+#endif /* linux */
+               {
+                       /* regular NULL-terminated string */
+                       return PyString_FromString(a->sun_path);
+               }
        }
 #endif /* AF_UNIX */
 
@@ -1098,14 +1109,28 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
                addr = (struct sockaddr_un*)&(s->sock_addr).un;
                if (!PyArg_Parse(args, "t#", &path, &len))
                        return 0;
-               if (len >= sizeof addr->sun_path) {
-                       PyErr_SetString(socket_error,
-                                       "AF_UNIX path too long");
-                       return 0;
+#ifdef linux
+               if (len > 0 && path[0] == 0) {
+                       /* Linux abstract namespace extension */
+                       if (len > sizeof addr->sun_path) {
+                               PyErr_SetString(socket_error,
+                                               "AF_UNIX path too long");
+                               return 0;
+                       }
+               }
+               else
+#endif /* linux */
+                {
+                       /* regular NULL-terminated string */
+                       if (len >= sizeof addr->sun_path) {
+                               PyErr_SetString(socket_error,
+                                               "AF_UNIX path too long");
+                               return 0;
+                       }
+                       addr->sun_path[len] = 0;
                }
                addr->sun_family = s->sock_family;
                memcpy(addr->sun_path, path, len);
-               addr->sun_path[len] = 0;
                *addr_ret = (struct sockaddr *) addr;
 #if defined(PYOS_OS2)
                *len_ret = sizeof(*addr);