The Assimilation Project  based on Assimilation version 1.1.7.1474836767
AssimCclasses.py
Go to the documentation of this file.
1 # pylint: disable=C0302
2 # vim: smartindent tabstop=4 shiftwidth=4 expandtab number colorcolumn=100
3 #C0302: too many lines in module
4 #
5 #
6 # This file is part of the Assimilation Project.
7 #
8 # Copyright (C) 2011, 2012 - Alan Robertson <alanr@unix.sh>
9 #
10 # The Assimilation software is free software: you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation, either version 3 of the License, or
13 # (at your option) any later version.
14 #
15 # The Assimilation software is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with the Assimilation Project software. If not, see http://www.gnu.org/licenses/
22 #
23 #
24 #pylint: disable=C0302,W0212
25 '''
26 A collection of classes which wrap our @ref C-Classes and provide Pythonic interfaces
27 to these C-classes.
28 '''
29 import collections
30 import traceback, types
31 import sys, gc
32 import AssimCtypes
33 from AssimCtypes import POINTER, cast, addressof, pointer, string_at, create_string_buffer, \
34  c_char_p, byref, memmove, c_int, badfree, \
35  g_free, GSList, GDestroyNotify, g_slist_length, g_slist_next, struct__GSList, \
36  g_slist_free, \
37  MALLOC, \
38  FRAMETYPE_SIG, \
39  Frame, AssimObj, NetAddr, SeqnoFrame, ReliableUDP, \
40  frame_new, addrframe_new, \
41  nvpairframe_new, frameset_new, frameset_append_frame, frameset_prepend_frame, \
42  seqnoframe_new, cstringframe_new, unknownframe_new, \
43  ipportframe_netaddr_new, ipportframe_ipv4_new, ipportframe_ipv6_new, \
44  frameset_construct_packet, frameset_get_flags, frameset_set_flags, frameset_clear_flags, \
45  frameset_dump, frameset_sender_key_id, frameset_sender_identity, \
46  LLDP_TLV_END, LLDP_TLV_CHID, LLDP_TLV_PID, LLDP_TLV_TTL, LLDP_TLV_PORT_DESCR, \
47  LLDP_TLV_SYS_NAME, LLDP_TLV_SYS_DESCR, LLDP_TLV_SYS_CAPS, LLDP_TLV_MGMT_ADDR, \
48  LLDP_TLV_ORG_SPECIFIC, \
49  LLDP_ORG802_1_VLAN_PVID, LLDP_ORG802_1_VLAN_PORTPROTO, LLDP_ORG802_1_VLAN_NAME, \
50  LLDP_ORG802_1_VLAN_PROTOID, LLDP_ORG802_3_PHY_CONFIG, LLDP_ORG802_3_POWERVIAMDI, \
51  LLDP_ORG802_3_LINKAGG, LLDP_ORG802_3_MTU, \
52  LLDP_PIDTYPE_ALIAS, LLDP_PIDTYPE_IFNAME, LLDP_PIDTYPE_LOCAL, LLDP_CHIDTYPE_ALIAS, \
53  LLDP_CHIDTYPE_IFNAME, LLDP_CHIDTYPE_LOCAL, LLDP_CHIDTYPE_MACADDR, \
54  LLDP_CHIDTYPE_COMPONENT, LLDP_CHIDTYPE_NETADDR, \
55  CDP_TLV_DEVID, CDP_TLV_ADDRESS, CDP_TLV_PORTID, CDP_TLV_CAPS, CDP_TLV_VERS, CDP_TLV_POWER, \
56  CDP_TLV_PLATFORM, CDP_TLV_MTU, CDP_TLV_SYSTEM_NAME, CDP_TLV_MANAGEMENT_ADDR, CDP_TLV_DUPLEX, \
57  CDP_TLV_LOCATION, CDP_TLV_EXT_PORTID, CDP_TLV_NATIVEVLAN, CDP_TLV_VLREPLY, CDP_TLV_VLQUERY, \
58  CDP_TLV_VTPDOMAIN, CDP_TLV_TRUST_BITMAP, CDP_TLV_UNTRUSTED_COS, CDP_TLV_HELLO, \
59  ADDR_FAMILY_IPV4, ADDR_FAMILY_IPV6, ADDR_FAMILY_802, \
60  is_valid_lldp_packet, is_valid_cdp_packet, \
61  netaddr_ipv4_new, netaddr_ipv6_new, netaddr_dns_new, netaddr_mac48_new, netaddr_mac64_new, \
62  proj_class_classname, \
63  assimobj_new, intframe_new, signframe_glib_new, packetdecoder_new, configcontext_new, \
64  configcontext_new_JSON_string, netio_new, netioudp_new, reliableudp_new,\
65  netio_is_dual_ipv4v6_stack, create_setconfig, create_sendexpecthb, \
66  get_lldptlv_type, \
67  get_lldptlv_len, \
68  get_lldptlv_body, \
69  get_lldptlv_first, \
70  get_lldptlv_next, \
71  get_cdptlv_type, \
72  get_cdptlv_len, \
73  get_cdptlv_body, \
74  get_cdptlv_first, \
75  get_cdptlv_next, \
76  pcap_capture_iter_new, pcap_capture_iter_del, pcap_capture_iter_next, \
77  tlv_get_guint8, tlv_get_guint16, tlv_get_guint24, tlv_get_guint32, tlv_get_guint64, \
78  CFG_EEXIST, CFG_CFGCTX, CFG_STRING, CFG_NETADDR, CFG_FRAME, CFG_INT64, CFG_ARRAY, \
79  CFG_FLOAT, CFG_BOOL, DEFAULT_FSP_QID, CFG_NULL, CMA_IDENTITY_NAME, \
80  COMPRESS_ZLIB, FRAMETYPE_COMPRESS, compressframe_new_string, \
81  cryptframe_associate_identity, cryptframe_set_dest_key_id, cryptframe_whois_key_id, \
82  cryptframe_get_dest_key_id, \
83  cryptframe_new_by_destaddr, cryptframe_get_key_ids, cryptframe_set_signing_key_id, \
84  cryptframe_private_key_by_id, cryptcurve25519_set_encryption_method, \
85  cryptcurve25519_cache_all_keypairs, CMA_KEY_PREFIX, curve25519_key_id_to_filename, \
86  cryptcurve25519_gen_persistent_keypair, cryptcurve25519_new, FRAMETYPE_CRYPTCURVE25519, \
87  proj_class_live_object_count, proj_class_dump_live_objects
88 from consts import CMAconsts
89 from frameinfo import FrameTypes, FrameSetTypes
90 
91 
92 #pylint: disable=R0903
93 class cClass(object):
94  'Just a handy collection of POINTER() objects'
95  def __init__(self):
96  pass
97  NetAddr = POINTER(AssimCtypes.NetAddr)
98  Frame = POINTER(AssimCtypes.Frame)
99  AddrFrame = POINTER(AssimCtypes.AddrFrame)
100  IntFrame = POINTER(AssimCtypes.IntFrame)
101  SeqnoFrame = POINTER(AssimCtypes.SeqnoFrame)
102  CstringFrame = POINTER(AssimCtypes.CstringFrame)
103  UnknownFrame = POINTER(AssimCtypes.UnknownFrame)
104  SignFrame = POINTER(AssimCtypes.SignFrame)
105  FrameSet = POINTER(AssimCtypes.FrameSet)
106  ConfigContext = POINTER(AssimCtypes.ConfigContext)
107  ConfigValue = POINTER(AssimCtypes.ConfigValue)
108  IpPortFrame = POINTER(AssimCtypes.IpPortFrame)
109  CompressFrame = POINTER(AssimCtypes.CompressFrame)
110  guint8 = POINTER(AssimCtypes.guint8)
111  GSList = POINTER(AssimCtypes.GSList)
112  CryptCurve25519 = POINTER(AssimCtypes.CryptCurve25519)
113 
114 #pylint: disable=C0123
115 def not_this_exact_type(obj, cls):
116  '''Do return True if this is NOT the given type.
117  This is necessary for dealing with Ctypes, but pylint hates this construct
118  so we ignore its warning.
119  '''
120  return type(obj) is not cls
121 
122 def CCref(obj):
123  '''
124  Increment the reference count to an AssimObj (_not_ a pyAssimObj)
125  Need to call CCref under the following circumstances:
126  When we are creating an object that points to another underlying C-class object
127  which already has a permanent reference to it somewhere else
128  For example, if we're returning a pyNetAddr object that points to a NetAddr object
129  that's in a ConfigContext object. If we don't, then when our pyNetAddr object goes
130  out of scope, then the underlying NetAddr object will be freed, even though there's
131  a reference to it in the ConfigContext object. Conversely, if the ConfigContext
132  object goes out of scope first, then the our pyNetAddr object could become invalid.
133 
134  Do not call it when you've constructed a new object that there were no previous pointers
135  to.
136  '''
137  base = obj[0]
138  while not_this_exact_type(base, AssimObj):
139  base = base.baseclass
140  base.ref(obj)
141 
142 def CCunref(obj):
143  'Unref an AssimObj object (or subclass)'
144  base = obj[0]
145  # This 'hasattr' construct only works because we are the base C-class
146  while hasattr(base, 'baseclass'):
147  base = base.baseclass
148  base.unref(obj)
149 
150 class pySwitchDiscovery(object):
151  '''
152  Class for interpreting switch discovery data via LLDP or CDP
153  Currently only LLDP is fully implemented.
154  '''
155  lldpnames = {
156  LLDP_TLV_END: ('END', True),
157  LLDP_TLV_CHID: ('ChassisId', True),
158  LLDP_TLV_PID: ('PortId', True),
159  LLDP_TLV_TTL: ('TTL', True),
160  LLDP_TLV_PORT_DESCR: ('PortDescription', False),
161  LLDP_TLV_SYS_NAME: ('SystemName', True),
162  LLDP_TLV_SYS_DESCR: ('SystemDescription', True),
163  LLDP_TLV_SYS_CAPS: ('SystemCapabilities', True),
164  LLDP_TLV_MGMT_ADDR: ('ManagementAddress', True),
165  LLDP_TLV_ORG_SPECIFIC: ('(OrgSpecific)', True),
166  }
167  lldp802_1names = {
168  LLDP_ORG802_1_VLAN_PVID: ('VlanPvId', False),
169  LLDP_ORG802_1_VLAN_PORTPROTO: ('VlanPortProtocol', False),
170  LLDP_ORG802_1_VLAN_NAME: ('VlanName', False),
171  LLDP_ORG802_1_VLAN_PROTOID: ('VlanProtocolId', False),
172  }
173  lldp802_3names = {
174  LLDP_ORG802_3_PHY_CONFIG: ('PhysicalConfiguration', False),
175  LLDP_ORG802_3_POWERVIAMDI: ('PowerViaMDI', False),
176  LLDP_ORG802_3_LINKAGG: ('LinkAggregation', False),
177 
178  }
179 
180  cdpnames = {
181  # System-wide capabilities
182  CDP_TLV_DEVID: ('ChassisId', True),
183  CDP_TLV_CAPS: ('SystemCapabilities', True),
184  CDP_TLV_VERS: ('SystemVersion', True),
185  CDP_TLV_PLATFORM: ('SystemPlatform', True),
186  CDP_TLV_VTPDOMAIN: ('VLANManagementDomain', True),
187  CDP_TLV_ADDRESS: ('SystemAddress', True),
188  CDP_TLV_MANAGEMENT_ADDR: ('ManagementAddress', True),
189  CDP_TLV_SYSTEM_NAME: ('SystemName', True),
190  CDP_TLV_LOCATION: ('SystemDescription', True),
191  CDP_TLV_HELLO: ('CiscoHello', True),
192  # Per-port capabilities follow
193  CDP_TLV_TRUST_BITMAP: ('CiscoTrustBitMap', False),
194  CDP_TLV_UNTRUSTED_COS: ('CiscoUnTrustedPortCOS', False),
195  CDP_TLV_NATIVEVLAN: ('VlanId', False),
196  CDP_TLV_VLQUERY: ('VlanQuery', False),
197  CDP_TLV_VLREPLY: ('VlanReply', False),
198  CDP_TLV_PORTID: ('PortId', False),
199  CDP_TLV_EXT_PORTID: ('PortDescription', False),
200  CDP_TLV_DUPLEX: ('duplex', False),
201  CDP_TLV_MTU: ('mtu', False),
202  CDP_TLV_POWER: ('PortPower', False),
203  }
204 
205  def __init__(self):
206  pass
207 
208  @staticmethod
209  def _byte0(pktstart):
210  'Return the first (zeroth) byte from a memory blob'
211  return int(cast(pktstart, cClass.guint8)[0])
212 
213  @staticmethod
214  def _byte1addr(pktstart):
215  'Return the address of byte 1 in a memory blob'
216  addr = addressof(pktstart.contents) + 1
217  return pointer(type(pktstart.contents).from_address(addr))
218 
219  @staticmethod
220  def _byteN(pktstart, n):
221  'Return the Nth byte from a memory blob'
222  return int(cast(pktstart, cClass.guint8)[n])
223 
224  @staticmethod
225  def _byteNaddr(pktstart, n):
226  'Return the address of the Nth byte in a memory blob'
227  addr = addressof(pktstart.contents) + n
228  return pointer(type(pktstart.contents).from_address(addr))
229 
230  @staticmethod
231  def _decode_netaddr(addrstart, addrlen):
232  'Return an appropriate pyNetAddr object corresponding to the given memory blob'
233  byte0 = pySwitchDiscovery._byte0(addrstart)
234  byte1addr = pySwitchDiscovery._byte1addr(addrstart)
235  Cnetaddr = None
236  if byte0 == ADDR_FAMILY_IPV6:
237  if addrlen != 17:
238  return None
239  Cnetaddr = netaddr_ipv6_new(byte1addr, 0)
240  elif byte0 == ADDR_FAMILY_IPV4:
241  if addrlen != 5:
242  return None
243  Cnetaddr = netaddr_ipv4_new(byte1addr, 0)
244  elif byte0 == ADDR_FAMILY_802:
245  if addrlen == 7:
246  Cnetaddr = netaddr_mac48_new(byte1addr)
247  elif addrlen == 9:
248  Cnetaddr = netaddr_mac64_new(byte1addr)
249  if Cnetaddr is not None:
250  return str(pyNetAddr(None, Cstruct=Cnetaddr))
251  return None
252 
253  @staticmethod
254  def decode_discovery(host, interface, instance, wallclock, pktstart, pktend):
255  'Return a JSON packet corresponding to the given switch discovery packet'
256 
257  if is_valid_lldp_packet(pktstart, pktend):
258  #print >> sys.stderr, '>>>>>>>>>>>>>>>LLDP PACKET'
259  return pySwitchDiscovery._decode_lldp(host, interface, instance,
260  wallclock, pktstart, pktend)
261 
262  if is_valid_cdp_packet(pktstart, pktend):
263  #print >> sys.stderr, '>>>>>>>>>>>>>>>CDP PACKET'
264  return pySwitchDiscovery._decode_cdp(host, interface, instance,
265  wallclock, pktstart, pktend)
266  raise ValueError('Malformed Switch Discovery Packet')
267 
268  @staticmethod
269  def _decode_lldp_chid(tlvptr, tlvlen):
270  'Decode the LLDP CHID field, and return an appropriate value'
271  chidtype = pySwitchDiscovery._byte0(tlvptr)
272 
273  if (chidtype == LLDP_CHIDTYPE_COMPONENT or chidtype == LLDP_CHIDTYPE_ALIAS
274  or chidtype == LLDP_CHIDTYPE_IFNAME or chidtype == LLDP_CHIDTYPE_LOCAL):
275  sloc = pySwitchDiscovery._byte1addr(tlvptr)
276  return string_at(sloc, tlvlen-1)
277  elif chidtype == LLDP_CHIDTYPE_MACADDR:
278  byte1addr = pySwitchDiscovery._byte1addr(tlvptr)
279  Cmacaddr = None
280  if tlvlen == 7:
281  Cmacaddr = netaddr_mac48_new(byte1addr)
282  elif tlvlen == 9:
283  Cmacaddr = netaddr_mac64_new(byte1addr)
284  if Cmacaddr is not None:
285  return pyNetAddr(None, Cstruct=Cmacaddr)
286  elif chidtype == LLDP_CHIDTYPE_NETADDR:
287  byte1addr = pySwitchDiscovery._byte1addr(tlvptr)
288  return pySwitchDiscovery._decode_netaddr(byte1addr, tlvlen-1)
289  return None
290 
291  #pylint: disable=R0914,R0912
292  @staticmethod
293  def _decode_lldp(host, interface, instance, wallclock, pktstart, pktend):
294  'Decode LLDP packet into a JSON discovery packet'
295  #print >> sys.stderr, 'DECODING LLDP PACKET!<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'
296  thisportinfo = pyConfigContext(init={
297  'ConnectsToHost': host,
298  'ConnectsToInterface': interface,
299  }
300  )
301  switchinfo = pyConfigContext(init={'ports': pyConfigContext()})
302  metadata = pyConfigContext(init={
303  'discovertype': '__LinkDiscovery',
304  'description': 'Link Level Switch Discovery (lldp)',
305  'source': '_decode_lldp()',
306  'host': host,
307  'instance': instance,
308  'localtime': str(wallclock),
309  'data': switchinfo,
310  }
311  )
312  capnames = [None,
313  CMAconsts.ROLE_repeater,
314  CMAconsts.ROLE_bridge,
315  CMAconsts.ROLE_AccessPoint,
316  CMAconsts.ROLE_router,
317  CMAconsts.ROLE_phone,
318  CMAconsts.ROLE_DOCSIS,
319  CMAconsts.ROLE_Station
320  ]
321 
322  sourcemacptr = pySwitchDiscovery._byteNaddr(cast(pktstart, cClass.guint8), 6)
323  if not sourcemacptr:
324  return metadata
325  Cmacaddr = netaddr_mac48_new(sourcemacptr)
326  sourcemac = pyNetAddr(None, Cstruct=Cmacaddr)
327 
328 
329  this = get_lldptlv_first(pktstart, pktend)
330  while this and this < pktend:
331  tlvtype = get_lldptlv_type(this, pktend)
332  tlvlen = get_lldptlv_len(this, pktend)
333  tlvptr = cast(get_lldptlv_body(this, pktend), cClass.guint8)
334  value = None
335  if tlvtype not in pySwitchDiscovery.lldpnames:
336  print >> sys.stderr, 'Cannot find tlvtype %d' % tlvtype
337  tlvtype = None
338  else:
339  (tlvname, isswitchinfo) = pySwitchDiscovery.lldpnames[tlvtype]
340 
341  if (tlvtype == LLDP_TLV_PORT_DESCR or tlvtype == LLDP_TLV_SYS_NAME or
342  tlvtype == LLDP_TLV_SYS_DESCR): #########################################
343  value = string_at(tlvptr, tlvlen)
344 
345  elif tlvtype == LLDP_TLV_PID: ###############################################
346  pidtype = pySwitchDiscovery._byte0(tlvptr)
347  if (pidtype == LLDP_PIDTYPE_ALIAS or pidtype == LLDP_PIDTYPE_IFNAME
348  or pidtype == LLDP_PIDTYPE_LOCAL):
349  sloc = pySwitchDiscovery._byte1addr(tlvptr)
350  value = string_at(sloc, tlvlen-1)
351 
352  elif tlvtype == LLDP_TLV_CHID: #############################################
353  value = pySwitchDiscovery._decode_lldp_chid(tlvptr, tlvlen)
354 
355  elif tlvtype == LLDP_TLV_MGMT_ADDR: #########################################
356  addrlen = pySwitchDiscovery._byte0(tlvptr)
357  byte1addr = pySwitchDiscovery._byte1addr(tlvptr)
358  value = pySwitchDiscovery._decode_netaddr(byte1addr, addrlen)
359 
360  elif tlvtype == LLDP_TLV_SYS_CAPS: #########################################
361  byte0 = pySwitchDiscovery._byte0(tlvptr)
362  byte1 = pySwitchDiscovery._byteN(tlvptr, 1)
363  byte2 = pySwitchDiscovery._byteN(tlvptr, 2)
364  byte3 = pySwitchDiscovery._byteN(tlvptr, 3)
365  caps0 = (byte0 << 8 | byte1)
366  caps1 = (byte2 << 8 | byte3)
367  # The values we assign here have many possibilities
368  # pylint: disable=R0204
369  value = pyConfigContext()
370  mask = 2
371  for j in range(1, 7):
372  if caps0 & mask:
373  value[capnames[j]] = ((caps1 & mask) != 0)
374  mask <<= 1
375 
376  elif tlvtype == LLDP_TLV_ORG_SPECIFIC: ######################################
377  pySwitchDiscovery._decode_lldp_org_specific(switchinfo, thisportinfo,
378  tlvptr, tlvlen, pktend)
379 
380  if value is not None:
381  if tlvtype == LLDP_TLV_PID:
382  switchinfo['ports'][value] = thisportinfo
383  thisportinfo['PortId'] = value
384  numericpart = value
385  while len(numericpart) > 0 and not numericpart.isdigit():
386  numericpart = numericpart[1:]
387  #if len > 0 and numericpart.isdigit():
388  # thisportinfo['PORTNUM'] = int(numericpart)
389  else:
390  if isswitchinfo:
391  switchinfo[tlvname] = value
392  else:
393  thisportinfo[tlvname] = value
394  this = get_lldptlv_next(this, pktend)
395  thisportinfo['sourceMAC'] = sourcemac
396  return metadata
397  @staticmethod
398  def _dump_c_bytes(prefix, tlvstart, tlvlen):
399  '''Dump out data from a given C-style address'''
400  dump = "%s: DUMP (%d bytes):" % (prefix, tlvlen)
401  for offset in range(0, tlvlen):
402  dump += ' %02x' % pySwitchDiscovery._byteN(tlvstart, offset)
403  print >> sys.stderr, dump
404 
405  @staticmethod
406  def _decode_lldp_org_specific(switchinfo, thisportinfo, tlvptr, tlvlen, pktend):
407  '''Decode LLDP org-specific TLV sets (or not...)'''
408  oui = tlv_get_guint24(tlvptr, pktend)
409  #print >> sys.stderr, 'ORG_OUI: 0x%06x' % oui
410  tlv3ptr = pySwitchDiscovery._byteNaddr(tlvptr, 3)
411  if oui == 0x0080c2:
412  pySwitchDiscovery._decode_lldp_802_1(switchinfo, thisportinfo,
413  tlv3ptr, tlvlen-3, pktend)
414  elif oui == 0x00120f:
415  pySwitchDiscovery._decode_lldp_802_3(switchinfo, thisportinfo,
416  tlv3ptr, tlvlen-3, pktend)
417  elif oui == 0x0012bb:
418  pySwitchDiscovery._decode_lldp_med(switchinfo, thisportinfo,
419  tlv3ptr, tlvlen-3, pktend)
420  elif oui == 0x00ceff:
421  pySwitchDiscovery._decode_lldp_profibus(switchinfo, thisportinfo,
422  tlv3ptr, tlvlen-3, pktend)
423  elif oui == 0x00cecf:
424  pySwitchDiscovery._decode_lldp_hytec(switchinfo, thisportinfo,
425  tlv3ptr, tlvlen-3, pktend)
426  else:
427  print >> sys.stderr, (
428  'Ignored %d bytes of unknown LLDP org-specific extensions. OUI: %06x.'
429  % (tlvlen, oui))
430 
431  @staticmethod
432  def _decode_lldp_802_1(_switchinfo, thisportinfo, tlvptr, tlvlen, pktend):
433  '''Decode 802.1 LLDP org-specific TLV sets (or not...)'''
434  subtype = pySwitchDiscovery._byte0(tlvptr)
435  tlvstart = pySwitchDiscovery._byte1addr(tlvptr)
436  if subtype == 1:
437  thisportinfo['pvid'] = tlv_get_guint16(tlvstart, pktend)
438  elif subtype == 2:
439  ppstatus = pySwitchDiscovery._byte0(tlvstart)
440  thisportinfo['pp_vlan_capable'] = ((ppstatus & 2) == 2)
441  thisportinfo['pp_vlan_enabled'] = ((ppstatus & 4) == 4)
442  thisportinfo['ppvid'] = tlv_get_guint16(
443  pySwitchDiscovery._byte1addr(tlvstart), pktend)
444  elif subtype == 3:
445  vlannameaddr = pySwitchDiscovery._byteNaddr(tlvptr, 3)
446  namelen = pySwitchDiscovery._byte0(vlannameaddr)
447  if namelen != tlvlen - 4:
448  print >> sys.stderr, 'F.4: invalid name length %s out of total of %s' % (namelen,
449  tlvlen)
450  pySwitchDiscovery._dump_c_bytes('PACKET:' , tlvptr, tlvlen)
451  else:
452  thisportinfo['vid'] = tlv_get_guint16(tlvstart, pktend)
453  thisportinfo['vlan_name'] = string_at(pySwitchDiscovery._byte1addr(vlannameaddr),
454  namelen).strip()
455  else:
456  print >> sys.stderr, (
457  'Ignored %d bytes of LLDP 802.1 extensions (Annex F, subtype %d).'
458  % (tlvlen, subtype))
459 
460  @staticmethod
461  def _decode_lldp_802_3(switchinfo, thisportinfo, tlvptr, tlvlen, pktend):
462  '''Decode 802.3 LLDP org-specific TLV sets (or not...)'''
463  subtype = pySwitchDiscovery._byte0(tlvptr)
464  if subtype == 1:
465  pySwitchDiscovery._decode_lldp_802_3_mac_phy(switchinfo, thisportinfo,
466  pySwitchDiscovery._byte1addr(tlvptr), tlvlen-1, pktend)
467  return
468  if subtype == LLDP_ORG802_3_MTU: # G.5: Maximum Frame Size TLV (4)
469  mtuaddr = pySwitchDiscovery._byte1addr(tlvptr)
470  thisportinfo['mtu'] = tlv_get_guint16(mtuaddr, pktend)
471  return
472  print >> sys.stderr, (
473  'Ignored %d bytes of LLDP 802.3 extensions (Annex G, subtype %d).'
474  % (tlvlen, subtype))
475 
476  @staticmethod
477  def dot3MauTypes(mautype):
478  '''MAU types and characteristics from RFC 3636 - starting at page 9
479  The LLDP spec says that MAU types returned by G2.3 MAU type are to be
480  the same as dot3MauType information in RFC 3636.
481  This is my take on that information.
482  '''
483  mautypes = {
484  1: {'speed':10, 'duplex':'half', 'media': 'thick coax'},
485  2: {'speed':10, 'duplex':'half', 'media': 'FOIRL'},
486  3: {'speed':10, 'duplex':'half', 'media': 'thick coax'},
487  4: {'speed':10, 'duplex':'half', 'media': 'thin coax'},
488  5: {'speed':10, 'media': 'UTP'},
489 
490  6: {'speed':10, 'media': 'passive fiber'},
491  7: {'speed':10, 'media': 'sync fiber'},
492  8: {'speed':10, 'media': 'async fiber'},
493  9: {'speed':10, 'media': 'broadband DTE'},
494  10: {'speed':10, 'duplex':'half', 'media': 'UTP'},
495 
496  11: {'speed':10, 'duplex':'full', 'media': 'UTP'},
497  12: {'speed':10, 'duplex':'half', 'media': 'async fiber'},
498  13: {'speed':10, 'duplex':'full', 'media': 'async fiber'},
499  14: {'speed':100, 'media': '4 pair category 3 UTP'},
500  15: {'speed':100, 'duplex':'half', 'media': '2 pair category 5 UTP'},
501 
502  16: {'speed':100, 'duplex':'half', 'media': '2 pair category 5 UTP'},
503  17: {'speed':100, 'duplex':'half', 'media': 'X fiber over PMT'},
504  18: {'speed':100, 'duplex':'full', 'media': 'X fiber over PMT'},
505  19: {'speed':100, 'duplex':'half', 'media': '2 pair category 3 UTP'},
506  20: {'speed':100, 'duplex':'full', 'media': '2 pair category 3 UTP'},
507 
508  21: {'speed':1000, 'duplex':'half', 'media': 'PCS/PMA, unknown PMD'},
509  22: {'speed':1000, 'duplex':'full', 'media': 'PCS/PMA, unknown PMD'},
510  23: {'speed':1000, 'duplex':'half', 'media':
511  'fiber over long-wavelength laser'},
512  24: {'speed':1000, 'duplex':'full', 'media':
513  'fiber over long-wavelength laser'},
514  25: {'speed':1000, 'duplex':'half', 'media':
515  'fiber over short-wavelength laser'},
516 
517  26: {'speed':1000, 'duplex':'full', 'media':
518  'fiber over short-wavelength laser'},
519  27: {'speed':1000, 'duplex':'half', 'media':
520  'copper over 150-ohm balanced cable'},
521  28: {'speed':1000, 'duplex':'full', 'media':
522  'copper over 150-ohm balanced cable'},
523  29: {'speed':1000, 'duplex':'half', 'media': 'Four-pair Category 5 UTP'},
524  30: {'speed':1000, 'duplex':'full', 'media': 'Four-pair Category 5 UTP'},
525 
526  31: {'speed':10000, 'media': 'X PCS/PMA, unknown MD'},
527  32: {'speed':10000, 'media': 'X fiber over WWDM optics'},
528  33: {'speed':10000, 'media': 'R PCS/PMA, unknown PMD'},
529  34: {'speed':10000, 'media': 'R fiber over 1550 nm optics'},
530  35: {'speed':10000, 'media': 'R fiber over 1310 nm optics'},
531 
532  36: {'speed':10000, 'media': 'R fiber over 850 nm optics'},
533  37: {'speed':10000, 'media': 'W PCS/PMA, unknown PMD'},
534  38: {'speed':10000, 'media': 'W fiber over 1550 nm optics'},
535  39: {'speed':10000, 'media': 'R fiber over 1310 nm optics'},
536  40: {'speed':10000, 'media': 'R fiber over 850 nm optics'},
537  }
538  return mautypes[mautype] if mautype in mautypes else {}
539 
540  @staticmethod
541  def _decode_lldp_802_3_mac_phy(_switchinfo, thisportinfo,
542  tlvptr, tlvlen, pktend):
543  '''Decode 802.3 MAC/PHY TLV org-specific TLV (or not...)'''
544  if tlvlen != 5:
545  print >> sys.stderr, (
546  'Invalid %d byte LLDP 802.3 MAC/PHY information (Annex G.2).' % tlvlen)
547  return
548  autoneg_status = pySwitchDiscovery._byte0(tlvptr)
549  thisportinfo['autoneg_supported'] = (autoneg_status & 0x01) == 0x01
550  thisportinfo['autoneg_enabled'] = (autoneg_status & 0x10) == 0x10
551  #@TODO: Need to add info about autonegotiation speeds/duplexes supported (pmd_autoneg)
552  # I'm ignoring the PMD_AUTONEG field because it's not horribly important
553  # and it's incorrect on the switches in my test lab - and it's kinda
554  # complicated to decode and figure out ;-)
555  #
556  # It has one bit for each speed/duplex it is _capable_ of autonegotiating.
557  # PMD auto-negotiation advertised capability is described as the field
558  # ifMauAutoNegCapAdvertisedBits in RFC 3636 (page 42)
559  # pmd_autoneg_addr = pySwitchDiscovery._byte1addr(tlvptr)
560  # pmd_autoneg = tlv_get_guint16(pmd_autoneg_addr, pktend)
561  mau_addr = pySwitchDiscovery._byteNaddr(tlvptr, 3)
562  mau_type = tlv_get_guint16(mau_addr, pktend)
563  mauinfo = pySwitchDiscovery.dot3MauTypes(mau_type)
564  for key in mauinfo:
565  thisportinfo[key] = mauinfo[key]
566  #print >> sys.stderr, ("Autoneg_status: 0x%02x" % autoneg_status)
567  #print >> sys.stderr, ("pmd_autoneg: %d" % pmd_autoneg)
568  #print >> sys.stderr, ("MAU type: %d" % mau_type)
569 
570  @staticmethod
571  def _decode_lldp_med(switchinfo, _thisportinfo, tlvptr, tlvlen, _pktend):
572  '''Decode LLDP-MED org-specific TLV (or not...)'''
573  subtype = pySwitchDiscovery._byte0(tlvptr)
574  # for Location Identification (0x03) see https://tools.ietf.org/html/rfc4776#page-7
575  # Co-ordinate LCI
576  # Coordinate-based location data format uses geospatial data, that is, latitude,
577  # longitude, and altitude (height or floors), including indications of resolution, with
578  # reference to a particular datum: WGS 84, NAD83-North American Vertical Datum of 1988
579  # (NAVD88), or NAD83-Mean Lower Low Water (MLLW). For more information, see RFC 3825,
580  # Dynamic Host Configuration Protocol Option for Coordinate-based Location
581  # Configuration Information.
582 
583  # ELIN LCI
584  # Emergency Location Identification Number (ELIN) location data format provides a unique
585  # number for each location for Emergency Call Services (ECS). In North America, ELINs
586  # are typically 10 digits long; ELINs up to 25 digits are supported.
587 
588  # Civic Address LCI
589  # The Civic Address location data format uses common street address format, as described
590  # in RFC4776.
591  if subtype == 5:
592  pySwitchDiscovery._get_med_string(switchinfo, 'hardware-revision', tlvptr, tlvlen)
593  elif subtype == 6:
594  pySwitchDiscovery._get_med_string(switchinfo, 'firmware-revision', tlvptr, tlvlen)
595  elif subtype == 7:
596  pySwitchDiscovery._get_med_string(switchinfo, 'software-revision', tlvptr, tlvlen)
597  elif subtype == 8:
598  pySwitchDiscovery._get_med_string(switchinfo, 'serial-number', tlvptr, tlvlen)
599  elif subtype == 9:
600  pySwitchDiscovery._get_med_string(switchinfo, 'manufacturer', tlvptr, tlvlen)
601  elif subtype == 10:
602  pySwitchDiscovery._get_med_string(switchinfo, 'model', tlvptr, tlvlen)
603  elif subtype == 11:
604  pySwitchDiscovery._get_med_string(switchinfo, 'asset-id', tlvptr, tlvlen)
605  else:
606  print >> sys.stderr, (
607  'Ignored %d bytes of LLDP-MED extensions (subtype %d).' % (tlvlen, subtype))
608 
609  @staticmethod
610  def _get_med_string(info, name, tlvptr, tlvlen):
611  '''Decode LLDP-MED string value - trim off extra white space at end'''
612  strptr = cast(pySwitchDiscovery._byte1addr(tlvptr), c_char_p)
613  info[name] = string_at(strptr, tlvlen-1).strip()
614 
615  @staticmethod
616  def _decode_lldp_profibus(_switchinfo, _thisportinfo, _tlvptr, tlvlen, _pktend):
617  '''Decode LLDP Profibus org-specific TLV (or not...)'''
618  print >> sys.stderr, (
619  'Ignored %d bytes of Profibus International LLDP extensions.' % tlvlen)
620 
621  @staticmethod
622  def _decode_lldp_hytec(_switchinfo, _thisportinfo, _tlvptr, tlvlen, _pktend):
623  '''Decode LLDP Hytec org-specific TLV (or not...)'''
624  print >> sys.stderr, (
625  'Ignored %d bytes of Hytec Geraetebau GmbH LLDP extensions.' % tlvlen)
626 
627  @staticmethod
628  def _decode_cdp(host, interface, instance, wallclock, pktstart, pktend):
629  'Decode CDP packet into a JSON discovery packet'
630  thisportinfo = pyConfigContext(init={
631  'ConnectsToHost': host,
632  'ConnectsToInterface': interface,
633  }
634  )
635  switchinfo = pyConfigContext(init = {'ports': pyConfigContext()})
636  metadata = pyConfigContext(init={
637  'discovertype': '__LinkDiscovery',
638  'description': 'Link Level Switch Discovery (cdp)',
639  'source': '_decode_cdp()',
640  'host': host,
641  'instance': instance,
642  'localtime': str(wallclock),
643  'data': switchinfo,
644  }
645  )
646  sourcemacptr = pySwitchDiscovery._byteNaddr(cast(pktstart, cClass.guint8), 6)
647  if not sourcemacptr:
648  return metadata
649  Cmacaddr = netaddr_mac48_new(sourcemacptr)
650  sourcemac = pyNetAddr(None, Cstruct=Cmacaddr)
651  this = get_cdptlv_first(pktstart, pktend)
652  while this and this < pktend:
653  tlvtype = get_cdptlv_type(this, pktend)
654  tlvlen = get_cdptlv_len(this, pktend)
655  tlvptr = cast(get_cdptlv_body(this, pktend), cClass.guint8)
656  this = get_cdptlv_next(this, pktend)
657  value = None
658  # Each of the different cases handles 'value' differently
659  # pylint: disable=R0204
660  if tlvtype not in pySwitchDiscovery.cdpnames:
661  tlvname = ('TLV_0x%02x' % tlvtype)
662  isswitchinfo = True # Gotta do _something_...
663  else:
664  (tlvname, isswitchinfo) = pySwitchDiscovery.cdpnames[tlvtype]
665  if tlvtype == CDP_TLV_DEVID:
666  value = string_at(tlvptr, tlvlen-4)
667  elif tlvtype == CDP_TLV_ADDRESS:
668  # 4 byte count + 'count' addresses
669  value = pySwitchDiscovery.getcdpaddresses(tlvlen, tlvptr, pktend)
670  elif tlvtype == CDP_TLV_PORTID:
671  value = string_at(tlvptr, tlvlen-4)
672  elif tlvtype == CDP_TLV_CAPS:
673  #bytez = [ '%02x' % pySwitchDiscovery._byteN(tlvptr, j) for j in range(0, tlvlen)]
674  #print >> sys.stderr, 'CAPBYTES = ', bytez
675  caps = pySwitchDiscovery.getNint(tlvptr, 4, pktend)
676  #print >> sys.stderr, ('CAPS IS: 0x%08x (%d bytes)' % (caps, tlvlen))
677  value = pySwitchDiscovery.construct_cdp_caps(caps)
678  elif tlvtype == CDP_TLV_VERS:
679  value = string_at(tlvptr, tlvlen-4)
680  elif tlvtype == CDP_TLV_PLATFORM:
681  value = string_at(tlvptr, tlvlen-4)
682  elif tlvtype == CDP_TLV_POWER:
683  tlen = tlvlen if tlvlen <= 2 else 2
684  value = pySwitchDiscovery.getNint(tlvptr, tlen, pktend)
685  elif tlvtype == CDP_TLV_MTU:
686  value = pySwitchDiscovery.getNint(tlvptr, tlvlen, pktend)
687  elif tlvtype == CDP_TLV_SYSTEM_NAME:
688  value = string_at(tlvptr, tlvlen-4)
689  elif tlvtype == CDP_TLV_MANAGEMENT_ADDR:
690  # 4 byte count + 'count' addresses
691  value = pySwitchDiscovery.getcdpaddresses(tlvlen, tlvptr, pktend)
692  elif tlvtype == CDP_TLV_VTPDOMAIN:
693  value = string_at(tlvptr, tlvlen-4)
694  elif tlvtype == CDP_TLV_NATIVEVLAN:
695  value = tlv_get_guint16(tlvptr, pktend)
696  elif tlvtype == CDP_TLV_UNTRUSTED_COS:
697  value = pySwitchDiscovery._byte0(tlvptr)
698  elif tlvtype == CDP_TLV_DUPLEX:
699  value = 'half' if pySwitchDiscovery._byte0(tlvptr) == 0 else 'full'
700  elif tlvtype == CDP_TLV_LOCATION:
701  value = string_at(tlvptr, tlvlen-4)
702  elif tlvtype == CDP_TLV_EXT_PORTID:
703  value = string_at(tlvptr, tlvlen-4)
704  else:
705  value='0x'
706  for offset in range(0, tlvlen):
707  value += ('%02x' % pySwitchDiscovery._byteN(tlvptr, offset))
708  #print >> sys.stderr, 'Ignoring CDP field %s: %s' % (tlvname, value)
709  value = None
710 
711  if value is None:
712  print >> sys.stderr, ('Ignored %d bytes for %s field [0x%02x]'
713  % (tlvlen, tlvname, tlvtype))
714  else:
715  if tlvtype == CDP_TLV_PORTID:
716  switchinfo['ports'][value] = thisportinfo
717  thisportinfo['PortId'] = value
718  numericpart = value
719  while len(numericpart) > 0 and not numericpart.isdigit():
720  numericpart = numericpart[1:]
721  #if len > 0 and numericpart.isdigit():
722  # thisportinfo['PORTNUM'] = int(numericpart)
723  else:
724  if isswitchinfo:
725  switchinfo[tlvname] = value
726  else:
727  thisportinfo[tlvname] = value
728  #print >> sys.stderr, ('TLVNAME[%s] %s has value "%s" -- len: %d'
729  #% (tlvtype, tlvname, value, len(str(value))))
730  thisportinfo['sourceMAC'] = sourcemac
731  return metadata
732 
733 
734  @staticmethod
735  def getNint(tlvptr, tlvlen, pktend):
736  'Return an integer of any size that we support...'
737  intptr = tlvptr
738  if tlvlen == 1:
739  return tlv_get_guint8(intptr, pktend)
740  if tlvlen == 2:
741  return tlv_get_guint16(intptr, pktend)
742  if tlvlen == 3:
743  return tlv_get_guint24(intptr, pktend)
744  if tlvlen == 4:
745  return tlv_get_guint32(intptr, pktend)
746  if tlvlen == 8:
747  return tlv_get_guint64(intptr, pktend)
748  return None
749 
750  @staticmethod
751  def construct_cdp_caps(capval):
752  'Construct Capability value from the CDP capability integer'
753  capnames = [CMAconsts.ROLE_router,
754  CMAconsts.ROLE_tb_bridge,
755  CMAconsts.ROLE_srcbridge,
756  CMAconsts.ROLE_bridge,
757  CMAconsts.ROLE_host,
758  CMAconsts.ROLE_igmp,
759  CMAconsts.ROLE_repeater
760  ]
761  mask = 1
762  value = []
763  for j in range(0, len(capnames)):
764  if capval & mask:
765  #value[capnames[j]] = ((capval & mask) != 0)
766  value.append(capnames[j])
767  mask <<= 1
768  return value
769 
770 
771  @staticmethod
772  def getcdpaddresses(tlvlen, tlvstart, pktend):
773  '''
774  Decode utterly bizarre CDP-specific address list format
775  4 bytes address count
776  'count' addresses in this form:
777  one bytes protocol length
778  'protocol length' bytes of protocol type
779  two bytes address length
780  'address length' bytes of address
781  IPv4:
782  protocol length = 1, protocol type = 0xCC
783  IPv6:
784  protocol length = 8 and address length = 16
785  protocol type == 0xAAAA0300000086DD ??
786  +-------+--------------------+----------+-----------------+
787  |Proto |Protocol Type | address | Actual address |
788  |Length |(protolength bytes) | length | (addresslength |
789  |1 byte |(1-255 bytes) | (2 bytes)| bytes) |
790  +-------+--------------------+----------+-----------------+
791 
792  Min length for an IPV4 address is 8 bytes
793  '''
794  minlength=8
795  retlist = []
796  offset = 0
797  count = pySwitchDiscovery.getNint(tlvstart, 4, pktend)
798  offset += 4
799  for j in range(0, count):
800  addr = None
801  if (offset+minlength) > tlvlen:
802  break
803  protolen = pySwitchDiscovery.getNint(pySwitchDiscovery._byteNaddr
804  ( cast(tlvstart, cClass.guint8), offset), 1, pktend)
805  offset += 2
806  if protolen < 1:
807  break
808  if offset >= tlvlen:
809  break
810  if protolen == 1:
811  prototype = pySwitchDiscovery._byteN(tlvstart, offset+protolen-1)
812  elif protolen == 16:
813  prototype = pySwitchDiscovery.getNint(
814  pySwitchDiscovery._byteNaddr(cast(tlvstart, cClass.guint8), offset+protolen-2)
815  , 2, pktend)
816  else:
817  prototype = 0xdeadbeef
818  offset += protolen
819  if offset > tlvlen:
820  break
821  addrlen = pySwitchDiscovery.getNint(pySwitchDiscovery._byteNaddr
822  ( cast(tlvstart, cClass.guint8), offset), 2, pktend)
823  if protolen == 1 and addrlen == 4 and prototype == 0xCC:
824  addrstr=''
825  for j in (offset+2, offset+3, offset, offset+1):
826  addrstr += chr(pySwitchDiscovery._byteN(tlvstart, j))
827  addr = netaddr_ipv4_new(c_char_p(addrstr), 0)
828  elif protolen == 8 and addrlen == 16 and prototype == 0x86DD:
829  # protocol type == 0xAAAA0300000086DD
830  addr = netaddr_ipv6_new(pySwitchDiscovery._byteNaddr(cast(tlvstart, cClass.guint8)
831  , offset), 0)
832  if addr is not None:
833  pyaddr = pyNetAddr(Cstruct=addr, addrstring=None)
834  retlist.append(pyaddr)
835  offset += addrlen
836 
837  if len(retlist) == 0:
838  return None
839  if len(retlist) == 1:
840  return retlist[0]
841  return retlist
842 
843 
844 
845 
846 class pyAssimObj(object):
847  'The base object for all the C-class objects'
848  def __init__(self, Cstruct=None):
849  'Create a base pyAssimObj object'
850  self._Cstruct = None
851  if Cstruct is not None:
852  assert not isinstance(Cstruct, (int, long))
853  self._Cstruct = Cstruct
854  else:
855  self._Cstruct = assimobj_new(0)
856  #print 'ASSIMOBJ:init: %s' % (Cstruct)
857 
858  def cclassname(self):
859  "Return the 'C' class name for this object"
860  return proj_class_classname(self._Cstruct)
861 
862  def __str__(self):
863  'Convert this AssimObj into a printable string'
864  if not self._Cstruct:
865  return "[None]"
866  base = self._Cstruct[0]
867  while not_this_exact_type(base, AssimObj):
868  base = base.baseclass
869  cstringret = cast(base.toString(self._Cstruct), c_char_p)
870  ret = string_at(cstringret)
871  g_free(cstringret)
872  return ret
873 
874  #pylint: disable=W0603
875  def __del__(self):
876  'Free up the underlying Cstruct for this pyAssimObj object.'
877  if not self._Cstruct or self._Cstruct is None:
878  return
879  global badfree
880  badfree = 0
881  CCunref(self._Cstruct)
882  if badfree != 0:
883  print >> sys.stderr, "Attempt to free something already freed(%s)" % str(self._Cstruct)
884  traceback.print_stack()
885  badfree = 0
886  self._Cstruct = None
887 
888  def refcount(self):
889  'Return the reference count for this object'
890  base = self._Cstruct[0]
891  while hasattr(base, 'baseclass'):
892  base = base.baseclass
893  return base._refcount
894 
896  '''This class represents the Python version of our C-class @ref NetAddr
897  - represented by the struct _NetAddr.
898  '''
899  def __init__(self, addrstring, port=None, Cstruct=None):
900  '''This constructor needs a list of integers of the right length as its first argument.
901  The length of the list determines the type of address generated.
902  4 bytes == ipv4
903  6 bytes == MAC address
904  8 bytes == MAC address
905  16 bytes == ipv6 address
906  This is slightly sleazy but it should work for the forseeable future.
907  '''
908 
909  self._Cstruct = None # Silence error messages in failure cases
910 
911  if Cstruct is not None:
912  assert (not isinstance(Cstruct, (int, long))) and Cstruct
913  pyAssimObj.__init__(self, Cstruct=Cstruct)
914  if port is not None:
915  self.setport(port)
916  assert self._Cstruct
917  return
918 
919  if port is None:
920  port = 0
921 
922  if isinstance(addrstring, unicode) or isinstance(addrstring, pyNetAddr):
923  addrstring = str(addrstring)
924  if isinstance(addrstring, str):
925  cs = netaddr_dns_new(addrstring)
926  if not cs:
927  raise ValueError('Illegal NetAddr initial value: "%s"' % addrstring)
928  if port != 0:
929  cs[0].setport(cs, port)
930  pyAssimObj.__init__(self, Cstruct=cs)
931  assert self._Cstruct
932  return
933 
934  self._init_from_binary(addrstring, port)
935  assert self._Cstruct
936 
937  def _init_from_binary(self, addrstring, port):
938  'Initialize an addrstring from a binary argument'
939  alen = len(addrstring)
940  addr = create_string_buffer(alen)
941  #print >> sys.stderr, "ADDRTYPE:", type(addr)
942  #print >> sys.stderr, "ADDRSTRINGTYPE:", type(addrstring)
943  for i in range(0, alen):
944  asi = addrstring[i]
945  #print >> sys.stderr, "ASI_TYPE: (%s,%s)" % (type(asi), asi)
946  if isinstance(asi, (str, unicode)):
947  addr[i] = str(asi)
948  else:
949  addr[i] = chr(asi)
950  #print >> sys.stderr, 'ADDR = %s' % addr
951  if alen == 4: # ipv4
952  NA = netaddr_ipv4_new(addr, port)
953  pyAssimObj.__init__(self, Cstruct=NA)
954  elif alen == 16: # ipv6
955  pyAssimObj.__init__(self, netaddr_ipv6_new(addr, port))
956  elif alen == 6: # "Normal" 48-bit MAC address
957  assert port == 0
958  pyAssimObj.__init__(self, netaddr_mac48_new(addr, port))
959  elif alen == 8: # Extended 64-bit MAC address
960  assert port == 0
961  pyAssimObj.__init__(self, netaddr_mac64_new(addr, port))
962  else:
963  raise ValueError('Invalid address length - not 4, 6, 8, or 16')
964 
965  def port(self):
966  'Return the port (if any) for this pyNetAddr object'
967  base = self._Cstruct[0]
968  while not_this_exact_type(base, NetAddr):
969  base = base.baseclass
970  return base.port(self._Cstruct)
971 
972  def setport(self, port):
973  'Return the port (if any) for this pyNetAddr object'
974  base = self._Cstruct[0]
975  while not_this_exact_type(base, NetAddr):
976  base = base.baseclass
977  base.setport(self._Cstruct, port)
978 
979  def addrtype(self):
980  'Return the type of address for this pyNetAddr object'
981  base = self._Cstruct[0]
982  while not_this_exact_type(base, NetAddr):
983  base = base.baseclass
984  return base.addrtype(self._Cstruct)
985 
986  def addrlen(self):
987  "Return the number of bytes necessary to represent this pyNetAddr object on the wire."
988  base = self._Cstruct[0]
989  while not_this_exact_type(base, NetAddr):
990  base = base.baseclass
991  return base._addrlen
992 
993  def islocal(self):
994  'Return True if this address is a local address'
995  base = self._Cstruct[0]
996  while not_this_exact_type(base, NetAddr):
997  base = base.baseclass
998  return base.islocal(self._Cstruct)
999 
1000  def isanyaddr(self):
1001  '''Return True if this address is the 'ANY' address'''
1002  base = self._Cstruct[0]
1003  while not_this_exact_type(base, NetAddr):
1004  base = base.baseclass
1005  return base.isanyaddr(self._Cstruct)
1006 
1007  def toIPv6(self, port=None):
1008  'Return an equivalent IPv6 address to the one that was given. Guaranteed to be a copy'
1009  base = self._Cstruct[0]
1010  while not_this_exact_type(base, NetAddr):
1011  base = base.baseclass
1012  newcs = cast(base.toIPv6(self._Cstruct), cClass.NetAddr)
1013  return pyNetAddr(None, Cstruct=newcs, port=port)
1014 
1015  def toIPv4(self, port=None):
1016  '''Return an equivalent IPv4 address to the one that was given - if possible.
1017  Guaranteed to be a copy'''
1018  base = self._Cstruct[0]
1019  while not_this_exact_type(base, NetAddr):
1020  base = base.baseclass
1021  newcs = cast(base.toIPv4(self._Cstruct), cClass.NetAddr)
1022  if not newcs:
1023  raise ValueError('Could not be converted to IPv4: %s' % (str(self)))
1024  return pyNetAddr(None, Cstruct=newcs, port=port)
1025 
1026  def __repr__(self):
1027  'Return a canonical representation of this NetAddr'
1028  assert self._Cstruct
1029  base = self._Cstruct[0]
1030  while not_this_exact_type(base, NetAddr):
1031  base = base.baseclass
1032  cstringret = base.canonStr(self._Cstruct)
1033  ret = string_at(cstringret)
1034  g_free(cstringret)
1035  return ret
1036 
1037 
1038  def __eq__(self, other):
1039  "Return True if the two pyNetAddrs are equal"
1040  if not other._Cstruct or not self._Cstruct:
1041  return False
1042  base = self._Cstruct[0]
1043  while not_this_exact_type(base, NetAddr):
1044  base = base.baseclass
1045  return True if base.equal(self._Cstruct, other._Cstruct) else False
1046 
1047  def __hash__(self):
1048  'Return a hash value for the given pyNetAddr'
1049  if not self._Cstruct:
1050  return 0
1051  base = self._Cstruct[0]
1052  while not_this_exact_type(base, NetAddr):
1053  base = base.baseclass
1054  return base.hash(self._Cstruct)
1055 
1056 
1058  '''This class represents the Python version of our C-class @ref Frame
1059  - represented by the struct _Frame.
1060  This class is a base class for several different pyFrame subclasses.
1061  Each of these various pyFrame subclasses have a corresponding C-class @ref Frame subclass.
1062  The purpose of these pyFrames and their subclasses is to talk on the wire with our C code in our
1063  nanoprobes.
1064 
1065  Deliberately leaving out the updatedata() C-class member function - at least for now.
1066  I suspect that the Python code will only need the corresponding calls in a @ref FrameSet
1067  - which would then update the corresponding @ref Frame member functions...
1068  '''
1069  #
1070  # Our subclasses need to implement these methods:
1071  # __init__ - subclass initializer
1072  # from_Cstruct classmethod - call the corresponding xxxframe_tlvconstructor() function
1073  # to act as a pseudo-constructor. This method/constructor is used to create
1074  # Python objects from incoming packet data.
1075  #
1076  def __init__(self, initval, Cstruct=None):
1077  "Initializer for the pyFrame object."
1078  if Cstruct is None:
1079  try:
1080  frametype = initval.tlvtype
1081  except(AttributeError):
1082  frametype = int(initval)
1083  # If we don't do this, then a subclass __init__ function must do it instead...
1084  pyAssimObj.__init__(self, Cstruct=frame_new(frametype, 0))
1085  else:
1086  pyAssimObj.__init__(self, Cstruct=Cstruct)
1087 
1088  def frametype(self):
1089  "Return the TLV type for the pyFrame object."
1090  base = self._Cstruct[0]
1091  while not_this_exact_type(base, Frame):
1092  base = base.baseclass
1093  return base.type
1094 
1095  def framelen(self):
1096  "Return the length of this frame in bytes (TLV length)."
1097  base = self._Cstruct[0]
1098  while not_this_exact_type(base, Frame):
1099  base = base.baseclass
1100  return base.length
1101 
1102  def framevalue(self):
1103  'Return a C-style pointer to the underlying raw TLV data (if any)'
1104  base = self._Cstruct[0]
1105  while not_this_exact_type(base, Frame):
1106  base = base.baseclass
1107  return cast(base.value, c_char_p)
1108 
1109  def frameend(self):
1110  'Return a C-style pointer to the underlying raw TLV data (if any)'
1111  base = self._Cstruct[0]
1112  while not_this_exact_type(base, Frame):
1113  base = base.baseclass
1114  return cast(base.value+base.length, c_char_p)
1115 
1116  def dataspace(self):
1117  'Return the amount of space this frame needs - including type and length'
1118  base = self._Cstruct[0]
1119  while not_this_exact_type(base, Frame):
1120  base = base.baseclass
1121  return base.dataspace(self._Cstruct)
1122 
1123  def isvalid(self):
1124  "Return True if this Frame is valid"
1125  base = self._Cstruct[0]
1126  while not_this_exact_type(base, Frame):
1127  base = base.baseclass
1128 # pstart = pointer(cast(base.value, c_char_p))
1129 # if pstart[0] is None:
1130 # return False
1131  return (int(base.isvalid(self._Cstruct, None, None)) != 0)
1132 
1133  def setvalue(self, value):
1134  'Assign a chunk of memory to the Value portion of this Frame'
1135  vlen = len(value)
1136  if isinstance(value, (str, unicode)):
1137  valbuf = create_string_buffer(vlen+1)
1138  for i in range(0, vlen):
1139  vi = value[i]
1140  valbuf[i] = vi
1141  valbuf[vlen] = chr(0)
1142  vlen += 1
1143  else:
1144  valbuf = create_string_buffer(vlen)
1145  for i in range(0, vlen):
1146  vi = value[i]
1147  valbuf[i] = int(vi)
1148  base = self._Cstruct[0]
1149  valptr = MALLOC(vlen)
1150  memmove(valptr, valbuf, vlen)
1151  while not_this_exact_type(base, Frame):
1152  base = base.baseclass
1153  base.setvalue(self._Cstruct, valptr, vlen, cast(None, GDestroyNotify))
1154 
1155  def dump(self, prefix):
1156  'Dump out this Frame (using C-class "dump" member function)'
1157  base = self._Cstruct[0]
1158  while not_this_exact_type(base, Frame):
1159  base = base.baseclass
1160  base.dump(self._Cstruct, cast(prefix, c_char_p))
1161 
1162  def __str__(self):
1163  'Convert this Frame to a string'
1164  base = self._Cstruct[0]
1165  while not_this_exact_type(base, AssimObj):
1166  base = base.baseclass
1167  cstringret = cast(base.toString(self._Cstruct), c_char_p)
1168  ret = string_at(cstringret)
1169  g_free(cstringret)
1170  return '%s: %s' % (FrameTypes.get(self.frametype())[1] , ret)
1171 
1172  @staticmethod
1173  def Cstruct2Frame(frameptr):
1174  'Unmarshalls a binary blob (Cstruct) into a Frame'
1175  frameptr = cast(frameptr, cClass.Frame)
1176  CCref(frameptr)
1177  frametype = frameptr[0].type
1178  Cclassname = proj_class_classname(frameptr)
1179  pyclassname = "py" + Cclassname
1180  if Cclassname == 'NetAddr':
1181  statement = "%s(%d, None, Cstruct=cast(frameptr, cClass.%s))" \
1182  % (pyclassname, frametype, Cclassname)
1183  elif Cclassname == Cclassname == 'IpPortFrame':
1184  statement = "%s(%d, None, None, Cstruct=cast(frameptr, cClass.%s))" \
1185  % (pyclassname, frametype, Cclassname)
1186  else:
1187  statement = "%s(%d, Cstruct=cast(frameptr, cClass.%s))" \
1188  % (pyclassname, frametype, Cclassname)
1189  #print >> sys.stderr, "EVAL:", statement
1190  # We construct the string from our data, so it's trusted data...
1191  # pylint: disable=W0123
1192  return eval(statement)
1193 
1195  '''This class represents the Python version of our C-class CompressFrame
1196  - represented by the struct _CompressFrame. It is used to tell us that
1197  what kind of compression we want in our communication stream.
1198  '''
1199  def __init__(self, frametype=FRAMETYPE_COMPRESS, compression_method=COMPRESS_ZLIB
1200  , Cstruct=None):
1201  self._Cstruct = None # Keep error legs from complaining.
1202  if Cstruct is None:
1203  Cstruct = compressframe_new_string(frametype, compression_method)
1204  else:
1205  Cstruct = Cstruct
1206  pyFrame.__init__(self, frametype, Cstruct=Cstruct)
1207 
1208 
1210  '''This class represents the Python version of our C-class AddrFrame
1211  - represented by the struct _AddrFrame.
1212  '''
1213  def __init__(self, frametype, addrstring=None, port=None, Cstruct=None):
1214  "Initializer for the pyAddrFrame object."
1215  self._Cstruct = None # Keep error legs from complaining.
1216  if Cstruct is None:
1217  if isinstance(addrstring, pyNetAddr):
1218  self._pyNetAddr = addrstring
1219  else:
1220  self._pyNetAddr = pyNetAddr(addrstring, port=port)
1221  Cstruct = addrframe_new(frametype, 0)
1222  if addrstring is not None:
1223  Cstruct[0].setnetaddr(Cstruct, self._pyNetAddr._Cstruct)
1224  else:
1225  assert port is None
1226  assert addrstring is None
1227  # Allow for prefixed address type - two bytes
1228  addrlen = Cstruct[0].baseclass.length - 2
1229  assert addrlen == 4 or addrlen == 6 or addrlen == 8 or addrlen == 16 \
1230  , ("addrlen is %d" % addrlen)
1231  addrstr = Cstruct[0].baseclass.value+2
1232  addrstring = create_string_buffer(addrlen)
1233  memmove(addrstring, addrstr, addrlen)
1234  self._pyNetAddr = pyNetAddr(addrstring, port=None)
1235  pyFrame.__init__(self, frametype, Cstruct=Cstruct)
1236 
1237  def addrtype(self):
1238  'Return the Address type for this AddrFrame'
1239  return self._pyNetAddr.addrtype()
1240 
1241  def getnetaddr(self):
1242  'Return the pyNetAddr for this AddrFrame'
1243  return self._pyNetAddr
1244 
1245  def __str__(self):
1246  return ("pyAddrFrame(%s, (%s))" \
1247  % (FrameTypes.get(self.frametype())[1], str(self._pyNetAddr)))
1248 
1250  '''This class represents the Python version of our C-class IpPortFrame
1251  - represented by the struct _IpPortFrame.
1252  '''
1253  def __init__(self, frametype, addrstring, port=None, Cstruct=None):
1254  "Initializer for the pyIpPortFrame object."
1255  self._Cstruct = None # Keep error legs from complaining.
1256  if Cstruct is None:
1257  if isinstance(addrstring, pyNetAddr):
1258  self._pyNetAddr = addrstring
1259  Cstruct = ipportframe_netaddr_new(frametype, addrstring._Cstruct)
1260  if not Cstruct:
1261  raise ValueError("invalid initializer")
1262  self.port = addrstring.port()
1263  else:
1264  Cstruct = self._init_from_binary(frametype, addrstring, port)
1265  else:
1266  assert port is None
1267  assert addrstring is None
1268  addrlen = Cstruct[0].baseclass.length - 4 # Allow for prefixed port and address type
1269  if addrlen != 4 and addrlen != 16:
1270  raise ValueError("Bad addrlen: %d" % addrlen)
1271  port = Cstruct[0].port
1272  self.port = port
1273  addrstr = Cstruct[0].baseclass.value+4
1274  addrstring = create_string_buffer(addrlen)
1275  memmove(addrstring, addrstr, addrlen)
1276  self._pyNetAddr = pyNetAddr(addrstring, port=port)
1277  pyFrame.__init__(self, frametype, Cstruct=Cstruct)
1278 
1279  def _init_from_binary(self, frametype, addrstring, port):
1280  'Initialize a pyIpAddrFrame from a binary argument'
1281  addrlen = len(addrstring)
1282  self._pyNetAddr = pyNetAddr(addrstring, port=port)
1283  if self._pyNetAddr is None:
1284  raise ValueError("Invalid initializer.")
1285  addrstr = create_string_buffer(addrlen)
1286  for j in range(0, addrlen):
1287  addrstr[j] = chr(addrstring[j])
1288  if addrlen == 4:
1289  Cstruct = ipportframe_ipv4_new(frametype, port, addrstr)
1290  elif addrlen == 16:
1291  Cstruct = ipportframe_ipv6_new(frametype, port, addrstr)
1292  else:
1293  raise ValueError('Bad address length: %d' % addrlen)
1294  self.port = port
1295  if port == 0:
1296  raise ValueError("zero port")
1297  if not Cstruct:
1298  raise ValueError("invalid initializer")
1299  return Cstruct
1300 
1301  def addrtype(self):
1302  'Return the Address type of this pyIpPortFrame'
1303  return self._pyNetAddr.addrtype()
1304 
1305  def getnetaddr(self):
1306  'Return the NetAddr of this pyIpPortFrame'
1307  return self._pyNetAddr
1308 
1309  def getport(self):
1310  'Return the port of this pyIpPortFrame'
1311  return self._pyNetAddr.port()
1312 
1313 
1315  '''This class represents the Python version of our C-class CstringFrame
1316  - represented by the struct _CstringFrame.
1317  This class represents a Frame standard NUL-terminated C string.
1318  '''
1319  def __init__(self, frametype, initval=None, Cstruct=None):
1320  '''Constructor for pyCstringFrame object - initial value should be something
1321  that looks a lot like a Python string'''
1322  if Cstruct is None:
1323  Cstruct = cstringframe_new(frametype, 0)
1324  pyFrame.__init__(self, frametype, Cstruct)
1325  if initval is not None:
1326  self.setvalue(initval)
1327 
1328  def getstr(self):
1329  'Return the String part of this pyCstringFrame'
1330  base = self._Cstruct[0]
1331  while not hasattr(base, 'value'):
1332  base = base.baseclass
1333  return string_at(base.value)
1334 
1336  '''This class represents the Python version of our IntFrame C-class
1337  - represented by the struct _IntFrame.
1338  This class represents an integer of 1, 2, 3, 4 or 8 bytes.
1339  '''
1340  def __init__(self, frametype, initval=None, intbytes=4, Cstruct=None):
1341  '''Constructor for pyIntFrame object
1342  - initial value should be something that looks a lot like an integer'''
1343  self._Cstruct = None
1344  if Cstruct is None:
1345  Cstruct = intframe_new(frametype, intbytes)
1346  if not Cstruct:
1347  raise ValueError("Invalid integer size (%d) in pyIntFrame constructor" % intbytes)
1348  pyFrame.__init__(self, frametype, Cstruct=Cstruct)
1349  if initval is not None:
1350  self.setint(initval)
1351 
1352  def __int__(self):
1353  '''Return the integer value of this pyIntFrame. (implemented by the
1354  underlying IntFrame object)'''
1355  return self._Cstruct[0].getint(self._Cstruct)
1356 
1357  def __str__(self):
1358  'Return a string representation of this pyIntFrame (the integer value).'
1359  return ("pyIntFrame(%s, (%d))" % (FrameTypes.get(self.frametype())[1], int(self)))
1360 
1361  def getint(self):
1362  'Return the integer value of this pyIntFrame - same as __int__.'
1363  return int(self)
1364 
1365  def setint(self, intval):
1366  '''Set the value of this pyIntFrame to the given integer value.
1367  Note that this value is range checked by the underlying IntFrame implementation.
1368  '''
1369  self._Cstruct[0].setint(self._Cstruct, int(intval))
1370 
1371  def intlength(self):
1372  '''Return the number of bytes in the integer underlying this pyIntFrame object.
1373  (implemented by underlying IntFrame object)'''
1374  return self._Cstruct[0].intlength(self._Cstruct)
1375 
1377  "Class for a Frame type we don't recognize"
1378  def __init__(self, frametype, Cstruct=None):
1379  'Initializer for pyUnknownFrame'
1380  if Cstruct is None:
1381  Cstruct = unknownframe_new(frametype)
1382  pyFrame.__init__(self, frametype, Cstruct)
1383 
1385  'Class for a Sequence Number Frame - for reliable UDP packet transmission.'
1386  def __init__(self, frametype, initval=None, Cstruct=None):
1387  'Initializer for pySeqnoFrame'
1388  self._Cstruct = None
1389  # TODO(?): Need to allow for initialization of seqno frames.
1390  if Cstruct is None:
1391  Cstruct = seqnoframe_new(frametype, 0)
1392  if not Cstruct:
1393  raise ValueError("Constructor error for PySeqnoFrame()")
1394  pyFrame.__init__(self, frametype, Cstruct=Cstruct)
1395  if initval is not None:
1396  self.setqid(initval[0])
1397  self.setreqid(initval[1])
1398 
1399  def setreqid(self, reqid):
1400  'Set the request ID portion of this SeqnoFrame'
1401  self._Cstruct[0].setreqid(self._Cstruct, reqid)
1402 
1403  def setqid(self, qid):
1404  'Set the Queue ID portion of this SeqnoFrame'
1405  self._Cstruct[0].setqid(self._Cstruct, qid)
1406 
1407  def getreqid(self):
1408  'Get the request ID portion of this SeqnoFrame'
1409  return self._Cstruct[0].getreqid(self._Cstruct)
1410 
1411  def getqid(self):
1412  'Get the Queue ID portion of this SeqnoFrame'
1413  return self._Cstruct[0].getqid(self._Cstruct)
1414 
1415  def __eq__(self, rhs):
1416  'Compare this pySeqnoFrame to another pySeqnoFrame'
1417  lhsbase = self._Cstruct[0]
1418  while not_this_exact_type(lhsbase, SeqnoFrame):
1419  lhsbase = lhsbase.baseclass
1420  return True if lhsbase.equal(self._Cstruct, rhs._Cstruct) else False
1421 
1422  def __str__(self):
1423  'Convert this pySeqnoFrame to a String'
1424  return ("pySeqNo(%s: (%d, %d))" \
1425  % (FrameTypes.get(self.frametype())[1], self.getqid(), self.getreqid()))
1426 
1428  '''Class for Digital Signature Frames
1429  - for authenticating data (subclasses will authenticate senders)'''
1430  def __init__(self, gchecksumtype, Cstruct=None):
1431  'Initializer for pySignFrame'
1432  self._Cstruct = None
1433  if Cstruct is None:
1434  Cstruct = signframe_glib_new(gchecksumtype, 0)
1435  if not Cstruct:
1436  raise ValueError("Invalid checksum type (%s) for PySignFrame()" % gchecksumtype)
1437  pyFrame.__init__(self, initval=FRAMETYPE_SIG, Cstruct=Cstruct)
1438 
1440  'Class for a Frame containing a single name/value pair'
1441  def __init__(self, frametype, name, value, Cstruct=None):
1442  'Initializer for pyNVpairFrame'
1443  self._Cstruct = None
1444  if Cstruct is None:
1445  Cstruct = nvpairframe_new(frametype, name, value, 0)
1446  if not Cstruct:
1447  raise ValueError("Invalid NVpair initializer for pyNVPairFrame()")
1448  pyFrame.__init__(self, initval=frametype, Cstruct=Cstruct)
1449 
1450  def name(self):
1451  'Return the name portion of a pyNVpairFrame'
1452  return string_at(self._Cstruct[0].name)
1453 
1454  def value(self):
1455  'Return the name portion of a pyNVpairFrame'
1456  return string_at(self._Cstruct[0].value)
1457 
1459  '''Abstract class for a generalized encryption frame
1460  Our main importance is for our static methods which allow us
1461  to map key ids to identities, and IP addresses to key ids.
1462  The underlying C code then automatically creates the correct
1463  CryptFrame objects for outgoing packets.
1464  '''
1465  NOTAKEY = AssimCtypes.NOTAKEY
1466  PUBLICKEY = AssimCtypes.PUBLICKEY
1467  PRIVATEKEY = AssimCtypes.PRIVATEKEY
1468  def __init__(self, destaddr=None, Cstruct=None):
1469  self._Cstruct = None
1470  if Cstruct is None and destaddr is None:
1471  raise ValueError('pyCryptFrame requires destaddr or Cstruct')
1472  if Cstruct is None:
1473  Cstruct = cryptframe_new_by_destaddr(destaddr._Cstruct)
1474  pyFrame.__init__(self, None, Cstruct=Cstruct)
1475 
1476  def receiver_id(self):
1477  'Return the key_id of the receiver key'
1478  return string_at(self._Cstruct[0].receiver_key_id)
1479 
1480  @staticmethod
1482  'Returns the set of key ids that we know about'
1483  keyidlist_int = cryptframe_get_key_ids()
1484  keyid_gslist = cast(keyidlist_int, cClass.GSList)
1485  keyid_list = []
1486  curkeyid = keyid_gslist
1487  while curkeyid:
1488  keyid_list.append(string_at(curkeyid[0].data))
1489  curkeyid = g_slist_next(curkeyid)
1490  g_slist_free(keyid_gslist)
1491  return keyid_list
1492 
1493  @staticmethod
1495  'Return the set of CMA key ids we know about'
1496  ret = []
1497  for keyid in pyCryptFrame.get_key_ids():
1498  if keyid.startswith(CMA_KEY_PREFIX):
1499  ret.append(keyid)
1500  return ret
1501 
1502  @staticmethod
1503  def associate_identity(identityname, key_id):
1504  '''Associate the given identity name with the given key id
1505  This allows many keys to be associated with a single identity, but
1506  does not support a key being associated with multiple identities
1507  (which doesn't make sense anyway).
1508  '''
1509  assert identityname is not None
1510  assert key_id is not None
1511  if not cryptframe_associate_identity(str(identityname), str(key_id)):
1512  raise ValueError("Problem with key id %s or identity %s" % (key_id, identityname))
1513 
1514  @staticmethod
1515  def get_identity(key_id):
1516  'Return the identity associated with the given key id'
1517  assert key_id is not None
1518  cret = cryptframe_whois_key_id(str(key_id))
1519  if not cret:
1520  return None
1521  return str(cret)
1522 
1523  @staticmethod
1524  def get_dest_identity(destaddr):
1525  'Return the identity associated with this pyNetAddr'
1526  key_id = pyCryptFrame.get_dest_key_id(destaddr)
1527  if key_id is None:
1528  return None
1529  return pyCryptFrame.get_identity(key_id)
1530 
1531  @staticmethod
1532  def get_dest_key_id(destaddr):
1533  'Return the key_id associated with this pyNetAddr'
1534  cret = cryptframe_get_dest_key_id(destaddr._Cstruct)
1535  if not cret:
1536  return None
1537  return str(cret)
1538 
1539  @staticmethod
1540  def dest_set_key_id(destaddr, key_id):
1541  '''Set the public key we should use when talking to the given destination
1542  address (including port).
1543  '''
1544  if not destaddr._Cstruct or key_id is None:
1545  raise ValueError('illegal parameters')
1546  if not cryptframe_set_dest_key_id(destaddr._Cstruct, str(key_id)):
1547  raise ValueError("Inappropriate key_id %s" % key_id)
1548 
1549 
1550 #This is a bizarre and buggy complaint...
1551 #AssimCclasses.py:1283: [R0904:pyCryptCurve25519] Too many public methods (21/20)
1552 #pylint: disable=R0904
1554  '''Encryption Frame based on Libsodium - Curve25519 public key encryption.
1555  Strangely enough, we may not actually use objects of this class - because it's
1556  effectively hidden by the C code from us having to know about it.
1557 
1558  Instead we just manage public keys, and map IP addresses to public keys
1559  and the C code under us takes care of the rest in terms of creating these objects.
1560  '''
1561  def __init__(self, publickey_id=None, privatekey_id=None, Cstruct=None):
1562  self._Cstruct = None
1563  if Cstruct is None:
1564  Cstruct = cryptcurve25519_new(FRAMETYPE_CRYPTCURVE25519, publickey_id, privatekey_id, 0)
1565  pyCryptFrame.__init__(self, Cstruct=Cstruct)
1566 
1567  @staticmethod
1568  def key_id_to_filename(key_id, keytype):
1569  'Translate a key_id to a filename'
1570  ret = curve25519_key_id_to_filename(key_id, keytype)
1571  pyret = string_at(ret.raw)
1572  g_free(ret)
1573  return pyret
1574 
1575  @staticmethod
1576  def initkeys():
1577  '''Initialize our set of persistent public keys / keypairs and get ready to encrypt.
1578  This involves several steps:
1579  1) Read in all available public and private keys
1580  2) If we have no CMA keys, then generate two keypairs and give instructions
1581  on hiding the second one...
1582  2) Figure out which private keys are ours and select which one (oldest) to use
1583  as our preferred signing key
1584  3) set the default signing method
1585 
1586  Note that there are still two issues that this doesn't deal with:
1587  Persisting the association between nanoprobe keys ids and (domain, hostname) pairs
1588  Assigning default IP addresses with nanoprobe key ids.
1589  '''
1590  warnings = []
1592  cma_ids = pyCryptFrame.get_cma_key_ids()
1593  cma_ids.sort()
1594  if len(cma_ids) == 0:
1595  warnings.append('No CMA keys found. Generating two CMA key-pairs to start.')
1596  for keyid in (0, 1):
1597  print >> sys.stderr, "Generating key id", keyid
1598  cryptcurve25519_gen_persistent_keypair('%s%05d' % (CMA_KEY_PREFIX, keyid))
1600  cma_ids = pyCryptFrame.get_cma_key_ids()
1601  elif len(cma_ids) == 1:
1602  lastkey = cma_ids[0]
1603  lastseqno = int(lastkey[len(CMA_KEY_PREFIX):])
1604  newkeyid = ('%s%05d' % (CMA_KEY_PREFIX, lastseqno + 1))
1605  warnings.append('Generating an additional CMA key-pair.')
1608  cma_ids = pyCryptFrame.get_cma_key_ids()
1609  if len(cma_ids) != 2:
1610  warnings.append('Unexpected number of CMA keys. Expecting 2, but got %d.'
1611  % len(cma_ids))
1612  # We want to use the lowest-numbered private key we have access to.
1613  privatecount = 0
1614  extras = []
1615  cma_ids.sort()
1616  for keyid in cma_ids:
1617  pyCryptFrame.associate_identity(CMA_IDENTITY_NAME, keyid)
1618  if cryptframe_private_key_by_id(keyid):
1619  privatecount += 1
1620  if privatecount == 1:
1622  else:
1623  extras.append(keyid)
1624  if privatecount < 1:
1625  raise RuntimeError('FATAL: No CMA private keys to sign with!')
1626  if privatecount != 1:
1627  warnings.append('Incorrect number of Private CMA keys. Expecting 1, but got %d.'
1628  % len(cma_ids))
1629  warnings.append('YOU MUST SECURELY HIDE all but one private CMA key.')
1630  for keyid in extras:
1631  warnings.append('SECURELY HIDE *private* key %s' %
1632  pyCryptCurve25519.key_id_to_filename(keyid, pyCryptFrame.PRIVATEKEY))
1634  return warnings
1635 
1636 
1638  'Class for Frame Sets - for collections of Frames making up a logical packet'
1639  def __init__(self, framesettype, Cstruct=None):
1640  'Initializer for pyFrameSet'
1641  if Cstruct is None:
1642  Cstruct = frameset_new(framesettype)
1643  pyAssimObj.__init__(self, Cstruct=Cstruct)
1644 
1645  def append(self, frame):
1646  'Append a frame to the end of a @ref FrameSet'
1647  frameset_append_frame(self._Cstruct, frame._Cstruct)
1648 
1649  def prepend(self, frame):
1650  'Prepend a frame before the first frame in a @ref FrameSet'
1651  frameset_prepend_frame(self._Cstruct, frame._Cstruct)
1652 
1653  def construct_packet(self, signframe, cryptframe=None, compressframe=None):
1654  'Construct packet from curent frameset + special prefix frames'
1655  cf = None
1656  cmpf = None
1657  if cryptframe is not None:
1658  cf = cryptframe._Cstruct
1659  if compressframe is not None:
1660  cmpf = compressframe._Cstruct
1661  frameset_construct_packet(self._Cstruct, signframe._Cstruct, cf, cmpf)
1662 
1663  def get_framesettype(self):
1664  'Return frameset type of this FrameSet'
1665  return self._Cstruct[0].fstype
1666 
1667  def get_flags(self):
1668  'Return current flags for this FrameSet'
1669  return frameset_get_flags(self._Cstruct)
1670 
1671  def set_flags(self, flags):
1672  "'OR' the given flags into the set of flags for this FrameSet"
1673  return frameset_set_flags(self._Cstruct, int(flags))
1674 
1675  def clear_flags(self, flags):
1676  "Clear the given flags for this FrameSet"
1677  return frameset_clear_flags(self._Cstruct, int(flags))
1678 
1679  def sender_key_id(self):
1680  'Return the key_id of the cryptographic sender of this FrameSet'
1681  #print >> sys.stderr, 'TYPE(self)', type(self), 'str(self)', str(self), type(self._Cstruct)
1682  ret = frameset_sender_key_id(self._Cstruct)
1683  #print >> sys.stderr, 'sender_key_id: TYPE(ret)', type(ret), 'ret', ret, \
1684  # 'raw', ret.raw, 'data', ret.data
1685  #print >> sys.stderr, 'sender_key_id: str(ret)', str(ret), type(str(ret)), not ret
1686  #print type(ret.raw), ret.raw
1687  if not ret:
1688  #print >> sys.stderr, 'Returning None(!)', self.get_framesettype()
1689  return None
1690  pyret = string_at(ret.raw)
1691  #print >> sys.stderr, 'PYRET:', type(pyret), 'pyret:', pyret
1692  return pyret
1693 
1694  def sender_identity(self):
1695  'Return the identity of the cryptographic sender of this FrameSet'
1696  cret = frameset_sender_identity(self._Cstruct)
1697  if not cret:
1698  return None
1699  return str(cret)
1700 
1701  def dump(self):
1702  'Dump out the given frameset'
1703  frameset_dump(self._Cstruct)
1704 
1705  def getpacket(self):
1706  'Return the constructed packet for this pyFrameSet'
1707  if not self._Cstruct[0].packet:
1708  raise ValueError("No packet constructed for frameset")
1709  return (self._Cstruct[0].packet, self._Cstruct[0].pktend)
1710 
1711  def __len__(self):
1712  'Return the number of Frames in this pyFrameSet'
1713  # This next statement OUGHT to work - and indeed it returns the right value
1714  # But somehow, 'self' doesn't get freed like it ought to :-(
1715  # BUG??
1716  #return g_slist_length(self._Cstruct[0].framelist)
1717  # So, let's do this instead...
1718  curframe = self._Cstruct[0].framelist
1719  count = 0
1720  while curframe:
1721  count += 1
1722  curframe = g_slist_next(curframe)
1723  return int(count)
1724 
1725  def __delitem__(self, key):
1726  "Fail - we don't implement this"
1727  raise NotImplementedError("FrameSet does not implement __delitem__()")
1728 
1729  def __getitem__(self, key):
1730  "Fail - we don't implement this"
1731  raise NotImplementedError("FrameSet does not implement __getitem__()")
1732 
1733  def __setitem__(self, key, value):
1734  "Fail - we don't implement this"
1735  raise NotImplementedError("FrameSet does not implement __setitem__()")
1736 
1737  def iter(self):
1738  'Generator yielding the set of pyFrames in this pyFrameSet'
1739  curframe = self._Cstruct[0].framelist
1740  while curframe:
1741  cast(curframe[0].data, struct__GSList._fields_[0][1])
1742  yieldval = pyFrame.Cstruct2Frame(cast(curframe[0].data, cClass.Frame))
1743  #print >> sys.stderr, ("Constructed frame IS [%s]" % str(yieldval))
1744  if not yieldval.isvalid():
1745  print >> sys.stderr \
1746  , "OOPS! Constructed %d byte frame from iter() is not valid [%s]" \
1747  % (yieldval.framelen(), str(yieldval))
1748  raise ValueError("Constructed %d byte frame from iter() is not valid [%s]"
1749  % (yieldval.framelen(), str(yieldval)))
1750  #print "Yielding:", str(yieldval), "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
1751  yield yieldval
1752  curframe = g_slist_next(curframe)
1753 
1754  def fstypestr(self):
1755  'Return the frameset type name as a string'
1756  return FrameSetTypes.get(self.get_framesettype())[0]
1757 
1758  def __str__(self):
1759  'Convert this pyFrameSet to a String'
1760  result = '%s:{' % self.fstypestr()
1761  comma = ''
1762  for frame in self.iter():
1763  result += '%s[%d]%s' % (comma, frame.framelen(), str(frame))
1764  comma = ', '
1765  result += "}"
1766  return result
1767 
1768 
1769 
1771  'Class for Decoding packets - for returning an array of FrameSets from a physical packet.'
1772  def __init__(self, Cstruct=None):
1773  'Initializer for pyPacketDecoder'
1774  if Cstruct is None:
1775  Cstruct = packetdecoder_new(0, None, 0)
1776  pyAssimObj.__init__(self, Cstruct=Cstruct)
1777 
1778  def fslist_from_pktdata(self, pktlocation):
1779  'Make a list of FrameSets out of a packet.'
1780  base = self._Cstruct[0]
1781  while not_this_exact_type(base, AssimCtypes.PacketDecoder):
1782  base = base.baseclass
1783  fs_gslistint = base.pktdata_to_framesetlist(self._Cstruct, pktlocation[0], pktlocation[1])
1784  return pyPacketDecoder.fslist_to_pyfs_array(fs_gslistint)
1785 
1786  @staticmethod
1787  def fslist_to_pyfs_array(listheadint):
1788  'Converts a GSList of FrameSets to a python array of pyFrameSets'
1789  fs_gslist = cast(listheadint, cClass.GSList)
1790  frameset_list = []
1791  curfs = fs_gslist
1792  while curfs:
1793  cfs = cast(curfs[0].data, cClass.FrameSet)
1794  fs = pyFrameSet(None, Cstruct=cfs)
1795  frameset_list.append(fs)
1796  curfs = g_slist_next(curfs)
1797  g_slist_free(fs_gslist)
1798  return frameset_list
1799 
1800 # R0904: Too many public methods
1801 #pylint: disable=R0904
1803  'Class for Holding configuration information - now a general JSON-compatible data bag'
1804 
1805  def __init__(self, init=None, filename=None, Cstruct=None):
1806  'Initializer for pyConfigContext'
1807  self._Cstruct = None # Keep error legs from complaining.
1808  if not Cstruct:
1809  # Cstruct overrides init and filename
1810  if filename is not None:
1811  f = open(filename, 'r')
1812  # filename overrides init
1813  init = f.read()
1814  f.close()
1815  if isinstance(init, str) or isinstance(init, unicode):
1816  Cstruct = configcontext_new_JSON_string(str(init))
1817  if not Cstruct:
1818  raise ValueError('Bad JSON [%s]' % str(init))
1819  init = None
1820  else:
1821  Cstruct = configcontext_new(0)
1822  pyAssimObj.__init__(self, Cstruct=Cstruct)
1823  if init is not None:
1824  for key in init.keys():
1825  self[key] = init[key]
1826 
1827 
1828  def getint(self, name):
1829  'Return the integer associated with "name"'
1830  return self._Cstruct[0].getint(self._Cstruct, name)
1831 
1832  def setint(self, name, value):
1833  'Set the integer associated with "name"'
1834  self._Cstruct[0].setint(self._Cstruct, name, value)
1835 
1836  def getbool(self, name):
1837  'Return the boolean associated with "name"'
1838  return self._Cstruct[0].getbool(self._Cstruct, name) != 0
1839 
1840  def setbool(self, name, value):
1841  'Set the boolean associated with "name"'
1842  self._Cstruct[0].setbool(self._Cstruct, name, bool(value))
1843 
1844  def getfloat(self, name):
1845  'Return the floating point value associated with "name"'
1846  return self._Cstruct[0].getdouble(self._Cstruct, name)
1847 
1848  def setfloat(self, name, value):
1849  'Set the floating point value associated with "name"'
1850  self._Cstruct[0].setdouble(self._Cstruct, name, float(value))
1851 
1852  def getaddr(self, name):
1853  'Return the NetAddr associated with "name"'
1854  naddr = self._Cstruct[0].getaddr(self._Cstruct, name)
1855  if naddr:
1856  naddr = cast(naddr, cClass.NetAddr)
1857  # We're creating a new reference to the pre-existing NetAddr
1858  CCref(naddr)
1859  return pyNetAddr(None, Cstruct=naddr)
1860  raise IndexError("No such NetAddr value [%s]" % name)
1861 
1862  def setaddr(self, name, value):
1863  'Set the @ref NetAddr associated with "name"'
1864  self._Cstruct[0].setaddr(self._Cstruct, name, value._Cstruct)
1865 
1866  def getframe(self, name):
1867  'Return the Frame associated with "name"'
1868  faddr = self._Cstruct[0].getframe(self._Cstruct, name)
1869  if faddr:
1870  # Cstruct2Frame already calls CCref()
1871  return pyFrame.Cstruct2Frame(faddr)
1872  raise IndexError("No such Frame value [%s]" % name)
1873 
1874  def setframe(self, name, value):
1875  'Set the @ref Frame associated with "name"'
1876  self._Cstruct[0].setframe(self._Cstruct, name, value._Cstruct)
1877 
1878  def getconfig(self, name):
1879  'Return the pyConfigContext object associated with "name"'
1880  caddr = self._Cstruct[0].getconfig(self._Cstruct, name)
1881  if caddr:
1882  caddr = cast(caddr, cClass.ConfigContext)
1883  # We're creating a new reference to the pre-existing NetAddr
1884  CCref(caddr)
1885  return pyConfigContext(Cstruct=caddr)
1886  raise IndexError("No such ConfigContext value [%s]" % name)
1887 
1888  def setconfig(self, name, value):
1889  'Set the @ref ConfigContext associated with "name"'
1890  self._Cstruct[0].setconfig(self._Cstruct, name, value._Cstruct)
1891 
1892  def getstring(self, name):
1893  'Return the string associated with "name"'
1894  ret = self._Cstruct[0].getstring(self._Cstruct, name)
1895  if ret:
1896  return string_at(ret)
1897  raise IndexError("No such String value [%s]" % name)
1898 
1899  def setstring(self, name, value):
1900  'Set the string associated with "name"'
1901  self._Cstruct[0].setstring(self._Cstruct, name, value)
1902 
1903  def getarray(self, name):
1904  'Return the array value associated with "name"'
1905  curlist = cast(self._Cstruct[0].getarray(self._Cstruct, name), cClass.GSList)
1906  #print >> sys.stderr, "CURLIST(initial) = %s" % curlist
1907  ret = []
1908  while curlist:
1909  #print >> sys.stderr, "CURLIST = %s" % curlist
1910  #cfgval = pyConfigValue(cast(cClass.ConfigValue, curlist[0].data).get())
1911  data = cast(curlist[0].data, cClass.ConfigValue)
1912  #print >> sys.stderr, "CURLIST->data = %s" % data
1913  CCref(data)
1914  cfgval = pyConfigValue(data).get()
1915  #print >> sys.stderr, "CURLIST->data->get() = %s" % cfgval
1916  ret.append(cfgval)
1917  curlist = g_slist_next(curlist)
1918  return ret
1919 
1920  def setarray(self, name, value):
1921  'Set a ConfigContext key value to be a sequence of values from an iterable'
1922  self._Cstruct[0].setarray(self._Cstruct, name, None)
1923  for elem in value:
1924  if isinstance(elem, bool):
1925  self._Cstruct[0].appendbool(self._Cstruct, name, elem)
1926  continue
1927  if isinstance(elem, (int, long)):
1928  self._Cstruct[0].appendint(self._Cstruct, name, elem)
1929  continue
1930  if isinstance(elem, float):
1931  self._Cstruct[0].appendfloat(self._Cstruct, name, elem)
1932  continue
1933  if isinstance(elem, str):
1934  self._Cstruct[0].appendstring(self._Cstruct, name, elem)
1935  continue
1936  if isinstance(elem, pyNetAddr):
1937  self._Cstruct[0].appendaddr(self._Cstruct, name, elem)
1938  continue
1939  if isinstance(elem, pyConfigContext):
1940  self._Cstruct[0].appendconfig(self._Cstruct, name, elem._Cstruct)
1941  continue
1942  if isinstance(elem, dict):
1943  cfgctx = pyConfigContext.from_dict(elem)
1944  self._Cstruct[0].appendconfig(self._Cstruct, name, cfgctx._Cstruct)
1945  continue
1946  raise ValueError("Cannot append/include array elements of type %s" % type(elem))
1947 
1948  @staticmethod
1949  def from_dict(dictval):
1950  'Construct a pyConfigContext from a dict-like object'
1951  newobj = pyConfigContext()
1952  for key in dictval.keys():
1953  keyval = dictval[key]
1954  if hasattr(keyval, 'keys'):
1955  keyval = pyConfigContext.from_dict(dictval[key])
1956  newobj[key] = dictval[key]
1957  return newobj
1958 
1959  def keys(self):
1960  'Return the set of keys for this object'
1961  l = []
1962  keylist = cast(self._Cstruct[0].keys(self._Cstruct), POINTER(GSList))
1963  curkey = keylist
1964  while curkey:
1965  l.append(string_at(curkey[0].data))
1966  curkey = g_slist_next(curkey)
1967  g_slist_free(keylist)
1968  return l
1969 
1970  def __iter__(self):
1971  'Iterate over self.keys()'
1972  for key in self.keys():
1973  yield key
1974 
1975  def gettype(self, name):
1976  '''Return the enumeration type of this particular key
1977  @todo Convert these enums to python types'''
1978  #print >> sys.stderr, 'gettype(%s)' % str(name)
1979  return self._Cstruct[0].gettype(self._Cstruct, str(name))
1980 
1981  def get(self, key, alternative=None):
1982  '''return value if object contains the given key - 'alternative' if not'''
1983  if self._Cstruct[0].gettype(self._Cstruct, str(key)) == CFG_EEXIST:
1984  return alternative
1985  return self[key]
1986 
1987  # pylint R0911: too many returns (9)
1988  # pylint: disable=R0911
1989  def deepget(self, key, alternative=None):
1990  '''return value if object contains the given *structured* key - 'alternative' if not'''
1991  try:
1992  (prefix, suffix) = key.split('.', 1)
1993  except ValueError:
1994  suffix = None
1995  prefix = key
1996  if prefix not in self:
1997  # Note that very similar code exists in GraphNodes get member function
1998  if not prefix.endswith(']'):
1999  return alternative
2000  else:
2001  # Looks like we have an array index
2002  proper = prefix[0:len(prefix)-1]
2003  try:
2004  (preprefix, idx) = proper.split('[', 1)
2005  except ValueError:
2006  return alternative
2007  if preprefix not in self:
2008  return alternative
2009  try:
2010  array = self[preprefix]
2011  idx = int(idx) # Possible ValueError
2012  value = array[idx] # possible IndexError or TypeError
2013  if suffix is None:
2014  return value
2015  except (TypeError, IndexError, ValueError):
2016  return alternative
2017  return value.deepget(suffix, alternative)
2018 
2019  prefixvalue = self[prefix]
2020  if suffix is None:
2021  return prefixvalue
2022  if not isinstance(prefixvalue, pyConfigContext):
2023  return alternative
2024  gotten = prefixvalue.deepget(suffix, alternative)
2025  return gotten
2026 
2027  def has_key(self, key):
2028  'return True if it has the given key'
2029  return self.__contains__(key)
2030 
2031  def __contains__(self, key):
2032  'return True if our object contains the given key'
2033  ktype = self._Cstruct[0].gettype(self._Cstruct, str(key))
2034  return ktype != CFG_EEXIST
2035 
2036  def __len__(self):
2037  'Return the number of items in this pyConfigContext'
2038  keylist = cast(self._Cstruct[0].keys(self._Cstruct), POINTER(GSList))
2039  llen = g_slist_length(keylist)
2040  g_slist_free(keylist)
2041  return llen
2042 
2043  def __delitem__(self, key):
2044  "Delete the given item"
2045  self._Cstruct[0].delkey(self._Cstruct, str(key))
2046 
2047  def __getitem__(self, name):
2048  'Return a value associated with "name"'
2049  name = str(name)
2050  ktype = self.gettype(name)
2051  #print >> sys.stderr, '************ GETITEM[%s] => %d *********************' % (name, ktype)
2052  if ktype == CFG_EEXIST:
2053  traceback.print_stack()
2054  raise IndexError("No such value [%s] in [%s]" % (name, str(self)))
2055  elif ktype == CFG_CFGCTX:
2056  return self.getconfig(name)
2057  elif ktype == CFG_STRING:
2058  return self.getstring(name)
2059  elif ktype == CFG_NETADDR:
2060  return self.getaddr(name)
2061  elif ktype == CFG_FRAME:
2062  return self.getframe(name)
2063  elif ktype == CFG_INT64:
2064  return self.getint(name)
2065  elif ktype == CFG_FLOAT:
2066  return self.getfloat(name)
2067  elif ktype == CFG_BOOL:
2068  return self.getbool(name)
2069  elif ktype == CFG_ARRAY:
2070  #print >> sys.stderr, '************ GETITEM[%s] => getarray(%s) *********************' \
2071  # % (name, name)
2072  return self.getarray(name)
2073  return None
2074 
2075  def __setitem__(self, name, value):
2076  'Set a value associated with "name" - in the appropriate table'
2077  if isinstance(value, str):
2078  return self.setstring(name, value)
2079  if isinstance(value, unicode):
2080  return self.setstring(name, str(value))
2081  if isinstance(value, pyNetAddr):
2082  return self.setaddr(name, value)
2083  if isinstance(value, pyFrame):
2084  return self.setframe(name, value)
2085  if isinstance(value, pyConfigContext):
2086  return self.setconfig(name, value)
2087  if isinstance(value, dict):
2088  return self.setconfig(name, pyConfigContext(value))
2089  if isinstance(value, (list, tuple)) or hasattr(value, '__iter__'):
2090  return self.setarray(name, value)
2091  if isinstance(value, float):
2092  return self.setfloat(name, value)
2093  if isinstance(value, dict):
2094  return self.setconfig(name, pyConfigContext.from_dict(value))
2095  if isinstance(value, bool):
2096  return self.setbool(name, value)
2097  self.setint(name, int(value))
2098 
2100  'A Python wrapper for a C implementation of something like a Python Dictionary'
2101  def __init__(self, Cstruct):
2102  'Initializer for pyConfigValue - now a subclass of pyAssimObj'
2103  pyAssimObj.__init__(self, Cstruct=Cstruct)
2104 
2105  def __str__(self):
2106  'Convert the given pyConfigValue to a String'
2107  str(self.get())
2108 
2109  # Too many returns
2110  # pylint: disable=R0911
2111  def get(self):
2112  'Return the value of this object'
2113  ret = None
2114  vtype = self._Cstruct[0].valtype
2115  if vtype == CFG_BOOL:
2116  return self._Cstruct[0].u.intvalue != 0
2117  elif vtype == CFG_INT64:
2118  return int(self._Cstruct[0].u.intvalue)
2119  elif vtype == CFG_STRING:
2120  return str(self._Cstruct[0].u.strvalue)
2121  elif vtype == CFG_FLOAT:
2122  return float(self._Cstruct[0].u.floatvalue)
2123  elif vtype == CFG_CFGCTX:
2124  # We're creating a new reference to the pre-existing NetAddr
2125  CCref(self._Cstruct[0].u.cfgctxvalue)
2126  return pyConfigContext(Cstruct=self._Cstruct[0].u.cfgctxvalue)
2127  elif vtype == CFG_NETADDR:
2128  net = pyNetAddr(None, Cstruct=self._Cstruct[0].u.addrvalue)
2129  # We're creating a new reference to the pre-existing NetAddr
2130  CCref(net._Cstruct)
2131  return net
2132  elif vtype == CFG_FRAME:
2133  # Cstruct2Frame calls CCref() - so we don't need to
2134  return pyFrame.Cstruct2Frame(self._Cstruct[0].u.framevalue)
2135  elif vtype == CFG_ARRAY:
2136  # An Array is a linked list (GSList) of ConfigValue objects...
2137  ret = []
2138  this = self._Cstruct[0].u.arrayvalue
2139  while this:
2140  dataptr = cast(this[0].data, struct__GSList._fields_[0][1])
2141  dataptr = cast(dataptr, cClass.ConfigValue)
2142  CCref(dataptr)
2143  thisobj = pyConfigValue(cast(dataptr, cClass.ConfigValue)).get()
2144  ret.append(thisobj)
2145  this = g_slist_next(this)
2146  return ret
2147  elif vtype == CFG_NULL:
2148  return None
2149  raise ValueError('Invalid valtype (%s)in pyConfigValue object' % self._Cstruct.valtype)
2150 
2152  'A Network I/O object - with a variety of subclasses'
2153  CONN_NONE = 0 # FSPR_NONE -- Apparently ctypesgen doesn't do enum values...
2154  CONN_INIT = 1 # FSPR_INIT
2155  CONN_UP = 2 # FSPR_UP
2156  CONN_SHUT1 = 3 # FSPR_SHUT1
2157  CONN_SHUT2 = 4 # FSPR_SHUT2
2158  CONN_SHUT3 = 5 # FSPR_SHUT3
2159 
2160  def __init__(self, configobj, packetdecoder, Cstruct=None):
2161  'Initializer for pyNetIO'
2162  self._Cstruct = None # Keep error legs from complaining.
2163  if Cstruct is None:
2164  Cstruct = netio_new(0, configobj._Cstruct, packetdecoder._Cstruct)
2165  self.config = configobj
2166  else:
2167  self._Cstruct = Cstruct
2168  base = self._Cstruct[0]
2169  while not hasattr(base, '_configinfo'):
2170  base = base.baseclass
2171  self.config = pyConfigContext(Cstruct=base._configinfo)
2172  CCref(base._configinfo)
2173  pyAssimObj.__init__(self, Cstruct=Cstruct)
2174 
2175  def setblockio(self, mode):
2176  'Set this NetIO object to blocking IO mode'
2177  base = self._Cstruct[0]
2178  while not hasattr(base, 'setblockio'):
2179  base = base.baseclass
2180  return base.setblockio(self._Cstruct, int(mode))
2181 
2182  def fileno(self):
2183  'Return the file descriptor for this pyNetIO object'
2184  base = self._Cstruct[0]
2185  while not hasattr(base, 'getfd'):
2186  base = base.baseclass
2187  return base.getfd(self._Cstruct)
2188 
2189  def bindaddr(self, addr, silent=False):
2190  'Bind the socket underneath this NetIO object to the given address'
2191  base = self._Cstruct[0]
2192  while not hasattr(base, 'bindaddr'):
2193  base = base.baseclass
2194  return base.bindaddr(self._Cstruct, addr._Cstruct, silent)
2195 
2196  def boundaddr(self):
2197  'Return the socket underlying this NetIO object'
2198  base = self._Cstruct[0]
2199  while not hasattr(base, 'bindaddr'):
2200  base = base.baseclass
2201  boundaddr = base.boundaddr(self._Cstruct)
2202  # We're creating a new reference to the pre-existing NetAddr
2203  ret = pyNetAddr(None, Cstruct=boundaddr)
2204  CCref(boundaddr)
2205  return ret
2206 
2207  def getrcvbufsize(self):
2208  'Return the receive buffer size for this socket'
2209  base = self._Cstruct[0]
2210  while not hasattr(base, 'getsockbufsize'):
2211  base = base.baseclass
2212  return base.getsockbufsize(self._Cstruct, True)
2213 
2214  def setrcvbufsize(self, bufsize):
2215  'Set and return the receive buffer size for this socket'
2216  base = self._Cstruct[0]
2217  while not hasattr(base, 'setsockbufsize'):
2218  base = base.baseclass
2219  return base.setsockbufsize(self._Cstruct, True, bufsize)
2220 
2221  def getsendbufsize(self):
2222  'Return the output buffer size for this socket'
2223  base = self._Cstruct[0]
2224  while not hasattr(base, 'getsockbufsize'):
2225  base = base.baseclass
2226  return base.getsockbufsize(self._Cstruct, False)
2227 
2228  def setsendbufsize(self, bufsize):
2229  'Return the output buffer size for this socket'
2230  base = self._Cstruct[0]
2231  while not hasattr(base, 'setsockbufsize'):
2232  base = base.baseclass
2233  return base.setsockbufsize(self._Cstruct, False, bufsize)
2234 
2235  def mcastjoin(self, addr):
2236  'Join the underlying socket to the given multicast address'
2237  base = self._Cstruct[0]
2238  while not hasattr(base, 'mcastjoin'):
2239  base = base.baseclass
2240  return base.mcastjoin(self._Cstruct, addr._Cstruct, None)
2241 
2242  def getmaxpktsize(self):
2243  'Return the max packet size for this pyNetIO'
2244  base = self._Cstruct[0]
2245  while not hasattr(base, 'getmaxpktsize'):
2246  base = base.baseclass
2247  return base.getmaxpktsize(self._Cstruct)
2248 
2249  def setmaxpktsize(self, size):
2250  'Set the max packet size for this pyNetIO'
2251  base = self._Cstruct[0]
2252  while not hasattr(base, 'setmaxpktsize'):
2253  base = base.baseclass
2254  return base.setmaxpktsize(self._Cstruct, int(size))
2255 
2256  def compressframe(self):
2257  'Return the compression frame for this pyNetIO - may be None'
2258  # Doesn't make a py class object out of it yet...
2259  base = self._Cstruct[0]
2260  while not hasattr(base, 'compressframe'):
2261  base = base.baseclass
2262  return base.compressframe(self._Cstruct)
2263 
2264  def signframe(self):
2265  'Return the digital signature frame for this pyNetIO'
2266  base = self._Cstruct[0]
2267  while not hasattr(base, 'signframe'):
2268  base = base.baseclass
2269  return pySignFrame(0, Cstruct=cast(base.signframe(self._Cstruct), cClass.SignFrame))
2270 
2271  def connstate(self, peeraddr, qid=DEFAULT_FSP_QID):
2272  'Return the state of this connection - return value is one of the pyNetIO constants'
2273  fsproto = self._Cstruct[0]._protocol
2274  return fsproto[0].connstate(fsproto, qid, peeraddr._Cstruct)
2275 
2276  def connactive(self, peeraddr, qid=DEFAULT_FSP_QID):
2277  '''Return TRUE if this connection is active.
2278  That is, if it's established and not in shutdown.
2279  Note that the presence of timeouts doesn't make a connection inactive.
2280  We can time out for days and still think the connection is active.
2281  '''
2282  connstate = self.connstate(peeraddr, qid)
2283  return connstate == pyNetIO.CONN_INIT or connstate == pyNetIO.CONN_UP
2284 
2285  def sendframesets(self, destaddr, framesetlist):
2286  'Send the (collection of) frameset(s) out on this pyNetIO'
2287  if destaddr.port() == 0:
2288  raise ValueError("Zero Port in sendframesets: destaddr=%s" % str(destaddr))
2289  if not isinstance(framesetlist, collections.Sequence):
2290  framesetlist = (framesetlist, )
2291  base = self._Cstruct[0]
2292  while not hasattr(base, 'sendaframeset'):
2293  base = base.baseclass
2294  # We ought to eventually construct a GSList of them and then call sendframesets
2295  # But this is easy for now...
2296  for frameset in framesetlist:
2297  base.sendaframeset(self._Cstruct, destaddr._Cstruct, frameset._Cstruct)
2298 
2299  def sendreliablefs(self, destaddr, framesetlist, qid=DEFAULT_FSP_QID):
2300  'Reliably send the (collection of) frameset(s) out on this pyNetIO (if possible)'
2301  if destaddr.port() == 0:
2302  raise ValueError("Zero Port in sendreliablefs: destaddr=%s" % str(destaddr))
2303  if not isinstance(framesetlist, collections.Sequence):
2304  framesetlist = (framesetlist, )
2305  base = self._Cstruct[0]
2306  while not hasattr(base, 'sendaframeset'):
2307  base = base.baseclass
2308  for frameset in framesetlist:
2309  success = base.sendareliablefs(self._Cstruct, destaddr._Cstruct, qid, frameset._Cstruct)
2310  if not success:
2311  raise IOError("sendareliablefs(%s, %s) failed." % (destaddr, frameset))
2312 
2313  def ackmessage(self, destaddr, frameset):
2314  'ACK (acknowledge) this frameset - (presumably sent reliably).'
2315 
2316  base = self._Cstruct[0]
2317  while not hasattr(base, 'ackmessage'):
2318  base = base.baseclass
2319  base.ackmessage(self._Cstruct, destaddr._Cstruct, frameset._Cstruct)
2320 
2321  def closeconn(self, qid, destaddr):
2322  'Close (reset) our connection to this address'
2323  base = self._Cstruct[0]
2324  while not hasattr(base, 'closeconn'):
2325  base = base.baseclass
2326  print >> sys.stderr, ('RESETTING CONNECTION (closeconn) TO %s' % str(destaddr))
2327  base.closeconn(self._Cstruct, qid, destaddr._Cstruct)
2328 
2329  def addalias(self, fromaddr, toaddr):
2330  'Close (reset) our connection to this address'
2331 
2332  base = self._Cstruct[0]
2333  while not hasattr(base, 'addalias'):
2334  base = base.baseclass
2335  base.addalias(self._Cstruct, fromaddr._Cstruct, toaddr._Cstruct)
2336 
2337  def recvframesets(self):
2338  '''Receive a collection of framesets read from this pyNetIO - all from the same Address.
2339  @return The return value is a tuple (address, framesetlist). '''
2340  #GSList * _netio_recvframesets (NetIO *self,NetAddr **src)
2341 
2342  base = self._Cstruct[0]
2343  while not hasattr(base, 'recvframesets'):
2344  base = base.baseclass
2345  netaddrint = netaddr_ipv4_new(create_string_buffer(4), 101)
2346  netaddr = cast(netaddrint, cClass.NetAddr)
2347  netaddr[0].baseclass.unref(netaddr) # We're about to replace it...
2348  # Basically we needed a pointer to pass, and this seemed like a good way to do it...
2349  # Maybe it was -- maybe it wasn't... It's a pretty expensive way to get this effect...
2350  fs_gslistint = base.recvframesets(self._Cstruct, byref(netaddr))
2351  fslist = pyPacketDecoder.fslist_to_pyfs_array(fs_gslistint)
2352  if netaddr and len(fslist) > 0:
2353  # recvframesets gave us that 'netaddr' for us to dispose of - there are no other refs
2354  # to it so we should NOT 'CCref' it. It's a new object - not a pointer to an old one.
2355  address = pyNetAddr(None, Cstruct=netaddr)
2356  else:
2357  address = None
2358  return (address, fslist)
2359 
2360  @staticmethod
2362  'Return True if our OS supports a dual IPv4/IPv6 stack'
2364 
2366  'UDP version of the pyNetIO abstract base class'
2367  def __init__(self, config, packetdecoder, Cstruct=None):
2368  'Initializer for pyNetIOudp'
2369  self._Cstruct = None # Keep error legs from complaining.
2370  if Cstruct is None:
2371  Cstruct = netioudp_new(0, config._Cstruct, packetdecoder._Cstruct)
2372  if not Cstruct:
2373  raise ValueError("Invalid parameters to pyNetIOudp constructor")
2374  pyNetIO.__init__(self, config, packetdecoder, Cstruct=Cstruct)
2375 
2377  'Reliable UDP version of the pyNetIOudp abstract base class'
2378  def __init__(self, config, packetdecoder, rexmit_timer_uS=0, Cstruct=None):
2379  'Initializer for pyReliableUDP'
2380  self._Cstruct = None # Keep error legs from complaining.
2381  if Cstruct is None:
2382  Cstruct = reliableudp_new(0, config._Cstruct, packetdecoder._Cstruct, rexmit_timer_uS)
2383  if not Cstruct:
2384  raise ValueError("Invalid parameters to pyReliableUDP constructor")
2385  pyNetIOudp.__init__(self, config, packetdecoder, Cstruct=Cstruct)
2386 
2387  def log_conn(self, destaddr, qid=DEFAULT_FSP_QID):
2388  'Log connection status/info to system logs'
2389  base = self._Cstruct[0]
2390  while not_this_exact_type(base, ReliableUDP):
2391  base = base.baseclass
2392  base.log_conn(self._Cstruct, qid, destaddr._Cstruct)
2393 
2394 class CMAlib(object):
2395  'Miscellaneous functions to create certain useful pyFrameSets'
2396 
2397  def __init__(self):
2398  'Do-nothing init function'
2399  pass
2400 
2401  @staticmethod
2403  'Create a setconfig FrameSet'
2404  fs = cast(create_setconfig(cfg._Cstruct), cClass.FrameSet)
2405  return pyFrameSet(None, Cstruct=fs)
2406 
2407  @staticmethod
2408  def create_sendexpecthb(cfg, msgtype, address):
2409  'Create a Send/Expect heartbeat FrameSet'
2410  ucfs = create_sendexpecthb(cfg._Cstruct, int(msgtype)
2411  , address._Cstruct, 1)
2412  fs = cast(ucfs, cClass.FrameSet)
2413  return pyFrameSet(None, Cstruct=fs)
2414 
2415 class pyPcapCapture(object):
2416  'Class to read binary packets from pcap packet capture files'
2417  def __init__(self, filename):
2418  self._Cstruct = pcap_capture_iter_new(filename)
2419  if not self._Cstruct:
2420  raise ValueError('Invalid parameters to pyPcapCapture constructor')
2421  # I'm saving this here because for some unclear reason it goes to None...
2422  self.destructor = pcap_capture_iter_del
2423 
2424  def __del__(self):
2425  'Clean up our pcap capture file descriptor'
2426  if self._Cstruct:
2427  self.destructor(self._Cstruct)
2428  self._Cstruct = None
2429 
2430  def __iter__(self):
2431  pktlen = c_int()
2432  pktend = cClass.guint8()
2433  ret = pcap_capture_iter_next(self._Cstruct, byref(pktend), byref(pktlen))
2434  if not ret:
2435  self.destructor(self._Cstruct)
2436  self._Cstruct = None
2437  return
2438  yield (cast(ret, cClass.guint8), pktend, int(pktlen.value))
2439 
2441  'Dump out live objects to help locate memory leaks'
2442  print >> sys.stderr, 'GC Garbage: [%s]' % str(gc.garbage)
2443  print >> sys.stderr, '***************LOOKING FOR pyAssimObjs***********'
2444  get_referrers = True
2445  cobjcount = 0
2446  gc.collect()
2447  for obj in gc.get_objects():
2448  if isinstance(obj, (pyAssimObj, pyCstringFrame)):
2449  cobjcount += 1
2450  cobj = 'None'
2451  if hasattr(obj, '_Cstruct') and obj._Cstruct is not None:
2452  cobj = ('0x%x' % addressof(getattr(obj, '_Cstruct')[0]))
2453  print >> sys.stderr, ('FOUND C object class(%s): %s -> %s'
2454  % (obj.__class__.__name__, str(obj)[:512], cobj))
2455  if get_referrers:
2457 
2458  print >> sys.stderr, ('%d python wrappers referring to %d C-objects'
2459  % (cobjcount, proj_class_live_object_count()))
2461 
2462 def follow_referrer_back(obj, level=0, maxlevel=4):
2463  'Follow and print object referrer chains back through "maxlevel" levels'
2464  print >> sys.stderr, ('++++%sREFERRERS' % (level * '**'))
2465  for referrer in gc.get_referrers(obj):
2466  if isinstance(referrer, (list, types.FrameType)):
2467  continue
2468  print >> sys.stderr, ('++++%sReferred to by(%s): %s'
2469  % (level * '**', type(referrer), str(referrer)[:512]))
2470  if level < maxlevel:
2471  follow_referrer_back(referrer, level+1)
2472 
2473 if __name__ == '__main__':
2475  'Code to minimally exercise the pyPcapCapture class'
2476  for f in ('../pcap/cdp_v2.pcap', '../pcap/lldp.detailed.pcap'):
2477  print 'Capture file: %s' % f
2478  capture = pyPcapCapture(f)
2479  for results in capture:
2480  (pkt, pktend, pktlen) = results
2481  print 'Pkt', pkt, 'pktend', pktend, 'pktlen', pktlen
WINEXPORT gboolean cryptframe_set_dest_key_id(NetAddr *destaddr, const char *key_id)
Set the encryption key to use when sending to destaddr Set destkey to NULL to stop encrypting to that...
Definition: cryptframe.c:470
guint16 frameset_set_flags(FrameSet *fs, guint16 flagbits)
Set (OR in) the given set of FrameSet flags.
Definition: frameset.c:319
WINEXPORT const void * get_cdptlv_next(const void *tlv_vp, const void *tlv_vpend)
Locate the next CDP TLV triple (iterator).
Definition: cdp_min.c:271
void frameset_dump(const FrameSet *fs)
Dump out a FrameSet.
Definition: frameset.c:365
ConfigContext * configcontext_new_JSON_string(const char *jsontext)
Construct a ConfigContext object from the given JSON string.
WINEXPORT GList * cryptframe_get_key_ids(void)
Return a GList of strings of all known key ids.
Definition: cryptframe.c:397
WINEXPORT guint16 get_cdptlv_type(const void *tlv_vp, const void *pktend)
Return type from the given TLV triplet in a CDP packet.
Definition: cdp_min.c:196
WINEXPORT void cryptcurve25519_set_encryption_method(void)
Function just to make setting the encryption method simpler from Python.
SeqnoFrame * seqnoframe_new(guint16 frametype, int objsize)
Construct new SeqnoFrame object.
Definition: seqnoframe.c:211
WINEXPORT AddrFrame * addrframe_new(guint16 frame_type, gsize framesize)
Construct a new AddrFrame class - allowing for "derived" frame types...
Definition: addrframe.c:201
def setconfig(self, name, value)
guint16 frameset_get_flags(FrameSet *fs)
Return the flags currently set on this FrameSet.
Definition: frameset.c:311
def bindaddr(self, addr, silent=False)
CryptCurve25519 * cryptcurve25519_new(guint16 frame_type, const char *sender_key_id, const char *receiver_key_id, gboolean forsending, gsize objsize)
Construct a new CryptCurve25519 object (frame).
WINEXPORT char * cryptcurve25519_gen_persistent_keypair(const char *giveitaname)
Create a persistent keypair and write it to disk Returns a MALLOCed string with the key id for the ke...
guint16 frameset_clear_flags(FrameSet *fs, guint16 flagbits)
Clear the given set of FrameSet flags (& ~flagbits)
Definition: frameset.c:329
WINEXPORT gboolean is_valid_cdp_packet(const void *packet, const void *pktend)
Check to see if this is a valid CDP packet.
Definition: cdp_min.c:94
def __init__(self, init=None, filename=None, Cstruct=None)
NetIOudp * netioudp_new(gsize objsize, ConfigContext *config, PacketDecoder *decoder)
Construct new UDP NetIO object (and its socket, etc)
Definition: netioudp.c:52
guint8 tlv_get_guint8(const void *vitem, const void *bufend)
Retrieve an unsigned 8 bit integer from the given location with error checking.
Definition: tlvhelper.c:31
WINEXPORT IpPortFrame * ipportframe_ipv6_new(guint16 frame_type, guint16 port, gconstpointer addr)
Construct and initialize an IPv6 IpPortFrame class.
Definition: ipportframe.c:217
def __setitem__(self, key, value)
def __init__(self, framesettype, Cstruct=None)
WINEXPORT SignFrame * signframe_glib_new(GChecksumType sigtype, gsize framesize)
Construct a new SignFrame - allowing for "derived" frame types...
Definition: signframe.c:334
def construct_packet(self, signframe, cryptframe=None, compressframe=None)
WINEXPORT IpPortFrame * ipportframe_netaddr_new(guint16 frame_type, NetAddr *addr)
Construct and initialize an IpPortFrame class from a IP NetAddr class.
Definition: ipportframe.c:234
guint64 tlv_get_guint64(const void *vitem, const void *bufend)
Retrieve an unsigned 64 bit integer from the given location with error checking and without caring ab...
Definition: tlvhelper.c:108
NetAddr * netaddr_dns_new(const char *sysname_or_addr)
Create a NetAddr from a DNS name or an ipv4 or ipv6 constant string.
Definition: netaddr.c:1004
IntFrame * intframe_new(guint16 frametype, int intbytes)
Construct new IntFrame object.
Definition: intframe.c:179
NetAddr * netaddr_mac64_new(gconstpointer macbuf)
Create new NetAddr from a MAC64 address.
Definition: netaddr.c:1077
def decode_discovery(host, interface, instance, wallclock, pktstart, pktend)
WINEXPORT gboolean cryptframe_associate_identity(const char *identity, const char *key_id)
Associate the given key id with the given identity Note that it is OK to associate multiple key ids w...
Definition: cryptframe.c:293
def fslist_from_pktdata(self, pktlocation)
FrameSet * frameset_new(guint16 frameset_type)
Construct a new frameset of the given type.
Definition: frameset.c:110
NetAddr * netaddr_ipv4_new(gconstpointer ipbuf, guint16 port)
Create new NetAddr from a IPv4 address.
Definition: netaddr.c:1084
WINEXPORT const char * frameset_sender_identity(const FrameSet *self)
Return the identity of this Frameset&#39;s CryptFrame sender – NULL if None or Unknown.
Definition: frameset.c:451
UnknownFrame * unknownframe_new(guint16 frame_type)
Construct a new UnknownFrame - disallowing for "derived" frame types...
Definition: unknownframe.c:55
WINEXPORT const void * get_cdptlv_first(const void *pkt, const void *pktend)
Return the first CDP TLV triple in a CDP packet.
Definition: cdp_min.c:240
PacketDecoder * packetdecoder_new(guint objsize, const FrameTypeToFrame *framemap, gint mapsize)
Initialize our frame type map.
Definition: packetdecoder.c:77
def connactive(self, peeraddr, qid=DEFAULT_FSP_QID)
def setaddr(self, name, value)
WINEXPORT CryptFrame * cryptframe_new_by_destaddr(const NetAddr *destaddr)
Construct a CryptFrame class appropriate for encrypting messages to destaddr
Definition: cryptframe.c:488
NetAddr * netaddr_mac48_new(gconstpointer macbuf)
Create new NetAddr from a MAC48 address.
Definition: netaddr.c:1070
def setbool(self, name, value)
WINEXPORT const char * cryptframe_whois_key_id(const char *key_id)
Return the identity associated with the given key id.
Definition: cryptframe.c:371
WINEXPORT const char * cryptframe_get_dest_key_id(const NetAddr *destaddr)
Return the key_id associated with the given destination address.
Definition: cryptframe.c:504
def setint(self, name, value)
void frameset_append_frame(FrameSet *fs, Frame *f)
Append frame to the front of the end of the frame list.
Definition: frameset.c:143
guint8 get_lldptlv_type(const void *tlv_vp, const void *pktend)
Return the &#39;Type&#39; of the given LLDP TLV entry The Type is the high order 7 bits from the zeroth byte ...
Definition: lldp_min.c:83
def toIPv6(self, port=None)
WINEXPORT gsize get_cdptlv_len(const void *tlv_vp, const void *pktend)
Return size of the given TLV triplet.
Definition: cdp_min.c:206
def associate_identity(identityname, key_id)
guint32 tlv_get_guint32(const void *vitem, const void *bufend)
Retrieve an unsigned 32 bit integer from the given location with error checking and without caring ab...
Definition: tlvhelper.c:81
def __init__(self, initval, Cstruct=None)
def __init__(self, frametype, initval=None, intbytes=4, Cstruct=None)
Frame * frame_new(guint16 frame_type, gsize framesize)
Construct a new frame - allowing for "derived" frame types...
Definition: frame.c:125
def get(self, key, alternative=None)
def _init_from_binary(self, addrstring, port)
def __init__(self, gchecksumtype, Cstruct=None)
def setarray(self, name, value)
gboolean netio_is_dual_ipv4v6_stack(void)
Definition: netio.c:954
NetAddr * netaddr_ipv6_new(gconstpointer ipbuf, guint16 port)
Create new NetAddr from a IPv6 address.
Definition: netaddr.c:1092
def setvalue(self, value)
def __init__(self, config, packetdecoder, Cstruct=None)
FSTATIC CryptFramePrivateKey * cryptframe_private_key_by_id(const char *key_id)
Return the non-const private key with the given id.
Definition: cryptframe.c:279
guint32 tlv_get_guint24(const void *vitem, const void *bufend)
Retrieve an unsigned 24 bit (3-byte) integer from the given location with error checking and without ...
Definition: tlvhelper.c:133
def setsendbufsize(self, bufsize)
def sendreliablefs(self, destaddr, framesetlist, qid=DEFAULT_FSP_QID)
def getcdpaddresses(tlvlen, tlvstart, pktend)
WINEXPORT char * curve25519_key_id_to_filename(const char *key_id, enum keytype ktype)
WINEXPORT struct pcap_capture_iter * pcap_capture_iter_new(const char *capture_filename)
Definition: pcap_min.c:254
guint32 proj_class_live_object_count(void)
Return the count of live C class objects.
Definition: proj_classes.c:406
WINEXPORT const char * frameset_sender_key_id(const FrameSet *self)
Return the key_id of this Frameset&#39;s CryptFrame sender – NULL if None.
Definition: frameset.c:434
def __setitem__(self, name, value)
def ackmessage(self, destaddr, frameset)
def connstate(self, peeraddr, qid=DEFAULT_FSP_QID)
def dest_set_key_id(destaddr, key_id)
def __init__(self, configobj, packetdecoder, Cstruct=None)
def key_id_to_filename(key_id, keytype)
ReliableUDP * reliableudp_new(gsize objsize, ConfigContext *config, PacketDecoder *decoder, guint rexmit_timer_uS)
Construct new UDP NetIO object (and its socket, etc)
Definition: reliableudp.c:69
def __init__(self, addrstring, port=None, Cstruct=None)
def setblockio(self, mode)
AssimObj * assimobj_new(guint objsize)
Definition: assimobj.c:74
def log_conn(self, destaddr, qid=DEFAULT_FSP_QID)
const char * proj_class_classname(gconstpointer object)
Return the class name of one of our managed objects.
Definition: proj_classes.c:324
NVpairFrame * nvpairframe_new(guint16 frame_type, gchar *name, gchar *value, gsize framesize)
Construct a new NVpairFrame - allowing for "derived" frame types...
Definition: nvpairframe.c:101
def __init__(self, frametype=FRAMETYPE_COMPRESS, compression_method=COMPRESS_ZLIB, Cstruct=None)
const void * get_lldptlv_first(const void *packet, const void *pktend)
Definition: lldp_min.c:195
def __init__(self, frametype, name, value, Cstruct=None)
def __init__(self, frametype, initval=None, Cstruct=None)
def getNint(tlvptr, tlvlen, pktend)
def setfloat(self, name, value)
void frameset_prepend_frame(FrameSet *fs, Frame *f)
Prepend frame to the front of the frame list.
Definition: frameset.c:132
def __init__(self, frametype, addrstring=None, port=None, Cstruct=None)
def __init__(self, Cstruct=None)
def closeconn(self, qid, destaddr)
#define MALLOC(nbytes)
should it just call g_malloc?
Definition: projectcommon.h:26
def follow_referrer_back(obj, level=0, maxlevel=4)
def sendframesets(self, destaddr, framesetlist)
def __init__(self, frametype, initval=None, Cstruct=None)
void frameset_construct_packet(FrameSet *fs, SignFrame *sigframe, CryptFrame *cryptframe, CompressFrame *compressframe)
Construct packet to go correspond to this frameset.
Definition: frameset.c:159
def _init_from_binary(self, frametype, addrstring, port)
WINEXPORT const void * get_cdptlv_body(const void *tlv_vp, const void *pktend)
Return the body (value) blob of a CDP TLV triplet.
Definition: cdp_min.c:229
def __init__(self, publickey_id=None, privatekey_id=None, Cstruct=None)
gboolean is_valid_lldp_packet(const void *tlv_vp, const void *pktend)
Definition: lldp_min.c:116
def __init__(self, frametype, Cstruct=None)
WINEXPORT IpPortFrame * ipportframe_ipv4_new(guint16 frame_type, guint16 port, gconstpointer addr)
Construct and initialize an IPv4 IpPortFrame class.
Definition: ipportframe.c:199
def addalias(self, fromaddr, toaddr)
NetIO * netio_new(gsize objsize, ConfigContext *config, PacketDecoder *decoder)
NetIO constructor.
Definition: netio.c:488
def not_this_exact_type(obj, cls)
def dump(self, prefix)
def create_sendexpecthb(cfg, msgtype, address)
WINEXPORT void cryptframe_set_signing_key_id(const char *key_id)
Set the default signing key.
Definition: cryptframe.c:416
const void * get_lldptlv_next(const void *tlv_vp, const void *pktend)
Return pointer to the next LLDP TLV entry after the current location.
Definition: lldp_min.c:209
def __init__(self, destaddr=None, Cstruct=None)
gsize get_lldptlv_len(const void *tlv_vp, const void *pktend)
Return the &#39;Length&#39; of the given LLDP TLV entry.
Definition: lldp_min.c:93
void proj_class_dump_live_objects(void)
Dump all live C class objects (address and Class)
Definition: proj_classes.c:356
ConfigContext * configcontext_new(gsize objsize)
Construct a new ConfigContext object - with no values defaulted.
CompressFrame * compressframe_new_string(guint16 frame_type, const char *compression_name)
def setframe(self, name, value)
def setmaxpktsize(self, size)
WINEXPORT void cryptcurve25519_cache_all_keypairs(void)
We read in and cache all the key pairs (or public keys) that we find in CRYPTKEYDIR.
def setrcvbufsize(self, bufsize)
def deepget(self, key, alternative=None)
guint16 tlv_get_guint16(const void *vitem, const void *bufend)
Retrieve an unsigned 16 bit integer from the given location with error checking and without caring ab...
Definition: tlvhelper.c:55
WINEXPORT const guint8 * pcap_capture_iter_next(struct pcap_capture_iter *iter, const guint8 **pktend, guint *pktlen)
Definition: pcap_min.c:285
def __init__(self, frametype, addrstring, port=None, Cstruct=None)
def setstring(self, name, value)
WINEXPORT CstringFrame * cstringframe_new(guint16 frame_type, gsize framesize)
Construct a new CstringFrame - allowing for "derived" frame types...
Definition: cstringframe.c:101
def __init__(self, Cstruct=None)
const void * get_lldptlv_body(const void *tlv_vp, const void *pktend)
Return the &#39;Value&#39; of the given LLDP TLV entry.
Definition: lldp_min.c:106
def toIPv4(self, port=None)
def __init__(self, config, packetdecoder, rexmit_timer_uS=0, Cstruct=None)