diff --git a/scapy/utils.py b/scapy/utils.py
index 40ce9a4b47a1b78247f8eab23ba6281e683a46e8..c3febf59e2bb97d9f1d61172b8e900cab20c17c8 100644
--- a/scapy/utils.py
+++ b/scapy/utils.py
@@ -548,49 +548,77 @@ def rdpcap(filename, count=-1):
 count: read only <count> packets
 
     """
-    try:
-        return _rdpcap(filename, count=count)
-    except Scapy_Exception:
-        pass
-    try:
-        return _rdpcapng(filename, count=count)
-    except Scapy_Exception:
-        raise Scapy_Exception("Not a valid pcap or pcapng file")
-
+    with PcapReader(filename) as fdesc:
+        return fdesc.read_all(count=count)
 
-def _rdpcap(filename, count=-1):
-    """Read a pcap file and return a packet list
 
-count: read only <count> packets
+class PcapReader_metaclass(type):
+    """Metaclass for (Raw)Pcap(Ng)Readers"""
 
-    """
-    with PcapReader(filename) as fdesc:
-        return fdesc.read_all(count=count)
+    def __new__(cls, name, bases, dct):
+        """The `alternative` class attribute is declared in the PcapNg
+        variant, and set here to the Pcap variant.
 
-def _rdpcapng(filename, count=-1):
-    """Read a pcapng file and return a packet list
+        """
+        newcls = super(PcapReader_metaclass, cls).__new__(cls, name, bases, dct)
+        if 'alternative' in dct:
+            dct['alternative'].alternative = newcls
+        return newcls
 
-count: read only <count> packets
+    def __call__(cls, filename):
+        """Creates a cls instance, use the `alternative` if that
+        fails.
 
-    """
-    with PcapNgReader(filename) as fdesc:
-        return fdesc.read_all(count=count)
+        """
+        i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
+        filename, fdesc, magic = cls.open(filename)
+        try:
+            i.__init__(filename, fdesc, magic)
+        except Scapy_Exception:
+            if "alternative" in cls.__dict__:
+                cls = cls.__dict__["alternative"]
+                i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__)
+                try:
+                    i.__init__(filename, fdesc, magic)
+                except Scapy_Exception:
+                    try:
+                        self.f.seek(-4, 1)
+                    except:
+                        pass
+                    raise Scapy_Exception("Not a supported capture file")
+
+        return i
+
+    @staticmethod
+    def open(filename):
+        """Open (if necessary) filename, and read the magic."""
+        if isinstance(filename, basestring):
+            try:
+                fdesc = gzip.open(filename,"rb")
+                magic = fdesc.read(4)
+            except IOError:
+                fdesc = open(filename,"rb")
+                magic = fdesc.read(4)
+        else:
+            fdesc = filename
+            filename = (fdesc.name
+                        if hasattr(fdesc, "name") else
+                        "No name")
+            magic = fdesc.read(4)
+        return filename, fdesc, magic
 
 
 class RawPcapReader:
     """A stateful pcap reader. Each packet is returned as a string"""
-
-    def __init__(self, filename):
-        magic = self.open(filename)
+    __metaclass__ = PcapReader_metaclass
+    def __init__(self, filename, fdesc, magic):
+        self.filename = filename
+        self.f = fdesc
         if magic == "\xa1\xb2\xc3\xd4": #big endian
             self.endian = ">"
         elif magic == "\xd4\xc3\xb2\xa1": #little endian
             self.endian = "<"
         else:
-            try:
-                self.f.seek(-4, 1)
-            except:
-                pass
             raise Scapy_Exception(
                 "Not a pcap capture file (bad magic: %r)" % magic
             )
@@ -602,23 +630,6 @@ class RawPcapReader:
         )
         self.linktype = linktype
 
-    def open(self, filename):
-        """Open (if necessary) filename"""
-        if isinstance(filename, basestring):
-            self.filename = filename
-            try:
-                self.f = gzip.open(filename,"rb")
-                return self.f.read(4)
-            except IOError:
-                self.f = open(filename,"rb")
-                return self.f.read(4)
-        else:
-            self.f = filename
-            self.filename = (filename.name
-                             if hasattr(filename, "name") else
-                             "No name")
-            return self.f.read(4)
-
     def __iter__(self):
         return self
 
@@ -684,8 +695,8 @@ class RawPcapReader:
 
 
 class PcapReader(RawPcapReader):
-    def __init__(self, filename):
-        RawPcapReader.__init__(self, filename)
+    def __init__(self, filename, fdesc, magic):
+        RawPcapReader.__init__(self, filename, fdesc, magic)
         try:
             self.LLcls = conf.l2types[self.linktype]
         except KeyError:
@@ -721,19 +732,18 @@ class RawPcapNgReader(RawPcapReader):
 
     """
 
-    def __init__(self, filename):
+    alternative = RawPcapReader
+
+    def __init__(self, filename, fdesc, magic):
+        self.filename = filename
+        self.f = fdesc
         # A list of (linktype, snaplen); will be populated by IDBs.
         self.interfaces = []
         self.blocktypes = {
             1: self.read_block_idb,
             6: self.read_block_epb,
         }
-        magic = self.open(filename)
         if magic != "\x0a\x0d\x0d\x0a": # PcapNg:
-            try:
-                self.f.seek(-4, 1)
-            except:
-                pass
             raise Scapy_Exception(
                 "Not a pcapng capture file (bad magic: %r)" % magic
             )
@@ -786,8 +796,12 @@ class RawPcapNgReader(RawPcapReader):
 
 
 class PcapNgReader(RawPcapNgReader):
-    def __init__(self, filename):
-        RawPcapNgReader.__init__(self, filename)
+
+    alternative = PcapReader
+
+    def __init__(self, filename, fdesc, magic):
+        RawPcapNgReader.__init__(self, filename, fdesc, magic)
+
     def read_packet(self, size=MTU):
         rp = RawPcapNgReader.read_packet(self, size=size)
         if rp is None:
diff --git a/test/regression.uts b/test/regression.uts
index 3cf4b298e4a57fda22d9f9297ac961509f19bedf..fd2569158aab4b6d7e6c2843baba25e2d3457cb2 100644
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -4300,10 +4300,10 @@ pcapfile = cStringIO.StringIO('\xd4\xc3\xb2\xa1\x02\x00\x04\x00\x00\x00\x00\x00\
 pcapngfile = cStringIO.StringIO('\n\r\r\n\\\x00\x00\x00M<+\x1a\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x01\x00,\x00File created by merging: \nFile1: test.pcap \n\x04\x00\x08\x00mergecap\x00\x00\x00\x00\\\x00\x00\x00\x01\x00\x00\x00\\\x00\x00\x00e\x00\x00\x00\xff\xff\x00\x00\x02\x006\x00Unknown/not available in original file format(libpcap)\x00\x00\t\x00\x01\x00\x06\x00\x00\x00\x00\x00\x00\x00\\\x00\x00\x00\x06\x00\x00\x00H\x00\x00\x00\x00\x00\x00\x00\x8d*\x05\x00/\xfc[\xcd(\x00\x00\x00(\x00\x00\x00E\x00\x00(\x00\x01\x00\x00@\x06|\xcd\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00\x91|\x00\x00H\x00\x00\x00\x06\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x8d*\x05\x00\x1f\xff[\xcd\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x11|\xce\x7f\x00\x00\x01\x7f\x00\x00\x01\x005\x005\x00\x08\x01r<\x00\x00\x00\x06\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x8d*\x05\x00\xb9\x02\\\xcd\x1c\x00\x00\x00\x1c\x00\x00\x00E\x00\x00\x1c\x00\x01\x00\x00@\x01|\xde\x7f\x00\x00\x01\x7f\x00\x00\x01\x08\x00\xf7\xff\x00\x00\x00\x00<\x00\x00\x00')
 
 = Read a pcap file
-pktpcap = utils._rdpcap(pcapfile)
+pktpcap = rdpcap(pcapfile)
 
 = Read a pcapng file
-pktpcapng = utils._rdpcapng(pcapngfile)
+pktpcapng = rdpcap(pcapngfile)
 
 = Check both packet lists are the same
 assert list(pktpcap) == list(pktpcapng)