--- Python-2.7.9/Doc/library/socket.rst 2015/03/30 16:16:05 1.1 +++ Python-2.7.9/Doc/library/socket.rst 2015/03/30 16:23:35 @@ -83,10 +83,23 @@ is the lower port number, and *v3* is the upper port number. If *addr_type* is :const:`TIPC_ADDR_ID`, then *v1* is the node, *v2* is the reference, and *v3* should be set to 0. +.. versionadded:: 2.7 + Linux-only support for IUCV is also available using the :const:`AF_IUCV` + address family on s390x. IUCV is a non-IP based network protocol designed + for virtual-machine to virtual-machine communication. Addresses are represented + by a tuple. The form of the tuple is + ``(node, userid, name)``, where: + + - *node* is the name of the z/VM system upon which the partner is running. Currenty, + this is ignored and only intra-z/VM communication is supported by the kernel. + - *userid* is the name of the virtual machine to communicate with. If left as blanks, + then it defaults to the virtual machine in which the program is running. + - *name* is the name of the application end point running within the virtual machine. + Multiple applications may be running and using `AF_IUCV`. All errors raise exceptions. The normal exceptions for invalid argument types and out-of-memory conditions can be raised; errors related to socket or address semantics raise the error :exc:`socket.error`. --- Python-2.7.9/Modules/socketmodule.c 2015/03/30 15:27:53 1.1 +++ Python-2.7.9/Modules/socketmodule.c 2015/04/01 19:16:42 @@ -5,12 +5,12 @@ This module provides an interface to Berkeley socket IPC. Limitations: - Only AF_INET, AF_INET6 and AF_UNIX address families are supported in a - portable manner, though AF_PACKET, AF_NETLINK and AF_TIPC are supported - under Linux. + portable manner, though AF_PACKET, AF_NETLINK, AF_TIPC, and AF_IUCV are + supported under Linux. - No read/write operations (use sendall/recv or makefile instead). - Additional restrictions apply on some non-Unix platforms (compensated for by socket.py). Module interface: @@ -69,11 +69,15 @@ v3 is the upper port number if addr_type is TIPC_ADDR_ID: v1 is the node v2 is the ref v3 is ignored - +- an AF_IUCV address is expressed as + (node, user, name) + - node: Name of z/VM system (default NULL) [1-8 char] + - user: User ID to connect to on that node [1-8 char] + - name: : Name of application end point running within user [1-8 char] Local naming conventions: - names starting with sock_ are socket object methods - names starting with socket_ are module-level functions @@ -259,10 +263,14 @@ /* Generic socket object definitions and includes */ #define PySocket_BUILDING_SOCKET #include "socketmodule.h" +#ifdef AF_IUCV +#include +#endif + /* Addressing includes */ #ifndef MS_WINDOWS /* Non-MS WINDOWS includes */ @@ -952,10 +960,21 @@ PyErr_SetString(socket_error, "unknown address family"); return -1; } } +#ifdef AF_IUCV +/* Support routine to strip trailing blanks for a string */ +static __inline__ void +strip(char *var, size_t lVar) +{ + int i; + + for (i = lVar - 2; (isspace(var[i]) && (i >= 0)); i--); + var[++i] = 0; +} +#endif /* Create a string object representing an IP address. This is always a string of the form 'dd.dd.dd.dd' (with variable size numbers). */ @@ -1213,10 +1232,28 @@ return NULL; } } #endif +#ifdef AF_IUCV + case AF_IUCV : + { + struct sockaddr_iucv *a = (struct sockaddr_iucv *) addr; + char node[9], user[9], name[9]; + + node[8] = user[8] = name[8] = 0; + memcpy(node, a->siucv_nodeid, sizeof(a->siucv_nodeid)); + memcpy(user, a->siucv_user_id, sizeof(a->siucv_user_id)); + memcpy(name, a->siucv_name, sizeof(a->siucv_name)); + strip(node, sizeof(node)); + strip(user, sizeof(user)); + strip(name, sizeof(name)); + + return Py_BuildValue("sss", &node, &user, &name); + } +#endif + /* More cases here... */ default: /* If we don't know the address family, don't raise an exception -- return it as a tuple. */ @@ -1587,10 +1624,73 @@ return 1; } #endif +#ifdef AF_IUCV + case AF_IUCV: + { + char *node, *user, *name; + Py_ssize_t lNode, lUser, lName; + struct sockaddr_iucv *addr; + + if (!PyTuple_Check(args)) { + PyErr_Format( + PyExc_TypeError, + "getsockaddrarg: " + "AF_IUCV address must be tuple, not %.500s", + Py_TYPE(args)->tp_name); + return 0; + } + + if (!PyArg_ParseTuple(args, "s#s#s#", + &node, &lNode, + &user, &lUser, + &name, &lName)) + return 0; + + if (lNode > 8) { + PyErr_SetString(socket_error, "Node name > 8 characters"); + return 0; + } + if (lUser > 8) { + PyErr_SetString(socket_error, "Virtual machine name > 8 characters"); + return 0; + } + if (lName > 8) { + PyErr_SetString(socket_error, "Application name > 8 characters"); + return 0; + } + + addr = (struct sockaddr_iucv *) addr_ret; + memset(addr, 0, sizeof(struct sockaddr_iucv)); + lNode = MIN(lNode, sizeof(addr->siucv_nodeid)); + lUser = MIN(lUser, sizeof(addr->siucv_user_id)); + lName = MIN(lName, sizeof(addr->siucv_name)); + + addr->siucv_family = AF_IUCV; + memset(addr->siucv_nodeid, ' ', sizeof(addr->siucv_nodeid)); + memset(addr->siucv_user_id, ' ', sizeof(addr->siucv_user_id)); + memset(addr->siucv_name, ' ', sizeof(addr->siucv_name)); + memcpy(addr->siucv_nodeid, node, lNode); + memcpy(addr->siucv_user_id, user, lUser); + memcpy(addr->siucv_name, name, lName); + if (addr->siucv_user_id[0] == ' ') { + PyErr_SetString(socket_error, "Missing z/VM user name"); + return 0; + } + if (addr->siucv_name[0] == ' ') { + PyErr_SetString(socket_error, "Missing application name"); + return 0; + } + + *len_ret = sizeof(*addr); + + return 1; + } +#endif + /* More cases here... */ default: PyErr_SetString(socket_error, "getsockaddrarg: bad family"); return 0; @@ -1680,10 +1780,18 @@ *len_ret = sizeof (struct sockaddr_tipc); return 1; } #endif +#ifdef AF_IUCV + case AF_IUCV: + { + *len_ret = sizeof (struct sockaddr_iucv); + return 1; + } +#endif + /* More cases here... */ default: PyErr_SetString(socket_error, "getsockaddrlen: bad family"); return 0; @@ -4817,10 +4925,14 @@ #endif #ifdef PACKET_FASTROUTE PyModule_AddIntMacro(m, PACKET_FASTROUTE); #endif +#ifdef AF_IUCV + PyModule_AddIntConstant(m, "AF_IUCV", AF_IUCV); +#endif + #ifdef HAVE_LINUX_TIPC_H PyModule_AddIntConstant(m, "AF_TIPC", AF_TIPC); /* for addresses */ PyModule_AddIntConstant(m, "TIPC_ADDR_NAMESEQ", TIPC_ADDR_NAMESEQ); --- Python-2.7.9/Lib/test/test_socket.py 2015/03/30 16:04:52 1.1 +++ Python-2.7.9/Lib/test/test_socket.py 2015/04/01 19:01:20 @@ -1773,10 +1773,71 @@ def _testStream(self): self.cli.send(MSG) self.cli.close() +def isIUCVAvailable(): + """Check if this platform supports IUCV + + """ + if not hasattr(socket, "AF_IUCV"): + return False + if not os.path.isfile("/proc/modules"): + return False + with open("/proc/modules") as f: + for line in f: + if line.startswith("af_iucv "): + return True + return False + +def getIUCVTarget(): + """Extract my z/VM user id from /proc/sysinfo + + """ + with open("/proc/sysinfo") as f: + for line in f: + if line.startswith("VM00 Name:"): + return line[22:].strip() + +@unittest.skipUnless(isIUCVAvailable(), + "Platform does not support AF_IUCV - ignoring") +class IUCVThreadableTest(unittest.TestCase, ThreadableTest): + def __init__(self, methodName = 'runTest'): + unittest.TestCase.__init__(self, methodName = methodName) + ThreadableTest.__init__(self) + + def setUp(self): + self.srv = socket.socket(socket.AF_IUCV, socket.SOCK_STREAM) + self.srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + userid = getIUCVTarget() + srvaddr = ("", userid, "SELF") + self.srv.bind(srvaddr) + self.srv.listen(5) + self.serverExplicitReady() + self.conn, self.connaddr = self.srv.accept() + + def clientSetUp(self): + # The is a hittable race between serverExplicitReady() and the + # accept() call; sleep a little while to avoid it, otherwise + # we could get an exception + time.sleep(0.1) + self.cli = socket.socket(socket.AF_IUCV, socket.SOCK_STREAM) + userid = getIUCVTarget() + addr = ("", userid, "SELF") + self.cli.connect(addr) + self.cliaddr = self.cli.getsockname() + + def testStream(self): + msg = self.conn.recv(1024) + self.assertEqual(msg, MSG) + self.assertEqual(self.cliaddr, self.connaddr) + + def _testStream(self): + self.cli.send(MSG) + self.cli.close() + + def test_main(): tests = [GeneralModuleTests, BasicTCPTest, TCPCloserTest, TCPTimeoutTest, TestExceptions, BufferIOTest, BasicTCPTest2, BasicUDPTest, UDPTimeoutTest ] @@ -1793,10 +1854,11 @@ NetworkConnectionBehaviourTest, ]) tests.append(BasicSocketPairTest) tests.append(TestLinuxAbstractNamespace) tests.extend([TIPCTest, TIPCThreadableTest]) + tests.extend([IUCVThreadableTest]) thread_info = test_support.threading_setup() test_support.run_unittest(*tests) test_support.threading_cleanup(*thread_info) --- Python-2.7.9/Lib/plat-linux2/IN.py 2015/03/30 15:24:46 1.1 +++ Python-2.7.9/Lib/plat-linux2/IN.py 2015/03/30 15:25:36 @@ -383,11 +383,12 @@ PF_SNA = 22 PF_IRDA = 23 PF_PPPOX = 24 PF_WANPIPE = 25 PF_BLUETOOTH = 31 -PF_MAX = 32 +PF_IUCV = 32 +PF_MAX = 33 AF_UNSPEC = PF_UNSPEC AF_LOCAL = PF_LOCAL AF_UNIX = PF_UNIX AF_FILE = PF_FILE AF_INET = PF_INET @@ -413,10 +414,11 @@ AF_SNA = PF_SNA AF_IRDA = PF_IRDA AF_PPPOX = PF_PPPOX AF_WANPIPE = PF_WANPIPE AF_BLUETOOTH = PF_BLUETOOTH +AF_IUCV = PF_IUCV AF_MAX = PF_MAX SOL_RAW = 255 SOL_DECNET = 261 SOL_X25 = 262 SOL_PACKET = 263