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