How do you access name of a ProtoField after declaration?

820 views Asked by At

How can I access the name property of a ProtoField after I declare it?

For example, something along the lines of:

myproto = Proto("myproto", "My Proto")

myproto.fields.foo = ProtoField.int8("myproto.foo", "Foo", base.DEC)

print(myproto.fields.foo.name)

Where I get the output:

Foo

2

There are 2 answers

1
charlesw On

Ok, this is janky, and certainly not the 'right' way to do it, but it seems to work.

I discovered this after looking at the output of

print(tostring(myproto.fields.foo))

This seems to spit out the value of each of the members of ProtoField, but I couldn't figure out the correct way to access them. So, instead, I decided to parse the string. This function will return 'Foo', but could be adapted to return the other fields as well.

function getname(field) 

--First, convert the field into a string

--this is going to result in a long string with 
--a bunch of info we dont need

local fieldString= tostring(field)  
-- fieldString looks like:
-- ProtoField(188403): Foo  myproto.foo base.DEC 0000000000000000 00000000 (null) 

--Split the string on '.' characters
a,b=fieldString:match"([^.]*).(.*)" 
--Split the first half of the previous result (a) on ':' characters
a,b=a:match"([^.]*):(.*)"

--At this point, b will equal " Foo myproto" 
--and we want to strip out that abreviation "abvr" part

--Count the number of times spaces occur in the string
local spaceCount = select(2, string.gsub(b, " ", ""))

--Declare a counter
local counter = 0

--Declare the name we are going to return
local constructedName = ''

--Step though each word in (b) separated by spaces
for word in b:gmatch("%w+") do 
    --If we hav reached the last space, go ahead and return 
    if counter == spaceCount-1  then
        return constructedName
    end

    --Add the current word to our name 
    constructedName = constructedName .. word .. " "

    --Increment counter
    counter = counter+1
end
end 
3
Christopher Maynard On

An alternate method that's a bit more terse:

local fieldString = tostring(field)
local i, j = string.find(fieldString, ": .* myproto")

print(string.sub(fieldString, i + 2, j - (1 + string.len("myproto")))

EDIT: Or an even simpler solution that works for any protocol:

local fieldString = tostring(field)
local i, j = string.find(fieldString, ": .* ")

print(string.sub(fieldString, i + 2, j - 1))

Of course the 2nd method only works as long as there are no spaces in the field name. Since that's not necessarily always going to be the case, the 1st method is more robust. Here is the 1st method wrapped up in a function that ought to be usable by any dissector:

-- The field is the field whose name you want to print.
-- The proto is the name of the relevant protocol
function printFieldName(field, protoStr)

    local fieldString = tostring(field)
    local i, j = string.find(fieldString, ": .* " .. protoStr)

    print(string.sub(fieldString, i + 2, j - (1 + string.len(protoStr)))
end

... and here it is in use:

printFieldName(myproto.fields.foo, "myproto")
printFieldName(someproto.fields.bar, "someproto")