root/scapy/fields.py

Revision 939:d64575f85d44, 24.4 kB (checked in by Phil <phil@secdev.org>, 2 months ago)

Remove \0 padding for StrFixedLenField? representations

Line 
1 ## This file is part of Scapy
2 ## See http://www.secdev.org/projects/scapy for more informations
3 ## Copyright (C) Philippe Biondi <phil@secdev.org>
4 ## This program is published under a GPLv2 license
5
6 import struct,copy,socket
7 from config import conf
8 from volatile import *
9 from data import *
10 from utils import *
11 from base_classes import BasePacket,Gen,Net
12
13
14 ############
15 ## Fields ##
16 ############
17
18 class Field:
19     """For more informations on how this work, please refer to
20        http://www.secdev.org/projects/scapy/files/scapydoc.pdf
21        chapter ``Adding a New Field''"""
22     islist=0
23     holds_packets=0
24     def __init__(self, name, default, fmt="H"):
25         self.name = name
26         if fmt[0] in "@=<>!":
27             self.fmt = fmt
28         else:
29             self.fmt = "!"+fmt
30         self.default = self.any2i(None,default)
31         self.sz = struct.calcsize(self.fmt)
32         self.owners = []
33
34     def register_owner(self, cls):
35         self.owners.append(cls)
36
37     def i2len(self, pkt, x):
38         """Convert internal value to a length usable by a FieldLenField"""
39         return self.sz
40     def i2count(self, pkt, x):
41         """Convert internal value to a number of elements usable by a FieldLenField.
42         Always 1 except for list fields"""
43         return 1
44     def h2i(self, pkt, x):
45         """Convert human value to internal value"""
46         return x
47     def i2h(self, pkt, x):
48         """Convert internal value to human value"""
49         return x
50     def m2i(self, pkt, x):
51         """Convert machine value to internal value"""
52         return x
53     def i2m(self, pkt, x):
54         """Convert internal value to machine value"""
55         if x is None:
56             x = 0
57         return x
58     def any2i(self, pkt, x):
59         """Try to understand the most input values possible and make an internal value from them"""
60         return self.h2i(pkt, x)
61     def i2repr(self, pkt, x):
62         """Convert internal value to a nice representation"""
63         return repr(self.i2h(pkt,x))
64     def addfield(self, pkt, s, val):
65         """Add an internal value  to a string"""
66         return s+struct.pack(self.fmt, self.i2m(pkt,val))
67     def getfield(self, pkt, s):
68         """Extract an internal value from a string"""
69         return  s[self.sz:], self.m2i(pkt, struct.unpack(self.fmt, s[:self.sz])[0])
70     def do_copy(self, x):
71         if hasattr(x, "copy"):
72             return x.copy()
73         if type(x) is list:
74             x = x[:]
75             for i in xrange(len(x)):
76                 if isinstance(x[i], BasePacket):
77                     x[i] = x[i].copy()
78         return x
79     def __repr__(self):
80         return "<Field (%s).%s>" % (",".join(x.__name__ for x in self.owners),self.name)
81     def copy(self):
82         return copy.deepcopy(self)
83     def randval(self):
84         """Return a volatile object whose value is both random and suitable for this field"""
85         fmtt = self.fmt[-1]
86         if fmtt in "BHIQ":
87             return {"B":RandByte,"H":RandShort,"I":RandInt, "Q":RandLong}[fmtt]()
88         elif fmtt == "s":
89             if self.fmt[0] in "0123456789":
90                 l = int(self.fmt[:-1])
91             else:
92                 l = int(self.fmt[1:-1])
93             return RandBin(l)
94         else:
95             warning("no random class for [%s] (fmt=%s)." % (self.name, self.fmt))
96            
97
98
99
100 class Emph:
101     fld = ""
102     def __init__(self, fld):
103         self.fld = fld
104     def __getattr__(self, attr):
105         return getattr(self.fld,attr)
106     def __hash__(self):
107         return hash(self.fld)
108     def __eq__(self, other):
109         return self.fld == other
110    
111
112 class ActionField:
113     _fld = None
114     def __init__(self, fld, action_method, **kargs):
115         self._fld = fld
116         self._action_method = action_method
117         self._privdata = kargs
118     def any2i(self, pkt, val):
119         getattr(pkt, self._action_method)(val, self._fld, **self._privdata)
120         return getattr(self._fld, "any2i")(pkt, val)
121     def __getattr__(self, attr):
122         return getattr(self._fld,attr)
123
124
125 class ConditionalField:
126     fld = None
127     def __init__(self, fld, cond):
128         self.fld = fld
129         self.cond = cond
130     def _evalcond(self,pkt):
131         return self.cond(pkt)
132        
133     def getfield(self, pkt, s):
134         if self._evalcond(pkt):
135             return self.fld.getfield(pkt,s)
136         else:
137             return s,None
138        
139     def addfield(self, pkt, s, val):
140         if self._evalcond(pkt):
141             return self.fld.addfield(pkt,s,val)
142         else:
143             return s
144     def __getattr__(self, attr):
145         return getattr(self.fld,attr)
146        
147
148 class PadField:
149     """Add bytes after the proxified field so that it ends at the specified
150        alignment from its begining"""
151     _fld = None
152     def __init__(self, fld, align, padwith=None):
153         self._fld = fld
154         self._align = align
155         self._padwith = padwith or ""
156
157     def addfield(self, pkt, s, val):
158         sval = self._fld.addfield(pkt, "", val)
159         return s+sval+struct.pack("%is" % (-len(sval)%self._align), self._padwith)
160    
161     def __getattr__(self, attr):
162         return getattr(self._fld,attr)
163        
164
165 class MACField(Field):
166     def __init__(self, name, default):
167         Field.__init__(self, name, default, "6s")
168     def i2m(self, pkt, x):
169         if x is None:
170             return "\0\0\0\0\0\0"
171         return mac2str(x)
172     def m2i(self, pkt, x):
173         return str2mac(x)
174     def any2i(self, pkt, x):
175         if type(x) is str and len(x) is 6:
176             x = self.m2i(pkt, x)
177         return x
178     def i2repr(self, pkt, x):
179         x = self.i2h(pkt, x)
180         if self in conf.resolve:
181             x = conf.manufdb._resolve_MAC(x)
182         return x
183     def randval(self):
184         return RandMAC()
185
186
187 class IPField(Field):
188     def __init__(self, name, default):
189         Field.__init__(self, name, default, "4s")
190     def h2i(self, pkt, x):
191         if type(x) is str:
192             try:
193                 inet_aton(x)
194             except socket.error:
195                 x = Net(x)
196         elif type(x) is list:
197             x = [self.h2i(pkt, n) for n in x]
198         return x
199     def resolve(self, x):
200         if self in conf.resolve:
201             try:
202                 ret = socket.gethostbyaddr(x)[0]
203             except:
204                 pass
205             else:
206                 if ret:
207                     return ret
208         return x
209     def i2m(self, pkt, x):
210         return inet_aton(x)
211     def m2i(self, pkt, x):
212         return inet_ntoa(x)
213     def any2i(self, pkt, x):
214         return self.h2i(pkt,x)
215     def i2repr(self, pkt, x):
216         return self.resolve(self.i2h(pkt, x))
217     def randval(self):
218         return RandIP()
219
220 class SourceIPField(IPField):
221     def __init__(self, name, dstname):
222         IPField.__init__(self, name, None)
223         self.dstname = dstname
224     def i2m(self, pkt, x):
225         if x is None:
226             iff,x,gw = pkt.route()
227             if x is None:
228                 x = "0.0.0.0"
229         return IPField.i2m(self, pkt, x)
230     def i2h(self, pkt, x):
231         if x is None:
232             dst=getattr(pkt,self.dstname)
233             if isinstance(dst,Gen):
234                 r = map(conf.route.route, dst)
235                 r.sort()
236                 if r[0] != r[-1]:
237                     warning("More than one possible route for %s"%repr(dst))
238                 iff,x,gw = r[0]
239             else:
240                 iff,x,gw = conf.route.route(dst)
241         return IPField.i2h(self, pkt, x)
242
243    
244
245
246 class ByteField(Field):
247     def __init__(self, name, default):
248         Field.__init__(self, name, default, "B")
249        
250 class XByteField(ByteField):
251     def i2repr(self, pkt, x):
252         if x is None:
253             x = 0
254         return lhex(self.i2h(pkt, x))
255
256 class X3BytesField(XByteField):
257     def __init__(self, name, default):
258         Field.__init__(self, name, default, "!I")
259     def addfield(self, pkt, s, val):
260         return s+struct.pack(self.fmt, self.i2m(pkt,val))[1:4]
261     def getfield(self, pkt, s):
262         return  s[3:], self.m2i(pkt, struct.unpack(self.fmt, "\x00"+s[:3])[0])
263
264
265 class ShortField(Field):
266     def __init__(self, name, default):
267         Field.__init__(self, name, default, "H")
268
269 class LEShortField(Field):
270     def __init__(self, name, default):
271         Field.__init__(self, name, default, "<H")
272
273 class XShortField(ShortField):
274     def i2repr(self, pkt, x):
275         if x is None:
276             x = 0
277         return lhex(self.i2h(pkt, x))
278
279
280 class IntField(Field):
281     def __init__(self, name, default):
282         Field.__init__(self, name, default, "I")
283
284 class SignedIntField(Field):
285     def __init__(self, name, default):
286         Field.__init__(self, name, default, "i")
287     def randval(self):
288         return RandSInt()
289
290 class LEIntField(Field):
291     def __init__(self, name, default):
292         Field.__init__(self, name, default, "<I")
293
294 class LESignedIntField(Field):
295     def __init__(self, name, default):
296         Field.__init__(self, name, default, "<i")
297     def randval(self):
298         return RandSInt()
299
300 class XIntField(IntField):
301     def i2repr(self, pkt, x):
302         if x is None:
303             x = 0
304         return lhex(self.i2h(pkt, x))
305
306
307 class LongField(Field):
308     def __init__(self, name, default):
309         Field.__init__(self, name, default, "Q")
310
311 class XLongField(LongField):
312     def i2repr(self, pkt, x):
313         if x is None:
314             x = 0
315         return lhex(self.i2h(pkt, x))
316
317 class IEEEFloatField(Field):
318     def __init__(self, name, default):
319         Field.__init__(self, name, default, "f")
320
321 class IEEEDoubleField(Field):
322     def __init__(self, name, default):
323         Field.__init__(self, name, default, "d")
324
325
326 class StrField(Field):
327     def __init__(self, name, default, fmt="H", remain=0):
328         Field.__init__(self,name,default,fmt)
329         self.remain = remain       
330     def i2len(self, pkt, i):
331         return len(i)
332     def i2m(self, pkt, x):
333         if x is None:
334             x = ""
335         elif type(x) is not str:
336             x=str(x)
337         return x
338     def addfield(self, pkt, s, val):
339         return s+self.i2m(pkt, val)
340     def getfield(self, pkt, s):
341         if self.remain == 0:
342             return "",self.m2i(pkt, s)
343         else:
344             return s[-self.remain:],self.m2i(pkt, s[:-self.remain])
345     def randval(self):
346         return RandBin(RandNum(0,1200))
347
348 class PacketField(StrField):
349     holds_packets=1
350     def __init__(self, name, default, cls, remain=0):
351         StrField.__init__(self, name, default, remain=remain)
352         self.cls = cls
353     def i2m(self, pkt, i):
354         return str(i)
355     def m2i(self, pkt, m):
356         return self.cls(m)
357     def getfield(self, pkt, s):
358         i = self.m2i(pkt, s)
359         remain = ""
360         if 'Padding' in i:
361             r = i['Padding']
362             del(r.underlayer.payload)
363             remain = r.load
364         return remain,i
365    
366 class PacketLenField(PacketField):
367     holds_packets=1
368     def __init__(self, name, default, cls, length_from=None):
369         PacketField.__init__(self, name, default, cls)
370         self.length_from = length_from
371     def getfield(self, pkt, s):
372         l = self.length_from(pkt)
373         i = self.m2i(pkt, s[:l])
374         return s[l:],i
375
376
377 class PacketListField(PacketField):
378     islist = 1
379     holds_packets=1
380     def __init__(self, name, default, cls, count_from=None, length_from=None):
381         if default is None:
382             default = []  # Create a new list for each instance
383         PacketField.__init__(self, name, default, cls)
384         self.count_from = count_from
385         self.length_from = length_from
386
387
388     def any2i(self, pkt, x):
389         if type(x) is not list:
390             return [x]
391         else:
392             return x
393     def i2count(self, pkt, val):
394         if type(val) is list:
395             return len(val)
396         return 1
397     def i2len(self, pkt, val):
398         return sum( len(p) for p in val )
399     def do_copy(self, x):
400         return map(lambda p:p.copy(), x)
401     def getfield(self, pkt, s):
402         c = l = None
403         if self.length_from is not None:
404             l = self.length_from(pkt)
405         elif self.count_from is not None:
406             c = self.count_from(pkt)
407            
408         lst = []
409         ret = ""
410         remain = s
411         if l is not None:
412             remain,ret = s[:l],s[l:]
413         while remain:
414             if c is not None:
415                 if c <= 0:
416                     break
417                 c -= 1
418             p = self.m2i(pkt,remain)
419             if 'Padding' in p:
420                 pad = p['Padding']
421                 remain = pad.load
422                 del(pad.underlayer.payload)
423             else:
424                 remain = ""
425             lst.append(p)
426         return remain+ret,lst
427     def addfield(self, pkt, s, val):
428         return s+"".join(map(str, val))
429
430
431 class StrFixedLenField(StrField):
432     def __init__(self, name, default, length=None, length_from=None):
433         StrField.__init__(self, name, default)
434         self.length_from  = length_from
435         if length is not None:
436             self.length_from = lambda pkt,length=length: length
437     def i2repr(self, pkt, v):
438         if type(v) is str:
439             v = v.rstrip("\0")
440         return repr(v)
441     def getfield(self, pkt, s):
442         l = self.length_from(pkt)
443         return s[l:], self.m2i(pkt,s[:l])
444     def addfield(self, pkt, s, val):
445         l = self.length_from(pkt)
446         return s+struct.pack("%is"%l,self.i2m(pkt, val))
447     def randval(self):
448         try:
449             l = self.length_from(None)
450         except:
451             l = RandNum(0,200)
452         return RandBin(l)
453
454 class NetBIOSNameField(StrFixedLenField):
455     def __init__(self, name, default, length=31):
456         StrFixedLenField.__init__(self, name, default, length)
457     def i2m(self, pkt, x):
458         l = self.length_from(pkt)/2
459         if x is None:
460             x = ""
461         x += " "*(l)
462         x = x[:l]
463         x = "".join(map(lambda x: chr(0x41+(ord(x)>>4))+chr(0x41+(ord(x)&0xf)), x))
464         x = " "+x
465         return x
466     def m2i(self, pkt, x):
467         x = x.strip("\x00").strip(" ")
468         return "".join(map(lambda x,y: chr((((ord(x)-1)&0xf)<<4)+((ord(y)-1)&0xf)), x[::2],x[1::2]))
469
470 class StrLenField(StrField):
471     def __init__(self, name, default, fld=None, length_from=None):
472         StrField.__init__(self, name, default)
473         self.length_from = length_from
474     def getfield(self, pkt, s):
475         l = self.length_from(pkt)
476         return s[l:], self.m2i(pkt,s[:l])
477
478 class FieldListField(Field):
479     islist=1
480     def __init__(self, name, default, field, length_from=None, count_from=None):
481         if default is None:
482             default = []  # Create a new list for each instance
483         Field.__init__(self, name, default)
484         self.count_from = count_from
485         self.length_from = length_from
486         self.field = field           
487            
488     def i2count(self, pkt, val):
489         if type(val) is list:
490             return len(val)
491         return 1
492     def i2len(self, pkt, val):
493         return sum( self.field.i2len(pkt,v) for v in val )
494    
495     def i2m(self, pkt, val):
496         if val is None:
497             val = []
498         return val
499     def any2i(self, pkt, x):
500         if type(x) is not list:
501             return [x]
502         else:
503             return x
504     def addfield(self, pkt, s, val):
505         val = self.i2m(pkt, val)
506         for v in val:
507             s = self.field.addfield(pkt, s, v)
508         return s
509     def getfield(self, pkt, s):
510         c = l = None
511         if self.length_from is not None:
512             l = self.length_from(pkt)
513         elif self.count_from is not None:
514             c = self.count_from(pkt)
515
516         val = []
517         ret=""
518         if l is not None:
519             s,ret = s[:l],s[l:]
520            
521         while s:
522             if c is not None:
523                 if c <= 0:
524                     break
525                 c -= 1
526             s,v = self.field.getfield(pkt, s)
527             val.append(v)
528         return s+ret, val
529
530 class FieldLenField(Field):
531     def __init__(self, name, default,  length_of=None, fmt = "H", count_of=None, adjust=lambda pkt,x:x, fld=None):
532         Field.__init__(self, name, default, fmt)
533         self.length_of=length_of
534         self.count_of=count_of
535         self.adjust=adjust
536         if fld is not None:
537             FIELD_LENGTH_MANAGEMENT_DEPRECATION(self.__class__.__name__)
538             self.length_of = fld
539     def i2m(self, pkt, x):
540         if x is None:
541             if self.length_of is not None:
542                 fld,fval = pkt.getfield_and_val(self.length_of)
543                 f = fld.i2len(pkt, fval)
544             else:
545                 fld,fval = pkt.getfield_and_val(self.count_of)
546                 f = fld.i2count(pkt, fval)
547             x = self.adjust(pkt,f)
548         return x
549
550 class StrNullField(StrField):
551     def addfield(self, pkt, s, val):
552         return s+self.i2m(pkt, val)+"\x00"
553     def getfield(self, pkt, s):
554         l = s.find("\x00")
555         if l < 0:
556             #XXX \x00 not found
557             return "",s
558         return s[l+1:],self.m2i(pkt, s[:l])
559     def randval(self):
560         return RandTermString(RandNum(0,1200),"\x00")
561
562 class StrStopField(StrField):
563     def __init__(self, name, default, stop, additionnal=0):
564         Field.__init__(self, name, default)
565         self.stop=stop
566         self.additionnal=additionnal
567     def getfield(self, pkt, s):
568         l = s.find(self.stop)
569         if l < 0:
570             return "",s
571 #            raise Scapy_Exception,"StrStopField: stop value [%s] not found" %stop
572         l += len(self.stop)+self.additionnal
573         return s[l:],s[:l]
574     def randval(self):
575         return RandTermString(RandNum(0,1200),self.stop)
576
577 class LenField(Field):
578     def i2m(self, pkt, x):
579         if x is None:
580             x = len(pkt.payload)
581         return x
582
583 class BCDFloatField(Field):
584     def i2m(self, pkt, x):
585         return int(256*x)
586     def m2i(self, pkt, x):
587         return x/256.0
588
589 class BitField(Field):
590     def __init__(self, name, default, size):
591         Field.__init__(self, name, default)
592         self.rev = size < 0
593         self.size = abs(size)
594     def reverse(self, val):
595         if self.size == 16:
596             val = socket.ntohs(val)
597         elif self.size == 32:
598             val = socket.ntohl(val)
599         return val
600        
601     def addfield(self, pkt, s, val):
602         val = self.i2m(pkt, val)
603         if type(s) is tuple:
604             s,bitsdone,v = s
605         else:
606             bitsdone = 0
607             v = 0
608         if self.rev:
609             val = self.reverse(val)
610         v <<= self.size
611         v |= val & ((1L<<self.size) - 1)
612         bitsdone += self.size
613         while bitsdone >= 8:
614             bitsdone -= 8
615             s = s+struct.pack("!B", v >> bitsdone)
616             v &= (1L<<bitsdone)-1
617         if bitsdone:
618             return s,bitsdone,v
619         else:
620             return s
621     def getfield(self, pkt, s):
622         if type(s) is tuple:
623             s,bn = s
624         else:
625             bn = 0
626         # we don't want to process all the string
627         nb_bytes = (self.size+bn-1)/8 + 1
628         w = s[:nb_bytes]
629
630         # split the substring byte by byte
631         bytes = struct.unpack('!%dB' % nb_bytes , w)
632
633         b = 0L
634         for c in range(nb_bytes):
635             b |= long(bytes[c]) << (nb_bytes-c-1)*8
636
637         # get rid of high order bits
638         b &= (1L << (nb_bytes*8-bn)) - 1
639
640         # remove low order bits
641         b = b >> (nb_bytes*8 - self.size - bn)
642
643         if self.rev:
644             b = self.reverse(b)
645
646         bn += self.size
647         s = s[bn/8:]
648         bn = bn%8
649         b = self.m2i(pkt, b)
650         if bn:
651             return (s,bn),b
652         else:
653             return s,b
654     def randval(self):
655         return RandNum(0,2**self.size-1)
656
657
658 class BitFieldLenField(BitField):
659     def __init__(self, name, default, size, length_of=None, count_of=None, adjust=lambda pkt,x:x):
660         BitField.__init__(self, name, default, size)
661         self.length_of=length_of
662         self.count_of=count_of
663         self.adjust=adjust
664     def i2m(self, pkt, x):
665         return FieldLenField.i2m.im_func(self, pkt, x)
666
667
668 class XBitField(BitField):
669     def i2repr(self, pkt, x):
670         return lhex(self.i2h(pkt,x))
671
672
673 class EnumField(Field):
674     def __init__(self, name, default, enum, fmt = "H"):
675         i2s = self.i2s = {}
676         s2i = self.s2i = {}
677         if type(enum) is list:
678             keys = xrange(len(enum))
679         else:
680             keys = enum.keys()
681         if filter(lambda x: type(x) is str, keys):
682             i2s,s2i = s2i,i2s
683         for k in keys:
684             i2s[k] = enum[k]
685             s2i[enum[k]] = k
686         Field.__init__(self, name, default, fmt)
687     def any2i_one(self, pkt, x):
688         if type(x) is str:
689             x = self.s2i[x]
690         return x
691     def i2repr_one(self, pkt, x):
692         if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s:
693             return self.i2s[x]
694         return repr(x)
695    
696     def any2i(self, pkt, x):
697         if type(x) is list:
698             return map(lambda z,pkt=pkt:self.any2i_one(pkt,z), x)
699         else:
700             return self.any2i_one(pkt,x)       
701     def i2repr(self, pkt, x):
702         if type(x) is list:
703             return map(lambda z,pkt=pkt:self.i2repr_one(pkt,z), x)
704         else:
705             return self.i2repr_one(pkt,x)
706
707 class CharEnumField(EnumField):
708     def __init__(self, name, default, enum, fmt = "1s"):
709         EnumField.__init__(self, name, default, enum, fmt)
710         k = self.i2s.keys()
711         if k and len(k[0]) != 1:
712             self.i2s,self.s2i = self.s2i,self.i2s
713     def any2i_one(self, pkt, x):
714         if len(x) != 1:
715             x = self.s2i[x]
716         return x
717
718 class BitEnumField(BitField,EnumField):
719     def __init__(self, name, default, size, enum):
720         EnumField.__init__(self, name, default, enum)
721         self.rev = size < 0
722         self.size = abs(size)
723     def any2i(self, pkt, x):
724         return EnumField.any2i(self, pkt, x)
725     def i2repr(self, pkt, x):
726         return EnumField.i2repr(self, pkt, x)
727
728 class ShortEnumField(EnumField):
729     def __init__(self, name, default, enum):
730         EnumField.__init__(self, name, default, enum, "H")
731
732 class LEShortEnumField(EnumField):
733     def __init__(self, name, default, enum):
734         EnumField.__init__(self, name, default, enum, "<H")
735
736 class ByteEnumField(EnumField):
737     def __init__(self, name, default, enum):
738         EnumField.__init__(self, name, default, enum, "B")
739
740 class IntEnumField(EnumField):
741     def __init__(self, name, default, enum):
742         EnumField.__init__(self, name, default, enum, "I")
743
744 class SignedIntEnumField(EnumField):
745     def __init__(self, name, default, enum):
746         EnumField.__init__(self, name, default, enum, "i")
747     def randval(self):
748         return RandSInt()
749
750 class LEIntEnumField(EnumField):
751     def __init__(self, name, default, enum):
752         EnumField.__init__(self, name, default, enum, "<I")
753
754 class XShortEnumField(ShortEnumField):
755     def i2repr_one(self, pkt, x):
756         if self not in conf.noenum and not isinstance(x,VolatileValue) and x in self.i2s:
757             return self.i2s[x]
758         return lhex(x)
759
760 # Little endian long field
761 class LELongField(Field):
762     def __init__(self, name, default):
763         Field.__init__(self, name, default, "<Q")
764
765 # Little endian fixed length field
766 class LEFieldLenField(FieldLenField):
767     def __init__(self, name, default,  length_of=None, fmt = "<H", count_of=None, adjust=lambda pkt,x:x, fld=None):
768         FieldLenField.__init__(self, name, default, length_of=length_of, fmt=fmt, fld=fld, adjust=adjust)
769
770
771 class FlagsField(BitField):
772     def __init__(self, name, default, size, names):
773         BitField.__init__(self, name, default, size)
774         self.multi = type(names) is list
775         if self.multi:
776             self.names = map(lambda x:[x], names)
777         else:
778             self.names = names
779     def any2i(self, pkt, x):
780         if type(x) is str:
781             if self.multi:
782                 x = map(lambda y:[y], x.split("+"))
783             y = 0
784             for i in x:
785                 y |= 1 << self.names.index(i)
786             x = y
787         return x
788     def i2repr(self, pkt, x):
789         if type(x) is list or type(x) is tuple:
790             return repr(x)
791         if self.multi:
792             r = []
793         else:
794             r = ""
795         i=0
796         while x:
797             if x & 1:
798                 r += self.names[i]
799             i += 1
800             x >>= 1
801         if self.multi:
802             r = "+".join(r)
803         return r
804
805            
806
807
808 class FixedPointField(BitField):
809     def __init__(self, name, default, size, frac_bits=16):
810         self.frac_bits = frac_bits
811         BitField.__init__(self, name, default, size)
812
813     def any2i(self, pkt, val):
814         if val is None:
815             return val
816         ival = int(val)
817         fract = int( (val-ival) * 2**self.frac_bits )
818         return (ival << self.frac_bits) | fract
819
820     def i2h(self, pkt, val):
821         int_part = val >> self.frac_bits
822         frac_part = val & (1L << self.frac_bits) - 1
823         frac_part /= 2.0**self.frac_bits
824         return int_part+frac_part
825     def i2repr(self, pkt, val):
826         return self.i2h(pkt, val)
Note: See TracBrowser for help on using the browser.