Skip to content
Snippets Groups Projects
Commit 59371f98 authored by Pierre Lalet's avatar Pierre Lalet
Browse files

Merged in MarcelPatzlaff/scapy (pull request #86)

IS-IS dissector
parents e768df92 e2e44b9f
No related branches found
No related tags found
No related merge requests found
...@@ -82,15 +82,26 @@ if scapy.config.conf.iface is None: ...@@ -82,15 +82,26 @@ if scapy.config.conf.iface is None:
scapy.config.conf.iface = LOOPBACK_NAME scapy.config.conf.iface = LOOPBACK_NAME
def get_if_addr6(iff):
"""
Returns the main global unicast address associated with provided
interface, in human readable form. If no global address is found,
None is returned.
"""
for x in in6_getifaddr():
if x[2] == iff and x[1] == IPV6_ADDR_GLOBAL:
return x[0]
return None
def get_if_raw_addr6(iff): def get_if_raw_addr6(iff):
""" """
Returns the main global unicast address associated with provided Returns the main global unicast address associated with provided
interface, in network format. If no global address is found, None interface, in network format. If no global address is found, None
is returned. is returned.
""" """
r = filter(lambda x: x[2] == iff and x[1] == IPV6_ADDR_GLOBAL, in6_getifaddr()) ip6= get_if_addr6(iff)
if len(r) == 0: if ip6 is not None:
return None return inet_pton(socket.AF_INET6, ip6)
else:
r = r[0][0] return None
return inet_pton(socket.AF_INET6, r)
...@@ -8,7 +8,7 @@ Automata with states, transitions and actions. ...@@ -8,7 +8,7 @@ Automata with states, transitions and actions.
""" """
from __future__ import with_statement from __future__ import with_statement
import types,itertools,time,os,sys,socket import types,itertools,time,os,sys,socket,traceback
from select import select from select import select
from collections import deque from collections import deque
import thread import thread
...@@ -429,13 +429,16 @@ class Automaton: ...@@ -429,13 +429,16 @@ class Automaton:
raise self.AutomatonError("INTERCEPT: unkown verdict: %r" % cmd.type) raise self.AutomatonError("INTERCEPT: unkown verdict: %r" % cmd.type)
self.my_send(pkt) self.my_send(pkt)
self.debug(3,"SENT : %s" % pkt.summary()) self.debug(3,"SENT : %s" % pkt.summary())
self.packets.append(pkt.copy())
if self.store_packets:
self.packets.append(pkt.copy())
## Internals ## Internals
def __init__(self, *args, **kargs): def __init__(self, *args, **kargs):
external_fd = kargs.pop("external_fd",{}) external_fd = kargs.pop("external_fd",{})
self.send_sock_class = kargs.pop("ll", conf.L3socket) self.send_sock_class = kargs.pop("ll", conf.L3socket)
self.recv_sock_class = kargs.pop("recvsock", conf.L2listen)
self.started = thread.allocate_lock() self.started = thread.allocate_lock()
self.threadid = None self.threadid = None
self.breakpointed = None self.breakpointed = None
...@@ -493,7 +496,8 @@ class Automaton: ...@@ -493,7 +496,8 @@ class Automaton:
except ATMT.NewStateRequested, state_req: except ATMT.NewStateRequested, state_req:
self.debug(2, "%s [%s] taken to state [%s]" % (cond.atmt_type, cond.atmt_condname, state_req.state)) self.debug(2, "%s [%s] taken to state [%s]" % (cond.atmt_type, cond.atmt_condname, state_req.state))
if cond.atmt_type == ATMT.RECV: if cond.atmt_type == ATMT.RECV:
self.packets.append(args[0]) if self.store_packets:
self.packets.append(args[0])
for action in self.actions[cond.atmt_condname]: for action in self.actions[cond.atmt_condname]:
self.debug(2, " + Running action [%s]" % action.func_name) self.debug(2, " + Running action [%s]" % action.func_name)
action(self, *state_req.action_args, **state_req.action_kargs) action(self, *state_req.action_args, **state_req.action_kargs)
...@@ -522,7 +526,7 @@ class Automaton: ...@@ -522,7 +526,7 @@ class Automaton:
# Start the automaton # Start the automaton
self.state=self.initial_states[0](self) self.state=self.initial_states[0](self)
self.send_sock = self.send_sock_class() self.send_sock = self.send_sock_class()
self.listen_sock = conf.L2listen(**self.socket_kargs) self.listen_sock = self.recv_sock_class(**self.socket_kargs)
self.packets = PacketList(name="session[%s]"%self.__class__.__name__) self.packets = PacketList(name="session[%s]"%self.__class__.__name__)
singlestep = True singlestep = True
...@@ -556,8 +560,9 @@ class Automaton: ...@@ -556,8 +560,9 @@ class Automaton:
c = Message(type=_ATMT_Command.END, result=e.args[0]) c = Message(type=_ATMT_Command.END, result=e.args[0])
self.cmdout.send(c) self.cmdout.send(c)
except Exception,e: except Exception,e:
self.debug(3, "Transfering exception [%s] from tid=%i"% (e,self.threadid)) exc_info = sys.exc_info()
m = Message(type = _ATMT_Command.EXCEPTION, exception=e, exc_info=sys.exc_info()) self.debug(3, "Transfering exception from tid=%i:\n%s"% (self.threadid, traceback.format_exc(exc_info)))
m = Message(type=_ATMT_Command.EXCEPTION, exception=e, exc_info=exc_info)
self.cmdout.send(m) self.cmdout.send(m)
self.debug(3, "Stopping control thread (tid=%i)"%self.threadid) self.debug(3, "Stopping control thread (tid=%i)"%self.threadid)
self.threadid = None self.threadid = None
......
This diff is collapsed.
...@@ -206,40 +206,7 @@ _OSPF_LSclasses = {1: "OSPF_Router_LSA", ...@@ -206,40 +206,7 @@ _OSPF_LSclasses = {1: "OSPF_Router_LSA",
def ospf_lsa_checksum(lsa): def ospf_lsa_checksum(lsa):
""" Fletcher checksum for OSPF LSAs, returned as a 2 byte string. return fletcher16_checkbytes("\x00\x00" + lsa[2:], 16) # leave out age
Give the whole LSA packet as argument.
For details on the algorithm, see RFC 2328 chapter 12.1.7 and RFC 905 Annex B.
"""
# This is based on the GPLed C implementation in Zebra <http://www.zebra.org/>
CHKSUM_OFFSET = 16
if len(lsa) < CHKSUM_OFFSET:
raise Exception("LSA Packet too short (%s bytes)" % len(lsa))
c0 = c1 = 0
# Calculation is done with checksum set to zero
lsa = lsa[:CHKSUM_OFFSET] + "\x00\x00" + lsa[CHKSUM_OFFSET + 2:]
for char in lsa[2:]: # leave out age
c0 += ord(char)
c1 += c0
c0 %= 255
c1 %= 255
x = ((len(lsa) - CHKSUM_OFFSET - 1) * c0 - c1) % 255
if (x <= 0):
x += 255
y = 510 - c0 - x
if (y > 255):
y -= 255
#checksum = (x << 8) + y
return chr(x) + chr(y)
class OSPF_LSA_Hdr(Packet): class OSPF_LSA_Hdr(Packet):
...@@ -456,69 +423,6 @@ class OSPF_LSAck(Packet): ...@@ -456,69 +423,6 @@ class OSPF_LSAck(Packet):
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# OSPFv3 # OSPFv3
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
# TODO: Add length_from / adjust functionality to IP6Field and remove this class
class OspfIP6Field(StrField, IP6Field):
"""
Special IP6Field for prefix fields in OSPFv3 LSAs
"""
def __init__(self, name, default, length=None, length_from=None):
StrField.__init__(self, name, default)
self.length_from = length_from
if length is not None:
self.length_from = lambda pkt, length = length: length
def any2i(self, pkt, x):
return IP6Field.any2i(self, pkt, x)
def i2repr(self, pkt, x):
return IP6Field.i2repr(self, pkt, x)
def h2i(self, pkt, x):
return IP6Field.h2i(self, pkt, x)
def i2m(self, pkt, x):
x = inet_pton(socket.AF_INET6, x)
l = self.length_from(pkt)
l = self.prefixlen_to_bytelen(l)
return x[:l]
def m2i(self, pkt, x):
l = self.length_from(pkt)
prefixlen = self.prefixlen_to_bytelen(l)
if l > 128:
warning("OspfIP6Field: Prefix length is > 128. Dissection of this packet will fail")
else:
pad = "\x00" * (16 - prefixlen)
x += pad
return inet_ntop(socket.AF_INET6, x)
def prefixlen_to_bytelen(self, l):
if l <= 32:
return 4
elif l <= 64:
return 8
elif l <= 96:
return 12
else:
return 16
def i2len(self, pkt, x):
l = self.length_from(pkt)
l = self.prefixlen_to_bytelen(l)
return l
def getfield(self, pkt, s):
l = self.length_from(pkt)
l = self.prefixlen_to_bytelen(l)
return s[l:], self.m2i(pkt, s[:l])
class OSPFv3_Hdr(Packet): class OSPFv3_Hdr(Packet):
name = "OSPFv3 Header" name = "OSPFv3 Header"
fields_desc = [ByteField("version", 3), fields_desc = [ByteField("version", 3),
...@@ -678,10 +582,10 @@ class OSPFv3_Inter_Area_Prefix_LSA(OSPF_BaseLSA): ...@@ -678,10 +582,10 @@ class OSPFv3_Inter_Area_Prefix_LSA(OSPF_BaseLSA):
ShortField("len", None), ShortField("len", None),
ByteField("reserved", 0), ByteField("reserved", 0),
X3BytesField("metric", 10), X3BytesField("metric", 10),
ByteField("prefixlen", 64), FieldLenField("prefixlen", None, length_of="prefix", fmt="B"),
OSPFv3PrefixOptionsField(), OSPFv3PrefixOptionsField(),
ShortField("reserved2", 0), ShortField("reserved2", 0),
OspfIP6Field("prefix", "2001:db8:0:42::", length_from=lambda pkt: pkt.prefixlen)] IP6PrefixField("prefix", "2001:db8:0:42::/64", wordbytes=4, length_from=lambda pkt: pkt.prefixlen)]
class OSPFv3_Inter_Area_Router_LSA(OSPF_BaseLSA): class OSPFv3_Inter_Area_Router_LSA(OSPF_BaseLSA):
...@@ -694,6 +598,8 @@ class OSPFv3_Inter_Area_Router_LSA(OSPF_BaseLSA): ...@@ -694,6 +598,8 @@ class OSPFv3_Inter_Area_Router_LSA(OSPF_BaseLSA):
XShortField("chksum", None), XShortField("chksum", None),
ShortField("len", None), ShortField("len", None),
ByteField("reserved", 0), ByteField("reserved", 0),
OSPFv3OptionsField(),
ByteField("reserved2", 0),
X3BytesField("metric", 1), X3BytesField("metric", 1),
IPField("router", "2.2.2.2")] IPField("router", "2.2.2.2")]
...@@ -709,10 +615,10 @@ class OSPFv3_AS_External_LSA(OSPF_BaseLSA): ...@@ -709,10 +615,10 @@ class OSPFv3_AS_External_LSA(OSPF_BaseLSA):
ShortField("len", None), ShortField("len", None),
FlagsField("flags", 0, 8, ["T", "F", "E"]), FlagsField("flags", 0, 8, ["T", "F", "E"]),
X3BytesField("metric", 20), X3BytesField("metric", 20),
ByteField("prefixlen", 64), FieldLenField("prefixlen", None, length_of="prefix", fmt="B"),
OSPFv3PrefixOptionsField(), OSPFv3PrefixOptionsField(),
ShortEnumField("reflstype", 0, _OSPFv3_LStypes), ShortEnumField("reflstype", 0, _OSPFv3_LStypes),
OspfIP6Field("prefix", "2001:db8:0:42::", length_from=lambda pkt: pkt.prefixlen), IP6PrefixField("prefix", "2001:db8:0:42::/64", wordbytes=4, length_from=lambda pkt: pkt.prefixlen),
ConditionalField(IP6Field("fwaddr", "::"), lambda pkt: pkt.flags & 0x02 == 0x02), ConditionalField(IP6Field("fwaddr", "::"), lambda pkt: pkt.flags & 0x02 == 0x02),
ConditionalField(IntField("tag", 0), lambda pkt: pkt.flags & 0x01 == 0x01), ConditionalField(IntField("tag", 0), lambda pkt: pkt.flags & 0x01 == 0x01),
ConditionalField(IPField("reflsid", 0), lambda pkt: pkt.reflstype != 0)] ConditionalField(IPField("reflsid", 0), lambda pkt: pkt.reflstype != 0)]
...@@ -725,10 +631,10 @@ class OSPFv3_Type_7_LSA(OSPFv3_AS_External_LSA): ...@@ -725,10 +631,10 @@ class OSPFv3_Type_7_LSA(OSPFv3_AS_External_LSA):
class OSPFv3_Prefix_Item(Packet): class OSPFv3_Prefix_Item(Packet):
name = "OSPFv3 Link Prefix Item" name = "OSPFv3 Link Prefix Item"
fields_desc = [ByteField("prefixlen", 64), fields_desc = [FieldLenField("prefixlen", None, length_of="prefix", fmt="B"),
OSPFv3PrefixOptionsField(), OSPFv3PrefixOptionsField(),
ShortField("metric", 10), ShortField("metric", 10),
OspfIP6Field("prefix", "2001:db8:0:42::", length_from=lambda pkt: pkt.prefixlen)] IP6PrefixField("prefix", "2001:db8:0:42::/64", wordbytes=4, length_from=lambda pkt: pkt.prefixlen)]
def extract_padding(self, s): def extract_padding(self, s):
return "", s return "", s
...@@ -746,7 +652,7 @@ class OSPFv3_Link_LSA(OSPF_BaseLSA): ...@@ -746,7 +652,7 @@ class OSPFv3_Link_LSA(OSPF_BaseLSA):
ByteField("prio", 1), ByteField("prio", 1),
OSPFv3OptionsField(), OSPFv3OptionsField(),
IP6Field("lladdr", "fe80::"), IP6Field("lladdr", "fe80::"),
IntField("prefixes", 0), FieldLenField("prefixes", None, count_of="prefixlist", fmt="I"),
PacketListField("prefixlist", None, OSPFv3_Prefix_Item, PacketListField("prefixlist", None, OSPFv3_Prefix_Item,
count_from = lambda pkt: pkt.prefixes)] count_from = lambda pkt: pkt.prefixes)]
...@@ -760,7 +666,7 @@ class OSPFv3_Intra_Area_Prefix_LSA(OSPF_BaseLSA): ...@@ -760,7 +666,7 @@ class OSPFv3_Intra_Area_Prefix_LSA(OSPF_BaseLSA):
XIntField("seq", 0x80000001), XIntField("seq", 0x80000001),
XShortField("chksum", None), XShortField("chksum", None),
ShortField("len", None), ShortField("len", None),
ShortField("prefixes", 0), FieldLenField("prefixes", None, count_of="prefixlist", fmt="H"),
ShortEnumField("reflstype", 0, _OSPFv3_LStypes), ShortEnumField("reflstype", 0, _OSPFv3_LStypes),
IPField("reflsid", "0.0.0.0"), IPField("reflsid", "0.0.0.0"),
IPField("refadrouter", "0.0.0.0"), IPField("refadrouter", "0.0.0.0"),
......
...@@ -412,7 +412,10 @@ class PacketListField(PacketField): ...@@ -412,7 +412,10 @@ class PacketListField(PacketField):
def i2len(self, pkt, val): def i2len(self, pkt, val):
return sum( len(p) for p in val ) return sum( len(p) for p in val )
def do_copy(self, x): def do_copy(self, x):
return map(lambda p:p.copy(), x) if x is None:
return None
else:
return map(lambda p:p.copy(), x)
def getfield(self, pkt, s): def getfield(self, pkt, s):
c = l = None c = l = None
if self.length_from is not None: if self.length_from is not None:
...@@ -509,16 +512,25 @@ class StrLenField(StrField): ...@@ -509,16 +512,25 @@ class StrLenField(StrField):
def getfield(self, pkt, s): def getfield(self, pkt, s):
l = self.length_from(pkt) l = self.length_from(pkt)
return s[l:], self.m2i(pkt,s[:l]) return s[l:], self.m2i(pkt,s[:l])
class BoundStrLenField(StrLenField):
def __init__(self,name, default, minlen= 0, maxlen= 255, fld=None, length_from=None):
StrLenField.__init__(self, name, default, fld, length_from)
self.minlen= minlen
self.maxlen= maxlen
def randval(self):
return RandBin(RandNum(self.minlen, self.maxlen))
class FieldListField(Field): class FieldListField(Field):
islist=1 islist=1
def __init__(self, name, default, field, length_from=None, count_from=None): def __init__(self, name, default, field, length_from=None, count_from=None):
if default is None: if default is None:
default = [] # Create a new list for each instance default = [] # Create a new list for each instance
self.field = field
Field.__init__(self, name, default) Field.__init__(self, name, default)
self.count_from = count_from self.count_from = count_from
self.length_from = length_from self.length_from = length_from
self.field = field
def i2count(self, pkt, val): def i2count(self, pkt, val):
if type(val) is list: if type(val) is list:
...@@ -533,9 +545,11 @@ class FieldListField(Field): ...@@ -533,9 +545,11 @@ class FieldListField(Field):
return val return val
def any2i(self, pkt, x): def any2i(self, pkt, x):
if type(x) is not list: if type(x) is not list:
return [x] return [self.field.any2i(pkt, x)]
else: else:
return x return map(lambda e, pkt=pkt: self.field.any2i(pkt, e), x)
def i2repr(self, pkt, x):
return map(lambda e, pkt=pkt: self.field.i2repr(pkt,e), x)
def addfield(self, pkt, s, val): def addfield(self, pkt, s, val):
val = self.i2m(pkt, val) val = self.i2m(pkt, val)
for v in val: for v in val:
...@@ -916,3 +930,76 @@ class FixedPointField(BitField): ...@@ -916,3 +930,76 @@ class FixedPointField(BitField):
return int_part+frac_part return int_part+frac_part
def i2repr(self, pkt, val): def i2repr(self, pkt, val):
return self.i2h(pkt, val) return self.i2h(pkt, val)
# Base class for IPv4 and IPv6 Prefixes inspired by IPField and IP6Field.
# Machine values are encoded in a multiple of wordbytes bytes.
class _IPPrefixFieldBase(Field):
def __init__(self, name, default, wordbytes, maxbytes, aton, ntoa, length_from):
self.wordbytes= wordbytes
self.maxbytes= maxbytes
self.aton= aton
self.ntoa= ntoa
Field.__init__(self, name, default, "%is" % self.maxbytes)
self.length_from= length_from
def _numbytes(self, pfxlen):
wbits= self.wordbytes * 8
return ((pfxlen + (wbits - 1)) / wbits) * self.wordbytes
def h2i(self, pkt, x):
# "fc00:1::1/64" -> ("fc00:1::1", 64)
[pfx,pfxlen]= x.split('/')
self.aton(pfx) # check for validity
return (pfx, int(pfxlen))
def i2h(self, pkt, x):
# ("fc00:1::1", 64) -> "fc00:1::1/64"
(pfx,pfxlen)= x
return "%s/%i" % (pfx,pfxlen)
def i2m(self, pkt, x):
# ("fc00:1::1", 64) -> ("\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64)
(pfx,pfxlen)= x
s= self.aton(pfx);
return (s[:self._numbytes(pfxlen)], pfxlen)
def m2i(self, pkt, x):
# ("\xfc\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 64) -> ("fc00:1::1", 64)
(s,pfxlen)= x
if len(s) < self.maxbytes:
s= s + ("\0" * (self.maxbytes - len(s)))
return (self.ntoa(s), pfxlen)
def any2i(self, pkt, x):
if x is None:
return (self.ntoa("\0"*self.maxbytes), 1)
return self.h2i(pkt,x)
def i2len(self, pkt, x):
(_,pfxlen)= x
return pfxlen
def addfield(self, pkt, s, val):
(rawpfx,pfxlen)= self.i2m(pkt,val)
fmt= "!%is" % self._numbytes(pfxlen)
return s+struct.pack(fmt, rawpfx)
def getfield(self, pkt, s):
pfxlen= self.length_from(pkt)
numbytes= self._numbytes(pfxlen)
fmt= "!%is" % numbytes
return s[numbytes:], self.m2i(pkt, (struct.unpack(fmt, s[:numbytes])[0], pfxlen))
class IPPrefixField(_IPPrefixFieldBase):
def __init__(self, name, default, wordbytes=1, length_from= None):
_IPPrefixFieldBase.__init__(self, name, default, wordbytes, 4, inet_aton, inet_ntoa, length_from)
class IP6PrefixField(_IPPrefixFieldBase):
def __init__(self, name, default, wordbytes= 1, length_from= None):
_IPPrefixFieldBase.__init__(self, name, default, wordbytes, 16, lambda a: inet_pton(socket.AF_INET6, a), lambda n: inet_ntop(socket.AF_INET6, n), length_from)
\ No newline at end of file
"""
CLNS Extension
~~~~~~~~~~~~~~~~~~~~~
:copyright: 2014 BENOCS GmbH, Berlin (Germany)
:author: Marcel Patzlaff, mpatzlaff@benocs.com
:license: GPLv2
This module is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This module is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
:description:
This module provides a layer and registration function for
OSI Connectionless-mode Network Services (such as IS-IS).
:TODO:
- rework this if a better way is found/implemented to bind
protocols such as IS-IS (or if IS-IS remains the sole CLN
protocol)
"""
import struct
from scapy.config import conf
from scapy.fields import ByteEnumField, PacketField
from scapy.layers.l2 import LLC
from scapy.packet import Packet, bind_layers
network_layer_protocol_ids= {
0x00 : "Null",
0x08 : "Q.933",
0x80 : "IEEE SNAP",
0x81 : "ISO 8438 CLNP",
0x82 : "ISO 9542 ES-IS",
0x83 : "ISO 10589 IS-IS",
0x8E : "IPv6",
0xB0 : "FRF.9",
0xB1 : "FRF.12",
0xC0 : "TRILL",
0xC1 : "IEEE 802.aq",
0xCC : "IPv4",
0xCF : "PPP"
}
_cln_protocols= {}
class _GenericClnsPdu(Packet):
name= "Generic CLNS PDU"
fields_desc= [
ByteEnumField("nlpid", 0x00, network_layer_protocol_ids),
PacketField("rawdata", None, conf.raw_layer)
]
class ConnectionlessNetworkService(Packet):
name= "Connectionless-mode Network Service"
def guess_payload_class(self, p):
cls= conf.raw_layer
if len(p) >= 1:
nlpid = struct.unpack("!B", p[0])[0]
cls= _cln_protocols.get(nlpid, _GenericClnsPdu)
return cls
@conf.commands.register
def register_cln_protocol(nlpid, cln_protocol_class):
if nlpid is None or cln_protocol_class is None:
return
_cln_protocols[nlpid]= cln_protocol_class
bind_layers(LLC, ConnectionlessNetworkService, dsap=0xfe, ssap=0xfe, ctrl=3)
\ No newline at end of file
...@@ -237,6 +237,60 @@ else: ...@@ -237,6 +237,60 @@ else:
s = ~s s = ~s
return (((s>>8)&0xff)|s<<8) & 0xffff return (((s>>8)&0xff)|s<<8) & 0xffff
def _fletcher16(charbuf):
# This is based on the GPLed C implementation in Zebra <http://www.zebra.org/>
c0 = c1 = 0
for char in charbuf:
c0 += ord(char)
c1 += c0
c0 %= 255
c1 %= 255
return (c0,c1)
@conf.commands.register
def fletcher16_checksum(binbuf):
""" Calculates Fletcher-16 checksum of the given buffer.
Note:
If the buffer contains the two checkbytes derived from the Fletcher-16 checksum
the result of this function has to be 0. Otherwise the buffer has been corrupted.
"""
(c0,c1)= _fletcher16(binbuf)
return (c1 << 8) | c0
@conf.commands.register
def fletcher16_checkbytes(binbuf, offset):
""" Calculates the Fletcher-16 checkbytes returned as 2 byte binary-string.
Including the bytes into the buffer (at the position marked by offset) the
global Fletcher-16 checksum of the buffer will be 0. Thus it is easy to verify
the integrity of the buffer on the receiver side.
For details on the algorithm, see RFC 2328 chapter 12.1.7 and RFC 905 Annex B.
"""
# This is based on the GPLed C implementation in Zebra <http://www.zebra.org/>
if len(binbuf) < offset:
raise Exception("Packet too short for checkbytes %d" % len(binbuf))
binbuf = binbuf[:offset] + "\x00\x00" + binbuf[offset + 2:]
(c0,c1)= _fletcher16(binbuf)
x = ((len(binbuf) - offset - 1) * c0 - c1) % 255
if (x <= 0):
x += 255
y = 510 - c0 - x
if (y > 255):
y -= 255
return chr(x) + chr(y)
def warning(x): def warning(x):
log_runtime.warning(x) log_runtime.warning(x)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment