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