OpenBSD Journal

A necessary evil: snmpd(8) and snmpctl(8)

Contributed by jason on from the .1.3.6.1.4.1.2021.11.9.0 dept.

Reyk Floeter writes in to tell us about his work on a new SNMP implementation...

I just imported snmpd(8) and snmpctl(8), an initial attempt to implement a new SNMP daemon for OpenBSD. SNMP is the "Simple Network Management Protocol" and it is still very commonly used in corporate networks, by network vendors, and in network management systems (NMS).

SNMP is very essential for me since I'm using it at work; our security appliances based on OpenBSD need to integrate into various SNMP scenarios. We had to use net-snmp for this; the BSD license is good but the code is very bad and full of ancient cruft and portability glue. Then there were many problems with the net-snmp port in OpenBSD, people reported 90% CPU usage on -misc, crashes, bugs, ...it was just a pain.

So I decided to have a look at SNMP to implement something new. When we don't like the existing alternatives or ports, we tend to re-implement it in OpenBSD, right? Having a new snmpd(8) using privilege separation, the imsg framework from ospfd/bgpd, knf, "security in mind", and a nice control program like snmpctl(8) would be really nice and solve some of our problems. And I knew that claudio@ already started working on a little ASN.1 BER implementation for another project; this was the perfect base for handling the annoying BER-encoding of SNMP messages.

I talked to some people during OpenCON about my idea and the initial code that I was working on. The expected reaction was always like "This is nice, but I don't like SNMP". SNMP is a necessary evil. People are upset and happy at the same time; will it be possible to implement a sane SNMP? Will it be possible to make it secure?

The code is still in a very early stage, snmpctl(8) is mostly a stub without any functionality, and the implemented MIBs are limited to (most of) the MIB-2, SNMPv3-MIB, and the IF-MIB. I plan to implement the IP-MIB, TCP-MIB, UDP-MIB, and BRIDGE-MIB next and continue with working on the daemon's infrastructure. There needs to be a way to talk to other daemons in OpenBSD without using SNMP BER messages: IMSG. snmpd(8) may connect to the daemons, query some IMSG information, and provide the SNMP MIBs for the outside world. I also plan to export some useful information like sensor status in an OpenBSD-specific MIB.

I DON'T want to provide a plug-in or module API, people can use net-snmp if they need a hyper-extensible codebase.

The daemon is currently based on the SNMPv2/3 RFCs, supporting SNMPv1/2 messages and a very simple community-based security model (SNMPv2c). The User-based Security Model (USM) will be added later, but the complexity of the new SNMPv3 standards is a little bit scary; they turned a simple protocol into a mess of layers, modules, and abstractions. There is also a very interesting draft about a SSH-based security model for SNMP (draft-ietf-isms-secshell), but it is defined by Cizzco and Huawai...

Sure, I'm looking for volunteers to test and to contribute to snmpd(8), have a look at the src/usr.sbin/snmpd/README file and the code in the OpenBSD source tree. It is not enabled in the builds yet and it will take some time before we are satisfied enough to enable it. Again, please don't propose any useless features XYZ, it is good to have net-snmp for all the additional foo.

reyk

For example, I get the following output when I query the new snmpd(8) with the snmpwalk tool from net-snmp:

# client: snmpwalk from net-snmp, server: new OpenBSD snmpd(8)
sysDescr = STRING: OpenBSD john.hq.vantronix.net 4.2 GENERIC.MP#6 amd64
sysObjectID = OID: enterprises.26766.42.2.1.42
sysUpTime = Timeticks: (2472) 0:00:24.72
sysContact = STRING: root@john.hq.vantronix.net
sysName = STRING: john.hq.vantronix.net
sysLocation = STRING: 
sysServices = INTEGER: 74
sysORLastChange = Timeticks: (0) 0:00:00.00
sysORIndex.1 = INTEGER: 1
sysORIndex.2 = INTEGER: 2
sysORIndex.3 = INTEGER: 3
sysORID.1 = OID: mib-2
sysORID.2 = OID: snmp
sysORID.3 = OID: ifMIB
sysORDescr.1 = STRING: iso.org.dod.internet.mgmt.mib-2
sysORDescr.2 = STRING: iso.org.dod.internet.mgmt.mib-2.snmp
sysORDescr.3 = STRING: iso.org.dod.internet.mgmt.mib-2.ifMIB
sysORUpTime.1 = Timeticks: (0) 0:00:00.00
sysORUpTime.2 = Timeticks: (0) 0:00:00.00
sysORUpTime.3 = Timeticks: (0) 0:00:00.00
ifNumber = INTEGER: 4
ifIndex.1 = INTEGER: 1
ifIndex.2 = INTEGER: 2
ifIndex.3 = INTEGER: 3
ifIndex.4 = INTEGER: 4
ifDescr.1 = STRING: em0
ifDescr.2 = STRING: ath0
ifDescr.3 = STRING: enc0
ifDescr.4 = STRING: lo0
ifType.1 = INTEGER: ethernetCsmacd(6)
ifType.2 = INTEGER: ethernetCsmacd(6)
ifType.3 = INTEGER: other(1)
ifType.4 = INTEGER: softwareLoopback(24)
ifMtu.1 = INTEGER: 1500
ifMtu.2 = INTEGER: 1500
ifMtu.3 = INTEGER: 1536
ifMtu.4 = INTEGER: 33168
ifSpeed.1 = Gauge32: 1000000000
ifSpeed.2 = Gauge32: 54000000
ifSpeed.3 = Gauge32: 0
ifSpeed.4 = Gauge32: 0
ifPhysAddress.1 = STRING: 0:1a:6b:36:2e:5
ifPhysAddress.2 = STRING: 0:16:cf:ab:4c:97
ifPhysAddress.3 = STRING: 
ifPhysAddress.4 = STRING: 
ifAdminStatus.1 = INTEGER: up(1)
ifAdminStatus.2 = INTEGER: down(2)
ifAdminStatus.3 = INTEGER: down(2)
ifAdminStatus.4 = INTEGER: up(1)
ifOperStatus.1 = INTEGER: up(1)
ifOperStatus.2 = INTEGER: down(2)
ifOperStatus.3 = INTEGER: down(2)
ifOperStatus.4 = INTEGER: unknown(4)
ifLastChange.1 = Timeticks: (2474) 0:00:24.74
ifLastChange.2 = Timeticks: (2474) 0:00:24.74
ifLastChange.3 = Timeticks: (2474) 0:00:24.74
ifLastChange.4 = Timeticks: (2474) 0:00:24.74
ifInOctets.1 = Counter32: 28675019
ifInOctets.2 = Counter32: 0
ifInOctets.3 = Counter32: 0
ifInOctets.4 = Counter32: 395717
ifInUcastPkts.1 = Counter32: 85059
ifInUcastPkts.2 = Counter32: 0
ifInUcastPkts.3 = Counter32: 0
ifInUcastPkts.4 = Counter32: 2473
ifInNUcastPkts.1 = Counter32: 267
ifInNUcastPkts.2 = Counter32: 0
ifInNUcastPkts.3 = Counter32: 0
ifInNUcastPkts.4 = Counter32: 0
ifInDiscards.1 = Counter32: 0
ifInDiscards.2 = Counter32: 0
ifInDiscards.3 = Counter32: 0
ifInDiscards.4 = Counter32: 0
ifInErrors.1 = Counter32: 0
ifInErrors.2 = Counter32: 0
ifInErrors.3 = Counter32: 0
ifInErrors.4 = Counter32: 0
ifInUnknownProtos.1 = Counter32: 0
ifInUnknownProtos.2 = Counter32: 0
ifInUnknownProtos.3 = Counter32: 0
ifInUnknownProtos.4 = Counter32: 0
ifOutOctets.1 = Counter32: 8354604
ifOutOctets.2 = Counter32: 0
ifOutOctets.3 = Counter32: 0
ifOutOctets.4 = Counter32: 400397
ifOutUcastPkts.1 = Counter32: 60000
ifOutUcastPkts.2 = Counter32: 0
ifOutUcastPkts.3 = Counter32: 0
ifOutUcastPkts.4 = Counter32: 2521
ifOutNUcastPkts.1 = Counter32: 0
ifOutNUcastPkts.2 = Counter32: 0
ifOutNUcastPkts.3 = Counter32: 0
ifOutNUcastPkts.4 = Counter32: 0
ifOutDiscards.1 = Counter32: 0
ifOutDiscards.2 = Counter32: 0
ifOutDiscards.3 = Counter32: 0
ifOutDiscards.4 = Counter32: 0
ifOutErrors.1 = Counter32: 0
ifOutErrors.2 = Counter32: 0
ifOutErrors.3 = Counter32: 0
ifOutErrors.4 = Counter32: 0
ifOutQLen.1 = Gauge32: 0
ifOutQLen.2 = Gauge32: 0
ifOutQLen.3 = Gauge32: 0
ifOutQLen.4 = Gauge32: 0
ifSpecific.1 = OID: zeroDotZero
ifSpecific.2 = OID: zeroDotZero
ifSpecific.3 = OID: zeroDotZero
ifSpecific.4 = OID: zeroDotZero
snmpInPkts = Counter32: 338
snmpOutPkts = Counter32: 335
snmpInBadVersions = Counter32: 0
snmpInBadCommunityNames = Counter32: 3
snmpInBadCommunityUses = Counter32: 0
snmpInASNParseErrs = Counter32: 0
snmpInTooBigs = Counter32: 0
snmpInNoSuchNames = Counter32: 0
snmpInBadValues = Counter32: 0
snmpInReadOnlys = Counter32: 0
snmpInGenErrs = Counter32: 344
snmpInTotalReqVars = Counter32: 0
snmpInTotalSetVars = Counter32: 0
snmpInGetRequests = Counter32: 0
snmpInGetNexts = Counter32: 352
snmpInSetRequests = Counter32: 0
snmpInGetResponses = Counter32: 0
snmpInTraps = Counter32: 0
snmpOutTooBigs = Counter32: 0
snmpOutNoSuchNames = Counter32: 0
snmpOutBadValues = Counter32: 0
snmpOutGenErrs = Counter32: 0
snmpOutGetRequests = Counter32: 0
snmpOutGetNexts = Counter32: 0
snmpOutSetRequests = Counter32: 0
snmpOutGetResponses = Counter32: 0
snmpOutTraps = Counter32: 0
snmpEnableAuthenTraps = INTEGER: disabled(2)
snmpSilentDrops = Count

(Comments are closed)


Comments
  1. By Paul 'WEiRD' de Weerd (2001:6f8:110a:0:21b:63ff:fe05:4982) weerd@weirdnet.nl on http://www.weirdnet.nl/

    > but the complexity of the new SNMPv3 standards is a little bit scary;

    Got to love the S in SNMP...

    Anyway, this is very cool stuff. Thanks Reyk !

    Comments
    1. By Justin (216.17.75.76) on

      > > but the complexity of the new SNMPv3 standards is a little bit scary;
      >
      > Got to love the S in SNMP...
      >
      > Anyway, this is very cool stuff. Thanks Reyk !

      I thought SNMP stood for Security's Not My Problem? Haha

      This is really cool. It's like that Pinky and the Brain - with everything OpenBSD is rewriting to be done properly whats next in the pipeline? Is it "try to take over the world" haha

  2. By Reyk Floeter (83.246.89.10) reyk@openbsd.org on http://team.vantronix.net/~reyk/

    The snmpwalk output got a little bit truncated... it doesn't really matter that much but the actual MIB implementation originally provided some more information about my laptop... ;)

    reyk

    Comments
    1. By scot bontrager (sbontrager) on

      > The snmpwalk output got a little bit truncated... it doesn't really matter that much but the actual MIB implementation originally provided some more information about my laptop... ;)
      >
      > reyk
      >

      Thanks for this! I've flipped through the code and it is clean and brilliant.

      Any interest in supporting HOST-RESOURCES-MIB? I'd be willing to start working on it myself tomorrow. My last exam of the semester is in 3 hours and I need something to keep me busy for the next two months.

      I need HR for my monitoring platform (hrStorageTable--drive utilization specifically). I'd love to dump net-snmpd for something smaller and cleaner, but can't unless HR.hrStorageTable is supported. It looks like I should be able to write it myself, I'll send it upstream if you are interested in rolling it into the official code. But, if you are going to write it, I don't want to duplicate efforts.

      Comments
      1. By scot bontrager (sbontrager) on

        > > The snmpwalk output got a little bit truncated... it doesn't really matter that much but the actual MIB implementation originally provided some more information about my laptop... ;)
        > >
        > > reyk
        > >
        >
        > Thanks for this! I've flipped through the code and it is clean and brilliant.
        >
        > Any interest in supporting HOST-RESOURCES-MIB? I'd be willing to start working on it myself tomorrow. My last exam of the semester is in 3 hours and I need something to keep me busy for the next two months.
        >
        > I need HR for my monitoring platform (hrStorageTable--drive utilization specifically). I'd love to dump net-snmpd for something smaller and cleaner, but can't unless HR.hrStorageTable is supported. It looks like I should be able to write it myself, I'll send it upstream if you are interested in rolling it into the official code. But, if you are going to write it, I don't want to duplicate efforts.

        Also, I have a completely unused enterprise ID I'd be willing to GIVE to OpenBSD so you don't need to sub off of vantronix's EID (and it's less than half of vantronix's--11k instead of 26k).

        Comments
        1. By marklar (203.11.81.235) marklar_@hotmail.com on

          > Also, I have a completely unused enterprise ID I'd be willing to GIVE to OpenBSD so you don't need to sub off of vantronix's EID (and it's less than half of vantronix's--11k instead of 26k).

          I've got an unused one as well in the 10k range I'd be willing to give to OpenBSD... how low can we go :)

          Comments
          1. By Reyk Floeter (212.202.20.73) reyk@openbsd.org on http://team.vantronix.net/~reyk/

            > > Also, I have a completely unused enterprise ID I'd be willing to GIVE to OpenBSD so you don't need to sub off of vantronix's EID (and it's less than half of vantronix's--11k instead of 26k).
            >
            > I've got an unused one as well in the 10k range I'd be willing to give to OpenBSD... how low can we go :)

            Please stop offering your PENs. The .vantronix sub-ID is a temporary solution until I get a new and dedicated PEN for OpenBSD. Just wait.

      2. By Reyk Floeter (212.202.20.73) reyk@openbsd.org on http://team.vantronix.net/~reyk/

        > > The snmpwalk output got a little bit truncated... it doesn't really matter that much but the actual MIB implementation originally provided some more information about my laptop... ;)
        > >
        > > reyk
        > >
        >
        > Thanks for this! I've flipped through the code and it is clean and brilliant.
        >
        > Any interest in supporting HOST-RESOURCES-MIB? I'd be willing to start working on it myself tomorrow. My last exam of the semester is in 3 hours and I need something to keep me busy for the next two months.
        >
        > I need HR for my monitoring platform (hrStorageTable--drive utilization specifically). I'd love to dump net-snmpd for something smaller and cleaner, but can't unless HR.hrStorageTable is supported. It looks like I should be able to write it myself, I'll send it upstream if you are interested in rolling it into the official code. But, if you are going to write it, I don't want to duplicate efforts.

        i do not intend to implement it very soon, so do it if you want... you can send me patches, but no guarantee that it will be merged into the tree.


  3. By Anonymous Coward (63.227.45.5) on

    How does this compare to FreeBSD's bsnmpd?

  4. By Steve Shockley (68.80.137.106) steve@shockley.net on

    Will there be any support for traps? It'd be nice to be able to send alerts for example for a failed drive from bio, if you've got management tools already deployed that talk snmp but not syslog.

  5. By viridari (24.148.239.228) magnus@trilug.org on http://unixbeard.blogspot.com

    Outstanding! Just when you think OpenBSD can't get any better, something like this happens.

    snmp is still quite relevant and for better or for worse it is used pretty widely for NMS purposes.

    Honestly SNMPv3 is a PITA. I still use SNMPv2c and firewall rules. It's not perfect but it works fine for my purposes.

    It would be outstanding to see core OpenBSD technologies like pf, bioctl, ntpd, etc. report metrics through your new SNMP daemon.

    Comments
    1. By Anonymous Coward (82.75.29.106) on

      > How about a MIB for pf? :)

      And bgpd and ospfd and ripd, etc.

  6. By Anonymous Coward (85.180.157.26) on

    Did you take a look at FreeBSD's bsnmpd? Why reinvent the wheel?

    Comments
    1. By Motley Fool (MotleyFool) on

      > Did you take a look at FreeBSD's bsnmpd? Why reinvent the wheel?

      That's the same as saying "Why have OpenBSD?".

    2. By Anonymous Coward (69.244.79.72) on

      > Did you take a look at FreeBSD's bsnmpd? Why reinvent the wheel?

      It's called Not Invented Here Syndrome. The nominal excuse is that it uses loadable modules.

      Still, there's a dearth of good SNMP implementation; bsnmp is not clearly an excellent implementation, maybe only time could show that; so, you can't fault anyone for starting fresh.

    3. By Reyk Floeter (212.202.20.73) reyk@openbsd.org on http://team.vantronix.net/~reyk/

      > Did you take a look at FreeBSD's bsnmpd? Why reinvent the wheel?

      Oh man, I hate this "Why reinvent the wheel" phrase.

      I don't like bsnmpd, read my text - I want a simple design and not a modular extensible something. And that's what other people in OpenBSD think. But feel free to use bsnmpd or to submit a port.

      I drive an Audi A3 (sportback). It is a nice, fast car and they kind of reinvented the wheel! Why should I drive a huge pickup truck when there's no need to go off-road or to carry a quad...?

      Comments
      1. By Terrell Prude' Jr. (151.188.247.104) tprude@cmosnetworks.com (this is a spamtrap address) on http://www.cmosnetworks.com/

        > > Did you take a look at FreeBSD's bsnmpd? Why reinvent the wheel?
        >
        > Oh man, I hate this "Why reinvent the wheel" phrase.
        >
        > I don't like bsnmpd, read my text - I want a simple design and not a modular extensible something. And that's what other people in OpenBSD think. But feel free to use bsnmpd or to submit a port.
        >
        > I drive an Audi A3 (sportback). It is a nice, fast car and they kind of reinvented the wheel! Why should I drive a huge pickup truck when there's no need to go off-road or to carry a quad...?
        >

        Because it makes you feel manly and redneck-l33t? :-D

        As the driver of a "huge pickup truck", namely a Ford F-250 diesel, I'd like to say thank you for writing this new SNMP implementation. You're right; SNMP is a necessary evil. We use both NMIS and Nagios at my place of work. Nagios uses SNMP polling for some things, and NMIS uses SNMP polling for *everything*. Both are good applications that get the job done for us. And both apps are generally run with net-snmp today.

        It'll be neat to have another one written with security in mind from the get-go.

        Thanks, Reyk.

        --TP

  7. By Anonymous Coward (69.244.79.72) on

    I don't see what issue people have with ASN.1. The only difficult is lack of tools, but this project is awesome: http://lionet.info/asn1c/

    Not that all the daemons should use ASN.1 BER for IPC, but with an ASN.1 compiler which generates the C code you can actually *prove*, mathematically, that your parser, and the resulting C structure, doesn't have any errors. Proving asn1c is correct is another thing, but that's a single code base to verify, as opposed to N bases to verify--one for each individual project hand parsing ASN.1. Even if you're using a generic ASN.1 parser, there's still the gap between the generic library parser and filling in your C structure.

    ASN.1 is orders of magnitude preferable to XML for things like this. Of course, just because its better than XML doesn't make it suitable. But, still, ASN.1 gets a bad rap. asn1c makes it so much easier to use, I've written quite a few daemons using ASN.1 as the IPC layer. That way C# and Java folks can use ASN.1 XER to control the daemon; that is, they can use all their shiny XML tools, and my little C daemon isn't burdened.


    Comments
    1. By Anonymous Coward (74.133.153.234) on

      What is wrong with bsnmpd from FreeBSD? Why reinvent the wheel yet again?

  8. By Anonymous Coward (89.83.122.209) on

    I have just try snmpd :

    # snmpd -dv
    startup
    snmpe_bind: binding to address 127.0.0.1:161

    $ snmpwalk -v1 -c public 127.0.0.1
    Timeout: No Response from 127.0.0.1


    Output :

    snmpe_parse: 127.0.0.1: SNMPv1 'public' context 1 request 1495414086
    snmpe_parse: 127.0.0.1: oid iso.org.dod.internet.mgmt.mib-2
    check_child: lost child: snmp engine terminated; signal 11
    terminating


    It's because it's not implemented yet or what's wrong ?

    Comments
    1. By Anonymous Coward (83.246.81.11) on

      > I have just try snmpd :
      >
      > # snmpd -dv
      > startup
      > snmpe_bind: binding to address 127.0.0.1:161
      >
      > $ snmpwalk -v1 -c public 127.0.0.1
      > Timeout: No Response from 127.0.0.1
      >
      >
      > Output :
      >
      > snmpe_parse: 127.0.0.1: SNMPv1 'public' context 1 request 1495414086
      > snmpe_parse: 127.0.0.1: oid iso.org.dod.internet.mgmt.mib-2
      > check_child: lost child: snmp engine terminated; signal 11
      > terminating
      >
      >
      > It's because it's not implemented yet or what's wrong ?

      snmpd is new software which hasn't been enabled in the builds yet. but i don't think undeadly.org is the right place for "bug reports", use tech@openbsd.org or send a private mail.
      yes, there might be bugs. wait until it is -stable or write a real bug report to the author.

      Comments
      1. By Anonymous Coward (89.83.122.209) on

        > > I have just try snmpd :
        > >
        > > # snmpd -dv
        > > startup
        > > snmpe_bind: binding to address 127.0.0.1:161
        > >
        > > $ snmpwalk -v1 -c public 127.0.0.1
        > > Timeout: No Response from 127.0.0.1
        > >
        > >
        > > Output :
        > >
        > > snmpe_parse: 127.0.0.1: SNMPv1 'public' context 1 request 1495414086
        > > snmpe_parse: 127.0.0.1: oid iso.org.dod.internet.mgmt.mib-2
        > > check_child: lost child: snmp engine terminated; signal 11
        > > terminating
        > >
        > >
        > > It's because it's not implemented yet or what's wrong ?
        >
        > snmpd is new software which hasn't been enabled in the builds yet. but i don't think undeadly.org is the right place for "bug reports", use tech@openbsd.org or send a private mail.
        > yes, there might be bugs. wait until it is -stable or write a real bug report to the author.

        it's just a try and i want to be sure, i saw reyk@ post here so ...

        Comments
        1. By Anonymous Coward (150.101.19.41) on

          > > > I have just try snmpd :
          > > >
          > > > # snmpd -dv
          > > > startup
          > > > snmpe_bind: binding to address 127.0.0.1:161
          > > >
          > > > $ snmpwalk -v1 -c public 127.0.0.1
          > > > Timeout: No Response from 127.0.0.1
          > > >
          > > >
          > > > Output :
          > > >
          > > > snmpe_parse: 127.0.0.1: SNMPv1 'public' context 1 request 1495414086
          > > > snmpe_parse: 127.0.0.1: oid iso.org.dod.internet.mgmt.mib-2
          > > > check_child: lost child: snmp engine terminated; signal 11
          > > > terminating
          > > >
          > > >
          > > > It's because it's not implemented yet or what's wrong ?
          > >
          > > snmpd is new software which hasn't been enabled in the builds yet. but i don't think undeadly.org is the right place for "bug reports", use tech@openbsd.org or send a private mail.
          > > yes, there might be bugs. wait until it is -stable or write a real bug report to the author.
          >
          > it's just a try and i want to be sure, i saw reyk@ post here so ...
          >
          >

          ---------------------------<snip>--------------------------------

          Reyk Floeter writes in to tell us about his work on a new SNMP implementation...

          Sure, I'm looking for volunteers to test and to contribute to snmpd(8), have a look at the src/usr.sbin/snmpd/README file and the code in the OpenBSD source tree. It is not enabled in the builds yet and it will take some time before we are satisfied enough to enable it.

          reyk

          ---------------------------</snip>-------------------------------

  9. By Anonymous Coward (24.37.242.64) on

    I think this is great! I love new things like this in OpenBSD.

    Will an snmpclient be written/included as well, or we'd have to use the one from ports or another?

    Comments
    1. By Reyk Floeter (83.246.89.10) reyk@openbsd.org on http://team.vantronix.net/~reyk/

      > I think this is great! I love new things like this in OpenBSD.
      >
      > Will an snmpclient be written/included as well, or we'd have to use the one from ports or another?

      some client functionality will be added to snmpctl.

      but the main purpose of snmpd is to run as a server and to provide information. so it will not support fancy stuff like dynamic parsing of ASN.1 MIBs to resolve OID names, it is safe to use the net-snmp's clients instead.

Credits

Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original deadly.org with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]