RPC(3)

NAME
packet.application.rpc - RPC module

DESCRIPTION

Decode RPC layer.

CLASSES

  class Header(baseobj.BaseObj)
Header object

Methods defined here:
---------------------

__init__(self, size, last_fragment)
Constructor which takes the size and last fragment as inputs

  class Prog(baseobj.BaseObj)
Prog object

Methods defined here:
---------------------

__init__(self, unpack)
Constructor which takes the Unpack object as input

  class RPC(packet.application.gss.GSS)
RPC object

Usage:
    from packet.application.rpc import RPC

    # Decode the RPC header
    x = RPC(pktt_obj, proto=6)

    # Decode NFS layer
    nfs = x.decode_payload()

Object definition:

RPC(
    [
        # If TCP
        fragment_hdr = Header(
            last_fragment = int,
            size          = int,
        ),
    ]
    xid  = int,
    type = int,

    [
        # If type == 0 (RPC call)
        rpc_version = int,
        program     = int,
        version     = int,
        procedure   = int,
        credential  = Credential(
            data   = string,
            flavor = int,
            size   = int,
        ),
        verifier = Credential(
            data   = string,
            flavor = int,
            size   = int,
        ),
    ] | [
        # If type == 1 (RPC reply)
        reply_status = int,
        [
            # If reply_status == 0
            verifier = Credential(
                data   = string,
                flavor = int,
                size   = int,
            ),
            accepted_status = int,
            [
                # If accepted_status == 2
                prog_mismatch = Prog(
                    low  = int,
                    high = int,
                )
            ]
        ] | [
            # If reply_status != 0
            rejected_status = int,
            [
                # If rejected_status == 0
                prog_mismatch = Prog(
                    low  = int,
                    high = int,
                )
            ] | [
                # If rejected_status != 0
                auth_status = int,
            ]
        ]
    ]
    psize = int,    # payload data size
    [data = string] # raw data of payload if unable to decode
)

Methods defined here:
---------------------

__bool__(self)
Truth value testing for the built-in operation bool()

__init__(self, pktt, proto=17, state=True)
Constructor

Initialize object's private data.

    pktt:
        Packet trace object (packet.pktt.Pktt) so this layer has
        access to the parent layers.

    proto:
        Transport layer protocol.

    state:
        Save call state. [default: True]

__str__(self)
String representation of object

The representation depends on the verbose level set by debug_repr().
If set to 0 the generic object representation is returned.
If set to 1 the representation of the object is:
    'RPC call   program: 100003, version: 4, procedure: 0, xid: 0xe37d3d5 '

If set to 2 the representation of the object is as follows:
    'CALL(0), program: 100003, version: 4, procedure: 0, xid: 0xe37d3d5'

decode_payload(self)
Decode RPC load

For RPC calls it is easy to decide if the RPC payload is an NFS packet
since the RPC program is in the RPC header, which for NFS the
program number is 100003. On the other hand, for RPC replies the RPC
header does not have any information on what the payload is, so the
transaction ID (xid) is used to map the replies to their calls and
thus deciding if RPC payload is an NFS packet or not.
This is further complicated when trying to decode callbacks, since
the program number for callbacks could be any number in the transient
program range [0x40000000, 0x5FFFFFFF]. Therefore, any program number
in the transient range is considered a callback and if the decoding
succeeds then this is an NFS callback, otherwise it is not.

Since the RPC replies do not contain any information about what type
of payload, when they are decoded correctly as NFS replies this
information is inserted in the RPC (pkt.rpc) object.
This information includes program number, RPC version, procedure
number as well as the call_index which is the packet index of its
corresponding call for each reply.

x.pkt.nfs = <NFSobject>

where <NFSobject> is an object of type COMPOUND4args or COMPOUND4res

class COMPOUND4args(
    tag          = string,
    minorversion = int,
    argarray     = [],
)

The argarray is a list of nfs_argop4 objects:

class nfs_argop4(
    argop = int,
    [<opobject> = <opargobject>,]
)

where opobject could be opsequence, opgetattr, etc., and opargobject
is the object which has the arguments for the given opobject, e.g.,
SEQUENCE4args, GETATTR4args, etc.

class COMPOUND4res(
    tag      = string,
    status   = int,
    resarray = [],
)

The resarray is a list of nfs_resop4 objects:

class nfs_resop4(
    resop = int,
    [<opobject> = <opresobject>,]
)

where opobject could be opsequence, opgetattr, etc., and opresobject
is the object which has the results for the given opobject, e.g.,
SEQUENCE4res, GETATTR4res, etc.

  class accept_stat_enum(packet.utils.Enum)
enum accept_stat

  class auth_stat_enum(packet.utils.Enum)
enum auth_stat

  class reject_stat_enum(packet.utils.Enum)
enum reject_stat

SEE ALSO
baseobj(3), packet.application.gss(3), packet.application.rpc_const(3), packet.application.rpc_creds(3), packet.nfs.mount3(3), packet.nfs.nfs(3), packet.nfs.nlm4(3), packet.nfs.portmap2(3), packet.utils(3)

BUGS
No known bugs.

AUTHOR
Jorge Mora (mora@netapp.com)