From patchwork Fri Jun 13 10:48:23 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kinglong Mee X-Patchwork-Id: 4348521 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id BBC8ABEEAA for ; Fri, 13 Jun 2014 10:48:40 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A5FA920263 for ; Fri, 13 Jun 2014 10:48:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 97F692011D for ; Fri, 13 Jun 2014 10:48:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751595AbaFMKsh (ORCPT ); Fri, 13 Jun 2014 06:48:37 -0400 Received: from mail-pa0-f49.google.com ([209.85.220.49]:42918 "EHLO mail-pa0-f49.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751468AbaFMKsg (ORCPT ); Fri, 13 Jun 2014 06:48:36 -0400 Received: by mail-pa0-f49.google.com with SMTP id lj1so2005889pab.22 for ; Fri, 13 Jun 2014 03:48:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:cc:subject :content-type:content-transfer-encoding; bh=gaNfx/uRocgH4PLZUrQUSj2gdzURFrT28xE6RlV5S70=; b=XdwAHT50KX0kqid+F1yLgHKExx2Up5fi5B825GPCESRyjyFNJN3z/qlYLyhUDlndIn IXvJWjRk6s4OigKz8Bx7wFk+VVqxFuYwEqPpl4G9ARvNMEAfFd92NcjaWgx9+4zyoPhh XvUexPJjN+YVkjOmWX46R/WJJJstfZPkmzxBVscmDxcMmbnSRsPsIB20zUXehxlUiR80 uBG7o7fsFm1/cE3WFiW8wwLFFkU8r+uWPa0pr0aL0EgWxdhU/rx5c8s9qyuZ1YuDWfF6 Oabo/uHveWwMyXxUxzsRA/RvaQfETq4cXzaxprbLkLMoadMYZyG6/M/cxaAaiYftgfdr MDHA== X-Received: by 10.68.253.73 with SMTP id zy9mr2295770pbc.114.1402656516119; Fri, 13 Jun 2014 03:48:36 -0700 (PDT) Received: from [192.168.0.100] ([171.92.21.4]) by mx.google.com with ESMTPSA id fe3sm2927630pbd.66.2014.06.13.03.48.31 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 13 Jun 2014 03:48:34 -0700 (PDT) Message-ID: <539AD6F7.8060301@gmail.com> Date: Fri, 13 Jun 2014 18:48:23 +0800 From: Kinglong Mee User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:24.0) Gecko/20100101 Thunderbird/24.6.0 MIME-Version: 1.0 To: "J. Bruce Fields" CC: Linux NFS Mailing List , kinglongmee@gmail.com Subject: [PATCH 1/3 v2] NFS4.0: Add IPv6 support Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP v2: fix a bug for parsing path. Signed-off-by: Kinglong Mee --- nfs4.0/lib/rpc/rpc.py | 15 ++++++++++----- nfs4.0/nfs4lib.py | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ nfs4.0/testserver.py | 26 ++++++-------------------- 3 files changed, 64 insertions(+), 25 deletions(-) diff --git a/nfs4.0/lib/rpc/rpc.py b/nfs4.0/lib/rpc/rpc.py index 60f70bd..8b39df4 100644 --- a/nfs4.0/lib/rpc/rpc.py +++ b/nfs4.0/lib/rpc/rpc.py @@ -188,6 +188,9 @@ class RPCClient(object): self.debug = 0 t = threading.currentThread() self.lock = threading.Lock() + self.af = socket.AF_INET; + if host.find(':') != -1: + self.af = socket.AF_INET6; self.remotehost = host self.remoteport = port self.timeout = timeout @@ -207,6 +210,7 @@ class RPCClient(object): self._init_security(self.sec_list) # Note this can make calls self.security = sec_list[0] + def _init_security(self, list): # Each element of list must have functions: # initialize, secure_data, make_cred, make_verf @@ -235,8 +239,7 @@ class RPCClient(object): if t in self._socket: out = self._socket[t] else: - out = self._socket[t] = socket.socket(socket.AF_INET, - socket.SOCK_STREAM) + out = self._socket[t] = socket.socket(self.af, socket.SOCK_STREAM) if self.uselowport: self.bindsocket(out) out.connect((self.remotehost, self.remoteport)) @@ -301,8 +304,7 @@ class RPCClient(object): t = threading.currentThread() self.lock.acquire() self._socket[t].close() - out = self._socket[t] = socket.socket(socket.AF_INET, - socket.SOCK_STREAM) + out = self._socket[t] = socket.socket(self.af, socket.SOCK_STREAM) # out.bind out.connect((self.remotehost, self.remoteport)) out.settimeout(self.timeout) @@ -454,7 +456,10 @@ class RPCClient(object): class Server(object): def __init__(self, host='', port=51423, name="SERVER"): - self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + try: + self.s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + except: + self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.s.bind((host, port)) self.port = self.s.getsockname()[1] diff --git a/nfs4.0/nfs4lib.py b/nfs4.0/nfs4lib.py index 5fc7bf3..0a20498 100644 --- a/nfs4.0/nfs4lib.py +++ b/nfs4.0/nfs4lib.py @@ -39,6 +39,7 @@ import time import struct import socket import sys +import re class NFSException(rpc.RPCError): pass @@ -1013,4 +1014,51 @@ def bitmap2list(bitmap): bitmap >>= 1 return out +def parse_nfs_url(url): + """Parse [nfs://]host:port/path, format taken from rfc 2224 + multipath addr:port pair are as such: + $ip1:$port1,$ip2:$port2.. + + Returns triple server, port, path. + """ + p = re.compile(r""" + (?:nfs://)? # Ignore an optionally prepended 'nfs://' + (?P[^/]+) + (?P/.*)? # set path=everything else, must start with / + $ + """, re.VERBOSE) + + m = p.match(url) + if m: + servers = m.group('servers') + server_list = [] + + for server in servers.split(','): + server = server.strip() + + idx = server.rfind(':') + bracket_idx = server.rfind(']') + + # the first : is before ipv6 addr ] -> no port specified + if bracket_idx > idx: + idx = -1 + + if idx >= 0: + host = server[:idx] + port = server[idx+1:] + else: + host = server + port = None + + # remove brackets around IPv6 addrs, if they exist + if host.startswith('[') and host.endswith(']'): + host = host[1:-1] + + port = (2049 if not port else int(port)) + server_list.append((host, port)) + + path = m.group('path') + return tuple(server_list), path + else: + raise ValueError("Error parsing NFS URL: %s" % url) diff --git a/nfs4.0/testserver.py b/nfs4.0/testserver.py index 606e2f0..41be74a 100755 --- a/nfs4.0/testserver.py +++ b/nfs4.0/testserver.py @@ -35,7 +35,6 @@ if __name__ == "__main__": if os.path.isfile(os.path.join(sys.path[0], 'lib', 'testmod.py')): sys.path.insert(1, os.path.join(sys.path[0], 'lib')) -import re import nfs4lib import testmod from optparse import OptionParser, OptionGroup, IndentedHelpFormatter @@ -57,23 +56,6 @@ if not hasattr(os, "getgid"): else: GID = os.getgid() - -def parse_url(url): - """Parse [nfs://]host:port/path""" - p = re.compile(r""" - (?:nfs://)? # Ignore an optionally prepended 'nfs://' - (?P[^:]+) # set host=everything up to next : - :? - (?P[^/]*) # set port=everything up to next / - (?P/.*$|$) # set path=everything else - """, re.VERBOSE) - - m = p.match(url) - if m: - return m.group('host'), m.group('port'), m.group('path') - else: - return None, None, None - def unixpath2comps(str, pathcomps=None): if pathcomps is None or str[0] == '/': pathcomps = [] @@ -284,9 +266,13 @@ def main(): if not args: p.error("Need a server") url = args.pop(0) - opt.server, opt.port, opt.path = parse_url(url) - if not opt.server: + server_list, opt.path = nfs4lib.parse_nfs_url(url) + + if not server_list: p.error("%s not a valid server name" % url) + + opt.server, opt.port = server_list[0] + if not opt.port: opt.port = 2049 else: