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