aboutsummaryrefslogtreecommitdiff
path: root/scripts/x509-dot.py
blob: c820018e0232c9662e8667dfaa5e84144c45f291 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# $Id$

"""
Generate .dot description of a certificate tree.

Copyright (C) 2009-2012  Internet Systems Consortium ("ISC")

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

Portions copyright (C) 2008  American Registry for Internet Numbers ("ARIN")

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND ARIN DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS.  IN NO EVENT SHALL ARIN BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
"""

import rpki.POW, sys, glob, os

class x509(object):

  ski = None
  aki = None

  show_file    = False
  show_ski     = False
  show_aki     = False
  show_issuer  = True
  show_subject = True

  cn_only      = True

  subjects = {}

  def __init__(self, filename):

    while filename.startswith("./"):
      filename = filename[2:]

    self.filename = filename

    f = open(filename, "rb")
    text = f.read()
    f.close()

    if "-----BEGIN" in text:
      self.pow = rpki.POW.X509.pemRead(text)
    else:
      self.pow = rpki.POW.X509.derRead(text)

    self.extensions = dict((e[0], e[2]) for e in (self.pow.getExtension(i) for i in xrange(self.pow.countExtensions())))

    if "subjectKeyIdentifier" in self.extensions:
      self.ski = ":".join(["%02X" % ord(i) for i in self.extensions.get("subjectKeyIdentifier")[1:]])

    if "authorityKeyIdentifier" in self.extensions:
      self.aki = ":".join(["%02X" % ord(i) for i in self.extensions.get("authorityKeyIdentifier")[3:]])

    self.subject = self.canonize(self.pow.getSubject())
    self.issuer  = self.canonize(self.pow.getIssuer())

    if self.subject in self.subjects:
      self.subjects[self.subject].append(self)
    else:
      self.subjects[self.subject] = [self]

  def canonize(self, name):

    if self.cn_only and len(name) == 1 and name[0][0] == "CN":
      return name[0][1]
    else:
      return "".join("/%s=%s" % n for n in name)

  def set_node(self, node):

    self.node = node

  def dot(self):

    label = []

    if self.show_issuer:
      label.append(("Issuer", self.issuer))

    if self.show_subject:
      label.append(("Subject", self.subject))

    if self.show_file:
      label.append(("File", self.filename))

    if self.show_aki:
      label.append(("AKI", self.aki))

    if self.show_ski:
      label.append(("SKI", self.ski))

    print "#", repr(label)

    if len(label) > 1:
      print '%s [shape = record, label = "{%s}"];' % (self.node, "|".join("{%s|%s}" % (x, y) for x, y in label if y is not None))
    else:
      print '%s [label = "%s"];' % (self.node, label[0][1])

    for issuer in self.subjects.get(self.issuer, ()):

      if issuer is self:
        print "# Issuer is self"
        issuer = None

      if issuer is not None and self.aki is not None and self.ski is not None and self.aki == self.ski:
        print "# Self-signed"
        issuer = None

      if issuer is not None and self.aki is not None and issuer.ski is not None and self.aki != issuer.ski:
        print "# AKI does not match issuer SKI"
        issuer = None

      if issuer is not None:
        print "%s -> %s;" % (issuer.node, self.node)

    print

certs = []

for topdir in sys.argv[1:] or ["."]:
  for dirpath, dirnames, filenames in os.walk(topdir):
    certs += [x509(dirpath + "/" + filename) for filename in filenames if filename.endswith(".cer")]

for i, cert in enumerate(certs):
  cert.set_node("cert_%d" % i)

print """\
digraph certificates {

rotate = 90;
#size = "11,8.5";
splines = true;
ratio = fill;

"""

for cert in certs:
  cert.dot()

print "}"
class="cp">#define REF_PRINT(a,b) fprintf(stderr,"%08X:%4d:%s\n",(int)b,b->references,a) #endif #ifndef DEVRANDOM /* set this to a comma-separated list of 'random' device files to try out. * My default, we will try to read at least one of these files */ #define DEVRANDOM "/dev/urandom","/dev/random","/dev/srandom" #endif #ifndef DEVRANDOM_EGD /* set this to a comma-seperated list of 'egd' sockets to try out. These * sockets will be tried in the order listed in case accessing the device files * listed in DEVRANDOM did not return enough entropy. */ #define DEVRANDOM_EGD "/var/run/egd-pool","/dev/egd-pool","/etc/egd-pool","/etc/entropy" #endif #if defined(OPENSSL_SYS_VXWORKS) # define NO_SYS_PARAM_H # define NO_CHMOD # define NO_SYSLOG #endif #if defined(OPENSSL_SYS_MACINTOSH_CLASSIC) # if macintosh==1 # ifndef MAC_OS_GUSI_SOURCE # define MAC_OS_pre_X # define NO_SYS_TYPES_H typedef long ssize_t; # endif # define NO_SYS_PARAM_H # define NO_CHMOD # define NO_SYSLOG # undef DEVRANDOM # define GETPID_IS_MEANINGLESS # endif #endif /******************************************************************** The Microsoft section ********************************************************************/ /* The following is used becaue of the small stack in some * Microsoft operating systems */ #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYSNAME_WIN32) # define MS_STATIC static #else # define MS_STATIC #endif #if defined(OPENSSL_SYS_WIN32) && !defined(WIN32) # define WIN32 #endif #if defined(OPENSSL_SYS_WIN16) && !defined(WIN16) # define WIN16 #endif #if defined(OPENSSL_SYS_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(OPENSSL_SYS_MSDOS) && !defined(MSDOS) # define MSDOS #endif #if defined(MSDOS) && !defined(GETPID_IS_MEANINGLESS) # define GETPID_IS_MEANINGLESS #endif #ifdef WIN32 #define get_last_sys_error() GetLastError() #define clear_sys_error() SetLastError(0) #if !defined(WINNT) #define WIN_CONSOLE_BUG #endif #else #define get_last_sys_error() errno #define clear_sys_error() errno=0 #endif #if defined(WINDOWS) #define get_last_socket_error() WSAGetLastError() #define clear_socket_error() WSASetLastError(0) #define readsocket(s,b,n) recv((s),(b),(n),0) #define writesocket(s,b,n) send((s),(b),(n),0) #define EADDRINUSE WSAEADDRINUSE #elif defined(__DJGPP__) #define WATT32 #define get_last_socket_error() errno #define clear_socket_error() errno=0 #define closesocket(s) close_s(s) #define readsocket(s,b,n) read_s(s,b,n) #define writesocket(s,b,n) send(s,b,n,0) #elif defined(MAC_OS_pre_X) #define get_last_socket_error() errno #define clear_socket_error() errno=0 #define closesocket(s) MacSocket_close(s) #define readsocket(s,b,n) MacSocket_recv((s),(b),(n),true) #define writesocket(s,b,n) MacSocket_send((s),(b),(n)) #elif defined(OPENSSL_SYS_VMS) #define get_last_socket_error() errno #define clear_socket_error() errno=0 #define ioctlsocket(a,b,c) ioctl(a,b,c) #define closesocket(s) close(s) #define readsocket(s,b,n) recv((s),(b),(n),0) #define writesocket(s,b,n) send((s),(b),(n),0) #elif defined(OPENSSL_SYS_VXWORKS) #define get_last_socket_error() errno #define clear_socket_error() errno=0 #define ioctlsocket(a,b,c) ioctl((a),(b),(int)(c)) #define closesocket(s) close(s) #define readsocket(s,b,n) read((s),(b),(n)) #define writesocket(s,b,n) write((s),(char *)(b),(n)) #elif defined(OPENSSL_SYS_NETWARE) #if defined(NETWARE_BSDSOCK) #define get_last_socket_error() errno #define clear_socket_error() errno=0 #define closesocket(s) close(s) #define readsocket(s,b,n) recv((s),(b),(n),0) #define writesocket(s,b,n) send((s),(b),(n),0) #else #define get_last_socket_error() WSAGetLastError() #define clear_socket_error() WSASetLastError(0) #define readsocket(s,b,n) recv((s),(b),(n),0) #define writesocket(s,b,n) send((s),(b),(n),0) #endif #else #define get_last_socket_error() errno #define clear_socket_error() errno=0 #define ioctlsocket(a,b,c) ioctl(a,b,c) #define closesocket(s) close(s) #define readsocket(s,b,n) read((s),(b),(n)) #define writesocket(s,b,n) write((s),(b),(n)) #endif #ifdef WIN16 # define MS_CALLBACK _far _loadds # define MS_FAR _far #else # define MS_CALLBACK # define MS_FAR #endif #ifdef OPENSSL_NO_STDIO # undef OPENSSL_NO_FP_API # define OPENSSL_NO_FP_API #endif #if (defined(WINDOWS) || defined(MSDOS)) # ifdef __DJGPP__ # include <unistd.h> # include <sys/stat.h> # include <sys/socket.h> # include <tcp.h> # include <netdb.h> # define _setmode setmode # define _O_TEXT O_TEXT # define _O_BINARY O_BINARY # undef DEVRANDOM # define DEVRANDOM "/dev/urandom\x24" # endif /* __DJGPP__ */ # ifndef S_IFDIR # define S_IFDIR _S_IFDIR # endif # ifndef S_IFMT # define S_IFMT _S_IFMT # endif # if !defined(WINNT) && !defined(__DJGPP__) # define NO_SYSLOG # endif # define NO_DIRENT # ifdef WINDOWS # if !defined(_WIN32_WCE) && !defined(_WIN32_WINNT) /* * Defining _WIN32_WINNT here in e_os.h implies certain "discipline." * Most notably we ought to check for availability of each specific * routine with GetProcAddress() and/or quard NT-specific calls with * GetVersion() < 0x80000000. One can argue that in latter "or" case * we ought to /DELAYLOAD some .DLLs in order to protect ourselves * against run-time link errors. This doesn't seem to be necessary, * because it turned out that already Windows 95, first non-NT Win32 * implementation, is equipped with at least NT 3.51 stubs, dummy * routines with same name, but which do nothing. Meaning that it's * apparently appropriate to guard generic NT calls with GetVersion * alone, while NT 4.0 and above calls ought to be additionally * checked upon with GetProcAddress. */ # define _WIN32_WINNT 0x0400 # endif # include <windows.h> # include <stddef.h> # include <errno.h> # include <string.h> # ifdef _WIN64 # define strlen(s) _strlen31(s) /* cut strings to 2GB */ static unsigned int _strlen31(const char *str) { unsigned int len=0; while (*str && len<0x80000000U) str++, len++; return len&0x7FFFFFFF; } # endif # include <malloc.h> # endif # include <io.h> # include <fcntl.h> # ifdef OPENSSL_SYS_WINCE # include <winsock_extras.h> # endif # define ssize_t long # if defined (__BORLANDC__) # define _setmode setmode # define _O_TEXT O_TEXT # define _O_BINARY O_BINARY # define _int64 __int64 # define _kbhit kbhit # endif # if defined(WIN16) && defined(SSLEAY) && defined(_WINEXITNOPERSIST) # define EXIT(n) _wsetexit(_WINEXITNOPERSIST) # define OPENSSL_EXIT(n) do { if (n == 0) EXIT(n); return(n); } while(0) # else # define EXIT(n) exit(n) # endif # define LIST_SEPARATOR_CHAR ';' # ifndef X_OK # define X_OK 0 # endif # ifndef W_OK # define W_OK 2 # endif # ifndef R_OK # define R_OK 4 # endif # define OPENSSL_CONF "openssl.cnf" # define SSLEAY_CONF OPENSSL_CONF # define NUL_DEV "nul" # define RFILE ".rnd" # ifdef OPENSSL_SYS_WINCE # define DEFAULT_HOME "" # else # define DEFAULT_HOME "C:" # endif #else /* The non-microsoft world world */ # ifdef OPENSSL_SYS_VMS # define VMS 1 /* some programs don't include stdlib, so exit() and others give implicit function warnings */ # include <stdlib.h> # if defined(__DECC) # include <unistd.h> # else # include <unixlib.h> # endif # define OPENSSL_CONF "openssl.cnf" # define SSLEAY_CONF OPENSSL_CONF # define RFILE ".rnd" # define LIST_SEPARATOR_CHAR ',' # define NUL_DEV "NLA0:" /* We don't have any well-defined random devices on VMS, yet... */ # undef DEVRANDOM /* We need to do this since VMS has the following coding on status codes: Bits 0-2: status type: 0 = warning, 1 = success, 2 = error, 3 = info ... The important thing to know is that odd numbers are considered good, while even ones are considered errors. Bits 3-15: actual status number Bits 16-27: facility number. 0 is considered "unknown" Bits 28-31: control bits. If bit 28 is set, the shell won't try to output the message (which, for random codes, just looks ugly) So, what we do here is to change 0 to 1 to get the default success status, and everything else is shifted up to fit into the status number field, and the status is tagged as an error, which I believe is what is wanted here. -- Richard Levitte */ # define EXIT(n) do { int __VMS_EXIT = n; \ if (__VMS_EXIT == 0) \ __VMS_EXIT = 1; \ else \ __VMS_EXIT = (n << 3) | 2; \ __VMS_EXIT |= 0x10000000; \ exit(__VMS_EXIT); } while(0) # define NO_SYS_PARAM_H # elif defined(OPENSSL_SYS_NETWARE) # include <fcntl.h> # include <unistd.h> # define NO_SYS_TYPES_H # undef DEVRANDOM # ifdef NETWARE_CLIB # define getpid GetThreadID # endif # define NO_SYSLOG # define _setmode setmode # define _kbhit kbhit # define _O_TEXT O_TEXT # define _O_BINARY O_BINARY # define OPENSSL_CONF "openssl.cnf" # define SSLEAY_CONF OPENSSL_CONF # define RFILE ".rnd" # define LIST_SEPARATOR_CHAR ';' # define EXIT(n) { if (n) printf("ERROR: %d\n", (int)n); exit(n); } # else /* !defined VMS */ # ifdef OPENSSL_SYS_MPE # define NO_SYS_PARAM_H # endif # ifdef OPENSSL_UNISTD # include OPENSSL_UNISTD # else # include <unistd.h> # endif # ifndef NO_SYS_TYPES_H # include <sys/types.h> # endif # if defined(NeXT) || defined(OPENSSL_SYS_NEWS4) # define pid_t int /* pid_t is missing on NEXTSTEP/OPENSTEP * (unless when compiling with -D_POSIX_SOURCE, * which doesn't work for us) */ # endif # if defined(NeXT) || defined(OPENSSL_SYS_NEWS4) || defined(OPENSSL_SYS_SUNOS) # define ssize_t int /* ditto */ # endif # ifdef OPENSSL_SYS_NEWS4 /* setvbuf is missing on mips-sony-bsd */ # define setvbuf(a, b, c, d) setbuffer((a), (b), (d)) typedef unsigned long clock_t; # endif # define OPENSSL_CONF "openssl.cnf" # define SSLEAY_CONF OPENSSL_CONF # define RFILE ".rnd" # define LIST_SEPARATOR_CHAR ':' # define NUL_DEV "/dev/null" # define EXIT(n) exit(n) # endif # define SSLeay_getpid() getpid() #endif /*************/ #ifdef USE_SOCKETS # if defined(WINDOWS) || defined(MSDOS) /* windows world */ # ifdef OPENSSL_NO_SOCK # define SSLeay_Write(a,b,c) (-1) # define SSLeay_Read(a,b,c) (-1) # define SHUTDOWN(fd) close(fd) # define SHUTDOWN2(fd) close(fd) # elif !defined(__DJGPP__) # include <winsock.h> extern HINSTANCE _hInstance; # ifdef _WIN64 /* * Even though sizeof(SOCKET) is 8, it's safe to cast it to int, because * the value constitutes an index in per-process table of limited size * and not a real pointer. */ # define socket(d,t,p) ((int)socket(d,t,p)) # define accept(s,f,l) ((int)accept(s,f,l)) # endif # define SSLeay_Write(a,b,c) send((a),(b),(c),0) # define SSLeay_Read(a,b,c) recv((a),(b),(c),0) # define SHUTDOWN(fd) { shutdown((fd),0); closesocket(fd); } # define SHUTDOWN2(fd) { shutdown((fd),2); closesocket(fd); } # else # define SSLeay_Write(a,b,c) write_s(a,b,c,0) # define SSLeay_Read(a,b,c) read_s(a,b,c) # define SHUTDOWN(fd) close_s(fd) # define SHUTDOWN2(fd) close_s(fd) # endif # elif defined(MAC_OS_pre_X) # include "MacSocket.h" # define SSLeay_Write(a,b,c) MacSocket_send((a),(b),(c)) # define SSLeay_Read(a,b,c) MacSocket_recv((a),(b),(c),true) # define SHUTDOWN(fd) MacSocket_close(fd) # define SHUTDOWN2(fd) MacSocket_close(fd) # elif defined(OPENSSL_SYS_NETWARE) /* NetWare uses the WinSock2 interfaces by default, but can be configured for BSD */ # if defined(NETWARE_BSDSOCK) # include <sys/socket.h> # include <netinet/in.h> # include <sys/time.h> # include <sys/select.h> # define INVALID_SOCKET (int)(~0) # else # include <novsock2.h> # endif # define SSLeay_Write(a,b,c) send((a),(b),(c),0) # define SSLeay_Read(a,b,c) recv((a),(b),(c),0) # define SHUTDOWN(fd) { shutdown((fd),0); closesocket(fd); } # define SHUTDOWN2(fd) { shutdown((fd),2); closesocket(fd); } # else # ifndef NO_SYS_PARAM_H # include <sys/param.h> # endif # ifdef OPENSSL_SYS_VXWORKS # include <time.h> # elif !defined(OPENSSL_SYS_MPE) # include <sys/time.h> /* Needed under linux for FD_XXX */ # endif # include <netdb.h> # if defined(OPENSSL_SYS_VMS_NODECC) # include <socket.h> # include <in.h> # include <inet.h> # else # include <sys/socket.h> # ifdef FILIO_H # include <sys/filio.h> /* Added for FIONBIO under unixware */ # endif # include <netinet/in.h> # include <arpa/inet.h> # endif # if defined(NeXT) || defined(_NEXT_SOURCE) # include <sys/fcntl.h> # include <sys/types.h> # endif # ifdef OPENSSL_SYS_AIX # include <sys/select.h> # endif # ifdef __QNX__ # include <sys/select.h> # endif # if defined(sun) # include <sys/filio.h> # else # ifndef VMS # include <sys/ioctl.h> # else /* ioctl is only in VMS > 7.0 and when socketshr is not used */ # if !defined(TCPIP_TYPE_SOCKETSHR) && defined(__VMS_VER) && (__VMS_VER > 70000000) # include <sys/ioctl.h> # endif # endif # endif # ifdef VMS # include <unixio.h> # if defined(TCPIP_TYPE_SOCKETSHR) # include <socketshr.h> # endif # endif # define SSLeay_Read(a,b,c) read((a),(b),(c)) # define SSLeay_Write(a,b,c) write((a),(b),(c)) # define SHUTDOWN(fd) { shutdown((fd),0); closesocket((fd)); } # define SHUTDOWN2(fd) { shutdown((fd),2); closesocket((fd)); } # ifndef INVALID_SOCKET # define INVALID_SOCKET (-1) # endif /* INVALID_SOCKET */ # endif #endif #if defined(__ultrix) # ifndef ssize_t # define ssize_t int # endif #endif #if defined(sun) && !defined(__svr4__) && !defined(__SVR4) /* include headers first, so our defines don't break it */ #include <stdlib.h> #include <string.h> /* bcopy can handle overlapping moves according to SunOS 4.1.4 manpage */ # define memmove(s1,s2,n) bcopy((s2),(s1),(n)) # define strtoul(s,e,b) ((unsigned long int)strtol((s),(e),(b))) extern char *sys_errlist[]; extern int sys_nerr; # define strerror(errnum) \ (((errnum)<0 || (errnum)>=sys_nerr) ? NULL : sys_errlist[errnum]) /* Being signed SunOS 4.x memcpy breaks ASN1_OBJECT table lookup */ #include "crypto/o_str.h" # define memcmp OPENSSL_memcmp #endif #ifndef OPENSSL_EXIT # if defined(MONOLITH) && !defined(OPENSSL_C) # define OPENSSL_EXIT(n) return(n) # else # define OPENSSL_EXIT(n) do { EXIT(n); return(n); } while(0) # endif #endif /***********************************************/ /* do we need to do this for getenv. * Just define getenv for use under windows */ #ifdef WIN16 /* How to do this needs to be thought out a bit more.... */ /*char *GETENV(char *); #define Getenv GETENV*/ #define Getenv getenv #else #define Getenv getenv #endif #define DG_GCC_BUG /* gcc < 2.6.3 on DGUX */ #ifdef sgi #define IRIX_CC_BUG /* all version of IRIX I've tested (4.* 5.*) */ #endif #ifdef OPENSSL_SYS_SNI #define IRIX_CC_BUG /* CDS++ up to V2.0Bsomething suffered from the same bug.*/ #endif #if defined(OPENSSL_SYS_WINDOWS) # define strcasecmp _stricmp # define strncasecmp _strnicmp #elif defined(OPENSSL_SYS_VMS) /* VMS below version 7.0 doesn't have strcasecmp() */ # include "o_str.h" # define strcasecmp OPENSSL_strcasecmp # define strncasecmp OPENSSL_strncasecmp # define OPENSSL_IMPLEMENTS_strncasecmp #elif defined(OPENSSL_SYS_OS2) && defined(__EMX__) # define strcasecmp stricmp # define strncasecmp strnicmp #elif defined(OPENSSL_SYS_NETWARE) && defined(NETWARE_CLIB) # define strcasecmp stricmp # define strncasecmp strnicmp #else # ifdef NO_STRINGS_H int strcasecmp(); int strncasecmp(); # else # include <strings.h> # endif /* NO_STRINGS_H */ #endif #if defined(OPENSSL_SYS_OS2) && defined(__EMX__) # include <io.h> # include <fcntl.h> # define NO_SYSLOG #endif /* vxworks */ #if defined(OPENSSL_SYS_VXWORKS) #include <ioLib.h> #include <tickLib.h> #include <sysLib.h> #define TTY_STRUCT int #define sleep(a) taskDelay((a) * sysClkRateGet()) #include <vxWorks.h> #include <sockLib.h> #include <taskLib.h> #define getpid taskIdSelf /* NOTE: these are implemented by helpers in database app! * if the database is not linked, we need to implement them * elswhere */ struct hostent *gethostbyname(const char *name); struct hostent *gethostbyaddr(const char *addr, int length, int type); struct servent *getservbyname(const char *name, const char *proto); #endif /* end vxworks */ #ifdef __cplusplus } #endif #endif