ia64/xen-unstable

changeset 3100:624548f0c77b

bitkeeper revision 1.1159.189.1 (41a4d173plGicbSNCc7tOur8hj7XBg)

Merge arcadians.cl.cam.ac.uk:/local/scratch-2/cl349/xen-tmp.bk
into arcadians.cl.cam.ac.uk:/local/scratch-2/cl349/xen.bk-smp-public
author cl349@arcadians.cl.cam.ac.uk
date Wed Nov 24 18:22:43 2004 +0000 (2004-11-24)
parents 4565455d7f26 f0d6fa2867c5
children a805584b4c8d
files .rootkeys BitKeeper/etc/ignore linux-2.6.9-xen-sparse/Makefile tools/libxutil/Makefile tools/libxutil/debug.h tools/libxutil/enum.c tools/libxutil/enum.h tools/libxutil/hash_table.c tools/libxutil/hash_table.h tools/libxutil/iostream.c tools/libxutil/iostream.h tools/libxutil/kernel_stream.c tools/libxutil/lexis.c tools/libxutil/lexis.h tools/libxutil/socket_stream.c tools/libxutil/socket_stream.h tools/libxutil/string_stream.c tools/libxutil/string_stream.h tools/libxutil/sxpr.c tools/libxutil/sxpr.h tools/libxutil/sxpr_parser.c tools/libxutil/sxpr_parser.h tools/libxutil/sys_net.c tools/libxutil/util.c tools/libxutil/util.h tools/vnet/00README tools/vnet/Makefile tools/vnet/doc/vnet-module.txt tools/vnet/doc/vnet-xend.txt tools/vnet/examples/Makefile tools/vnet/examples/network-vnet tools/vnet/examples/vnet97.sxp tools/vnet/examples/vnet98.sxp tools/vnet/examples/vnet99.sxp tools/vnet/vnet-module/00README tools/vnet/vnet-module/Makefile tools/vnet/vnet-module/Makefile-2.4 tools/vnet/vnet-module/Makefile-2.6 tools/vnet/vnet-module/Makefile.ver tools/vnet/vnet-module/Makefile.vnet tools/vnet/vnet-module/esp.c tools/vnet/vnet-module/esp.h tools/vnet/vnet-module/etherip.c tools/vnet/vnet-module/etherip.h tools/vnet/vnet-module/if_etherip.h tools/vnet/vnet-module/if_varp.h tools/vnet/vnet-module/linux/pfkeyv2.h tools/vnet/vnet-module/random.c tools/vnet/vnet-module/random.h tools/vnet/vnet-module/sa.c tools/vnet/vnet-module/sa.h tools/vnet/vnet-module/sa_algorithm.c tools/vnet/vnet-module/sa_algorithm.h tools/vnet/vnet-module/skb_context.c tools/vnet/vnet-module/skb_context.h tools/vnet/vnet-module/skb_util.c tools/vnet/vnet-module/skb_util.h tools/vnet/vnet-module/tunnel.c tools/vnet/vnet-module/tunnel.h tools/vnet/vnet-module/varp.c tools/vnet/vnet-module/varp.h tools/vnet/vnet-module/varp_socket.c tools/vnet/vnet-module/vif.c tools/vnet/vnet-module/vif.h tools/vnet/vnet-module/vnet.c tools/vnet/vnet-module/vnet.h tools/vnet/vnet-module/vnet_dev.c tools/vnet/vnet-module/vnet_dev.h tools/vnet/vnet-module/vnet_ioctl.c tools/vnet/vnet-module/vnet_ioctl.h tools/vnet/vnetd/Makefile tools/vnet/vnetd/connection.c tools/vnet/vnetd/connection.h tools/vnet/vnetd/marshal.c tools/vnet/vnetd/marshal.h tools/vnet/vnetd/select.c tools/vnet/vnetd/select.h tools/vnet/vnetd/timer.c tools/vnet/vnetd/timer.h tools/vnet/vnetd/vcache.c tools/vnet/vnetd/vcache.h tools/vnet/vnetd/vnetd.c tools/vnet/vnetd/vnetd.h tools/xfrd/Make.xfrd tools/xfrd/Makefile tools/xfrd/debug.h tools/xfrd/enum.c tools/xfrd/enum.h tools/xfrd/hash_table.c tools/xfrd/hash_table.h tools/xfrd/lexis.c tools/xfrd/lexis.h tools/xfrd/sxpr.c tools/xfrd/sxpr.h tools/xfrd/sxpr_parser.c tools/xfrd/sxpr_parser.h tools/xfrd/xen_domain.c tools/xfrd/xfrd.c xen/arch/ia64/privop.c xen/arch/ia64/process.c xen/arch/ia64/regionreg.c xen/arch/ia64/vcpu.c xen/arch/ia64/xenasm.S
line diff
     1.1 --- a/.rootkeys	Wed Nov 24 11:51:49 2004 +0000
     1.2 +++ b/.rootkeys	Wed Nov 24 18:22:43 2004 +0000
     1.3 @@ -127,6 +127,7 @@ 409ba2e7akOFqQUg6Qyg2s28xcXiMg linux-2.4
     1.4  3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.27-xen-sparse/mm/swapfile.c
     1.5  41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.27-xen-sparse/mm/vmalloc.c
     1.6  41505c57WAd5l1rlfCLNSCpx9J13vA linux-2.4.27-xen-sparse/net/core/skbuff.c
     1.7 +41a270bfmh73b5G5UMWfoUZhxoIjTg linux-2.6.9-xen-sparse/Makefile
     1.8  40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.9-xen-sparse/arch/xen/Kconfig
     1.9  40f56237utH41NPukqHksuNf29IC9A linux-2.6.9-xen-sparse/arch/xen/Kconfig.drivers
    1.10  40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.9-xen-sparse/arch/xen/Makefile
    1.11 @@ -341,20 +342,35 @@ 40589968UQFnJeOMn8UIFLbXBuwXjw tools/lib
    1.12  40e1b09dMYB4ItGCqcMIzirdMd9I-w tools/libxutil/Makefile
    1.13  40e033325Sjqs-_4TuzeUEprP_gYFg tools/libxutil/allocate.c
    1.14  40e03332KYz7o1bn2MG_KPbBlyoIMA tools/libxutil/allocate.h
    1.15 +41a216cav5JJbtDQnusfuMa_1x_Xpw tools/libxutil/debug.h
    1.16 +40e9808eyjiahG5uF6AMelNVujBzCg tools/libxutil/enum.c
    1.17 +40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/libxutil/enum.h
    1.18  40e03332p5Dc_owJQRuN72ymJZddFQ tools/libxutil/file_stream.c
    1.19  40e03332jWfB2viAhLSkq1WK0r_iDQ tools/libxutil/file_stream.h
    1.20  40e03332rUjNMGg11n2rN6V4DCrvOg tools/libxutil/gzip_stream.c
    1.21  40e033321O5Qg22haLoq5lpmk4tooQ tools/libxutil/gzip_stream.h
    1.22 +40e9808easXCzzAZQodEfKAhgUXSPA tools/libxutil/hash_table.c
    1.23 +40e9808e94BNXIVVKBFHC3rnkvwtJg tools/libxutil/hash_table.h
    1.24  40e03332ihnBGzHykVwZnFmkAppb4g tools/libxutil/iostream.c
    1.25  40e03332UGwbLR4wsw4ft14p0Yw5pg tools/libxutil/iostream.h
    1.26  40e0333245DLDzJemeSVBLuutHtzEQ tools/libxutil/kernel_stream.c
    1.27  40e03332aK0GkgpDdc-PVTkWKTeOBg tools/libxutil/kernel_stream.h
    1.28 +40e9808epW9iHcLXuO3QfUfLzB7onw tools/libxutil/lexis.c
    1.29 +40e9808egccMhCizayQRGtpBA3L5MQ tools/libxutil/lexis.h
    1.30 +41a216caM4z39Fzjb91rv9Ed_4By1A tools/libxutil/socket_stream.c
    1.31 +41a216caqinvF1I5FQMHA4HTRz8MSA tools/libxutil/socket_stream.h
    1.32  40e03332KT_tnnoAMbPVAZBB7kSOAQ tools/libxutil/string_stream.c
    1.33  40e03332-VtK6_OZa1vMHXFil8uq6w tools/libxutil/string_stream.h
    1.34 +40e9808e5_PLdodqVOSx0b4T_f5aeg tools/libxutil/sxpr.c
    1.35 +40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/libxutil/sxpr.h
    1.36 +40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/libxutil/sxpr_parser.c
    1.37 +40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/libxutil/sxpr_parser.h
    1.38  40e03332Rkvq6nn_UNjzAAK_Tk9v1g tools/libxutil/sys_net.c
    1.39  40e03332lQHvQHw4Rh7VsT1_sui29A tools/libxutil/sys_net.h
    1.40  40e033321smklZd7bDSdWvQCeIshtg tools/libxutil/sys_string.c
    1.41  40e03332h5V611rRWURRLqb1Ekatxg tools/libxutil/sys_string.h
    1.42 +41a216cayFe2FQroFuzvNPw1AvNiqQ tools/libxutil/util.c
    1.43 +41a216ca7mgVSnCBHPCLkGOIqPS1CQ tools/libxutil/util.h
    1.44  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.45  40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
    1.46  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.47 @@ -533,6 +549,64 @@ 4104ffca-jPHLVOrW0n0VghEXXtKxg tools/sv/
    1.48  40fcefb3yMSrZvApO9ToIi-iQwnchA tools/sv/images/xen.png
    1.49  41013a83z27rKvWIxAfUBMVZ1eDCDg tools/sv/inc/script.js
    1.50  40fcefb3zGC9XNBkSwTEobCoq8YClA tools/sv/inc/style.css
    1.51 +41a21888_WlknVWjSxb32Fo13_ujsw tools/vnet/00README
    1.52 +41a21888bOiOJc7blzRbe4MNJoaYTw tools/vnet/Makefile
    1.53 +41a21888mg2k5HeiVjlQYEtJBZT4Qg tools/vnet/doc/vnet-module.txt
    1.54 +41a21888cuxfT8wjCdRR6V1lqf5NtA tools/vnet/doc/vnet-xend.txt
    1.55 +41a21888xEQJAIGktS6XQ4xz2TyA5g tools/vnet/examples/Makefile
    1.56 +41a21888FGQhPR5LJ1GRtOSIIN3QEw tools/vnet/examples/network-vnet
    1.57 +41a21888QPgKrulCfR9SY_pxZKU0KA tools/vnet/examples/vnet97.sxp
    1.58 +41a21888Gm0UBs1i7HqveT7Yz0u8DQ tools/vnet/examples/vnet98.sxp
    1.59 +41a21888r4oGPuGv2Lxl-thgV3H54w tools/vnet/examples/vnet99.sxp
    1.60 +41a21888c9TCRlUwJS9WBjB3e9aWgg tools/vnet/vnet-module/00README
    1.61 +41a21888K2ItolEkksc1MUqyTDI_Kg tools/vnet/vnet-module/Makefile
    1.62 +41a21888mJsFJD7bVMm-nrnWnalGBw tools/vnet/vnet-module/Makefile-2.4
    1.63 +41a21888Znze3-UCCBZ-Nxpj-bNeHA tools/vnet/vnet-module/Makefile-2.6
    1.64 +41a21889fwc1judJ7DYvyEviSJ3TPg tools/vnet/vnet-module/Makefile.ver
    1.65 +41a21889m_sYkdODF3j5uhMP-Guy9Q tools/vnet/vnet-module/Makefile.vnet
    1.66 +41a21889bXW2lC28U6KS_s5tOJ_W9Q tools/vnet/vnet-module/esp.c
    1.67 +41a21889L2MfLDsUFQxstt-0frIVmw tools/vnet/vnet-module/esp.h
    1.68 +41a21889V1jOsB2JExI-XQl720WHwg tools/vnet/vnet-module/etherip.c
    1.69 +41a21889IpMYbNufHMDXe2ndNw4JxA tools/vnet/vnet-module/etherip.h
    1.70 +41a21889LT9TNqO2EvTFIUTujrkX9w tools/vnet/vnet-module/if_etherip.h
    1.71 +41a21889PESythGZFG6kmSoOkkN2Nw tools/vnet/vnet-module/if_varp.h
    1.72 +41a21889nCPEomHqOyQ4vnhEm4II4g tools/vnet/vnet-module/linux/pfkeyv2.h
    1.73 +41a21889A_fw4pRmCbBfZdtRunM5Eg tools/vnet/vnet-module/random.c
    1.74 +41a218899Xy2dPKSu3pkuqaqkfKMTA tools/vnet/vnet-module/random.h
    1.75 +41a21889rIH5S1dv8ygdSsTGNlg0JA tools/vnet/vnet-module/sa.c
    1.76 +41a218896Z4vxy6gnV9h0fWRWu0lKQ tools/vnet/vnet-module/sa.h
    1.77 +41a21889qFD8BTbDpB55uVmSVDEsgw tools/vnet/vnet-module/sa_algorithm.c
    1.78 +41a21889r2AwTe-OCSSVMxBzz8uDtw tools/vnet/vnet-module/sa_algorithm.h
    1.79 +41a21889tvjtL7O8tMveVB8MdSKPnQ tools/vnet/vnet-module/skb_context.c
    1.80 +41a21889lD_QOUz2Msd7fB5rJQzfxA tools/vnet/vnet-module/skb_context.h
    1.81 +41a21889F1r1xnJamzdeuClR8MNwQg tools/vnet/vnet-module/skb_util.c
    1.82 +41a21889sS4bjVqEna24sS8NpV7SRA tools/vnet/vnet-module/skb_util.h
    1.83 +41a21889MDawEK3J_f_oAGnZznhG2w tools/vnet/vnet-module/tunnel.c
    1.84 +41a218896TlHXpVVqF50uz_u_WMXRw tools/vnet/vnet-module/tunnel.h
    1.85 +41a21889nQYbJbqrOApg_RbkwPtXGg tools/vnet/vnet-module/varp.c
    1.86 +41a21889Pev5MJlqqass6CxN4mmvPw tools/vnet/vnet-module/varp.h
    1.87 +41a21889GbsHHfkpA-PkOvltfEwpMA tools/vnet/vnet-module/varp_socket.c
    1.88 +41a21889sknn8zd5xCJlpQbs7MvxKg tools/vnet/vnet-module/vif.c
    1.89 +41a21889VsKKWpe6rcXOSLPy2FuNWQ tools/vnet/vnet-module/vif.h
    1.90 +41a21889dgkOyuSTVqy7D8TPIzrUyw tools/vnet/vnet-module/vnet.c
    1.91 +41a21889ocAdwk7V1nNt4iBpmYW-Mw tools/vnet/vnet-module/vnet.h
    1.92 +41a21889YrTiC0ArJSGFtiaHz2j1qQ tools/vnet/vnet-module/vnet_dev.c
    1.93 +41a21889rHT4vrC4VAfk7-xP_K5aBg tools/vnet/vnet-module/vnet_dev.h
    1.94 +41a21889qJj6GjT2f5hMHRvPS1AW4w tools/vnet/vnet-module/vnet_ioctl.c
    1.95 +41a2188a8W4xYB0LYm512agtoEv52g tools/vnet/vnet-module/vnet_ioctl.h
    1.96 +41a2188aFF_1T9OgpqUjjjaCqKB8lw tools/vnet/vnetd/Makefile
    1.97 +41a2188a9j84qS4CxqMLVCvyGpA93w tools/vnet/vnetd/connection.c
    1.98 +41a2188atexNEami9TNVYNkRSb7Bqg tools/vnet/vnetd/connection.h
    1.99 +41a2188abgYpITSrWoMGHHrM56nklw tools/vnet/vnetd/marshal.c
   1.100 +41a2188aUbOi5tAYwOS4aPixo1EGwQ tools/vnet/vnetd/marshal.h
   1.101 +41a2188aDJlSVB1s_st2MSWxW8kMwg tools/vnet/vnetd/select.c
   1.102 +41a2188aE9LUDdSSwNT3BWVWCvGSnQ tools/vnet/vnetd/select.h
   1.103 +41a2188aTbMKv_Eig12dSrBUEBl1Jg tools/vnet/vnetd/timer.c
   1.104 +41a2188aIzBGqQ6DUVzCxfBsN0Q6Ww tools/vnet/vnetd/timer.h
   1.105 +41a2188aIf3Xk6uvk7KzjdpOsflAEw tools/vnet/vnetd/vcache.c
   1.106 +41a2188ar6_vOO3_tEJQjmFVU3409A tools/vnet/vnetd/vcache.h
   1.107 +41a2188aETrGU60X9WtGhYVfU7z0Pw tools/vnet/vnetd/vnetd.c
   1.108 +41a2188ahYjemudGyB7078AWMFR-0w tools/vnet/vnetd/vnetd.h
   1.109  4194e861IgTabTt8HOuh143QIJFD1Q tools/x2d2/Makefile
   1.110  4194e861M2gcBz4i94cQYpqzi8n6UA tools/x2d2/cntrl_con.c
   1.111  4194e8612TrrMvC8ZlA4h2ZYCPWz4g tools/x2d2/minixend.c
   1.112 @@ -549,23 +623,13 @@ 40e9808epTR4zWrYjGUnaaynK20Q5A tools/xfr
   1.113  40e9808eysqT4VNDlJFqsZB2rdg4Qw tools/xfrd/connection.c
   1.114  40e9808eyXfJUi4E0C3WSgrEXqQ1sQ tools/xfrd/connection.h
   1.115  40e9808eULGwffNOE4kBrAfZ9YAVMA tools/xfrd/debug.h
   1.116 -40e9808eyjiahG5uF6AMelNVujBzCg tools/xfrd/enum.c
   1.117 -40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/xfrd/enum.h
   1.118 -40e9808easXCzzAZQodEfKAhgUXSPA tools/xfrd/hash_table.c
   1.119 -40e9808e94BNXIVVKBFHC3rnkvwtJg tools/xfrd/hash_table.h
   1.120  411b5139tfKZfWs1LQHmwDR_wjKoxQ tools/xfrd/http.h
   1.121 -40e9808epW9iHcLXuO3QfUfLzB7onw tools/xfrd/lexis.c
   1.122 -40e9808egccMhCizayQRGtpBA3L5MQ tools/xfrd/lexis.h
   1.123  40e9808ePADCSKL1YgGCt2TbYPnYkw tools/xfrd/lzi_stream.c
   1.124  40e9808eDNAdpF71o5teYb9DTT-PRw tools/xfrd/lzi_stream.h
   1.125  40e9808eQxi0EzTcPJtosrzxEIjA-Q tools/xfrd/marshal.c
   1.126  40e9808etg13xfRm0Lqd8vY-jHOoTg tools/xfrd/marshal.h
   1.127  40e9808eCsmywryb036TdtRMJHDMmQ tools/xfrd/select.c
   1.128  40e9808e99OcM547cKMTfmCVSoWVAw tools/xfrd/select.h
   1.129 -40e9808e5_PLdodqVOSx0b4T_f5aeg tools/xfrd/sxpr.c
   1.130 -40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/xfrd/sxpr.h
   1.131 -40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/xfrd/sxpr_parser.c
   1.132 -40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/xfrd/sxpr_parser.h
   1.133  40e9808eF3NVldqRNS5IHM8gbFAvpw tools/xfrd/xdr.c
   1.134  40e9808ezXzoRHm7pybXU69NtnjimA tools/xfrd/xdr.h
   1.135  40e9808edpUtf4bJ8IbqClPJj_OvbA tools/xfrd/xen_domain.c
   1.136 @@ -576,6 +640,11 @@ 40e9808eHXvs_5eggj9McD_J90mhNw tools/xfr
   1.137  3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
   1.138  3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
   1.139  3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk
   1.140 +41a26ebcqaSGVQ8qTMwpPwOJSJ7qSw xen/arch/ia64/privop.c
   1.141 +41a26ebc4BOHDUsT0TSnryPeV2xfRA xen/arch/ia64/process.c
   1.142 +41a26ebcJ30TFl1v2kR8rqpEBvOtVw xen/arch/ia64/regionreg.c
   1.143 +41a26ebc--sjlYZQxmIxyCx3jw70qA xen/arch/ia64/vcpu.c
   1.144 +41a26ebc4jSBGQOuyNIPDST58mNbBw xen/arch/ia64/xenasm.S
   1.145  3ddb79bcZbRBzT3elFWSX7u6NtMagQ xen/arch/x86/Makefile
   1.146  3ddb79bcBQF85CfLS4i1WGZ4oLLaCA xen/arch/x86/Rules.mk
   1.147  3e5636e5FAYZ5_vQnmgwFJfSdmO5Mw xen/arch/x86/acpi.c
     2.1 --- a/BitKeeper/etc/ignore	Wed Nov 24 11:51:49 2004 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Wed Nov 24 18:22:43 2004 +0000
     2.3 @@ -63,6 +63,13 @@ tools/check/.*
     2.4  tools/libxc/xen/*
     2.5  tools/misc/miniterm/miniterm
     2.6  tools/misc/xen_cpuperf
     2.7 +tools/vnet/gc
     2.8 +tools/vnet/gc*/*
     2.9 +tools/vnet/vnet-module/*.ko
    2.10 +tools/vnet/vnet-module/.*.cmd
    2.11 +tools/vnet/vnet-module/.tmp_versions/*
    2.12 +tools/vnet/vnet-module/vnet_module.mod.*
    2.13 +tools/vnetd/vnetd
    2.14  tools/web-shutdown.tap
    2.15  tools/x2d2/minixend
    2.16  tools/xentrace/xentrace
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/linux-2.6.9-xen-sparse/Makefile	Wed Nov 24 18:22:43 2004 +0000
     3.3 @@ -0,0 +1,1293 @@
     3.4 +VERSION = 2
     3.5 +PATCHLEVEL = 6
     3.6 +SUBLEVEL = 9
     3.7 +EXTRAVERSION =
     3.8 +NAME=Zonked Quokka
     3.9 +
    3.10 +# *DOCUMENTATION*
    3.11 +# To see a list of typical targets execute "make help"
    3.12 +# More info can be located in ./README
    3.13 +# Comments in this file are targeted only to the developer, do not
    3.14 +# expect to learn how to build the kernel reading this file.
    3.15 +
    3.16 +# Do not print "Entering directory ..."
    3.17 +MAKEFLAGS += --no-print-directory
    3.18 +
    3.19 +# We are using a recursive build, so we need to do a little thinking
    3.20 +# to get the ordering right.
    3.21 +#
    3.22 +# Most importantly: sub-Makefiles should only ever modify files in
    3.23 +# their own directory. If in some directory we have a dependency on
    3.24 +# a file in another dir (which doesn't happen often, but it's of
    3.25 +# unavoidable when linking the built-in.o targets which finally
    3.26 +# turn into vmlinux), we will call a sub make in that other dir, and
    3.27 +# after that we are sure that everything which is in that other dir
    3.28 +# is now up to date.
    3.29 +#
    3.30 +# The only cases where we need to modify files which have global
    3.31 +# effects are thus separated out and done before the recursive
    3.32 +# descending is started. They are now explicitly listed as the
    3.33 +# prepare rule.
    3.34 +
    3.35 +# To put more focus on warnings, be less verbose as default
    3.36 +# Use 'make V=1' to see the full commands
    3.37 +
    3.38 +ifdef V
    3.39 +  ifeq ("$(origin V)", "command line")
    3.40 +    KBUILD_VERBOSE = $(V)
    3.41 +  endif
    3.42 +endif
    3.43 +ifndef KBUILD_VERBOSE
    3.44 +  KBUILD_VERBOSE = 0
    3.45 +endif
    3.46 +
    3.47 +# Call sparse as part of compilation of C files
    3.48 +# Use 'make C=1' to enable sparse checking
    3.49 +
    3.50 +ifdef C
    3.51 +  ifeq ("$(origin C)", "command line")
    3.52 +    KBUILD_CHECKSRC = $(C)
    3.53 +  endif
    3.54 +endif
    3.55 +ifndef KBUILD_CHECKSRC
    3.56 +  KBUILD_CHECKSRC = 0
    3.57 +endif
    3.58 +
    3.59 +# Use make M=dir to specify directory of external module to build
    3.60 +# Old syntax make ... SUBDIRS=$PWD is still supported
    3.61 +# Setting the environment variable KBUILD_EXTMOD take precedence
    3.62 +ifdef SUBDIRS
    3.63 +  KBUILD_EXTMOD ?= $(SUBDIRS)
    3.64 +endif
    3.65 +ifdef M
    3.66 +  ifeq ("$(origin M)", "command line")
    3.67 +    KBUILD_EXTMOD := $(M)
    3.68 +  endif
    3.69 +endif
    3.70 +
    3.71 +
    3.72 +# kbuild supports saving output files in a separate directory.
    3.73 +# To locate output files in a separate directory two syntax'es are supported.
    3.74 +# In both cases the working directory must be the root of the kernel src.
    3.75 +# 1) O=
    3.76 +# Use "make O=dir/to/store/output/files/"
    3.77 +# 
    3.78 +# 2) Set KBUILD_OUTPUT
    3.79 +# Set the environment variable KBUILD_OUTPUT to point to the directory
    3.80 +# where the output files shall be placed.
    3.81 +# export KBUILD_OUTPUT=dir/to/store/output/files/
    3.82 +# make
    3.83 +#
    3.84 +# The O= assigment takes precedence over the KBUILD_OUTPUT environment variable.
    3.85 +
    3.86 +
    3.87 +# KBUILD_SRC is set on invocation of make in OBJ directory
    3.88 +# KBUILD_SRC is not intended to be used by the regular user (for now)
    3.89 +ifeq ($(KBUILD_SRC),)
    3.90 +
    3.91 +# OK, Make called in directory where kernel src resides
    3.92 +# Do we want to locate output files in a separate directory?
    3.93 +ifdef O
    3.94 +  ifeq ("$(origin O)", "command line")
    3.95 +    KBUILD_OUTPUT := $(O)
    3.96 +  endif
    3.97 +endif
    3.98 +
    3.99 +# That's our default target when none is given on the command line
   3.100 +.PHONY: _all
   3.101 +_all:
   3.102 +
   3.103 +ifneq ($(KBUILD_OUTPUT),)
   3.104 +# Invoke a second make in the output directory, passing relevant variables
   3.105 +# check that the output directory actually exists
   3.106 +saved-output := $(KBUILD_OUTPUT)
   3.107 +KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd)
   3.108 +$(if $(KBUILD_OUTPUT),, \
   3.109 +     $(error output directory "$(saved-output)" does not exist))
   3.110 +
   3.111 +.PHONY: $(MAKECMDGOALS)
   3.112 +
   3.113 +$(filter-out _all,$(MAKECMDGOALS)) _all:
   3.114 +	$(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT)		\
   3.115 +	KBUILD_SRC=$(CURDIR)	     KBUILD_VERBOSE=$(KBUILD_VERBOSE)	\
   3.116 +	KBUILD_CHECK=$(KBUILD_CHECK) KBUILD_EXTMOD="$(KBUILD_EXTMOD)"	\
   3.117 +        -f $(CURDIR)/Makefile $@
   3.118 +
   3.119 +# Leave processing to above invocation of make
   3.120 +skip-makefile := 1
   3.121 +endif # ifneq ($(KBUILD_OUTPUT),)
   3.122 +endif # ifeq ($(KBUILD_SRC),)
   3.123 +
   3.124 +# We process the rest of the Makefile if this is the final invocation of make
   3.125 +ifeq ($(skip-makefile),)
   3.126 +
   3.127 +# If building an external module we do not care about the all: rule
   3.128 +# but instead _all depend on modules
   3.129 +.PHONY: all
   3.130 +ifeq ($(KBUILD_EXTMOD),)
   3.131 +_all: all
   3.132 +else
   3.133 +_all: modules
   3.134 +endif
   3.135 +
   3.136 +srctree		:= $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))
   3.137 +TOPDIR		:= $(srctree)
   3.138 +# FIXME - TOPDIR is obsolete, use srctree/objtree
   3.139 +objtree		:= $(CURDIR)
   3.140 +src		:= $(srctree)
   3.141 +obj		:= $(objtree)
   3.142 +
   3.143 +VPATH		:= $(srctree)
   3.144 +
   3.145 +export srctree objtree VPATH TOPDIR
   3.146 +
   3.147 +nullstring :=
   3.148 +space      := $(nullstring) # end of line
   3.149 +
   3.150 +# Take the contents of any files called localversion* and the config
   3.151 +# variable CONFIG_LOCALVERSION and append them to KERNELRELEASE. Be
   3.152 +# careful not to include files twice if building in the source
   3.153 +# directory. LOCALVERSION from the command line override all of this
   3.154 +
   3.155 +ifeq ($(objtree),$(srctree))
   3.156 +localversion-files := $(wildcard $(srctree)/localversion*)
   3.157 +else
   3.158 +localversion-files := $(wildcard $(objtree)/localversion* $(srctree)/localversion*)
   3.159 +endif
   3.160 +
   3.161 +LOCALVERSION = $(subst $(space),, \
   3.162 +	       $(shell cat /dev/null $(localversion-files)) \
   3.163 +	       $(subst ",,$(CONFIG_LOCALVERSION)))
   3.164 +
   3.165 +KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)$(LOCALVERSION)
   3.166 +
   3.167 +# SUBARCH tells the usermode build what the underlying arch is.  That is set
   3.168 +# first, and if a usermode build is happening, the "ARCH=um" on the command
   3.169 +# line overrides the setting of ARCH below.  If a native build is happening,
   3.170 +# then ARCH is assigned, getting whatever value it gets normally, and 
   3.171 +# SUBARCH is subsequently ignored.
   3.172 +
   3.173 +SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
   3.174 +				  -e s/arm.*/arm/ -e s/sa110/arm/ \
   3.175 +				  -e s/s390x/s390/ -e s/parisc64/parisc/ )
   3.176 +
   3.177 +# Cross compiling and selecting different set of gcc/bin-utils
   3.178 +# ---------------------------------------------------------------------------
   3.179 +#
   3.180 +# When performing cross compilation for other architectures ARCH shall be set
   3.181 +# to the target architecture. (See arch/* for the possibilities).
   3.182 +# ARCH can be set during invocation of make:
   3.183 +# make ARCH=ia64
   3.184 +# Another way is to have ARCH set in the environment.
   3.185 +# The default ARCH is the host where make is executed.
   3.186 +
   3.187 +# CROSS_COMPILE specify the prefix used for all executables used
   3.188 +# during compilation. Only gcc and related bin-utils executables
   3.189 +# are prefixed with $(CROSS_COMPILE).
   3.190 +# CROSS_COMPILE can be set on the command line
   3.191 +# make CROSS_COMPILE=ia64-linux-
   3.192 +# Alternatively CROSS_COMPILE can be set in the environment.
   3.193 +# Default value for CROSS_COMPILE is not to prefix executables
   3.194 +# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile
   3.195 +
   3.196 +ARCH		?= $(SUBARCH)
   3.197 +CROSS_COMPILE	?=
   3.198 +
   3.199 +# Architecture as present in compile.h
   3.200 +UTS_MACHINE := $(ARCH)
   3.201 +
   3.202 +# SHELL used by kbuild
   3.203 +CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
   3.204 +	  else if [ -x /bin/bash ]; then echo /bin/bash; \
   3.205 +	  else echo sh; fi ; fi)
   3.206 +
   3.207 +HOSTCC  	= gcc
   3.208 +HOSTCXX  	= g++
   3.209 +HOSTCFLAGS	= -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
   3.210 +HOSTCXXFLAGS	= -O2
   3.211 +
   3.212 +# 	Decide whether to build built-in, modular, or both.
   3.213 +#	Normally, just do built-in.
   3.214 +
   3.215 +KBUILD_MODULES :=
   3.216 +KBUILD_BUILTIN := 1
   3.217 +
   3.218 +#	If we have only "make modules", don't compile built-in objects.
   3.219 +#	When we're building modules with modversions, we need to consider
   3.220 +#	the built-in objects during the descend as well, in order to
   3.221 +#	make sure the checksums are uptodate before we record them.
   3.222 +
   3.223 +ifeq ($(MAKECMDGOALS),modules)
   3.224 +  KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1)
   3.225 +endif
   3.226 +
   3.227 +#	If we have "make <whatever> modules", compile modules
   3.228 +#	in addition to whatever we do anyway.
   3.229 +#	Just "make" or "make all" shall build modules as well
   3.230 +
   3.231 +ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
   3.232 +  KBUILD_MODULES := 1
   3.233 +endif
   3.234 +
   3.235 +ifeq ($(MAKECMDGOALS),)
   3.236 +  KBUILD_MODULES := 1
   3.237 +endif
   3.238 +
   3.239 +export KBUILD_MODULES KBUILD_BUILTIN KBUILD_VERBOSE
   3.240 +export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD
   3.241 +
   3.242 +# Beautify output
   3.243 +# ---------------------------------------------------------------------------
   3.244 +#
   3.245 +# Normally, we echo the whole command before executing it. By making
   3.246 +# that echo $($(quiet)$(cmd)), we now have the possibility to set
   3.247 +# $(quiet) to choose other forms of output instead, e.g.
   3.248 +#
   3.249 +#         quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
   3.250 +#         cmd_cc_o_c       = $(CC) $(c_flags) -c -o $@ $<
   3.251 +#
   3.252 +# If $(quiet) is empty, the whole command will be printed.
   3.253 +# If it is set to "quiet_", only the short version will be printed. 
   3.254 +# If it is set to "silent_", nothing wil be printed at all, since
   3.255 +# the variable $(silent_cmd_cc_o_c) doesn't exist.
   3.256 +#
   3.257 +# A simple variant is to prefix commands with $(Q) - that's usefull
   3.258 +# for commands that shall be hidden in non-verbose mode.
   3.259 +#
   3.260 +#	$(Q)ln $@ :<
   3.261 +#
   3.262 +# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
   3.263 +# If KBUILD_VERBOSE equals 1 then the above command is displayed.
   3.264 +
   3.265 +ifeq ($(KBUILD_VERBOSE),1)
   3.266 +  quiet =
   3.267 +  Q =
   3.268 +else
   3.269 +  quiet=quiet_
   3.270 +  Q = @
   3.271 +endif
   3.272 +
   3.273 +# If the user is running make -s (silent mode), suppress echoing of
   3.274 +# commands
   3.275 +
   3.276 +ifneq ($(findstring s,$(MAKEFLAGS)),)
   3.277 +  quiet=silent_
   3.278 +endif
   3.279 +
   3.280 +export quiet Q KBUILD_VERBOSE
   3.281 +
   3.282 +######
   3.283 +# cc support functions to be used (only) in arch/$(ARCH)/Makefile
   3.284 +# See documentation in Documentation/kbuild/makefiles.txt
   3.285 +
   3.286 +# cc-option
   3.287 +# Usage: cflags-y += $(call gcc-option, -march=winchip-c6, -march=i586)
   3.288 +
   3.289 +cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
   3.290 +             > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
   3.291 +
   3.292 +# For backward compatibility
   3.293 +check_gcc = $(warning check_gcc is deprecated - use cc-option) \
   3.294 +            $(call cc-option, $(1),$(2))
   3.295 +
   3.296 +# cc-option-yn
   3.297 +# Usage: flag := $(call gcc-option-yn, -march=winchip-c6)
   3.298 +cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
   3.299 +                > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
   3.300 +
   3.301 +# cc-version
   3.302 +# Usage gcc-ver := $(call cc-version $(CC))
   3.303 +cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh \
   3.304 +              $(if $(1), $(1), $(CC)))
   3.305 +
   3.306 +
   3.307 +# Look for make include files relative to root of kernel src
   3.308 +MAKEFLAGS += --include-dir=$(srctree)
   3.309 +
   3.310 +# For maximum performance (+ possibly random breakage, uncomment
   3.311 +# the following)
   3.312 +
   3.313 +#MAKEFLAGS += -rR
   3.314 +
   3.315 +# Make variables (CC, etc...)
   3.316 +
   3.317 +AS		= $(CROSS_COMPILE)as
   3.318 +LD		= $(CROSS_COMPILE)ld
   3.319 +CC		= $(CROSS_COMPILE)gcc
   3.320 +CPP		= $(CC) -E
   3.321 +AR		= $(CROSS_COMPILE)ar
   3.322 +NM		= $(CROSS_COMPILE)nm
   3.323 +STRIP		= $(CROSS_COMPILE)strip
   3.324 +OBJCOPY		= $(CROSS_COMPILE)objcopy
   3.325 +OBJDUMP		= $(CROSS_COMPILE)objdump
   3.326 +AWK		= awk
   3.327 +GENKSYMS	= scripts/genksyms/genksyms
   3.328 +DEPMOD		= /sbin/depmod
   3.329 +KALLSYMS	= scripts/kallsyms
   3.330 +PERL		= perl
   3.331 +CHECK		= sparse
   3.332 +CHECKFLAGS     := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__
   3.333 +MODFLAGS	= -DMODULE
   3.334 +CFLAGS_MODULE   = $(MODFLAGS)
   3.335 +AFLAGS_MODULE   = $(MODFLAGS)
   3.336 +LDFLAGS_MODULE  = -r
   3.337 +CFLAGS_KERNEL	=
   3.338 +AFLAGS_KERNEL	=
   3.339 +
   3.340 +NOSTDINC_FLAGS  = -nostdinc -iwithprefix include
   3.341 +
   3.342 +# Use LINUXINCLUDE when you must reference the include/ directory.
   3.343 +# Needed to be compatible with the O= option
   3.344 +LINUXINCLUDE    := -Iinclude \
   3.345 +                   $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include)
   3.346 +
   3.347 +CPPFLAGS        := -D__KERNEL__ $(LINUXINCLUDE)
   3.348 +
   3.349 +CFLAGS 		:= -Wall -Wstrict-prototypes -Wno-trigraphs \
   3.350 +	  	   -fno-strict-aliasing -fno-common
   3.351 +AFLAGS		:= -D__ASSEMBLY__
   3.352 +
   3.353 +export	VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION LOCALVERSION KERNELRELEASE \
   3.354 +	ARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC \
   3.355 +	CPP AR NM STRIP OBJCOPY OBJDUMP MAKE AWK GENKSYMS PERL UTS_MACHINE \
   3.356 +	HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS
   3.357 +
   3.358 +export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS
   3.359 +export CFLAGS CFLAGS_KERNEL CFLAGS_MODULE 
   3.360 +export AFLAGS AFLAGS_KERNEL AFLAGS_MODULE
   3.361 +
   3.362 +# When compiling out-of-tree modules, put MODVERDIR in the module
   3.363 +# tree rather than in the kernel tree. The kernel tree might
   3.364 +# even be read-only.
   3.365 +export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions
   3.366 +
   3.367 +# The temporary file to save gcc -MD generated dependencies must not
   3.368 +# contain a comma
   3.369 +comma := ,
   3.370 +depfile = $(subst $(comma),_,$(@D)/.$(@F).d)
   3.371 +
   3.372 +# Files to ignore in find ... statements
   3.373 +
   3.374 +RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc \) -prune -o
   3.375 +RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc
   3.376 +
   3.377 +# ===========================================================================
   3.378 +# Rules shared between *config targets and build targets
   3.379 +
   3.380 +# Basic helpers built in scripts/
   3.381 +.PHONY: scripts_basic
   3.382 +scripts_basic:
   3.383 +	$(Q)$(MAKE) $(build)=scripts/basic
   3.384 +
   3.385 +# To make sure we do not include .config for any of the *config targets
   3.386 +# catch them early, and hand them over to scripts/kconfig/Makefile
   3.387 +# It is allowed to specify more targets when calling make, including
   3.388 +# mixing *config targets and build targets.
   3.389 +# For example 'make oldconfig all'. 
   3.390 +# Detect when mixed targets is specified, and make a second invocation
   3.391 +# of make so .config is not included in this case either (for *config).
   3.392 +
   3.393 +no-dot-config-targets := clean mrproper distclean \
   3.394 +			 cscope TAGS tags help %docs check%
   3.395 +
   3.396 +config-targets := 0
   3.397 +mixed-targets  := 0
   3.398 +dot-config     := 1
   3.399 +
   3.400 +ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
   3.401 +	ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
   3.402 +		dot-config := 0
   3.403 +	endif
   3.404 +endif
   3.405 +
   3.406 +ifeq ($(KBUILD_EXTMOD),)
   3.407 +        ifneq ($(filter config %config,$(MAKECMDGOALS)),)
   3.408 +                config-targets := 1
   3.409 +                ifneq ($(filter-out config %config,$(MAKECMDGOALS)),)
   3.410 +                        mixed-targets := 1
   3.411 +                endif
   3.412 +        endif
   3.413 +endif
   3.414 +
   3.415 +ifeq ($(mixed-targets),1)
   3.416 +# ===========================================================================
   3.417 +# We're called with mixed targets (*config and build targets).
   3.418 +# Handle them one by one.
   3.419 +
   3.420 +%:: FORCE
   3.421 +	$(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@
   3.422 +
   3.423 +else
   3.424 +ifeq ($(config-targets),1)
   3.425 +# ===========================================================================
   3.426 +# *config targets only - make sure prerequisites are updated, and descend
   3.427 +# in scripts/kconfig to make the *config target
   3.428 +
   3.429 +config: scripts_basic FORCE
   3.430 +	$(Q)$(MAKE) $(build)=scripts/kconfig $@
   3.431 +%config: scripts_basic FORCE
   3.432 +	$(Q)$(MAKE) $(build)=scripts/kconfig $@
   3.433 +
   3.434 +else
   3.435 +# ===========================================================================
   3.436 +# Build targets only - this includes vmlinux, arch specific targets, clean
   3.437 +# targets and others. In general all targets except *config targets.
   3.438 +
   3.439 +ifeq ($(KBUILD_EXTMOD),)
   3.440 +# Additional helpers built in scripts/
   3.441 +# Carefully list dependencies so we do not try to build scripts twice
   3.442 +# in parrallel
   3.443 +.PHONY: scripts
   3.444 +scripts: scripts_basic include/config/MARKER
   3.445 +	$(Q)$(MAKE) $(build)=$(@)
   3.446 +
   3.447 +scripts_basic: include/linux/autoconf.h
   3.448 +
   3.449 +# Objects we will link into vmlinux / subdirs we need to visit
   3.450 +init-y		:= init/
   3.451 +drivers-y	:= drivers/ sound/
   3.452 +net-y		:= net/
   3.453 +libs-y		:= lib/
   3.454 +core-y		:= usr/
   3.455 +endif # KBUILD_EXTMOD
   3.456 +
   3.457 +ifeq ($(dot-config),1)
   3.458 +# In this section, we need .config
   3.459 +
   3.460 +# Read in dependencies to all Kconfig* files, make sure to run
   3.461 +# oldconfig if changes are detected.
   3.462 +-include .config.cmd
   3.463 +
   3.464 +include .config
   3.465 +
   3.466 +# If .config needs to be updated, it will be done via the dependency
   3.467 +# that autoconf has on .config.
   3.468 +# To avoid any implicit rule to kick in, define an empty command
   3.469 +.config: ;
   3.470 +
   3.471 +# If .config is newer than include/linux/autoconf.h, someone tinkered
   3.472 +# with it and forgot to run make oldconfig
   3.473 +include/linux/autoconf.h: .config
   3.474 +	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
   3.475 +else
   3.476 +# Dummy target needed, because used as prerequisite
   3.477 +include/linux/autoconf.h: ;
   3.478 +endif
   3.479 +
   3.480 +# The all: target is the default when no target is given on the
   3.481 +# command line.
   3.482 +# This allow a user to issue only 'make' to build a kernel including modules
   3.483 +# Defaults vmlinux but it is usually overriden in the arch makefile
   3.484 +all: vmlinux
   3.485 +
   3.486 +ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
   3.487 +CFLAGS		+= -Os
   3.488 +else
   3.489 +CFLAGS		+= -O2
   3.490 +endif
   3.491 +
   3.492 +ifndef CONFIG_FRAME_POINTER
   3.493 +CFLAGS		+= -fomit-frame-pointer
   3.494 +endif
   3.495 +
   3.496 +ifdef CONFIG_DEBUG_INFO
   3.497 +CFLAGS		+= -g
   3.498 +endif
   3.499 +
   3.500 +# warn about C99 declaration after statement
   3.501 +CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
   3.502 +
   3.503 +include $(srctree)/arch/$(ARCH)/Makefile
   3.504 +
   3.505 +# Default kernel image to build when no specific target is given.
   3.506 +# KBUILD_IMAGE may be overruled on the commandline or
   3.507 +# set in the environment
   3.508 +# Also any assingments in arch/$(ARCH)/Makefiel take precedence over
   3.509 +# this default value
   3.510 +export KBUILD_IMAGE ?= vmlinux
   3.511 +
   3.512 +#
   3.513 +# INSTALL_PATH specifies where to place the updated kernel and system map
   3.514 +# images.  Uncomment if you want to place them anywhere other than root.
   3.515 +#
   3.516 +
   3.517 +#export	INSTALL_PATH=/boot
   3.518 +
   3.519 +#
   3.520 +# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory
   3.521 +# relocations required by build roots.  This is not defined in the
   3.522 +# makefile but the arguement can be passed to make if needed.
   3.523 +#
   3.524 +
   3.525 +MODLIB	:= $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE)
   3.526 +export MODLIB
   3.527 +
   3.528 +
   3.529 +ifeq ($(KBUILD_EXTMOD),)
   3.530 +core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/
   3.531 +
   3.532 +vmlinux-dirs	:= $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
   3.533 +		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
   3.534 +		     $(net-y) $(net-m) $(libs-y) $(libs-m)))
   3.535 +
   3.536 +vmlinux-alldirs	:= $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \
   3.537 +		     $(init-n) $(init-) \
   3.538 +		     $(core-n) $(core-) $(drivers-n) $(drivers-) \
   3.539 +		     $(net-n)  $(net-)  $(libs-n)    $(libs-))))
   3.540 +
   3.541 +init-y		:= $(patsubst %/, %/built-in.o, $(init-y))
   3.542 +core-y		:= $(patsubst %/, %/built-in.o, $(core-y))
   3.543 +drivers-y	:= $(patsubst %/, %/built-in.o, $(drivers-y))
   3.544 +net-y		:= $(patsubst %/, %/built-in.o, $(net-y))
   3.545 +libs-y1		:= $(patsubst %/, %/lib.a, $(libs-y))
   3.546 +libs-y2		:= $(patsubst %/, %/built-in.o, $(libs-y))
   3.547 +libs-y		:= $(libs-y1) $(libs-y2)
   3.548 +
   3.549 +# Build vmlinux
   3.550 +# ---------------------------------------------------------------------------
   3.551 +# vmlinux is build from the objects selected by $(vmlinux-init) and
   3.552 +# $(vmlinux-main). Most are built-in.o files from top-level directories
   3.553 +# in the kernel tree, others are specified in arch/$(ARCH)Makefile.
   3.554 +# Ordering when linking is important, and $(vmlinux-init) must be first.
   3.555 +#
   3.556 +# vmlinux
   3.557 +#   ^
   3.558 +#   |
   3.559 +#   +-< $(vmlinux-init)
   3.560 +#   |   +--< init/version.o + more
   3.561 +#   |
   3.562 +#   +--< $(vmlinux-main)
   3.563 +#   |    +--< driver/built-in.o mm/built-in.o + more
   3.564 +#   |
   3.565 +#   +-< kallsyms.o (see description in CONFIG_KALLSYMS section)
   3.566 +#
   3.567 +# vmlinux version (uname -v) cannot be updated during normal
   3.568 +# descending-into-subdirs phase since we do not yet know if we need to
   3.569 +# update vmlinux.
   3.570 +# Therefore this step is delayed until just before final link of vmlinux -
   3.571 +# except in the kallsyms case where it is done just before adding the
   3.572 +# symbols to the kernel.
   3.573 +#
   3.574 +# System.map is generated to document addresses of all kernel symbols
   3.575 +
   3.576 +vmlinux-init := $(head-y) $(init-y)
   3.577 +vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y)
   3.578 +vmlinux-all  := $(vmlinux-init) $(vmlinux-main)
   3.579 +vmlinux-lds  := arch/$(ARCH)/kernel/vmlinux.lds
   3.580 +
   3.581 +# Rule to link vmlinux - also used during CONFIG_KALLSYMS
   3.582 +# May be overridden by arch/$(ARCH)/Makefile
   3.583 +quiet_cmd_vmlinux__ ?= LD      $@
   3.584 +      cmd_vmlinux__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -o $@ \
   3.585 +      -T $(vmlinux-lds) $(vmlinux-init)                          \
   3.586 +      --start-group $(vmlinux-main) --end-group                  \
   3.587 +      $(filter-out $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) FORCE ,$^)
   3.588 +
   3.589 +# Generate new vmlinux version
   3.590 +quiet_cmd_vmlinux_version = GEN     .version
   3.591 +      cmd_vmlinux_version = set -e;                     \
   3.592 +	. $(srctree)/scripts/mkversion > .tmp_version;	\
   3.593 +	mv -f .tmp_version .version;			\
   3.594 +	$(MAKE) $(build)=init
   3.595 +
   3.596 +# Generate System.map
   3.597 +quiet_cmd_sysmap = SYSMAP 
   3.598 +      cmd_sysmap = $(CONFIG_SHELL) $(srctree)/scripts/mksysmap
   3.599 +
   3.600 +# Link of vmlinux
   3.601 +# If CONFIG_KALLSYMS is set .version is already updated
   3.602 +# Generate System.map and verify that the content is consistent
   3.603 +
   3.604 +define rule_vmlinux__
   3.605 +	$(if $(CONFIG_KALLSYMS),,+$(call cmd,vmlinux_version))
   3.606 +
   3.607 +	$(call cmd,vmlinux__)
   3.608 +	$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
   3.609 +
   3.610 +	$(Q)$(if $($(quiet)cmd_sysmap),                 \
   3.611 +	  echo '  $($(quiet)cmd_sysmap) System.map' &&) \
   3.612 +	$(cmd_sysmap) $@ System.map;                    \
   3.613 +	if [ $$? -ne 0 ]; then                          \
   3.614 +		rm -f $@;                               \
   3.615 +		/bin/false;                             \
   3.616 +	fi;
   3.617 +	$(verify_kallsyms)
   3.618 +endef
   3.619 +
   3.620 +
   3.621 +ifdef CONFIG_KALLSYMS
   3.622 +# Generate section listing all symbols and add it into vmlinux $(kallsyms.o)
   3.623 +# It's a three stage process:
   3.624 +# o .tmp_vmlinux1 has all symbols and sections, but __kallsyms is
   3.625 +#   empty
   3.626 +#   Running kallsyms on that gives us .tmp_kallsyms1.o with
   3.627 +#   the right size - vmlinux version (uname -v) is updated during this step
   3.628 +# o .tmp_vmlinux2 now has a __kallsyms section of the right size,
   3.629 +#   but due to the added section, some addresses have shifted.
   3.630 +#   From here, we generate a correct .tmp_kallsyms2.o
   3.631 +# o The correct .tmp_kallsyms2.o is linked into the final vmlinux.
   3.632 +# o Verify that the System.map from vmlinux matches the map from
   3.633 +#   .tmp_vmlinux2, just in case we did not generate kallsyms correctly.
   3.634 +# o If CONFIG_KALLSYMS_EXTRA_PASS is set, do an extra pass using
   3.635 +#   .tmp_vmlinux3 and .tmp_kallsyms3.o.  This is only meant as a
   3.636 +#   temporary bypass to allow the kernel to be built while the
   3.637 +#   maintainers work out what went wrong with kallsyms.
   3.638 +
   3.639 +ifdef CONFIG_KALLSYMS_EXTRA_PASS
   3.640 +last_kallsyms := 3
   3.641 +else
   3.642 +last_kallsyms := 2
   3.643 +endif
   3.644 +
   3.645 +kallsyms.o := .tmp_kallsyms$(last_kallsyms).o
   3.646 +
   3.647 +define verify_kallsyms
   3.648 +	$(Q)$(if $($(quiet)cmd_sysmap),                       \
   3.649 +	  echo '  $($(quiet)cmd_sysmap) .tmp_System.map' &&)  \
   3.650 +	  $(cmd_sysmap) .tmp_vmlinux$(last_kallsyms) .tmp_System.map
   3.651 +	$(Q)cmp -s System.map .tmp_System.map ||              \
   3.652 +		(echo Inconsistent kallsyms data;             \
   3.653 +		 echo Try setting CONFIG_KALLSYMS_EXTRA_PASS; \
   3.654 +		 rm .tmp_kallsyms* ; /bin/false )
   3.655 +endef
   3.656 +
   3.657 +# Update vmlinux version before link
   3.658 +# Use + in front of this rule to silent warning about make -j1
   3.659 +cmd_ksym_ld = $(cmd_vmlinux__)
   3.660 +define rule_ksym_ld
   3.661 +	+$(call cmd,vmlinux_version)
   3.662 +	$(call cmd,vmlinux__)
   3.663 +	$(Q)echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd
   3.664 +endef
   3.665 +
   3.666 +# Generate .S file with all kernel symbols
   3.667 +quiet_cmd_kallsyms = KSYM    $@
   3.668 +      cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
   3.669 +                     $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
   3.670 +
   3.671 +.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
   3.672 +	$(call if_changed_dep,as_o_S)
   3.673 +
   3.674 +.tmp_kallsyms%.S: .tmp_vmlinux% $(KALLSYMS)
   3.675 +	$(call cmd,kallsyms)
   3.676 +
   3.677 +# .tmp_vmlinux1 must be complete except kallsyms, so update vmlinux version
   3.678 +.tmp_vmlinux1: $(vmlinux-lds) $(vmlinux-all) FORCE
   3.679 +	$(call if_changed_rule,ksym_ld)
   3.680 +
   3.681 +.tmp_vmlinux2: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms1.o FORCE
   3.682 +	$(call if_changed,vmlinux__)
   3.683 +
   3.684 +.tmp_vmlinux3: $(vmlinux-lds) $(vmlinux-all) .tmp_kallsyms2.o FORCE
   3.685 +	$(call if_changed,vmlinux__)
   3.686 +
   3.687 +# Needs to visit scripts/ before $(KALLSYMS) can be used.
   3.688 +$(KALLSYMS): scripts ;
   3.689 +
   3.690 +endif # ifdef CONFIG_KALLSYMS
   3.691 +
   3.692 +# vmlinux image - including updated kernel symbols
   3.693 +vmlinux: $(vmlinux-lds) $(vmlinux-init) $(vmlinux-main) $(kallsyms.o) FORCE
   3.694 +	$(call if_changed_rule,vmlinux__)
   3.695 +
   3.696 +# The actual objects are generated when descending, 
   3.697 +# make sure no implicit rule kicks in
   3.698 +$(sort $(vmlinux-init) $(vmlinux-main)) $(vmlinux-lds): $(vmlinux-dirs) ;
   3.699 +
   3.700 +# Handle descending into subdirectories listed in $(vmlinux-dirs)
   3.701 +# Preset locale variables to speed up the build process. Limit locale
   3.702 +# tweaks to this spot to avoid wrong language settings when running
   3.703 +# make menuconfig etc.
   3.704 +# Error messages still appears in the original language
   3.705 +
   3.706 +.PHONY: $(vmlinux-dirs)
   3.707 +$(vmlinux-dirs): prepare-all scripts
   3.708 +	$(Q)$(MAKE) $(build)=$@
   3.709 +
   3.710 +# Things we need to do before we recursively start building the kernel
   3.711 +# or the modules are listed in "prepare-all".
   3.712 +# A multi level approach is used. prepare1 is updated first, then prepare0.
   3.713 +# prepare-all is the collection point for the prepare targets.
   3.714 +
   3.715 +.PHONY: prepare-all prepare prepare0 prepare1 prepare2
   3.716 +
   3.717 +# prepare 2 generate Makefile to be placed in output directory, if
   3.718 +# using a seperate output directory. This allows convinient use
   3.719 +# of make in output directory
   3.720 +prepare2:
   3.721 +	$(Q)if /usr/bin/env test ! $(srctree) -ef $(objtree); then \
   3.722 +	$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile              \
   3.723 +	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)         \
   3.724 +	    > $(objtree)/Makefile;                                 \
   3.725 +	fi
   3.726 +
   3.727 +# prepare1 is used to check if we are building in a separate output directory,
   3.728 +# and if so do:
   3.729 +# 1) Check that make has not been executed in the kernel src $(srctree)
   3.730 +# 2) Create the include2 directory, used for the second asm symlink
   3.731 +
   3.732 +prepare1: prepare2
   3.733 +ifneq ($(KBUILD_SRC),)
   3.734 +	@echo '  Using $(srctree) as source for kernel'
   3.735 +	$(Q)if [ -h $(srctree)/include/asm -o -f $(srctree)/.config ]; then \
   3.736 +		echo "  $(srctree) is not clean, please run 'make mrproper'";\
   3.737 +		echo "  in the '$(srctree)' directory.";\
   3.738 +		/bin/false; \
   3.739 +	fi;
   3.740 +	$(Q)if [ ! -d include2 ]; then mkdir -p include2; fi;
   3.741 +	$(Q)ln -fsn $(srctree)/include/asm-$(ARCH) include2/asm
   3.742 +endif
   3.743 +
   3.744 +prepare0: prepare1 include/linux/version.h include/asm include/config/MARKER
   3.745 +ifneq ($(KBUILD_MODULES),)
   3.746 +	$(Q)rm -rf $(MODVERDIR)
   3.747 +	$(Q)mkdir -p $(MODVERDIR)
   3.748 +endif
   3.749 +
   3.750 +# All the preparing..
   3.751 +prepare-all: prepare0 prepare
   3.752 +
   3.753 +#	Leave this as default for preprocessing vmlinux.lds.S, which is now
   3.754 +#	done in arch/$(ARCH)/kernel/Makefile
   3.755 +
   3.756 +export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
   3.757 +
   3.758 +# Single targets
   3.759 +# ---------------------------------------------------------------------------
   3.760 +
   3.761 +%.s: %.c scripts FORCE
   3.762 +	$(Q)$(MAKE) $(build)=$(@D) $@
   3.763 +%.i: %.c scripts FORCE
   3.764 +	$(Q)$(MAKE) $(build)=$(@D) $@
   3.765 +%.o: %.c scripts FORCE
   3.766 +	$(Q)$(MAKE) $(build)=$(@D) $@
   3.767 +%/:      scripts prepare FORCE
   3.768 +	$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) $(build)=$(@D)
   3.769 +%.lst: %.c scripts FORCE
   3.770 +	$(Q)$(MAKE) $(build)=$(@D) $@
   3.771 +%.s: %.S scripts FORCE
   3.772 +	$(Q)$(MAKE) $(build)=$(@D) $@
   3.773 +%.o: %.S scripts FORCE
   3.774 +	$(Q)$(MAKE) $(build)=$(@D) $@
   3.775 +
   3.776 +# 	FIXME: The asm symlink changes when $(ARCH) changes. That's
   3.777 +#	hard to detect, but I suppose "make mrproper" is a good idea
   3.778 +#	before switching between archs anyway.
   3.779 +
   3.780 +include/asm:
   3.781 +	@echo '  SYMLINK $@ -> include/asm-$(ARCH)'
   3.782 +	$(Q)if [ ! -d include ]; then mkdir -p include; fi;
   3.783 +	@ln -fsn asm-$(ARCH) $@
   3.784 +
   3.785 +# 	Split autoconf.h into include/linux/config/*
   3.786 +
   3.787 +include/config/MARKER: include/linux/autoconf.h
   3.788 +	@echo '  SPLIT   include/linux/autoconf.h -> include/config/*'
   3.789 +	@scripts/basic/split-include include/linux/autoconf.h include/config
   3.790 +	@touch $@
   3.791 +
   3.792 +# Generate some files
   3.793 +# ---------------------------------------------------------------------------
   3.794 +
   3.795 +# KERNELRELEASE can change from a few different places, meaning version.h
   3.796 +# needs to be updated, so this check is forced on all builds
   3.797 +
   3.798 +uts_len := 64
   3.799 +
   3.800 +define filechk_version.h
   3.801 +	if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
   3.802 +	  echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
   3.803 +	  exit 1; \
   3.804 +	fi; \
   3.805 +	(echo \#define UTS_RELEASE \"$(KERNELRELEASE)\"; \
   3.806 +	  echo \#define LINUX_VERSION_CODE `expr $(VERSION) \\* 65536 + $(PATCHLEVEL) \\* 256 + $(SUBLEVEL)`; \
   3.807 +	 echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))'; \
   3.808 +	)
   3.809 +endef
   3.810 +
   3.811 +include/linux/version.h: $(srctree)/Makefile FORCE
   3.812 +	$(call filechk,version.h)
   3.813 +
   3.814 +# ---------------------------------------------------------------------------
   3.815 +
   3.816 +.PHONY: depend dep
   3.817 +depend dep:
   3.818 +	@echo '*** Warning: make $@ is unnecessary now.'
   3.819 +
   3.820 +# ---------------------------------------------------------------------------
   3.821 +# Modules
   3.822 +
   3.823 +ifdef CONFIG_MODULES
   3.824 +
   3.825 +# 	By default, build modules as well
   3.826 +
   3.827 +all: modules
   3.828 +
   3.829 +#	Build modules
   3.830 +
   3.831 +.PHONY: modules
   3.832 +modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux)
   3.833 +	@echo '  Building modules, stage 2.';
   3.834 +	$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
   3.835 +
   3.836 +
   3.837 +# Target to prepare building external modules
   3.838 +.PHONY: modules_prepare
   3.839 +modules_prepare: prepare-all scripts
   3.840 +
   3.841 +# Target to install modules
   3.842 +.PHONY: modules_install
   3.843 +modules_install: _modinst_ _modinst_post
   3.844 +
   3.845 +.PHONY: _modinst_
   3.846 +_modinst_:
   3.847 +	@if [ -z "`$(DEPMOD) -V | grep module-init-tools`" ]; then \
   3.848 +		echo "Warning: you may need to install module-init-tools"; \
   3.849 +		echo "See http://www.codemonkey.org.uk/docs/post-halloween-2.6.txt";\
   3.850 +		sleep 1; \
   3.851 +	fi
   3.852 +	@rm -rf $(MODLIB)/kernel
   3.853 +	@rm -f $(MODLIB)/source
   3.854 +	@mkdir -p $(MODLIB)/kernel
   3.855 +	@ln -s $(srctree) $(MODLIB)/source
   3.856 +	@if [ ! $(objtree) -ef  $(MODLIB)/build ]; then \
   3.857 +		rm -f $(MODLIB)/build ; \
   3.858 +		ln -s $(objtree) $(MODLIB)/build ; \
   3.859 +	fi
   3.860 +	$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
   3.861 +
   3.862 +# If System.map exists, run depmod.  This deliberately does not have a
   3.863 +# dependency on System.map since that would run the dependency tree on
   3.864 +# vmlinux.  This depmod is only for convenience to give the initial
   3.865 +# boot a modules.dep even before / is mounted read-write.  However the
   3.866 +# boot script depmod is the master version.
   3.867 +ifeq "$(strip $(INSTALL_MOD_PATH))" ""
   3.868 +depmod_opts	:=
   3.869 +else
   3.870 +depmod_opts	:= -b $(INSTALL_MOD_PATH) -r
   3.871 +endif
   3.872 +.PHONY: _modinst_post
   3.873 +_modinst_post: _modinst_
   3.874 +	if [ -r System.map ]; then $(DEPMOD) -ae -F System.map $(depmod_opts) $(KERNELRELEASE); fi
   3.875 +
   3.876 +else # CONFIG_MODULES
   3.877 +
   3.878 +# Modules not configured
   3.879 +# ---------------------------------------------------------------------------
   3.880 +
   3.881 +modules modules_install: FORCE
   3.882 +	@echo
   3.883 +	@echo "The present kernel configuration has modules disabled."
   3.884 +	@echo "Type 'make config' and enable loadable module support."
   3.885 +	@echo "Then build a kernel with module support enabled."
   3.886 +	@echo
   3.887 +	@exit 1
   3.888 +
   3.889 +endif # CONFIG_MODULES
   3.890 +
   3.891 +# Generate asm-offsets.h 
   3.892 +# ---------------------------------------------------------------------------
   3.893 +
   3.894 +define filechk_gen-asm-offsets
   3.895 +	(set -e; \
   3.896 +	 echo "#ifndef __ASM_OFFSETS_H__"; \
   3.897 +	 echo "#define __ASM_OFFSETS_H__"; \
   3.898 +	 echo "/*"; \
   3.899 +	 echo " * DO NOT MODIFY."; \
   3.900 +	 echo " *"; \
   3.901 +	 echo " * This file was generated by arch/$(ARCH)/Makefile"; \
   3.902 +	 echo " *"; \
   3.903 +	 echo " */"; \
   3.904 +	 echo ""; \
   3.905 +	 sed -ne "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"; \
   3.906 +	 echo ""; \
   3.907 +	 echo "#endif" )
   3.908 +endef
   3.909 +
   3.910 +
   3.911 +###
   3.912 +# Cleaning is done on three levels.
   3.913 +# make clean     Delete most generated files
   3.914 +#                Leave enough to build external modules
   3.915 +# make mrproper  Delete the current configuration, and all generated files
   3.916 +# make distclean Remove editor backup files, patch leftover files and the like
   3.917 +
   3.918 +# Directories & files removed with 'make clean'
   3.919 +CLEAN_DIRS  += $(MODVERDIR)
   3.920 +CLEAN_FILES +=	vmlinux System.map \
   3.921 +                .tmp_kallsyms* .tmp_version .tmp_vmlinux* .tmp_System.map
   3.922 +
   3.923 +# Directories & files removed with 'make mrproper'
   3.924 +MRPROPER_DIRS  += include/config include2
   3.925 +MRPROPER_FILES += .config .config.old include/asm .version \
   3.926 +                  include/linux/autoconf.h include/linux/version.h \
   3.927 +                  Module.symvers tags TAGS cscope* include/.asm-ignore
   3.928 +
   3.929 +# clean - Delete most, but leave enough to build external modules
   3.930 +#
   3.931 +clean: rm-dirs  := $(CLEAN_DIRS)
   3.932 +clean: rm-files := $(CLEAN_FILES)
   3.933 +clean-dirs      := $(addprefix _clean_,$(vmlinux-alldirs))
   3.934 +
   3.935 +.PHONY: $(clean-dirs) clean archclean
   3.936 +$(clean-dirs):
   3.937 +	$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
   3.938 +
   3.939 +clean: archclean $(clean-dirs)
   3.940 +	$(call cmd,rmdirs)
   3.941 +	$(call cmd,rmfiles)
   3.942 +	@find . $(RCS_FIND_IGNORE) \
   3.943 +	 	\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
   3.944 +		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
   3.945 +		-type f -print | xargs rm -f
   3.946 +
   3.947 +# mrproper - Delete all generated files, including .config
   3.948 +#
   3.949 +mrproper: rm-dirs  := $(wildcard $(MRPROPER_DIRS))
   3.950 +mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
   3.951 +mrproper-dirs      := $(addprefix _mrproper_,Documentation/DocBook scripts)
   3.952 +
   3.953 +.PHONY: $(mrproper-dirs) mrproper archmrproper
   3.954 +$(mrproper-dirs):
   3.955 +	$(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
   3.956 +
   3.957 +mrproper: clean archmrproper $(mrproper-dirs)
   3.958 +	$(call cmd,rmdirs)
   3.959 +	$(call cmd,rmfiles)
   3.960 +
   3.961 +# distclean
   3.962 +#
   3.963 +.PHONY: distclean
   3.964 +
   3.965 +distclean: mrproper
   3.966 +	@find $(srctree) $(RCS_FIND_IGNORE) \
   3.967 +	 	\( -name '*.orig' -o -name '*.rej' -o -name '*~' \
   3.968 +		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
   3.969 +	 	-o -name '.*.rej' -o -size 0 \
   3.970 +		-o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \
   3.971 +		-type f -print | xargs rm -f
   3.972 +
   3.973 +
   3.974 +# Packaging of the kernel to various formats
   3.975 +# ---------------------------------------------------------------------------
   3.976 +# rpm target kept for backward compatibility
   3.977 +package-dir	:= $(srctree)/scripts/package
   3.978 +
   3.979 +.PHONY: %-pkg rpm
   3.980 +
   3.981 +%pkg: FORCE
   3.982 +	$(Q)$(MAKE) -f $(package-dir)/Makefile $@
   3.983 +rpm: FORCE
   3.984 +	$(Q)$(MAKE) -f $(package-dir)/Makefile $@
   3.985 +
   3.986 +
   3.987 +# Brief documentation of the typical targets used
   3.988 +# ---------------------------------------------------------------------------
   3.989 +
   3.990 +boards := $(wildcard $(srctree)/arch/$(ARCH)/configs/*_defconfig)
   3.991 +boards := $(notdir $(boards))
   3.992 +
   3.993 +help:
   3.994 +	@echo  'Cleaning targets:'
   3.995 +	@echo  '  clean		  - remove most generated files but keep the config'
   3.996 +	@echo  '  mrproper	  - remove all generated files + config + various backup files'
   3.997 +	@echo  ''
   3.998 +	@echo  'Configuration targets:'
   3.999 +	@$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
  3.1000 +	@echo  ''
  3.1001 +	@echo  'Other generic targets:'
  3.1002 +	@echo  '  all		  - Build all targets marked with [*]'
  3.1003 +	@echo  '* vmlinux	  - Build the bare kernel'
  3.1004 +	@echo  '* modules	  - Build all modules'
  3.1005 +	@echo  '  modules_install - Install all modules'
  3.1006 +	@echo  '  dir/            - Build all files in dir and below'
  3.1007 +	@echo  '  dir/file.[ois]  - Build specified target only'
  3.1008 +	@echo  '  rpm		  - Build a kernel as an RPM package'
  3.1009 +	@echo  '  tags/TAGS	  - Generate tags file for editors'
  3.1010 +	@echo  '  cscope	  - Generate cscope index'
  3.1011 +	@echo  ''
  3.1012 +	@echo  'Static analysers'
  3.1013 +	@echo  '  buildcheck      - List dangling references to vmlinux discarded sections'
  3.1014 +	@echo  '                    and init sections from non-init sections'
  3.1015 +	@echo  '  checkstack      - Generate a list of stack hogs'
  3.1016 +	@echo  '  namespacecheck  - Name space analysis on compiled kernel'
  3.1017 +	@echo  ''
  3.1018 +	@echo  'Kernel packaging:'
  3.1019 +	@$(MAKE) -f $(package-dir)/Makefile help
  3.1020 +	@echo  ''
  3.1021 +	@echo  'Documentation targets:'
  3.1022 +	@$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp
  3.1023 +	@echo  ''
  3.1024 +	@echo  'Architecture specific targets ($(ARCH)):'
  3.1025 +	@$(if $(archhelp),$(archhelp),\
  3.1026 +		echo '  No architecture specific help defined for $(ARCH)')
  3.1027 +	@echo  ''
  3.1028 +	@$(if $(boards), \
  3.1029 +		$(foreach b, $(boards), \
  3.1030 +		printf "  %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \
  3.1031 +		echo '')
  3.1032 +
  3.1033 +	@echo  '  make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build'
  3.1034 +	@echo  '  make O=dir [targets] Locate all output files in "dir", including .config'
  3.1035 +	@echo  '  make C=1   [targets] Check all c source with $$CHECK (sparse)'
  3.1036 +	@echo  '  make C=2   [targets] Force check of all c source with $$CHECK (sparse)'
  3.1037 +	@echo  ''
  3.1038 +	@echo  'Execute "make" or "make all" to build all targets marked with [*] '
  3.1039 +	@echo  'For further info see the ./README file'
  3.1040 +
  3.1041 +
  3.1042 +# Documentation targets
  3.1043 +# ---------------------------------------------------------------------------
  3.1044 +%docs: scripts_basic FORCE
  3.1045 +	$(Q)$(MAKE) $(build)=Documentation/DocBook $@
  3.1046 +
  3.1047 +else # KBUILD_EXTMOD
  3.1048 +
  3.1049 +###
  3.1050 +# External module support.
  3.1051 +# When building external modules the kernel used as basis is considered
  3.1052 +# read-only, and no consistency checks are made and the make
  3.1053 +# system is not used on the basis kernel. If updates are required
  3.1054 +# in the basis kernel ordinary make commands (without M=...) must
  3.1055 +# be used.
  3.1056 +#
  3.1057 +# The following are the only valid targets when building external
  3.1058 +# modules.
  3.1059 +# make M=dir clean     Delete all automatically generated files
  3.1060 +# make M=dir modules   Make all modules in specified dir
  3.1061 +# make M=dir	       Same as 'make M=dir modules'
  3.1062 +# make M=dir modules_install
  3.1063 +#                      Install the modules build in the module directory
  3.1064 +#                      Assumes install directory is already created
  3.1065 +
  3.1066 +# We are always building modules
  3.1067 +KBUILD_MODULES := 1
  3.1068 +.PHONY: crmodverdir
  3.1069 +crmodverdir:
  3.1070 +	$(Q)mkdir -p $(MODVERDIR)
  3.1071 +
  3.1072 +module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
  3.1073 +.PHONY: $(module-dirs) modules
  3.1074 +$(module-dirs): crmodverdir
  3.1075 +	$(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@)
  3.1076 +
  3.1077 +modules: $(module-dirs)
  3.1078 +	@echo '  Building modules, stage 2.';
  3.1079 +	$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modpost
  3.1080 +
  3.1081 +.PHONY: modules_install
  3.1082 +modules_install:
  3.1083 +	$(Q)$(MAKE) -rR -f $(srctree)/scripts/Makefile.modinst
  3.1084 +
  3.1085 +clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD))
  3.1086 +
  3.1087 +.PHONY: $(clean-dirs) clean
  3.1088 +$(clean-dirs):
  3.1089 +	$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
  3.1090 +
  3.1091 +clean:	rm-dirs := $(MODVERDIR)
  3.1092 +clean: $(clean-dirs)
  3.1093 +	$(call cmd,rmdirs)
  3.1094 +	@find $(KBUILD_EXTMOD) $(RCS_FIND_IGNORE) \
  3.1095 +	 	\( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
  3.1096 +		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \) \
  3.1097 +		-type f -print | xargs rm -f
  3.1098 +
  3.1099 +help:
  3.1100 +	@echo  '  Building external modules.'
  3.1101 +	@echo  '  Syntax: make -C path/to/kernel/src M=$$PWD target'
  3.1102 +	@echo  ''
  3.1103 +	@echo  '  modules         - default target, build the module(s)'
  3.1104 +	@echo  '  modules_install - install the module'
  3.1105 +	@echo  '  clean           - remove generated files in module directory only'
  3.1106 +	@echo  ''
  3.1107 +endif # KBUILD_EXTMOD
  3.1108 +
  3.1109 +# Generate tags for editors
  3.1110 +# ---------------------------------------------------------------------------
  3.1111 +
  3.1112 +define all-sources
  3.1113 +	( find $(srctree) $(RCS_FIND_IGNORE) \
  3.1114 +	       \( -name include -o -name arch \) -prune -o \
  3.1115 +	       -name '*.[chS]' -print; \
  3.1116 +	  find $(srctree)/arch/$(ARCH) $(RCS_FIND_IGNORE) \
  3.1117 +	       -name '*.[chS]' -print; \
  3.1118 +	  find $(srctree)/security/selinux/include $(RCS_FIND_IGNORE) \
  3.1119 +	       -name '*.[chS]' -print; \
  3.1120 +	  find $(srctree)/include $(RCS_FIND_IGNORE) \
  3.1121 +	       \( -name config -o -name 'asm-*' \) -prune \
  3.1122 +	       -o -name '*.[chS]' -print; \
  3.1123 +	  find $(srctree)/include/asm-$(ARCH) $(RCS_FIND_IGNORE) \
  3.1124 +	       -name '*.[chS]' -print; \
  3.1125 +	  find $(srctree)/include/asm-generic $(RCS_FIND_IGNORE) \
  3.1126 +	       -name '*.[chS]' -print )
  3.1127 +endef
  3.1128 +
  3.1129 +quiet_cmd_cscope-file = FILELST cscope.files
  3.1130 +      cmd_cscope-file = $(all-sources) > cscope.files
  3.1131 +
  3.1132 +quiet_cmd_cscope = MAKE    cscope.out
  3.1133 +      cmd_cscope = cscope -k -b -q
  3.1134 +
  3.1135 +cscope: FORCE
  3.1136 +	$(call cmd,cscope-file)
  3.1137 +	$(call cmd,cscope)
  3.1138 +
  3.1139 +quiet_cmd_TAGS = MAKE   $@
  3.1140 +cmd_TAGS = $(all-sources) | etags -
  3.1141 +
  3.1142 +# 	Exuberant ctags works better with -I
  3.1143 +
  3.1144 +quiet_cmd_tags = MAKE   $@
  3.1145 +define cmd_tags
  3.1146 +	rm -f $@; \
  3.1147 +	CTAGSF=`ctags --version | grep -i exuberant >/dev/null && echo "-I __initdata,__exitdata,EXPORT_SYMBOL,EXPORT_SYMBOL_NOVERS"`; \
  3.1148 +	$(all-sources) | xargs ctags $$CTAGSF -a
  3.1149 +endef
  3.1150 +
  3.1151 +TAGS: FORCE
  3.1152 +	$(call cmd,TAGS)
  3.1153 +
  3.1154 +tags: FORCE
  3.1155 +	$(call cmd,tags)
  3.1156 +
  3.1157 +
  3.1158 +# Scripts to check various things for consistency
  3.1159 +# ---------------------------------------------------------------------------
  3.1160 +
  3.1161 +configcheck:
  3.1162 +	find * $(RCS_FIND_IGNORE) \
  3.1163 +		-name '*.[hcS]' -type f -print | sort \
  3.1164 +		| xargs $(PERL) -w scripts/checkconfig.pl
  3.1165 +
  3.1166 +includecheck:
  3.1167 +	find * $(RCS_FIND_IGNORE) \
  3.1168 +		-name '*.[hcS]' -type f -print | sort \
  3.1169 +		| xargs $(PERL) -w scripts/checkincludes.pl
  3.1170 +
  3.1171 +versioncheck:
  3.1172 +	find * $(RCS_FIND_IGNORE) \
  3.1173 +		-name '*.[hcS]' -type f -print | sort \
  3.1174 +		| xargs $(PERL) -w scripts/checkversion.pl
  3.1175 +
  3.1176 +buildcheck:
  3.1177 +	$(PERL) $(srctree)/scripts/reference_discarded.pl
  3.1178 +	$(PERL) $(srctree)/scripts/reference_init.pl
  3.1179 +
  3.1180 +namespacecheck:
  3.1181 +	$(PERL) $(srctree)/scripts/namespace.pl
  3.1182 +
  3.1183 +endif #ifeq ($(config-targets),1)
  3.1184 +endif #ifeq ($(mixed-targets),1)
  3.1185 +
  3.1186 +.PHONY: checkstack
  3.1187 +checkstack:
  3.1188 +	$(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \
  3.1189 +	$(PERL) $(src)/scripts/checkstack.pl $(ARCH)
  3.1190 +
  3.1191 +# FIXME Should go into a make.lib or something 
  3.1192 +# ===========================================================================
  3.1193 +
  3.1194 +quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN   $(wildcard $(rm-dirs)))
  3.1195 +      cmd_rmdirs = rm -rf $(rm-dirs)
  3.1196 +
  3.1197 +quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files)))
  3.1198 +      cmd_rmfiles = rm -f $(rm-files)
  3.1199 +
  3.1200 +
  3.1201 +a_flags = -Wp,-MD,$(depfile) $(AFLAGS) $(AFLAGS_KERNEL) \
  3.1202 +	  $(NOSTDINC_FLAGS) $(CPPFLAGS) \
  3.1203 +	  $(modkern_aflags) $(EXTRA_AFLAGS) $(AFLAGS_$(*F).o)
  3.1204 +
  3.1205 +quiet_cmd_as_o_S = AS      $@
  3.1206 +cmd_as_o_S       = $(CC) $(a_flags) -c -o $@ $<
  3.1207 +
  3.1208 +# read all saved command lines
  3.1209 +
  3.1210 +targets := $(wildcard $(sort $(targets)))
  3.1211 +cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
  3.1212 +
  3.1213 +ifneq ($(cmd_files),)
  3.1214 +  $(cmd_files): ;	# Do not try to update included dependency files
  3.1215 +  include $(cmd_files)
  3.1216 +endif
  3.1217 +
  3.1218 +# Execute command and generate cmd file
  3.1219 +if_changed = $(if $(strip $? \
  3.1220 +		          $(filter-out $(cmd_$(1)),$(cmd_$@))\
  3.1221 +			  $(filter-out $(cmd_$@),$(cmd_$(1)))),\
  3.1222 +	@set -e; \
  3.1223 +	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
  3.1224 +	$(cmd_$(1)); \
  3.1225 +	echo 'cmd_$@ := $(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).cmd)
  3.1226 +
  3.1227 +
  3.1228 +# execute the command and also postprocess generated .d dependencies
  3.1229 +# file
  3.1230 +if_changed_dep = $(if $(strip $? $(filter-out FORCE $(wildcard $^),$^)\
  3.1231 +		          $(filter-out $(cmd_$(1)),$(cmd_$@))\
  3.1232 +			  $(filter-out $(cmd_$@),$(cmd_$(1)))),\
  3.1233 +	$(Q)set -e; \
  3.1234 +	$(if $($(quiet)cmd_$(1)),echo '  $(subst ','\'',$($(quiet)cmd_$(1)))';) \
  3.1235 +	$(cmd_$(1)); \
  3.1236 +	scripts/basic/fixdep $(depfile) $@ '$(subst $$,$$$$,$(subst ','\'',$(cmd_$(1))))' > $(@D)/.$(@F).tmp; \
  3.1237 +	rm -f $(depfile); \
  3.1238 +	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd)
  3.1239 +
  3.1240 +# Usage: $(call if_changed_rule,foo)
  3.1241 +# will check if $(cmd_foo) changed, or any of the prequisites changed,
  3.1242 +# and if so will execute $(rule_foo)
  3.1243 +
  3.1244 +if_changed_rule = $(if $(strip $? \
  3.1245 +		               $(filter-out $(cmd_$(1)),$(cmd_$(@F)))\
  3.1246 +			       $(filter-out $(cmd_$(@F)),$(cmd_$(1)))),\
  3.1247 +	               $(Q)$(rule_$(1)))
  3.1248 +
  3.1249 +# If quiet is set, only print short version of command
  3.1250 +
  3.1251 +cmd = @$(if $($(quiet)cmd_$(1)),echo '  $($(quiet)cmd_$(1))' &&) $(cmd_$(1))
  3.1252 +
  3.1253 +# filechk is used to check if the content of a generated file is updated.
  3.1254 +# Sample usage:
  3.1255 +# define filechk_sample
  3.1256 +#	echo $KERNELRELEASE
  3.1257 +# endef
  3.1258 +# version.h : Makefile
  3.1259 +#	$(call filechk,sample)
  3.1260 +# The rule defined shall write to stdout the content of the new file.
  3.1261 +# The existing file will be compared with the new one.
  3.1262 +# - If no file exist it is created
  3.1263 +# - If the content differ the new file is used
  3.1264 +# - If they are equal no change, and no timestamp update
  3.1265 +
  3.1266 +define filechk
  3.1267 +	@set -e;				\
  3.1268 +	echo '  CHK     $@';			\
  3.1269 +	mkdir -p $(dir $@);			\
  3.1270 +	$(filechk_$(1)) < $< > $@.tmp;		\
  3.1271 +	if [ -r $@ ] && cmp -s $@ $@.tmp; then	\
  3.1272 +		rm -f $@.tmp;			\
  3.1273 +	else					\
  3.1274 +		echo '  UPD     $@';		\
  3.1275 +		mv -f $@.tmp $@;		\
  3.1276 +	fi
  3.1277 +endef
  3.1278 +
  3.1279 +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=dir
  3.1280 +# Usage:
  3.1281 +# $(Q)$(MAKE) $(build)=dir
  3.1282 +build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
  3.1283 +
  3.1284 +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir
  3.1285 +# Usage:
  3.1286 +# $(Q)$(MAKE) $(clean)=dir
  3.1287 +clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj
  3.1288 +
  3.1289 +#	$(call descend,<dir>,<target>)
  3.1290 +#	Recursively call a sub-make in <dir> with target <target>
  3.1291 +# Usage is deprecated, because make does not see this as an invocation of make.
  3.1292 +descend =$(Q)$(MAKE) -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj=$(1) $(2)
  3.1293 +
  3.1294 +endif	# skip-makefile
  3.1295 +
  3.1296 +FORCE:
     4.1 --- a/tools/libxutil/Makefile	Wed Nov 24 11:51:49 2004 +0000
     4.2 +++ b/tools/libxutil/Makefile	Wed Nov 24 18:22:43 2004 +0000
     4.3 @@ -5,11 +5,18 @@ CC = gcc
     4.4  
     4.5  LIB_SRCS :=
     4.6  LIB_SRCS += allocate.c
     4.7 +LIB_SRCS += enum.c
     4.8  LIB_SRCS += file_stream.c
     4.9  LIB_SRCS += gzip_stream.c
    4.10 +LIB_SRCS += hash_table.c
    4.11  LIB_SRCS += iostream.c
    4.12 -#LIB_SRCS += sys_net.c
    4.13 +LIB_SRCS += lexis.c
    4.14 +LIB_SRCS += string_stream.c
    4.15 +LIB_SRCS += sxpr.c
    4.16 +LIB_SRCS += sxpr_parser.c
    4.17 +LIB_SRCS += sys_net.c
    4.18  LIB_SRCS += sys_string.c
    4.19 +LIB_SRCS += util.c
    4.20  
    4.21  LIB_OBJS := $(LIB_SRCS:.c=.o)
    4.22  
    4.23 @@ -29,6 +36,7 @@ LIB_NAME := libxutil
    4.24  LIB      := $(LIB_NAME).so 
    4.25  LIB      += $(LIB_NAME).so.$(MAJOR)
    4.26  LIB      += $(LIB_NAME).so.$(MAJOR).$(MINOR)
    4.27 +LIB      += $(LIB_NAME).a
    4.28  
    4.29  all: check-for-zlib
    4.30  	$(MAKE) $(LIB)
    4.31 @@ -42,6 +50,9 @@ all: check-for-zlib
    4.32  $(LIB_NAME).so.$(MAJOR).$(MINOR): $(LIB_OBJS)
    4.33  	$(CC) -Wl,-soname -Wl,$(LIB_NAME).so.$(MAJOR) -shared -o $@ $^
    4.34  
    4.35 +$(LIB_NAME).a: $(LIB_OBJS)
    4.36 +	$(AR) rc $@ $^
    4.37 +
    4.38  check-for-zlib:
    4.39  	@if [ ! -e /usr/include/zlib.h ]; then \
    4.40  	echo "***********************************************************"; \
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/libxutil/debug.h	Wed Nov 24 18:22:43 2004 +0000
     5.3 @@ -0,0 +1,72 @@
     5.4 +/*
     5.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     5.6 + *
     5.7 + * This library is free software; you can redistribute it and/or modify
     5.8 + * it under the terms of the GNU Lesser General Public License as published by
     5.9 + * the Free Software Foundation; either version 2.1 of the License, or
    5.10 + * (at your option) any later version.
    5.11 + *
    5.12 + * This library is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU Lesser General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU Lesser General Public License
    5.18 + * along with this library; if not, write to the Free Software
    5.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    5.20 + */
    5.21 +#ifndef _XUTIL_DEBUG_H_
    5.22 +#define _XUTIL_DEBUG_H_
    5.23 +
    5.24 +#ifndef MODULE_NAME
    5.25 +#define MODULE_NAME ""
    5.26 +#endif
    5.27 +
    5.28 +#ifdef __KERNEL__
    5.29 +#include <linux/config.h>
    5.30 +#include <linux/kernel.h>
    5.31 +
    5.32 +#ifdef DEBUG
    5.33 +
    5.34 +#define dprintf(fmt, args...) printk(KERN_DEBUG   "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    5.35 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    5.36 +#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    5.37 +#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    5.38 +
    5.39 +#else
    5.40 +
    5.41 +#define dprintf(fmt, args...) do {} while(0)
    5.42 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args)
    5.43 +#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME fmt, ##args)
    5.44 +#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME fmt, ##args)
    5.45 +
    5.46 +#endif
    5.47 +
    5.48 +#else
    5.49 +
    5.50 +#include <stdio.h>
    5.51 +
    5.52 +#ifdef DEBUG
    5.53 +
    5.54 +#define dprintf(fmt, args...) fprintf(stdout, "%d [DBG] " MODULE_NAME ">%s" fmt, getpid(), __FUNCTION__, ##args)
    5.55 +#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args)
    5.56 +#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args)
    5.57 +#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args)
    5.58 +
    5.59 +#else
    5.60 +
    5.61 +#define dprintf(fmt, args...) do {} while(0)
    5.62 +#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME fmt, getpid(), ##args)
    5.63 +#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME fmt, getpid(), ##args)
    5.64 +#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME fmt, getpid(), ##args)
    5.65 +
    5.66 +#endif
    5.67 +
    5.68 +#endif
    5.69 +
    5.70 +/** Print format for an IP address.
    5.71 + * See NIPQUAD(), HIPQUAD()
    5.72 + */
    5.73 +#define IPFMT "%u.%u.%u.%u"
    5.74 +
    5.75 +#endif /* ! _XUTIL_DEBUG_H_ */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/libxutil/enum.c	Wed Nov 24 18:22:43 2004 +0000
     6.3 @@ -0,0 +1,61 @@
     6.4 +/*
     6.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
     6.6 + *
     6.7 + * This library is free software; you can redistribute it and/or modify
     6.8 + * it under the terms of the GNU Lesser General Public License as
     6.9 + * published by the Free Software Foundation; either version 2.1 of the
    6.10 + * License, or  (at your option) any later version. This library is 
    6.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
    6.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
    6.13 + * FITNESS FOR A PARTICULAR PURPOSE.
    6.14 + * See the GNU Lesser General Public License for more details.
    6.15 + *
    6.16 + * You should have received a copy of the GNU Lesser General Public License
    6.17 + * along with this library; if not, write to the Free Software Foundation,
    6.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    6.19 + */
    6.20 +
    6.21 +#ifdef __KERNEL__
    6.22 +#include <linux/errno.h>
    6.23 +#else
    6.24 +#include <errno.h>
    6.25 +#endif
    6.26 +
    6.27 +#include "sys_string.h"
    6.28 +#include "enum.h"
    6.29 +
    6.30 +/** Map an enum name to its value using a table.
    6.31 + *
    6.32 + * @param name enum name
    6.33 + * @param defs enum definitions
    6.34 + * @return enum value or -1 if not known
    6.35 + */
    6.36 +int enum_name_to_val(char *name, EnumDef *defs){
    6.37 +    int val = -1;
    6.38 +    for(; defs->name; defs++){
    6.39 +	if(!strcmp(defs->name, name)){
    6.40 +	    val = defs->val;
    6.41 +	    break;
    6.42 +	}
    6.43 +    }
    6.44 +    return val;
    6.45 +}
    6.46 +
    6.47 +/** Map an enum value to its name using a table.
    6.48 + *
    6.49 + * @param val enum value
    6.50 + * @param defs enum definitions
    6.51 + * @param defs_n number of definitions
    6.52 + * @return enum name or NULL if not known
    6.53 + */
    6.54 +char *enum_val_to_name(int val, EnumDef *defs){
    6.55 +    char *name = NULL;
    6.56 +    for(; defs->name; defs++){
    6.57 +	if(val == defs->val){
    6.58 +	    name = defs->name;
    6.59 +	    break;
    6.60 +	}
    6.61 +    }
    6.62 +    return name;
    6.63 +}
    6.64 +
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/libxutil/enum.h	Wed Nov 24 18:22:43 2004 +0000
     7.3 @@ -0,0 +1,30 @@
     7.4 +/*
     7.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
     7.6 + *
     7.7 + * This library is free software; you can redistribute it and/or modify
     7.8 + * it under the terms of the GNU Lesser General Public License as
     7.9 + * published by the Free Software Foundation; either version 2.1 of the
    7.10 + * License, or  (at your option) any later version. This library is 
    7.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
    7.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.13 + * FITNESS FOR A PARTICULAR PURPOSE.
    7.14 + * See the GNU Lesser General Public License for more details.
    7.15 + *
    7.16 + * You should have received a copy of the GNU Lesser General Public License
    7.17 + * along with this library; if not, write to the Free Software Foundation,
    7.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    7.19 + */
    7.20 +
    7.21 +#ifndef _XUTIL_ENUM_H_
    7.22 +#define _XUTIL_ENUM_H_
    7.23 +
    7.24 +/** Mapping of an enum value to a name. */
    7.25 +typedef struct EnumDef {
    7.26 +    int val;
    7.27 +    char *name;
    7.28 +} EnumDef;
    7.29 +
    7.30 +extern int enum_name_to_val(char *name, EnumDef *defs);
    7.31 +extern char *enum_val_to_name(int val, EnumDef *defs);
    7.32 +
    7.33 +#endif /* _XUTIL_ENUM_H_ */
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/libxutil/hash_table.c	Wed Nov 24 18:22:43 2004 +0000
     8.3 @@ -0,0 +1,640 @@
     8.4 +/*
     8.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
     8.6 + *
     8.7 + * This library is free software; you can redistribute it and/or modify
     8.8 + * it under the terms of the GNU Lesser General Public License as published by
     8.9 + * the Free Software Foundation; either version 2.1 of the License, or
    8.10 + * (at your option) any later version.
    8.11 + *
    8.12 + * This library is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 + * GNU Lesser General Public License for more details.
    8.16 + *
    8.17 + * You should have received a copy of the GNU Lesser General Public License
    8.18 + * along with this library; if not, write to the Free Software
    8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    8.20 + */
    8.21 +
    8.22 +#ifdef __KERNEL__
    8.23 +#  include <linux/config.h>
    8.24 +#  include <linux/module.h>
    8.25 +#  include <linux/kernel.h>
    8.26 +#  include <linux/errno.h>
    8.27 +#else
    8.28 +#  include <errno.h>
    8.29 +#  include <stddef.h>
    8.30 +#endif
    8.31 +
    8.32 +//#include <limits.h>
    8.33 +
    8.34 +#include "allocate.h"
    8.35 +#include "hash_table.h"
    8.36 +
    8.37 +/** @file
    8.38 + * Base support for hashtables.
    8.39 + *
    8.40 + * Hash codes are reduced modulo the number of buckets to index tables,
    8.41 + * so there is no need for hash functions to limit the range of hashcodes.
    8.42 + * In fact it is assumed that hashcodes do not change when the number of
    8.43 + * buckets in the table changes.
    8.44 + */
    8.45 +
    8.46 +/*==========================================================================*/
    8.47 +/** Number of bits in half a word. */
    8.48 +//#if __WORDSIZE == 64
    8.49 +//#define HALF_WORD_BITS 32
    8.50 +//#else
    8.51 +#define HALF_WORD_BITS 16
    8.52 +//#endif
    8.53 +
    8.54 +/** Mask for lo half of a word. On 32-bit this is 
    8.55 + * (1<<16) - 1 = 65535 = 0xffff
    8.56 + * It's 4294967295 = 0xffffffff on 64-bit.
    8.57 + */
    8.58 +#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1)
    8.59 +
    8.60 +/** Get the lo half of a word. */
    8.61 +#define LO_HALF(x) ((x) & LO_HALF_MASK)
    8.62 +
    8.63 +/** Get the hi half of a word. */
    8.64 +#define HI_HALF(x) ((x) >> HALF_WORD_BITS)
    8.65 +
    8.66 +/** Do a full hash on both inputs, using DES-style non-linear scrambling.
    8.67 + * Both inputs are replaced with the results of the hash.
    8.68 + *
    8.69 + * @param pleft input/output word
    8.70 + * @param pright input/output word
    8.71 + */
    8.72 +void pseudo_des(unsigned long *pleft, unsigned long *pright){
    8.73 +    // Bit-rich mixing constant.
    8.74 +    static const unsigned long a_mixer[] = {
    8.75 +        0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, };
    8.76 +
    8.77 +    // Bit-rich mixing constant.
    8.78 +    static const unsigned long b_mixer[] = {
    8.79 +        0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, };
    8.80 +
    8.81 +    // Number of iterations - must be 2 or 4.
    8.82 +    static const int ncycle = 4;
    8.83 +    //static const int ncycle = 2;
    8.84 +
    8.85 +    unsigned long left = *pleft, right = *pright;
    8.86 +    unsigned long v, v_hi, v_lo;
    8.87 +    int i;
    8.88 +
    8.89 +    for(i=0; i<ncycle; i++){
    8.90 +        // Flip some bits in right to get v.
    8.91 +        v = right;
    8.92 +        v ^= a_mixer[i];
    8.93 +        // Get lo and hi halves of v.
    8.94 +        v_lo = LO_HALF(v);
    8.95 +        v_hi = HI_HALF(v);
    8.96 +        // Non-linear mix of the halves of v.
    8.97 +        v = ((v_lo * v_lo) + ~(v_hi * v_hi));
    8.98 +        // Swap the halves of v.
    8.99 +        v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS));
   8.100 +        // Flip some bits.
   8.101 +        v ^= b_mixer[i];
   8.102 +        // More non-linear mixing.
   8.103 +        v += (v_lo * v_hi);
   8.104 +        v ^= left;
   8.105 +        left = right;
   8.106 +        right = v;
   8.107 +    }
   8.108 +    *pleft = left;
   8.109 +    *pright = right;
   8.110 +}
   8.111 +
   8.112 +/** Hash a string.
   8.113 + *
   8.114 + * @param s input to hash
   8.115 + * @return hashcode
   8.116 + */
   8.117 +Hashcode hash_string(char *s){
   8.118 +    Hashcode h = 0;
   8.119 +    if(s){
   8.120 +        for( ; *s; s++){
   8.121 +            h = hash_2ul(h, *s);
   8.122 +        }
   8.123 +    }
   8.124 +    return h;
   8.125 +}
   8.126 +
   8.127 +/** Get the bucket for a hashcode in a hash table.
   8.128 + *
   8.129 + * @param table to get bucket from
   8.130 + * @param hashcode to get bucket for
   8.131 + * @return bucket
   8.132 + */
   8.133 +inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){
   8.134 +    return table->buckets + (hashcode % table->buckets_n);
   8.135 +}
   8.136 +
   8.137 +/** Initialize a hash table.
   8.138 + * Can be safely called more than once.
   8.139 + *
   8.140 + * @param table to initialize
   8.141 + */
   8.142 +void HashTable_init(HashTable *table){
   8.143 +    int i;
   8.144 +
   8.145 +    if(!table->init_done){
   8.146 +        table->init_done = 1;
   8.147 +        table->next_id = 0;
   8.148 +        for(i=0; i<table->buckets_n; i++){
   8.149 +            HTBucket *bucket = get_bucket(table, i);
   8.150 +            bucket->head = 0;
   8.151 +            bucket->count = 0;
   8.152 +        }
   8.153 +        table->entry_count = 0;
   8.154 +    }
   8.155 +}
   8.156 +
   8.157 +/** Allocate a new hashtable.
   8.158 + * If the number of buckets is not positive the default is used.
   8.159 + * The number of buckets should usually be prime.
   8.160 + *
   8.161 + * @param buckets_n number of buckets
   8.162 + * @return new hashtable or null
   8.163 + */
   8.164 +HashTable *HashTable_new(int buckets_n){
   8.165 +    HashTable *z = ALLOCATE(HashTable);
   8.166 +    if(!z) goto exit;
   8.167 +    if(buckets_n <= 0){
   8.168 +        buckets_n = HT_BUCKETS_N;
   8.169 +    }
   8.170 +    z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
   8.171 +    if(!z->buckets){
   8.172 +        deallocate(z);
   8.173 +        z = 0;
   8.174 +        goto exit;
   8.175 +    }
   8.176 +    z->buckets_n = buckets_n;
   8.177 +    HashTable_init(z);
   8.178 +  exit:
   8.179 +    return z;
   8.180 +}
   8.181 +
   8.182 +/** Free a hashtable.
   8.183 + * Any entries are removed and freed.
   8.184 + *
   8.185 + * @param h hashtable (ignored if null)
   8.186 + */
   8.187 +void HashTable_free(HashTable *h){
   8.188 +    if(h){
   8.189 +        HashTable_clear(h);
   8.190 +        deallocate(h->buckets);
   8.191 +        deallocate(h);
   8.192 +    }
   8.193 +}
   8.194 +
   8.195 +/** Push an entry on the list in the bucket for a given hashcode.
   8.196 + *
   8.197 + * @param table to add entry to
   8.198 + * @param hashcode for the entry
   8.199 + * @param entry to add
   8.200 + */
   8.201 +static inline void push_on_bucket(HashTable *table, Hashcode hashcode,
   8.202 +				  HTEntry *entry){
   8.203 +    HTBucket *bucket;
   8.204 +    HTEntry *old_head;
   8.205 +
   8.206 +    bucket = get_bucket(table, hashcode);
   8.207 +    old_head = bucket->head;
   8.208 +    bucket->count++;
   8.209 +    bucket->head = entry;
   8.210 +    entry->next = old_head;
   8.211 +}
   8.212 +
   8.213 +/** Change the number of buckets in a hashtable.
   8.214 + * No-op if the number of buckets is not positive.
   8.215 + * Existing entries are reallocated to buckets based on their hashcodes.
   8.216 + * The table is unmodified if the number of buckets cannot be changed.
   8.217 + *
   8.218 + * @param table hashtable
   8.219 + * @param buckets_n new number of buckets
   8.220 + * @return 0 on success, error code otherwise
   8.221 + */
   8.222 +int HashTable_set_buckets_n(HashTable *table, int buckets_n){
   8.223 +    int err = 0;
   8.224 +    HTBucket *old_buckets = table->buckets;
   8.225 +    int old_buckets_n = table->buckets_n;
   8.226 +    int i;
   8.227 +
   8.228 +    if(buckets_n <= 0){
   8.229 +        err = -EINVAL;
   8.230 +        goto exit;
   8.231 +    }
   8.232 +    table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
   8.233 +    if(!table->buckets){
   8.234 +        err = -ENOMEM;
   8.235 +        table->buckets = old_buckets;
   8.236 +        goto exit;
   8.237 +    }
   8.238 +    table->buckets_n = buckets_n;
   8.239 +    for(i=0; i<old_buckets_n; i++){
   8.240 +        HTBucket *bucket = old_buckets + i;
   8.241 +        HTEntry *entry, *next;
   8.242 +        for(entry = bucket->head; entry; entry = next){
   8.243 +            next = entry->next;
   8.244 +            push_on_bucket(table, entry->hashcode, entry);
   8.245 +        }
   8.246 +    }
   8.247 +    deallocate(old_buckets);
   8.248 +  exit:
   8.249 +    return err;
   8.250 +}
   8.251 +
   8.252 +/** Adjust the number of buckets so the table is neither too full nor too empty.
   8.253 + * The table is unmodified if adjusting fails.
   8.254 + *
   8.255 + * @param table hash table
   8.256 + * @param buckets_min minimum number of buckets (use default if 0 or negative)
   8.257 + * @return 0 on success, error code otherwise
   8.258 + */
   8.259 +int HashTable_adjust(HashTable *table, int buckets_min){
   8.260 +    int buckets_n = 0;
   8.261 +    int err = 0;
   8.262 +    if(buckets_min <= 0) buckets_min = HT_BUCKETS_N;
   8.263 +    if(table->entry_count >= table->buckets_n){
   8.264 +        // The table is dense - expand it.
   8.265 +        buckets_n = 2 * table->buckets_n;
   8.266 +    } else if((table->buckets_n > buckets_min) &&
   8.267 +              (4 * table->entry_count < table->buckets_n)){
   8.268 +        // The table is more than minimum size and sparse - shrink it.
   8.269 +        buckets_n = 2 * table->entry_count;
   8.270 +        if(buckets_n < buckets_min) buckets_n = buckets_min;
   8.271 +    }
   8.272 +    if(buckets_n){
   8.273 +        err = HashTable_set_buckets_n(table, buckets_n);
   8.274 +    }
   8.275 +    return err;
   8.276 +}
   8.277 +
   8.278 +/** Allocate a new entry for a given value.
   8.279 + *
   8.280 + * @param value to put in the entry
   8.281 + * @return entry, or 0 on failure
   8.282 + */
   8.283 +HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){
   8.284 +    HTEntry *z = ALLOCATE(HTEntry);
   8.285 +    if(z){
   8.286 +        z->hashcode = hashcode;
   8.287 +        z->key = key;
   8.288 +        z->value = value;
   8.289 +    }
   8.290 +    return z;
   8.291 +}
   8.292 +
   8.293 +/** Free an entry.
   8.294 + *
   8.295 + * @param z entry to free
   8.296 + */
   8.297 +inline void HTEntry_free(HTEntry *z){
   8.298 +    if(z){
   8.299 +        deallocate(z);
   8.300 +    }
   8.301 +}
   8.302 +
   8.303 +/** Free an entry in a hashtable.
   8.304 + * The table's entry_free_fn is used is defined, otherwise 
   8.305 + * the HTEntry itself is freed.
   8.306 + *
   8.307 + * @param table hashtable
   8.308 + * @param entry to free
   8.309 + */
   8.310 +inline void HashTable_free_entry(HashTable *table, HTEntry *entry){
   8.311 +    if(!entry)return;
   8.312 +    if(table && table->entry_free_fn){
   8.313 +        table->entry_free_fn(table, entry);
   8.314 +    } else {
   8.315 +        HTEntry_free(entry);
   8.316 +    }
   8.317 +}
   8.318 +
   8.319 +/** Get the first entry satisfying a test from the bucket for the
   8.320 + * given hashcode.
   8.321 + *
   8.322 + * @param table to look in
   8.323 + * @param hashcode indicates the bucket
   8.324 + * @param test_fn test to apply to elements
   8.325 + * @param arg first argument to calls to test_fn
   8.326 + * @return entry found, or 0
   8.327 + */
   8.328 +inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
   8.329 +				      TableTestFn *test_fn, TableArg arg){
   8.330 +    HTBucket *bucket;
   8.331 +    HTEntry *entry = 0;
   8.332 +    HTEntry *next;
   8.333 +
   8.334 +    bucket = get_bucket(table, hashcode);
   8.335 +    for(entry = bucket->head; entry; entry = next){
   8.336 +        next = entry->next;
   8.337 +        if(test_fn(arg, table, entry)){
   8.338 +            break;
   8.339 +        }
   8.340 +    }
   8.341 +    return entry;
   8.342 +}
   8.343 +
   8.344 +/** Test hashtable keys for equality.
   8.345 + * Uses the table's key_equal_fn if defined, otherwise pointer equality.
   8.346 + *
   8.347 + * @param key1 key to compare
   8.348 + * @param key2 key to compare
   8.349 + * @return 1 if equal, 0 otherwise
   8.350 + */
   8.351 +inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){
   8.352 +    return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2);
   8.353 +}
   8.354 +
   8.355 +/** Compute the hashcode of a hashtable key.
   8.356 + * The table's key_hash_fn is used if defined, otherwise the address of
   8.357 + * the key is hashed.
   8.358 + *
   8.359 + * @param table hashtable
   8.360 + * @param key to hash
   8.361 + * @return hashcode
   8.362 + */
   8.363 +inline Hashcode HashTable_key_hash(HashTable *table, void *key){
   8.364 +    return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key));
   8.365 +}
   8.366 +
   8.367 +/** Test if an entry has a given key.
   8.368 + *
   8.369 + * @param arg containing key to test for
   8.370 + * @param table the entry is in
   8.371 + * @param entry to test
   8.372 + * @return 1 if the entry has the key, 0 otherwise
   8.373 + */
   8.374 +static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){
   8.375 +    return HashTable_key_equal(table, arg.ptr, entry->key);
   8.376 +}
   8.377 +
   8.378 +/** Get an entry with a given key.
   8.379 + *
   8.380 + * @param table to search
   8.381 + * @param key to look for
   8.382 + * @return entry if found, null otherwise
   8.383 + */
   8.384 +#if 0
   8.385 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
   8.386 +    TableArg arg = { ptr: key };
   8.387 +    return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg);
   8.388 +}
   8.389 +#else
   8.390 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
   8.391 +    Hashcode hashcode;
   8.392 +    HTBucket *bucket;
   8.393 +    HTEntry *entry = 0;
   8.394 +    HTEntry *next;
   8.395 +
   8.396 +    hashcode = HashTable_key_hash(table, key);
   8.397 +    bucket = get_bucket(table, hashcode);
   8.398 +    for(entry = bucket->head; entry; entry = next){
   8.399 +        next = entry->next;
   8.400 +        if(HashTable_key_equal(table, key, entry->key)){
   8.401 +            break;
   8.402 +        }
   8.403 +    }
   8.404 +    return entry;
   8.405 +}
   8.406 +#endif
   8.407 +
   8.408 +/** Get the value of an entry with a given key.
   8.409 + *
   8.410 + * @param table to search
   8.411 + * @param key to look for
   8.412 + * @return value if an entry was found, null otherwise
   8.413 + */
   8.414 +inline void * HashTable_get(HashTable *table, void *key){
   8.415 +    HTEntry *entry = HashTable_get_entry(table, key);
   8.416 +    return (entry ? entry->value : 0);
   8.417 +}
   8.418 +
   8.419 +/** Print the buckets in a table.
   8.420 + *
   8.421 + * @param table to print
   8.422 + */
   8.423 +void show_buckets(HashTable *table, IOStream *io){
   8.424 +    int i,j ;
   8.425 +    IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n);
   8.426 +    for(i=0; i<table->buckets_n; i++){
   8.427 +        if(0 || table->buckets[i].count>0){
   8.428 +            IOStream_print(io, "bucket %3d %3d %10p ", i,
   8.429 +                        table->buckets[i].count,
   8.430 +                        table->buckets[i].head);
   8.431 +            for(j = table->buckets[i].count; j>0; j--){
   8.432 +                IOStream_print(io, "+");
   8.433 +            }
   8.434 +            IOStream_print(io, "\n");
   8.435 +        }
   8.436 +    }
   8.437 +    HashTable_print(table, io); 
   8.438 +}
   8.439 +    
   8.440 +/** Print an entry in a table.
   8.441 + *
   8.442 + * @param entry to print
   8.443 + * @param arg a pointer to an IOStream to print to
   8.444 + * @return 0
   8.445 + */
   8.446 +static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){
   8.447 +    IOStream *io = (IOStream*)arg.ptr;
   8.448 +    IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n",
   8.449 +                entry->hashcode % table->buckets_n,
   8.450 +                entry->hashcode,
   8.451 +                entry->index,
   8.452 +                entry, entry->key, entry->value);
   8.453 +    return 0;
   8.454 +}
   8.455 +
   8.456 +/** Print a hash table.
   8.457 + *
   8.458 + * @param table to print
   8.459 + */
   8.460 +void HashTable_print(HashTable *table, IOStream *io){
   8.461 +    IOStream_print(io, "{\n");
   8.462 +    HashTable_map(table, print_entry, (TableArg){ ptr: io });
   8.463 +    IOStream_print(io, "}\n");
   8.464 +}
   8.465 +/*==========================================================================*/
   8.466 +
   8.467 +/** Get the next entry id to use for a table.
   8.468 + *
   8.469 + * @param table hash table
   8.470 + * @return non-zero entry id
   8.471 + */
   8.472 +static inline unsigned long get_next_id(HashTable *table){
   8.473 +    unsigned long id;
   8.474 +
   8.475 +    if(table->next_id == 0){
   8.476 +        table->next_id = 1;
   8.477 +    }
   8.478 +    id = table->next_id++;
   8.479 +    return id;
   8.480 +}
   8.481 +
   8.482 +/** Add an entry to the bucket for the
   8.483 + * given hashcode.
   8.484 + *
   8.485 + * @param table to insert in
   8.486 + * @param hashcode indicates the bucket
   8.487 + * @param key to add an entry for
   8.488 + * @param value to add an entry for
   8.489 + * @return entry on success, 0 on failure
   8.490 + */
   8.491 +inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){
   8.492 +    HTEntry *entry = HTEntry_new(hashcode, key, value);
   8.493 +    if(entry){
   8.494 +        entry->index = get_next_id(table);
   8.495 +        push_on_bucket(table, hashcode, entry);
   8.496 +        table->entry_count++;
   8.497 +    }
   8.498 +    return entry;
   8.499 +}
   8.500 +
   8.501 +/** Move the front entry for a bucket to the correct point in the bucket order as
   8.502 + * defined by the order function. If this is called every time a new entry is added
   8.503 + * the bucket will be maintained in sorted order.
   8.504 + *
   8.505 + * @param table to modify
   8.506 + * @param hashcode indicates the bucket
   8.507 + * @param order entry comparison function
   8.508 + * @return 0 if an entry was moved, 1 if not
   8.509 + */
   8.510 +int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){
   8.511 +    HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL;
   8.512 +    HTBucket *bucket;
   8.513 +    int err = 1;
   8.514 +
   8.515 +    bucket = get_bucket(table, hashcode);
   8.516 +    new_entry = bucket->head;
   8.517 +    if(!new_entry || !new_entry->next) goto exit;
   8.518 +    for(entry = new_entry->next; entry; prev = entry, entry = entry->next){
   8.519 +        if(order(new_entry, entry) <= 0) break;
   8.520 +    }
   8.521 +    if(prev){
   8.522 +        err = 0;
   8.523 +        bucket->head = new_entry->next; 
   8.524 +        new_entry->next = entry;
   8.525 +        prev->next = new_entry;
   8.526 +    }
   8.527 +  exit:
   8.528 +    return err;
   8.529 +}
   8.530 +
   8.531 +/** Add an entry to a hashtable.
   8.532 + * The entry is added to the bucket for its key's hashcode.
   8.533 + *
   8.534 + * @param table to insert in
   8.535 + * @param key to add an entry for
   8.536 + * @param value to add an entry for
   8.537 + * @return entry on success, 0 on failure
   8.538 + */
   8.539 +inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){
   8.540 +    return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value);
   8.541 +}
   8.542 +
   8.543 +
   8.544 +/** Remove entries satisfying a test from the bucket for the
   8.545 + * given hashcode. 
   8.546 + *
   8.547 + * @param table to remove from
   8.548 + * @param hashcode indicates the bucket
   8.549 + * @param test_fn test to apply to elements
   8.550 + * @param arg first argument to calls to test_fn
   8.551 + * @return number of entries removed
   8.552 + */
   8.553 +inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
   8.554 +				  TableTestFn *test_fn, TableArg arg){
   8.555 +    HTBucket *bucket;
   8.556 +    HTEntry *entry, *prev = 0, *next;
   8.557 +    int removed_count = 0;
   8.558 +
   8.559 +    bucket = get_bucket(table, hashcode);
   8.560 +    for(entry = bucket->head; entry; entry = next){
   8.561 +        next = entry->next;
   8.562 +        if(test_fn(arg, table, entry)){
   8.563 +            if(prev){
   8.564 +                prev->next = next;
   8.565 +            } else {
   8.566 +                bucket->head = next;
   8.567 +            }
   8.568 +            bucket->count--;
   8.569 +            table->entry_count--;
   8.570 +            removed_count++;
   8.571 +            HashTable_free_entry(table, entry);
   8.572 +            entry = 0;
   8.573 +        }
   8.574 +        prev = entry;
   8.575 +    }
   8.576 +    return removed_count;
   8.577 +}
   8.578 +
   8.579 +/** Remove entries with a given key. 
   8.580 + *
   8.581 + * @param table to remove from
   8.582 + * @param key of entries to remove
   8.583 + * @return number of entries removed
   8.584 + */
   8.585 +inline int HashTable_remove(HashTable *table, void *key){
   8.586 +#if 1
   8.587 +    Hashcode hashcode;
   8.588 +    HTBucket *bucket;
   8.589 +    HTEntry *entry, *prev = 0, *next;
   8.590 +    int removed_count = 0;
   8.591 +
   8.592 +    hashcode = HashTable_key_hash(table, key);
   8.593 +    bucket = get_bucket(table, hashcode);
   8.594 +    for(entry = bucket->head; entry; entry = next){
   8.595 +        next = entry->next;
   8.596 +        if(HashTable_key_equal(table, key, entry->key)){
   8.597 +            if(prev){
   8.598 +                prev->next = next;
   8.599 +            } else {
   8.600 +                bucket->head = next;
   8.601 +            }
   8.602 +            bucket->count--;
   8.603 +            table->entry_count--;
   8.604 +            removed_count++;
   8.605 +            HashTable_free_entry(table, entry);
   8.606 +            entry = 0;
   8.607 +        }
   8.608 +        prev = entry;
   8.609 +    }
   8.610 +    return removed_count;
   8.611 +#else
   8.612 +    return HashTable_remove_entry(table, HashTable_key_hash(table, key),
   8.613 +				  has_key, (TableArg){ ptr: key});
   8.614 +#endif
   8.615 +}
   8.616 +
   8.617 +/** Remove (and free) all the entries in a bucket.
   8.618 + *
   8.619 + * @param bucket to clear
   8.620 + */
   8.621 +static inline void bucket_clear(HashTable *table, HTBucket *bucket){
   8.622 +    HTEntry *entry, *next;
   8.623 +
   8.624 +    for(entry = bucket->head; entry; entry = next){
   8.625 +        next = entry->next;
   8.626 +        HashTable_free_entry(table, entry);
   8.627 +    }
   8.628 +    bucket->head = 0;
   8.629 +    table->entry_count -= bucket->count;
   8.630 +    bucket->count = 0;
   8.631 +}
   8.632 +
   8.633 +/** Remove (and free) all the entries in a table.
   8.634 + *
   8.635 + * @param table to clear
   8.636 + */
   8.637 +void HashTable_clear(HashTable *table){
   8.638 +    int i, n = table->buckets_n;
   8.639 +
   8.640 +    for(i=0; i<n; i++){
   8.641 +        bucket_clear(table, table->buckets + i);
   8.642 +    }
   8.643 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/libxutil/hash_table.h	Wed Nov 24 18:22:43 2004 +0000
     9.3 @@ -0,0 +1,294 @@
     9.4 +/*
     9.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
     9.6 + *
     9.7 + * This library is free software; you can redistribute it and/or modify
     9.8 + * it under the terms of the GNU Lesser General Public License as published by
     9.9 + * the Free Software Foundation; either version 2.1 of the License, or
    9.10 + * (at your option) any later version.
    9.11 + *
    9.12 + * This library is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 + * GNU Lesser General Public License for more details.
    9.16 + *
    9.17 + * You should have received a copy of the GNU Lesser General Public License
    9.18 + * along with this library; if not, write to the Free Software
    9.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.20 + */
    9.21 +
    9.22 +#ifndef _XUTIL_HASH_TABLE_H_
    9.23 +#define _XUTIL_HASH_TABLE_H_
    9.24 +
    9.25 +#include "iostream.h"
    9.26 +
    9.27 +typedef unsigned long Hashcode;
    9.28 +
    9.29 +/** Type used to pass parameters to table functions. */
    9.30 +typedef union TableArg {
    9.31 +    unsigned long ul;
    9.32 +    void *ptr;
    9.33 +} TableArg;
    9.34 +
    9.35 +/** An entry in a bucket list. */
    9.36 +typedef struct HTEntry {
    9.37 +    /** Hashcode of the entry's key. */
    9.38 +    Hashcode hashcode;
    9.39 +    /** Identifier for this entry in the table. */
    9.40 +    int index;
    9.41 +    /** The key for this entry. */
    9.42 +    void *key;
    9.43 +    /** The value in this entry. */
    9.44 +    void *value;
    9.45 +    /** The next entry in the list. */
    9.46 +    struct HTEntry *next;
    9.47 +} HTEntry;
    9.48 +
    9.49 +/** A bucket in a rule table. */
    9.50 +typedef struct HTBucket {
    9.51 +    /** Number of entries in the bucket. */
    9.52 +    int count;
    9.53 +    /** First entry in the bucket (may be null). */
    9.54 +    HTEntry *head;
    9.55 +} HTBucket;
    9.56 +
    9.57 +/** Default number of buckets in a hash table.
    9.58 + * You want enough buckets so the lists in the buckets will typically be short.
    9.59 + * It's a good idea if this is prime, since that will help to spread hashcodes
    9.60 + * around the table.
    9.61 + */
    9.62 +//#define HT_BUCKETS_N 1
    9.63 +//#define HT_BUCKETS_N 3
    9.64 +//#define HT_BUCKETS_N 7
    9.65 +//#define HT_BUCKETS_N 17
    9.66 +//#define HT_BUCKETS_N 97
    9.67 +//#define HT_BUCKETS_N 211
    9.68 +//#define HT_BUCKETS_N 401
    9.69 +#define HT_BUCKETS_N 1021
    9.70 +
    9.71 +typedef struct HashTable HashTable;
    9.72 +
    9.73 +/** Type for a function used to select table entries. */
    9.74 +typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry);
    9.75 +
    9.76 +/** Type for a function to map over table entries. */
    9.77 +typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry);
    9.78 +
    9.79 +/** Type for a function to free table entries. */
    9.80 +typedef void TableFreeFn(HashTable *table, HTEntry *entry);
    9.81 +
    9.82 +/** Type for a function to hash table keys. */
    9.83 +typedef Hashcode TableHashFn(void *key);
    9.84 +
    9.85 +/** Type for a function to test table keys for equality. */
    9.86 +typedef int TableEqualFn(void *key1, void *key2);
    9.87 +
    9.88 +/** Type for a function to order table entries. */
    9.89 +typedef int TableOrderFn(HTEntry *e1, HTEntry *e2);
    9.90 +
    9.91 +/** General hash table.
    9.92 + * A hash table with a list in each bucket.
    9.93 + * Functions can be supplied for freeing entries, hashing keys, and comparing keys.
    9.94 + * These all default to 0, when default behaviour treating keys as integers is used.
    9.95 + */
    9.96 +struct HashTable {
    9.97 +    /** Flag indicating whether the table has been initialised. */
    9.98 +    int init_done;
    9.99 +    /** Next value for the id field in inserted rules. */
   9.100 +    unsigned long next_id;
   9.101 +    /** Number of buckets in the bucket array. */
   9.102 +    int buckets_n;
   9.103 +    /** Array of buckets, each with its own list. */
   9.104 +    HTBucket *buckets;
   9.105 +    /** Number of entries in the table. */
   9.106 +    int entry_count;
   9.107 +    /** Function to free keys and values in entries. */
   9.108 +    TableFreeFn *entry_free_fn;
   9.109 +    /** Function to hash keys. */
   9.110 +    TableHashFn *key_hash_fn;
   9.111 +    /** Function to compare keys for equality. */
   9.112 +    TableEqualFn *key_equal_fn;
   9.113 +    /** Place for the user of the table to hang extra data. */
   9.114 +    void *user_data;
   9.115 +};
   9.116 +
   9.117 +extern HashTable *HashTable_new(int bucket_n);
   9.118 +extern void HashTable_free(HashTable *table);
   9.119 +extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value);
   9.120 +extern void HTEntry_free(HTEntry *entry);
   9.121 +extern int HashTable_set_bucket_n(HashTable *table, int bucket_n);
   9.122 +extern void HashTable_clear(HashTable *table);
   9.123 +extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value);
   9.124 +extern HTEntry * HashTable_get_entry(HashTable *table, void *key);
   9.125 +extern HTEntry * HashTable_add(HashTable *table, void *key, void *value);
   9.126 +extern void * HashTable_get(HashTable *table, void *key);
   9.127 +extern int HashTable_remove(HashTable *table, void *key);
   9.128 +extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
   9.129 +                                      TableTestFn *test_fn, TableArg arg);
   9.130 +extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
   9.131 +                                   TableTestFn *test_fn, TableArg arg);
   9.132 +//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg);
   9.133 +extern void HashTable_print(HashTable *table, IOStream *out);
   9.134 +extern int HashTable_set_buckets_n(HashTable *table, int buckets_n);
   9.135 +extern int HashTable_adjust(HashTable *table, int buckets_min);
   9.136 +extern void pseudo_des(unsigned long *pleft, unsigned long *pright);
   9.137 +extern Hashcode hash_string(char *s);
   9.138 +
   9.139 +extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order);
   9.140 +
   9.141 +/** Control whether to use hashing based on DES or simple
   9.142 + * hashing. DES hashing is `more random' but much more expensive.
   9.143 + */
   9.144 +#define HASH_PSEUDO_DES 0
   9.145 +
   9.146 +/** Hash a long using a quick and dirty linear congruential random number generator.
   9.147 + *  See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator".
   9.148 + *
   9.149 + * @param a value to hash
   9.150 + * @return hashed input
   9.151 + */
   9.152 +static inline unsigned long lcrng_hash(unsigned long a){
   9.153 +    return (1664525L * a + 1013904223L);
   9.154 +}
   9.155 +
   9.156 +/** Hash an unsigned long.
   9.157 + *
   9.158 + * @param a input to hash
   9.159 + * @return hashcode
   9.160 + */
   9.161 +static inline Hashcode hash_ul(unsigned long a){
   9.162 +#if HASH_PSEUDO_DES
   9.163 +    unsigned long left = a;
   9.164 +    unsigned long right = 0L;
   9.165 +    pseudo_des(&left, &right);
   9.166 +    return right;
   9.167 +#else
   9.168 +    a = lcrng_hash(a);
   9.169 +    a = lcrng_hash(a);
   9.170 +    return a;
   9.171 +#endif
   9.172 +}
   9.173 +
   9.174 +/** Hash two unsigned longs together.
   9.175 + *
   9.176 + * @param a input to hash
   9.177 + * @param b input to hash
   9.178 + * @return hashcode
   9.179 + */
   9.180 +static inline Hashcode hash_2ul(unsigned long a, unsigned long b){
   9.181 +#if HASH_PSEUDO_DES
   9.182 +    unsigned long left = a;
   9.183 +    unsigned long right = b;
   9.184 +    pseudo_des(&left, &right);
   9.185 +    return right;
   9.186 +#else
   9.187 +    a = lcrng_hash(a);
   9.188 +    a ^= b;
   9.189 +    a = lcrng_hash(a);
   9.190 +    return a;
   9.191 +#endif
   9.192 +}
   9.193 +
   9.194 +/** Hash a hashcode and an unsigned long together.
   9.195 + *
   9.196 + * @param a input hashcode
   9.197 + * @param b input to hash
   9.198 + * @return hashcode
   9.199 + */
   9.200 +static inline Hashcode hash_hul(Hashcode a, unsigned long b){
   9.201 +#if HASH_PSEUDO_DES
   9.202 +    unsigned long left = a;
   9.203 +    unsigned long right = b;
   9.204 +    pseudo_des(&left, &right);
   9.205 +    return right;
   9.206 +#else
   9.207 +    a ^= b;
   9.208 +    a = lcrng_hash(a);
   9.209 +    return a;
   9.210 +#endif
   9.211 +}
   9.212 +
   9.213 +/** Macro to declare variables for HashTable_for_each() to use.
   9.214 + *
   9.215 + * @param entry variable that is set to entries in the table
   9.216 + */
   9.217 +#define HashTable_for_decl(entry) \
   9.218 +  HashTable *_var_table; \
   9.219 +  HTBucket *_var_bucket; \
   9.220 +  HTBucket *_var_end; \
   9.221 +  HTEntry *_var_next; \
   9.222 +  HTEntry *entry
   9.223 +
   9.224 +/** Macro to iterate over the entries in a hashtable.
   9.225 + * Must be in a scope where HashTable_for_decl() has been used to declare
   9.226 + * variables for it to use.
   9.227 + * The variable 'entry' is iterated over entries in the table.
   9.228 + * The code produced is syntactically a loop, so it must be followed by
   9.229 + * a loop body, typically some statements in braces:
   9.230 + * HashTable_for_each(entry, table){ ...loop body... }
   9.231 + *
   9.232 + * HashTable_for_each() and HashTable_for_decl() cannot be used for nested
   9.233 + * loops as variables will clash.
   9.234 + *
   9.235 + * @note The simplest way to code a direct loop over the entries in a hashtable
   9.236 + * is to use a loop over the buckets, with a nested loop over the entries
   9.237 + * in a bucket. Using this approach in a macro means the macro contains
   9.238 + * an opening brace, and calls to it must be followed by 2 braces!
   9.239 + * To avoid this the code has been restructured so that it is a for loop.
   9.240 + * So that statements could be used in the test expression of the for loop,
   9.241 + * we have used the gcc statement expression extension ({ ... }).
   9.242 + *
   9.243 + * @param entry variable to iterate over the entries
   9.244 + * @param table to iterate over (non-null)
   9.245 + */
   9.246 +#define HashTable_for_each(entry, table) \
   9.247 +  _var_table = table; \
   9.248 +  _var_bucket = _var_table->buckets; \
   9.249 +  _var_end = _var_bucket + _var_table->buckets_n; \
   9.250 +  for(entry=0, _var_next=0; \
   9.251 +      ({ if(_var_next){ \
   9.252 +             entry = _var_next; \
   9.253 +             _var_next = entry->next; \
   9.254 +          } else { \
   9.255 +             while(_var_bucket < _var_end){ \
   9.256 +                 entry = _var_bucket->head; \
   9.257 +                 _var_bucket++; \
   9.258 +                 if(entry){ \
   9.259 +                      _var_next = entry->next; \
   9.260 +                      break; \
   9.261 +                 } \
   9.262 +             } \
   9.263 +          }; \
   9.264 +         entry; }); \
   9.265 +      entry = _var_next )
   9.266 +
   9.267 +/** Map a function over the entries in a table.
   9.268 + * Mapping stops when the function returns a non-zero value.
   9.269 + * Uses the gcc statement expression extension ({ ... }).
   9.270 + *
   9.271 + * @param table to map over
   9.272 + * @param fn function to apply to entries
   9.273 + * @param arg first argument to call the function with
   9.274 + * @return 0 if fn always returned 0, first non-zero value otherwise
   9.275 + */
   9.276 +#define HashTable_map(table, fn, arg) \
   9.277 +  ({ HashTable_for_decl(_var_entry); \
   9.278 +    TableArg _var_arg = arg; \
   9.279 +    int _var_value = 0; \
   9.280 +    HashTable_for_each(_var_entry, table){ \
   9.281 +        if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \
   9.282 +    } \
   9.283 +    _var_value; })
   9.284 +
   9.285 +/** Cast x to the type for a key or value in a hash table.
   9.286 + * This avoids compiler warnings when using short integers
   9.287 + * as keys or values (especially on 64-bit platforms).
   9.288 + */
   9.289 +#define HKEY(x) ((void*)(unsigned long)(x))
   9.290 +
   9.291 +/** Cast x from the type for a key or value in a hash table.
   9.292 + * to an unsigned long. This avoids compiler warnings when using
   9.293 + * short integers as keys or values (especially on 64-bit platforms).
   9.294 + */
   9.295 +#define HVAL(x) ((unsigned long)(x))
   9.296 +
   9.297 +#endif /* !_XUTIL_HASH_TABLE_H_ */
    10.1 --- a/tools/libxutil/iostream.c	Wed Nov 24 11:51:49 2004 +0000
    10.2 +++ b/tools/libxutil/iostream.c	Wed Nov 24 18:22:43 2004 +0000
    10.3 @@ -1,3 +1,21 @@
    10.4 +/*
    10.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    10.6 + *
    10.7 + * This library is free software; you can redistribute it and/or modify
    10.8 + * it under the terms of the GNU Lesser General Public License as published by
    10.9 + * the Free Software Foundation; either version 2.1 of the License, or
   10.10 + * (at your option) any later version.
   10.11 + *
   10.12 + * This library is distributed in the hope that it will be useful,
   10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.15 + * GNU Lesser General Public License for more details.
   10.16 + *
   10.17 + * You should have received a copy of the GNU Lesser General Public License
   10.18 + * along with this library; if not, write to the Free Software
   10.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   10.20 + */
   10.21 +
   10.22  #include "iostream.h"
   10.23  #include "sys_string.h"
   10.24  
    11.1 --- a/tools/libxutil/iostream.h	Wed Nov 24 11:51:49 2004 +0000
    11.2 +++ b/tools/libxutil/iostream.h	Wed Nov 24 18:22:43 2004 +0000
    11.3 @@ -1,14 +1,34 @@
    11.4 -#ifndef _XC_LINUX_SAVE_H_
    11.5 -#define _XC_LINUX_SAVE_H_
    11.6 +/*
    11.7 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    11.8 + *
    11.9 + * This library is free software; you can redistribute it and/or modify
   11.10 + * it under the terms of the GNU Lesser General Public License as published by
   11.11 + * the Free Software Foundation; either version 2.1 of the License, or
   11.12 + * (at your option) any later version.
   11.13 + *
   11.14 + * This library is distributed in the hope that it will be useful,
   11.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.17 + * GNU Lesser General Public License for more details.
   11.18 + *
   11.19 + * You should have received a copy of the GNU Lesser General Public License
   11.20 + * along with this library; if not, write to the Free Software
   11.21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   11.22 + */
   11.23 +
   11.24 +#ifndef _XUTIL_IOSTREAM_H_
   11.25 +#define _XUTIL_IOSTREAM_H_
   11.26  
   11.27  #include <stdarg.h>
   11.28 -#include <stdint.h>
   11.29 -#include <stddef.h>
   11.30  
   11.31  #ifdef __KERNEL__
   11.32 +#include <linux/config.h>
   11.33 +#include <linux/types.h>
   11.34  #include <linux/errno.h>
   11.35  #else
   11.36  #include <errno.h>
   11.37 +#include <stdint.h>
   11.38 +#include <stddef.h>
   11.39  #endif
   11.40  
   11.41  #include "allocate.h"
   11.42 @@ -240,4 +260,4 @@ static inline int IOStream_get_written(I
   11.43  }
   11.44  
   11.45  
   11.46 -#endif /* ! _XC_LINUX_SAVE_H_ */
   11.47 +#endif /* ! _XUTIL_IOSTREAM_H_ */
    12.1 --- a/tools/libxutil/kernel_stream.c	Wed Nov 24 11:51:49 2004 +0000
    12.2 +++ b/tools/libxutil/kernel_stream.c	Wed Nov 24 18:22:43 2004 +0000
    12.3 @@ -50,7 +50,7 @@ typedef struct KernelData {
    12.4      char buf[BUF_N];
    12.5  } KernelData;
    12.6  
    12.7 -static int kernel_write(IOStream *s, const char *msg, int n);
    12.8 +static int kernel_write(IOStream *s, const void *msg, size_t n);
    12.9  static void kernel_free(IOStream *s);
   12.10  static void kernel_stream_lock(IOStream *s);
   12.11  static void kernel_stream_unlock(IOStream *s);
   12.12 @@ -145,13 +145,13 @@ void kernel_stream_unlock(IOStream *s){
   12.13   * @param args print arguments
   12.14   * @return result of the print
   12.15   */
   12.16 -static int kernel_write(IOStream *stream, const char *buf, int n){
   12.17 +static int kernel_write(IOStream *stream, const void *buf, size_t n){
   12.18    KernelData *kdata = get_kernel_data(stream);
   12.19    int k;
   12.20    k = kdata->buf_n - 1;
   12.21    if(n < k) k = n;
   12.22    memcpy(kdata->buf, buf, k);
   12.23 -  kdata->buf[k] = '\0'
   12.24 +  kdata->buf[k] = '\0';
   12.25    printk(kdata->buf);
   12.26    return k;
   12.27  }
   12.28 @@ -167,7 +167,7 @@ static void kernel_free(IOStream *io){
   12.29    KernelData *kdata;
   12.30    if(io == &iokernel) return;
   12.31    kdata = get_kernel_data(io);
   12.32 -  zero(kdata, sizeof(*kdata));
   12.33 +  memset(kdata, 0, sizeof(*kdata));
   12.34    deallocate(kdata);
   12.35  }
   12.36  #endif /* __KERNEL__ */
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/libxutil/lexis.c	Wed Nov 24 18:22:43 2004 +0000
    13.3 @@ -0,0 +1,94 @@
    13.4 +/*
    13.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    13.6 + *
    13.7 + * This library is free software; you can redistribute it and/or modify
    13.8 + * it under the terms of the GNU Lesser General Public License as
    13.9 + * published by the Free Software Foundation; either version 2.1 of the
   13.10 + * License, or  (at your option) any later version. This library is 
   13.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   13.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   13.14 + * See the GNU Lesser General Public License for more details.
   13.15 + *
   13.16 + * You should have received a copy of the GNU Lesser General Public License
   13.17 + * along with this library; if not, write to the Free Software Foundation,
   13.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   13.19 + */
   13.20 +
   13.21 +/** @file
   13.22 + * Lexical analysis.
   13.23 + */
   13.24 +
   13.25 +#include "sys_string.h"
   13.26 +#include "lexis.h"
   13.27 +#include <errno.h>
   13.28 +
   13.29 +/** Check if a value lies in a (closed) range.
   13.30 + *
   13.31 + * @param x value to test
   13.32 + * @param lo low end of the range
   13.33 + * @param hi high end of the range
   13.34 + * @return 1 if x is in the interval [lo, hi], 0 otherwise
   13.35 + */
   13.36 +inline static int in_range(int x, int lo, int hi){
   13.37 +    return (lo <= x) && (x <= hi);
   13.38 +}
   13.39 +
   13.40 +/** Determine if a string is an (unsigned) decimal number.
   13.41 + * 
   13.42 + * @param s pointer to characters to test
   13.43 + * @param n length of string
   13.44 + * @return 1 if s is a decimal number, 0 otherwise.
   13.45 + */
   13.46 +int is_decimal_number(const char *s, int n){
   13.47 +    int i;
   13.48 +    if(n <= 0)return 0;
   13.49 +    for(i = 0; i < n; i++){
   13.50 +        if(!in_decimal_digit_class(s[i])) return 0;
   13.51 +    }
   13.52 +    return 1;
   13.53 +}
   13.54 +
   13.55 +/** Determine if a string is a hex number.
   13.56 + * Hex numbers are 0, or start with 0x or 0X followed
   13.57 + * by a non-zero number of hex digits (0-9,a-f,A-F).
   13.58 + * 
   13.59 + * @param s pointer to characters to test
   13.60 + * @param n length of string
   13.61 + * @return 1 if s is a hex number, 0 otherwise.
   13.62 + */
   13.63 +int is_hex_number(const char *s, int n){
   13.64 +    int i;
   13.65 +    if(n <= 0) return 0;
   13.66 +    if(n == 1){
   13.67 +        return s[0]=='0';
   13.68 +    }
   13.69 +    if(n <= 3) return 0;
   13.70 +    if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0;
   13.71 +    for(i = 2; i < n; i++){
   13.72 +        if(!in_hex_digit_class(s[i])) return 0;
   13.73 +    }
   13.74 +    return 1;
   13.75 +}
   13.76 +
   13.77 +/** Test if a string matches a keyword.
   13.78 + * The comparison is case-insensitive.
   13.79 + * The comparison fails if either argument is null.
   13.80 + *
   13.81 + * @param s string
   13.82 + * @param k keyword
   13.83 + * @return 1 if they match, 0 otherwise
   13.84 + */
   13.85 +int is_keyword(const char *s, const char *k){
   13.86 +  return s && k && !strcasecmp(s, k);
   13.87 +}
   13.88 +
   13.89 +/** Test if a string matches a character.
   13.90 + *
   13.91 + * @param s string
   13.92 + * @param c character (non-null)
   13.93 + * @return 1 if s contains exactly c, 0 otherwise
   13.94 + */
   13.95 +int is_keychar(const char *s, char c){
   13.96 +  return c && (s[0] == c) && !s[1];
   13.97 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/libxutil/lexis.h	Wed Nov 24 18:22:43 2004 +0000
    14.3 @@ -0,0 +1,128 @@
    14.4 +/*
    14.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    14.6 + *
    14.7 + * This library is free software; you can redistribute it and/or modify
    14.8 + * it under the terms of the GNU Lesser General Public License as
    14.9 + * published by the Free Software Foundation; either version 2.1 of the
   14.10 + * License, or  (at your option) any later version. This library is 
   14.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   14.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   14.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   14.14 + * See the GNU Lesser General Public License for more details.
   14.15 + *
   14.16 + * You should have received a copy of the GNU Lesser General Public License
   14.17 + * along with this library; if not, write to the Free Software Foundation,
   14.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   14.19 + */
   14.20 +
   14.21 +#ifndef _XUTIL_LEXIS_H_
   14.22 +#define _XUTIL_LEXIS_H_
   14.23 +
   14.24 +#include "sys_string.h"
   14.25 +
   14.26 +#ifdef __KERNEL__
   14.27 +#  include <linux/ctype.h>
   14.28 +#else
   14.29 +#  include <ctype.h>
   14.30 +#endif
   14.31 +
   14.32 +/** @file
   14.33 + * Lexical analysis.
   14.34 + */
   14.35 +
   14.36 +/** Class of characters treated as space. */
   14.37 +#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 })
   14.38 +
   14.39 +/** Class of separator characters. */
   14.40 +#define sep_class "{}()<>[]@!;"
   14.41 +
   14.42 +#define comment_class "#"
   14.43 +
   14.44 +/** Determine if a character is in a given class.
   14.45 + * 
   14.46 + * @param c character to test
   14.47 + * @param s null-terminated string of characters in the class
   14.48 + * @return 1 if c is in the class, 0 otherwise.
   14.49 + */
   14.50 +static inline int in_class(int c, const char *s){
   14.51 +  return s && (strchr(s, c) != 0);
   14.52 +}
   14.53 +
   14.54 +/** Determine if a character is in the space class.
   14.55 + * 
   14.56 + * @param c character to test
   14.57 + * @return 1 if c is in the class, 0 otherwise.
   14.58 + */
   14.59 +static inline int in_space_class(int c){
   14.60 +    return in_class(c, space_class);
   14.61 +}
   14.62 +
   14.63 +static inline int in_comment_class(int c){
   14.64 +    return in_class(c, comment_class);
   14.65 +}
   14.66 +
   14.67 +/** Determine if a character is in the separator class.
   14.68 + * Separator characters terminate tokens, and do not need space
   14.69 + * to separate them.
   14.70 + * 
   14.71 + * @param c character to test
   14.72 + * @return 1 if c is in the class, 0 otherwise.
   14.73 + */
   14.74 +static inline int in_sep_class(int c){
   14.75 +    return in_class(c, sep_class);
   14.76 +}
   14.77 +
   14.78 +/** Determine if a character is in the alpha class.
   14.79 + * 
   14.80 + * @param c character to test
   14.81 + * @return 1 if c is in the class, 0 otherwise.
   14.82 + */
   14.83 +static inline int in_alpha_class(int c){
   14.84 +    return isalpha(c);
   14.85 +}
   14.86 +
   14.87 +/** Determine if a character is in the octal digit class.
   14.88 + * 
   14.89 + * @param c character to test
   14.90 + * @return 1 if c is in the class, 0 otherwise.
   14.91 + */
   14.92 +static inline int in_octal_digit_class(int c){
   14.93 +    return '0' <= c && c <= '7';
   14.94 +}
   14.95 +
   14.96 +/** Determine if a character is in the decimal digit class.
   14.97 + * 
   14.98 + * @param c character to test
   14.99 + * @return 1 if c is in the class, 0 otherwise.
  14.100 + */
  14.101 +static inline int in_decimal_digit_class(int c){
  14.102 +    return isdigit(c);
  14.103 +}
  14.104 +
  14.105 +/** Determine if a character is in the hex digit class.
  14.106 + * 
  14.107 + * @param c character to test
  14.108 + * @return 1 if c is in the class, 0 otherwise.
  14.109 + */
  14.110 +static inline int in_hex_digit_class(int c){
  14.111 +    return isdigit(c) || in_class(c, "abcdefABCDEF");
  14.112 +}
  14.113 +
  14.114 +
  14.115 +static inline int in_string_quote_class(int c){
  14.116 +    return in_class(c, "'\"");
  14.117 +}
  14.118 +
  14.119 +static inline int in_printable_class(int c){
  14.120 +    return ('A' <= c && c <= 'Z')
  14.121 +        || ('a' <= c && c <= 'z')
  14.122 +        || ('0' <= c && c <= '9')
  14.123 +        || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~");
  14.124 +}
  14.125 +
  14.126 +extern int is_decimal_number(const char *s, int n);
  14.127 +extern int is_hex_number(const char *s, int n);
  14.128 +extern int is_keyword(const char *s, const char *k);
  14.129 +extern int is_keychar(const char *s, char c);
  14.130 +
  14.131 +#endif /* !_XUTIL_LEXIS_H_ */
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tools/libxutil/socket_stream.c	Wed Nov 24 18:22:43 2004 +0000
    15.3 @@ -0,0 +1,230 @@
    15.4 +/*
    15.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    15.6 + *
    15.7 + * This library is free software; you can redistribute it and/or modify
    15.8 + * it under the terms of the GNU Lesser General Public License as published by
    15.9 + * the Free Software Foundation; either version 2.1 of the License, or
   15.10 + * (at your option) any later version.
   15.11 + *
   15.12 + * This library is distributed in the hope that it will be useful,
   15.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.15 + * GNU Lesser General Public License for more details.
   15.16 + *
   15.17 + * You should have received a copy of the GNU Lesser General Public License
   15.18 + * along with this library; if not, write to the Free Software
   15.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   15.20 + */
   15.21 +
   15.22 +/** @file
   15.23 + * An IOStream implementation using sockets.
   15.24 + */
   15.25 +#ifndef __KERNEL__
   15.26 +
   15.27 +#include <stdio.h>
   15.28 +#include <stdlib.h>
   15.29 +#include <string.h>
   15.30 +#include <unistd.h>
   15.31 +#include <errno.h>
   15.32 +#include "allocate.h"
   15.33 +#include "socket_stream.h"
   15.34 +
   15.35 +#define MODULE_NAME "sock"
   15.36 +#define DEBUG 0
   15.37 +//#undef DEBUG
   15.38 +#include "debug.h"
   15.39 +
   15.40 +static int socket_read(IOStream *s, void *buf, size_t n);
   15.41 +static int socket_write(IOStream *s, const void *buf, size_t n);
   15.42 +static int socket_error(IOStream *s);
   15.43 +static int socket_close(IOStream *s);
   15.44 +static void socket_free(IOStream *s);
   15.45 +static int socket_flush(IOStream *s);
   15.46 +
   15.47 +/** Methods used by a socket IOStream. */
   15.48 +static const IOMethods socket_methods = {
   15.49 +    read:  socket_read,
   15.50 +    write: socket_write,
   15.51 +    error: socket_error,
   15.52 +    close: socket_close,
   15.53 +    free:  socket_free,
   15.54 +    flush: socket_flush,
   15.55 +};
   15.56 +
   15.57 +/** Get the socket data.
   15.58 + * 
   15.59 + * @param io socket stream
   15.60 + * @return data
   15.61 + */
   15.62 +static inline SocketData * socket_data(IOStream *io){
   15.63 +    return (SocketData *)io->data;
   15.64 +}
   15.65 +
   15.66 +/** Test if a stream is a socket stream.
   15.67 + *
   15.68 + * @param io stream
   15.69 + * @return 0 if a socket stream, -EINVAL if not
   15.70 + */
   15.71 +int socket_stream_check(IOStream *io){
   15.72 +    return (io && io->methods == &socket_methods ? 0 : -EINVAL);
   15.73 +}
   15.74 +
   15.75 +/** Get the data for a socket stream.
   15.76 + *
   15.77 + * @param io stream
   15.78 + * @param data return value for the data
   15.79 + * @return 0 if a socket stream, -EINVAL if not
   15.80 + */
   15.81 +int socket_stream_data(IOStream *io, SocketData **data){
   15.82 +    int err = socket_stream_check(io);
   15.83 +    if(err){
   15.84 +        *data = NULL;
   15.85 +    } else {
   15.86 +        *data = socket_data(io);
   15.87 +    }
   15.88 +    return err;
   15.89 +}
   15.90 +
   15.91 +/** Set the destination address for a socket stream.
   15.92 + *
   15.93 + * @param io stream
   15.94 + * @param addr address
   15.95 + * @return 0 if a socket stream, -EINVAL if not
   15.96 + */
   15.97 +int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){
   15.98 +    int err = 0;
   15.99 +    SocketData *data = NULL;
  15.100 +    err = socket_stream_data(io, &data);
  15.101 +    if(!err){
  15.102 +        data->daddr = *addr;
  15.103 +    }
  15.104 +    return err;
  15.105 +}
  15.106 +
  15.107 +/** Set the send flags for a socket stream.
  15.108 + *
  15.109 + * @param io stream
  15.110 + * @param flags flags
  15.111 + * @return 0 if a socket stream, -EINVAL if not
  15.112 + */
  15.113 +int socket_stream_set_flags(IOStream *io, int flags){
  15.114 +    int err = 0;
  15.115 +    SocketData *data = NULL;
  15.116 +    err = socket_stream_data(io, &data);
  15.117 +    if(!err){
  15.118 +        data->flags = flags;
  15.119 +    }
  15.120 +    return err;
  15.121 +}
  15.122 +
  15.123 +/** Write to the underlying socket using sendto.
  15.124 + *
  15.125 + * @param stream input
  15.126 + * @param buf where to put input
  15.127 + * @param n number of bytes to write
  15.128 + * @return number of bytes written
  15.129 + */
  15.130 +static int socket_write(IOStream *s, const void *buf, size_t n){
  15.131 +    SocketData *data = socket_data(s);
  15.132 +    struct sockaddr *daddr = (struct sockaddr *)&data->daddr;
  15.133 +    socklen_t daddr_n = sizeof(data->daddr);
  15.134 +    int k;
  15.135 +    dprintf("> sock=%d addr=%s:%d n=%d\n",
  15.136 +            data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n);
  15.137 +    if(0){
  15.138 +        struct sockaddr_in self = {};
  15.139 +        socklen_t self_n;
  15.140 +        getsockname(data->fd, (struct sockaddr *)&self, &self_n);
  15.141 +        dprintf("> sockname sock=%d %s:%d\n",
  15.142 +                data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port));
  15.143 +    }
  15.144 +    k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n);
  15.145 +    dprintf("> sendto=%d\n", k);
  15.146 +    return k;
  15.147 +}
  15.148 +
  15.149 +/** Read from the underlying stream using recv();
  15.150 + *
  15.151 + * @param stream input
  15.152 + * @param buf where to put input
  15.153 + * @param n number of bytes to read
  15.154 + * @return number of bytes read
  15.155 + */
  15.156 +static int socket_read(IOStream *s, void *buf, size_t n){
  15.157 +    SocketData *data = socket_data(s);
  15.158 +    int k;
  15.159 +    struct sockaddr *saddr = (struct sockaddr *)&data->saddr;
  15.160 +    socklen_t saddr_n = sizeof(data->saddr);
  15.161 +    k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n);
  15.162 +    return k;
  15.163 +}
  15.164 +
  15.165 +/** Flush the socket (no-op).
  15.166 + *
  15.167 + * @param s socket stream
  15.168 + * @return 0 on success, error code otherwise
  15.169 + */
  15.170 +static int socket_flush(IOStream *s){
  15.171 +    return 0;
  15.172 +}
  15.173 +
  15.174 +/** Check if a socket stream has an error (no-op).
  15.175 + *
  15.176 + * @param s socket stream
  15.177 + * @return 1 if has an error, 0 otherwise
  15.178 + */
  15.179 +static int socket_error(IOStream *s){
  15.180 +    // Read SOL_SOCKET/SO_ERROR ?
  15.181 +    return 0;
  15.182 +}
  15.183 +
  15.184 +/** Close a socket stream.
  15.185 + *
  15.186 + * @param s socket stream to close
  15.187 + * @return result of the close
  15.188 + */
  15.189 +static int socket_close(IOStream *s){
  15.190 +    SocketData *data = socket_data(s);
  15.191 +    return close(data->fd);
  15.192 +}
  15.193 +
  15.194 +/** Free a socket stream.
  15.195 + *
  15.196 + * @param s socket stream
  15.197 + */
  15.198 +static void socket_free(IOStream *s){
  15.199 +    SocketData *data = socket_data(s);
  15.200 +    deallocate(data);
  15.201 +}
  15.202 +
  15.203 +/** Create an IOStream for a socket.
  15.204 + *
  15.205 + * @param fd socket to wtap
  15.206 + * @return new IOStream using fd for i/o
  15.207 + */
  15.208 +IOStream *socket_stream_new(int fd){
  15.209 +    int err = -ENOMEM;
  15.210 +    IOStream *io = NULL;
  15.211 +    SocketData *data = NULL;
  15.212 +
  15.213 +    io = ALLOCATE(IOStream);
  15.214 +    if(!io) goto exit;
  15.215 +    io->methods = &socket_methods;
  15.216 +    data = ALLOCATE(SocketData);
  15.217 +    if(!data) goto exit;
  15.218 +    io->data = data;
  15.219 +    data->fd = fd;
  15.220 +    data->buf_n = sizeof(data->buf);
  15.221 +    err = 0;
  15.222 +  exit:
  15.223 +    if(err){
  15.224 +        if(io){
  15.225 +            if(data) deallocate(data);
  15.226 +            deallocate(io);
  15.227 +            io = NULL;
  15.228 +        }
  15.229 +    }
  15.230 +    return io;
  15.231 +}
  15.232 +
  15.233 +#endif
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/libxutil/socket_stream.h	Wed Nov 24 18:22:43 2004 +0000
    16.3 @@ -0,0 +1,53 @@
    16.4 +/*
    16.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    16.6 + *
    16.7 + * This library is free software; you can redistribute it and/or modify
    16.8 + * it under the terms of the GNU Lesser General Public License as published by
    16.9 + * the Free Software Foundation; either version 2.1 of the License, or
   16.10 + * (at your option) any later version.
   16.11 + *
   16.12 + * This library is distributed in the hope that it will be useful,
   16.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.15 + * GNU Lesser General Public License for more details.
   16.16 + *
   16.17 + * You should have received a copy of the GNU Lesser General Public License
   16.18 + * along with this library; if not, write to the Free Software
   16.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   16.20 + */
   16.21 +
   16.22 +#ifndef _XEN_LIB_SOCKET_STREAM_H_
   16.23 +#define _XEN_LIB_SOCKET_STREAM_H_
   16.24 +
   16.25 +#ifndef __KERNEL__
   16.26 +#include "iostream.h"
   16.27 +#include <stdio.h>
   16.28 +
   16.29 +#include <sys/socket.h>
   16.30 +#include <netinet/in.h>
   16.31 +#include <arpa/inet.h>
   16.32 +
   16.33 +/** Data associated with a socket stream. */
   16.34 +typedef struct SocketData {
   16.35 +    /** The socket file descriptor. */
   16.36 +    int fd;
   16.37 +    /** Source address from last read (recvfrom). */
   16.38 +    struct sockaddr_in saddr;
   16.39 +    /** Destination address for writes (sendto). */
   16.40 +    struct sockaddr_in daddr;
   16.41 +    /** Write flags (sendto). */
   16.42 +    int flags;
   16.43 +    /** Buffer size. */
   16.44 +    int buf_n;
   16.45 +    /** Buffer for formatted printing. */
   16.46 +    char buf[1024];
   16.47 +} SocketData;
   16.48 +
   16.49 +extern IOStream *socket_stream_new(int fd);
   16.50 +extern int socket_stream_data(IOStream *io, SocketData **data);
   16.51 +extern int socket_stream_check(IOStream *io);
   16.52 +extern int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr);
   16.53 +extern int socket_stream_set_flags(IOStream *io, int flags);
   16.54 +
   16.55 +#endif
   16.56 +#endif /* !_XEN_LIB_SOCKET_STREAM_H_ */
    17.1 --- a/tools/libxutil/string_stream.c	Wed Nov 24 11:51:49 2004 +0000
    17.2 +++ b/tools/libxutil/string_stream.c	Wed Nov 24 18:22:43 2004 +0000
    17.3 @@ -1,5 +1,5 @@
    17.4  /*
    17.5 - * Copyright (C) 2001, 2002 Hewlett-Packard Company.
    17.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    17.7   *
    17.8   * This library is free software; you can redistribute it and/or modify
    17.9   * it under the terms of the GNU Lesser General Public License as published by
    18.1 --- a/tools/libxutil/string_stream.h	Wed Nov 24 11:51:49 2004 +0000
    18.2 +++ b/tools/libxutil/string_stream.h	Wed Nov 24 18:22:43 2004 +0000
    18.3 @@ -1,5 +1,5 @@
    18.4  /*
    18.5 - * Copyright (C) 2001, 2002 Hewlett-Packard Company.
    18.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    18.7   *
    18.8   * This library is free software; you can redistribute it and/or modify
    18.9   * it under the terms of the GNU Lesser General Public License as published by
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/libxutil/sxpr.c	Wed Nov 24 18:22:43 2004 +0000
    19.3 @@ -0,0 +1,956 @@
    19.4 +/*
    19.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    19.6 + *
    19.7 + * This library is free software; you can redistribute it and/or modify
    19.8 + * it under the terms of the GNU Lesser General Public License as
    19.9 + * published by the Free Software Foundation; either version 2.1 of the
   19.10 + * License, or  (at your option) any later version. This library is 
   19.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   19.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   19.14 + * See the GNU Lesser General Public License for more details.
   19.15 + *
   19.16 + * You should have received a copy of the GNU Lesser General Public License
   19.17 + * along with this library; if not, write to the Free Software Foundation,
   19.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   19.19 + */
   19.20 +
   19.21 +#include <stdarg.h>
   19.22 +#include "sys_string.h"
   19.23 +#include "lexis.h"
   19.24 +#include "sys_net.h"
   19.25 +#include "hash_table.h"
   19.26 +#include "sxpr.h"
   19.27 +
   19.28 +#ifdef __KERNEL__
   19.29 +#include <linux/errno.h>
   19.30 +#else
   19.31 +#include <errno.h>
   19.32 +#endif
   19.33 +
   19.34 +#undef free
   19.35 +
   19.36 +/** @file
   19.37 + * General representation of sxprs.
   19.38 + * Includes print, equal, and free functions for the sxpr types.
   19.39 + *
   19.40 + * Zero memory containing an Sxpr will have the value ONONE - this is intentional.
   19.41 + * When a function returning an sxpr cannot allocate memory we return ONOMEM.
   19.42 + *
   19.43 + */
   19.44 +
   19.45 +static int atom_print(IOStream *io, Sxpr obj, unsigned flags);
   19.46 +static int atom_equal(Sxpr x, Sxpr y);
   19.47 +static void atom_free(Sxpr obj);
   19.48 +
   19.49 +static int string_print(IOStream *io, Sxpr obj, unsigned flags);
   19.50 +static int string_equal(Sxpr x, Sxpr y);
   19.51 +static void string_free(Sxpr obj);
   19.52 +
   19.53 +static int cons_print(IOStream *io, Sxpr obj, unsigned flags);
   19.54 +static int cons_equal(Sxpr x, Sxpr y);
   19.55 +static void cons_free(Sxpr obj);
   19.56 +
   19.57 +static int null_print(IOStream *io, Sxpr obj, unsigned flags);
   19.58 +static int none_print(IOStream *io, Sxpr obj, unsigned flags);
   19.59 +static int int_print(IOStream *io, Sxpr obj, unsigned flags);
   19.60 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags);
   19.61 +
   19.62 +/** Type definitions. */
   19.63 +static SxprType types[1024] = {
   19.64 +    [T_NONE]     { type:    T_NONE,     name: "none",       print: none_print      },
   19.65 +    [T_NULL]     { type:    T_NULL,     name: "null",       print: null_print      },
   19.66 +    [T_UINT]     { type:    T_UINT,     name: "int",        print: int_print,      },
   19.67 +    [T_BOOL]     { type:    T_BOOL,     name: "bool",       print: bool_print,     },
   19.68 +    [T_ATOM]     { type:    T_ATOM,     name: "atom",       print: atom_print,
   19.69 +		   pointer: TRUE,
   19.70 +		   free:    atom_free,
   19.71 +		   equal:   atom_equal,
   19.72 +		 },
   19.73 +    [T_STRING]   { type:    T_STRING,   name: "string",     print: string_print,
   19.74 +		   pointer: TRUE,
   19.75 +		   free:    string_free,
   19.76 +		   equal:   string_equal,
   19.77 +		 },
   19.78 +    [T_CONS]     { type:    T_CONS,     name: "cons",       print: cons_print,
   19.79 +		   pointer: TRUE,
   19.80 +		   free:    cons_free,
   19.81 +		   equal:   cons_equal,
   19.82 +		 },
   19.83 +};
   19.84 +
   19.85 +/** Number of entries in the types array. */
   19.86 +static int type_sup = sizeof(types)/sizeof(types[0]);
   19.87 +
   19.88 +/** Get the type definition for a given type code.
   19.89 + *
   19.90 + * @param ty type code
   19.91 + * @return type definition or null
   19.92 + */
   19.93 +SxprType *get_sxpr_type(int ty){
   19.94 +    if(0 <= ty && ty < type_sup){
   19.95 +        return types+ty;
   19.96 +    }
   19.97 +    return NULL;
   19.98 +}
   19.99 +
  19.100 +/** The default print function.
  19.101 + *
  19.102 + * @param io stream to print to
  19.103 + * @param x sxpr to print
  19.104 + * @param flags print flags
  19.105 + * @return number of bytes written on success
  19.106 + */
  19.107 +int default_print(IOStream *io, Sxpr x, unsigned flags){
  19.108 +    return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x));
  19.109 +}
  19.110 +
  19.111 +/** The default equal function.
  19.112 + * Uses eq().
  19.113 + *
  19.114 + * @param x sxpr to compare
  19.115 + * @param y sxpr to compare
  19.116 + * @return 1 if equal, 0 otherwise
  19.117 + */
  19.118 +int default_equal(Sxpr x, Sxpr y){
  19.119 +    return eq(x, y);
  19.120 +}
  19.121 +
  19.122 +/** General sxpr print function.
  19.123 + * Prints an sxpr on a stream using the print function for the sxpr type.
  19.124 + * Printing is controlled by flags from the PrintFlags enum.
  19.125 + * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr
  19.126 + * (for debugging).
  19.127 + *
  19.128 + * @param io stream to print to
  19.129 + * @param x sxpr to print
  19.130 + * @param flags print flags
  19.131 + * @return number of bytes written
  19.132 + */
  19.133 +int objprint(IOStream *io, Sxpr x, unsigned flags){
  19.134 +    SxprType *def = get_sxpr_type(get_type(x));
  19.135 +    ObjPrintFn *print_fn = (def && def->print ? def->print : default_print);
  19.136 +    int k = 0;
  19.137 +    if(!io) return k;
  19.138 +    if(flags & PRINT_TYPE){
  19.139 +	k += IOStream_print(io, "%s:", def->name);
  19.140 +    }
  19.141 +    k += print_fn(io, x, flags);
  19.142 +    return k;
  19.143 +}
  19.144 +
  19.145 +/** General sxpr free function.
  19.146 + * Frees an sxpr using the free function for its type.
  19.147 + * Free functions must recursively free any subsxprs.
  19.148 + * If no function is defined then the default is to
  19.149 + * free sxprs whose type has pointer true.
  19.150 + * Sxprs must not be used after freeing.
  19.151 + *
  19.152 + * @param x sxpr to free
  19.153 + */
  19.154 +void objfree(Sxpr x){
  19.155 +    SxprType *def = get_sxpr_type(get_type(x));
  19.156 +
  19.157 +    if(def){
  19.158 +	if(def->free){
  19.159 +	    def->free(x);
  19.160 +	} else if (def->pointer){
  19.161 +	    hfree(x);
  19.162 +	}
  19.163 +    }
  19.164 +}
  19.165 +
  19.166 +/** General sxpr equality function.
  19.167 + * Compares x and y using the equal function for x.
  19.168 + * Uses default_equal() if x has no equal function.
  19.169 + *
  19.170 + * @param x sxpr to compare
  19.171 + * @param y sxpr to compare
  19.172 + * @return 1 if equal, 0 otherwise
  19.173 + */
  19.174 +int objequal(Sxpr x, Sxpr y){
  19.175 +    SxprType *def = get_sxpr_type(get_type(x));
  19.176 +    ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal);
  19.177 +    return equal_fn(x, y);
  19.178 +}
  19.179 +
  19.180 +/** Search for a key in an alist.
  19.181 + * An alist is a list of conses, where the cars
  19.182 + * of the conses are the keys. Compares keys using equality.
  19.183 + *
  19.184 + * @param k key
  19.185 + * @param l alist to search
  19.186 + * @return first element of l with car k, or ONULL
  19.187 + */
  19.188 +Sxpr assoc(Sxpr k, Sxpr l){
  19.189 +    for( ; CONSP(l) ; l = CDR(l)){
  19.190 +        Sxpr x = CAR(l);
  19.191 +        if(CONSP(x) && objequal(k, CAR(x))){
  19.192 +            return x;   
  19.193 +        }
  19.194 +    }
  19.195 +    return ONULL;
  19.196 +}
  19.197 +
  19.198 +/** Search for a key in an alist.
  19.199 + * An alist is a list of conses, where the cars
  19.200 + * of the conses are the keys. Compares keys using eq.
  19.201 + *
  19.202 + * @param k key
  19.203 + * @param l alist to search
  19.204 + * @return first element of l with car k, or ONULL
  19.205 + */
  19.206 +Sxpr assocq(Sxpr k, Sxpr l){
  19.207 +    for( ; CONSP(l); l = CDR(l)){
  19.208 +        Sxpr x = CAR(l);
  19.209 +        if(CONSP(x) && eq(k, CAR(x))){
  19.210 +            return x;
  19.211 +        }
  19.212 +    }
  19.213 +    return ONULL;
  19.214 +}
  19.215 +
  19.216 +/** Add a new key and value to an alist.
  19.217 + *
  19.218 + * @param k key
  19.219 + * @param l value
  19.220 + * @param l alist
  19.221 + * @return l with the new cell added to the front
  19.222 + */
  19.223 +Sxpr acons(Sxpr k, Sxpr v, Sxpr l){
  19.224 +    Sxpr x, y;
  19.225 +    x = cons_new(k, v);
  19.226 +    if(NOMEMP(x)) return x;
  19.227 +    y = cons_new(x, l);
  19.228 +    if(NOMEMP(y)) cons_free_cells(x);
  19.229 +    return y;
  19.230 +}
  19.231 +
  19.232 +/** Test if a list contains an element.
  19.233 + * Uses sxpr equality.
  19.234 + *
  19.235 + * @param l list
  19.236 + * @param x element to look for
  19.237 + * @return a tail of l with x as car, or ONULL
  19.238 + */
  19.239 +Sxpr cons_member(Sxpr l, Sxpr x){
  19.240 +    for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){}
  19.241 +    return l;
  19.242 +}
  19.243 +
  19.244 +/** Test if a list contains an element satisfying a test.
  19.245 + * The test function is called with v and an element of the list.
  19.246 + *
  19.247 + * @param l list
  19.248 + * @param test_fn test function to use
  19.249 + * @param v value for first argument to the test
  19.250 + * @return a tail of l with car satisfying the test, or 0
  19.251 + */
  19.252 +Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
  19.253 +    for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ }
  19.254 +    return l;
  19.255 +}
  19.256 +
  19.257 +/** Test if the elements of list 't' are a subset of the elements
  19.258 + * of list 's'. Element order is not significant.
  19.259 + *
  19.260 + * @param s element list to check subset of
  19.261 + * @param t element list to check if is a subset
  19.262 + * @return 1 if is a subset, 0 otherwise
  19.263 + */
  19.264 +int cons_subset(Sxpr s, Sxpr t){
  19.265 +    for( ; CONSP(t); t = CDR(t)){
  19.266 +	if(!CONSP(cons_member(s, CAR(t)))){
  19.267 +	    return 0;
  19.268 +	}
  19.269 +    }
  19.270 +    return 1;
  19.271 +}
  19.272 +
  19.273 +/** Test if two lists have equal sets of elements.
  19.274 + * Element order is not significant.
  19.275 + *
  19.276 + * @param s list to check
  19.277 + * @param t list to check
  19.278 + * @return 1 if equal, 0 otherwise
  19.279 + */
  19.280 +int cons_set_equal(Sxpr s, Sxpr t){
  19.281 +    return cons_subset(s, t) && cons_subset(t, s);
  19.282 +}
  19.283 +
  19.284 +#ifdef USE_GC
  19.285 +/*============================================================================*/
  19.286 +/* The functions inside this ifdef are only safe if GC is used.
  19.287 + * Otherwise they may leak memory.
  19.288 + */
  19.289 +
  19.290 +/** Remove an element from a list (GC only).
  19.291 + * Uses sxpr equality and removes all instances, even
  19.292 + * if there are more than one.
  19.293 + *
  19.294 + * @param l list to remove elements from
  19.295 + * @param x element to remove
  19.296 + * @return modified input list
  19.297 + */
  19.298 +Sxpr cons_remove(Sxpr l, Sxpr x){
  19.299 +    return cons_remove_if(l, eq, x);
  19.300 +}
  19.301 +
  19.302 +/** Remove elements satisfying a test (GC only).
  19.303 + * The test function is called with v and an element of the set.
  19.304 + *
  19.305 + * @param l list to remove elements from
  19.306 + * @param test_fn function to use to decide if an element should be removed
  19.307 + * @return modified input list
  19.308 + */
  19.309 +Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
  19.310 +    Sxpr prev = ONULL, elt, next;
  19.311 +
  19.312 +    for(elt = l; CONSP(elt); elt = next){
  19.313 +        next = CDR(elt);
  19.314 +        if(test_fn(v, CAR(elt))){
  19.315 +            if(NULLP(prev)){
  19.316 +                l = next;
  19.317 +            } else {
  19.318 +                CDR(prev) = next;
  19.319 +            }
  19.320 +        }
  19.321 +    }
  19.322 +    return l;
  19.323 +}
  19.324 +
  19.325 +/** Set the value for a key in an alist (GC only).
  19.326 + * If the key is present, changes the value, otherwise
  19.327 + * adds a new cell.
  19.328 + *
  19.329 + * @param k key
  19.330 + * @param v value
  19.331 + * @param l alist
  19.332 + * @return modified or extended list
  19.333 + */
  19.334 +Sxpr setf(Sxpr k, Sxpr v, Sxpr l){
  19.335 +    Sxpr e = assoc(k, l);
  19.336 +    if(NULLP(e)){
  19.337 +        l = acons(k, v, l);
  19.338 +    } else {
  19.339 +        CAR(CDR(e)) = v;
  19.340 +    }
  19.341 +    return l;
  19.342 +}
  19.343 +/*============================================================================*/
  19.344 +#endif /* USE_GC */
  19.345 +
  19.346 +/** Create a new atom with the given name.
  19.347 + *
  19.348 + * @param name the name
  19.349 + * @return new atom
  19.350 + */
  19.351 +Sxpr atom_new(char *name){
  19.352 +    Sxpr n, obj = ONOMEM;
  19.353 +
  19.354 +    n = string_new(name);
  19.355 +    if(NOMEMP(n)) goto exit;
  19.356 +    obj = HALLOC(ObjAtom, T_ATOM);
  19.357 +    if(NOMEMP(obj)) goto exit;
  19.358 +    OBJ_ATOM(obj)->name = n;
  19.359 +  exit:
  19.360 +    return obj;
  19.361 +}
  19.362 +
  19.363 +/** Free an atom.
  19.364 + *
  19.365 + * @param obj to free
  19.366 + */
  19.367 +void atom_free(Sxpr obj){
  19.368 +    // Interned atoms are shared, so do not free.
  19.369 +    if(OBJ_ATOM(obj)->interned) return;
  19.370 +    objfree(OBJ_ATOM(obj)->name);
  19.371 +    hfree(obj);
  19.372 +}
  19.373 +
  19.374 +/** Print an atom. Prints the atom name.
  19.375 + *
  19.376 + * @param io stream to print to
  19.377 + * @param obj to print
  19.378 + * @param flags print flags
  19.379 + * @return number of bytes printed
  19.380 + */
  19.381 +int atom_print(IOStream *io, Sxpr obj, unsigned flags){
  19.382 +    //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW));
  19.383 +    return string_print(io, OBJ_ATOM(obj)->name, flags);
  19.384 +}
  19.385 +
  19.386 +/** Atom equality.
  19.387 + *
  19.388 + * @param x to compare
  19.389 + * @param y to compare
  19.390 + * @return 1 if equal, 0 otherwise
  19.391 + */
  19.392 +int atom_equal(Sxpr x, Sxpr y){
  19.393 +    int ok;
  19.394 +    ok = eq(x, y);
  19.395 +    if(ok) goto exit;
  19.396 +    ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name);
  19.397 +    if(ok) goto exit;
  19.398 +    ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y);
  19.399 +  exit:
  19.400 +    return ok;
  19.401 +}
  19.402 +
  19.403 +/** Get the name of an atom.
  19.404 + *
  19.405 + * @param obj atom
  19.406 + * @return name
  19.407 + */
  19.408 +char * atom_name(Sxpr obj){
  19.409 +    return string_string(OBJ_ATOM(obj)->name);
  19.410 +}
  19.411 +
  19.412 +/** Get the C string from a string sxpr.
  19.413 + *
  19.414 + * @param obj string sxpr
  19.415 + * @return string
  19.416 + */
  19.417 +char * string_string(Sxpr obj){
  19.418 +    return OBJ_STRING(obj);
  19.419 +}
  19.420 +
  19.421 +/** Get the length of a string.
  19.422 + *
  19.423 + * @param obj string
  19.424 + * @return length
  19.425 + */
  19.426 +int string_length(Sxpr obj){
  19.427 +    return strlen(OBJ_STRING(obj));
  19.428 +}
  19.429 +
  19.430 +/** Create a new string. The input string is copied,
  19.431 + * and must be null-terminated.
  19.432 + *
  19.433 + * @param s characters to put in the string
  19.434 + * @return new sxpr
  19.435 + */
  19.436 +Sxpr string_new(char *s){
  19.437 +    int n = (s ? strlen(s) : 0);
  19.438 +    Sxpr obj;
  19.439 +    obj = halloc(n+1, T_STRING);
  19.440 +    if(!NOMEMP(obj)){
  19.441 +        char *str = OBJ_STRING(obj);
  19.442 +        strncpy(str, s, n);
  19.443 +        str[n] = '\0';
  19.444 +    }
  19.445 +    return obj;
  19.446 +}
  19.447 +
  19.448 +/** Free a string.
  19.449 + *
  19.450 + * @param obj to free
  19.451 + */
  19.452 +void string_free(Sxpr obj){
  19.453 +    hfree(obj);
  19.454 +}
  19.455 +
  19.456 +/** Determine if a string needs escapes when printed
  19.457 + * using the given flags.
  19.458 + *
  19.459 + * @param str string to check
  19.460 + * @param flags print flags
  19.461 + * @return 1 if needs escapes, 0 otherwise
  19.462 + */
  19.463 +int needs_escapes(char *str, unsigned flags){
  19.464 +    char *c;
  19.465 +    int val = 0;
  19.466 +
  19.467 +    if(str){
  19.468 +	for(c=str; *c; c++){
  19.469 +	    if(in_alpha_class(*c)) continue;
  19.470 +	    if(in_decimal_digit_class(*c)) continue;
  19.471 +	    if(in_class(*c, "/._+:@~-")) continue;
  19.472 +	    val = 1;
  19.473 +	    break;
  19.474 +	}
  19.475 +    }
  19.476 +    //printf("\n> val=%d str=|%s|\n", val, str);
  19.477 +    return val;
  19.478 +}
  19.479 +
  19.480 +/** Print a string to a stream, with escapes if necessary.
  19.481 + *
  19.482 + * @param io stream to print to
  19.483 + * @param str string
  19.484 + * @param flags print flags
  19.485 + * @return number of bytes written
  19.486 + */
  19.487 +int _string_print(IOStream *io, char *str, unsigned flags){
  19.488 +    int k = 0;
  19.489 +    if((flags & PRINT_RAW) || !needs_escapes(str, flags)){
  19.490 +        k += IOStream_print(io, str);
  19.491 +    } else {
  19.492 +	k += IOStream_print(io, "\"");
  19.493 +	if(str){
  19.494 +            char *s;
  19.495 +            for(s = str; *s; s++){
  19.496 +                if(*s < ' ' || *s >= 127 ){
  19.497 +                    switch(*s){
  19.498 +                    case '\a': k += IOStream_print(io, "\\a");  break;
  19.499 +                    case '\b': k += IOStream_print(io, "\\b");  break;
  19.500 +                    case '\f': k += IOStream_print(io, "\\f");  break;
  19.501 +                    case '\n': k += IOStream_print(io, "\\n");  break;
  19.502 +                    case '\r': k += IOStream_print(io, "\\r");  break;
  19.503 +                    case '\t': k += IOStream_print(io, "\\t");  break;
  19.504 +                    case '\v': k += IOStream_print(io, "\\v");  break;
  19.505 +                    default:
  19.506 +                        // Octal escape;
  19.507 +                        k += IOStream_print(io, "\\%o", *s);
  19.508 +                        break;
  19.509 +                    }
  19.510 +                } else if(*s == c_double_quote ||
  19.511 +                          *s == c_single_quote ||
  19.512 +                          *s == c_escape){
  19.513 +                    k += IOStream_print(io, "\\%c", *s);
  19.514 +                } else {
  19.515 +                    k+= IOStream_print(io, "%c", *s);
  19.516 +                }
  19.517 +            }
  19.518 +	}
  19.519 +	k += IOStream_print(io, "\"");
  19.520 +    }
  19.521 +    return k;
  19.522 +}
  19.523 +
  19.524 +/** Print a string to a stream, with escapes if necessary.
  19.525 + *
  19.526 + * @param io stream to print to
  19.527 + * @param obj string
  19.528 + * @param flags print flags
  19.529 + * @return number of bytes written
  19.530 + */
  19.531 +int string_print(IOStream *io, Sxpr obj, unsigned flags){
  19.532 +    return _string_print(io, OBJ_STRING(obj), flags);
  19.533 +}
  19.534 +
  19.535 +/** Compare an sxpr with a string for equality.
  19.536 + *
  19.537 + * @param x string to compare with
  19.538 + * @param y sxpr to compare
  19.539 + * @return 1 if equal, 0 otherwise
  19.540 + */
  19.541 +int string_equal(Sxpr x, Sxpr y){
  19.542 +    int ok = 0;
  19.543 +    ok = eq(x,y);
  19.544 +    if(ok) goto exit;
  19.545 +    ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y));
  19.546 +    if(ok) goto exit;
  19.547 +    ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y));
  19.548 +  exit:
  19.549 +    return ok;
  19.550 +}
  19.551 +
  19.552 +/** Create a new cons cell.
  19.553 + * The cell is ONOMEM if either argument is.
  19.554 + *
  19.555 + * @param car sxpr for the car
  19.556 + * @param cdr sxpr for the cdr
  19.557 + * @return new cons
  19.558 + */
  19.559 +Sxpr cons_new(Sxpr car, Sxpr cdr){
  19.560 +    Sxpr obj;
  19.561 +    if(NOMEMP(car) || NOMEMP(cdr)){
  19.562 +        obj = ONOMEM;
  19.563 +    } else {
  19.564 +        obj = HALLOC(ObjCons, T_CONS);
  19.565 +        if(!NOMEMP(obj)){
  19.566 +            ObjCons *z = OBJ_CONS(obj);
  19.567 +            z->car = car;
  19.568 +            z->cdr = cdr;
  19.569 +        }
  19.570 +    }
  19.571 +    return obj;
  19.572 +}
  19.573 +
  19.574 +/** Push a new element onto a list.
  19.575 + *
  19.576 + * @param list list to add to
  19.577 + * @param elt element to add
  19.578 + * @return 0 if successful, error code otherwise
  19.579 + */
  19.580 +int cons_push(Sxpr *list, Sxpr elt){
  19.581 +    Sxpr l;
  19.582 +    l = cons_new(elt, *list);
  19.583 +    if(NOMEMP(l)) return -ENOMEM;
  19.584 +    *list = l;
  19.585 +    return 0;
  19.586 +}
  19.587 +
  19.588 +/** Free a cons. Recursively frees the car and cdr.
  19.589 + *
  19.590 + * @param obj to free
  19.591 + */
  19.592 +void cons_free(Sxpr obj){
  19.593 +    Sxpr next;
  19.594 +    for(; CONSP(obj); obj = next){
  19.595 +	next = CDR(obj);
  19.596 +	objfree(CAR(obj));
  19.597 +	hfree(obj);
  19.598 +    }
  19.599 +    if(!NULLP(obj)){
  19.600 +	objfree(obj);
  19.601 +    }
  19.602 +}
  19.603 +
  19.604 +/** Free a cons and its cdr cells, but not the car sxprs.
  19.605 + * Does nothing if called on something that is not a cons.
  19.606 + *
  19.607 + * @param obj to free
  19.608 + */
  19.609 +void cons_free_cells(Sxpr obj){
  19.610 +    Sxpr next;
  19.611 +    for(; CONSP(obj); obj = next){
  19.612 +	next = CDR(obj);
  19.613 +	hfree(obj);
  19.614 +    }
  19.615 +}
  19.616 +
  19.617 +/** Print a cons.
  19.618 + * Prints the cons in list format if the cdrs are conses.
  19.619 + * uses pair (dot) format if the last cdr is not a cons (or null).
  19.620 + *
  19.621 + * @param io stream to print to
  19.622 + * @param obj to print
  19.623 + * @param flags print flags
  19.624 + * @return number of bytes written
  19.625 + */
  19.626 +int cons_print(IOStream *io, Sxpr obj, unsigned flags){
  19.627 +    int first = 1;
  19.628 +    int k = 0;
  19.629 +    k += IOStream_print(io, "(");
  19.630 +    for( ; CONSP(obj) ; obj = CDR(obj)){
  19.631 +        if(first){ 
  19.632 +            first = 0;
  19.633 +        } else {
  19.634 +            k += IOStream_print(io, " ");
  19.635 +        }
  19.636 +        k += objprint(io, CAR(obj), flags);
  19.637 +    }
  19.638 +    if(!NULLP(obj)){
  19.639 +        k += IOStream_print(io, " . ");
  19.640 +        k += objprint(io, obj, flags);
  19.641 +    }
  19.642 +    k += IOStream_print(io, ")");
  19.643 +    return (IOStream_error(io) ? -1 : k);
  19.644 +}
  19.645 +
  19.646 +/** Compare a cons with another sxpr for equality.
  19.647 + * If y is a cons, compares the cars and cdrs recursively.
  19.648 + *
  19.649 + * @param x cons to compare
  19.650 + * @param y sxpr to compare
  19.651 + * @return 1 if equal, 0 otherwise
  19.652 + */
  19.653 +int cons_equal(Sxpr x, Sxpr y){
  19.654 +    return CONSP(y) &&
  19.655 +        objequal(CAR(x), CAR(y)) &&
  19.656 +        objequal(CDR(x), CDR(y));
  19.657 +}
  19.658 +
  19.659 +/** Return the length of a cons list.
  19.660 + *
  19.661 + * @param obj list
  19.662 + * @return length
  19.663 + */
  19.664 +int cons_length(Sxpr obj){
  19.665 +    int count = 0;
  19.666 +    for( ; CONSP(obj); obj = CDR(obj)){
  19.667 +        count++;
  19.668 +    }
  19.669 +    return count;
  19.670 +}
  19.671 +
  19.672 +/** Destructively reverse a cons list in-place.
  19.673 + * If the argument is not a cons it is returned unchanged.
  19.674 + * 
  19.675 + * @param l to reverse
  19.676 + * @return reversed list
  19.677 + */
  19.678 +Sxpr nrev(Sxpr l){
  19.679 +    if(CONSP(l)){
  19.680 +	// Iterate down the cells in the list making the cdr of
  19.681 +	// each cell point to the previous cell. The last cell 
  19.682 +	// is the head of the reversed list.
  19.683 +	Sxpr prev = ONULL;
  19.684 +	Sxpr cell = l;
  19.685 +	Sxpr next;
  19.686 +
  19.687 +	while(1){
  19.688 +	    next = CDR(cell);
  19.689 +	    CDR(cell) = prev;
  19.690 +	    if(!CONSP(next)) break;
  19.691 +	    prev = cell;
  19.692 +	    cell = next;
  19.693 +	}
  19.694 +	l = cell;
  19.695 +    }
  19.696 +    return l;
  19.697 +}
  19.698 +
  19.699 +/** Print the null sxpr.	
  19.700 + *
  19.701 + * @param io stream to print to
  19.702 + * @param obj to print
  19.703 + * @param flags print flags
  19.704 + * @return number of bytes written
  19.705 + */
  19.706 +static int null_print(IOStream *io, Sxpr obj, unsigned flags){
  19.707 +    return IOStream_print(io, "()");
  19.708 +}
  19.709 +
  19.710 +/** Print the `unspecified' sxpr none.
  19.711 + *
  19.712 + * @param io stream to print to
  19.713 + * @param obj to print
  19.714 + * @param flags print flags
  19.715 + * @return number of bytes written
  19.716 + */
  19.717 +static int none_print(IOStream *io, Sxpr obj, unsigned flags){
  19.718 +    return IOStream_print(io, "<none>");
  19.719 +}
  19.720 +
  19.721 +/** Print an integer.
  19.722 + *
  19.723 + * @param io stream to print to
  19.724 + * @param obj to print
  19.725 + * @param flags print flags
  19.726 + * @return number of bytes written
  19.727 + */
  19.728 +static int int_print(IOStream *io, Sxpr obj, unsigned flags){
  19.729 +    return IOStream_print(io, "%d", OBJ_INT(obj));
  19.730 +}
  19.731 +
  19.732 +/** Print a boolean.
  19.733 + *
  19.734 + * @param io stream to print to
  19.735 + * @param obj to print
  19.736 + * @param flags print flags
  19.737 + * @return number of bytes written
  19.738 + */
  19.739 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags){
  19.740 +    return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false));
  19.741 +}
  19.742 +
  19.743 +int sxprp(Sxpr obj, Sxpr name){
  19.744 +    return CONSP(obj) && objequal(CAR(obj), name);
  19.745 +}
  19.746 +
  19.747 +/** Get the name of an element.
  19.748 + * 
  19.749 + * @param obj element
  19.750 + * @return name
  19.751 + */
  19.752 +Sxpr sxpr_name(Sxpr obj){
  19.753 +    Sxpr val = ONONE;
  19.754 +    if(CONSP(obj)){
  19.755 +        val = CAR(obj);
  19.756 +    } else if(STRINGP(obj) || ATOMP(obj)){
  19.757 +        val = obj;
  19.758 +    }
  19.759 +    return val;
  19.760 +}
  19.761 +
  19.762 +int sxpr_is(Sxpr obj, char *s){
  19.763 +    if(ATOMP(obj)) return !strcmp(atom_name(obj), s);
  19.764 +    if(STRINGP(obj)) return !strcmp(string_string(obj), s);
  19.765 +    return 0;
  19.766 +}
  19.767 +
  19.768 +int sxpr_elementp(Sxpr obj, Sxpr name){
  19.769 +    int ok = 0;
  19.770 +    ok = CONSP(obj) && objequal(CAR(obj), name);
  19.771 +    return ok;
  19.772 +}
  19.773 +
  19.774 +/** Get the attributes of an sxpr.
  19.775 + * 
  19.776 + * @param obj sxpr
  19.777 + * @return attributes
  19.778 + */
  19.779 +Sxpr sxpr_attributes(Sxpr obj){
  19.780 +    Sxpr val = ONULL;
  19.781 +    if(CONSP(obj)){
  19.782 +        obj = CDR(obj);
  19.783 +        if(CONSP(obj)){
  19.784 +            obj = CAR(obj);
  19.785 +            if(sxprp(obj, intern("@"))){
  19.786 +                val = CDR(obj);
  19.787 +            }
  19.788 +        }
  19.789 +    }
  19.790 +    return val;
  19.791 +}
  19.792 +
  19.793 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){
  19.794 +    Sxpr val = ONONE;
  19.795 +    val = assoc(sxpr_attributes(obj), key);
  19.796 +    if(CONSP(val) && CONSP(CDR(val))){
  19.797 +        val = CADR(def);
  19.798 +    } else {
  19.799 +        val = def;
  19.800 +    }
  19.801 +    return val;
  19.802 +}
  19.803 +
  19.804 +/** Get the children of an sxpr.
  19.805 + * 
  19.806 + * @param obj sxpr
  19.807 + * @return children
  19.808 + */
  19.809 +Sxpr sxpr_children(Sxpr obj){
  19.810 +    Sxpr val = ONULL;
  19.811 +    if(CONSP(obj)){
  19.812 +        val = CDR(obj);
  19.813 +        if(CONSP(val) && sxprp(CAR(val), intern("@"))){
  19.814 +            val = CDR(val);
  19.815 +        }
  19.816 +    }
  19.817 +    return val;
  19.818 +}
  19.819 +
  19.820 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){
  19.821 +    Sxpr val = ONONE;
  19.822 +    Sxpr l;
  19.823 +    for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){
  19.824 +        if(sxprp(CAR(l), name)){
  19.825 +            val = CAR(l);
  19.826 +            break;
  19.827 +        }
  19.828 +    }
  19.829 +    if(NONEP(val)) val = def;
  19.830 +    return val;
  19.831 +}
  19.832 +
  19.833 +Sxpr sxpr_child0(Sxpr obj, Sxpr def){
  19.834 +    Sxpr val = ONONE;
  19.835 +    Sxpr l = sxpr_children(obj);
  19.836 +    if(CONSP(l)){
  19.837 +        val = CAR(l);
  19.838 +    } else {
  19.839 +        val = def;
  19.840 +    }
  19.841 +    return val;
  19.842 +}
  19.843 +
  19.844 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def){
  19.845 +    Sxpr val = def;
  19.846 +    Sxpr l;
  19.847 +    int i;
  19.848 +    for (i = 0, l = sxpr_children(obj); CONSP(l); i++, l = CDR(l)){
  19.849 +        if(i == n){
  19.850 +            val = CAR(l);
  19.851 +            break;
  19.852 +        }
  19.853 +    }
  19.854 +    return val;
  19.855 +}
  19.856 +    
  19.857 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){
  19.858 +    Sxpr val = ONONE;
  19.859 +    val = sxpr_child(obj, name, ONONE);
  19.860 +    if(NONEP(val)){
  19.861 +        val = def;
  19.862 +    } else {
  19.863 +        val = sxpr_child0(val, def);
  19.864 +    }
  19.865 +    return val;
  19.866 +}
  19.867 +
  19.868 +/** Table of interned symbols. Indexed by symbol name. */
  19.869 +static HashTable *symbols = NULL;
  19.870 +
  19.871 +/** Hash function for entries in the symbol table.
  19.872 + *
  19.873 + * @param key to hash
  19.874 + * @return hashcode
  19.875 + */
  19.876 +static Hashcode sym_hash_fn(void *key){
  19.877 +    return hash_string((char*)key);
  19.878 +}
  19.879 +
  19.880 +/** Key equality function for the symbol table.
  19.881 + *
  19.882 + * @param x to compare
  19.883 + * @param y to compare
  19.884 + * @return 1 if equal, 0 otherwise
  19.885 + */
  19.886 +static int sym_equal_fn(void *x, void *y){
  19.887 +    return !strcmp((char*)x, (char*)y);
  19.888 +}
  19.889 +
  19.890 +/** Entry free function for the symbol table.
  19.891 + *
  19.892 + * @param table the entry is in
  19.893 + * @param entry being freed
  19.894 + */
  19.895 +static void sym_free_fn(HashTable *table, HTEntry *entry){
  19.896 +    if(entry){
  19.897 +	objfree(((ObjAtom*)entry->value)->name);
  19.898 +	HTEntry_free(entry);
  19.899 +    }
  19.900 +}
  19.901 +	
  19.902 +/** Initialize the symbol table.
  19.903 + *
  19.904 + * @return 0 on sucess, error code otherwise
  19.905 + */
  19.906 +static int init_symbols(void){
  19.907 +    symbols = HashTable_new(100);
  19.908 +    if(symbols){
  19.909 +        symbols->key_hash_fn = sym_hash_fn;
  19.910 +        symbols->key_equal_fn = sym_equal_fn;
  19.911 +	symbols->entry_free_fn = sym_free_fn;
  19.912 +        return 0;
  19.913 +    }
  19.914 +    return -1;
  19.915 +}
  19.916 +
  19.917 +/** Cleanup the symbol table. Frees the table and all its symbols.
  19.918 + */
  19.919 +void cleanup_symbols(void){
  19.920 +    HashTable_free(symbols);
  19.921 +    symbols = NULL;
  19.922 +}
  19.923 +
  19.924 +/** Get the interned symbol with the given name.
  19.925 + * No new symbol is created.
  19.926 + *
  19.927 + * @return symbol or null
  19.928 + */
  19.929 +Sxpr get_symbol(char *sym){
  19.930 +    HTEntry *entry;
  19.931 +    if(!symbols){
  19.932 +	if(init_symbols()) return ONOMEM;
  19.933 +	return ONULL;
  19.934 +    }
  19.935 +    entry = HashTable_get_entry(symbols, sym);
  19.936 +    if(entry){
  19.937 +        return OBJP(T_ATOM, entry->value);
  19.938 +    } else {
  19.939 +        return ONULL;
  19.940 +    }
  19.941 +}
  19.942 +
  19.943 +/** Get the interned symbol with the given name.
  19.944 + * Creates a new symbol if necessary.
  19.945 + *
  19.946 + * @return symbol
  19.947 + */
  19.948 +Sxpr intern(char *sym){
  19.949 +    Sxpr symbol = get_symbol(sym);
  19.950 +    if(NULLP(symbol)){
  19.951 +	if(!symbols) return ONOMEM;
  19.952 +        symbol = atom_new(sym);
  19.953 +        if(!NOMEMP(symbol)){
  19.954 +	    OBJ_ATOM(symbol)->interned = TRUE;
  19.955 +            HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));
  19.956 +        }
  19.957 +    }
  19.958 +    return symbol;
  19.959 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/libxutil/sxpr.h	Wed Nov 24 18:22:43 2004 +0000
    20.3 @@ -0,0 +1,420 @@
    20.4 +/*
    20.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    20.6 + *
    20.7 + * This library is free software; you can redistribute it and/or modify
    20.8 + * it under the terms of the GNU Lesser General Public License as
    20.9 + * published by the Free Software Foundation; either version 2.1 of the
   20.10 + * License, or  (at your option) any later version. This library is 
   20.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   20.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   20.14 + * See the GNU Lesser General Public License for more details.
   20.15 + *
   20.16 + * You should have received a copy of the GNU Lesser General Public License
   20.17 + * along with this library; if not, write to the Free Software Foundation,
   20.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   20.19 + */
   20.20 +#ifndef _XUTIL_SXPR_H_
   20.21 +#define _XUTIL_SXPR_H_
   20.22 +
   20.23 +#ifdef __KERNEL__
   20.24 +#include <linux/config.h>
   20.25 +#include <linux/types.h>
   20.26 +#else
   20.27 +#include <stdint.h>
   20.28 +#endif
   20.29 +
   20.30 +#include "hash_table.h"
   20.31 +#include "iostream.h"
   20.32 +#include "allocate.h"
   20.33 +
   20.34 +/** @file
   20.35 + * Definitions for rules and sxprs.
   20.36 + */
   20.37 +
   20.38 +#ifndef NULL
   20.39 +#define NULL 0
   20.40 +#endif
   20.41 +
   20.42 +#ifndef TRUE
   20.43 +#define TRUE 1
   20.44 +#endif
   20.45 +
   20.46 +#ifndef FALSE
   20.47 +#define FALSE 0
   20.48 +#endif
   20.49 +
   20.50 +/** Sxpr type. */
   20.51 +typedef int16_t TypeCode;
   20.52 +
   20.53 +/** A typed sxpr handle.*/
   20.54 +typedef struct Sxpr {
   20.55 +    /** Sxpr type. */
   20.56 +    TypeCode type;
   20.57 +    union {
   20.58 +	/** Sxpr value. */
   20.59 +        unsigned long ul;
   20.60 +	/** Pointer. */
   20.61 +        void *ptr;
   20.62 +    } v;
   20.63 +} Sxpr;
   20.64 +
   20.65 +/** Sxpr type to indicate out of memory. */
   20.66 +#define T_NOMEM      ((TypeCode)-1)
   20.67 +/** The 'unspecified' sxpr. */
   20.68 +#define T_NONE       ((TypeCode)0)
   20.69 +/** The empty list. */
   20.70 +#define T_NULL       ((TypeCode)1)
   20.71 +/** Unsigned integer. */
   20.72 +#define T_UINT       ((TypeCode)2)
   20.73 +/** A string. */
   20.74 +#define T_STRING     ((TypeCode)3)
   20.75 +/** An atom. */
   20.76 +#define T_ATOM       ((TypeCode)4)
   20.77 +/** A boolean. */
   20.78 +#define T_BOOL       ((TypeCode)5)
   20.79 +
   20.80 +/** A cons (pair or list). */
   20.81 +#define T_CONS       ((TypeCode)10)
   20.82 +
   20.83 +/** An error. */
   20.84 +#define T_ERR        ((TypeCode)40)
   20.85 +
   20.86 +/** An atom. */
   20.87 +typedef struct ObjAtom {
   20.88 +    Sxpr name;
   20.89 +    Hashcode hashcode;
   20.90 +    int interned;
   20.91 +} ObjAtom;
   20.92 +
   20.93 +/** A cons (pair). */
   20.94 +typedef struct ObjCons {
   20.95 +    Sxpr car;
   20.96 +    Sxpr cdr;
   20.97 +} ObjCons;
   20.98 +
   20.99 +/** A vector. */
  20.100 +typedef struct ObjVector {
  20.101 +    int n;
  20.102 +    Sxpr data[0];
  20.103 +} ObjVector;
  20.104 +
  20.105 +/** Flags for sxpr printing. */
  20.106 +enum PrintFlags {
  20.107 +    PRINT_RAW           = 0x001,
  20.108 +    PRINT_TYPE          = 0x002,
  20.109 +    PRINT_PRETTY        = 0x004,
  20.110 +    PRINT_NUM           = 0x008,
  20.111 +};
  20.112 +
  20.113 +/** An integer sxpr.
  20.114 + *
  20.115 + * @param ty type
  20.116 + * @param val integer value
  20.117 + */
  20.118 +#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }}
  20.119 +
  20.120 +/** A pointer sxpr.
  20.121 + * If the pointer is non-null, returns an sxpr containing it.
  20.122 + * If the pointer is null, returns ONOMEM.
  20.123 + *
  20.124 + * @param ty type
  20.125 + * @param val pointer
  20.126 + */
  20.127 +#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM)
  20.128 +
  20.129 +/** Make an integer sxpr containing a pointer.
  20.130 + *
  20.131 + * @param val pointer
  20.132 + */
  20.133 +#define PTR(val) OBJP(T_UINT, (void*)(val))
  20.134 +
  20.135 +/** Make an integer sxpr.
  20.136 + * @param x value
  20.137 + */
  20.138 +#define OINT(x)       OBJI(T_UINT,  x)
  20.139 +
  20.140 +/** Make an error sxpr.
  20.141 + *
  20.142 + * @param x value
  20.143 + */
  20.144 +#define OERR(x)       OBJI(T_ERR,   x)
  20.145 +
  20.146 +/** Out of memory constant. */
  20.147 +#define ONOMEM        OBJI(T_NOMEM, 0)
  20.148 +
  20.149 +/** The `unspecified' constant. */
  20.150 +#define ONONE         OBJI(T_NONE,  0)
  20.151 +
  20.152 +/** Empty list constant. */
  20.153 +#define ONULL         OBJI(T_NULL,  0)
  20.154 +
  20.155 +/** False constant. */
  20.156 +#define OFALSE        OBJI(T_BOOL,  0)
  20.157 +
  20.158 +/** True constant. */
  20.159 +#define OTRUE         OBJI(T_BOOL,  1)
  20.160 +
  20.161 +/* Recognizers for the various sxpr types.  */
  20.162 +#define ATOMP(obj)        has_type(obj, T_ATOM)
  20.163 +#define BOOLP(obj)        has_type(obj, T_BOOL)
  20.164 +#define CONSP(obj)        has_type(obj, T_CONS)
  20.165 +#define ERRP(obj)         has_type(obj, T_ERR)
  20.166 +#define INTP(obj)         has_type(obj, T_UINT)
  20.167 +#define NOMEMP(obj)       has_type(obj, T_NOMEM)
  20.168 +#define NONEP(obj)        has_type(obj, T_NONE)
  20.169 +#define NULLP(obj)        has_type(obj, T_NULL)
  20.170 +#define STRINGP(obj)      has_type(obj, T_STRING)
  20.171 +
  20.172 +#define TRUEP(obj)    get_ul(obj)
  20.173 +
  20.174 +/** Convert an sxpr to an unsigned integer. */
  20.175 +#define OBJ_UINT(x)   get_ul(x)
  20.176 +/** Convert an sxpr to an integer. */
  20.177 +#define OBJ_INT(x)    (int)get_ul(x)
  20.178 +
  20.179 +/* Conversions of sxprs to their values.
  20.180 + * No checking is done.
  20.181 + */
  20.182 +#define OBJ_STRING(x)  ((char*)get_ptr(x))
  20.183 +#define OBJ_CONS(x)    ((ObjCons*)get_ptr(x))
  20.184 +#define OBJ_ATOM(x)    ((ObjAtom*)get_ptr(x))
  20.185 +#define OBJ_SET(x)     ((ObjSet*)get_ptr(x))
  20.186 +#define CAR(x)         (OBJ_CONS(x)->car)
  20.187 +#define CDR(x)         (OBJ_CONS(x)->cdr)
  20.188 +
  20.189 +#define CAAR(x)        (CAR(CAR(x)))
  20.190 +#define CADR(x)        (CAR(CDR(x)))
  20.191 +#define CDAR(x)        (CDR(CAR(x)))
  20.192 +#define CDDR(x)        (CDR(CDR(x)))
  20.193 +
  20.194 +/** Get the integer value from an sxpr.
  20.195 + *
  20.196 + * @param obj sxpr
  20.197 + * @return value
  20.198 + */
  20.199 +static inline unsigned long get_ul(Sxpr obj){
  20.200 +    return obj.v.ul;
  20.201 +}
  20.202 +
  20.203 +/** Get the pointer value from an sxpr.
  20.204 + *
  20.205 + * @param obj sxpr
  20.206 + * @return value
  20.207 + */
  20.208 +static inline void * get_ptr(Sxpr obj){
  20.209 +    return obj.v.ptr;
  20.210 +}
  20.211 +
  20.212 +/** Create an sxpr containing a pointer.
  20.213 + *
  20.214 + * @param type typecode
  20.215 + * @param val pointer
  20.216 + * @return sxpr
  20.217 + */
  20.218 +static inline Sxpr obj_ptr(TypeCode type, void *val){
  20.219 +    return (Sxpr){ type: type, v: { ptr: val } };
  20.220 +}
  20.221 +
  20.222 +/** Create an sxpr containing an integer.
  20.223 + *
  20.224 + * @param type typecode
  20.225 + * @param val integer
  20.226 + * @return sxpr
  20.227 + */
  20.228 +static inline Sxpr obj_ul(TypeCode type, unsigned long val){
  20.229 +    return (Sxpr){ type: type, v: { ul: val } };
  20.230 +}
  20.231 +
  20.232 +/** Get the type of an sxpr.
  20.233 + *
  20.234 + * @param obj sxpr
  20.235 + * @return type
  20.236 + */
  20.237 +static inline TypeCode get_type(Sxpr obj){
  20.238 +    return obj.type;
  20.239 +}
  20.240 +
  20.241 +/** Check the type of an sxpr.
  20.242 + *
  20.243 + * @param obj sxpr
  20.244 + * @param type to check
  20.245 + * @return 1 if has the type, 0 otherwise
  20.246 + */
  20.247 +static inline int has_type(Sxpr obj, TypeCode type){
  20.248 +    return get_type(obj) == type;
  20.249 +}
  20.250 +
  20.251 +/** Compare sxprs for literal equality of type and value.
  20.252 + *
  20.253 + * @param x sxpr to compare
  20.254 + * @param y sxpr to compare
  20.255 + * @return 1 if equal, 0 otherwise
  20.256 + */
  20.257 +static inline int eq(Sxpr x, Sxpr y){
  20.258 +    return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y)));
  20.259 +}
  20.260 +
  20.261 +/** Checked version of CAR
  20.262 + *
  20.263 + * @param x sxpr
  20.264 + * @return CAR if a cons, x otherwise
  20.265 + */
  20.266 +static inline Sxpr car(Sxpr x){
  20.267 +    return (CONSP(x) ? CAR(x) : x);
  20.268 +}
  20.269 +
  20.270 +/** Checked version of CDR.
  20.271 + *
  20.272 + * @param x sxpr
  20.273 + * @return CDR if a cons, null otherwise
  20.274 + */
  20.275 +static inline Sxpr cdr(Sxpr x){
  20.276 +    return (CONSP(x) ? CDR(x) : ONULL);
  20.277 +}
  20.278 +
  20.279 +/** Allocate some memory and return an sxpr containing it.
  20.280 + * Returns ONOMEM if allocation failed.
  20.281 + *
  20.282 + * @param n number of bytes to allocate
  20.283 + * @param ty typecode
  20.284 + * @return sxpr
  20.285 + */
  20.286 +static inline Sxpr halloc(size_t n,  TypeCode ty){
  20.287 +    return OBJP(ty, allocate(n));
  20.288 +}
  20.289 +
  20.290 +/** Allocate an sxpr containing a pointer to the given type.
  20.291 + *
  20.292 + * @param ty type (uses sizeof to determine how many bytes to allocate)
  20.293 + * @param code typecode
  20.294 + * @return sxpr, ONOMEM if allocation failed
  20.295 + */
  20.296 +#define HALLOC(ty, code) halloc(sizeof(ty), code)
  20.297 +
  20.298 +typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags);
  20.299 +typedef int ObjEqualFn(Sxpr obj, Sxpr other);
  20.300 +typedef void ObjFreeFn(Sxpr obj);
  20.301 +
  20.302 +/** An sxpr type definition. */
  20.303 +typedef struct SxprType {
  20.304 +    TypeCode type;
  20.305 +    char *name;
  20.306 +    int pointer;
  20.307 +    ObjPrintFn *print;
  20.308 +    ObjEqualFn *equal;
  20.309 +    ObjFreeFn *free;
  20.310 +} SxprType;
  20.311 +
  20.312 +
  20.313 +extern SxprType *get_sxpr_type(int ty);
  20.314 +
  20.315 +/** Free the pointer in an sxpr.
  20.316 + *
  20.317 + * @param x sxpr containing a pointer
  20.318 + */
  20.319 +static inline void hfree(Sxpr x){
  20.320 +    deallocate(get_ptr(x));
  20.321 +}
  20.322 +
  20.323 +extern int objprint(IOStream *io, Sxpr x, unsigned flags);
  20.324 +extern int objequal(Sxpr x, Sxpr y);
  20.325 +extern void objfree(Sxpr x);
  20.326 +
  20.327 +extern void cons_free_cells(Sxpr obj);
  20.328 +extern Sxpr intern(char *s);
  20.329 +
  20.330 +extern Sxpr assoc(Sxpr k, Sxpr l);
  20.331 +extern Sxpr assocq(Sxpr k, Sxpr l);
  20.332 +extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l);
  20.333 +extern Sxpr nrev(Sxpr l);
  20.334 +extern Sxpr cons_member(Sxpr l, Sxpr x);
  20.335 +extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
  20.336 +extern int cons_subset(Sxpr s, Sxpr t);
  20.337 +extern int cons_set_equal(Sxpr s, Sxpr t);
  20.338 +
  20.339 +#ifdef USE_GC
  20.340 +extern Sxpr cons_remove(Sxpr l, Sxpr x);
  20.341 +extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
  20.342 +#endif
  20.343 +
  20.344 +extern Sxpr atom_new(char *name);
  20.345 +extern char * atom_name(Sxpr obj);
  20.346 +
  20.347 +extern Sxpr string_new(char *s);
  20.348 +extern char * string_string(Sxpr obj);
  20.349 +extern int string_length(Sxpr obj);
  20.350 +
  20.351 +extern Sxpr cons_new(Sxpr car, Sxpr cdr);
  20.352 +extern int cons_push(Sxpr *list, Sxpr elt);
  20.353 +extern int cons_length(Sxpr obj);
  20.354 +
  20.355 +Sxpr sxpr_name(Sxpr obj);
  20.356 +int sxpr_is(Sxpr obj, char *s);
  20.357 +int sxpr_elementp(Sxpr obj, Sxpr name);
  20.358 +Sxpr sxpr_attributes(Sxpr obj);
  20.359 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def);
  20.360 +Sxpr sxpr_children(Sxpr obj);
  20.361 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def);
  20.362 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def);
  20.363 +Sxpr sxpr_child0(Sxpr obj, Sxpr def);
  20.364 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def);
  20.365 +
  20.366 +/** Create a new atom.
  20.367 + *
  20.368 + * @param s atom name
  20.369 + * @return new atom
  20.370 + */
  20.371 +static inline Sxpr mkatom(char *s){
  20.372 +    return atom_new(s);
  20.373 +}
  20.374 +
  20.375 +/** Create a new string sxpr.
  20.376 + *
  20.377 + * @param s string bytes (copied)
  20.378 + * @return new string
  20.379 + */
  20.380 +static inline Sxpr mkstring(char *s){
  20.381 +    return string_new(s);
  20.382 +}
  20.383 +
  20.384 +/** Create an integer sxpr.
  20.385 + *
  20.386 + * @param i value
  20.387 + * @return sxpr
  20.388 + */
  20.389 +static inline Sxpr mkint(int i){
  20.390 +    return OBJI(T_UINT, i);
  20.391 +}
  20.392 +
  20.393 +/** Create a boolean sxpr.
  20.394 + *
  20.395 + * @param b value
  20.396 + * @return sxpr
  20.397 + */
  20.398 +static inline Sxpr mkbool(int b){
  20.399 +    return OBJI(T_BOOL, (b ? 1 : 0));
  20.400 +}
  20.401 +
  20.402 +/* Constants used in parsing and printing. */
  20.403 +#define k_list_open    "("
  20.404 +#define c_list_open    '('
  20.405 +#define k_list_close   ")"
  20.406 +#define c_list_close   ')'
  20.407 +#define k_true         "true"
  20.408 +#define k_false        "false"
  20.409 +
  20.410 +#define c_var          '$'
  20.411 +#define c_escape       '\\'
  20.412 +#define c_single_quote '\''
  20.413 +#define c_double_quote '"'
  20.414 +#define c_string_open  c_double_quote
  20.415 +#define c_string_close c_double_quote
  20.416 +#define c_data_open    '['
  20.417 +#define c_data_close   ']'
  20.418 +#define c_binary       '*'
  20.419 +#define c_eval         '!'
  20.420 +#define c_concat_open  '{'
  20.421 +#define c_concat_close '}'
  20.422 +
  20.423 +#endif /* ! _XUTIL_SXPR_H_ */
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/libxutil/sxpr_parser.c	Wed Nov 24 18:22:43 2004 +0000
    21.3 @@ -0,0 +1,933 @@
    21.4 +/*
    21.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    21.6 + *
    21.7 + * This library is free software; you can redistribute it and/or modify
    21.8 + * it under the terms of the GNU Lesser General Public License as
    21.9 + * published by the Free Software Foundation; either version 2.1 of the
   21.10 + * License, or  (at your option) any later version. This library is 
   21.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   21.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   21.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   21.14 + * See the GNU Lesser General Public License for more details.
   21.15 + *
   21.16 + * You should have received a copy of the GNU Lesser General Public License
   21.17 + * along with this library; if not, write to the Free Software Foundation,
   21.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   21.19 + */
   21.20 +
   21.21 +#ifdef __KERNEL__
   21.22 +#  include <linux/config.h>
   21.23 +#  include <linux/module.h>
   21.24 +#  include <linux/kernel.h>
   21.25 +#  include <linux/string.h>
   21.26 +#  include <linux/errno.h>
   21.27 +#else
   21.28 +#  include <stdlib.h>
   21.29 +#  include <errno.h>
   21.30 +#endif
   21.31 +
   21.32 +#include "iostream.h"
   21.33 +#include "lexis.h"
   21.34 +#include "sxpr_parser.h"
   21.35 +#include "sys_string.h"
   21.36 +#include "enum.h"
   21.37 +
   21.38 +/** @file
   21.39 + * Sxpr parsing.
   21.40 + *
   21.41 + * So that the parser does not leak memory, all sxprs constructed by
   21.42 + * the parser must be freed on error.  On successful parse the sxpr
   21.43 + * returned becomes the responsibility of the caller.
   21.44 + *
   21.45 + * @author Mike Wray <mike.wray@hpl.hp.com>
   21.46 + */
   21.47 +
   21.48 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
   21.49 +#define printf(fmt, args...)   IOStream_print(iostdout, fmt, ##args)
   21.50 +
   21.51 +static void reset(Parser *z);
   21.52 +static int inputchar(Parser *p, char c);
   21.53 +static int savechar(Parser *p, char c);
   21.54 +extern void parse_error(Parser *in);
   21.55 +extern void parse_error_id(Parser *in, ParseErrorId id);
   21.56 +
   21.57 +static int begin_start(Parser *p, char c);
   21.58 +static int state_start(Parser *p, char c);
   21.59 +static int end_start(Parser *p);
   21.60 +
   21.61 +static int begin_comment(Parser *p, char c);
   21.62 +static int state_comment(Parser *p, char c);
   21.63 +static int end_comment(Parser *p);
   21.64 +
   21.65 +static int begin_string(Parser *p, char c);
   21.66 +static int state_string(Parser *p, char c);
   21.67 +static int end_string(Parser *p);
   21.68 +static int state_escape(Parser *p, char c);
   21.69 +static int state_octal(Parser *p, char c);
   21.70 +static int state_hex(Parser *p, char c);
   21.71 +
   21.72 +static int begin_atom(Parser *p, char c);
   21.73 +static int state_atom(Parser *p, char c);
   21.74 +static int end_atom(Parser *p);
   21.75 +
   21.76 +static int state_list(Parser *p, char c);
   21.77 +static int begin_list(Parser *p, char c);
   21.78 +static int end_list(Parser *p);
   21.79 +
   21.80 +/** Print a parse error.
   21.81 + *
   21.82 + * @param in parser
   21.83 + * @param msg format followed by printf arguments
   21.84 + */
   21.85 +void eprintf(Parser *in, char *msg, ...){
   21.86 +    va_list args;
   21.87 +    if(in->error_out){
   21.88 +        va_start(args, msg);
   21.89 +        IOStream_vprint(in->error_out, msg, args);
   21.90 +        va_end(args);
   21.91 +    }
   21.92 +}
   21.93 +
   21.94 +/** Print a parse warning.
   21.95 + *
   21.96 + * @param in parser
   21.97 + * @param msg format followed by printf arguments
   21.98 + */
   21.99 +void wprintf(Parser *in, char *msg, ...){
  21.100 +    va_list args;
  21.101 +    if(in->error_out){
  21.102 +        va_start(args, msg);
  21.103 +        IOStream_vprint(in->error_out, msg, args);
  21.104 +        va_end(args);
  21.105 +    }
  21.106 +}
  21.107 +
  21.108 +/*============================================================================*/
  21.109 +
  21.110 +/** Record defining the message for a parse error. */
  21.111 +typedef struct {
  21.112 +  ParseErrorId id;
  21.113 +  char *message;
  21.114 +} ParseError;
  21.115 +
  21.116 +/** Format for printing parse error messages. */
  21.117 +#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
  21.118 +
  21.119 +/** Message catalog for the parse error codes. */
  21.120 +static ParseError catalog[] = {
  21.121 +  { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
  21.122 +  { PARSE_ERR_NOMEM,                  "out of memory" },
  21.123 +  { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
  21.124 +  { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
  21.125 +  { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
  21.126 +  { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
  21.127 +  { 0, NULL }
  21.128 +};
  21.129 +
  21.130 +/** Number of entries in the message catalog. */
  21.131 +const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
  21.132 +
  21.133 +void ParserState_free(ParserState *z){
  21.134 +    if(!z) return;
  21.135 +    objfree(z->val);
  21.136 +    deallocate(z);
  21.137 +}
  21.138 +
  21.139 +int ParserState_new(ParserStateFn *fn, char *name,
  21.140 +                    ParserState *parent, ParserState **val){
  21.141 +    int err = 0;
  21.142 +    ParserState *z;
  21.143 +    z = ALLOCATE(ParserState);
  21.144 +    if(z){
  21.145 +        z->name = name;
  21.146 +        z->fn = fn;
  21.147 +        z->parent = parent;
  21.148 +        z->val = ONULL;
  21.149 +    } else {
  21.150 +        err = -ENOMEM;
  21.151 +    }
  21.152 +    if(!err) *val = z;
  21.153 +    return err;
  21.154 +}
  21.155 +
  21.156 +/** Free a parser.
  21.157 + * No-op if the parser is null.
  21.158 + *
  21.159 + * @param z parser 
  21.160 + */
  21.161 +void Parser_free(Parser *z){
  21.162 +    if(!z) return;
  21.163 +    objfree(z->val);
  21.164 +    z->val = ONONE;
  21.165 +    deallocate(z);
  21.166 +}
  21.167 +
  21.168 +/** Create a new parser. The error stream defaults to null.
  21.169 + */
  21.170 +Parser * Parser_new(void){
  21.171 +    Parser *z = ALLOCATE(Parser);
  21.172 +    int err = -ENOMEM;
  21.173 +  
  21.174 +    if(!z) goto exit;
  21.175 +    err = 0;
  21.176 +    reset(z);
  21.177 +  exit:
  21.178 +    if(err){
  21.179 +        Parser_free(z);
  21.180 +        z = NULL;
  21.181 +    }
  21.182 +    return z;
  21.183 +}
  21.184 +
  21.185 +/** Get the next character.
  21.186 + * Records the character read in the parser,
  21.187 + * and sets the line and character counts.
  21.188 + *
  21.189 + * @param p parser
  21.190 + * @return error flag: 0 on success, non-zero on error
  21.191 + */
  21.192 +static int inputchar(Parser *p, char c){
  21.193 +    int err = 0;
  21.194 +    if(c=='\n'){
  21.195 +        p->line_no++;
  21.196 +        p->char_no = 0;
  21.197 +    } else {
  21.198 +        p->char_no++;
  21.199 +    }
  21.200 +    return err;
  21.201 +}
  21.202 +
  21.203 +static int savechar(Parser *p, char c){
  21.204 +    int err = 0;
  21.205 +    if(p->buf_i >= p->buf_n){
  21.206 +        err = -ENOMEM;
  21.207 +        goto exit;
  21.208 +    }
  21.209 +    p->buf[p->buf_i] = c;
  21.210 +    p->buf_i++;
  21.211 +  exit:
  21.212 +    return err;
  21.213 +}
  21.214 +
  21.215 +int Parser_input_char(Parser *p, char c){
  21.216 +    int err = 0;
  21.217 +    if(at_eof(p)){
  21.218 +        //skip;
  21.219 +    } else {
  21.220 +        inputchar(p, c);
  21.221 +    }
  21.222 +    if(!p->state){
  21.223 +        err = begin_start(p, c);
  21.224 +        if(err) goto exit;
  21.225 +    }
  21.226 +    err = p->state->fn(p, c);
  21.227 +  exit:
  21.228 +    return err;
  21.229 +}
  21.230 +
  21.231 +int Parser_input_eof(Parser *p){
  21.232 +    int err = 0;
  21.233 +    p->eof = 1;
  21.234 +    err = Parser_input_char(p, IOSTREAM_EOF);
  21.235 +    return err;
  21.236 +}
  21.237 +
  21.238 +int Parser_input(Parser *p, char *buf, int buf_n){
  21.239 +    int err = 0;
  21.240 +    int i = 0;
  21.241 +    if(buf_n <= 0){
  21.242 +        err = Parser_input_eof(p);
  21.243 +        goto exit;
  21.244 +    }
  21.245 +    for(i = 0; i<buf_n; i++){
  21.246 +        err = Parser_input_char(p, buf[i]);
  21.247 +        if(err) goto exit;
  21.248 +    }
  21.249 +  exit:
  21.250 +    err = (err < 0 ? err : buf_n);
  21.251 +    return err;
  21.252 +}
  21.253 +
  21.254 +int Parser_push(Parser *p, ParserStateFn *fn, char *name){
  21.255 +    int err = 0;
  21.256 +    err = ParserState_new(fn, name, p->state, &p->state);
  21.257 +    return err;
  21.258 +}
  21.259 +        
  21.260 +int Parser_pop(Parser *p){
  21.261 +    int err = 0;
  21.262 +    ParserState *s = p->state;
  21.263 +    p->state = s->parent;
  21.264 +    if (p->start_state == s)
  21.265 +        p->start_state = NULL;
  21.266 +    ParserState_free(s);
  21.267 +    return err;
  21.268 +}
  21.269 +
  21.270 +int Parser_return(Parser *p){
  21.271 +    int err = 0;
  21.272 +    Sxpr val = ONONE;
  21.273 +    if(!p->state){
  21.274 +        err = -EINVAL;
  21.275 +        goto exit;
  21.276 +    }
  21.277 +    val = p->state->val;
  21.278 +    p->state->val = ONONE;
  21.279 +    err = Parser_pop(p);
  21.280 +    if(err) goto exit;
  21.281 +    if(p->state){
  21.282 +        err = cons_push(&p->state->val, val);
  21.283 +    } else {
  21.284 +        val = nrev(val);
  21.285 +        p->val = val;
  21.286 +    }
  21.287 +  exit:
  21.288 +    if(err){
  21.289 +        objfree(val);
  21.290 +    }
  21.291 +    return err;
  21.292 +}
  21.293 +
  21.294 +/** Determine if a character is a separator.
  21.295 + *
  21.296 + * @param p parser
  21.297 + * @param c character to test
  21.298 + * @return 1 if a separator, 0 otherwise
  21.299 + */
  21.300 +static int is_separator(Parser *p, char c){
  21.301 +    return in_sep_class(c);
  21.302 +}
  21.303 +
  21.304 +/** Return the current token.
  21.305 + * The return value points at the internal buffer, so
  21.306 + * it must not be modified (or freed). Use copy_token() if you need a copy.
  21.307 + *
  21.308 + * @param p parser
  21.309 + * @return token
  21.310 + */
  21.311 +char *peek_token(Parser *p){
  21.312 +    return p->buf;
  21.313 +}
  21.314 +
  21.315 +/** Return a copy of the current token.
  21.316 + * The returned value should be freed when finished with.
  21.317 + *
  21.318 + * @param p parser
  21.319 + * @return copy of token
  21.320 + */
  21.321 +char *copy_token(Parser *p){
  21.322 +    return strdup(peek_token(p));
  21.323 +}
  21.324 +
  21.325 +static int do_intern(Parser *p){
  21.326 +    int err = 0;
  21.327 +    Sxpr obj = intern(peek_token(p));
  21.328 +    if(NOMEMP(obj)){
  21.329 +        err = -ENOMEM;
  21.330 +    } else {
  21.331 +        p->state->val = obj;
  21.332 +    }
  21.333 +    return err;
  21.334 +}
  21.335 +
  21.336 +static int do_string(Parser *p){
  21.337 +    int err = 0;
  21.338 +    Sxpr obj;
  21.339 +    obj = string_new(peek_token(p));
  21.340 +    if(NOMEMP(obj)){
  21.341 +        err = -ENOMEM;
  21.342 +    } else {
  21.343 +        p->state->val = obj;
  21.344 +    }
  21.345 +    return err;
  21.346 +}
  21.347 +
  21.348 +void newtoken(Parser *p){
  21.349 +    memset(p->buf, 0, p->buf_n);
  21.350 +    p->buf_i = 0;
  21.351 +    p->tok_begin_line = p->line_no;
  21.352 +    p->tok_begin_char = p->char_no;
  21.353 +}
  21.354 +
  21.355 +int get_escape(char c, char *d){
  21.356 +    int err = 0;
  21.357 +    switch(c){
  21.358 +    case 'a':            *d = '\a'; break;
  21.359 +    case 'b':            *d = '\b'; break;
  21.360 +    case 'f':            *d = '\f'; break;
  21.361 +    case 'n':            *d = '\n'; break;
  21.362 +    case 'r':            *d = '\r'; break;
  21.363 +    case 't':            *d = '\t'; break;
  21.364 +    case 'v':            *d = '\v'; break;
  21.365 +    case c_escape:       *d = c_escape; break;
  21.366 +    case c_single_quote: *d = c_single_quote; break;
  21.367 +    case c_double_quote: *d = c_double_quote; break;
  21.368 +    default:
  21.369 +        err = -EINVAL;
  21.370 +    }
  21.371 +    return err;
  21.372 +}
  21.373 +
  21.374 +int Parser_ready(Parser *p){
  21.375 +    return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));
  21.376 +}
  21.377 +
  21.378 +Sxpr Parser_get_val(Parser *p){
  21.379 +    Sxpr v = ONONE;
  21.380 +    if(CONSP(p->val)){
  21.381 +        v = CAR(p->val);
  21.382 +        p->val = CDR(p->val);
  21.383 +    } else if (CONSP(p->start_state->val)){
  21.384 +        p->val = p->start_state->val;
  21.385 +        p->val = nrev(p->val);
  21.386 +        p->start_state->val = ONULL;
  21.387 +        v = CAR(p->val);
  21.388 +        p->val = CDR(p->val);
  21.389 +    }        
  21.390 +    return v;
  21.391 +}
  21.392 +
  21.393 +Sxpr Parser_get_all(Parser *p){
  21.394 +    Sxpr v = ONULL;
  21.395 +    if(CONSP(p->val)){
  21.396 +        v = p->val;
  21.397 +        p->val = ONONE;
  21.398 +    } else if(p->start_state && CONSP(p->start_state->val)){
  21.399 +        v = p->start_state->val;
  21.400 +        p->start_state->val = ONULL;
  21.401 +        v = nrev(v);
  21.402 +    }
  21.403 +    return v;
  21.404 +}
  21.405 +    
  21.406 +int begin_start(Parser *p, char c){
  21.407 +    int err = 0;
  21.408 +    err = Parser_push(p, state_start, "start");
  21.409 +    if(err) goto exit;
  21.410 +    p->start_state = p->state;
  21.411 +  exit:
  21.412 +    return err;
  21.413 +}
  21.414 +
  21.415 +int state_start(Parser *p, char c){
  21.416 +    int err = 0;
  21.417 +    if(at_eof(p)){
  21.418 +        err = end_start(p);
  21.419 +    } else if(in_space_class(c)){
  21.420 +        //skip
  21.421 +    } else if(in_comment_class(c)){
  21.422 +        begin_comment(p, c);
  21.423 +    } else if(c == c_list_open){
  21.424 +        begin_list(p, c);
  21.425 +    } else if(c == c_list_close){
  21.426 +        parse_error(p);
  21.427 +        err = -EINVAL;
  21.428 +    } else if(in_string_quote_class(c)){
  21.429 +        begin_string(p, c);
  21.430 +    } else if(in_printable_class(c)){
  21.431 +        begin_atom(p, c);
  21.432 +    } else if(c == 0x04){
  21.433 +        //ctrl-D, EOT: end-of-text.
  21.434 +        Parser_input_eof(p);
  21.435 +    } else {
  21.436 +        parse_error(p);
  21.437 +        err = -EINVAL;
  21.438 +    }
  21.439 +    return err;
  21.440 +}
  21.441 +
  21.442 +int end_start(Parser *p){
  21.443 +    int err = 0;
  21.444 +    err = Parser_return(p);
  21.445 +    return err;
  21.446 +}
  21.447 +
  21.448 +int begin_comment(Parser *p, char c){
  21.449 +    int err = 0;
  21.450 +    err = Parser_push(p, state_comment, "comment");
  21.451 +    if(err) goto exit;
  21.452 +    err = inputchar(p, c);
  21.453 +  exit:
  21.454 +    return err;
  21.455 +}
  21.456 +
  21.457 +int state_comment(Parser *p, char c){
  21.458 +    int err = 0;
  21.459 +    if(c == '\n' || at_eof(p)){
  21.460 +        err = end_comment(p);
  21.461 +    } else {
  21.462 +        err = inputchar(p, c);
  21.463 +    }
  21.464 +    return err;
  21.465 +}
  21.466 +
  21.467 +int end_comment(Parser *p){
  21.468 +    return Parser_pop(p);
  21.469 +}
  21.470 +
  21.471 +int begin_string(Parser *p, char c){
  21.472 +    int err = 0;
  21.473 +    err = Parser_push(p, state_string, "string");
  21.474 +    if(err) goto exit;
  21.475 +    newtoken(p);
  21.476 +    p->state->delim = c;
  21.477 +  exit:
  21.478 +    return err;
  21.479 +}
  21.480 +
  21.481 +int state_string(Parser *p, char c){
  21.482 +    int err = 0;
  21.483 +    if(at_eof(p)){
  21.484 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  21.485 +        err = -EINVAL;
  21.486 +    } else if(c == p->state->delim){
  21.487 +        err = end_string(p);
  21.488 +    } else if(c == '\\'){
  21.489 +        err = Parser_push(p, state_escape, "escape");
  21.490 +    } else {
  21.491 +        err = savechar(p, c);
  21.492 +    }
  21.493 +    return err;
  21.494 +}
  21.495 +
  21.496 +int end_string(Parser *p){
  21.497 +    int err = 0;
  21.498 +    err = do_string(p);
  21.499 +    if(err) goto exit;
  21.500 +    err = Parser_return(p);
  21.501 +  exit:
  21.502 +    return err;
  21.503 +}
  21.504 +
  21.505 +int state_escape(Parser *p, char c){
  21.506 +    int err = 0;
  21.507 +    char d;
  21.508 +    if(at_eof(p)){
  21.509 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  21.510 +        err = -EINVAL;
  21.511 +        goto exit;
  21.512 +    }
  21.513 +    if(get_escape(c, &d) == 0){
  21.514 +        err = savechar(p, d);
  21.515 +        if(err) goto exit;
  21.516 +        err = Parser_pop(p);
  21.517 +    } else if(c == 'x'){
  21.518 +        p->state->fn = state_hex;
  21.519 +        p->state->ival = 0;
  21.520 +        p->state->count = 0;
  21.521 +    } else {
  21.522 +        p->state->fn = state_octal;
  21.523 +        p->state->ival = 0;
  21.524 +        p->state->count = 0;
  21.525 +        err = Parser_input_char(p, c);
  21.526 +    }
  21.527 +  exit:
  21.528 +    return err;
  21.529 +}
  21.530 +
  21.531 +int octaldone(Parser *p){
  21.532 +    int err = 0;
  21.533 +    char d = (char)(p->state->ival & 0xff);
  21.534 +    err = Parser_pop(p);
  21.535 +    if(err) goto exit;
  21.536 +    err = Parser_input_char(p, d);
  21.537 +  exit:
  21.538 +    return err;
  21.539 +}
  21.540 +
  21.541 +int octaldigit(Parser *p, char c){
  21.542 +    int err = 0;
  21.543 +    p->state->ival *= 8;
  21.544 +    p->state->ival += c - '0'; 
  21.545 +    p->state->count++;
  21.546 +    if(err) goto exit;
  21.547 +    if(p->state->ival < 0 || p->state->ival > 0xff){
  21.548 +        parse_error(p);
  21.549 +        err = -EINVAL;
  21.550 +        goto exit;
  21.551 +    }
  21.552 +    if(p->state->count == 3){
  21.553 +        err = octaldone(p);
  21.554 +    }
  21.555 +  exit:
  21.556 +    return err;
  21.557 +}
  21.558 +
  21.559 +int state_octal(Parser *p, char c){
  21.560 +    int err = 0;
  21.561 +    if(at_eof(p)){
  21.562 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  21.563 +        err = -EINVAL;
  21.564 +        goto exit;
  21.565 +    } else if('0' <= c && c <= '7'){
  21.566 +        err = octaldigit(p, c);
  21.567 +    } else {
  21.568 +        err = octaldone(p);
  21.569 +        if(err) goto exit;
  21.570 +        Parser_input_char(p, c);
  21.571 +    }
  21.572 +  exit:
  21.573 +    return err;
  21.574 +}
  21.575 +
  21.576 +int hexdone(Parser *p){
  21.577 +    int err = 0;
  21.578 +    char d = (char)(p->state->ival & 0xff);
  21.579 +    err = Parser_pop(p);
  21.580 +    if(err) goto exit;
  21.581 +    err = Parser_input_char(p, d);
  21.582 +  exit:
  21.583 +    return err;
  21.584 +}
  21.585 +    
  21.586 +int hexdigit(Parser *p, char c, char d){
  21.587 +    int err = 0;
  21.588 +    p->state->ival *= 16;
  21.589 +    p->state->ival += c - d; 
  21.590 +    p->state->count++;
  21.591 +    if(err) goto exit;
  21.592 +    if(p->state->ival < 0 || p->state->ival > 0xff){
  21.593 +        parse_error(p);
  21.594 +        err = -EINVAL;
  21.595 +        goto exit;
  21.596 +    }
  21.597 +    if(p->state->count == 2){
  21.598 +        err = hexdone(p);
  21.599 +    }
  21.600 +  exit:
  21.601 +    return err;
  21.602 +}
  21.603 +    
  21.604 +int state_hex(Parser *p, char c){
  21.605 +    int err = 0;
  21.606 +    if(at_eof(p)){
  21.607 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  21.608 +        err = -EINVAL;
  21.609 +        goto exit;
  21.610 +    } else if('0' <= c && c <= '9'){
  21.611 +        err = hexdigit(p, c, '0');
  21.612 +    } else if('A' <= c && c <= 'F'){
  21.613 +        err = hexdigit(p, c, 'A');
  21.614 +    } else if('a' <= c && c <= 'f'){
  21.615 +        err = hexdigit(p, c, 'a');
  21.616 +    } else if(p->state->count){
  21.617 +        err =hexdone(p);
  21.618 +        if(err) goto exit;
  21.619 +        Parser_input_char(p, c);
  21.620 +    }
  21.621 +  exit:
  21.622 +    return err;
  21.623 +}
  21.624 +
  21.625 +int begin_atom(Parser *p, char c){
  21.626 +    int err = 0;
  21.627 +    err = Parser_push(p, state_atom, "atom");
  21.628 +    if(err) goto exit;
  21.629 +    newtoken(p);
  21.630 +    err = savechar(p, c);
  21.631 +  exit:
  21.632 +    return err;
  21.633 +}
  21.634 +
  21.635 +int state_atom(Parser *p, char c){
  21.636 +    int err = 0;
  21.637 +    if(at_eof(p)){
  21.638 +        err = end_atom(p);
  21.639 +    } else if(is_separator(p, c) ||
  21.640 +              in_space_class(c) ||
  21.641 +              in_comment_class(c)){
  21.642 +        err = end_atom(p);
  21.643 +        if(err) goto exit;
  21.644 +        err = Parser_input_char(p, c);
  21.645 +    } else {
  21.646 +        err = savechar(p, c);
  21.647 +    }
  21.648 +  exit:
  21.649 +    return err;
  21.650 +}
  21.651 +
  21.652 +int end_atom(Parser *p){
  21.653 +    int err = 0;
  21.654 +    err = do_intern(p);
  21.655 +    if(err) goto exit;
  21.656 +    err = Parser_return(p);
  21.657 +  exit:
  21.658 +    return err;
  21.659 +}
  21.660 +
  21.661 +int state_list(Parser *p, char c){
  21.662 +    int err = 0;
  21.663 +    if(at_eof(p)){
  21.664 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  21.665 +        err = -EINVAL;
  21.666 +    } else if(c == c_list_close){
  21.667 +        p->state->val = nrev(p->state->val);
  21.668 +        err = end_list(p);
  21.669 +    } else {
  21.670 +        err = state_start(p, c);
  21.671 +    }
  21.672 +    return err;
  21.673 +    
  21.674 +}
  21.675 +
  21.676 +int begin_list(Parser *p, char c){
  21.677 +    return Parser_push(p, state_list, "list");
  21.678 +}
  21.679 +
  21.680 +int end_list(Parser *p){
  21.681 +    return Parser_return(p);
  21.682 +}
  21.683 +
  21.684 +/** Reset the fields of a parser to initial values.
  21.685 + *
  21.686 + * @param z parser
  21.687 + */
  21.688 +static void reset(Parser *z){
  21.689 +  IOStream *error_out = z->error_out;
  21.690 +  int flags = z->flags;
  21.691 +  memzero(z, sizeof(Parser));
  21.692 +  z->buf_n = sizeof(z->buf) - 1;
  21.693 +  z->buf_i = 0;
  21.694 +  z->line_no = 1;
  21.695 +  z->char_no = 0;
  21.696 +  z->error_out = error_out;
  21.697 +  z->flags = flags;
  21.698 +}
  21.699 +
  21.700 +/** Set the parser error stream.
  21.701 + * Parse errors are reported on the the error stream if it is non-null.
  21.702 + * 
  21.703 + * @param z parser
  21.704 + * @param error_out error stream
  21.705 + */
  21.706 +void set_error_stream(Parser *z, IOStream *error_out){
  21.707 +  if(z){
  21.708 +    z->error_out = error_out;
  21.709 +  }
  21.710 +}
  21.711 +
  21.712 +/** Get the parser error message for an error code.
  21.713 + *
  21.714 + * @param id error code
  21.715 + * @return error message (empty string if the code is unknown)
  21.716 + */
  21.717 +static char *get_message(ParseErrorId id){
  21.718 +  int i;
  21.719 +  for(i=0; i<catalog_n; i++){
  21.720 +    if(id == catalog[i].id){
  21.721 +      return catalog[i].message;
  21.722 +    }
  21.723 +  }
  21.724 +  return "";
  21.725 +}
  21.726 +
  21.727 +/** Get the line number.
  21.728 + *
  21.729 + * @param in parser
  21.730 + */
  21.731 +int get_line(Parser *in){
  21.732 +  return in->line_no;
  21.733 +}
  21.734 +
  21.735 +/** Get the column number.
  21.736 + *
  21.737 + * @param in parser
  21.738 + */
  21.739 +int get_column(Parser *in){
  21.740 +  return in->char_no;
  21.741 +}
  21.742 +
  21.743 +/** Get the line number the current token started on.
  21.744 + *
  21.745 + * @param in parser
  21.746 + */
  21.747 +int get_tok_line(Parser *in){
  21.748 +  return in->tok_begin_line;
  21.749 +}
  21.750 +
  21.751 +/** Get the column number the current token started on.
  21.752 + *
  21.753 + * @param in parser
  21.754 + */
  21.755 +int get_tok_column(Parser *in){
  21.756 +  return in->tok_begin_char;
  21.757 +}
  21.758 +
  21.759 +/** Report a parse error.
  21.760 + * Does nothing if the error stream is null or there is no error.
  21.761 + *
  21.762 + * @param in parser
  21.763 + */
  21.764 +static void report_error(Parser *in){
  21.765 +  if(in->error_out && in->err){
  21.766 +    char *msg = get_message(in->err);
  21.767 +    char *tok = peek_token(in);
  21.768 +    IOStream_print(in->error_out, PARSE_ERR_FMT,
  21.769 +		   get_tok_line(in), get_tok_column(in), msg);
  21.770 +    if(tok && tok[0]){
  21.771 +        IOStream_print(in->error_out, " '%s'", tok);
  21.772 +    }
  21.773 +    IOStream_print(in->error_out, "\n");
  21.774 +  }
  21.775 +}
  21.776 +
  21.777 +/** Get the error message for the current parse error code.
  21.778 + * Does nothing if there is no error.
  21.779 + *
  21.780 + * @param in parser
  21.781 + * @param buf where to place the message
  21.782 + * @param n maximum number of characters to place in buf
  21.783 + * @return current error code (zero for no error)
  21.784 + */
  21.785 +int parse_error_message(Parser *in, char *buf, int n){
  21.786 +    if(in->err){
  21.787 +        char *msg = get_message(in->err);
  21.788 +        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
  21.789 +    }
  21.790 +    return in->err;
  21.791 +}
  21.792 +
  21.793 +/** Flag an unspecified parse error. All subsequent reads will fail.
  21.794 + *
  21.795 + * @param in parser
  21.796 + */
  21.797 +void parse_error(Parser *in){
  21.798 +    parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
  21.799 +}
  21.800 +
  21.801 +/** Flag a parse error. All subsequent reads will fail.
  21.802 + * Does not change the parser error code if it is already set.
  21.803 + *
  21.804 + * @param in parser
  21.805 + * @param id error code
  21.806 + */
  21.807 +void parse_error_id(Parser *in, ParseErrorId id){
  21.808 +    if(!in->err){
  21.809 +        in->err = id;
  21.810 +        report_error(in);
  21.811 +    }
  21.812 +}
  21.813 +
  21.814 +/** Test if the parser's error flag is set.
  21.815 + *
  21.816 + * @param in parser
  21.817 + * @return 1 if set, 0 otherwise
  21.818 + */
  21.819 +int has_error(Parser *in){
  21.820 +    return (in->err > 0);
  21.821 +}
  21.822 +
  21.823 +/** Test if the parser is at end of input.
  21.824 + *
  21.825 + * @param in parser
  21.826 + * @return 1 if at EOF, 0 otherwise
  21.827 + */
  21.828 +int at_eof(Parser *p){
  21.829 +    return p->eof;
  21.830 +}
  21.831 +
  21.832 +#ifdef SXPR_PARSER_MAIN
  21.833 +/* Stuff for standalone testing. */
  21.834 +
  21.835 +#include "file_stream.h"
  21.836 +#include "string_stream.h"
  21.837 +
  21.838 +extern int stringof(Sxpr exp, char **s);
  21.839 +int child_string(Sxpr exp, Sxpr key, char **s){
  21.840 +    int err = 0;
  21.841 +    Sxpr val = sxpr_child_value(exp, key, ONONE);
  21.842 +    err = stringof(val, s);
  21.843 +    return err;
  21.844 +}
  21.845 +
  21.846 +extern int intof(Sxpr exp, int *v);
  21.847 +int child_int(Sxpr exp, Sxpr key, int *v){
  21.848 +    int err = 0;
  21.849 +    Sxpr val = sxpr_child_value(exp, key, ONONE);
  21.850 +    err = intof(val, v);
  21.851 +    return err;
  21.852 +}
  21.853 +
  21.854 +int eval_vnet(Sxpr exp){
  21.855 +    int err = 0;
  21.856 +    Sxpr oid = intern("id");
  21.857 +    int id;
  21.858 +    err = child_int(exp, oid, &id);
  21.859 +    if(err) goto exit;
  21.860 +    dprintf("> vnet id=%d\n", id);
  21.861 + exit:
  21.862 +    dprintf("< err=%d\n", err);
  21.863 +    return err;
  21.864 +}
  21.865 +
  21.866 +int eval_connect(Sxpr exp){
  21.867 +    int err = 0;
  21.868 +    Sxpr ovif = intern("vif");
  21.869 +    Sxpr ovnet = intern("vnet");
  21.870 +    char *vif;
  21.871 +    int vnet;
  21.872 +
  21.873 +    err = child_string(exp, ovif, &vif);
  21.874 +    if(err) goto exit;
  21.875 +    err = child_int(exp, ovnet, &vnet);
  21.876 +    if(err) goto exit;
  21.877 +    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
  21.878 + exit:
  21.879 +    dprintf("< err=%d\n", err);
  21.880 +    return err;
  21.881 +}
  21.882 +
  21.883 +int eval(Sxpr exp){
  21.884 +    int err = 0;
  21.885 +    Sxpr oconnect = intern("connect");
  21.886 +    Sxpr ovnet = intern("vnet");
  21.887 +    
  21.888 +    if(sxpr_elementp(exp, ovnet)){
  21.889 +        err = eval_vnet(exp);
  21.890 +    } else if(sxpr_elementp(exp, oconnect)){
  21.891 +        err = eval_connect(exp);
  21.892 +    } else {
  21.893 +        err = -EINVAL;
  21.894 +    }
  21.895 +    return err;
  21.896 +}
  21.897 +
  21.898 +/** Main program for testing.
  21.899 + * Parses input and prints it.
  21.900 + *
  21.901 + * @param argc number of arguments
  21.902 + * @param argv arguments
  21.903 + * @return error code
  21.904 + */
  21.905 +int main(int argc, char *argv[]){
  21.906 +    Parser *pin;
  21.907 +    int err = 0;
  21.908 +    char buf[1024];
  21.909 +    int k;
  21.910 +    Sxpr obj;
  21.911 +    //Sxpr l, x;
  21.912 +    int i = 0;
  21.913 +
  21.914 +    pin = Parser_new();
  21.915 +    set_error_stream(pin, iostdout);
  21.916 +    dprintf("> parse...\n");
  21.917 +    while(1){
  21.918 +        k = fread(buf, 1, 1, stdin);
  21.919 +        err = Parser_input(pin, buf, k);
  21.920 +        while(Parser_ready(pin)){
  21.921 +            obj = Parser_get_val(pin);
  21.922 +            printf("obj %d\n", i++);
  21.923 +            objprint(iostdout, obj, 0); printf("\n");
  21.924 +        }
  21.925 +        if(k <= 0) break;
  21.926 +    }
  21.927 +/*     obj = Parser_get_all(pin); */
  21.928 +/*     for(l = obj ; CONSP(l); l = CDR(l)){ */
  21.929 +/*         x = CAR(l); */
  21.930 +/*         objprint(iostdout, x, 0); printf("\n"); */
  21.931 +/*         eval(x); */
  21.932 +/*     } */
  21.933 +    dprintf("> err=%d\n", err);
  21.934 +    return 0;
  21.935 +}
  21.936 +#endif
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tools/libxutil/sxpr_parser.h	Wed Nov 24 18:22:43 2004 +0000
    22.3 @@ -0,0 +1,134 @@
    22.4 +/*
    22.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    22.6 + *
    22.7 + * This library is free software; you can redistribute it and/or modify
    22.8 + * it under the terms of the GNU Lesser General Public License as
    22.9 + * published by the Free Software Foundation; either version 2.1 of the
   22.10 + * License, or  (at your option) any later version. This library is 
   22.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   22.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   22.14 + * See the GNU Lesser General Public License for more details.
   22.15 + *
   22.16 + * You should have received a copy of the GNU Lesser General Public License
   22.17 + * along with this library; if not, write to the Free Software Foundation,
   22.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   22.19 + */
   22.20 +
   22.21 +#ifndef _XUTIL_SXPR_PARSER_H_
   22.22 +#define _XUTIL_SXPR_PARSER_H_
   22.23 +
   22.24 +#include "sxpr.h"
   22.25 +#include "iostream.h"
   22.26 +
   22.27 +/** @file
   22.28 + * Sxpr parsing definitions.
   22.29 + */
   22.30 +
   22.31 +/** Size of a parser input buffer.
   22.32 + * Tokens read must fit into this size (including trailing null).
   22.33 + */
   22.34 +#define PARSER_BUF_SIZE 1024
   22.35 +
   22.36 +struct Parser;
   22.37 +typedef int ParserStateFn(struct Parser *, char c);
   22.38 +
   22.39 +typedef struct ParserState {
   22.40 +    struct ParserState *parent;
   22.41 +    Sxpr val;
   22.42 +    int ival;
   22.43 +    int count;
   22.44 +    char delim;
   22.45 +    ParserStateFn *fn;
   22.46 +    char *name;
   22.47 +} ParserState;
   22.48 +
   22.49 +/** Structure representing an input source for the parser.
   22.50 + * Can read from any IOStream implementation.
   22.51 + */
   22.52 +typedef struct Parser {
   22.53 +    Sxpr val;
   22.54 +    /** Error reporting stream (null for no reports). */
   22.55 +    IOStream *error_out;
   22.56 +    int eof;
   22.57 +    /** Error flag. Non-zero if there has been a read error. */
   22.58 +    int err;
   22.59 +    /** Line number on input (from 1). */
   22.60 +    int line_no;
   22.61 +    /** Column number of input (reset on new line). */
   22.62 +    int char_no;
   22.63 +    /** Lookahead character. */
   22.64 +    char c;
   22.65 +    /** Buffer for reading tokens. */
   22.66 +    char buf[PARSER_BUF_SIZE];
   22.67 +    /** Size of token buffer. */
   22.68 +    int buf_n;
   22.69 +    int buf_i;
   22.70 +    /** Line the last token started on. */
   22.71 +    int tok_begin_line;
   22.72 +    /** Character number the last token started on. */
   22.73 +    int tok_begin_char;
   22.74 +    /** Parsing flags. */
   22.75 +    int flags;
   22.76 +    ParserState *state;
   22.77 +    ParserState *start_state;
   22.78 +} Parser;
   22.79 +
   22.80 +/** Parser error codes. */
   22.81 +typedef enum {
   22.82 +    PARSE_ERR_NONE=0,
   22.83 +    PARSE_ERR_UNSPECIFIED,
   22.84 +    PARSE_ERR_NOMEM,
   22.85 +    PARSE_ERR_UNEXPECTED_EOF,
   22.86 +    PARSE_ERR_TOKEN_TOO_LONG,
   22.87 +    PARSE_ERR_INVALID_SYNTAX,
   22.88 +    PARSE_ERR_INVALID_ESCAPE,
   22.89 +} ParseErrorId;
   22.90 +
   22.91 +
   22.92 +/** Parser flags. */
   22.93 +//enum {
   22.94 +//};
   22.95 +
   22.96 +/** Raise some parser flags.
   22.97 + *
   22.98 + * @param in parser
   22.99 + * @param flags flags mask
  22.100 + */
  22.101 +inline static void parser_flags_raise(Parser *in, int flags){
  22.102 +    in->flags |= flags;
  22.103 +}
  22.104 +
  22.105 +/** Lower some parser flags.
  22.106 + *
  22.107 + * @param in parser
  22.108 + * @param flags flags mask
  22.109 + */
  22.110 +inline static void parser_flags_lower(Parser *in, int flags){
  22.111 +    in->flags &= ~flags;
  22.112 +}
  22.113 +
  22.114 +/** Clear all parser flags.
  22.115 + *
  22.116 + * @param in parser
  22.117 + */
  22.118 +inline static void parser_flags_clear(Parser *in){
  22.119 +    in->flags = 0;
  22.120 +}
  22.121 +
  22.122 +extern void Parser_free(Parser *z);
  22.123 +extern Parser * Parser_new(void);
  22.124 +extern int Parser_input(Parser *p, char *buf, int buf_n);
  22.125 +extern int Parser_input_eof(Parser *p);
  22.126 +extern int Parser_input_char(Parser *p, char c);
  22.127 +extern void set_error_stream(Parser *z, IOStream *error_out);
  22.128 +
  22.129 +extern int parse_error_message(Parser *in, char *buf, int n);
  22.130 +extern int has_error(Parser *in);
  22.131 +extern int at_eof(Parser *in);
  22.132 +
  22.133 +int Parser_ready(Parser *p);
  22.134 +Sxpr Parser_get_val(Parser *p);
  22.135 +Sxpr Parser_get_all(Parser *p);
  22.136 +
  22.137 +#endif /* ! _XUTIL_SXPR_PARSER_H_ */
    23.1 --- a/tools/libxutil/sys_net.c	Wed Nov 24 11:51:49 2004 +0000
    23.2 +++ b/tools/libxutil/sys_net.c	Wed Nov 24 18:22:43 2004 +0000
    23.3 @@ -232,21 +232,17 @@ char *get_port_service(unsigned long por
    23.4  int convert_service_to_port(const char *s, unsigned long *port){
    23.5      int err = 0;
    23.6      unsigned long value;
    23.7 -    printf("%s> %s\n", __FUNCTION__, s);
    23.8      if(convert_atoul(s, &value) == 0){
    23.9          int ok = (0 <= value) && (value <= PORT_MAX);
   23.10 -        printf("> value = %ld\n", value);
   23.11          if(ok){
   23.12              value = htons((unsigned short)value);
   23.13          } else {
   23.14              err = -EINVAL;
   23.15          }
   23.16      } else {
   23.17 -        printf("> get_service_port...\n");
   23.18          err = get_service_port(s, &value);
   23.19      }
   23.20      *port = (err ? 0: value);
   23.21 -    printf("%s< err=%d\n", __FUNCTION__, err);
   23.22      return err;
   23.23  }
   23.24  
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/tools/libxutil/util.c	Wed Nov 24 18:22:43 2004 +0000
    24.3 @@ -0,0 +1,106 @@
    24.4 +/*
    24.5 + * Copyright (C) 2002 - 2004 Mike Wray <mike.wray@hp.com>.
    24.6 + *
    24.7 + * This library is free software; you can redistribute it and/or modify
    24.8 + * it under the terms of the GNU Lesser General Public License as
    24.9 + * published by the Free Software Foundation; either version 2.1 of the
   24.10 + * License, or  (at your option) any later version. This library is 
   24.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   24.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   24.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   24.14 + * See the GNU Lesser General Public License for more details.
   24.15 + *
   24.16 + * You should have received a copy of the GNU Lesser General Public License
   24.17 + * along with this library; if not, write to the Free Software Foundation,
   24.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   24.19 + */
   24.20 +
   24.21 +#include "sys_net.h"
   24.22 +#include "sys_string.h"
   24.23 +
   24.24 +#ifndef __KERNEL__
   24.25 +#  include <grp.h>   
   24.26 +#  include <pwd.h>  
   24.27 +#endif
   24.28 +
   24.29 +#include "util.h"
   24.30 +
   24.31 +
   24.32 +/** @file Various utility functions.
   24.33 + */
   24.34 +
   24.35 +/** Print an address (in network order) as an IPv4 address string
   24.36 + * in dot notation.
   24.37 + *
   24.38 + * @param io where to print address
   24.39 + * @param address to print (in network order)
   24.40 + * @return bytes printed
   24.41 + */
   24.42 +int print_address(IOStream *io, unsigned long address){
   24.43 +#ifdef __KERNEL__
   24.44 +    address = ntohl(address);
   24.45 +    return IOStream_print(io, "%u.%u.%u.%u", 
   24.46 +                          (unsigned)((address >> 24) & 0xff),
   24.47 +                          (unsigned)((address >> 16) & 0xff),
   24.48 +                          (unsigned)((address >>  8) & 0xff),
   24.49 +                          (unsigned)((address      ) & 0xff));
   24.50 +#else
   24.51 +    struct in_addr inaddr = { s_addr: address };
   24.52 +    return IOStream_print(io, inet_ntoa(inaddr));
   24.53 +#endif
   24.54 +}
   24.55 +
   24.56 +/** Get the protocol number for a protocol.
   24.57 + *
   24.58 + * @param name protocol name
   24.59 + * @param protocol where to put the protocol number
   24.60 + * @return 0 if OK, error otherwise
   24.61 + */  
   24.62 +int get_protocol_number(char *name, unsigned long *protocol){
   24.63 +#ifdef __KERNEL__
   24.64 +    return -1;
   24.65 +#else
   24.66 +    struct protoent *proto = getprotobyname(name);
   24.67 +    if(!proto){
   24.68 +	return -1;
   24.69 +    }
   24.70 +    *protocol = proto->p_proto;
   24.71 +    return 0;
   24.72 +#endif
   24.73 +}
   24.74 +
   24.75 +/** Get the protocol name for a protocol number.
   24.76 + *
   24.77 + * @param protocol number
   24.78 + * @return name or null
   24.79 + */
   24.80 +char *get_protocol_name(unsigned long protocol){
   24.81 +#ifdef __KERNEL__
   24.82 +    return 0;
   24.83 +#else
   24.84 +    struct protoent *proto = getprotobynumber(protocol);
   24.85 +    if(!proto){
   24.86 +	return 0;
   24.87 +    }
   24.88 +    return proto->p_name;
   24.89 +#endif
   24.90 +}
   24.91 +
   24.92 +/** Get the host name for an address.
   24.93 + *
   24.94 + * @param addr address
   24.95 + * @return host name or null
   24.96 + */
   24.97 +char *get_host_name(unsigned long addr){
   24.98 +#ifdef __KERNEL__
   24.99 +    return 0;
  24.100 +#else
  24.101 +    struct in_addr inaddr;
  24.102 +    struct hostent *host = 0;
  24.103 +
  24.104 +    inaddr.s_addr = addr;
  24.105 +    host = gethostbyaddr((char*)&inaddr, sizeof(inaddr), AF_INET);
  24.106 +    if(!host) return NULL;
  24.107 +    return host->h_name;
  24.108 +#endif
  24.109 +}
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/tools/libxutil/util.h	Wed Nov 24 18:22:43 2004 +0000
    25.3 @@ -0,0 +1,28 @@
    25.4 +/*
    25.5 + * Copyright (C) 2002 - 2004 Mike Wray <mike.wray@hp.com>.
    25.6 + *
    25.7 + * This library is free software; you can redistribute it and/or modify
    25.8 + * it under the terms of the GNU Lesser General Public License as
    25.9 + * published by the Free Software Foundation; either version 2.1 of the
   25.10 + * License, or  (at your option) any later version. This library is 
   25.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   25.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   25.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   25.14 + * See the GNU Lesser General Public License for more details.
   25.15 + *
   25.16 + * You should have received a copy of the GNU Lesser General Public License
   25.17 + * along with this library; if not, write to the Free Software Foundation,
   25.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   25.19 + */
   25.20 +
   25.21 +#ifndef _XEN_LIB_UTIL_H_
   25.22 +#define _XEN_LIB_UTIL_H_
   25.23 +
   25.24 +#include "iostream.h"
   25.25 +
   25.26 +extern int print_address(IOStream *io, unsigned long address);
   25.27 +extern int get_protocol_number(char *name, unsigned long *protocol);
   25.28 +extern char *get_protocol_name(unsigned long protocol);
   25.29 +extern char *get_host_name(unsigned long addr);
   25.30 +
   25.31 +#endif /* ! _XEN_LIB_UTIL_H_ */
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/tools/vnet/00README	Wed Nov 24 18:22:43 2004 +0000
    26.3 @@ -0,0 +1,10 @@
    26.4 +This directory contains the implementation of vnets:
    26.5 +virtual private networks for virtual machines.
    26.6 +See doc/ for more information and examples/ for example
    26.7 +configurations.
    26.8 +
    26.9 +The kernel module is in vnet-module/ and the vnet forwarding
   26.10 +daemon is in vnetd/. The vnetd daemon makes vnets work across
   26.11 +subnets when multicast routing is not available.
   26.12 +
   26.13 +Mike Wray <mike.wray@hp.com>
   26.14 \ No newline at end of file
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/tools/vnet/Makefile	Wed Nov 24 18:22:43 2004 +0000
    27.3 @@ -0,0 +1,42 @@
    27.4 +
    27.5 +export LINUX_RELEASE ?=2.6
    27.6 +
    27.7 +all: compile
    27.8 +
    27.9 +compile: vnetd vnet-module
   27.10 +
   27.11 +gc.tar.gz:
   27.12 +	wget http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/$@
   27.13 +
   27.14 +gc: gc.tar.gz
   27.15 +	tar xfz gc.tar.gz
   27.16 +	ln -sf gc?.? gc
   27.17 +
   27.18 +gc-install: gc
   27.19 +	(cd gc && ./configure --prefix=`pwd`/install && make && make install)
   27.20 +
   27.21 +gc-clean:
   27.22 +	-$(MAKE) -C gc clean
   27.23 +
   27.24 +gc-pristine:
   27.25 +	-rm -rf gc?.? gc
   27.26 +
   27.27 +.PHONY: vnetd vnet-module install dist clean
   27.28 +
   27.29 +vnetd: gc-install
   27.30 +	$(MAKE) -C vnetd
   27.31 +
   27.32 +vnet-module:
   27.33 +	$(MAKE) -C vnet-module
   27.34 +
   27.35 +install: compile
   27.36 +	$(MAKE) -C vnetd install
   27.37 +	$(MAKE) -C vnet-module install
   27.38 +	$(MAKE) -C examples install
   27.39 +
   27.40 +dist: $(TARGET)
   27.41 +	$(MAKE) prefix=`pwd`/../../install dist=yes install
   27.42 +
   27.43 +clean:
   27.44 +	-$(MAKE) -C vnetd clean
   27.45 +	-$(MAKE) -C vnet-module clean
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/vnet/doc/vnet-module.txt	Wed Nov 24 18:22:43 2004 +0000
    28.3 @@ -0,0 +1,50 @@
    28.4 +Vnet Module Command Interface
    28.5 +Mike Wray <mike.wray@hp.com>
    28.6 +2004/09/17
    28.7 +
    28.8 +When insmod the vnet-module creates /proc/vnet/policy which
    28.9 +can be used to control the module by writing commands into it.
   28.10 +The return code from the command should be returned by close.
   28.11 +
   28.12 +The commands are:
   28.13 +
   28.14 +(vnet.add (id <id>) [(security { none | auth | conf } )] )
   28.15 +
   28.16 +Create the vnet with id <id> and the given security level (default none).
   28.17 +Security levels:
   28.18 +- none: no security
   28.19 +- auth: message authentication (IPSEC hmac)
   28.20 +- conf: message confidentiality (IPSEC hmac and encryption)
   28.21 +
   28.22 +(vnet.del (id <id>))
   28.23 +
   28.24 +Delete the vnet with id <id>.
   28.25 +
   28.26 +(vif.add (vnet <vnetid>) (vmac <macaddr>))
   28.27 +
   28.28 +Add the vif with MAC address <macaddr> to the vnet with id <vnetid>.
   28.29 +This makes the vnet module respond to VARP requests for <macaddr>
   28.30 +on vnet <vnetid>.
   28.31 +
   28.32 +(vif.del (vnet <vnetid>) (vmac <macaddr>))
   28.33 +
   28.34 +Remove the vif with MAC address <macaddr> from the vnet with id <vnetid>.
   28.35 +The vnet module will stop responding to VARP for the vif.
   28.36 +
   28.37 +Examples:
   28.38 +
   28.39 +To create vnet 10 with no security:
   28.40 +
   28.41 +echo '(vnet.add (id 10))' > /proc/vnet/policy
   28.42 +
   28.43 +To create vnet 11 with message authentication:
   28.44 +
   28.45 +echo '(vnet.add (id 11) (security auth))' > /proc/vnet/policy
   28.46 +
   28.47 +To add the vif with vmac "aa:00:00:bc:34:ae" to vnet 10:
   28.48 +
   28.49 +echo '(vif.add (vnet 10) (vmac aa:00:00:bc:34:ae))' > /proc/vnet/policy
   28.50 +
   28.51 +To remove the vif from the vnet:
   28.52 +
   28.53 +echo '(vif.del (vnet 10) (vmac aa:00:00:bc:34:ae))' > /proc/vnet/policy
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/tools/vnet/doc/vnet-xend.txt	Wed Nov 24 18:22:43 2004 +0000
    29.3 @@ -0,0 +1,140 @@
    29.4 +
    29.5 +Vnets: Virtual Networks for Virtual Machines
    29.6 +
    29.7 +Mike Wray <mike.wray@hp.com>
    29.8 +
    29.9 +0) Introduction
   29.10 +---------------
   29.11 +
   29.12 +Vnets provide virtual private LANs for virtual machines.
   29.13 +This is done using bridging and tunneling. A virtual interface
   29.14 +on a vnet can only see other interfaces on the same vnet - it cannot
   29.15 +see the real network, and the real network cannot see it either.
   29.16 +
   29.17 +Virtual interfaces on the same vnet can be on the same machine
   29.18 +or on different machines, they can still talk. The hosting machines
   29.19 +can even be on different subnets if you run vnetd to forward,
   29.20 +or have multicast routing enabled.
   29.21 +
   29.22 +
   29.23 +1) Installing vnet support
   29.24 +--------------------------
   29.25 +
   29.26 +Assuming the code has been installed (make install in the parent directory),
   29.27 +configure xend to use 'network-vnet' instead of the default 'network' to
   29.28 +start up networking. This just loads the vnet module when networking starts.
   29.29 +
   29.30 +In /etc/xend/xend-config.sxp:
   29.31 +
   29.32 +Configure the network script:
   29.33 +
   29.34 +(network-script        network-vnet)
   29.35 +
   29.36 +Restart xend.
   29.37 +
   29.38 +2) Creating vnets
   29.39 +-----------------
   29.40 +
   29.41 +Xend already implements commands to add/remove vnets and
   29.42 +bridge to them. To add a vnet use
   29.43 +
   29.44 +xm call vnet_add <vnet config file>
   29.45 +
   29.46 +For example, if vnet97.sxp contains:
   29.47 +
   29.48 +(vnet (id 97) (bridge vnet97) (vnetif vnetif97) (security none))
   29.49 +
   29.50 +do
   29.51 +
   29.52 +xm call vnet_add vnet97.sxp
   29.53 +
   29.54 +This will define a vnet with id 97 and no security. The bridge for the
   29.55 +vnet is called vnet97 and the virtual interface for it is vnetif97.
   29.56 +To add an interface on a vm to this vnet simply set its bridge to vnet97
   29.57 +in its configuration.
   29.58 +
   29.59 +In Python:
   29.60 +
   29.61 +vif="bridge=vnet97"
   29.62 +
   29.63 +In sxp:
   29.64 +
   29.65 +(dev (vif (mac aa:00:00:01:02:03) (bridge vnet97)))
   29.66 +
   29.67 +Once configured, vnets are persistent in the xend database.
   29.68 +To remove a vnet use
   29.69 +
   29.70 +xm call vnet_delete <vnet id>
   29.71 +
   29.72 +To list vnets use
   29.73 +
   29.74 +xm call vnets
   29.75 +
   29.76 +To get information on a vnet id use
   29.77 +
   29.78 +xm call vnet <vnet id>
   29.79 +
   29.80 +3) Troubleshooting
   29.81 +------------------
   29.82 +
   29.83 +The vnet module should appear in 'lsmod'.
   29.84 +If a vnet has been configured it should appear in the output of 'xm call vnets'.
   29.85 +Its bridge and interface should appear in 'ifconfig'.
   29.86 +It should also show in 'brctl show', with its attached interfaces.
   29.87 +
   29.88 +You can 'see into' a vnet from dom0 if you put an IP address on the bridge.
   29.89 +For example, if you have vnet97 with a vm with ip addr 10.0.0.12 on it,
   29.90 +then
   29.91 +
   29.92 +ifconfig vnet97 10.0.0.20 up
   29.93 +
   29.94 +should let you ping 10.0.0.12 via the vnet97 bridge.
   29.95 +
   29.96 +4) Examples
   29.97 +-----------
   29.98 +
   29.99 +Here's the full config for a vm on vnet 97, using ip addr 10.0.0.12:
  29.100 +
  29.101 +(vm
  29.102 + (name dom12)
  29.103 + (memory '64')
  29.104 + (cpu '1')
  29.105 + (console '8502')
  29.106 + (image
  29.107 +  (linux
  29.108 +   (kernel /boot/vmlinuz-2.6.9-xenU)
  29.109 +   (ip 10.0.0.12:1.2.3.4::::eth0:off)
  29.110 +   (root /dev/hda1)
  29.111 +   (args 'rw fastboot 4')
  29.112 +  )
  29.113 + )
  29.114 + (device (vbd (uname phy:hda2) (dev hda1) (mode w)))
  29.115 + (device (vif (mac aa:00:00:11:00:12) (bridge vnet97)))
  29.116 +)
  29.117 +
  29.118 +If you run another vm on the same vnet:
  29.119 +
  29.120 +(vm
  29.121 + (name dom11)
  29.122 + (memory '64')
  29.123 + (cpu '1')
  29.124 + (console '8501')
  29.125 + (image
  29.126 +  (linux
  29.127 +   (kernel /boot/vmlinuz-2.6.9-xenU)
  29.128 +   (ip 10.0.0.11:1.2.3.4::::eth0:off)
  29.129 +   (root /dev/hda1)
  29.130 +   (args 'rw fastboot 4')
  29.131 +  )
  29.132 + )
  29.133 + (device (vbd (uname phy:hda3) (dev hda1) (mode w)))
  29.134 + (device (vif (mac aa:00:00:11:00:11) (bridge vnet97)))
  29.135 +)
  29.136 +
  29.137 +the vms should be able to talk over the vnet. Check with ping.
  29.138 +If they are both on the same machine the connection will simply
  29.139 +be the vnet97 bridge, if they are on separate machines their
  29.140 +packets will be tunneled in etherip. They should be able to
  29.141 +see each other, but not the real network.
  29.142 +
  29.143 +
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/tools/vnet/examples/Makefile	Wed Nov 24 18:22:43 2004 +0000
    30.3 @@ -0,0 +1,12 @@
    30.4 +# -*- mode: Makefile; -*-
    30.5 +#============================================================================
    30.6 +
    30.7 +XEN_SCRIPT_DIR:=/etc/xen/scripts
    30.8 +
    30.9 +all:
   30.10 +
   30.11 +install:
   30.12 +	install -m 0755 -d $(prefix)$(XEN_SCRIPT_DIR)
   30.13 +	install -m 0554 network-vnet $(prefix)$(XEN_SCRIPT_DIR)
   30.14 +
   30.15 +clean:
   30.16 \ No newline at end of file
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/tools/vnet/examples/network-vnet	Wed Nov 24 18:22:43 2004 +0000
    31.3 @@ -0,0 +1,218 @@
    31.4 +#!/bin/sh
    31.5 +#============================================================================
    31.6 +# Default Xen network start/stop script.
    31.7 +# Xend calls a network script when it starts.
    31.8 +# The script name to use is defined in /etc/xen/xend-config.sxp
    31.9 +# in the network-script field.
   31.10 +#
   31.11 +# This script creates a bridge (default xen-br0), adds a device
   31.12 +# (default eth0) to it, copies the IP addresses from the device
   31.13 +# to the bridge and adjusts the routes accordingly.
   31.14 +#
   31.15 +# If all goes well, this should ensure that networking stays up.
   31.16 +# However, some configurations are upset by this, especially
   31.17 +# NFS roots. If the bridged setup does not meet your needs,
   31.18 +# configure a different script, for example using routing instead.
   31.19 +#
   31.20 +# Usage:
   31.21 +#
   31.22 +# network (start|stop|status) {VAR=VAL}*
   31.23 +#
   31.24 +# Vars:
   31.25 +#
   31.26 +# bridge     The bridge to use (default xen-br0).
   31.27 +# netdev     The interface to add to the bridge (default eth0).
   31.28 +# antispoof  Whether to use iptables to prevent spoofing (default yes).
   31.29 +#
   31.30 +# start:
   31.31 +# Creates the bridge and enslaves netdev to it.
   31.32 +# Copies the IP addresses from netdev to the bridge.
   31.33 +# Deletes the routes to netdev and adds them on bridge.
   31.34 +#
   31.35 +# stop:
   31.36 +# Removes netdev from the bridge.
   31.37 +# Deletes the routes to bridge and adds them to netdev.
   31.38 +#
   31.39 +# status:
   31.40 +# Print ifconfig for netdev and bridge.
   31.41 +# Print routes.
   31.42 +#
   31.43 +#============================================================================
   31.44 +
   31.45 +# Exit if anything goes wrong.
   31.46 +set -e 
   31.47 +
   31.48 +# First arg is the operation.
   31.49 +OP=$1
   31.50 +shift
   31.51 +
   31.52 +# Pull variables in args in to environment.
   31.53 +for arg ; do export "${arg}" ; done
   31.54 +
   31.55 +bridge=${bridge:-xen-br0}
   31.56 +netdev=${netdev:-eth0}
   31.57 +antispoof=${antispoof:-yes}
   31.58 +
   31.59 +echo "network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof"
   31.60 +
   31.61 +# Usage: transfer_addrs src dst
   31.62 +# Copy all IP addresses (including aliases) from device $src to device $dst.
   31.63 +transfer_addrs () {
   31.64 +    local src=$1
   31.65 +    local dst=$2
   31.66 +    # Don't bother if $dst already has IP addresses.
   31.67 +    if ip addr show dev ${dst} | egrep -q '^ *inet' ; then
   31.68 +        return
   31.69 +    fi
   31.70 +    # Address lines start with 'inet' and have the device in them.
   31.71 +    # Replace 'inet' with 'ip addr add' and change the device name $src
   31.72 +    # to 'dev $src'. Remove netmask as we'll add routes later.
   31.73 +    ip addr show dev ${src} | egrep '^ *inet' | sed -e "
   31.74 +s/inet/ip addr add/
   31.75 +s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)/[0-9]\+@\1@
   31.76 +s/${src}/dev ${dst}/
   31.77 +" | sh -e
   31.78 +}
   31.79 +
   31.80 +# Usage: transfer_routes src dst
   31.81 +# Get all IP routes to device $src, delete them, and
   31.82 +# add the same routes to device $dst.
   31.83 +# The original routes have to be deleted, otherwise adding them
   31.84 +# for $dst fails (duplicate routes).
   31.85 +transfer_routes () {
   31.86 +    local src=$1
   31.87 +    local dst=$2
   31.88 +    # List all routes and grep the ones with $src in.
   31.89 +    # Stick 'ip route del' on the front to delete.
   31.90 +    # Change $src to $dst and use 'ip route add' to add.
   31.91 +    ip route list | grep ${src} | sed -e "
   31.92 +h
   31.93 +s/^/ip route del /
   31.94 +P
   31.95 +g
   31.96 +s/${src}/${dst}/
   31.97 +s/^/ip route add /
   31.98 +P
   31.99 +d
  31.100 +" | sh -e
  31.101 +}
  31.102 +
  31.103 +# Usage: create_bridge dev bridge
  31.104 +# Create bridge $bridge and add device $dev to it.
  31.105 +create_bridge () {
  31.106 +    local dev=$1
  31.107 +    local bridge=$2
  31.108 +
  31.109 +    # Don't create the bridge if it already exists.
  31.110 +    if ! brctl show | grep -q ${bridge} ; then
  31.111 +        brctl addbr ${bridge}
  31.112 +        brctl stp ${bridge} off
  31.113 +        brctl setfd ${bridge} 0
  31.114 +    fi
  31.115 +    ifconfig ${bridge} up
  31.116 +}
  31.117 +
  31.118 +# Usage: antispoofing dev bridge
  31.119 +# Set the default forwarding policy for $dev to drop.
  31.120 +# Allow forwarding to the bridge.
  31.121 +antispoofing () {
  31.122 +    local dev=$1
  31.123 +    local bridge=$2
  31.124 +
  31.125 +    iptables -P FORWARD DROP
  31.126 +    iptables -A FORWARD -m physdev --physdev-in ${dev} -j ACCEPT
  31.127 +}
  31.128 +
  31.129 +# Usage: show_status dev bridge
  31.130 +# Print ifconfig and routes.
  31.131 +show_status () {
  31.132 +    local dev=$1
  31.133 +    local bridge=$2
  31.134 +    
  31.135 +    echo '============================================================'
  31.136 +    ifconfig ${dev}
  31.137 +    ifconfig ${bridge}
  31.138 +    echo ' '
  31.139 +    ip route list
  31.140 +    echo ' '
  31.141 +    route -n
  31.142 +    echo '============================================================'
  31.143 +}
  31.144 +
  31.145 +# Insert the vnet module if it can be found and
  31.146 +# it's not already there.
  31.147 +vnet_insert () {
  31.148 +    local module="vnet_module"
  31.149 +    local mod_dir=/lib/modules/$(uname -r)/kernel
  31.150 +    local mod_path="${mod_dir}/${module}"
  31.151 +    local mod_obj=""
  31.152 +
  31.153 +    for ext in ".o" ".ko" ; do
  31.154 +        f=${mod_path}${ext}
  31.155 +        if [ -f ${f} ] ; then
  31.156 +            mod_obj=$f
  31.157 +            break
  31.158 +        fi
  31.159 +    done
  31.160 +    if [ "${mod_obj}" == "" ] ; then
  31.161 +        return
  31.162 +    fi
  31.163 +    if lsmod | grep -q ${module} ; then
  31.164 +        echo "VNET: ${module} loaded"
  31.165 +    else
  31.166 +        echo "VNET: Loading ${module}..."
  31.167 +               insmod ${mod_obj}
  31.168 +    fi
  31.169 +}
  31.170 +
  31.171 +op_start () {
  31.172 +    if [ "${bridge}" == "null" ] ; then
  31.173 +        return
  31.174 +    fi
  31.175 +    # Create the bridge and give it the interface IP addresses.
  31.176 +    # Move the interface routes onto the bridge.
  31.177 +    create_bridge ${netdev} ${bridge}
  31.178 +    transfer_addrs ${netdev} ${bridge}
  31.179 +    transfer_routes ${netdev} ${bridge}
  31.180 +    # Don't add $dev to $bridge if it's already on a bridge.
  31.181 +    if ! brctl show | grep -q ${netdev} ; then
  31.182 +        brctl addif ${bridge} ${netdev}
  31.183 +    fi
  31.184 +    
  31.185 +    if [ ${antispoof} == 'yes' ] ; then
  31.186 +        antispoofing ${netdev} ${bridge}
  31.187 +    fi
  31.188 +
  31.189 +    vnet_insert
  31.190 +}
  31.191 +
  31.192 +op_stop () {
  31.193 +    if [ "${bridge}" == "null" ] ; then
  31.194 +        return
  31.195 +    fi
  31.196 +    # Remove the interface from the bridge.
  31.197 +    # Move the routes back to the interface.
  31.198 +    brctl delif ${bridge} ${netdev}
  31.199 +    transfer_routes ${bridge} ${netdev}
  31.200 +
  31.201 +    # It's not our place to be enabling forwarding...
  31.202 +}
  31.203 +
  31.204 +case ${OP} in
  31.205 +    start)
  31.206 +        op_start
  31.207 +        ;;
  31.208 +    
  31.209 +    stop)
  31.210 +        op_stop
  31.211 +        ;;
  31.212 +
  31.213 +    status)
  31.214 +        show_status ${netdev} ${bridge}
  31.215 +       ;;
  31.216 +
  31.217 +    *)
  31.218 +       echo 'Unknown command: ' ${OP}
  31.219 +       echo 'Valid commands are: start, stop, status'
  31.220 +       exit 1
  31.221 +esac
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/tools/vnet/examples/vnet97.sxp	Wed Nov 24 18:22:43 2004 +0000
    32.3 @@ -0,0 +1,3 @@
    32.4 +# Vnet configuration for a vnet with id 97 and no security.
    32.5 +# Configure using 'xm call vnet_add vnet97.sxp'.
    32.6 +(vnet (id 97) (bridge vnet97) (vnetif vnetif97) (security none))
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/tools/vnet/examples/vnet98.sxp	Wed Nov 24 18:22:43 2004 +0000
    33.3 @@ -0,0 +1,3 @@
    33.4 +# Vnet configuration for a vnet with id 98 and message authentication.
    33.5 +# Configure using 'xm call vnet_add vnet98.sxp'.
    33.6 +(vnet (id 98) (bridge vnet98) (vnetif vnetif98) (security auth))
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/tools/vnet/examples/vnet99.sxp	Wed Nov 24 18:22:43 2004 +0000
    34.3 @@ -0,0 +1,3 @@
    34.4 +# Vnet configuration for a vnet with id 99 and message confidentiality.
    34.5 +# Configure using 'xm call vnet_add vnet99.sxp'.
    34.6 +(vnet (id 99) (bridge vnet99) (vnetif vnetif99) (security conf))
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/tools/vnet/vnet-module/00README	Wed Nov 24 18:22:43 2004 +0000
    35.3 @@ -0,0 +1,41 @@
    35.4 +Vnet module for network virtualization.
    35.5 +Mike Wray <mike.wray@hp.com>
    35.6 +
    35.7 +*) Compiling
    35.8 +The vnet module can be compiled for 2.4 or 2.6 series kernels.
    35.9 +The makefiles  use the following variables, which
   35.10 +can be set in your env or on the make command line:
   35.11 +
   35.12 +LINUX_RELEASE: linux release to compile for, 2.4 (default), or 2.6.
   35.13 +XENO_ROOT: root of the xen tree containing kernel source. Default '..'.
   35.14 +ROOT: root path to install in, default is XENO_ROOT/install.
   35.15 +      Set to '/' to install relative to filesystem root.
   35.16 +KERNEL_VERSION: kernel version, default got from XENO_ROOT.
   35.17 +KERNEL_MINOR: kernel minor version, default -xen0.
   35.18 +KERNEL_SRC: path to kernel source, default linux-<VERSION> under XENO_ROOT.
   35.19 +
   35.20 +*) For 2.4 kernel
   35.21 +
   35.22 +To compile from scratch:
   35.23 +
   35.24 +make clean
   35.25 +make 
   35.26 +
   35.27 +This will build vnet_module.o in the current directory.
   35.28 +To install the module use
   35.29 +
   35.30 +make install
   35.31 +
   35.32 +*) For 2.6 kernel
   35.33 +
   35.34 +To compile from scratch:
   35.35 +
   35.36 +make clean
   35.37 +make LINUX_RELEASE=2.6
   35.38 +
   35.39 +This will build vnet_module.ko in the current directory.
   35.40 +To install the module use
   35.41 +
   35.42 +make LINUX_RELEASE=2.6 install
   35.43 +
   35.44 +
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/tools/vnet/vnet-module/Makefile	Wed Nov 24 18:22:43 2004 +0000
    36.3 @@ -0,0 +1,67 @@
    36.4 +# -*- mode: Makefile; -*-
    36.5 +#============================================================================
    36.6 +#
    36.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    36.8 +#
    36.9 +# This program is free software; you can redistribute it and/or modify
   36.10 +# it under the terms of the GNU General Public License as published by the
   36.11 +# Free Software Foundation; either version 2 of the License, or (at your
   36.12 +# option) any later version.
   36.13 +#
   36.14 +# This program is distributed in the hope that it will be useful, but
   36.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   36.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   36.17 +# for more details.
   36.18 +#
   36.19 +# You should have received a copy of the GNU General Public License along
   36.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   36.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   36.22 +#============================================================================
   36.23 +
   36.24 +#============================================================================
   36.25 +ifeq ($(src),)
   36.26 +LINUX_RELEASE ?=2.6
   36.27 +
   36.28 +include Makefile-$(LINUX_RELEASE)
   36.29 +
   36.30 +#============================================================================
   36.31 +else
   36.32 +#============================================================================
   36.33 +# This section is for the 2.6 kbuild.
   36.34 +
   36.35 +#$(warning KBUILD_EXTMOD $(KBUILD_EXTMOD))
   36.36 +#$(warning src $(src))
   36.37 +#$(warning obj $(obj))
   36.38 +
   36.39 +include $(src)/Makefile.vnet
   36.40 +
   36.41 +obj-m = vnet_module.o
   36.42 +vnet_module-objs = $(VNET_OBJ)
   36.43 +vnet_module-objs += $(VNET_LIB_OBJ)
   36.44 +
   36.45 +#----------------------------------------------------------------------------
   36.46 +# The fancy stuff in the kernel build defeats 'vpath %.c' so we can't
   36.47 +# use that to get the lib files compiled.
   36.48 +# Setup explicit rules for them using the kbuild C compile rule.
   36.49 +
   36.50 +# File names in the lib dir.
   36.51 +remote_srcs = $(foreach file,$(VNET_LIB_SRC),$(LIB_DIR)/$(file))
   36.52 +
   36.53 +# Equivalent file names here.
   36.54 +local_srcs = $(foreach file,$(VNET_LIB_SRC),$(src)/$(file))
   36.55 +
   36.56 +# Objects for the local names.
   36.57 +local_objs = $(local_srcs:.c=.o)
   36.58 +
   36.59 +# Make the local objects depend on compiling the remote sources.
   36.60 +$(local_objs): $(src)/%.o: $(LIB_DIR)/%.c
   36.61 +	$(call if_changed_rule,cc_o_c)
   36.62 +#----------------------------------------------------------------------------
   36.63 +
   36.64 +vpath %.h $(LIB_DIR)
   36.65 +EXTRA_CFLAGS += -I $(LIB_DIR)
   36.66 +EXTRA_CFLAGS += -I $(src)
   36.67 +
   36.68 +endif
   36.69 +#============================================================================
   36.70 +
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/tools/vnet/vnet-module/Makefile-2.4	Wed Nov 24 18:22:43 2004 +0000
    37.3 @@ -0,0 +1,97 @@
    37.4 +# -*- mode: Makefile; -*-
    37.5 +#============================================================================
    37.6 +#
    37.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    37.8 +#
    37.9 +# This program is free software; you can redistribute it and/or modify
   37.10 +# it under the terms of the GNU General Public License as published by the
   37.11 +# Free Software Foundation; either version 2 of the License, or (at your
   37.12 +# option) any later version.
   37.13 +#
   37.14 +# This program is distributed in the hope that it will be useful, but
   37.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   37.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   37.17 +# for more details.
   37.18 +#
   37.19 +# You should have received a copy of the GNU General Public License along
   37.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   37.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   37.22 +#============================================================================
   37.23 +
   37.24 +#============================================================================
   37.25 +# Vnet module makefile for 2.4 series kernels.
   37.26 +
   37.27 +include Makefile.ver
   37.28 +
   37.29 +KERNEL_MODULE := vnet_module.o
   37.30 +
   37.31 +CONFIG_MODVERSIONS := $(shell grep 'CONFIG_MODVERSIONS=y' $(KERNEL_SRC)/.config && echo 1 || echo 0)
   37.32 +
   37.33 +include Makefile.vnet
   37.34 +
   37.35 +VNET_OBJ += $(VNET_LIB_OBJ)
   37.36 +
   37.37 +#----------------------------------------------------------------------------
   37.38 +
   37.39 +vpath %.h $(KERNEL_SRC)/include
   37.40 +INCLUDES+= -I $(KERNEL_SRC)/include
   37.41 +
   37.42 +vpath %.h $(LIB_DIR)
   37.43 +vpath %.c $(LIB_DIR)
   37.44 +INCLUDES += -I $(LIB_DIR)
   37.45 +
   37.46 +INCLUDES+= -I .
   37.47 +
   37.48 +#----------------------------------------------------------------------------
   37.49 +
   37.50 +CPPFLAGS += -D__KERNEL__
   37.51 +CPPFLAGS += -DMODULE
   37.52 +
   37.53 +ifeq ($(CONFIG_MODVERSIONS), 1)
   37.54 +CPPFLAGS += -DMODVERSIONS
   37.55 +CPPFLAGS += -include $(KERNEL_SRC)/include/linux/modversions.h
   37.56 +endif
   37.57 +
   37.58 +CPPFLAGS += $(INCLUDES)
   37.59 +
   37.60 +CFLAGS += -Wall
   37.61 +CFLAGS += -Wstrict-prototypes
   37.62 +CFLAGS += -Wno-trigraphs
   37.63 +CFLAGS += -Wno-unused-function
   37.64 +CFLAGS += -Wno-unused-parameter 
   37.65 +
   37.66 +CFLAGS += -g
   37.67 +CFLAGS += -O2
   37.68 +CFLAGS += -fno-strict-aliasing 
   37.69 +CFLAGS += -fno-common 
   37.70 +#CFLAGS += -fomit-frame-pointer
   37.71 +
   37.72 +# Dependencies. Gcc generates them for us.
   37.73 +CFLAGS += -Wp,-MD,.$(@F).d
   37.74 +VNET_DEP = .*.d
   37.75 +#----------------------------------------------------------------------------
   37.76 +
   37.77 +.PHONY: all
   37.78 +all: module
   37.79 +
   37.80 +.PHONY: module modules
   37.81 +module modules: $(KERNEL_MODULE)
   37.82 +
   37.83 +$(KERNEL_MODULE): $(VNET_OBJ)
   37.84 +	$(LD) -r -o $@ $^
   37.85 +
   37.86 +.PHONY: install install-module modules_install
   37.87 +install install-module modules_install: module
   37.88 +	install -m 0755 -d $(prefix)$(KERNEL_MODULE_DIR)
   37.89 +	install -m 0554 $(KERNEL_MODULE) $(prefix)$(KERNEL_MODULE_DIR)
   37.90 +
   37.91 +TAGS:
   37.92 +	etags *.c *.h
   37.93 +
   37.94 +.PHONY: clean
   37.95 +clean:
   37.96 +	@rm -f *.a *.o *.ko *~
   37.97 +	@rm -f $(VNET_DEP) .*.cmd *.mod.?
   37.98 +	@rm -rf .tmp_versions
   37.99 +
  37.100 +-include $(VNET_DEP)
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/tools/vnet/vnet-module/Makefile-2.6	Wed Nov 24 18:22:43 2004 +0000
    38.3 @@ -0,0 +1,51 @@
    38.4 +# -*- mode: Makefile; -*-
    38.5 +#============================================================================
    38.6 +#
    38.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    38.8 +#
    38.9 +# This program is free software; you can redistribute it and/or modify
   38.10 +# it under the terms of the GNU General Public License as published by the
   38.11 +# Free Software Foundation; either version 2 of the License, or (at your
   38.12 +# option) any later version.
   38.13 +#
   38.14 +# This program is distributed in the hope that it will be useful, but
   38.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   38.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   38.17 +# for more details.
   38.18 +#
   38.19 +# You should have received a copy of the GNU General Public License along
   38.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   38.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   38.22 +#============================================================================
   38.23 +
   38.24 +#============================================================================
   38.25 +# Vnet module makefile for 2.6 series kernels.
   38.26 +
   38.27 +LINUX_RELEASE ?= 2.6
   38.28 +include Makefile.ver
   38.29 +
   38.30 +KERNEL_MODULE = vnet_module.ko
   38.31 +
   38.32 +#----------------------------------------------------------------------------
   38.33 +#export KBUILD_VERBOSE=1
   38.34 +
   38.35 +.PHONY: all
   38.36 +all: module
   38.37 +
   38.38 +.PHONY: module
   38.39 +module modules:
   38.40 +	$(MAKE) -C $(KERNEL_SRC) M=`pwd` modules
   38.41 +
   38.42 +.PHONY: install install-module modules_install
   38.43 +install install-module modules_install: module
   38.44 +	install -m 0755 -d $(prefix)$(KERNEL_MODULE_DIR)
   38.45 +	install -m 0554 $(KERNEL_MODULE) $(prefix)$(KERNEL_MODULE_DIR)
   38.46 +
   38.47 +.PHONY: clean
   38.48 +clean:
   38.49 +	@$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
   38.50 +	@rm -f *.a *.o *.ko *~ .*.d .*.cmd *.mod.?
   38.51 +
   38.52 +TAGS:
   38.53 +	etags *.c *.h
   38.54 +
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/tools/vnet/vnet-module/Makefile.ver	Wed Nov 24 18:22:43 2004 +0000
    39.3 @@ -0,0 +1,49 @@
    39.4 +# -*- mode: Makefile; -*-
    39.5 +#============================================================================
    39.6 +#
    39.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    39.8 +#
    39.9 +# This program is free software; you can redistribute it and/or modify
   39.10 +# it under the terms of the GNU General Public License as published by the
   39.11 +# Free Software Foundation; either version 2 of the License, or (at your
   39.12 +# option) any later version.
   39.13 +#
   39.14 +# This program is distributed in the hope that it will be useful, but
   39.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   39.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   39.17 +# for more details.
   39.18 +#
   39.19 +# You should have received a copy of the GNU General Public License along
   39.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   39.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   39.22 +#============================================================================
   39.23 +
   39.24 +#----------------------------------------------------------------------------
   39.25 +# Xeno/xen.
   39.26 +
   39.27 +# Root of xen tree.
   39.28 +XEN_ROOT ?=../../..
   39.29 +
   39.30 +# Path to relativize the install. Set to /
   39.31 +# to install relative to filesystem root.
   39.32 +prefix ?=$(XEN_ROOT)/install/
   39.33 +#----------------------------------------------------------------------------
   39.34 +
   39.35 +LINUX_RELEASE ?=2.6
   39.36 +KERNEL_MINOR ?=-xen0
   39.37 +
   39.38 +LINUX_VERSION ?= $(shell ( /bin/ls -ld $(XEN_ROOT)/linux-$(LINUX_RELEASE).*-xen-sparse ) 2>/dev/null | \
   39.39 +                      sed -e 's!^.*linux-\(.\+\)-xen-sparse!\1!' )
   39.40 +
   39.41 +ifeq ($(LINUX_VERSION),)
   39.42 +$(error Kernel source for linux $(LINUX_RELEASE) not found)
   39.43 +endif
   39.44 +
   39.45 +KERNEL_VERSION =$(LINUX_VERSION)$(KERNEL_MINOR)
   39.46 +
   39.47 +KERNEL_SRC ?= $(XEN_ROOT)/linux-$(KERNEL_VERSION)
   39.48 +
   39.49 +KERNEL_MODULE_DIR = /lib/modules/$(KERNEL_VERSION)/kernel
   39.50 +
   39.51 +#$(warning KERNEL_VERSION $(KERNEL_VERSION))
   39.52 +#$(warning KERNEL_SRC $(KERNEL_SRC))
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/tools/vnet/vnet-module/Makefile.vnet	Wed Nov 24 18:22:43 2004 +0000
    40.3 @@ -0,0 +1,57 @@
    40.4 +# -*- mode: Makefile; -*-
    40.5 +#============================================================================
    40.6 +#
    40.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    40.8 +#
    40.9 +# This program is free software; you can redistribute it and/or modify
   40.10 +# it under the terms of the GNU General Public License as published by the
   40.11 +# Free Software Foundation; either version 2 of the License, or (at your
   40.12 +# option) any later version.
   40.13 +#
   40.14 +# This program is distributed in the hope that it will be useful, but
   40.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   40.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   40.17 +# for more details.
   40.18 +#
   40.19 +# You should have received a copy of the GNU General Public License along
   40.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   40.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   40.22 +#============================================================================
   40.23 +
   40.24 +ifeq ($(src),)
   40.25 +SRC_DIR=
   40.26 +else
   40.27 +SRC_DIR=$(src)/
   40.28 +endif
   40.29 +
   40.30 +LIB_DIR := $(SRC_DIR)../../libxutil
   40.31 +
   40.32 +VNET_SRC :=
   40.33 +VNET_SRC += esp.c
   40.34 +VNET_SRC += etherip.c
   40.35 +VNET_SRC += random.c
   40.36 +VNET_SRC += sa_algorithm.c
   40.37 +VNET_SRC += sa.c
   40.38 +VNET_SRC += skb_context.c
   40.39 +VNET_SRC += skb_util.c
   40.40 +VNET_SRC += tunnel.c
   40.41 +VNET_SRC += varp.c
   40.42 +VNET_SRC += varp_socket.c
   40.43 +VNET_SRC += vif.c
   40.44 +VNET_SRC += vnet.c
   40.45 +VNET_SRC += vnet_dev.c
   40.46 +VNET_SRC += vnet_ioctl.c
   40.47 +
   40.48 +VNET_LIB_SRC += allocate.c
   40.49 +VNET_LIB_SRC += enum.c
   40.50 +VNET_LIB_SRC += hash_table.c
   40.51 +VNET_LIB_SRC += iostream.c
   40.52 +VNET_LIB_SRC += kernel_stream.c
   40.53 +VNET_LIB_SRC += sxpr.c
   40.54 +VNET_LIB_SRC += sxpr_parser.c
   40.55 +VNET_LIB_SRC += sys_net.c
   40.56 +VNET_LIB_SRC += sys_string.c
   40.57 +
   40.58 +VNET_OBJ := $(VNET_SRC:.c=.o)
   40.59 +VNET_LIB_OBJ := $(VNET_LIB_SRC:.c=.o)
   40.60 +
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/tools/vnet/vnet-module/esp.c	Wed Nov 24 18:22:43 2004 +0000
    41.3 @@ -0,0 +1,863 @@
    41.4 +/*
    41.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    41.6 + *
    41.7 + * This program is free software; you can redistribute it and/or modify
    41.8 + * it under the terms of the GNU General Public License as published by the 
    41.9 + * Free Software Foundation; either version 2 of the License, or (at your
   41.10 + * option) any later version.
   41.11 + * 
   41.12 + * This program is distributed in the hope that it will be useful, but
   41.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   41.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   41.15 + * for more details.
   41.16 + *
   41.17 + * You should have received a copy of the GNU General Public License along
   41.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   41.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   41.20 + *
   41.21 + */
   41.22 +#include <linux/config.h>
   41.23 +#include <linux/module.h>
   41.24 +#include <linux/types.h>
   41.25 +#include <linux/sched.h>
   41.26 +#include <linux/kernel.h>
   41.27 +#include <asm/uaccess.h>
   41.28 +
   41.29 +#include <linux/init.h>
   41.30 +
   41.31 +#include <linux/version.h>
   41.32 +
   41.33 +#include <linux/skbuff.h>
   41.34 +#include <linux/netdevice.h>
   41.35 +#include <linux/net.h>
   41.36 +#include <linux/in.h>
   41.37 +#include <linux/inet.h>
   41.38 +
   41.39 +#include <net/ip.h>
   41.40 +#include <net/protocol.h>
   41.41 +#include <net/route.h>
   41.42 +
   41.43 +#include <linux/if_ether.h>
   41.44 +#include <linux/icmp.h>
   41.45 +
   41.46 +#include <asm/scatterlist.h>
   41.47 +#include <linux/crypto.h>
   41.48 +#include <linux/pfkeyv2.h>
   41.49 +#include <linux/random.h>
   41.50 +
   41.51 +#include <esp.h>
   41.52 +#include <sa.h>
   41.53 +#include <sa_algorithm.h>
   41.54 +#include <tunnel.h>
   41.55 +#include <vnet.h>
   41.56 +#include <skb_util.h>
   41.57 +
   41.58 +static const int DEBUG_ICV = 0;
   41.59 +
   41.60 +#define MODULE_NAME "IPSEC"
   41.61 +#define DEBUG 1
   41.62 +#undef DEBUG
   41.63 +#include "debug.h"
   41.64 +
   41.65 +/* Outgoing packet:                            [ eth | ip | data ]
   41.66 + * After etherip:        [ eth2 | ip2 |  ethip | eth | ip | data ]
   41.67 + * After esp   :   [ eth2 | ip2 | esp | {ethip | eth | ip | data} | pad | icv ]
   41.68 + *                                                        ^     +
   41.69 + * The curly braces { ... } denote encryption.
   41.70 + * The esp header includes the fixed esp headers and the iv (variable size).
   41.71 + * The point marked ^ does not move. To the left is in the header, to the right
   41.72 + * is in the frag. Remember that all outgoing skbs (from domains) have 1 frag.
   41.73 + * Data after + is added by esp, using an extra frag.
   41.74 + *
   41.75 + * Incoming as above.
   41.76 + * After decrypt:  [ eth2 | ip2 | esp |  ethip | eth | ip | data  | pad | icv ]
   41.77 + * Trim tail:      [ eth2 | ip2 | esp |  ethip | eth | ip | data ]
   41.78 + * Drop hdr:             [ eth2 | ip2 |  ethip | eth | ip | data ]
   41.79 + *                                    ^
   41.80 + * The point marked ^ does not move. Incoming skbs are linear (no frags).
   41.81 + * The tail is trimmed by adjusting skb->tail and len.
   41.82 + * The esp hdr is dropped by using memmove to move the headers and
   41.83 + * adjusting the skb pointers.
   41.84 + *
   41.85 + * todo: Now this code is in linux we can't assume 1 frag for outbound skbs,
   41.86 + * or (maybe) that memmove is safe on inbound.
   41.87 + */
   41.88 +
   41.89 +/** Round n up to a multiple of block.
   41.90 + * If block is less than 2 does nothing.
   41.91 + * Otherwise assume block is a power of 2.
   41.92 + *
   41.93 + * @param n to round up
   41.94 + * @param block size to round to a multiple of
   41.95 + * @return rounded value
   41.96 + */
   41.97 +static inline int roundup(int n, int block){
   41.98 +    if(block <= 1) return n;
   41.99 +    block--;
  41.100 +    return (n + block) & ~block;
  41.101 +}
  41.102 +
  41.103 +/** Check if n is a multiple of block.
  41.104 + * If block is less than 2 returns 1.
  41.105 + * Otherwise assumes block is a power of 2.
  41.106 + *
  41.107 + * @param n to check
  41.108 + * @param block block size
  41.109 + * @return 1 if a multiple, 0 otherwise
  41.110 + */
  41.111 +static inline int multipleof(int n, int block){
  41.112 +    if(block <= 1) return 1;
  41.113 +    block--;
  41.114 +    return !(n & block);
  41.115 +}
  41.116 +
  41.117 +/** Convert from bits to bytes.
  41.118 + *
  41.119 + * @param n number of bits
  41.120 + * @return number of bytes
  41.121 + */
  41.122 +static inline int bits_to_bytes(int n){
  41.123 +    return n / 8;
  41.124 +}
  41.125 +
  41.126 +
  41.127 +/** Insert esp padding at the end of an skb.
  41.128 + * Inserts padding bytes, number of padding bytes, protocol number.
  41.129 + *
  41.130 + * @param skb skb
  41.131 + * @param offset offset from skb end to where padding should end
  41.132 + * @param extra_n total amount of padding
  41.133 + * @param protocol protocol number (from original ip hdr)
  41.134 + * @return 0 on success, error code otherwise
  41.135 + */
  41.136 +static int esp_sa_pad(struct sk_buff *skb, int offset, int extra_n,
  41.137 +                      unsigned char protocol){
  41.138 +    int err;
  41.139 +    char *data;
  41.140 +    int pad_n = extra_n - ESP_PAD_N;
  41.141 +    int i;
  41.142 +    char buf[extra_n];
  41.143 +
  41.144 +    data = buf;
  41.145 +    for(i = 1; i <= pad_n; i++){
  41.146 +        *data++ = i;
  41.147 +    }
  41.148 +    *data++ = pad_n;
  41.149 +    *data++ = protocol;
  41.150 +    err = skb_put_bits(skb, skb->len - offset - extra_n, buf, extra_n);
  41.151 +    return err;
  41.152 +}
  41.153 +
  41.154 +/** Encrypt skb. Skips esp header and iv.
  41.155 + * Assumes skb->data points at esp header.
  41.156 + *
  41.157 + * @param esp esp state
  41.158 + * @parm esph esp header
  41.159 + * @param skb packet
  41.160 + * @param head_n size of esp header and iv
  41.161 + * @param iv_n size of iv
  41.162 + * @param text_n size of ciphertext
  41.163 + * @return 0 on success, error code otherwise
  41.164 + */
  41.165 +static int esp_sa_encrypt(ESPState *esp, ESPHdr *esph, struct sk_buff *skb,
  41.166 +                   int head_n, int iv_n, int text_n){
  41.167 +    int err = 0;
  41.168 +    int sg_n = skb_shinfo(skb)->nr_frags + 1;
  41.169 +    struct scatterlist sg[sg_n];
  41.170 +
  41.171 +    err = skb_scatterlist(skb, sg, &sg_n, head_n, text_n);
  41.172 +    if(err) goto exit;
  41.173 +    if(iv_n){
  41.174 +        crypto_cipher_set_iv(esp->cipher.tfm, esp->cipher.iv, iv_n);
  41.175 +    }
  41.176 +    crypto_cipher_encrypt(esp->cipher.tfm, sg, sg, text_n);
  41.177 +    if(iv_n){
  41.178 +        memcpy(esph->data, esp->cipher.iv, iv_n);
  41.179 +        crypto_cipher_get_iv(esp->cipher.tfm, esp->cipher.iv, iv_n);
  41.180 +    }
  41.181 +  exit:
  41.182 +    return err;
  41.183 +}
  41.184 +
  41.185 +/** Decrypt skb. Skips esp header and iv.
  41.186 + * Assumes skb->data points at esp header.
  41.187 + *
  41.188 + * @param esp esp state
  41.189 + * @parm esph esp header
  41.190 + * @param skb packet
  41.191 + * @param head_n size of esp header and iv
  41.192 + * @param iv_n size of iv
  41.193 + * @param text_n size of ciphertext
  41.194 + * @return 0 on success, error code otherwise
  41.195 + */
  41.196 +static int esp_sa_decrypt(ESPState *esp, ESPHdr *esph, struct sk_buff *skb,
  41.197 +                   int head_n, int iv_n, int text_n){
  41.198 +    int err = 0;
  41.199 +    int sg_n = skb_shinfo(skb)->nr_frags + 1;
  41.200 +    struct scatterlist sg[sg_n];
  41.201 +
  41.202 +    err = skb_scatterlist(skb, sg, &sg_n, head_n, text_n);
  41.203 +    if(err) goto exit;
  41.204 +    if(iv_n){
  41.205 +        crypto_cipher_set_iv(esp->cipher.tfm, esph->data, iv_n);
  41.206 +    }
  41.207 +    crypto_cipher_decrypt(esp->cipher.tfm, sg, sg, text_n);
  41.208 +  exit:
  41.209 +    return err;
  41.210 +}
  41.211 +
  41.212 +/** Compute icv. Includes esp header, iv and ciphertext.
  41.213 + * Assumes skb->data points at esp header.
  41.214 + *
  41.215 + * @param esp esp state
  41.216 + * @param skb packet
  41.217 + * @param digest_n number of bytes to digest
  41.218 + * @param icv_n size of icv
  41.219 + * @return 0 on success, error code otherwise
  41.220 + */
  41.221 +static int esp_sa_digest(ESPState *esp, struct sk_buff *skb, int digest_n, int icv_n){
  41.222 +    int err = 0;
  41.223 +    u8 icv[icv_n];
  41.224 +    
  41.225 +    if(DEBUG_ICV){
  41.226 +        dprintf("> skb digest_n=%d icv_n=%d\n", digest_n, icv_n);
  41.227 +        skb_print_bits(skb, 0, digest_n);
  41.228 +    }
  41.229 +    memset(icv, 0, icv_n);
  41.230 +    esp->digest.icv(esp, skb, 0, digest_n, icv);
  41.231 +    skb_put_bits(skb, digest_n, icv, icv_n);
  41.232 +    return err;
  41.233 +}
  41.234 +
  41.235 +/** Check the icv and trim it from the skb tail.
  41.236 + *
  41.237 + * @param sa sa state
  41.238 + * @param esp esp state
  41.239 + * @param esph esp header
  41.240 + * @param skb packet
  41.241 + * @return 0 on success, error code otherwise
  41.242 + */
  41.243 +static int esp_check_icv(SAState *sa, ESPState *esp, ESPHdr *esph, struct sk_buff *skb){
  41.244 +    int err = 0;
  41.245 +    int icv_n = esp->digest.icv_n;
  41.246 +    int digest_n = skb->len - icv_n;
  41.247 +    u8 icv_skb[icv_n];
  41.248 +    u8 icv_new[icv_n];
  41.249 +
  41.250 +    dprintf(">\n");
  41.251 +    if(DEBUG_ICV){
  41.252 +        dprintf("> skb len=%d digest_n=%d icv_n=%d\n",
  41.253 +                skb->len, digest_n, icv_n);
  41.254 +        skb_print_bits(skb, 0, skb->len);
  41.255 +    }
  41.256 +    if(skb_copy_bits(skb, digest_n, icv_skb, icv_n)){
  41.257 +        wprintf("> Error getting icv from skb\n");
  41.258 +        goto exit;
  41.259 +    }
  41.260 +    esp->digest.icv(esp, skb, 0, digest_n, icv_new);
  41.261 +    if(DEBUG_ICV){
  41.262 +        dprintf("> len=%d icv_n=%d", digest_n, icv_n);
  41.263 +        printk("\nskb="); buf_print(icv_skb, icv_n);
  41.264 +        printk("new="); buf_print(icv_new, icv_n);
  41.265 +    }
  41.266 +    if(unlikely(memcmp(icv_new, icv_skb, icv_n))){
  41.267 +        wprintf("> ICV check failed!\n");
  41.268 +        err = -EINVAL;
  41.269 +        sa->counts.integrity_failures++;
  41.270 +        goto exit;
  41.271 +    }
  41.272 +    skb_trim_tail(skb, icv_n);
  41.273 +  exit:
  41.274 +    dprintf("< err=%d\n", err);
  41.275 +    return err;
  41.276 +}
  41.277 +
  41.278 +/** Send a packet via an ESP SA.
  41.279 + *
  41.280 + * @param sa SA state
  41.281 + * @param skb packet to send
  41.282 + * @param tunnel underlying tunnel
  41.283 + * @return 0 on success, negative error code otherwise
  41.284 + */
  41.285 +static int esp_sa_send(SAState *sa, struct sk_buff *skb, Tunnel *tunnel){
  41.286 +    int err = 0;
  41.287 +    int ip_n;           // Size of ip header.
  41.288 +    int plaintext_n;	// Size of plaintext.
  41.289 +    int ciphertext_n;   // Size of ciphertext (including padding).
  41.290 +    int extra_n;        // Extra bytes needed for ciphertext.
  41.291 +    int icv_n = 0;      // Size of integrity check value (icv).
  41.292 +    int iv_n = 0;       // Size of initialization vector (iv).
  41.293 +    int head_n;         // Size of esp header and iv.
  41.294 +    int tail_n;         // Size of esp trailer: padding and icv.
  41.295 +    ESPState  *esp;
  41.296 +    ESPHdr *esph;
  41.297 +
  41.298 +    dprintf(">\n");
  41.299 +    esp = sa->data;
  41.300 +    ip_n = (skb->nh.iph->ihl << 2);
  41.301 +    // Assuming skb->data points at ethernet header, exclude ethernet
  41.302 +    // header and IP header.
  41.303 +    plaintext_n = skb->len - ETH_HLEN - ip_n;
  41.304 +    // Add size of padding fields.
  41.305 +    ciphertext_n = roundup(plaintext_n + ESP_PAD_N, esp->cipher.block_n);
  41.306 +    if(esp->cipher.pad_n > 0){
  41.307 +        ciphertext_n = roundup(ciphertext_n, esp->cipher.pad_n);
  41.308 +    }
  41.309 +    extra_n = ciphertext_n - plaintext_n;
  41.310 +    iv_n = esp->cipher.iv_n;
  41.311 +    icv_n = esp->digest.icv_n;
  41.312 +    dprintf("> len=%d plaintext=%d ciphertext=%d extra=%d\n",
  41.313 +            skb->len, plaintext_n, ciphertext_n, extra_n);
  41.314 +    dprintf("> iv=%d icv=%d\n", iv_n, icv_n);
  41.315 +    skb_print_bits(skb, 0, skb->len);
  41.316 +
  41.317 +    // Add headroom for esp header and iv, tailroom for the ciphertext
  41.318 +    // and icv.
  41.319 +    head_n = ESP_HDR_N + iv_n;
  41.320 +    tail_n = extra_n + icv_n;
  41.321 +    err = skb_make_room(&skb, skb, head_n, tail_n);
  41.322 +    if(err) goto exit;
  41.323 +    dprintf("> skb=%p\n", skb);
  41.324 +    // Move the headers up to make space for the esp header.  We can
  41.325 +    // use memmove() since all this data fits in the skb head.
  41.326 +    // todo: Can't assume this anymore?
  41.327 +    dprintf("> header push...\n");
  41.328 +    __skb_push(skb, head_n);
  41.329 +    if(0 && skb->mac.raw){
  41.330 +        dprintf("> skb->mac=%p\n", skb->mac.raw);
  41.331 +        dprintf("> ETH header pull...\n");
  41.332 +        memmove(skb->data, skb->mac.raw, ETH_HLEN);
  41.333 +        skb->mac.raw = skb->data; 
  41.334 +        __skb_pull(skb, ETH_HLEN);
  41.335 +    }
  41.336 +    dprintf("> IP header pull...\n");
  41.337 +    memmove(skb->data, skb->nh.raw, ip_n);
  41.338 +    skb->nh.raw = skb->data;
  41.339 +    __skb_pull(skb, ip_n);
  41.340 +    esph = (void*)skb->data;
  41.341 +    // Add spi and sequence number.
  41.342 +    esph->spi = sa->ident.spi;
  41.343 +    esph->seq = htonl(++sa->replay.send_seq);
  41.344 +    // Insert the padding bytes: extra bytes less the pad fields
  41.345 +    // themselves.
  41.346 +    dprintf("> esp_sa_pad ...\n");
  41.347 +    esp_sa_pad(skb, icv_n, extra_n, skb->nh.iph->protocol);
  41.348 +    if(sa->security & SA_CONF){
  41.349 +        dprintf("> esp_sa_encrypt...\n");
  41.350 +        err = esp_sa_encrypt(esp, esph, skb, head_n, iv_n, ciphertext_n);
  41.351 +        if(err) goto exit;
  41.352 +    }
  41.353 +    if(icv_n){
  41.354 +        dprintf("> esp_sa_digest...\n");
  41.355 +        err = esp_sa_digest(esp, skb, head_n + ciphertext_n, icv_n);
  41.356 +        if(err) goto exit;
  41.357 +    }
  41.358 +    dprintf("> IP header push...\n");
  41.359 +    __skb_push(skb, ip_n);
  41.360 +    if(0 && skb->mac.raw){
  41.361 +        dprintf("> ETH header push...\n");
  41.362 +        __skb_push(skb, ETH_HLEN);
  41.363 +    }
  41.364 +    // Fix ip header. Adjust length field, set protocol, zero
  41.365 +    // checksum.
  41.366 +    {
  41.367 +        // Total packet length (bytes).
  41.368 +        int tot_len = ntohs(skb->nh.iph->tot_len);
  41.369 +        tot_len += head_n;
  41.370 +        tot_len += tail_n;
  41.371 +        skb->nh.iph->protocol = IPPROTO_ESP;
  41.372 +        skb->nh.iph->tot_len  = htons(tot_len);
  41.373 +        skb->nh.iph->check    = 0;
  41.374 +    }
  41.375 +    err = Tunnel_send(tunnel, skb);
  41.376 +  exit:
  41.377 +    dprintf("< err=%d\n", err);
  41.378 +    return err;
  41.379 +}
  41.380 +
  41.381 +/** Release an skb context.
  41.382 + * Drops the refcount on the SA.
  41.383 + *
  41.384 + * @param context to free
  41.385 + */
  41.386 +static void esp_context_free_fn(SkbContext *context){
  41.387 +    SAState *sa;
  41.388 +    if(!context) return;
  41.389 +    sa = context->data;
  41.390 +    if(!sa) return;
  41.391 +    context->data = NULL;
  41.392 +    SAState_decref(sa);
  41.393 +}   
  41.394 +
  41.395 +/** Receive a packet via an ESP SA.
  41.396 + * Does ESP receive processing (check icv, decrypt), strips
  41.397 + * ESP header and re-receives.
  41.398 + *
  41.399 + * @param sa SA
  41.400 + * @param skb packet
  41.401 + * @return 0 on success, negative error code otherwise
  41.402 + */
  41.403 +static int esp_sa_recv(SAState *sa, struct sk_buff *skb){
  41.404 +    int err = -EINVAL;
  41.405 +    int mine = 0;
  41.406 +    int vnet = 0; //todo: fixme - need to record skb vnet somewhere
  41.407 +    ESPState *esp;
  41.408 +    ESPHdr *esph;
  41.409 +    ESPPadding *pad;
  41.410 +    int block_n;	// Cipher blocksize.
  41.411 +    int icv_n;          // Size of integrity check value (icv).
  41.412 +    int iv_n;           // Size of initialization vector (iv).
  41.413 +    int text_n;         // Size of text (ciphertext or plaintext).
  41.414 +    int head_n;         // Size of esp header and iv.
  41.415 +
  41.416 +    dprintf("> skb=%p\n", skb);
  41.417 +    // Assumes skb->data points at esp hdr.
  41.418 +    esph = (void*)skb->data;
  41.419 +    esp = sa->data;
  41.420 +    block_n = crypto_tfm_alg_blocksize(esp->cipher.tfm);
  41.421 +    icv_n = esp->digest.icv_n;
  41.422 +    iv_n = esp->cipher.iv_n;
  41.423 +    head_n = ESP_HDR_N + iv_n;
  41.424 +    text_n = skb->len - head_n - icv_n;
  41.425 +    if(text_n < ESP_PAD_N || !multipleof(text_n, block_n)){
  41.426 +        wprintf("> Invalid size: text_n=%d tfm:block_n=%d esp:block_n=%d\n",
  41.427 +                text_n, block_n, esp->cipher.block_n);
  41.428 +        goto exit;
  41.429 +    }
  41.430 +    if(icv_n){
  41.431 +        err = esp_check_icv(sa, esp, esph, skb);
  41.432 +        if(err) goto exit;
  41.433 +    }
  41.434 +    mine = 1;
  41.435 +    if(sa->security & SA_CONF){
  41.436 +        err = esp_sa_decrypt(esp, esph, skb, head_n, iv_n, text_n);
  41.437 +        if(err) goto exit;
  41.438 +    }
  41.439 +    // Strip esp header by moving the other headers down.
  41.440 +    //todo Maybe not safe to do this anymore.
  41.441 +    memmove(skb->mac.raw + head_n, skb->mac.raw, (skb->data - skb->mac.raw));
  41.442 +    skb->mac.raw += head_n;
  41.443 +    skb->nh.raw  += head_n;
  41.444 +    // Move skb->data back to ethernet header.
  41.445 +    // Do in 2 moves to ensure offsets are +ve,
  41.446 +    // since args to skb_pull/skb_push are unsigned.
  41.447 +    __skb_pull(skb, head_n);
  41.448 +    __skb_push(skb, skb->data - skb->mac.raw);
  41.449 +    // After this esph is invalid.
  41.450 +    esph = NULL;
  41.451 +    // Trim padding, restore protocol in IP header.
  41.452 +    pad = skb_trim_tail(skb, ESP_PAD_N);
  41.453 +    text_n -= ESP_PAD_N;
  41.454 +    if((pad->pad_n > 255) | (pad->pad_n > text_n)){
  41.455 +        wprintf("> Invalid padding: pad_n=%d text_n=%d\n", pad->pad_n, text_n);
  41.456 +        goto exit;
  41.457 +    }
  41.458 +    skb_trim_tail(skb, pad->pad_n);
  41.459 +    skb->nh.iph->protocol = pad->protocol;
  41.460 +    err = skb_push_context(skb, vnet, sa->ident.addr, IPPROTO_ESP,
  41.461 +                           sa, esp_context_free_fn);
  41.462 +    if(err) goto exit;
  41.463 +    // Increase sa refcount now the skb context refers to it.
  41.464 +    SAState_incref(sa);
  41.465 +    err = netif_rx(skb);
  41.466 +  exit:
  41.467 +    if(mine) err = 1;
  41.468 +    dprintf("< skb=%p err=%d\n", skb, err);
  41.469 +    return err;
  41.470 +}
  41.471 +
  41.472 +/** Estimate the packet size for some data using ESP processing.    
  41.473 + *
  41.474 + * @param sa ESP SA
  41.475 + * @param data_n data size
  41.476 + * @return size after ESP processing
  41.477 + */
  41.478 +static u32 esp_sa_size(SAState *sa, int data_n){
  41.479 +    // Even in transport mode have to round up to blocksize.
  41.480 +    // Have to add some padding for alignment even if pad_n is zero.
  41.481 +    ESPState *esp = sa->data;
  41.482 +    
  41.483 +    data_n = roundup(data_n + ESP_PAD_N, esp->cipher.block_n);
  41.484 +    if(esp->cipher.pad_n > 0){
  41.485 +        data_n = roundup(data_n, esp->cipher.pad_n);
  41.486 +    }
  41.487 +    data_n += esp->digest.icv_n;
  41.488 +    //data_n += esp->cipher.iv_n;
  41.489 +    data_n += ESP_HDR_N;
  41.490 +    return data_n;
  41.491 +}
  41.492 +
  41.493 +/** Compute an icv using HMAC digest.
  41.494 + *
  41.495 + * @param esp ESP state
  41.496 + * @param skb packet to digest
  41.497 + * @param offset offset to start at
  41.498 + * @param len number of bytes to digest
  41.499 + * @param icv return parameter for ICV
  41.500 + * @return 0 on success, negative error code otherwise
  41.501 + */
  41.502 +static inline void esp_hmac_digest(ESPState *esp, struct sk_buff *skb,
  41.503 +                                   int offset, int len, u8 *icv){
  41.504 +    int err = 0;
  41.505 +    struct crypto_tfm *digest = esp->digest.tfm;
  41.506 +    char *icv_tmp = esp->digest.icv_tmp;
  41.507 +    int sg_n = skb_shinfo(skb)->nr_frags + 1;
  41.508 +    struct scatterlist sg[sg_n];
  41.509 +
  41.510 +    dprintf("> offset=%d len=%d\n", offset, len);
  41.511 +    memset(icv, 0, esp->digest.icv_n);
  41.512 +    if(DEBUG_ICV){
  41.513 +        dprintf("> key len=%d\n", esp->digest.key_n);
  41.514 +        printk("\nkey=");
  41.515 +        buf_print(esp->digest.key,esp->digest.key_n); 
  41.516 +    }
  41.517 +    crypto_hmac_init(digest, esp->digest.key, &esp->digest.key_n);
  41.518 +    err = skb_scatterlist(skb, sg, &sg_n, offset, len);
  41.519 +    crypto_hmac_update(digest, sg, sg_n);
  41.520 +    crypto_hmac_final(digest, esp->digest.key, &esp->digest.key_n, icv_tmp);
  41.521 +    if(DEBUG_ICV){
  41.522 +        dprintf("> digest len=%d ", esp->digest.icv_n);
  41.523 +        printk("\nval=");
  41.524 +        buf_print(icv_tmp, esp->digest.icv_n);
  41.525 +    }
  41.526 +    memcpy(icv, icv_tmp, esp->digest.icv_n);
  41.527 +    dprintf("<\n");
  41.528 +}
  41.529 +
  41.530 +/** Finish up an esp state.
  41.531 + * Releases the digest, cipher, iv and frees the state.
  41.532 + *
  41.533 + * @parma esp state
  41.534 + */
  41.535 +static void esp_fini(ESPState *esp){
  41.536 +    if(!esp) return;
  41.537 +    if(esp->digest.tfm){
  41.538 +        crypto_free_tfm(esp->digest.tfm);
  41.539 +        esp->digest.tfm = NULL; 
  41.540 +    }
  41.541 +    if(esp->digest.icv_tmp){
  41.542 +        kfree(esp->digest.icv_tmp);
  41.543 +        esp->digest.icv_tmp = NULL;
  41.544 +    }
  41.545 +    if(esp->cipher.tfm){
  41.546 +        crypto_free_tfm(esp->cipher.tfm);
  41.547 +        esp->cipher.tfm = NULL;
  41.548 +    }
  41.549 +    if(esp->cipher.iv){
  41.550 +        kfree(esp->cipher.iv);
  41.551 +        esp->cipher.iv = NULL;
  41.552 +    }
  41.553 +    kfree(esp);
  41.554 +}
  41.555 +
  41.556 +/** Release an ESP SA.
  41.557 + *
  41.558 + * @param sa ESO SA
  41.559 + */
  41.560 +static void esp_sa_fini(SAState *sa){
  41.561 +    ESPState *esp;
  41.562 +    if(!sa) return;
  41.563 +    esp = sa->data;
  41.564 +    if(!esp) return;
  41.565 +    esp_fini(esp);
  41.566 +    sa->data = NULL;
  41.567 +}
  41.568 +
  41.569 +/** Initialize the cipher for an ESP SA.
  41.570 + *
  41.571 + * @param sa ESP SA
  41.572 + * @param esp ESP state
  41.573 + * @return 0 on success, negative error code otherwise
  41.574 + */
  41.575 +static int esp_cipher_init(SAState *sa, ESPState *esp){
  41.576 +    int err = 0; 
  41.577 +    SAAlgorithm *algo = NULL;
  41.578 +    int cipher_mode = CRYPTO_TFM_MODE_CBC;
  41.579 +
  41.580 +    dprintf("> sa=%p esp=%p\n", sa, esp);
  41.581 +    dprintf("> cipher=%s\n", sa->cipher.name);
  41.582 +    algo = sa_cipher_by_name(sa->cipher.name);
  41.583 +    if(!algo){
  41.584 +        wprintf("> Cipher unavailable: %s\n", sa->cipher.name);
  41.585 +        err = -EINVAL;
  41.586 +        goto exit;
  41.587 +    }
  41.588 +    esp->cipher.key_n = roundup(sa->cipher.bits, 8);
  41.589 +    // If cipher is null must use ECB because CBC algo does not support blocksize 1.
  41.590 +    if(strcmp(sa->cipher.name, "cipher_null")){
  41.591 +        cipher_mode = CRYPTO_TFM_MODE_ECB;
  41.592 +    }
  41.593 +    esp->cipher.tfm = crypto_alloc_tfm(sa->cipher.name, cipher_mode);
  41.594 +    if(!esp->cipher.tfm){
  41.595 +        err = -ENOMEM;
  41.596 +        goto exit;
  41.597 +    }
  41.598 +    esp->cipher.block_n = roundup(crypto_tfm_alg_blocksize(esp->cipher.tfm), 4);
  41.599 +    esp->cipher.iv_n = crypto_tfm_alg_ivsize(esp->cipher.tfm);
  41.600 +    esp->cipher.pad_n = 0;
  41.601 +    if(esp->cipher.iv_n){
  41.602 +        esp->cipher.iv = kmalloc(esp->cipher.iv_n, GFP_KERNEL);
  41.603 +        get_random_bytes(esp->cipher.iv, esp->cipher.iv_n);
  41.604 +    }
  41.605 +    crypto_cipher_setkey(esp->cipher.tfm, esp->cipher.key, esp->cipher.key_n);
  41.606 +    err = 0;
  41.607 +  exit:
  41.608 +    dprintf("< err=%d\n", err);
  41.609 +    return err;
  41.610 +}
  41.611 +
  41.612 +/** Initialize the digest for an ESP SA.
  41.613 + *
  41.614 + * @param sa ESP SA
  41.615 + * @param esp ESP state
  41.616 + * @return 0 on success, negative error code otherwise
  41.617 + */
  41.618 +static int esp_digest_init(SAState *sa, ESPState *esp){
  41.619 +    int err = 0;
  41.620 +    SAAlgorithm *algo = NULL;
  41.621 +    
  41.622 +    dprintf(">\n");
  41.623 +    esp->digest.key = sa->digest.key;
  41.624 +    esp->digest.key_n = bits_to_bytes(roundup(sa->digest.bits, 8));
  41.625 +    esp->digest.tfm = crypto_alloc_tfm(sa->digest.name, 0);
  41.626 +    if(!esp->digest.tfm){
  41.627 +        err = -ENOMEM;
  41.628 +        goto exit;
  41.629 +    }
  41.630 +    algo = sa_digest_by_name(sa->digest.name);
  41.631 +    if(!algo){
  41.632 +        wprintf("> Digest unavailable: %s\n", sa->digest.name);
  41.633 +        err = -EINVAL;
  41.634 +        goto exit;
  41.635 +    }
  41.636 +    esp->digest.icv = esp_hmac_digest;
  41.637 +    esp->digest.icv_full_n = bits_to_bytes(algo->info.digest.icv_fullbits);
  41.638 +    esp->digest.icv_n = bits_to_bytes(algo->info.digest.icv_truncbits);
  41.639 +    
  41.640 +    if(esp->digest.icv_full_n != crypto_tfm_alg_digestsize(esp->digest.tfm)){
  41.641 +        err = -EINVAL;
  41.642 +        wprintf("> digest %s, size %u != %hu\n",
  41.643 +                sa->digest.name,
  41.644 +                crypto_tfm_alg_digestsize(esp->digest.tfm),
  41.645 +                esp->digest.icv_full_n);
  41.646 +        goto exit;
  41.647 +    }
  41.648 +    
  41.649 +    esp->digest.icv_tmp = kmalloc(esp->digest.icv_full_n, GFP_KERNEL);
  41.650 +    if(!esp->digest.icv_tmp){
  41.651 +        err = -ENOMEM;
  41.652 +        goto exit;
  41.653 +    }
  41.654 +  exit:
  41.655 +    dprintf("< err=%d\n", err);
  41.656 +    return err;
  41.657 +}
  41.658 +
  41.659 +/** Initialize an ESP SA.
  41.660 + *
  41.661 + * @param sa ESP SA
  41.662 + * @param args arguments
  41.663 + * @return 0 on success, negative error code otherwise
  41.664 + */
  41.665 +static int esp_sa_init(SAState *sa, void *args){
  41.666 +    int err = 0;
  41.667 +    ESPState *esp = NULL;
  41.668 +    
  41.669 +    dprintf("> sa=%p\n", sa);
  41.670 +    esp = kmalloc(sizeof(*esp), GFP_KERNEL);
  41.671 +    if(!esp){
  41.672 +        err = -ENOMEM;
  41.673 +        goto exit;
  41.674 +    }
  41.675 +    *esp = (ESPState){};
  41.676 +    err = esp_cipher_init(sa, esp);
  41.677 +    if(err) goto exit;
  41.678 +    err = esp_digest_init(sa, esp);
  41.679 +    if(err) goto exit;
  41.680 +    sa->data = esp;
  41.681 +  exit:
  41.682 +    if(err){
  41.683 +        if(esp) esp_fini(esp);
  41.684 +    }
  41.685 +    dprintf("< err=%d\n", err);
  41.686 +    return err;
  41.687 +}
  41.688 +
  41.689 +/** SA type for ESP.
  41.690 + */
  41.691 +static SAType esp_sa_type = {
  41.692 +    .name     = "ESP",
  41.693 +    .protocol = IPPROTO_ESP,
  41.694 +    .init     = esp_sa_init,
  41.695 +    .fini     = esp_sa_fini,
  41.696 +    .size     = esp_sa_size,
  41.697 +    .recv     = esp_sa_recv,
  41.698 +    .send     = esp_sa_send
  41.699 +};
  41.700 +
  41.701 +/** Get the ESP header from a packet.
  41.702 + *
  41.703 + * @param skb packet
  41.704 + * @param esph return parameter for header
  41.705 + * @return 0 on success, negative error code otherwise
  41.706 + */
  41.707 +static int esp_skb_header(struct sk_buff *skb, ESPHdr **esph){
  41.708 +    int err = 0;
  41.709 +    if(skb->len < ESP_HDR_N){
  41.710 +        err = -EINVAL;
  41.711 +        goto exit;
  41.712 +    }
  41.713 +    *esph = (ESPHdr*)skb->data;
  41.714 +  exit:
  41.715 +    return err;
  41.716 +}
  41.717 +
  41.718 +/** Handle an incoming skb with ESP protocol.
  41.719 + *
  41.720 + * Lookup spi, if state found hand to the state.
  41.721 + * If no state, check spi, if ok, create state and pass to it.
  41.722 + * If spi not ok, drop.
  41.723 + * 
  41.724 + * @param skb packet
  41.725 + * @return 0 on sucess, negative error code otherwise
  41.726 + */
  41.727 +static int esp_protocol_recv(struct sk_buff *skb){
  41.728 +    int err = 0;
  41.729 +    const int eth_n = ETH_HLEN;
  41.730 +    int ip_n;
  41.731 +    ESPHdr *esph = NULL;
  41.732 +    SAState *sa = NULL;
  41.733 +    u32 addr;
  41.734 +    
  41.735 +    dprintf(">\n");
  41.736 +    dprintf("> recv skb=\n"); skb_print_bits(skb, 0, skb->len);
  41.737 +    ip_n = (skb->nh.iph->ihl << 2);
  41.738 +    if(skb->data == skb->mac.raw){
  41.739 +        // skb->data points at ethernet header.
  41.740 +        if (!pskb_may_pull(skb, eth_n + ip_n)){
  41.741 +            wprintf("> Malformed skb\n");
  41.742 +            err = -EINVAL;
  41.743 +            goto exit;
  41.744 +        }
  41.745 +        skb_pull(skb, eth_n + ip_n);
  41.746 +    }
  41.747 +    addr = skb->nh.iph->daddr;
  41.748 +    err = esp_skb_header(skb, &esph);
  41.749 +    if(err) goto exit;
  41.750 +    dprintf("> spi=%08x protocol=%d addr=" IPFMT "\n",
  41.751 +            esph->spi, IPPROTO_ESP, NIPQUAD(addr));
  41.752 +    sa = sa_table_lookup_spi(esph->spi, IPPROTO_ESP, addr);
  41.753 +    if(!sa){
  41.754 +        err = vnet_sa_create(esph->spi, IPPROTO_ESP, addr, &sa);
  41.755 +        if(err) goto exit;
  41.756 +    }
  41.757 +    err = SAState_recv(sa, skb);
  41.758 +  exit:
  41.759 +    if(sa) SAState_decref(sa);
  41.760 +    dprintf("< err=%d\n", err);
  41.761 +    return err;
  41.762 +}
  41.763 +
  41.764 +/** Handle an ICMP error related to ESP.
  41.765 + *
  41.766 + * @param skb ICMP error packet
  41.767 + * @param info
  41.768 + */
  41.769 +static void esp_protocol_icmp_err(struct sk_buff *skb, u32 info){
  41.770 +    struct iphdr *iph = (struct iphdr*)skb->data;
  41.771 +    ESPHdr *esph;
  41.772 +    SAState *sa;
  41.773 +    
  41.774 +    dprintf("> ICMP error type=%d code=%d\n",
  41.775 +            skb->h.icmph->type, skb->h.icmph->code);
  41.776 +    if(skb->h.icmph->type != ICMP_DEST_UNREACH ||
  41.777 +       skb->h.icmph->code != ICMP_FRAG_NEEDED){
  41.778 +        return;
  41.779 +    }
  41.780 +    
  41.781 +    //todo: need to check skb has enough len to do this.
  41.782 +    esph = (ESPHdr*)(skb->data + (iph->ihl << 2));
  41.783 +    sa = sa_table_lookup_spi(esph->spi, IPPROTO_ESP, iph->daddr);
  41.784 +    if(!sa) return;
  41.785 +    wprintf("> ICMP unreachable on SA ESP spi=%08x addr=" IPFMT "\n",
  41.786 +            ntohl(esph->spi), NIPQUAD(iph->daddr));
  41.787 +    SAState_decref(sa);
  41.788 +}
  41.789 +
  41.790 +//============================================================================
  41.791 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  41.792 +// Code for 2.6 kernel.
  41.793 +
  41.794 +/** Protocol handler for ESP.
  41.795 + */
  41.796 +static struct net_protocol esp_protocol = {
  41.797 +    .handler     = esp_protocol_recv,
  41.798 +    .err_handler = esp_protocol_icmp_err
  41.799 +};
  41.800 +
  41.801 +static int esp_protocol_add(void){
  41.802 +    return inet_add_protocol(&esp_protocol, IPPROTO_ESP);
  41.803 +}
  41.804 +
  41.805 +static int esp_protocol_del(void){
  41.806 +    return inet_del_protocol(&esp_protocol, IPPROTO_ESP);
  41.807 +}
  41.808 +
  41.809 +//============================================================================
  41.810 +#else
  41.811 +//============================================================================
  41.812 +// Code for 2.4 kernel.
  41.813 +
  41.814 +/** Protocol handler for ESP.
  41.815 + */
  41.816 +static struct inet_protocol esp_protocol = {
  41.817 +    .name        = "ESP",
  41.818 +    .protocol    = IPPROTO_ESP,
  41.819 +    .handler     = esp_protocol_recv,
  41.820 +    .err_handler = esp_protocol_icmp_err
  41.821 +};
  41.822 +
  41.823 +static int esp_protocol_add(void){
  41.824 +    inet_add_protocol(&esp_protocol);
  41.825 +    return 0;
  41.826 +}
  41.827 +
  41.828 +static int esp_protocol_del(void){
  41.829 +    return inet_del_protocol(&esp_protocol);
  41.830 +}
  41.831 +
  41.832 +#endif
  41.833 +//============================================================================
  41.834 +
  41.835 +
  41.836 +/** Initialize the ESP module.
  41.837 + * Registers the ESP protocol and SA type.
  41.838 + *
  41.839 + * @return 0 on success, negative error code otherwise
  41.840 + */
  41.841 +int __init esp_module_init(void){
  41.842 +    int err = 0;
  41.843 +    dprintf(">\n");
  41.844 +    err = SAType_add(&esp_sa_type);
  41.845 +    if(err < 0){
  41.846 +        eprintf("> Error adding esp sa type\n");
  41.847 +        goto exit;
  41.848 +    }
  41.849 +    esp_protocol_add();
  41.850 +  exit:
  41.851 +    dprintf("< err=%d\n", err);
  41.852 +    return err;
  41.853 +}
  41.854 +
  41.855 +/** Finalize the ESP module.
  41.856 + * Deregisters the ESP protocol and SA type.
  41.857 + */
  41.858 +void __exit esp_module_exit(void){
  41.859 +    if(esp_protocol_del() < 0){
  41.860 +        eprintf("> Error removing esp protocol\n");
  41.861 +    }
  41.862 +    if(SAType_del(&esp_sa_type) < 0){
  41.863 +        eprintf("> Error removing esp sa type\n");
  41.864 +    }
  41.865 +}
  41.866 +
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/tools/vnet/vnet-module/esp.h	Wed Nov 24 18:22:43 2004 +0000
    42.3 @@ -0,0 +1,111 @@
    42.4 +/*
    42.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    42.6 + *
    42.7 + * This program is free software; you can redistribute it and/or modify
    42.8 + * it under the terms of the GNU General Public License as published by the 
    42.9 + * Free Software Foundation; either version 2 of the License, or (at your
   42.10 + * option) any later version.
   42.11 + * 
   42.12 + * This program is distributed in the hope that it will be useful, but
   42.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   42.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   42.15 + * for more details.
   42.16 + *
   42.17 + * You should have received a copy of the GNU General Public License along
   42.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   42.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   42.20 + *
   42.21 + */
   42.22 +#ifndef __VNET_ESP_H__
   42.23 +#define __VNET_ESP_H__
   42.24 +
   42.25 +#include <linux/config.h>
   42.26 +#include <linux/types.h>
   42.27 +#include <linux/crypto.h>
   42.28 +
   42.29 +/** Header used by IPSEC ESP (Encapsulated Security Payload). */
   42.30 +typedef struct ESPHdr {
   42.31 +    /** The spi (security parameters index). */
   42.32 +    u32 spi;
   42.33 +    /** Sequence number. */
   42.34 +    u32 seq;
   42.35 +    /* Variable length data (depends on crypto suite).
   42.36 +       Mind the 64 bit alignment! */
   42.37 +    u8  data[0];
   42.38 +} ESPHdr;
   42.39 +
   42.40 +/** Padding trailer used by IPSEC ESP.
   42.41 + * Follows the padding itself with the padding length and the
   42.42 + * protocol being encapsulated.
   42.43 + */
   42.44 +typedef struct ESPPadding {
   42.45 +    u8 pad_n;
   42.46 +    u8 protocol;
   42.47 +} ESPPadding;
   42.48 +
   42.49 +/** Size of the esp header (spi and seq). */
   42.50 +static const int ESP_HDR_N = sizeof(ESPHdr);
   42.51 +
   42.52 +/** Size of the esp pad and next protocol field. */
   42.53 +static const int ESP_PAD_N = sizeof(ESPPadding);
   42.54 +
   42.55 +enum {
   42.56 +    SASTATE_VOID,
   42.57 +    SASTATE_ACQUIRE,
   42.58 +    SASTATE_VALID,
   42.59 +    SASTATE_ERROR,
   42.60 +    SASTATE_EXPIRED,
   42.61 +    SASTATE_DEAD,
   42.62 +};
   42.63 +
   42.64 +struct ESPState;
   42.65 +
   42.66 +/** A cipher instance. */
   42.67 +typedef struct ESPCipher {
   42.68 +    /** Cipher key. */
   42.69 +    u8 *key;
   42.70 +    /** Key size (bytes). */
   42.71 +    int key_n;
   42.72 +    /** Initialization vector (IV). */
   42.73 +    u8 *iv;
   42.74 +    /** IV size (bytes). */
   42.75 +    int iv_n;
   42.76 +    /** Block size for padding (bytes). */
   42.77 +    int pad_n;
   42.78 +    /** Cipher block size (bytes). */
   42.79 +    int block_n;
   42.80 +    /** Cipher crypto transform. */
   42.81 +    struct crypto_tfm *tfm;
   42.82 +} ESPCipher;
   42.83 +
   42.84 +/** A digest instance. */
   42.85 +typedef struct ESPDigest {
   42.86 +    /** Digest key. */
   42.87 +    u8 *key;
   42.88 +    /** Key size (bytes) */
   42.89 +    int key_n;
   42.90 +    /** ICV size used (bytes). */
   42.91 +    u8 icv_n;
   42.92 +    /** Full ICV size when computed (bytes). */
   42.93 +    u8 icv_full_n;
   42.94 +    /** Working storage for computing ICV. */
   42.95 +    u8 *icv_tmp;
   42.96 +    /** Function used to compute ICV (e.g. HMAC). */
   42.97 +    void (*icv)(struct ESPState *esp,
   42.98 +                struct sk_buff *skb,
   42.99 +                int offset,
  42.100 +                int len,
  42.101 +                u8 *icv);
  42.102 +    /** Digest crypto transform (e.g. SHA). */
  42.103 +    struct crypto_tfm *tfm;
  42.104 +} ESPDigest;
  42.105 +
  42.106 +typedef struct ESPState {
  42.107 +    struct ESPCipher cipher;
  42.108 +    struct ESPDigest digest;
  42.109 +} ESPState;
  42.110 +
  42.111 +extern int esp_module_init(void);
  42.112 +extern void esp_module_exit(void);
  42.113 +
  42.114 +#endif /* !__VNET_ESP_H__ */
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/tools/vnet/vnet-module/etherip.c	Wed Nov 24 18:22:43 2004 +0000
    43.3 @@ -0,0 +1,411 @@
    43.4 +/*
    43.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    43.6 + *
    43.7 + * This program is free software; you can redistribute it and/or modify
    43.8 + * it under the terms of the GNU General Public License as published by the 
    43.9 + * Free Software Foundation; either version 2 of the License, or (at your
   43.10 + * option) any later version.
   43.11 + * 
   43.12 + * This program is distributed in the hope that it will be useful, but
   43.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   43.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   43.15 + * for more details.
   43.16 + *
   43.17 + * You should have received a copy of the GNU General Public License along
   43.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   43.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   43.20 + *
   43.21 + */
   43.22 +#include <linux/config.h>
   43.23 +#include <linux/module.h>
   43.24 +#include <linux/types.h>
   43.25 +#include <linux/kernel.h>
   43.26 +#include <linux/init.h>
   43.27 +
   43.28 +#include <linux/version.h>
   43.29 +
   43.30 +#include <linux/skbuff.h>
   43.31 +#include <linux/net.h>
   43.32 +#include <linux/netdevice.h>
   43.33 +#include <linux/in.h>
   43.34 +#include <linux/inet.h>
   43.35 +#include <linux/netfilter_ipv4.h>
   43.36 +#include <linux/icmp.h>
   43.37 +
   43.38 +#include <net/ip.h>
   43.39 +#include <net/protocol.h>
   43.40 +#include <net/route.h>
   43.41 +#include <net/checksum.h>
   43.42 +
   43.43 +#include <etherip.h>
   43.44 +#include <tunnel.h>
   43.45 +#include <vnet.h>
   43.46 +#include <varp.h>
   43.47 +#include <if_varp.h>
   43.48 +#include <skb_util.h>
   43.49 +
   43.50 +#define MODULE_NAME "VNET"
   43.51 +//#define DEBUG 1
   43.52 +#undef DEBUG
   43.53 +#include "debug.h"
   43.54 +
   43.55 +/** @file Etherip implementation.
   43.56 + * The etherip protocol is used to transport Ethernet frames in IP packets.
   43.57 + */
   43.58 +
   43.59 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   43.60 +#define MAC_ETH(_skb) ((struct ethhdr *)(_skb)->mac.raw)
   43.61 +#else
   43.62 +#define MAC_ETH(_skb) ((_skb)->mac.ethernet)
   43.63 +#endif
   43.64 +
   43.65 +/** Get the vnet label from an etherip header.
   43.66 + *
   43.67 + * @param hdr header
   43.68 + * @return vnet (in host order)
   43.69 + */
   43.70 +int etheriphdr_get_vnet(struct etheriphdr *hdr){
   43.71 +#ifdef CONFIG_ETHERIP_EXT
   43.72 +    return ntohl(hdr->vnet);
   43.73 +#else
   43.74 +    return hdr->reserved;
   43.75 +#endif
   43.76 +}
   43.77 +
   43.78 +/** Set the vnet label in an etherip header.
   43.79 + * Also sets the etherip version.
   43.80 + *
   43.81 + * @param hdr header
   43.82 + * @param vnet vnet label (in host order)
   43.83 + */
   43.84 +void etheriphdr_set_vnet(struct etheriphdr *hdr, int vnet){
   43.85 +#ifdef CONFIG_ETHERIP_EXT
   43.86 +    hdr->version = 4;
   43.87 +    hdr->vnet = htonl(vnet);
   43.88 +#else
   43.89 +    hdr->version = 3;
   43.90 +    hdr->reserved = vnet & 0x0fff;
   43.91 +#endif
   43.92 +}
   43.93 +
   43.94 +/** Open an etherip tunnel.
   43.95 + *
   43.96 + * @param tunnel to open
   43.97 + * @return 0 on success, error code otherwise
   43.98 + */
   43.99 +static int etherip_tunnel_open(Tunnel *tunnel){
  43.100 +    return 0;
  43.101 +}
  43.102 +
  43.103 +/** Close an etherip tunnel.
  43.104 + *
  43.105 + * @param tunnel to close
  43.106 + */
  43.107 +static void etherip_tunnel_close(Tunnel *tunnel){
  43.108 +}
  43.109 +
  43.110 +
  43.111 +/** Send a packet via an etherip tunnel.
  43.112 + * Adds etherip header, new ip header, new ethernet header around
  43.113 + * ethernet frame.
  43.114 + *
  43.115 + * @param tunnel tunnel
  43.116 + * @param skb packet
  43.117 + * @return 0 on success, error code otherwise
  43.118 + */
  43.119 +static int etherip_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
  43.120 +    int err = 0;
  43.121 +    const int etherip_n = sizeof(struct etheriphdr);
  43.122 +    const int ip_n = sizeof(struct iphdr);
  43.123 +    const int eth_n = ETH_HLEN;
  43.124 +    int head_n = 0;
  43.125 +    int vnet = tunnel->key.vnet;
  43.126 +    struct etheriphdr *etheriph;
  43.127 +    struct ethhdr *ethh;
  43.128 +    u32 saddr = 0;
  43.129 +
  43.130 +    dprintf("> skb=%p vnet=%d\n", skb, vnet);
  43.131 +    head_n = etherip_n + ip_n + eth_n;
  43.132 +    err = skb_make_room(&skb, skb, head_n, 0);
  43.133 +    if(err) goto exit;
  43.134 +
  43.135 +    //err = vnet_get_device_address(skb->dev, &saddr);
  43.136 +    //if(err) goto exit;
  43.137 +    
  43.138 +    // The original ethernet header.
  43.139 +    ethh = MAC_ETH(skb);
  43.140 +    //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len);
  43.141 +    // Null the pointer as we are pushing a new IP header.
  43.142 +    skb->mac.raw = NULL;
  43.143 +
  43.144 +    // Setup the etherip header.
  43.145 +    //dprintf("> push etherip header...\n");
  43.146 +    etheriph = (struct etheriphdr *)skb_push(skb, etherip_n);
  43.147 +    etheriphdr_set_vnet(etheriph, vnet);
  43.148 +
  43.149 +    // Setup the IP header.
  43.150 +    //dprintf("> push IP header...\n");
  43.151 +    skb->nh.raw = skb_push(skb, ip_n); 
  43.152 +    skb->nh.iph->version  = 4;			// Standard version.
  43.153 +    skb->nh.iph->ihl      = ip_n / 4;		// IP header length (32-bit words).
  43.154 +    skb->nh.iph->tos      = 0;			// No special type-of-service.
  43.155 +    skb->nh.iph->tot_len  = htons(skb->len);    // Total packet length (bytes).
  43.156 +    skb->nh.iph->id       = 0;			// No flow id (since no frags).
  43.157 +    skb->nh.iph->frag_off = htons(IP_DF);	// Don't fragment - can't handle frags.
  43.158 +    skb->nh.iph->ttl      = 64;			// Linux default time-to-live.
  43.159 +    skb->nh.iph->protocol = IPPROTO_ETHERIP;    // IP protocol number.
  43.160 +    skb->nh.iph->saddr    = saddr;		// Source address.
  43.161 +    skb->nh.iph->daddr    = tunnel->key.addr;	// Destination address.
  43.162 +    skb->nh.iph->check    = 0;
  43.163 +
  43.164 +    // Ethernet header will be filled-in by device.
  43.165 +    err = Tunnel_send(tunnel->base, skb);
  43.166 +    skb = NULL;
  43.167 +  exit:
  43.168 +    if(err && skb) dev_kfree_skb(skb);
  43.169 +    //dprintf("< err=%d\n", err);
  43.170 +    return err;
  43.171 +}
  43.172 +
  43.173 +/** Tunnel type for etherip.
  43.174 + */
  43.175 +static TunnelType _etherip_tunnel_type = {
  43.176 +    .name	= "ETHERIP",
  43.177 +    .open	= etherip_tunnel_open,
  43.178 +    .close	= etherip_tunnel_close,
  43.179 +    .send 	= etherip_tunnel_send
  43.180 +};
  43.181 +
  43.182 +TunnelType *etherip_tunnel_type = &_etherip_tunnel_type;
  43.183 +
  43.184 +/* Defeat compiler warnings about unused functions. */
  43.185 +static void print_str(char *s, int n) __attribute__((unused));
  43.186 +
  43.187 +static void print_str(char *s, int n) {
  43.188 +    int i;
  43.189 +
  43.190 +    for(i=0; i<n; s++, i++){
  43.191 +        if(i && i % 40 == 0) printk("\n");
  43.192 +        if(('a'<= *s && *s <= 'z') ||
  43.193 +           ('A'<= *s && *s <= 'Z') ||
  43.194 +           ('0'<= *s && *s <= '9')){
  43.195 +            printk("%c", *s);
  43.196 +        } else {
  43.197 +            printk("<%x>", (unsigned)(0xff & *s));
  43.198 +        }
  43.199 +    }
  43.200 +    printk("\n");
  43.201 +}
  43.202 +
  43.203 +/** Do etherip receive processing.
  43.204 + * Strips etherip header to extract the ethernet frame, sets
  43.205 + * the vnet from the header and re-receives the frame.
  43.206 + *
  43.207 + * @param skb packet
  43.208 + * @return 0 on success, error code otherwise
  43.209 + */
  43.210 +static int etherip_protocol_recv(struct sk_buff *skb){
  43.211 +    int err = 0;
  43.212 +    int mine = 0;
  43.213 +    const int eth_n = ETH_HLEN;
  43.214 +    int ip_n;
  43.215 +    const int etherip_n = sizeof(struct etheriphdr);
  43.216 +    struct etheriphdr *etheriph;
  43.217 +    struct ethhdr *ethhdr;
  43.218 +    Vnet *vinfo = NULL;
  43.219 +    u32 vnet;
  43.220 +
  43.221 +    ethhdr = MAC_ETH(skb);
  43.222 +    if(MULTICAST(skb->nh.iph->daddr) &&
  43.223 +       (skb->nh.iph->daddr != varp_mcast_addr)){
  43.224 +        // Ignore multicast packets not addressed to us.
  43.225 +        dprintf("> dst=%u.%u.%u.%u varp_mcast_addr=%u.%u.%u.%u\n",
  43.226 +                NIPQUAD(skb->nh.iph->daddr),
  43.227 +                NIPQUAD(varp_mcast_addr));
  43.228 +        goto exit;
  43.229 +    }
  43.230 +    ip_n = (skb->nh.iph->ihl << 2);
  43.231 +    if(skb->data == skb->mac.raw){
  43.232 +        // skb->data points at ethernet header.
  43.233 +        //dprintf("> len=%d\n", skb->len);
  43.234 +        if (!pskb_may_pull(skb, eth_n + ip_n)){
  43.235 +            wprintf("> Malformed skb\n");
  43.236 +            err = -EINVAL;
  43.237 +            goto exit;
  43.238 +        }
  43.239 +        skb_pull(skb, eth_n + ip_n);
  43.240 +    }
  43.241 +    // Assume skb->data points at etherip header.
  43.242 +    etheriph = (void*)skb->data;
  43.243 +    if(!pskb_may_pull(skb, etherip_n)){
  43.244 +        wprintf("> Malformed skb\n");
  43.245 +        err = -EINVAL;
  43.246 +        goto exit;
  43.247 +    }
  43.248 +    vnet = etheriphdr_get_vnet(etheriph);
  43.249 +    dprintf("> Rcvd skb=%p vnet=%d\n", skb, vnet);
  43.250 +    // If vnet is secure, context must include IPSEC ESP.
  43.251 +    err = vnet_check_context(vnet, SKB_CONTEXT(skb), &vinfo);
  43.252 +    Vnet_decref(vinfo);
  43.253 +    if(err){
  43.254 +        wprintf("> Failed security check\n");
  43.255 +        goto exit;
  43.256 +    }
  43.257 +    mine = 1;
  43.258 +    // Point at the headers in the contained ethernet frame.
  43.259 +    skb->mac.raw = skb_pull(skb, etherip_n);
  43.260 +
  43.261 +    // Know source ip, vnet, vmac, so could update varp cache.
  43.262 +    // But if traffic comes to us over a vnetd tunnel this points the coa
  43.263 +    // at the vnetd rather than the endpoint. So don't do it.
  43.264 +    //varp_update(htonl(vnet), MAC_ETH(skb)->h_source, skb->nh.iph->saddr);
  43.265 +
  43.266 +    // Assuming a standard Ethernet frame.
  43.267 +    skb->nh.raw = skb_pull(skb, ETH_HLEN);
  43.268 +
  43.269 +#ifdef CONFIG_NETFILTER
  43.270 +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
  43.271 +    // This stops our new pkt header being clobbered by a subsequent
  43.272 +    // call to nf_bridge_maybe_copy_header. Just replicate the
  43.273 +    // corresponding nf_bridge_save_header.
  43.274 +    if(skb->nf_bridge){
  43.275 +        int header_size = 16;
  43.276 +        if(MAC_ETH(skb)->h_proto == __constant_htons(ETH_P_8021Q)) {
  43.277 +            header_size = 18;
  43.278 +        }
  43.279 +        memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
  43.280 +    }
  43.281 +#endif
  43.282 +#endif
  43.283 +    
  43.284 +    if(1){
  43.285 +	struct ethhdr *eth = MAC_ETH(skb);
  43.286 +        // Devices use eth_type_trans() to set skb->pkt_type and skb->protocol.
  43.287 +        // Set them from contained ethhdr, or leave as received?
  43.288 +        // 'Ware use of hard_header_len in eth_type_trans().
  43.289 +
  43.290 +        //skb->protocol = htons(ETH_P_IP);
  43.291 +
  43.292 +        if(ntohs(eth->h_proto) >= 1536){
  43.293 +            skb->protocol = eth->h_proto;
  43.294 +        } else {
  43.295 +            skb->protocol = htons(ETH_P_802_2);
  43.296 +        }
  43.297 +        
  43.298 +	if(mac_is_multicast(eth->h_dest)){
  43.299 +            if(mac_is_broadcast(eth->h_dest)){
  43.300 +                skb->pkt_type = PACKET_BROADCAST;
  43.301 +	    } else {
  43.302 +                skb->pkt_type = PACKET_MULTICAST;
  43.303 +            }
  43.304 +        } else {
  43.305 +            skb->pkt_type = PACKET_HOST;
  43.306 +	}
  43.307 +
  43.308 +        memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
  43.309 +        if (skb->ip_summed == CHECKSUM_HW){
  43.310 +            skb->ip_summed = CHECKSUM_NONE;
  43.311 +            //skb->csum = csum_sub(skb->csum,
  43.312 +            //                     csum_partial(skb->mac.raw, skb->nh.raw - skb->mac.raw, 0));
  43.313 +        }
  43.314 +        dst_release(skb->dst);
  43.315 +        skb->dst = NULL;
  43.316 +#ifdef CONFIG_NETFILTER
  43.317 +        nf_conntrack_put(skb->nfct);
  43.318 +        skb->nfct = NULL;
  43.319 +#ifdef CONFIG_NETFILTER_DEBUG
  43.320 +        skb->nf_debug = 0;
  43.321 +#endif
  43.322 +#endif
  43.323 +    }
  43.324 +
  43.325 +    //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len + ETH_HLEN);
  43.326 +
  43.327 +    err = vnet_skb_recv(skb, vnet, (Vmac*)MAC_ETH(skb)->h_dest);
  43.328 +  exit:
  43.329 +    if(mine) err = 1;
  43.330 +    dprintf("< skb=%p err=%d\n", skb, err);
  43.331 +    return err;
  43.332 +}
  43.333 +
  43.334 +/** Handle an ICMP error related to etherip.
  43.335 + *
  43.336 + * @param skb ICMP error packet
  43.337 + * @param info
  43.338 + */
  43.339 +static void etherip_protocol_icmp_err(struct sk_buff *skb, u32 info){
  43.340 +    struct iphdr *iph = (struct iphdr*)skb->data;
  43.341 +    
  43.342 +    wprintf("> ICMP error type=%d code=%d addr=" IPFMT "\n",
  43.343 +            skb->h.icmph->type, skb->h.icmph->code, NIPQUAD(iph->daddr));
  43.344 +
  43.345 +    if (skb->h.icmph->type != ICMP_DEST_UNREACH ||
  43.346 +        skb->h.icmph->code != ICMP_FRAG_NEEDED){
  43.347 +        return;
  43.348 +    }
  43.349 +    wprintf("> MTU too big addr= " IPFMT "\n", NIPQUAD(iph->daddr)); 
  43.350 +}
  43.351 +
  43.352 +//============================================================================
  43.353 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  43.354 +// Code for 2.6 kernel.
  43.355 +
  43.356 +/** Etherip protocol. */
  43.357 +static struct net_protocol etherip_protocol = {
  43.358 +    .handler	 = etherip_protocol_recv,
  43.359 +    .err_handler = etherip_protocol_icmp_err,
  43.360 +};
  43.361 +
  43.362 +static int etherip_protocol_add(void){
  43.363 +    return inet_add_protocol(&etherip_protocol, IPPROTO_ETHERIP);
  43.364 +}
  43.365 +
  43.366 +static int etherip_protocol_del(void){
  43.367 +    return inet_del_protocol(&etherip_protocol, IPPROTO_ETHERIP);
  43.368 +}
  43.369 +
  43.370 +//============================================================================
  43.371 +#else
  43.372 +//============================================================================
  43.373 +// Code for 2.4 kernel.
  43.374 +
  43.375 +/** Etherip protocol. */
  43.376 +static struct inet_protocol etherip_protocol = {
  43.377 +    .name        = "ETHERIP",
  43.378 +    .protocol    = IPPROTO_ETHERIP,
  43.379 +    .handler	 = etherip_protocol_recv,
  43.380 +    .err_handler = etherip_protocol_icmp_err,
  43.381 +};
  43.382 +
  43.383 +static int etherip_protocol_add(void){
  43.384 +    inet_add_protocol(&etherip_protocol);
  43.385 +    return 0;
  43.386 +}
  43.387 +
  43.388 +static int etherip_protocol_del(void){
  43.389 +    return inet_del_protocol(&etherip_protocol);
  43.390 +}
  43.391 +
  43.392 +#endif
  43.393 +//============================================================================
  43.394 +
  43.395 +
  43.396 +/** Initialize the etherip module.
  43.397 + * Registers the etherip protocol.
  43.398 + *
  43.399 + * @return 0 on success, error code otherwise
  43.400 + */
  43.401 +int __init etherip_module_init(void) {
  43.402 +    int err = 0;
  43.403 +    etherip_protocol_add();
  43.404 +    return err;
  43.405 +}
  43.406 +
  43.407 +/** Finalize the etherip module.
  43.408 + * Deregisters the etherip protocol.
  43.409 + */
  43.410 +void __exit etherip_module_exit(void) {
  43.411 +    if(etherip_protocol_del() < 0){
  43.412 +        printk(KERN_INFO "%s: can't remove etherip protocol\n", __FUNCTION__);
  43.413 +    }
  43.414 +}
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/tools/vnet/vnet-module/etherip.h	Wed Nov 24 18:22:43 2004 +0000
    44.3 @@ -0,0 +1,27 @@
    44.4 +/*
    44.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    44.6 + *
    44.7 + * This program is free software; you can redistribute it and/or modify
    44.8 + * it under the terms of the GNU General Public License as published by the 
    44.9 + * Free Software Foundation; either version 2 of the License, or (at your
   44.10 + * option) any later version.
   44.11 + * 
   44.12 + * This program is distributed in the hope that it will be useful, but
   44.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   44.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   44.15 + * for more details.
   44.16 + *
   44.17 + * You should have received a copy of the GNU General Public License along
   44.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   44.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   44.20 + *
   44.21 + */
   44.22 +#ifndef _VNET_ETHERIP_H_
   44.23 +#define _VNET_ETHERIP_H_
   44.24 +
   44.25 +#include "if_etherip.h"
   44.26 +
   44.27 +extern int etherip_module_init(void);
   44.28 +extern void etherip_module_exit(void);
   44.29 +
   44.30 +#endif
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/tools/vnet/vnet-module/if_etherip.h	Wed Nov 24 18:22:43 2004 +0000
    45.3 @@ -0,0 +1,51 @@
    45.4 +/*
    45.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    45.6 + *
    45.7 + * This program is free software; you can redistribute it and/or modify
    45.8 + * it under the terms of the GNU General Public License as published by the 
    45.9 + * Free Software Foundation; either version 2 of the License, or (at your
   45.10 + * option) any later version.
   45.11 + * 
   45.12 + * This program is distributed in the hope that it will be useful, but
   45.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   45.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   45.15 + * for more details.
   45.16 + *
   45.17 + * You should have received a copy of the GNU General Public License along
   45.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   45.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   45.20 + *
   45.21 + */
   45.22 +#ifndef _VNET_IF_ETHERIP_H_
   45.23 +#define _VNET_IF_ETHERIP_H_
   45.24 +/*----------------------------------------------------------------------------*/
   45.25 +#ifdef CONFIG_ETHERIP_EXT
   45.26 +struct etheriphdr {
   45.27 +    __u8 version;
   45.28 +    __u32 vnet;
   45.29 +} __attribute__ ((packed));
   45.30 +
   45.31 +/*----------------------------------------------------------------------------*/
   45.32 +#else
   45.33 +struct etheriphdr
   45.34 +{
   45.35 +#if defined(__LITTLE_ENDIAN_BITFIELD)
   45.36 +    __u16    reserved:12,
   45.37 +             version:4;
   45.38 +#elif defined (__BIG_ENDIAN_BITFIELD)
   45.39 +    __u16    version:4,
   45.40 +            reserved:12;
   45.41 +#else
   45.42 +#error  "Please fix <asm/byteorder.h>"
   45.43 +#endif
   45.44 +
   45.45 +};
   45.46 +#endif
   45.47 +
   45.48 +#ifndef IPPROTO_ETHERIP
   45.49 +#define IPPROTO_ETHERIP 97
   45.50 +#endif
   45.51 +
   45.52 +/*----------------------------------------------------------------------------*/
   45.53 +
   45.54 +#endif /* ! _VNET_IF_ETHERIP_H_ */
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/tools/vnet/vnet-module/if_varp.h	Wed Nov 24 18:22:43 2004 +0000
    46.3 @@ -0,0 +1,53 @@
    46.4 +/*
    46.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    46.6 + *
    46.7 + * This program is free software; you can redistribute it and/or modify
    46.8 + * it under the terms of the GNU General Public License as published by the 
    46.9 + * Free Software Foundation; either version 2 of the License, or (at your
   46.10 + * option) any later version.
   46.11 + * 
   46.12 + * This program is distributed in the hope that it will be useful, but
   46.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   46.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   46.15 + * for more details.
   46.16 + *
   46.17 + * You should have received a copy of the GNU General Public License along
   46.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   46.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   46.20 + *
   46.21 + */
   46.22 +
   46.23 +#ifndef _VNET_IF_VARP_H
   46.24 +#define _VNET_IF_VARP_H
   46.25 +
   46.26 +typedef struct Vmac {
   46.27 +    unsigned char mac[ETH_ALEN];
   46.28 +} Vmac;
   46.29 +
   46.30 +enum {
   46.31 +    VARP_ID          = 1,
   46.32 +    VARP_OP_REQUEST  = 1,
   46.33 +    VARP_OP_ANNOUNCE = 2,
   46.34 +};
   46.35 +
   46.36 +typedef struct VnetMsgHdr {
   46.37 +    uint16_t id;
   46.38 +    uint16_t opcode;
   46.39 +} __attribute__((packed)) VnetMsgHdr;
   46.40 +
   46.41 +typedef struct VarpHdr {
   46.42 +    VnetMsgHdr;
   46.43 +    uint32_t vnet;
   46.44 +    Vmac vmac;
   46.45 +    uint32_t addr;
   46.46 +} __attribute__((packed)) VarpHdr;
   46.47 +
   46.48 +/** Default address for varp/vnet broadcasts: 224.10.0.1 */
   46.49 +#define VARP_MCAST_ADDR     0xe00a0001
   46.50 +
   46.51 +/** UDP port to use for varp protocol. */
   46.52 +#define VARP_PORT           1798
   46.53 +
   46.54 +
   46.55 +
   46.56 +#endif /* ! _VNET_IF_VARP_H */
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/tools/vnet/vnet-module/linux/pfkeyv2.h	Wed Nov 24 18:22:43 2004 +0000
    47.3 @@ -0,0 +1,329 @@
    47.4 +/* PF_KEY user interface, this is defined by rfc2367 so
    47.5 + * do not make arbitrary modifications or else this header
    47.6 + * file will not be compliant.
    47.7 + */
    47.8 +
    47.9 +#ifndef _LINUX_PFKEY2_H
   47.10 +#define _LINUX_PFKEY2_H
   47.11 +
   47.12 +#include <linux/types.h>
   47.13 +
   47.14 +#define PF_KEY_V2		2
   47.15 +#define PFKEYV2_REVISION	199806L
   47.16 +
   47.17 +struct sadb_msg {
   47.18 +	uint8_t		sadb_msg_version;
   47.19 +	uint8_t		sadb_msg_type;
   47.20 +	uint8_t		sadb_msg_errno;
   47.21 +	uint8_t		sadb_msg_satype;
   47.22 +	uint16_t	sadb_msg_len;
   47.23 +	uint16_t	sadb_msg_reserved;
   47.24 +	uint32_t	sadb_msg_seq;
   47.25 +	uint32_t	sadb_msg_pid;
   47.26 +} __attribute__((packed));
   47.27 +/* sizeof(struct sadb_msg) == 16 */
   47.28 +
   47.29 +struct sadb_ext {
   47.30 +	uint16_t	sadb_ext_len;
   47.31 +	uint16_t	sadb_ext_type;
   47.32 +} __attribute__((packed));
   47.33 +/* sizeof(struct sadb_ext) == 4 */
   47.34 +
   47.35 +struct sadb_sa {
   47.36 +	uint16_t	sadb_sa_len;
   47.37 +	uint16_t	sadb_sa_exttype;
   47.38 +	uint32_t	sadb_sa_spi;
   47.39 +	uint8_t		sadb_sa_replay;
   47.40 +	uint8_t		sadb_sa_state;
   47.41 +	uint8_t		sadb_sa_auth;
   47.42 +	uint8_t		sadb_sa_encrypt;
   47.43 +	uint32_t	sadb_sa_flags;
   47.44 +} __attribute__((packed));
   47.45 +/* sizeof(struct sadb_sa) == 16 */
   47.46 +
   47.47 +struct sadb_lifetime {
   47.48 +	uint16_t	sadb_lifetime_len;
   47.49 +	uint16_t	sadb_lifetime_exttype;
   47.50 +	uint32_t	sadb_lifetime_allocations;
   47.51 +	uint64_t	sadb_lifetime_bytes;
   47.52 +	uint64_t	sadb_lifetime_addtime;
   47.53 +	uint64_t	sadb_lifetime_usetime;
   47.54 +} __attribute__((packed));
   47.55 +/* sizeof(struct sadb_lifetime) == 32 */
   47.56 +
   47.57 +struct sadb_address {
   47.58 +	uint16_t	sadb_address_len;
   47.59 +	uint16_t	sadb_address_exttype;
   47.60 +	uint8_t		sadb_address_proto;
   47.61 +	uint8_t		sadb_address_prefixlen;
   47.62 +	uint16_t	sadb_address_reserved;
   47.63 +} __attribute__((packed));
   47.64 +/* sizeof(struct sadb_address) == 8 */
   47.65 +
   47.66 +struct sadb_key {
   47.67 +	uint16_t	sadb_key_len;
   47.68 +	uint16_t	sadb_key_exttype;
   47.69 +	uint16_t	sadb_key_bits;
   47.70 +	uint16_t	sadb_key_reserved;
   47.71 +} __attribute__((packed));
   47.72 +/* sizeof(struct sadb_key) == 8 */
   47.73 +
   47.74 +struct sadb_ident {
   47.75 +	uint16_t	sadb_ident_len;
   47.76 +	uint16_t	sadb_ident_exttype;
   47.77 +	uint16_t	sadb_ident_type;
   47.78 +	uint16_t	sadb_ident_reserved;
   47.79 +	uint64_t	sadb_ident_id;
   47.80 +} __attribute__((packed));
   47.81 +/* sizeof(struct sadb_ident) == 16 */
   47.82 +
   47.83 +struct sadb_sens {
   47.84 +	uint16_t	sadb_sens_len;
   47.85 +	uint16_t	sadb_sens_exttype;
   47.86 +	uint32_t	sadb_sens_dpd;
   47.87 +	uint8_t		sadb_sens_sens_level;
   47.88 +	uint8_t		sadb_sens_sens_len;
   47.89 +	uint8_t		sadb_sens_integ_level;
   47.90 +	uint8_t		sadb_sens_integ_len;
   47.91 +	uint32_t	sadb_sens_reserved;
   47.92 +} __attribute__((packed));
   47.93 +/* sizeof(struct sadb_sens) == 16 */
   47.94 +
   47.95 +/* followed by:
   47.96 +	uint64_t	sadb_sens_bitmap[sens_len];
   47.97 +	uint64_t	sadb_integ_bitmap[integ_len];  */
   47.98 +
   47.99 +struct sadb_prop {
  47.100 +	uint16_t	sadb_prop_len;
  47.101 +	uint16_t	sadb_prop_exttype;
  47.102 +	uint8_t		sadb_prop_replay;
  47.103 +	uint8_t		sadb_prop_reserved[3];
  47.104 +} __attribute__((packed));
  47.105 +/* sizeof(struct sadb_prop) == 8 */
  47.106 +
  47.107 +/* followed by:
  47.108 +	struct sadb_comb sadb_combs[(sadb_prop_len +
  47.109 +		sizeof(uint64_t) - sizeof(struct sadb_prop)) /
  47.110 +		sizeof(strut sadb_comb)]; */
  47.111 +
  47.112 +struct sadb_comb {
  47.113 +	uint8_t		sadb_comb_auth;
  47.114 +	uint8_t		sadb_comb_encrypt;
  47.115 +	uint16_t	sadb_comb_flags;
  47.116 +	uint16_t	sadb_comb_auth_minbits;
  47.117 +	uint16_t	sadb_comb_auth_maxbits;
  47.118 +	uint16_t	sadb_comb_encrypt_minbits;
  47.119 +	uint16_t	sadb_comb_encrypt_maxbits;
  47.120 +	uint32_t	sadb_comb_reserved;
  47.121 +	uint32_t	sadb_comb_soft_allocations;
  47.122 +	uint32_t	sadb_comb_hard_allocations;
  47.123 +	uint64_t	sadb_comb_soft_bytes;
  47.124 +	uint64_t	sadb_comb_hard_bytes;
  47.125 +	uint64_t	sadb_comb_soft_addtime;
  47.126 +	uint64_t	sadb_comb_hard_addtime;
  47.127 +	uint64_t	sadb_comb_soft_usetime;
  47.128 +	uint64_t	sadb_comb_hard_usetime;
  47.129 +} __attribute__((packed));
  47.130 +/* sizeof(struct sadb_comb) == 72 */
  47.131 +
  47.132 +struct sadb_supported {
  47.133 +	uint16_t	sadb_supported_len;
  47.134 +	uint16_t	sadb_supported_exttype;
  47.135 +	uint32_t	sadb_supported_reserved;
  47.136 +} __attribute__((packed));
  47.137 +/* sizeof(struct sadb_supported) == 8 */
  47.138 +
  47.139 +/* followed by:
  47.140 +	struct sadb_alg sadb_algs[(sadb_supported_len +
  47.141 +		sizeof(uint64_t) - sizeof(struct sadb_supported)) /
  47.142 +		sizeof(struct sadb_alg)]; */
  47.143 +
  47.144 +struct sadb_alg {
  47.145 +	uint8_t		sadb_alg_id;
  47.146 +	uint8_t		sadb_alg_ivlen;
  47.147 +	uint16_t	sadb_alg_minbits;
  47.148 +	uint16_t	sadb_alg_maxbits;
  47.149 +	uint16_t	sadb_alg_reserved;
  47.150 +} __attribute__((packed));
  47.151 +/* sizeof(struct sadb_alg) == 8 */
  47.152 +
  47.153 +struct sadb_spirange {
  47.154 +	uint16_t	sadb_spirange_len;
  47.155 +	uint16_t	sadb_spirange_exttype;
  47.156 +	uint32_t	sadb_spirange_min;
  47.157 +	uint32_t	sadb_spirange_max;
  47.158 +	uint32_t	sadb_spirange_reserved;
  47.159 +} __attribute__((packed));
  47.160 +/* sizeof(struct sadb_spirange) == 16 */
  47.161 +
  47.162 +struct sadb_x_kmprivate {
  47.163 +	uint16_t	sadb_x_kmprivate_len;
  47.164 +	uint16_t	sadb_x_kmprivate_exttype;
  47.165 +	u_int32_t	sadb_x_kmprivate_reserved;
  47.166 +} __attribute__((packed));
  47.167 +/* sizeof(struct sadb_x_kmprivate) == 8 */
  47.168 +
  47.169 +struct sadb_x_sa2 {
  47.170 +	uint16_t	sadb_x_sa2_len;
  47.171 +	uint16_t	sadb_x_sa2_exttype;
  47.172 +	uint8_t		sadb_x_sa2_mode;
  47.173 +	uint8_t		sadb_x_sa2_reserved1;
  47.174 +	uint16_t	sadb_x_sa2_reserved2;
  47.175 +	uint32_t	sadb_x_sa2_sequence;
  47.176 +	uint32_t	sadb_x_sa2_reqid;
  47.177 +} __attribute__((packed));
  47.178 +/* sizeof(struct sadb_x_sa2) == 16 */
  47.179 +
  47.180 +struct sadb_x_policy {
  47.181 +	uint16_t	sadb_x_policy_len;
  47.182 +	uint16_t	sadb_x_policy_exttype;
  47.183 +	uint16_t	sadb_x_policy_type;
  47.184 +	uint8_t		sadb_x_policy_dir;
  47.185 +	uint8_t		sadb_x_policy_reserved;
  47.186 +	uint32_t	sadb_x_policy_id;
  47.187 +	uint32_t	sadb_x_policy_reserved2;
  47.188 +} __attribute__((packed));
  47.189 +/* sizeof(struct sadb_x_policy) == 16 */
  47.190 +
  47.191 +struct sadb_x_ipsecrequest {
  47.192 +	uint16_t	sadb_x_ipsecrequest_len;
  47.193 +	uint16_t	sadb_x_ipsecrequest_proto;
  47.194 +	uint8_t		sadb_x_ipsecrequest_mode;
  47.195 +	uint8_t		sadb_x_ipsecrequest_level;
  47.196 +	uint16_t	sadb_x_ipsecrequest_reqid;
  47.197 +} __attribute__((packed));
  47.198 +/* sizeof(struct sadb_x_ipsecrequest) == 16 */
  47.199 +
  47.200 +/* This defines the TYPE of Nat Traversal in use.  Currently only one
  47.201 + * type of NAT-T is supported, draft-ietf-ipsec-udp-encaps-06
  47.202 + */
  47.203 +struct sadb_x_nat_t_type {
  47.204 +	uint16_t	sadb_x_nat_t_type_len;
  47.205 +	uint16_t	sadb_x_nat_t_type_exttype;
  47.206 +	uint8_t		sadb_x_nat_t_type_type;
  47.207 +	uint8_t		sadb_x_nat_t_type_reserved[3];
  47.208 +} __attribute__((packed));
  47.209 +/* sizeof(struct sadb_x_nat_t_type) == 8 */
  47.210 +
  47.211 +/* Pass a NAT Traversal port (Source or Dest port) */
  47.212 +struct sadb_x_nat_t_port {
  47.213 +	uint16_t	sadb_x_nat_t_port_len;
  47.214 +	uint16_t	sadb_x_nat_t_port_exttype;
  47.215 +	uint16_t	sadb_x_nat_t_port_port;
  47.216 +	uint16_t	sadb_x_nat_t_port_reserved;
  47.217 +} __attribute__((packed));
  47.218 +/* sizeof(struct sadb_x_nat_t_port) == 8 */
  47.219 +
  47.220 +/* Message types */
  47.221 +#define SADB_RESERVED		0
  47.222 +#define SADB_GETSPI		1
  47.223 +#define SADB_UPDATE		2
  47.224 +#define SADB_ADD		3
  47.225 +#define SADB_DELETE		4
  47.226 +#define SADB_GET		5
  47.227 +#define SADB_ACQUIRE		6
  47.228 +#define SADB_REGISTER		7
  47.229 +#define SADB_EXPIRE		8
  47.230 +#define SADB_FLUSH		9
  47.231 +#define SADB_DUMP		10
  47.232 +#define SADB_X_PROMISC		11
  47.233 +#define SADB_X_PCHANGE		12
  47.234 +#define SADB_X_SPDUPDATE	13
  47.235 +#define SADB_X_SPDADD		14
  47.236 +#define SADB_X_SPDDELETE	15
  47.237 +#define SADB_X_SPDGET		16
  47.238 +#define SADB_X_SPDACQUIRE	17
  47.239 +#define SADB_X_SPDDUMP		18
  47.240 +#define SADB_X_SPDFLUSH		19
  47.241 +#define SADB_X_SPDSETIDX	20
  47.242 +#define SADB_X_SPDEXPIRE	21
  47.243 +#define SADB_X_SPDDELETE2	22
  47.244 +#define SADB_X_NAT_T_NEW_MAPPING	23
  47.245 +#define SADB_MAX		23
  47.246 +
  47.247 +/* Security Association flags */
  47.248 +#define SADB_SAFLAGS_PFS	1
  47.249 +
  47.250 +/* Security Association states */
  47.251 +#define SADB_SASTATE_LARVAL	0
  47.252 +#define SADB_SASTATE_MATURE	1
  47.253 +#define SADB_SASTATE_DYING	2
  47.254 +#define SADB_SASTATE_DEAD	3
  47.255 +#define SADB_SASTATE_MAX	3
  47.256 +
  47.257 +/* Security Association types */
  47.258 +#define SADB_SATYPE_UNSPEC	0
  47.259 +#define SADB_SATYPE_AH		2
  47.260 +#define SADB_SATYPE_ESP		3
  47.261 +#define SADB_SATYPE_RSVP	5
  47.262 +#define SADB_SATYPE_OSPFV2	6
  47.263 +#define SADB_SATYPE_RIPV2	7
  47.264 +#define SADB_SATYPE_MIP		8
  47.265 +#define SADB_X_SATYPE_IPCOMP	9
  47.266 +#define SADB_SATYPE_MAX		9
  47.267 +
  47.268 +/* Authentication algorithms */
  47.269 +#define SADB_AALG_NONE			0
  47.270 +#define SADB_AALG_MD5HMAC		2
  47.271 +#define SADB_AALG_SHA1HMAC		3
  47.272 +#define SADB_X_AALG_SHA2_256HMAC	5
  47.273 +#define SADB_X_AALG_SHA2_384HMAC	6
  47.274 +#define SADB_X_AALG_SHA2_512HMAC	7
  47.275 +#define SADB_X_AALG_RIPEMD160HMAC	8
  47.276 +#define SADB_X_AALG_NULL		251	/* kame */
  47.277 +#define SADB_AALG_MAX			251
  47.278 +
  47.279 +/* Encryption algorithms */
  47.280 +#define SADB_EALG_NONE			0
  47.281 +#define SADB_EALG_DESCBC		2
  47.282 +#define SADB_EALG_3DESCBC		3
  47.283 +#define SADB_X_EALG_CASTCBC		6
  47.284 +#define SADB_X_EALG_BLOWFISHCBC		7
  47.285 +#define SADB_EALG_NULL			11
  47.286 +#define SADB_X_EALG_AESCBC		12
  47.287 +#define SADB_EALG_MAX			12
  47.288 +
  47.289 +/* Compression algorithms */
  47.290 +#define SADB_X_CALG_NONE		0
  47.291 +#define SADB_X_CALG_OUI			1
  47.292 +#define SADB_X_CALG_DEFLATE		2
  47.293 +#define SADB_X_CALG_LZS			3
  47.294 +#define SADB_X_CALG_LZJH		4
  47.295 +#define SADB_X_CALG_MAX			4
  47.296 +
  47.297 +/* Extension Header values */
  47.298 +#define SADB_EXT_RESERVED		0
  47.299 +#define SADB_EXT_SA			1
  47.300 +#define SADB_EXT_LIFETIME_CURRENT	2
  47.301 +#define SADB_EXT_LIFETIME_HARD		3
  47.302 +#define SADB_EXT_LIFETIME_SOFT		4
  47.303 +#define SADB_EXT_ADDRESS_SRC		5
  47.304 +#define SADB_EXT_ADDRESS_DST		6
  47.305 +#define SADB_EXT_ADDRESS_PROXY		7
  47.306 +#define SADB_EXT_KEY_AUTH		8
  47.307 +#define SADB_EXT_KEY_ENCRYPT		9
  47.308 +#define SADB_EXT_IDENTITY_SRC		10
  47.309 +#define SADB_EXT_IDENTITY_DST		11
  47.310 +#define SADB_EXT_SENSITIVITY		12
  47.311 +#define SADB_EXT_PROPOSAL		13
  47.312 +#define SADB_EXT_SUPPORTED_AUTH		14
  47.313 +#define SADB_EXT_SUPPORTED_ENCRYPT	15
  47.314 +#define SADB_EXT_SPIRANGE		16
  47.315 +#define SADB_X_EXT_KMPRIVATE		17
  47.316 +#define SADB_X_EXT_POLICY		18
  47.317 +#define SADB_X_EXT_SA2			19
  47.318 +/* The next four entries are for setting up NAT Traversal */
  47.319 +#define SADB_X_EXT_NAT_T_TYPE		20
  47.320 +#define SADB_X_EXT_NAT_T_SPORT		21
  47.321 +#define SADB_X_EXT_NAT_T_DPORT		22
  47.322 +#define SADB_X_EXT_NAT_T_OA		23
  47.323 +#define SADB_EXT_MAX			23
  47.324 +
  47.325 +/* Identity Extension values */
  47.326 +#define SADB_IDENTTYPE_RESERVED	0
  47.327 +#define SADB_IDENTTYPE_PREFIX	1
  47.328 +#define SADB_IDENTTYPE_FQDN	2
  47.329 +#define SADB_IDENTTYPE_USERFQDN	3
  47.330 +#define SADB_IDENTTYPE_MAX	3
  47.331 +
  47.332 +#endif /* !(_LINUX_PFKEY2_H) */
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/tools/vnet/vnet-module/random.c	Wed Nov 24 18:22:43 2004 +0000
    48.3 @@ -0,0 +1,101 @@
    48.4 +/*
    48.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    48.6 + *
    48.7 + * This program is free software; you can redistribute it and/or modify
    48.8 + * it under the terms of the GNU General Public License as published by the 
    48.9 + * Free Software Foundation; either version 2 of the License, or (at your
   48.10 + * option) any later version.
   48.11 + * 
   48.12 + * This program is distributed in the hope that it will be useful, but
   48.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   48.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   48.15 + * for more details.
   48.16 + *
   48.17 + * You should have received a copy of the GNU General Public License along
   48.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   48.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   48.20 + *
   48.21 + */
   48.22 +#include <linux/config.h>
   48.23 +#include <linux/module.h>
   48.24 +#include <linux/init.h>
   48.25 +#include <linux/sched.h>
   48.26 +#include <linux/random.h>
   48.27 +
   48.28 +#include "hash_table.h"
   48.29 +
   48.30 +#define MODULE_NAME "RANDOM"
   48.31 +#define DEBUG 1
   48.32 +#undef DEBUG
   48.33 +#include "debug.h"
   48.34 +
   48.35 +/** @file
   48.36 + * Source of randomness.
   48.37 + * Current implementation is not enough.
   48.38 + * Needs to be cryptographically strong.
   48.39 + */
   48.40 +
   48.41 +static unsigned long seed = 0;
   48.42 +static unsigned long count = 0;
   48.43 +
   48.44 +static unsigned long stir(unsigned long *a, unsigned long b){
   48.45 +    pseudo_des(a, &b);
   48.46 +    return b;
   48.47 +}    
   48.48 +
   48.49 +/** Get one random byte.
   48.50 + *
   48.51 + * @return random byte
   48.52 + */
   48.53 +int get_random_byte(void){
   48.54 +    return stir(&seed, ++count);
   48.55 +}
   48.56 +
   48.57 +#if 0
   48.58 +/* Get some random bytes.
   48.59 + *
   48.60 + * @param dst destination for the bytes
   48.61 + * @param dst_n number of bytes to get
   48.62 + */
   48.63 +void get_random_bytes(void *dst, int dst_n){
   48.64 +    int i;
   48.65 +    char *p = (char *)dst;
   48.66 +    for(i = 0; i < dst_n; i++){
   48.67 +        *p++ = get_random_byte();
   48.68 +    }
   48.69 +}
   48.70 +#endif
   48.71 +
   48.72 +/** Contribute a random byte.
   48.73 + *
   48.74 + * @param b byte to contribute
   48.75 + */
   48.76 +void add_random_byte(int b){
   48.77 +    stir(&seed, ++count);
   48.78 +    stir(&seed, b);
   48.79 +}
   48.80 +
   48.81 +/** Contribute some random bytes.
   48.82 + *
   48.83 + * @param src bytes to contribute
   48.84 + * @param src_n number of bytes
   48.85 + */
   48.86 +void add_random_bytes(const void *src, int src_n){
   48.87 +    int i;
   48.88 +    char *p = (char *)src;
   48.89 +    for(i = 0; i < src_n; i++){
   48.90 +        add_random_byte(*p++);
   48.91 +    }
   48.92 +}
   48.93 +
   48.94 +int __init random_module_init(void){
   48.95 +    int dummy;
   48.96 +    int tmp = jiffies;
   48.97 +    seed = (unsigned long)&dummy;
   48.98 +    add_random_byte(tmp);
   48.99 +    return 0;
  48.100 +}
  48.101 +
  48.102 +void __exit random_module_exit(void){
  48.103 +}
  48.104 +
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/tools/vnet/vnet-module/random.h	Wed Nov 24 18:22:43 2004 +0000
    49.3 @@ -0,0 +1,30 @@
    49.4 +/*
    49.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    49.6 + *
    49.7 + * This program is free software; you can redistribute it and/or modify
    49.8 + * it under the terms of the GNU General Public License as published by the 
    49.9 + * Free Software Foundation; either version 2 of the License, or (at your
   49.10 + * option) any later version.
   49.11 + * 
   49.12 + * This program is distributed in the hope that it will be useful, but
   49.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   49.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   49.15 + * for more details.
   49.16 + *
   49.17 + * You should have received a copy of the GNU General Public License along
   49.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   49.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   49.20 + *
   49.21 + */
   49.22 +#ifndef __VNET_RANDOM_H__
   49.23 +#define __VNET_RANDOM_H__
   49.24 +
   49.25 +extern int get_random_byte(void);
   49.26 +extern void get_random_bytes(void *dst, int dst_n);
   49.27 +extern void add_random_byte(int b);
   49.28 +extern void add_random_bytes(const void *src, int src_n);
   49.29 +
   49.30 +extern int random_module_init(void);
   49.31 +extern void random_module_exit(void);
   49.32 +
   49.33 +#endif /* ! __VNET_RANDOM_H__ */
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/tools/vnet/vnet-module/sa.c	Wed Nov 24 18:22:43 2004 +0000
    50.3 @@ -0,0 +1,670 @@
    50.4 +/*
    50.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    50.6 + *
    50.7 + * This program is free software; you can redistribute it and/or modify
    50.8 + * it under the terms of the GNU General Public License as published by the 
    50.9 + * Free Software Foundation; either version 2 of the License, or (at your
   50.10 + * option) any later version.
   50.11 + * 
   50.12 + * This program is distributed in the hope that it will be useful, but
   50.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   50.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   50.15 + * for more details.
   50.16 + *
   50.17 + * You should have received a copy of the GNU General Public License along
   50.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   50.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   50.20 + *
   50.21 + */
   50.22 +#include <linux/config.h>
   50.23 +#include <linux/kernel.h>
   50.24 +
   50.25 +#include <net/ip.h>
   50.26 +#include <net/protocol.h>
   50.27 +#include <net/route.h>
   50.28 +#include <linux/skbuff.h>
   50.29 +
   50.30 +#include <linux/in.h>
   50.31 +#include <linux/inet.h>
   50.32 +#include <linux/netdevice.h>
   50.33 +
   50.34 +#include <sa.h>
   50.35 +#include <sa_algorithm.h>
   50.36 +#include "hash_table.h"
   50.37 +#include "allocate.h"
   50.38 +
   50.39 +#define MODULE_NAME "IPSEC"
   50.40 +#define DEBUG 1
   50.41 +#undef DEBUG
   50.42 +#include "debug.h"
   50.43 +
   50.44 +/** @file IPSEC Security Association (SA).
   50.45 + */
   50.46 +
   50.47 +/** Maximum number of protocols.*/
   50.48 +#define INET_PROTOCOL_MAX 256
   50.49 +
   50.50 +/** Table of SA types indexed by protocol. */
   50.51 +static SAType *sa_type[INET_PROTOCOL_MAX] = {};
   50.52 +
   50.53 +/** Hash a protocol number.
   50.54 + *
   50.55 + * @param protocol protocol number
   50.56 + * @return hashcode
   50.57 + */
   50.58 +static inline unsigned char InetProtocol_hash(int protocol){
   50.59 +    return (protocol) & (INET_PROTOCOL_MAX - 1);
   50.60 +}
   50.61 +
   50.62 +/** Register an SA type.
   50.63 + * It is an error if an SA type is already registered for the protocol.
   50.64 + *
   50.65 + * @param type SA type
   50.66 + * @return 0 on success, error code otherwise
   50.67 + */
   50.68 +int SAType_add(SAType *type){
   50.69 +    int err = -EINVAL;
   50.70 +    int hash;
   50.71 +    if(!type) goto exit;
   50.72 +    hash = InetProtocol_hash(type->protocol);
   50.73 +    if(sa_type[hash]) goto exit;
   50.74 +    err = 0;
   50.75 +    sa_type[hash] = type;
   50.76 +  exit:
   50.77 +    return err;
   50.78 +}
   50.79 +
   50.80 +/** Deregister an SA type.
   50.81 + * It is an error if no SA type is registered for the protocol.
   50.82 + *
   50.83 + * @param type SA type
   50.84 + * @return 0 on success, error code otherwise
   50.85 + */
   50.86 +int SAType_del(SAType *type){
   50.87 +    int err = -EINVAL;
   50.88 +    int hash;
   50.89 +    if(!type) goto exit;
   50.90 +    hash = InetProtocol_hash(type->protocol);
   50.91 +    if(!sa_type[hash]) goto exit;
   50.92 +    err = 0;
   50.93 +    sa_type[hash] = NULL;
   50.94 +  exit:
   50.95 +    return err;
   50.96 +}
   50.97 +
   50.98 +int SAType_get(int protocol, SAType **type){
   50.99 +   int err = -ENOENT;
  50.100 +   int hash;
  50.101 +   hash = InetProtocol_hash(protocol);
  50.102 +   *type = sa_type[hash];
  50.103 +   if(!*type) goto exit;
  50.104 +   err = 0;
  50.105 +  exit:
  50.106 +   return err;
  50.107 +}
  50.108 +
  50.109 +/* Defeat compiler warnings about unused functions. */
  50.110 +static int sa_key_check(SAKey *key, enum sa_alg_type type) __attribute__((unused));
  50.111 +static u32 random_spi(void) __attribute__((unused));
  50.112 +static u32 generate_key(u32 key, u32 offset, u32 spi) __attribute__((unused));
  50.113 +
  50.114 +/** Check a key has an acceptable length for an algorithm.
  50.115 + *
  50.116 + * @param key key
  50.117 + * @param type algorithm
  50.118 + * @return 0 on success, error code otherwise
  50.119 + */
  50.120 +static int sa_key_check(SAKey *key, enum sa_alg_type type){
  50.121 +    return 0;
  50.122 +}
  50.123 +
  50.124 +static unsigned long sa_spi_counter = 0;
  50.125 +
  50.126 +/** Generate a random spi.
  50.127 + * Uses a hashed counter.
  50.128 + *
  50.129 + * @return spi
  50.130 + */
  50.131 +static u32 random_spi(void){
  50.132 +    unsigned long left, right = 0;
  50.133 +    u32 spi;
  50.134 +    do{
  50.135 +        left = sa_spi_counter++;
  50.136 +        pseudo_des(&left, &right);
  50.137 +        spi = right;
  50.138 +    } while(!spi);
  50.139 +    return spi;
  50.140 +}
  50.141 +
  50.142 +/** Mangle some input to generate output.
  50.143 + * This is used to derive spis and keying material from secrets,
  50.144 + * so it probably ought to be cryptographically strong.
  50.145 + * Probably ought to use a good hash (sha1) or cipher (aes).
  50.146 + *
  50.147 + * @param input input values
  50.148 + * @param n number of values
  50.149 + * @return mangled value
  50.150 + */
  50.151 +static u32 mangle(u32 input[], int n){
  50.152 +    unsigned long left = 0, right = 0;
  50.153 +    int i;
  50.154 +    for(i=0; i<n; i++){
  50.155 +        left ^= input[i];
  50.156 +        pseudo_des(&left, &right);
  50.157 +    }
  50.158 +    return (u32)right;
  50.159 +}
  50.160 +
  50.161 +/** Generate a spi for a given protocol and address, using a secret key.
  50.162 + * The offset is used when it is necessary to generate more than one spi
  50.163 + * for the same protocol and address.
  50.164 + *
  50.165 + * @param key key
  50.166 + * @param offset offset
  50.167 + * @param protocol protocol
  50.168 + * @param addr IP address
  50.169 + * @return spi
  50.170 + */
  50.171 +static u32 generate_spi(u32 key, u32 offset, u32 protocol, u32 addr){
  50.172 +    u32 input[] = { key, offset, protocol, addr };
  50.173 +    u32 spi;
  50.174 +    dprintf(">\n");
  50.175 +    spi = mangle(input, 4);
  50.176 +    dprintf("< spi=%x\n", spi);
  50.177 +    return spi;
  50.178 +}
  50.179 +
  50.180 +/** Generate keying material for a given spi, based on a
  50.181 + * secret.
  50.182 + *
  50.183 + * @param key secret
  50.184 + * @param offset offset
  50.185 + * @param spi spi
  50.186 + * @return keying material
  50.187 + */
  50.188 +static u32 generate_key(u32 key, u32 offset, u32 spi){
  50.189 +    u32 input[] = { key, offset, spi };
  50.190 +    return mangle(input, 3);
  50.191 +}    
  50.192 +
  50.193 +/** Allocate a spi.
  50.194 + * Want to use random ones.
  50.195 + * So check for ones not in use.
  50.196 + *
  50.197 + * When using static keying, both ends need to agree on key.
  50.198 + * How does that work? Also, will suddenly get traffic using a spi,
  50.199 + * and will have to create SA then. Or need to create in advance.
  50.200 + * But can't do that because don't know peers.
  50.201 + * When get message on a spi that doesn't exist - do what?
  50.202 + * Use a spi related to the destination addr and a secret.
  50.203 + * Then receiver can check if spi is ok and create SA on demand.
  50.204 + * Use hash of key, protocol, addr to generate. Then have to check
  50.205 + * for in-use because of potential collisions. Receiver can do the
  50.206 + * same hash and check spi is in usable range. Then derive keys from
  50.207 + * the spi (using another secret).
  50.208 + *
  50.209 + * @param key spi generation key
  50.210 + * @param protocol protocol
  50.211 + * @param addr IP address
  50.212 + * @param spip return parameter for spi
  50.213 + * @return 0 on success, error code otherwise
  50.214 + */
  50.215 +int sa_spi_alloc(u32 key, u32 protocol, u32 addr, u32 *spip){
  50.216 +    int err = 0;
  50.217 +    int i = 0, n = 100;
  50.218 +    u32 spi;
  50.219 +    for(i = 0; i < n; i++, spi++){
  50.220 +        spi = generate_spi(key, i, protocol, addr);
  50.221 +        if(!spi) continue;
  50.222 +        if(!sa_table_lookup_spi(spi, protocol, addr)){
  50.223 +            *spip = spi;
  50.224 +            goto exit;
  50.225 +        }
  50.226 +    }
  50.227 +    err = -ENOMEM;
  50.228 +  exit:
  50.229 +    return err;
  50.230 +}
  50.231 +
  50.232 +/** Table of SAs. Indexed by unique id and spi/protocol/addr triple.
  50.233 + */
  50.234 +static HashTable *sa_table = NULL;
  50.235 +
  50.236 +static u32 sa_id = 1;
  50.237 +
  50.238 +/** Hash an SA id.
  50.239 + *
  50.240 + * @param id SA id
  50.241 + * @return hashcode
  50.242 + */
  50.243 +static inline Hashcode sa_table_hash_id(u32 id){
  50.244 +    return hash_ul(id);
  50.245 +}
  50.246 +
  50.247 +/** Hash SA spi/protocol/addr.
  50.248 + *
  50.249 + * @param spi spi
  50.250 + * @param protocol protocol
  50.251 + * @param addr IP address
  50.252 + * @return hashcode
  50.253 + */
  50.254 +static inline Hashcode sa_table_hash_spi(u32 spi, u32 protocol, u32 addr){
  50.255 +    Hashcode h = 0;
  50.256 +    h = hash_2ul(spi, protocol);
  50.257 +    h = hash_hul(h, addr);
  50.258 +    return h;
  50.259 +}
  50.260 +
  50.261 +/** Test if an SA entry has a given value.
  50.262 + *
  50.263 + * @param arg contains SA pointer
  50.264 + * @param table hashtable
  50.265 + * @param entry entry containing SA
  50.266 + * @return 1 if it does, 0 otherwise
  50.267 + */
  50.268 +static int sa_table_state_fn(TableArg arg, HashTable *table, HTEntry *entry){
  50.269 +    return entry->value == arg.ptr;
  50.270 +}
  50.271 +
  50.272 +/** Test if an SA entry has a given id.
  50.273 + *
  50.274 + * @param arg contains SA id
  50.275 + * @param table hashtable
  50.276 + * @param entry entry containing SA
  50.277 + * @return 1 if it does, 0 otherwise
  50.278 + */
  50.279 +static int sa_table_id_fn(TableArg arg, HashTable *table, HTEntry *entry){
  50.280 +    SAState *state = entry->value;
  50.281 +    u32 id = arg.ul;
  50.282 +    return state->ident.id == id;
  50.283 +}
  50.284 +
  50.285 +/** Test if an SA entry has a given spi/protocol/addr.
  50.286 + *
  50.287 + * @param arg contains SAIdent pointer
  50.288 + * @param table hashtable
  50.289 + * @param entry entry containing SA
  50.290 + * @return 1 if it does, 0 otherwise
  50.291 + */
  50.292 +static int sa_table_spi_fn(TableArg arg, HashTable *table, HTEntry *entry){
  50.293 +    SAState *state = entry->value;
  50.294 +    SAIdent *ident = arg.ptr;
  50.295 +    return state->ident.spi      == ident->spi
  50.296 +        && state->ident.protocol == ident->protocol
  50.297 +        && state->ident.addr     == ident->addr;
  50.298 +}
  50.299 +
  50.300 +/** Free an SA entry. Decrements the SA refcount and frees the entry.
  50.301 + *
  50.302 + * @param table containing table
  50.303 + * @param entry to free
  50.304 + */
  50.305 +void sa_table_free_fn(HashTable *table, HTEntry *entry){
  50.306 +    if(!entry) return;
  50.307 +    if(entry->value){
  50.308 +        SAState *state = entry->value;
  50.309 +        SAState_decref(state);
  50.310 +    }
  50.311 +    deallocate(entry);
  50.312 +}
  50.313 +
  50.314 +/** Initialize the SA table.
  50.315 + *
  50.316 + * @return 0 on success, error code otherwise
  50.317 + */
  50.318 +int sa_table_init(void){
  50.319 +    int err = 0;
  50.320 +    sa_table = HashTable_new(0);
  50.321 +    if(!sa_table){
  50.322 +        err = -ENOMEM;
  50.323 +        goto exit;
  50.324 +    }
  50.325 +    sa_table->entry_free_fn = sa_table_free_fn;
  50.326 +
  50.327 +  exit:
  50.328 +    return err;
  50.329 +}
  50.330 +
  50.331 +void sa_table_exit(void){
  50.332 +    HashTable_free(sa_table);
  50.333 +}
  50.334 +
  50.335 +/** Remove an SA from the table.
  50.336 + *
  50.337 + * @param state SA
  50.338 + */
  50.339 +int sa_table_delete(SAState *state){
  50.340 +    int count = 0;
  50.341 +    Hashcode h1, h2;
  50.342 +    TableArg arg = { .ptr = state };
  50.343 +    // Remove by id.
  50.344 +    h1 = sa_table_hash_id(state->ident.id);
  50.345 +    count += HashTable_remove_entry(sa_table, h1, sa_table_state_fn, arg);
  50.346 +    // Remove by spi/protocol/addr if spi nonzero.
  50.347 +    if(!state->ident.spi) goto exit;
  50.348 +    h2 = sa_table_hash_spi(state->ident.spi, state->ident.protocol, state->ident.addr);
  50.349 +    if(h1 == h2) goto exit;
  50.350 +    count += HashTable_remove_entry(sa_table, h2, sa_table_state_fn, arg);
  50.351 +  exit:
  50.352 +    return count;
  50.353 +}
  50.354 +
  50.355 +/** Add an SA to the table.
  50.356 + * The SA is indexed by id and spi/protocol/addr (if the spi is non-zero).
  50.357 + *
  50.358 + * @param state SA
  50.359 + * @return 0 on success, error code otherwise
  50.360 + */
  50.361 +int sa_table_add(SAState *state){
  50.362 +    int err = 0;
  50.363 +    Hashcode h1, h2;
  50.364 +    int entries = 0;
  50.365 +
  50.366 +    dprintf(">\n");
  50.367 +    // Index by id.
  50.368 +    h1 = sa_table_hash_id(state->ident.id);
  50.369 +    if(!HashTable_add_entry(sa_table, h1, HKEY(state->ident.id), state)){
  50.370 +        err = -ENOMEM;
  50.371 +        goto exit;
  50.372 +    }
  50.373 +    entries++;
  50.374 +    SAState_incref(state);
  50.375 +    // Index by spi/protocol/addr if spi non-zero.
  50.376 +    if(state->ident.spi){
  50.377 +        h2 = sa_table_hash_spi(state->ident.spi, state->ident.protocol, state->ident.addr);
  50.378 +        if(h1 != h2){
  50.379 +            if(!HashTable_add_entry(sa_table, h2, HKEY(state->ident.id), state)){
  50.380 +                err = -ENOMEM;
  50.381 +                goto exit;
  50.382 +            }
  50.383 +            entries++;
  50.384 +            SAState_incref(state);
  50.385 +        }
  50.386 +    }
  50.387 +  exit:
  50.388 +    if(err && entries){
  50.389 +        sa_table_delete(state);
  50.390 +    }
  50.391 +    dprintf("< err=%d\n", err);
  50.392 +    return err;
  50.393 +}
  50.394 +
  50.395 +
  50.396 +/** Find an SA by spi/protocol/addr.
  50.397 + * Increments the SA refcount on success.
  50.398 + *
  50.399 + * @param spi spi
  50.400 + * @param protocol protocol
  50.401 + * @param addr IP address
  50.402 + * @return SA or NULL
  50.403 + */
  50.404 +SAState * sa_table_lookup_spi(u32 spi, u32 protocol, u32 addr){
  50.405 +    SAState *state = NULL;
  50.406 +    Hashcode h;
  50.407 +    SAIdent id = {
  50.408 +        .spi      = spi,
  50.409 +        .protocol = protocol,
  50.410 +        .addr     = addr };
  50.411 +    TableArg arg = { .ptr = &id };
  50.412 +    HTEntry *entry = NULL;
  50.413 +
  50.414 +    h = sa_table_hash_spi(spi, protocol, addr);
  50.415 +    entry = HashTable_find_entry(sa_table, h, sa_table_spi_fn, arg);
  50.416 +    if(entry){
  50.417 +        state = entry->value;
  50.418 +        SAState_incref(state);
  50.419 +    }
  50.420 +    return state;
  50.421 +}
  50.422 +
  50.423 +/** Find an SA by unique id.
  50.424 + * Increments the SA refcount on success.
  50.425 + *
  50.426 + * @param id id
  50.427 + * @return SA or NULL
  50.428 + */
  50.429 +SAState * sa_table_lookup_id(u32 id){
  50.430 +    Hashcode h;
  50.431 +    TableArg arg = { .ul = id };
  50.432 +    HTEntry *entry = NULL;
  50.433 +    SAState *state = NULL;
  50.434 +
  50.435 +    dprintf("> id=%u\n", id);
  50.436 +    h = sa_table_hash_id(id);
  50.437 +    entry = HashTable_find_entry(sa_table, h, sa_table_id_fn, arg);
  50.438 +    if(entry){
  50.439 +        state = entry->value;
  50.440 +        SAState_incref(state);
  50.441 +    }
  50.442 +    dprintf("< state=%p\n", state);
  50.443 +    return state;
  50.444 +}
  50.445 +
  50.446 +/** Replace an existing SA by another in the table.
  50.447 + * The existing SA is not removed if the new one cannot be added.
  50.448 + *
  50.449 + * @param existing SA to replace
  50.450 + * @param state new SA
  50.451 + * @return 0 on success, error code otherwise
  50.452 + */
  50.453 +static int sa_table_replace(SAState *existing, SAState *state){
  50.454 +    int err = 0;
  50.455 +    // Need check for in-use?
  50.456 +    
  50.457 +    dprintf(">\n");
  50.458 +    if(existing->keying.state != SA_STATE_ACQUIRE){
  50.459 +        err = -EINVAL;
  50.460 +        goto exit;
  50.461 +    }
  50.462 +    // replace it.
  50.463 +    err = sa_table_add(state);
  50.464 +    if(err) goto exit;
  50.465 +    sa_table_delete(existing);
  50.466 +  exit:
  50.467 +    dprintf("< err=%d\n", err);
  50.468 +    return err;
  50.469 +}
  50.470 +
  50.471 +/** Allocate an SA.
  50.472 + *
  50.473 + * @return SA or NULL
  50.474 + */
  50.475 +SAState *SAState_alloc(void){
  50.476 +    SAState *state;
  50.477 +    
  50.478 +    dprintf(">\n");
  50.479 +    state = kmalloc(sizeof(SAState), GFP_ATOMIC);
  50.480 +    if(!state) goto exit;
  50.481 +    *state = (SAState){};
  50.482 +    atomic_set(&state->refcount, 1);
  50.483 +    state->lock = SPIN_LOCK_UNLOCKED;
  50.484 +  exit:
  50.485 +    dprintf("< state=%p\n", state);
  50.486 +    return state;
  50.487 +}
  50.488 +
  50.489 +/** Create an SA in initial state.
  50.490 + * It has no spi and its keying state is acquire.
  50.491 + * It must have a unique id, protocol and address.
  50.492 + * At some point it should get updated with a complete SA.
  50.493 + *
  50.494 + * @param ident SA identifier
  50.495 + * @param statep return parameter for new SA
  50.496 + * @return 0 on success, error code otherwise
  50.497 + */
  50.498 +int SAState_init(SAIdent *ident, SAState **statep){
  50.499 +    int err = 0;
  50.500 +    SAState *state = NULL;
  50.501 +   
  50.502 +    if(ident->spi || !ident->id){
  50.503 +        err = -EINVAL;
  50.504 +        goto exit;
  50.505 +    }
  50.506 +    state = SAState_alloc();
  50.507 +    if (!state){
  50.508 +        err = -ENOMEM;
  50.509 +        goto exit;
  50.510 +    }
  50.511 +    state->ident = *ident;
  50.512 +    state->keying.state = SA_STATE_ACQUIRE;
  50.513 +  exit:
  50.514 +    return err;
  50.515 +}
  50.516 +
  50.517 +/** Create a complete SA, with spi and cipher suite.
  50.518 + *
  50.519 + * @param info SA parameters
  50.520 + * @param statep return parameter for new SA
  50.521 + * @return 0 on success, error code otherwise
  50.522 + */
  50.523 +int SAState_create(SAInfo *info, SAState **statep){
  50.524 +    int err = 0;
  50.525 +    SAState *state = NULL;
  50.526 +
  50.527 +    dprintf(">\n");
  50.528 +    state = SAState_alloc();
  50.529 +    if (!state){
  50.530 +        err = -ENOMEM;
  50.531 +        goto exit;
  50.532 +    }
  50.533 +    state->ident = info->ident;
  50.534 +    state->limits = info->limits;
  50.535 +    state->digest = info->digest;
  50.536 +    state->cipher = info->cipher;
  50.537 +    state->compress = info->compress;
  50.538 +    state->security = info->security;
  50.539 +    err = SAType_get(state->ident.protocol, &state->type);
  50.540 +    if (err) goto exit;
  50.541 +    err = state->type->init(state, NULL);
  50.542 +    if (err) goto exit;
  50.543 +    state->keying.state = SA_STATE_VALID;
  50.544 +  exit:
  50.545 +    if(err){
  50.546 +        SAState_decref(state);
  50.547 +        state = NULL;
  50.548 +    }
  50.549 +    *statep = state;
  50.550 +    dprintf("< err=%d\n", err);
  50.551 +    return err;
  50.552 +}
  50.553 +
  50.554 +/** Create an SA for the given spi etc.
  50.555 + * For now we fix the cipher suite and the keys.
  50.556 + * Digest is SHA1 HMAC with a 128-bit key.
  50.557 + * Cipher is AES (Rijndael) in CBC mode with a 128-bit key.
  50.558 + *
  50.559 + * The cipher suite and keys should really come from policy, with the
  50.560 + * possibility of negotiating them with the peer (using IKE).
  50.561 + * Negotiation creates difficulties though - because the SA cannot
  50.562 + * be created immediately we have to be able to queue packets
  50.563 + * while the SA is being negotiated.
  50.564 + *
  50.565 + * @param spi spi
  50.566 + * @param protocol protocol
  50.567 + * @param addr address
  50.568 + * @param sa return parameter for SA
  50.569 + * @return 0 on success, error code otherwise
  50.570 + */
  50.571 +int sa_create(int security, u32 spi, u32 protocol, u32 addr, SAState **sa){
  50.572 +    int err = 0;
  50.573 +    SAInfo info = {};
  50.574 +    char *digest_name = "sha1";
  50.575 +    char *digest_key = "0123456789abcdef";
  50.576 +    int digest_key_n = strlen(digest_key);
  50.577 +    char *cipher_name= "aes";
  50.578 +    char *cipher_key = "0123456789ABCDEF";
  50.579 +    int cipher_key_n = strlen(cipher_key);
  50.580 +
  50.581 +    dprintf("> security=%d spi=%u protocol=%u addr=" IPFMT "\n",
  50.582 +            security, spi, protocol, NIPQUAD(addr));
  50.583 +    if(!spi){
  50.584 +        spi = generate_spi(0, 0, protocol, addr);
  50.585 +    }
  50.586 +    dprintf("> info...\n");
  50.587 +    info.ident.id = sa_id++;
  50.588 +    info.ident.spi = spi;
  50.589 +    info.ident.protocol = protocol;
  50.590 +    info.ident.addr = addr;
  50.591 +    info.security = security;
  50.592 +
  50.593 +    //sa_algorithm_probe_all();
  50.594 +
  50.595 +    dprintf("> digest name=%s key_n=%d\n", digest_name, digest_key_n);
  50.596 +    strcpy(info.digest.name, digest_name);
  50.597 +    info.digest.bits = digest_key_n * 8;
  50.598 +    memcpy(info.digest.key, digest_key, digest_key_n);
  50.599 +
  50.600 +    if(security & SA_CONF){
  50.601 +        dprintf("> cipher name=%s key_n=%d\n", cipher_name, cipher_key_n);
  50.602 +        strcpy(info.cipher.name, cipher_name);
  50.603 +        info.cipher.bits = cipher_key_n * 8;
  50.604 +        memcpy(info.cipher.key, cipher_key, cipher_key_n);
  50.605 +    } else {
  50.606 +        dprintf("> cipher name=%s key_n=%d\n", "cipher_null", 0);
  50.607 +        strcpy(info.cipher.name, "cipher_null");
  50.608 +        info.cipher.bits = 0;
  50.609 +        memset(info.cipher.key, 0, sizeof(info.cipher.key));
  50.610 +    }
  50.611 +
  50.612 +    err = sa_set(&info, 0, sa);
  50.613 +    dprintf("< err=%d\n", err);
  50.614 +    return err;
  50.615 +}
  50.616 +
  50.617 +/** Create or update an SA.
  50.618 + * The SA is added to the table.
  50.619 + *
  50.620 + * @param info SA parameters
  50.621 + * @param update create if zero, update otherwise
  50.622 + * @return 0 on success, error code otherwise
  50.623 + */
  50.624 +int sa_set(SAInfo *info, int update, SAState **val){
  50.625 +    int err = 0;
  50.626 +    SAState *state = NULL;
  50.627 +    SAState *existing = NULL;
  50.628 +
  50.629 +    dprintf("> info=%p update=%d val=%p\n", info, update, val);
  50.630 +    existing = sa_table_lookup_id(info->ident.id);
  50.631 +    if(update && !existing){
  50.632 +        err = -ENOENT;
  50.633 +    } else if(!update && existing){
  50.634 +        err = -EINVAL;
  50.635 +    }
  50.636 +    if(err) goto exit;
  50.637 +    err = SAState_create(info, &state);
  50.638 +    if (err) goto exit;
  50.639 +    if(existing){
  50.640 +        err = sa_table_replace(existing, state);
  50.641 +    } else {
  50.642 +        err = sa_table_add(state);
  50.643 +    }
  50.644 +  exit:
  50.645 +    if(existing) SAState_decref(existing);
  50.646 +    if(val && !err){
  50.647 +        *val = state;
  50.648 +    } else {
  50.649 +        SAState_decref(state);
  50.650 +    }
  50.651 +    dprintf("< err=%d\n", err);
  50.652 +    return err;
  50.653 +}
  50.654 +
  50.655 +/** Delete an SA. Removes it from the SA table.
  50.656 + * It is an error if no SA with the given id exists.
  50.657 + *
  50.658 + * @param id SA id
  50.659 + * @return 0 on success, error code otherwise
  50.660 + */
  50.661 +int sa_delete(int id){
  50.662 +    int err = 0;
  50.663 +    SAState *state;
  50.664 +    state = sa_table_lookup_id(id);
  50.665 +    if (!state){
  50.666 +        err = -ENOENT;
  50.667 +        goto exit;
  50.668 +    }
  50.669 +    sa_table_delete(state);
  50.670 +    SAState_decref(state);
  50.671 +  exit:
  50.672 +    return err;
  50.673 +}
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/tools/vnet/vnet-module/sa.h	Wed Nov 24 18:22:43 2004 +0000
    51.3 @@ -0,0 +1,199 @@
    51.4 +/*
    51.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    51.6 + *
    51.7 + * This program is free software; you can redistribute it and/or modify
    51.8 + * it under the terms of the GNU General Public License as published by the 
    51.9 + * Free Software Foundation; either version 2 of the License, or (at your
   51.10 + * option) any later version.
   51.11 + * 
   51.12 + * This program is distributed in the hope that it will be useful, but
   51.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   51.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   51.15 + * for more details.
   51.16 + *
   51.17 + * You should have received a copy of the GNU General Public License along
   51.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   51.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   51.20 + *
   51.21 + */
   51.22 +#ifndef __VNET_SA_H__
   51.23 +#define __VNET_SA_H__
   51.24 +
   51.25 +#include <linux/types.h>
   51.26 +#include <linux/crypto.h>
   51.27 +
   51.28 +#include <tunnel.h>
   51.29 +
   51.30 +#ifndef CRYPTO_MAX_KEY_BYTES
   51.31 +#define CRYPTO_MAX_KEY_BYTES            64
   51.32 +#define CRYPTO_MAX_KEY_BITS             (CRYPTO_MAX_KEY_BYTES * 8)
   51.33 +#endif
   51.34 +
   51.35 +typedef struct SALimits {
   51.36 +    u64 bytes_soft;
   51.37 +    u64 bytes_hard;
   51.38 +    u64 packets_soft;
   51.39 +    u64 packets_hard;
   51.40 +} SALimits;
   51.41 +
   51.42 +typedef struct SACounts {
   51.43 +    u64 bytes;
   51.44 +    u64 packets;
   51.45 +    u32 integrity_failures;
   51.46 +} SACounts;
   51.47 +
   51.48 +typedef struct SAReplay {
   51.49 +    int replay;
   51.50 +    u32 send_seq;
   51.51 +    u32 recv_seq;
   51.52 +    u32 bitmap;
   51.53 +    u32 replay_window;
   51.54 +} SAReplay;
   51.55 +
   51.56 +typedef struct SAKey {
   51.57 +    char name[CRYPTO_MAX_ALG_NAME];
   51.58 +    int bits;
   51.59 +    char key[CRYPTO_MAX_KEY_BYTES];
   51.60 +} SAKey;
   51.61 +
   51.62 +typedef struct SAKeying {
   51.63 +    u8 state;
   51.64 +    u8 dying;
   51.65 +} SAKeying;
   51.66 +
   51.67 +typedef struct SAIdent {
   51.68 +    u32 id;
   51.69 +    u32 spi;
   51.70 +    u32 addr;
   51.71 +    u32 protocol;
   51.72 +} SAIdent;
   51.73 +
   51.74 +struct SAType;
   51.75 +
   51.76 +/** Security assocation (SA). */
   51.77 +typedef struct SAState {
   51.78 +    atomic_t refcount;
   51.79 +    spinlock_t lock;
   51.80 +    /** Identifier. */
   51.81 +    struct SAIdent ident;
   51.82 +    /** Security flags. */
   51.83 +    int security;
   51.84 +    /** Keying state. */
   51.85 +    struct SAKeying keying;
   51.86 +    /** Byte counts etc. */
   51.87 +    struct SACounts counts;
   51.88 +    /** Byte limits etc. */
   51.89 +    struct SALimits limits;
   51.90 +    /** Replay protection. */
   51.91 +    struct SAReplay replay;
   51.92 +    /** Digest algorithm. */
   51.93 +    struct SAKey digest;
   51.94 +    /** Cipher algorithm. */
   51.95 +    struct SAKey cipher;
   51.96 +    /** Compress algorith. */
   51.97 +    struct SAKey compress;
   51.98 +    /** SA type (ESP, AH). */
   51.99 +    struct SAType *type;
  51.100 +    /** Data for the SA type to use. */
  51.101 +    void *data;
  51.102 +} SAState;
  51.103 +    
  51.104 +typedef struct SAType {
  51.105 +    char *name;
  51.106 +    int protocol;
  51.107 +    int (*init)(SAState *state, void *args);
  51.108 +    void (*fini)(SAState *state);
  51.109 +    int (*recv)(SAState *state, struct sk_buff *skb);
  51.110 +    int (*send)(SAState *state, struct sk_buff *skb, Tunnel *tunnel);
  51.111 +    u32 (*size)(SAState *state, int size);
  51.112 +} SAType;
  51.113 +
  51.114 +/** Information needed to create an SA.
  51.115 + * Unused algorithms have zero key size.
  51.116 + */
  51.117 +typedef struct SAInfo {
  51.118 +    /** Identifier. */
  51.119 +    SAIdent ident;
  51.120 +    /** Security flags. */
  51.121 +    int security;
  51.122 +    /** Digest algorithm and key. */
  51.123 +    SAKey digest;
  51.124 +    /** Cipher algorithm and key. */
  51.125 +    SAKey cipher;
  51.126 +    /** Compress algorithm and key. */
  51.127 +    SAKey compress;
  51.128 +    /** SA lifetime limits. */
  51.129 +    SALimits limits;
  51.130 +    /** Replay protection window. */
  51.131 +    int replay_window;
  51.132 +} SAInfo;
  51.133 +
  51.134 +enum sa_alg_type {
  51.135 +    SA_ALG_DIGEST = 1,
  51.136 +    SA_ALG_CIPHER = 2,
  51.137 +    SA_ALG_COMPRESS = 3,
  51.138 +};
  51.139 +
  51.140 +extern int SAType_add(SAType *type);
  51.141 +extern int SAType_del(SAType *type);
  51.142 +extern int SAType_get(int protocol, SAType **type);
  51.143 +
  51.144 +extern int sa_table_init(void);
  51.145 +extern void sa_table_exit(void);
  51.146 +extern int sa_table_delete(SAState *state);
  51.147 +extern int sa_table_add(SAState *state);
  51.148 +extern SAState * sa_table_lookup_spi(u32 spi, u32 protocol, u32 addr);
  51.149 +extern SAState * sa_table_lookup_id(u32 id);
  51.150 +
  51.151 +/** Increment reference count.
  51.152 + *
  51.153 + * @param sa security association (may be null)
  51.154 + */
  51.155 +static inline void SAState_incref(SAState *sa){
  51.156 +    if(!sa) return;
  51.157 +    atomic_inc(&sa->refcount);
  51.158 +}
  51.159 +
  51.160 +/** Decrement reference count, freeing if zero.
  51.161 + *
  51.162 + * @param sa security association (may be null)
  51.163 + */
  51.164 +static inline void SAState_decref(SAState *sa){
  51.165 +    if(!sa) return;
  51.166 +    if(atomic_dec_and_test(&sa->refcount)){
  51.167 +        sa->type->fini(sa);
  51.168 +        kfree(sa);
  51.169 +    }
  51.170 +}
  51.171 +
  51.172 +extern SAState *SAState_alloc(void);
  51.173 +extern int SAState_init(SAIdent *id, SAState **statep);
  51.174 +extern int SAState_create(SAInfo *info, SAState **statep);
  51.175 +
  51.176 +static inline int SAState_send(SAState *sa, struct sk_buff *skb, Tunnel *tunnel){
  51.177 +    return sa->type->send(sa, skb, tunnel);
  51.178 +}
  51.179 +
  51.180 +static inline int SAState_recv(SAState *sa, struct sk_buff *skb){
  51.181 +    return sa->type->recv(sa, skb);
  51.182 +}
  51.183 +
  51.184 +static inline int SAState_size(SAState *sa, int n){
  51.185 +    return sa->type->size(sa, n);
  51.186 +}
  51.187 +
  51.188 +extern int sa_create(int security, u32 spi, u32 protocol, u32 addr, SAState **sa);
  51.189 +extern int sa_set(SAInfo *info, int update, SAState **val);
  51.190 +extern int sa_delete(int id);
  51.191 +
  51.192 +enum {
  51.193 +    SA_AUTH = 1,
  51.194 +    SA_CONF = 2
  51.195 +};
  51.196 +
  51.197 +enum {
  51.198 +    SA_STATE_ACQUIRE = 1,
  51.199 +    SA_STATE_VALID   = 2,
  51.200 +};
  51.201 +
  51.202 +#endif /* !__VNET_SA_H__ */
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/tools/vnet/vnet-module/sa_algorithm.c	Wed Nov 24 18:22:43 2004 +0000
    52.3 @@ -0,0 +1,367 @@
    52.4 +/* 
    52.5 + * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
    52.6 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    52.7 + *
    52.8 + * This program is free software; you can redistribute it and/or modify
    52.9 + * it under the terms of the GNU General Public License as published by the 
   52.10 + * Free Software Foundation; either version 2 of the License, or (at your
   52.11 + * option) any later version.
   52.12 + * 
   52.13 + * This program is distributed in the hope that it will be useful, but
   52.14 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   52.15 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   52.16 + * for more details.
   52.17 + *
   52.18 + * You should have received a copy of the GNU General Public License along
   52.19 + * with this program; if not, write to the Free software Foundation, Inc.,
   52.20 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   52.21 + *
   52.22 + */
   52.23 +#include <linux/config.h>
   52.24 +#include <linux/kernel.h>
   52.25 +#include <linux/string.h>
   52.26 +#include <linux/crypto.h>
   52.27 +#include <linux/sched.h>
   52.28 +//#include <asm/softirq.h>
   52.29 +
   52.30 +#include <sa_algorithm.h>
   52.31 +
   52.32 +#define MODULE_NAME "IPSEC"
   52.33 +#define DEBUG 1
   52.34 +#undef DEBUG
   52.35 +#include "debug.h"
   52.36 +
   52.37 +/** @file Tables of supported IPSEC algorithms.
   52.38 + * Has tables for digests, ciphers and compression algorithms.
   52.39 + */
   52.40 +
   52.41 +/*
   52.42 + * Algorithms supported by IPsec.  These entries contain properties which
   52.43 + * are used in key negotiation and sa processing, and are used to verify
   52.44 + * that instantiated crypto transforms have correct parameters for IPsec
   52.45 + * purposes.
   52.46 + */
   52.47 +
   52.48 +/** Digests. */
   52.49 +static SAAlgorithm digest_alg[] = {
   52.50 +    {
   52.51 +        .name = "digest_null",
   52.52 +        .info = {
   52.53 +            .digest = {
   52.54 +                .icv_truncbits = 0,
   52.55 +                .icv_fullbits = 0,
   52.56 +            }
   52.57 +        },
   52.58 +        .alg = {
   52.59 +            .sadb_alg_id = SADB_X_AALG_NULL,
   52.60 +            .sadb_alg_ivlen = 0,
   52.61 +            .sadb_alg_minbits = 0,
   52.62 +            .sadb_alg_maxbits = 0
   52.63 +        }
   52.64 +    },
   52.65 +    {
   52.66 +	.name = "md5",
   52.67 +	.info = { .digest = {
   52.68 +            .icv_truncbits = 96,
   52.69 +            .icv_fullbits = 128,
   52.70 +        } },
   52.71 +        .alg = {
   52.72 +            .sadb_alg_id = SADB_AALG_MD5HMAC,
   52.73 +            .sadb_alg_ivlen = 0,
   52.74 +            .sadb_alg_minbits = 128,
   52.75 +            .sadb_alg_maxbits = 128
   52.76 +	}
   52.77 +    },
   52.78 +    {
   52.79 +	.name = "sha1",
   52.80 +	.info = {
   52.81 +            .digest = {
   52.82 +                .icv_truncbits = 96,
   52.83 +                .icv_fullbits = 160,
   52.84 +            }
   52.85 +	},
   52.86 +	.alg = {
   52.87 +            .sadb_alg_id = SADB_AALG_SHA1HMAC,
   52.88 +            .sadb_alg_ivlen = 0,
   52.89 +            .sadb_alg_minbits = 160,
   52.90 +            .sadb_alg_maxbits = 160
   52.91 +	}
   52.92 +    },
   52.93 +    {
   52.94 +	.name = "sha256",
   52.95 +	.info = {
   52.96 +            .digest = {
   52.97 +                .icv_truncbits = 128,
   52.98 +                .icv_fullbits = 256,
   52.99 +            }
  52.100 +	},
  52.101 +	.alg = {
  52.102 +            .sadb_alg_id = SADB_X_AALG_SHA2_256HMAC,
  52.103 +            .sadb_alg_ivlen = 0,
  52.104 +            .sadb_alg_minbits = 256,
  52.105 +            .sadb_alg_maxbits = 256
  52.106 +	}
  52.107 +    },
  52.108 +/*     { */
  52.109 +/*         .name = "ripemd160", */
  52.110 +/*         .info = { */
  52.111 +/*             .digest = { */
  52.112 +/*                 .icv_truncbits = 96, */
  52.113 +/*                 .icv_fullbits = 160, */
  52.114 +/*             } */
  52.115 +/* 	}, */
  52.116 +/*         .alg = { */
  52.117 +/*             .sadb_alg_id = SADB_X_AALG_RIPEMD160HMAC, */
  52.118 +/*             .sadb_alg_ivlen = 0, */
  52.119 +/*             .sadb_alg_minbits = 160, */
  52.120 +/*             .sadb_alg_maxbits = 160 */
  52.121 +/* 	} */
  52.122 +/*     }, */
  52.123 +    { /* Terminator */ }
  52.124 +};
  52.125 +
  52.126 +/** Ciphers. */
  52.127 +static SAAlgorithm cipher_alg[] = {
  52.128 +    {
  52.129 +	.name = "cipher_null",
  52.130 +        .info = {
  52.131 +            .cipher = {
  52.132 +                .blockbits = 8,
  52.133 +                .defkeybits = 0,
  52.134 +            }
  52.135 +	},
  52.136 +        .alg = {
  52.137 +            .sadb_alg_id =	SADB_EALG_NULL,
  52.138 +            .sadb_alg_ivlen = 0,
  52.139 +            .sadb_alg_minbits = 0,
  52.140 +            .sadb_alg_maxbits = 0
  52.141 +	}
  52.142 +    },
  52.143 +    {
  52.144 +        .name = "des",
  52.145 +        .info = {
  52.146 +            .cipher = {
  52.147 +                .blockbits = 64,
  52.148 +                .defkeybits = 64,
  52.149 +            }
  52.150 +	},
  52.151 +        .alg = {
  52.152 +            .sadb_alg_id = SADB_EALG_DESCBC,
  52.153 +            .sadb_alg_ivlen = 8,
  52.154 +            .sadb_alg_minbits = 64,
  52.155 +            .sadb_alg_maxbits = 64
  52.156 +	}
  52.157 +    },
  52.158 +    {
  52.159 +	.name = "des3_ede",
  52.160 +	.info = {
  52.161 +            .cipher = {
  52.162 +                .blockbits = 64,
  52.163 +                .defkeybits = 192,
  52.164 +            }
  52.165 +	},
  52.166 +        .alg = {
  52.167 +            .sadb_alg_id = SADB_EALG_3DESCBC,
  52.168 +            .sadb_alg_ivlen = 8,
  52.169 +            .sadb_alg_minbits = 192,
  52.170 +            .sadb_alg_maxbits = 192
  52.171 +	}
  52.172 +    },
  52.173 +/*     { */
  52.174 +/* 	.name = "cast128", */ //cast5?
  52.175 +/* 	.info = { */
  52.176 +/*             .cipher = { */
  52.177 +/*                 .blockbits = 64, */
  52.178 +/*                 .defkeybits = 128, */
  52.179 +/*             } */
  52.180 +/* 	}, */
  52.181 +/* 	.alg = { */
  52.182 +/*             .sadb_alg_id = SADB_X_EALG_CASTCBC, */
  52.183 +/*             .sadb_alg_ivlen = 8, */
  52.184 +/*             .sadb_alg_minbits = 40, */
  52.185 +/*             .sadb_alg_maxbits = 128 */
  52.186 +/* 	} */
  52.187 +/*     }, */
  52.188 +    {
  52.189 +	.name = "blowfish",
  52.190 +        .info = {
  52.191 +            .cipher = {
  52.192 +                .blockbits = 64,
  52.193 +                .defkeybits = 128,
  52.194 +            }
  52.195 +	},
  52.196 +	.alg = {
  52.197 +            .sadb_alg_id = SADB_X_EALG_BLOWFISHCBC,
  52.198 +            .sadb_alg_ivlen = 8,
  52.199 +            .sadb_alg_minbits = 40,
  52.200 +            .sadb_alg_maxbits = 448
  52.201 +	}
  52.202 +    },
  52.203 +    {
  52.204 +	.name = "aes",
  52.205 +	.info = {
  52.206 +            .cipher = {
  52.207 +                .blockbits = 128,
  52.208 +                .defkeybits = 128,
  52.209 +            }
  52.210 +	},
  52.211 +	.alg = {
  52.212 +            .sadb_alg_id = SADB_X_EALG_AESCBC,
  52.213 +            .sadb_alg_ivlen = 8,
  52.214 +            .sadb_alg_minbits = 128,
  52.215 +            .sadb_alg_maxbits = 256
  52.216 +	}
  52.217 +    },
  52.218 +    { /* Terminator */ }
  52.219 +};
  52.220 +
  52.221 +/** Compressors. */
  52.222 +static SAAlgorithm compress_alg[] = {
  52.223 +    {
  52.224 +	.name = "deflate",
  52.225 +	.info = {
  52.226 +            .compress = {
  52.227 +                .threshold = 90,
  52.228 +            }
  52.229 +	},
  52.230 +	.alg = { .sadb_alg_id = SADB_X_CALG_DEFLATE }
  52.231 +    },
  52.232 +/*     { */
  52.233 +/* 	.name = "lzs", */
  52.234 +/* 	.info = { */
  52.235 +/*             .compress = { */
  52.236 +/*                 .threshold = 90, */
  52.237 +/*             } */
  52.238 +/* 	}, */
  52.239 +/* 	.alg = { .sadb_alg_id = SADB_X_CALG_LZS } */
  52.240 +/*     }, */
  52.241 +/*     { */
  52.242 +/* 	.name = "lzjh", */
  52.243 +/* 	.info = { */
  52.244 +/*             .compress = { */
  52.245 +/*                 .threshold = 50, */
  52.246 +/*             } */
  52.247 +/* 	}, */
  52.248 +/* 	.alg = { .sadb_alg_id = SADB_X_CALG_LZJH } */
  52.249 +/*     }, */
  52.250 +    { /* Terminator */ }
  52.251 +};
  52.252 +
  52.253 +static SAAlgorithm *sa_algorithm_by_id(SAAlgorithm *algo, int alg_id) {
  52.254 +    for( ; algo && algo->name; algo++){
  52.255 +        if (algo->alg.sadb_alg_id == alg_id) {
  52.256 +            return (algo->available ? algo : NULL);
  52.257 +        }
  52.258 +    }
  52.259 +    return NULL;
  52.260 +}
  52.261 +
  52.262 +
  52.263 +static SAAlgorithm *sa_algorithm_by_name(SAAlgorithm *algo, char *name) {
  52.264 +	if (!name) return NULL;
  52.265 +	for( ; algo && algo->name; algo++){
  52.266 +		if (strcmp(name, algo->name) == 0) {
  52.267 +                    return (algo->available ? algo : NULL);
  52.268 +                }
  52.269 +	}
  52.270 +	return NULL;
  52.271 +}
  52.272 +
  52.273 +SAAlgorithm *sa_digest_by_id(int alg_id) {
  52.274 +    return sa_algorithm_by_id(digest_alg, alg_id);
  52.275 +}
  52.276 +
  52.277 +SAAlgorithm *sa_cipher_by_id(int alg_id) {
  52.278 +    return sa_algorithm_by_id(cipher_alg, alg_id);
  52.279 +}
  52.280 +
  52.281 +SAAlgorithm *sa_compress_by_id(int alg_id) {
  52.282 +    return sa_algorithm_by_id(compress_alg, alg_id);
  52.283 +}
  52.284 +
  52.285 +SAAlgorithm *sa_digest_by_name(char *name) {
  52.286 +    return sa_algorithm_by_name(digest_alg, name);
  52.287 +}
  52.288 +
  52.289 +SAAlgorithm *sa_cipher_by_name(char *name) {
  52.290 +    return sa_algorithm_by_name(cipher_alg, name);
  52.291 +}
  52.292 +
  52.293 +SAAlgorithm *sa_compress_by_name(char *name) {
  52.294 +    return sa_algorithm_by_name(compress_alg, name);
  52.295 +}
  52.296 +
  52.297 +SAAlgorithm *sa_digest_by_index(unsigned int idx) {
  52.298 +    return digest_alg + idx;
  52.299 +}
  52.300 +
  52.301 +SAAlgorithm *sa_cipher_by_index(unsigned int idx) {
  52.302 +    return cipher_alg + idx;
  52.303 +}
  52.304 +
  52.305 +SAAlgorithm *sa_compress_by_index(unsigned int idx) {
  52.306 +    return compress_alg + idx;
  52.307 +}
  52.308 +
  52.309 +static void sa_algorithm_probe(SAAlgorithm *algo){
  52.310 +    int status;
  52.311 +    dprintf("> algo=%p\n", algo); 
  52.312 +    for( ; algo && algo->name; algo++){
  52.313 +        dprintf("> algorithm %s...\n", algo->name);
  52.314 +        status = crypto_alg_available(algo->name, 0);
  52.315 +        dprintf("> algorithm %s status=%d\n",algo->name, status); 
  52.316 +        if (algo->available != status){
  52.317 +            algo->available = status;
  52.318 +        }
  52.319 +    }
  52.320 +    dprintf("<\n"); 
  52.321 +}
  52.322 +
  52.323 +/** Crypto api is broken. When an unregistered algorithm is requested it
  52.324 + * tri