Sunday, January 31, 2010

OpenBSD and Python

Last time we covered FreeBSD's third party module, freebsd; this time we'll take a quick look at the equivalent openbsd package for the OpenBSD operating system.

$ python2.5
Python 2.5.4 (r254:67916, Jul  1 2009, 11:37:21)
[GCC 3.3.5 (propolice)] on openbsd4
Type "help", "copyright", "credits" or "license" for more information.
>>> import openbsd
>>> dir(openbsd)
['__builtins__', '__doc__', '__file__', '__name__', '__path__', '_ifconfig', '_netstat', '_packetDescriptors', '_pcap', '_sysvar', 'arc4random', 'ifconfig', 'netstat', 'packet', 'pcap', 'utils']

Let's see what all is hidden in that utils item:

>>> dir(openbsd.utils)
['DoubleAssociation', '__builtins__', '__doc__', '__file__', '__name__', 'cksum16', 'ethToBytes', 'ethToStr', 'findLongestSubsequence', 'getBlocks', 'ip6FromPrefix', 'ip6ToBytes', 'ip6ToStr', 'ipFromPrefix', 'ipToBytes', 'ipToStr', 'isIP6Addr', 'isIPAddr', 'isStringLike', 'multichar', 'multiord']

OK, a fair number of network addressing related functions.

help(openbsd.utils.ipFromPrefix)

ipFromPrefix(prefix)
    Produce an IPv4 address (netmask) from a prefix length.

That sounds handy.  Let's give it a shot:

>>> openbsd.utils.ipFromPrefix(24)
'255.255.255.0'

>>> help(openbsd.utils.DoubleAssociation)

Help on class DoubleAssociation in module openbsd.utils:

class DoubleAssociation(__builtin__.dict)
 |  A double-association is a broadminded dictionary - it goes both ways.
 |
 |  The rather simple implementation below requires the keys and values to
 |  be two disjoint sets. That is, if a given value is both a key and a
 |  value in a DoubleAssociation, you get unexpected behaviour.
 |
 |  Method resolution order:
 |      DoubleAssociation
 |      __builtin__.dict
 |      __builtin__.object
 |
 |  Methods defined here:
 |
 |  __init__(self, idict=None)
 |      # FIXME:
 |      #   While DoubleAssociation is adequate for our use, it is not entirely complete:
 |      #       - Deletion should delete both associations
 |      #       - Other dict methods that set values (eg. setdefault) will need to be over-ridden.



This one is kind of interesting - let's have a look:

>>> d = {1:'a', 2:'b', 3:'c'}
>>> d.get(1)
'a'
>>> print d.get('a')
None
>>> da = openbsd.utils.DoubleAssociation(d)
>>> da.get(1)
'a'
>>> da.get('a')
1

Just like the doc described it.  Both the keys and the values are keys, if that makes sense.

Back up to the main modules of the openbsd package:

>>> help(openbsd.arc4random)







NAME
    openbsd.arc4random

FILE
    /usr/local/lib/python2.5/site-packages/openbsd/arc4random.so

FUNCTIONS
    getbytes(...)
        Get some random bytes.






And the result -




>>> bytesx = openbsd.arc4random.getbytes(10)
>>> [bytex for bytex in bytesx]
['\xb4', '\xd1', '\x86', '\xb7', 'g', '8', '\x10', '}', '\x8b', '\xe5']



One last module on a more common theme:

NAME
    openbsd.ifconfig - A Python module for querying and manipulating network interfaces.

FILE
    /usr/local/lib/python2.5/site-packages/openbsd/ifconfig.py

CLASSES
    __builtin__.int(__builtin__.object)
        FlagVal
    __builtin__.object
        Flags
        IFConfig
        Interface
        MTU
        Media
        Metric
    exceptions.Exception(exceptions.BaseException)
        _ifconfig.IfConfigError

    class FlagVal(__builtin__.int)
     |  Method resolution order:
(etc.)
    

>>> intx = openbsd.ifconfig.Interface('rl0')
>>> print intx
rl0: flags=8843 mtu 1500
         media: Ethernet autoselect
         link: 00:30:bd:72:6a:a0
         inet6: fe80:2::230:bdff:fe72:6aa0
         inet: 192.168.100.100
>>> dir(intx)
['Iftype', 'Name', '__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_addrToStr', '_addrTypeLookup', '_getAddresses', '_getinfo', '_setflags', '_setmetric', '_setmtu', 'addAddress', 'addresses', 'delAddress', 'flags', 'media', 'metric', 'mtu', 'setAddress']
>>> intx.media
media: Ethernet autoselect
>>> intx.addresses
[{'address': {'sa_family': 18L, 'iftype': 'ETHER', 'address': '00:30:bd:72:6a:a0'}}, {'netmask': {'sa_family': 24L, 'address': 'ffff:ffff:ffff:ffff::'}, 'address': {'sa_family': 24L, 'address': 'fe80:2::230:bdff:fe72:6aa0'}}, {'netmask': {'sa_family': 0L, 'address': None}, 'dstaddr': {'sa_family': 2L, 'address': '192.168.100.255'}, 'address': {'sa_family': 2L, 'address': '192.168.100.100'}}]
>>>   


ifconfig available within Python - sweet.  rl0 is the ethernet device on my old Dell tower.

Examination of the openbsd package shows that it has quite a bit to offer.  If you're using OpenBSD, there's nothing stopping you from doing routine sysadmin tasks with Python.  If not, now you've got a reason to check it out.

2 comments:

  1. That looks handy. You should consider adding freebsd & openbsd support to PSI http://bitbucket.org/chrismiles/psi/

    Cheers,
    Chris

    ReplyDelete
  2. Chris,
    Thanks for the heads up. I was ignorant of PSI's existence.
    Not sure I'm up to contributing to PSI, but I'll probably make use of it soon.
    Carl T.

    ReplyDelete