ia64/xen-unstable

changeset 3094:42bdac6c8985

bitkeeper revision 1.1159.1.445 (41a47974rZ1vtGT5wjpKwbMSnQ8gwA)

sync w/ head.
author cl349@arcadians.cl.cam.ac.uk
date Wed Nov 24 12:07:16 2004 +0000 (2004-11-24)
parents 4565455d7f26 f068615fc588
children f1c44a4d4998
files .rootkeys BitKeeper/etc/ignore linux-2.6.9-xen-sparse/Makefile linux-2.6.9-xen-sparse/arch/xen/Kconfig linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig linux-2.6.9-xen-sparse/drivers/xen/Makefile linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c linux-2.6.9-xen-sparse/drivers/xen/blktap/Makefile linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.c linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.h linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_datapath.c linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_userdev.c 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 xen/arch/x86/extable.c xen/arch/x86/irq.c xen/arch/x86/nmi.c xen/arch/x86/pdb-stub.c xen/arch/x86/smp.c xen/arch/x86/traps.c xen/arch/x86/x86_32/asm-offsets.c xen/arch/x86/x86_32/entry.S xen/arch/x86/x86_32/seg_fixup.c xen/arch/x86/x86_32/xen.lds xen/include/asm-x86/debugger.h xen/include/asm-x86/irq.h xen/include/asm-x86/processor.h xen/include/asm-x86/x86_32/regs.h
line diff
     1.1 --- a/.rootkeys	Wed Nov 24 11:51:49 2004 +0000
     1.2 +++ b/.rootkeys	Wed Nov 24 12:07:16 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 @@ -195,6 +196,12 @@ 40f562395atl9x4suKGhPkjqLOXESg linux-2.6
    1.12  40f56239-JNIaTzlviVJohVdoYOUpw linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c
    1.13  40f56239y9naBTXe40Pi2J_z3p-d1g linux-2.6.9-xen-sparse/drivers/xen/blkfront/block.h
    1.14  40f56239BVfPsXBiWQitXgDRtOsiqg linux-2.6.9-xen-sparse/drivers/xen/blkfront/vbd.c
    1.15 +41a226e0vjAcDXHOnXE5ummcdUD2mg linux-2.6.9-xen-sparse/drivers/xen/blktap/Makefile
    1.16 +41a226e0VeZA1N8tbU6nvJ3OxUcJmw linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.c
    1.17 +41a226e1k4J5VMLnrYXDWRqElS49YQ linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.h
    1.18 +41a226e1-A_Hy7utS8vJKaXnH_tzfA linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c
    1.19 +41a226e19NoUUTOvs7jumDMRYDIO4Q linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_datapath.c
    1.20 +41a226e1MNSyWWK5dEVgvSQ5OW0fDA linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_userdev.c
    1.21  40f56239fsLjvtD8YBRAWphps4FDjg linux-2.6.9-xen-sparse/drivers/xen/console/Makefile
    1.22  3e5a4e651TH-SXHoufurnWjgl5bfOA linux-2.6.9-xen-sparse/drivers/xen/console/console.c
    1.23  40f56239KYxO0YabhPzCTeUuln-lnA linux-2.6.9-xen-sparse/drivers/xen/evtchn/Makefile
    1.24 @@ -341,20 +348,35 @@ 40589968UQFnJeOMn8UIFLbXBuwXjw tools/lib
    1.25  40e1b09dMYB4ItGCqcMIzirdMd9I-w tools/libxutil/Makefile
    1.26  40e033325Sjqs-_4TuzeUEprP_gYFg tools/libxutil/allocate.c
    1.27  40e03332KYz7o1bn2MG_KPbBlyoIMA tools/libxutil/allocate.h
    1.28 +41a216cav5JJbtDQnusfuMa_1x_Xpw tools/libxutil/debug.h
    1.29 +40e9808eyjiahG5uF6AMelNVujBzCg tools/libxutil/enum.c
    1.30 +40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/libxutil/enum.h
    1.31  40e03332p5Dc_owJQRuN72ymJZddFQ tools/libxutil/file_stream.c
    1.32  40e03332jWfB2viAhLSkq1WK0r_iDQ tools/libxutil/file_stream.h
    1.33  40e03332rUjNMGg11n2rN6V4DCrvOg tools/libxutil/gzip_stream.c
    1.34  40e033321O5Qg22haLoq5lpmk4tooQ tools/libxutil/gzip_stream.h
    1.35 +40e9808easXCzzAZQodEfKAhgUXSPA tools/libxutil/hash_table.c
    1.36 +40e9808e94BNXIVVKBFHC3rnkvwtJg tools/libxutil/hash_table.h
    1.37  40e03332ihnBGzHykVwZnFmkAppb4g tools/libxutil/iostream.c
    1.38  40e03332UGwbLR4wsw4ft14p0Yw5pg tools/libxutil/iostream.h
    1.39  40e0333245DLDzJemeSVBLuutHtzEQ tools/libxutil/kernel_stream.c
    1.40  40e03332aK0GkgpDdc-PVTkWKTeOBg tools/libxutil/kernel_stream.h
    1.41 +40e9808epW9iHcLXuO3QfUfLzB7onw tools/libxutil/lexis.c
    1.42 +40e9808egccMhCizayQRGtpBA3L5MQ tools/libxutil/lexis.h
    1.43 +41a216caM4z39Fzjb91rv9Ed_4By1A tools/libxutil/socket_stream.c
    1.44 +41a216caqinvF1I5FQMHA4HTRz8MSA tools/libxutil/socket_stream.h
    1.45  40e03332KT_tnnoAMbPVAZBB7kSOAQ tools/libxutil/string_stream.c
    1.46  40e03332-VtK6_OZa1vMHXFil8uq6w tools/libxutil/string_stream.h
    1.47 +40e9808e5_PLdodqVOSx0b4T_f5aeg tools/libxutil/sxpr.c
    1.48 +40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/libxutil/sxpr.h
    1.49 +40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/libxutil/sxpr_parser.c
    1.50 +40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/libxutil/sxpr_parser.h
    1.51  40e03332Rkvq6nn_UNjzAAK_Tk9v1g tools/libxutil/sys_net.c
    1.52  40e03332lQHvQHw4Rh7VsT1_sui29A tools/libxutil/sys_net.h
    1.53  40e033321smklZd7bDSdWvQCeIshtg tools/libxutil/sys_string.c
    1.54  40e03332h5V611rRWURRLqb1Ekatxg tools/libxutil/sys_string.h
    1.55 +41a216cayFe2FQroFuzvNPw1AvNiqQ tools/libxutil/util.c
    1.56 +41a216ca7mgVSnCBHPCLkGOIqPS1CQ tools/libxutil/util.h
    1.57  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.58  40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
    1.59  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.60 @@ -533,6 +555,64 @@ 4104ffca-jPHLVOrW0n0VghEXXtKxg tools/sv/
    1.61  40fcefb3yMSrZvApO9ToIi-iQwnchA tools/sv/images/xen.png
    1.62  41013a83z27rKvWIxAfUBMVZ1eDCDg tools/sv/inc/script.js
    1.63  40fcefb3zGC9XNBkSwTEobCoq8YClA tools/sv/inc/style.css
    1.64 +41a21888_WlknVWjSxb32Fo13_ujsw tools/vnet/00README
    1.65 +41a21888bOiOJc7blzRbe4MNJoaYTw tools/vnet/Makefile
    1.66 +41a21888mg2k5HeiVjlQYEtJBZT4Qg tools/vnet/doc/vnet-module.txt
    1.67 +41a21888cuxfT8wjCdRR6V1lqf5NtA tools/vnet/doc/vnet-xend.txt
    1.68 +41a21888xEQJAIGktS6XQ4xz2TyA5g tools/vnet/examples/Makefile
    1.69 +41a21888FGQhPR5LJ1GRtOSIIN3QEw tools/vnet/examples/network-vnet
    1.70 +41a21888QPgKrulCfR9SY_pxZKU0KA tools/vnet/examples/vnet97.sxp
    1.71 +41a21888Gm0UBs1i7HqveT7Yz0u8DQ tools/vnet/examples/vnet98.sxp
    1.72 +41a21888r4oGPuGv2Lxl-thgV3H54w tools/vnet/examples/vnet99.sxp
    1.73 +41a21888c9TCRlUwJS9WBjB3e9aWgg tools/vnet/vnet-module/00README
    1.74 +41a21888K2ItolEkksc1MUqyTDI_Kg tools/vnet/vnet-module/Makefile
    1.75 +41a21888mJsFJD7bVMm-nrnWnalGBw tools/vnet/vnet-module/Makefile-2.4
    1.76 +41a21888Znze3-UCCBZ-Nxpj-bNeHA tools/vnet/vnet-module/Makefile-2.6
    1.77 +41a21889fwc1judJ7DYvyEviSJ3TPg tools/vnet/vnet-module/Makefile.ver
    1.78 +41a21889m_sYkdODF3j5uhMP-Guy9Q tools/vnet/vnet-module/Makefile.vnet
    1.79 +41a21889bXW2lC28U6KS_s5tOJ_W9Q tools/vnet/vnet-module/esp.c
    1.80 +41a21889L2MfLDsUFQxstt-0frIVmw tools/vnet/vnet-module/esp.h
    1.81 +41a21889V1jOsB2JExI-XQl720WHwg tools/vnet/vnet-module/etherip.c
    1.82 +41a21889IpMYbNufHMDXe2ndNw4JxA tools/vnet/vnet-module/etherip.h
    1.83 +41a21889LT9TNqO2EvTFIUTujrkX9w tools/vnet/vnet-module/if_etherip.h
    1.84 +41a21889PESythGZFG6kmSoOkkN2Nw tools/vnet/vnet-module/if_varp.h
    1.85 +41a21889nCPEomHqOyQ4vnhEm4II4g tools/vnet/vnet-module/linux/pfkeyv2.h
    1.86 +41a21889A_fw4pRmCbBfZdtRunM5Eg tools/vnet/vnet-module/random.c
    1.87 +41a218899Xy2dPKSu3pkuqaqkfKMTA tools/vnet/vnet-module/random.h
    1.88 +41a21889rIH5S1dv8ygdSsTGNlg0JA tools/vnet/vnet-module/sa.c
    1.89 +41a218896Z4vxy6gnV9h0fWRWu0lKQ tools/vnet/vnet-module/sa.h
    1.90 +41a21889qFD8BTbDpB55uVmSVDEsgw tools/vnet/vnet-module/sa_algorithm.c
    1.91 +41a21889r2AwTe-OCSSVMxBzz8uDtw tools/vnet/vnet-module/sa_algorithm.h
    1.92 +41a21889tvjtL7O8tMveVB8MdSKPnQ tools/vnet/vnet-module/skb_context.c
    1.93 +41a21889lD_QOUz2Msd7fB5rJQzfxA tools/vnet/vnet-module/skb_context.h
    1.94 +41a21889F1r1xnJamzdeuClR8MNwQg tools/vnet/vnet-module/skb_util.c
    1.95 +41a21889sS4bjVqEna24sS8NpV7SRA tools/vnet/vnet-module/skb_util.h
    1.96 +41a21889MDawEK3J_f_oAGnZznhG2w tools/vnet/vnet-module/tunnel.c
    1.97 +41a218896TlHXpVVqF50uz_u_WMXRw tools/vnet/vnet-module/tunnel.h
    1.98 +41a21889nQYbJbqrOApg_RbkwPtXGg tools/vnet/vnet-module/varp.c
    1.99 +41a21889Pev5MJlqqass6CxN4mmvPw tools/vnet/vnet-module/varp.h
   1.100 +41a21889GbsHHfkpA-PkOvltfEwpMA tools/vnet/vnet-module/varp_socket.c
   1.101 +41a21889sknn8zd5xCJlpQbs7MvxKg tools/vnet/vnet-module/vif.c
   1.102 +41a21889VsKKWpe6rcXOSLPy2FuNWQ tools/vnet/vnet-module/vif.h
   1.103 +41a21889dgkOyuSTVqy7D8TPIzrUyw tools/vnet/vnet-module/vnet.c
   1.104 +41a21889ocAdwk7V1nNt4iBpmYW-Mw tools/vnet/vnet-module/vnet.h
   1.105 +41a21889YrTiC0ArJSGFtiaHz2j1qQ tools/vnet/vnet-module/vnet_dev.c
   1.106 +41a21889rHT4vrC4VAfk7-xP_K5aBg tools/vnet/vnet-module/vnet_dev.h
   1.107 +41a21889qJj6GjT2f5hMHRvPS1AW4w tools/vnet/vnet-module/vnet_ioctl.c
   1.108 +41a2188a8W4xYB0LYm512agtoEv52g tools/vnet/vnet-module/vnet_ioctl.h
   1.109 +41a2188aFF_1T9OgpqUjjjaCqKB8lw tools/vnet/vnetd/Makefile
   1.110 +41a2188a9j84qS4CxqMLVCvyGpA93w tools/vnet/vnetd/connection.c
   1.111 +41a2188atexNEami9TNVYNkRSb7Bqg tools/vnet/vnetd/connection.h
   1.112 +41a2188abgYpITSrWoMGHHrM56nklw tools/vnet/vnetd/marshal.c
   1.113 +41a2188aUbOi5tAYwOS4aPixo1EGwQ tools/vnet/vnetd/marshal.h
   1.114 +41a2188aDJlSVB1s_st2MSWxW8kMwg tools/vnet/vnetd/select.c
   1.115 +41a2188aE9LUDdSSwNT3BWVWCvGSnQ tools/vnet/vnetd/select.h
   1.116 +41a2188aTbMKv_Eig12dSrBUEBl1Jg tools/vnet/vnetd/timer.c
   1.117 +41a2188aIzBGqQ6DUVzCxfBsN0Q6Ww tools/vnet/vnetd/timer.h
   1.118 +41a2188aIf3Xk6uvk7KzjdpOsflAEw tools/vnet/vnetd/vcache.c
   1.119 +41a2188ar6_vOO3_tEJQjmFVU3409A tools/vnet/vnetd/vcache.h
   1.120 +41a2188aETrGU60X9WtGhYVfU7z0Pw tools/vnet/vnetd/vnetd.c
   1.121 +41a2188ahYjemudGyB7078AWMFR-0w tools/vnet/vnetd/vnetd.h
   1.122  4194e861IgTabTt8HOuh143QIJFD1Q tools/x2d2/Makefile
   1.123  4194e861M2gcBz4i94cQYpqzi8n6UA tools/x2d2/cntrl_con.c
   1.124  4194e8612TrrMvC8ZlA4h2ZYCPWz4g tools/x2d2/minixend.c
   1.125 @@ -549,23 +629,13 @@ 40e9808epTR4zWrYjGUnaaynK20Q5A tools/xfr
   1.126  40e9808eysqT4VNDlJFqsZB2rdg4Qw tools/xfrd/connection.c
   1.127  40e9808eyXfJUi4E0C3WSgrEXqQ1sQ tools/xfrd/connection.h
   1.128  40e9808eULGwffNOE4kBrAfZ9YAVMA tools/xfrd/debug.h
   1.129 -40e9808eyjiahG5uF6AMelNVujBzCg tools/xfrd/enum.c
   1.130 -40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/xfrd/enum.h
   1.131 -40e9808easXCzzAZQodEfKAhgUXSPA tools/xfrd/hash_table.c
   1.132 -40e9808e94BNXIVVKBFHC3rnkvwtJg tools/xfrd/hash_table.h
   1.133  411b5139tfKZfWs1LQHmwDR_wjKoxQ tools/xfrd/http.h
   1.134 -40e9808epW9iHcLXuO3QfUfLzB7onw tools/xfrd/lexis.c
   1.135 -40e9808egccMhCizayQRGtpBA3L5MQ tools/xfrd/lexis.h
   1.136  40e9808ePADCSKL1YgGCt2TbYPnYkw tools/xfrd/lzi_stream.c
   1.137  40e9808eDNAdpF71o5teYb9DTT-PRw tools/xfrd/lzi_stream.h
   1.138  40e9808eQxi0EzTcPJtosrzxEIjA-Q tools/xfrd/marshal.c
   1.139  40e9808etg13xfRm0Lqd8vY-jHOoTg tools/xfrd/marshal.h
   1.140  40e9808eCsmywryb036TdtRMJHDMmQ tools/xfrd/select.c
   1.141  40e9808e99OcM547cKMTfmCVSoWVAw tools/xfrd/select.h
   1.142 -40e9808e5_PLdodqVOSx0b4T_f5aeg tools/xfrd/sxpr.c
   1.143 -40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/xfrd/sxpr.h
   1.144 -40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/xfrd/sxpr_parser.c
   1.145 -40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/xfrd/sxpr_parser.h
   1.146  40e9808eF3NVldqRNS5IHM8gbFAvpw tools/xfrd/xdr.c
   1.147  40e9808ezXzoRHm7pybXU69NtnjimA tools/xfrd/xdr.h
   1.148  40e9808edpUtf4bJ8IbqClPJj_OvbA tools/xfrd/xen_domain.c
   1.149 @@ -576,6 +646,11 @@ 40e9808eHXvs_5eggj9McD_J90mhNw tools/xfr
   1.150  3f72f1bdJPsV3JCnBqs9ddL9tr6D2g xen/COPYING
   1.151  3ddb79bcbOVHh38VJzc97-JEGD4dJQ xen/Makefile
   1.152  3ddb79bcWnTwYsQRWl_PaneJfa6p0w xen/Rules.mk
   1.153 +41a26ebcqaSGVQ8qTMwpPwOJSJ7qSw xen/arch/ia64/privop.c
   1.154 +41a26ebc4BOHDUsT0TSnryPeV2xfRA xen/arch/ia64/process.c
   1.155 +41a26ebcJ30TFl1v2kR8rqpEBvOtVw xen/arch/ia64/regionreg.c
   1.156 +41a26ebc--sjlYZQxmIxyCx3jw70qA xen/arch/ia64/vcpu.c
   1.157 +41a26ebc4jSBGQOuyNIPDST58mNbBw xen/arch/ia64/xenasm.S
   1.158  3ddb79bcZbRBzT3elFWSX7u6NtMagQ xen/arch/x86/Makefile
   1.159  3ddb79bcBQF85CfLS4i1WGZ4oLLaCA xen/arch/x86/Rules.mk
   1.160  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 12:07:16 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 12:07:16 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/linux-2.6.9-xen-sparse/arch/xen/Kconfig	Wed Nov 24 11:51:49 2004 +0000
     4.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/Kconfig	Wed Nov 24 12:07:16 2004 +0000
     4.3 @@ -49,6 +49,20 @@ config XEN_BLKDEV_BACKEND
     4.4            block devices to other guests via a high-performance shared-memory
     4.5            interface.
     4.6  
     4.7 +if XEN_BLKDEV_BACKEND
     4.8 +config XEN_BLKDEV_TAP_BE
     4.9 +        bool "Block Tap support for backend driver (DANGEROUS)"
    4.10 +        default n
    4.11 +        help
    4.12 +          If you intend to use the block tap driver, the backend domain will
    4.13 +          not know the domain id of the real frontend, and so will not be able
    4.14 +          to map its data pages.  This modifies the backend to attempt to map
    4.15 +          from both the tap domain and the real frontend.  This presents a
    4.16 +          security risk, and so should ONLY be used for development
    4.17 +          with the blktap.  This option will be removed as the block drivers are
    4.18 +          modified to use grant tables.
    4.19 +endif
    4.20 +
    4.21  config XEN_NETDEV_BACKEND
    4.22          bool "Network-device backend driver"
    4.23          default y if XEN_PHYSDEV_ACCESS
    4.24 @@ -94,6 +108,16 @@ config XEN_NETDEV_FRONTEND_PIPELINED_TRA
    4.25            enabled; then you must say N here.
    4.26  endif
    4.27  
    4.28 +config XEN_BLKDEV_TAP
    4.29 +        bool "Block device tap driver"
    4.30 +        default n
    4.31 +        help
    4.32 +          This driver allows a VM to interact on block device channels
    4.33 +          to other VMs.  Block messages may be passed through or redirected
    4.34 +          to a character device, allowing device prototyping in application
    4.35 +          space.  Odds are that you want to say N here.
    4.36 +
    4.37 +
    4.38  config XEN_WRITABLE_PAGETABLES
    4.39  	bool
    4.40  	default y
     5.1 --- a/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig	Wed Nov 24 11:51:49 2004 +0000
     5.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/configs/xen0_defconfig	Wed Nov 24 12:07:16 2004 +0000
     5.3 @@ -13,9 +13,11 @@ CONFIG_NO_IDLE_HZ=y
     5.4  CONFIG_XEN_PRIVILEGED_GUEST=y
     5.5  CONFIG_XEN_PHYSDEV_ACCESS=y
     5.6  CONFIG_XEN_BLKDEV_BACKEND=y
     5.7 +# CONFIG_XEN_BLKDEV_TAP_BE is not set
     5.8  CONFIG_XEN_NETDEV_BACKEND=y
     5.9  CONFIG_XEN_BLKDEV_FRONTEND=y
    5.10  CONFIG_XEN_NETDEV_FRONTEND=y
    5.11 +# CONFIG_XEN_BLKDEV_TAP is not set
    5.12  # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
    5.13  CONFIG_XEN_WRITABLE_PAGETABLES=y
    5.14  CONFIG_XEN_SCRUB_PAGES=y
     6.1 --- a/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig	Wed Nov 24 11:51:49 2004 +0000
     6.2 +++ b/linux-2.6.9-xen-sparse/arch/xen/configs/xenU_defconfig	Wed Nov 24 12:07:16 2004 +0000
     6.3 @@ -13,9 +13,11 @@ CONFIG_NO_IDLE_HZ=y
     6.4  # CONFIG_XEN_PRIVILEGED_GUEST is not set
     6.5  # CONFIG_XEN_PHYSDEV_ACCESS is not set
     6.6  # CONFIG_XEN_BLKDEV_BACKEND is not set
     6.7 +# CONFIG_XEN_BLKDEV_TAP_BE is not set
     6.8  # CONFIG_XEN_NETDEV_BACKEND is not set
     6.9  CONFIG_XEN_BLKDEV_FRONTEND=y
    6.10  CONFIG_XEN_NETDEV_FRONTEND=y
    6.11 +# CONFIG_XEN_BLKDEV_TAP is not set
    6.12  # CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
    6.13  CONFIG_XEN_WRITABLE_PAGETABLES=y
    6.14  CONFIG_XEN_SCRUB_PAGES=y
     7.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/Makefile	Wed Nov 24 11:51:49 2004 +0000
     7.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/Makefile	Wed Nov 24 12:07:16 2004 +0000
     7.3 @@ -9,4 +9,5 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkb
     7.4  obj-$(CONFIG_XEN_NETDEV_BACKEND)	+= netback/
     7.5  obj-$(CONFIG_XEN_BLKDEV_FRONTEND)	+= blkfront/
     7.6  obj-$(CONFIG_XEN_NETDEV_FRONTEND)	+= netfront/
     7.7 +obj-$(CONFIG_XEN_BLKDEV_TAP)    	+= blktap/
     7.8  
     8.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c	Wed Nov 24 11:51:49 2004 +0000
     8.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blkback/blkback.c	Wed Nov 24 12:07:16 2004 +0000
     8.3 @@ -69,6 +69,19 @@ static PEND_RING_IDX pending_prod, pendi
     8.4  static kmem_cache_t *buffer_head_cachep;
     8.5  #endif
     8.6  
     8.7 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
     8.8 +/*
     8.9 + * If the tap driver is used, we may get pages belonging to either the tap
    8.10 + * or (more likely) the real frontend.  The backend must specify which domain
    8.11 + * a given page belongs to in update_va_mapping though.  For the moment, 
    8.12 + * we pass in the domid of the real frontend in PROBE messages and store 
    8.13 + * this value in alt_dom.  Then on mapping, we try both.  This is a Guiness 
    8.14 + * book of records-calibre grim hack, and represents a bit of a security risk.
    8.15 + * Grant tables will soon solve the problem though!
    8.16 + */
    8.17 +static domid_t alt_dom = 0;
    8.18 +#endif
    8.19 +
    8.20  static int do_block_io_op(blkif_t *blkif, int max_to_do);
    8.21  static void dispatch_probe(blkif_t *blkif, blkif_request_t *req);
    8.22  static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req);
    8.23 @@ -324,12 +337,27 @@ static void dispatch_probe(blkif_t *blki
    8.24           (blkif_last_sect(req->frame_and_sects[0]) != 7) )
    8.25          goto out;
    8.26  
    8.27 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
    8.28 +    /* Grab the real frontend out of the probe message. */
    8.29 +    alt_dom = (domid_t)req->frame_and_sects[1];
    8.30 +#endif
    8.31 +    
    8.32      if ( HYPERVISOR_update_va_mapping_otherdomain(
    8.33          MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT,
    8.34          (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
    8.35 -        0, blkif->domid) )
    8.36 +        0, blkif->domid) ) {
    8.37 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
    8.38 +        /* That didn't work.  Try alt_dom. */
    8.39 +        if ( HYPERVISOR_update_va_mapping_otherdomain(
    8.40 +            MMAP_VADDR(pending_idx, 0) >> PAGE_SHIFT,
    8.41 +            (pte_t) { (req->frame_and_sects[0] & PAGE_MASK) | __PAGE_KERNEL },
    8.42 +            0, alt_dom) )
    8.43 +            goto out;
    8.44 +#else  
    8.45          goto out;
    8.46 -
    8.47 +#endif
    8.48 +    }
    8.49 +    
    8.50      rsp = vbd_probe(blkif, (vdisk_t *)MMAP_VADDR(pending_idx, 0), 
    8.51                      PAGE_SIZE / sizeof(vdisk_t));
    8.52  
    8.53 @@ -412,8 +440,11 @@ static void dispatch_rw_block_io(blkif_t
    8.54          mcl[i].args[0] = MMAP_VADDR(pending_idx, i) >> PAGE_SHIFT;
    8.55          mcl[i].args[1] = (phys_seg[i].buffer & PAGE_MASK) | remap_prot;
    8.56          mcl[i].args[2] = 0;
    8.57 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
    8.58 +        mcl[i].args[3] = (alt_dom != 0) ? alt_dom : blkif->domid;
    8.59 +#else
    8.60          mcl[i].args[3] = blkif->domid;
    8.61 -
    8.62 +#endif
    8.63          phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
    8.64              FOREIGN_FRAME(phys_seg[i].buffer >> PAGE_SHIFT);
    8.65      }
    8.66 @@ -580,7 +611,10 @@ static int __init blkif_init(void)
    8.67  #endif
    8.68  
    8.69      blkif_ctrlif_init();
    8.70 -
    8.71 +    
    8.72 +#ifdef CONFIG_XEN_BLKDEV_TAP_BE
    8.73 +    printk(KERN_ALERT "NOTE: Blkif backend is running with tap support on!\n");
    8.74 +#endif
    8.75      return 0;
    8.76  }
    8.77  
     9.1 --- a/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c	Wed Nov 24 11:51:49 2004 +0000
     9.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blkfront/blkfront.c	Wed Nov 24 12:07:16 2004 +0000
     9.3 @@ -1263,7 +1263,8 @@ static void blkif_status(blkif_fe_interf
     9.4  {
     9.5      if ( status->handle != blkif_handle )
     9.6      {
     9.7 -        WPRINTK(" Invalid blkif: handle=%u", status->handle);
     9.8 +        WPRINTK(" Invalid blkif: handle=%u\n", status->handle);
     9.9 +        unexpected(status);
    9.10          return;
    9.11      }
    9.12  
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/Makefile	Wed Nov 24 12:07:16 2004 +0000
    10.3 @@ -0,0 +1,3 @@
    10.4 +
    10.5 +obj-y	:= blktap_userdev.o blktap_datapath.o blktap_controlmsg.o blktap.o 
    10.6 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.c	Wed Nov 24 12:07:16 2004 +0000
    11.3 @@ -0,0 +1,86 @@
    11.4 +/******************************************************************************
    11.5 + * blktap.c
    11.6 + * 
    11.7 + * XenLinux virtual block-device tap.
    11.8 + * 
    11.9 + * Copyright (c) 2004, Andrew Warfield
   11.10 + *
   11.11 + * Based on the original split block driver:
   11.12 + * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
   11.13 + * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
   11.14 + * Copyright (c) 2004, Christian Limpach
   11.15 + * 
   11.16 + * Note that unlike the split block driver code, this driver has been developed
   11.17 + * strictly for Linux 2.6
   11.18 + */
   11.19 +
   11.20 +#include "blktap.h"
   11.21 +
   11.22 +int __init xlblk_init(void)
   11.23 +{
   11.24 +    ctrl_msg_t               cmsg;
   11.25 +    blkif_fe_driver_status_t fe_st;
   11.26 +    blkif_be_driver_status_t be_st;
   11.27 +
   11.28 +    printk(KERN_INFO "Initialising Xen block tap device\n");
   11.29 +
   11.30 +    DPRINTK("   tap - Backend connection init:\n");
   11.31 +
   11.32 +
   11.33 +    (void)ctrl_if_register_receiver(CMSG_BLKIF_FE, blkif_ctrlif_rx,
   11.34 +                                    CALLBACK_IN_BLOCKING_CONTEXT);
   11.35 +
   11.36 +    /* Send a driver-UP notification to the domain controller. */
   11.37 +    cmsg.type      = CMSG_BLKIF_FE;
   11.38 +    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
   11.39 +    cmsg.length    = sizeof(blkif_fe_driver_status_t);
   11.40 +    fe_st.status   = BLKIF_DRIVER_STATUS_UP;
   11.41 +    memcpy(cmsg.msg, &fe_st, sizeof(fe_st));
   11.42 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   11.43 +
   11.44 +    DPRINTK("   tap - Frontend connection init:\n");
   11.45 +    
   11.46 +    active_reqs_init();
   11.47 +    
   11.48 +    ptfe_blkif.status = DISCONNECTED;
   11.49 +
   11.50 +    (void)ctrl_if_register_receiver(CMSG_BLKIF_BE, blkif_ctrlif_rx, 
   11.51 +                                    CALLBACK_IN_BLOCKING_CONTEXT);
   11.52 +
   11.53 +    /* Send a driver-UP notification to the domain controller. */
   11.54 +    cmsg.type      = CMSG_BLKIF_BE;
   11.55 +    cmsg.subtype   = CMSG_BLKIF_BE_DRIVER_STATUS;
   11.56 +    cmsg.length    = sizeof(blkif_be_driver_status_t);
   11.57 +    be_st.status   = BLKIF_DRIVER_STATUS_UP;
   11.58 +    memcpy(cmsg.msg, &be_st, sizeof(be_st));
   11.59 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   11.60 +
   11.61 +    DPRINTK("   tap - Userland channel init:\n");
   11.62 +
   11.63 +    blktap_init();
   11.64 +
   11.65 +    DPRINTK("Blkif tap device initialized.\n");
   11.66 +
   11.67 +    return 0;
   11.68 +}
   11.69 +
   11.70 +void blkdev_suspend(void)
   11.71 +{
   11.72 +}
   11.73 +
   11.74 +void blkdev_resume(void)
   11.75 +{
   11.76 +    ctrl_msg_t               cmsg;
   11.77 +    blkif_fe_driver_status_t st;    
   11.78 +
   11.79 +    /* Send a driver-UP notification to the domain controller. */
   11.80 +    cmsg.type      = CMSG_BLKIF_FE;
   11.81 +    cmsg.subtype   = CMSG_BLKIF_FE_DRIVER_STATUS;
   11.82 +    cmsg.length    = sizeof(blkif_fe_driver_status_t);
   11.83 +    st.status      = BLKIF_DRIVER_STATUS_UP;
   11.84 +    memcpy(cmsg.msg, &st, sizeof(st));
   11.85 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
   11.86 +}
   11.87 +
   11.88 +
   11.89 +__initcall(xlblk_init);
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap.h	Wed Nov 24 12:07:16 2004 +0000
    12.3 @@ -0,0 +1,254 @@
    12.4 +/*
    12.5 + * blktap.h
    12.6 + * 
    12.7 + * Interfaces for the Xen block tap driver.
    12.8 + * 
    12.9 + * (c) 2004, Andrew Warfield, University of Cambridge
   12.10 + * 
   12.11 + */
   12.12 +
   12.13 +#ifndef __BLKTAP_H__
   12.14 +#define __BLKTAP_H__
   12.15 +
   12.16 +#include <linux/version.h>
   12.17 +#include <linux/blkdev.h>
   12.18 +#include <linux/config.h>
   12.19 +#include <linux/sched.h>
   12.20 +#include <linux/interrupt.h>
   12.21 +#include <asm-xen/ctrl_if.h>
   12.22 +#include <linux/slab.h>
   12.23 +#include <linux/blkdev.h>
   12.24 +#include <asm/io.h>
   12.25 +#include <asm/setup.h>
   12.26 +#include <asm/pgalloc.h>
   12.27 +#include <asm-xen/hypervisor.h>
   12.28 +#include <asm-xen/xen-public/io/blkif.h>
   12.29 +
   12.30 +/* -------[ debug / pretty printing ]--------------------------------- */
   12.31 +
   12.32 +#if 0
   12.33 +#define ASSERT(_p) \
   12.34 +    if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
   12.35 +    __LINE__, __FILE__); *(int*)0=0; }
   12.36 +#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
   12.37 +                           __FILE__ , __LINE__ , ## _a )
   12.38 +#else
   12.39 +#define ASSERT(_p) ((void)0)
   12.40 +#define DPRINTK(_f, _a...) ((void)0)
   12.41 +#endif
   12.42 +
   12.43 +#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
   12.44 +
   12.45 +/* -------[ connection / request tracking ]--------------------------- */
   12.46 +
   12.47 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   12.48 +#define VMALLOC_VMADDR(x) ((unsigned long)(x))
   12.49 +#endif
   12.50 +
   12.51 +extern spinlock_t blkif_io_lock;
   12.52 +
   12.53 +typedef struct blkif_st {
   12.54 +    /* Unique identifier for this interface. */
   12.55 +    domid_t          domid;
   12.56 +    unsigned int     handle;
   12.57 +    /* Physical parameters of the comms window. */
   12.58 +    unsigned long    shmem_frame;
   12.59 +    unsigned int     evtchn;
   12.60 +    int              irq;
   12.61 +    /* Comms information. */
   12.62 +    blkif_ring_t    *blk_ring_base; /* ioremap()'ed ptr to shmem_frame. */
   12.63 +    BLKIF_RING_IDX     blk_req_cons;  /* Request consumer. */
   12.64 +    BLKIF_RING_IDX     blk_resp_prod; /* Private version of resp. producer. */
   12.65 +    
   12.66 +    enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
   12.67 +    /*
   12.68 +     * DISCONNECT response is deferred until pending requests are ack'ed.
   12.69 +     * We therefore need to store the id from the original request.
   12.70 +     */    u8               disconnect_rspid;
   12.71 +    struct blkif_st *hash_next;
   12.72 +    struct list_head blkdev_list;
   12.73 +    spinlock_t       blk_ring_lock;
   12.74 +    atomic_t         refcnt;
   12.75 +    
   12.76 +    struct work_struct work;
   12.77 +} blkif_t;
   12.78 +
   12.79 +typedef struct {
   12.80 +    blkif_t       *blkif;
   12.81 +    unsigned long  id;
   12.82 +    int            nr_pages;
   12.83 +    unsigned long  mach_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   12.84 +    unsigned long  virt_fas[BLKIF_MAX_SEGMENTS_PER_REQUEST];
   12.85 +    int            next_free;
   12.86 +} active_req_t;
   12.87 +
   12.88 +
   12.89 +/* -------[ block ring structs ]-------------------------------------- */
   12.90 +
   12.91 +/* Types of ring. */
   12.92 +#define BLKIF_REQ_RING_TYPE 1
   12.93 +#define BLKIF_RSP_RING_TYPE 2
   12.94 +
   12.95 +/* generic ring struct. */
   12.96 +typedef struct blkif_generic_ring_struct {
   12.97 +    int type;
   12.98 +} blkif_generic_ring_t;
   12.99 +
  12.100 +/* A requestor's view of a ring. */
  12.101 +typedef struct blkif_req_ring_struct {
  12.102 +
  12.103 +    int type;                    /* Will be BLKIF_REQ_RING_TYPE        */
  12.104 +    BLKIF_RING_IDX req_prod;     /* PRIVATE req_prod index             */
  12.105 +    BLKIF_RING_IDX rsp_cons;     /* Response consumer index            */
  12.106 +    blkif_ring_t *ring;          /* Pointer to shared ring struct      */
  12.107 +
  12.108 +} blkif_req_ring_t;
  12.109 +
  12.110 +#define BLKIF_REQ_RING_INIT { BLKIF_REQ_RING_TYPE, 0, 0, 0 }
  12.111 +
  12.112 +/* A responder's view of a ring. */
  12.113 +typedef struct blkif_rsp_ring_struct {
  12.114 +
  12.115 +    int type;       
  12.116 +    BLKIF_RING_IDX rsp_prod;     /* PRIVATE rsp_prod index             */
  12.117 +    BLKIF_RING_IDX req_cons;     /* Request consumer index             */
  12.118 +    blkif_ring_t *ring;          /* Pointer to shared ring struct      */
  12.119 +
  12.120 +} blkif_rsp_ring_t;
  12.121 +
  12.122 +#define BLKIF_RSP_RING_INIT = { BLKIF_RSP_RING_TYPE, 0, 0, 0 }
  12.123 +
  12.124 +#define RING(a) (blkif_generic_ring_t *)(a)
  12.125 +
  12.126 +inline int BLKTAP_RING_FULL(blkif_generic_ring_t *ring);
  12.127 +
  12.128 +
  12.129 +/* -------[ interposition -> character device interface ]------------- */
  12.130 +
  12.131 +/* /dev/xen/blktap resides at device number major=10, minor=200        */ 
  12.132 +#define BLKTAP_MINOR 202
  12.133 +
  12.134 +/* size of the extra VMA area to map in attached pages. */
  12.135 +#define BLKTAP_VMA_PAGES BLKIF_RING_SIZE
  12.136 +
  12.137 +/* blktap IOCTLs:                                                      */
  12.138 +#define BLKTAP_IOCTL_KICK_FE         1
  12.139 +#define BLKTAP_IOCTL_KICK_BE         2
  12.140 +#define BLKTAP_IOCTL_SETMODE         3
  12.141 +
  12.142 +/* blktap switching modes: (Set with BLKTAP_IOCTL_SETMODE)             */
  12.143 +#define BLKTAP_MODE_PASSTHROUGH      0x00000000  /* default            */
  12.144 +#define BLKTAP_MODE_INTERCEPT_FE     0x00000001
  12.145 +#define BLKTAP_MODE_INTERCEPT_BE     0x00000002
  12.146 +#define BLKTAP_MODE_COPY_FE          0x00000004
  12.147 +#define BLKTAP_MODE_COPY_BE          0x00000008
  12.148 +#define BLKTAP_MODE_COPY_FE_PAGES    0x00000010
  12.149 +#define BLKTAP_MODE_COPY_BE_PAGES    0x00000020
  12.150 +
  12.151 +#define BLKTAP_MODE_INTERPOSE \
  12.152 +           (BLKTAP_MODE_INTERCEPT_FE | BLKTAP_MODE_INTERCEPT_BE)
  12.153 +
  12.154 +#define BLKTAP_MODE_COPY_BOTH \
  12.155 +           (BLKTAP_MODE_COPY_FE | BLKTAP_MODE_COPY_BE)
  12.156 +
  12.157 +#define BLKTAP_MODE_COPY_BOTH_PAGES \
  12.158 +           (BLKTAP_MODE_COPY_FE_PAGES | BLKTAP_MODE_COPY_BE_PAGES)
  12.159 +
  12.160 +static inline int BLKTAP_MODE_VALID(unsigned long arg)
  12.161 +{
  12.162 +    return (
  12.163 +        ( arg == BLKTAP_MODE_PASSTHROUGH  ) ||
  12.164 +        ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
  12.165 +        ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
  12.166 +        ( arg == BLKTAP_MODE_INTERPOSE    ) ||
  12.167 +        ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
  12.168 +        ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
  12.169 +        ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
  12.170 +        );
  12.171 +}
  12.172 +
  12.173 +
  12.174 +
  12.175 +/* -------[ Mappings to User VMA ]------------------------------------ */
  12.176 +#define MAX_PENDING_REQS 64
  12.177 +#define BATCH_PER_DOMAIN 16
  12.178 +extern struct vm_area_struct *blktap_vma;
  12.179 +
  12.180 +/* The following are from blkback.c and should probably be put in a
  12.181 + * header and included from there.
  12.182 + * The mmap area described here is where attached data pages eill be mapped.
  12.183 + */
  12.184 + 
  12.185 +extern unsigned long mmap_vstart;
  12.186 +#define MMAP_PAGES_PER_REQUEST \
  12.187 +    (BLKIF_MAX_SEGMENTS_PER_REQUEST + 1)
  12.188 +#define MMAP_PAGES             \
  12.189 +    (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
  12.190 +#define MMAP_VADDR(_req,_seg)                        \
  12.191 +    (mmap_vstart +                                   \
  12.192 +     ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
  12.193 +     ((_seg) * PAGE_SIZE))
  12.194 +
  12.195 +/* immediately before the mmap area, we have a bunch of pages reserved
  12.196 + * for shared memory rings.
  12.197 + */
  12.198 +
  12.199 +#define RING_PAGES 128 
  12.200 +extern unsigned long rings_vstart;
  12.201 +
  12.202 +/* -------[ Here be globals ]----------------------------------------- */
  12.203 +
  12.204 +extern unsigned long blktap_mode;
  12.205 +
  12.206 +
  12.207 +/* blkif struct, containing ring to FE domain */
  12.208 +extern blkif_t ptfe_blkif; 
  12.209 +
  12.210 +/* Connection to a single backend domain. */
  12.211 +extern blkif_ring_t *blk_ptbe_ring;   /* Ring from the PT to the BE dom    */ 
  12.212 +extern BLKIF_RING_IDX ptbe_resp_cons; /* Response consumer for comms ring. */
  12.213 +extern BLKIF_RING_IDX ptbe_req_prod;  /* Private request producer.         */
  12.214 +
  12.215 +/* Rings up to user space. */ 
  12.216 +extern blkif_req_ring_t fe_ring;// = BLKIF_REQ_RING_INIT;
  12.217 +extern blkif_rsp_ring_t be_ring;// = BLKIF_RSP_RING_INIT;
  12.218 +
  12.219 +/* Event channel to backend domain. */
  12.220 +extern unsigned int blkif_ptbe_evtchn;
  12.221 +
  12.222 +/* User ring status... this will soon vanish into a ring struct. */
  12.223 +extern unsigned long blktap_ring_ok;
  12.224 +
  12.225 +/* -------[ ...and function prototypes. ]----------------------------- */
  12.226 +
  12.227 +/* init function for character device interface.                       */
  12.228 +int blktap_init(void);
  12.229 +
  12.230 +/* interfaces to the char driver, passing messages to and from apps.   */
  12.231 +void blktap_kick_user(void);
  12.232 +int blktap_write_to_ring(blkif_request_t *req);
  12.233 +
  12.234 +
  12.235 +/* user ring access functions: */
  12.236 +int blktap_write_fe_ring(blkif_request_t *req);
  12.237 +int blktap_write_be_ring(blkif_response_t *rsp);
  12.238 +int blktap_read_fe_ring(void);
  12.239 +int blktap_read_be_ring(void);
  12.240 +
  12.241 +/* and the helpers they call: */
  12.242 +inline int write_resp_to_fe_ring(blkif_response_t *rsp);
  12.243 +inline void kick_fe_domain(void);
  12.244 +
  12.245 +inline int write_req_to_be_ring(blkif_request_t *req);
  12.246 +inline void kick_be_domain(void);
  12.247 +
  12.248 +/* Interrupt handlers. */
  12.249 +irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 
  12.250 +                                  struct pt_regs *ptregs);
  12.251 +irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs);
  12.252 +
  12.253 +/* Control message receiver. */
  12.254 +extern void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id);
  12.255 +
  12.256 +#define __BLKINT_H__
  12.257 +#endif
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_controlmsg.c	Wed Nov 24 12:07:16 2004 +0000
    13.3 @@ -0,0 +1,358 @@
    13.4 +/******************************************************************************
    13.5 + * blktap_controlmsg.c
    13.6 + * 
    13.7 + * XenLinux virtual block-device tap.
    13.8 + * Control interfaces to the frontend and backend drivers.
    13.9 + * 
   13.10 + * Copyright (c) 2004, Andrew Warfield
   13.11 + *
   13.12 + */
   13.13 + 
   13.14 +#include "blktap.h"
   13.15 +
   13.16 +#define BLKIF_STATE_CLOSED       0
   13.17 +#define BLKIF_STATE_DISCONNECTED 1
   13.18 +#define BLKIF_STATE_CONNECTED    2
   13.19 +
   13.20 +static char *blkif_state_name[] = {
   13.21 +    [BLKIF_STATE_CLOSED]       = "closed",
   13.22 +    [BLKIF_STATE_DISCONNECTED] = "disconnected",
   13.23 +    [BLKIF_STATE_CONNECTED]    = "connected",
   13.24 +};
   13.25 +
   13.26 +static char * blkif_status_name[] = {
   13.27 +    [BLKIF_INTERFACE_STATUS_CLOSED]       = "closed",
   13.28 +    [BLKIF_INTERFACE_STATUS_DISCONNECTED] = "disconnected",
   13.29 +    [BLKIF_INTERFACE_STATUS_CONNECTED]    = "connected",
   13.30 +    [BLKIF_INTERFACE_STATUS_CHANGED]      = "changed",
   13.31 +};
   13.32 +static unsigned int blkif_pt_state = BLKIF_STATE_CLOSED;
   13.33 +static unsigned blkif_ptbe_irq;
   13.34 +unsigned int blkif_ptbe_evtchn;
   13.35 +
   13.36 +/*-----[ Control Messages to/from Frontend VMs ]--------------------------*/
   13.37 +
   13.38 +
   13.39 +void blkif_ptfe_create(blkif_be_create_t *create)
   13.40 +{
   13.41 +    blkif_t      *blkif;
   13.42 +    domid_t       domid  = create->domid;
   13.43 +    unsigned int  handle = create->blkif_handle;
   13.44 +
   13.45 +
   13.46 +    /* May want to store info on the connecting domain here. */
   13.47 +
   13.48 +    DPRINTK("PT got BE_CREATE\n");
   13.49 +    blkif = &ptfe_blkif; /* for convenience if the hash is readded later. */
   13.50 +
   13.51 +    /* blkif struct init code from blkback.c */
   13.52 +    memset(blkif, 0, sizeof(*blkif));
   13.53 +    blkif->domid  = domid;
   13.54 +    blkif->handle = handle;
   13.55 +    blkif->status = DISCONNECTED;    
   13.56 +    spin_lock_init(&blkif->blk_ring_lock);
   13.57 +    atomic_set(&blkif->refcnt, 0);
   13.58 +
   13.59 +    create->status = BLKIF_BE_STATUS_OKAY;
   13.60 +}
   13.61 +
   13.62 +
   13.63 +void blkif_ptfe_destroy(blkif_be_destroy_t *destroy)
   13.64 +{
   13.65 +    /* Clear anything that we initialized above. */
   13.66 +
   13.67 +    DPRINTK("PT got BE_DESTROY\n");
   13.68 +    destroy->status = BLKIF_BE_STATUS_OKAY;
   13.69 +}
   13.70 +
   13.71 +void blkif_ptfe_connect(blkif_be_connect_t *connect)
   13.72 +{
   13.73 +    domid_t       domid  = connect->domid;
   13.74 +    /*unsigned int  handle = connect->blkif_handle;*/
   13.75 +    unsigned int  evtchn = connect->evtchn;
   13.76 +    unsigned long shmem_frame = connect->shmem_frame;
   13.77 +    struct vm_struct *vma;
   13.78 +    pgprot_t      prot;
   13.79 +    int           error;
   13.80 +    blkif_t      *blkif;
   13.81 +
   13.82 +    DPRINTK("PT got BE_CONNECT\n");
   13.83 +
   13.84 +    blkif = &ptfe_blkif; /* for convenience if the hash is readded later. */
   13.85 +
   13.86 +    if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL )
   13.87 +    {
   13.88 +        connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
   13.89 +        return;
   13.90 +    }
   13.91 +
   13.92 +    prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED);
   13.93 +    error = direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(vma->addr),
   13.94 +                                    shmem_frame<<PAGE_SHIFT, PAGE_SIZE,
   13.95 +                                    prot, domid);
   13.96 +    if ( error != 0 )
   13.97 +    {
   13.98 +        WPRINTK("BE_CONNECT: error! (%d)\n", error);
   13.99 +        if ( error == -ENOMEM ) 
  13.100 +            connect->status = BLKIF_BE_STATUS_OUT_OF_MEMORY;
  13.101 +        else if ( error == -EFAULT ) {
  13.102 +            connect->status = BLKIF_BE_STATUS_MAPPING_ERROR;
  13.103 +            WPRINTK("BE_CONNECT: MAPPING error!\n");
  13.104 +        }
  13.105 +        else
  13.106 +            connect->status = BLKIF_BE_STATUS_ERROR;
  13.107 +        vfree(vma->addr);
  13.108 +        return;
  13.109 +    }
  13.110 +
  13.111 +    if ( blkif->status != DISCONNECTED )
  13.112 +    {
  13.113 +        connect->status = BLKIF_BE_STATUS_INTERFACE_CONNECTED;
  13.114 +        vfree(vma->addr);
  13.115 +        return;
  13.116 +    }
  13.117 +
  13.118 +    blkif->evtchn        = evtchn;
  13.119 +    blkif->irq           = bind_evtchn_to_irq(evtchn);
  13.120 +    blkif->shmem_frame   = shmem_frame;
  13.121 +    blkif->blk_ring_base = (blkif_ring_t *)vma->addr;
  13.122 +    blkif->status        = CONNECTED;
  13.123 +    /*blkif_get(blkif);*/
  13.124 +
  13.125 +    request_irq(blkif->irq, blkif_ptfe_int, 0, "blkif-pt-backend", blkif);
  13.126 +
  13.127 +    connect->status = BLKIF_BE_STATUS_OKAY;
  13.128 +}
  13.129 +
  13.130 +void blkif_ptfe_disconnect(blkif_be_disconnect_t *disconnect)
  13.131 +{
  13.132 +    /*
  13.133 +     * don't actually set the passthrough to disconnected.
  13.134 +     * We just act as a pipe, and defer to the real ends to handle things like
  13.135 +     * recovery.
  13.136 +     */
  13.137 +
  13.138 +    DPRINTK("PT got BE_DISCONNECT\n");
  13.139 +
  13.140 +    disconnect->status = BLKIF_BE_STATUS_OKAY;
  13.141 +    return;
  13.142 +}
  13.143 +
  13.144 +/*-----[ Control Messages to/from Backend VM ]----------------------------*/
  13.145 +
  13.146 +/* Tell the controller to bring up the interface. */
  13.147 +static void blkif_ptbe_send_interface_connect(void)
  13.148 +{
  13.149 +    ctrl_msg_t cmsg = {
  13.150 +        .type    = CMSG_BLKIF_FE,
  13.151 +        .subtype = CMSG_BLKIF_FE_INTERFACE_CONNECT,
  13.152 +        .length  = sizeof(blkif_fe_interface_connect_t),
  13.153 +    };
  13.154 +    blkif_fe_interface_connect_t *msg = (void*)cmsg.msg;
  13.155 +    msg->handle      = 0;
  13.156 +    msg->shmem_frame = virt_to_machine(blk_ptbe_ring) >> PAGE_SHIFT;
  13.157 +    
  13.158 +    ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
  13.159 +}
  13.160 +
  13.161 +static void blkif_ptbe_close(void)
  13.162 +{
  13.163 +}
  13.164 +
  13.165 +/* Move from CLOSED to DISCONNECTED state. */
  13.166 +static void blkif_ptbe_disconnect(void)
  13.167 +{
  13.168 +    blk_ptbe_ring = (blkif_ring_t *)__get_free_page(GFP_KERNEL);
  13.169 +    blk_ptbe_ring->req_prod = blk_ptbe_ring->resp_prod 
  13.170 +                            = ptbe_resp_cons = ptbe_req_prod = 0;
  13.171 +    blkif_pt_state  = BLKIF_STATE_DISCONNECTED;
  13.172 +    DPRINTK("Blkif-Passthrough-BE is now DISCONNECTED.\n");
  13.173 +    blkif_ptbe_send_interface_connect();
  13.174 +}
  13.175 +
  13.176 +static void blkif_ptbe_connect(blkif_fe_interface_status_t *status)
  13.177 +{
  13.178 +    int err = 0;
  13.179 +    
  13.180 +    blkif_ptbe_evtchn = status->evtchn;
  13.181 +    blkif_ptbe_irq    = bind_evtchn_to_irq(blkif_ptbe_evtchn);
  13.182 +
  13.183 +    err = request_irq(blkif_ptbe_irq, blkif_ptbe_int, 
  13.184 +                      SA_SAMPLE_RANDOM, "blkif", NULL);
  13.185 +    if ( err ) {
  13.186 +	WPRINTK("blkfront request_irq failed (%d)\n", err);
  13.187 +        return;
  13.188 +    } else {
  13.189 +	/* transtion to connected in case we need to do a 
  13.190 +           a partion probe on a whole disk */
  13.191 +        blkif_pt_state = BLKIF_STATE_CONNECTED;
  13.192 +    }
  13.193 +}
  13.194 +
  13.195 +static void unexpected(blkif_fe_interface_status_t *status)
  13.196 +{
  13.197 +    WPRINTK(" TAP: Unexpected blkif status %s in state %s\n", 
  13.198 +           blkif_status_name[status->status],
  13.199 +           blkif_state_name[blkif_pt_state]);
  13.200 +}
  13.201 +
  13.202 +static void blkif_ptbe_status(
  13.203 +    blkif_fe_interface_status_t *status)
  13.204 +{
  13.205 +    if ( status->handle != 0 )
  13.206 +    {
  13.207 +        DPRINTK("Status change on unsupported blkif %d\n",
  13.208 +               status->handle);
  13.209 +        return;
  13.210 +    }
  13.211 +
  13.212 +    DPRINTK("ptbe_status: got %s\n", blkif_status_name[status->status]);
  13.213 +    
  13.214 +    switch ( status->status )
  13.215 +    {
  13.216 +    case BLKIF_INTERFACE_STATUS_CLOSED:
  13.217 +        switch ( blkif_pt_state )
  13.218 +        {
  13.219 +        case BLKIF_STATE_CLOSED:
  13.220 +            unexpected(status);
  13.221 +            break;
  13.222 +        case BLKIF_STATE_DISCONNECTED:
  13.223 +        case BLKIF_STATE_CONNECTED:
  13.224 +            unexpected(status);
  13.225 +            blkif_ptbe_close();
  13.226 +            break;
  13.227 +        }
  13.228 +        break;
  13.229 +        
  13.230 +    case BLKIF_INTERFACE_STATUS_DISCONNECTED:
  13.231 +        switch ( blkif_pt_state )
  13.232 +        {
  13.233 +        case BLKIF_STATE_CLOSED:
  13.234 +            blkif_ptbe_disconnect();
  13.235 +            break;
  13.236 +        case BLKIF_STATE_DISCONNECTED:
  13.237 +        case BLKIF_STATE_CONNECTED:
  13.238 +            printk(KERN_ALERT "*** add recovery code to the tap driver. ***\n");
  13.239 +            unexpected(status);
  13.240 +            break;
  13.241 +        }
  13.242 +        break;
  13.243 +        
  13.244 +    case BLKIF_INTERFACE_STATUS_CONNECTED:
  13.245 +        switch ( blkif_pt_state )
  13.246 +        {
  13.247 +        case BLKIF_STATE_CLOSED:
  13.248 +            unexpected(status);
  13.249 +            blkif_ptbe_disconnect();
  13.250 +            blkif_ptbe_connect(status);
  13.251 +            break;
  13.252 +        case BLKIF_STATE_DISCONNECTED:
  13.253 +            blkif_ptbe_connect(status);
  13.254 +            break;
  13.255 +        case BLKIF_STATE_CONNECTED:
  13.256 +            unexpected(status);
  13.257 +            blkif_ptbe_connect(status);
  13.258 +            break;
  13.259 +        }
  13.260 +        break;
  13.261 +
  13.262 +   case BLKIF_INTERFACE_STATUS_CHANGED:
  13.263 +        switch ( blkif_pt_state )
  13.264 +        {
  13.265 +        case BLKIF_STATE_CLOSED:
  13.266 +        case BLKIF_STATE_DISCONNECTED:
  13.267 +            unexpected(status);
  13.268 +            break;
  13.269 +        case BLKIF_STATE_CONNECTED:
  13.270 +            /* vbd_update(); */
  13.271 +            /* tap doesn't really get state changes... */
  13.272 +            unexpected(status);
  13.273 +            break;
  13.274 +        }
  13.275 +       break;
  13.276 +       
  13.277 +    default:
  13.278 +        DPRINTK("Status change to unknown value %d\n", status->status);
  13.279 +        break;
  13.280 +    }
  13.281 +}
  13.282 +
  13.283 +/*-----[ All control messages enter here: ]-------------------------------*/
  13.284 +
  13.285 +void blkif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
  13.286 +{
  13.287 +    switch ( msg->type )
  13.288 +    {
  13.289 +    case CMSG_BLKIF_FE:
  13.290 +
  13.291 +        switch ( msg->subtype )
  13.292 +        {
  13.293 +        case CMSG_BLKIF_FE_INTERFACE_STATUS:
  13.294 +            if ( msg->length != sizeof(blkif_fe_interface_status_t) )
  13.295 +                goto parse_error;
  13.296 +            blkif_ptbe_status((blkif_fe_interface_status_t *) &msg->msg[0]);
  13.297 +            break;        
  13.298 +
  13.299 +        default:
  13.300 +            goto parse_error;
  13.301 +        }
  13.302 +
  13.303 +    case CMSG_BLKIF_BE:
  13.304 +        
  13.305 +        switch ( msg->subtype )
  13.306 +        {
  13.307 +        case CMSG_BLKIF_BE_CREATE:
  13.308 +            if ( msg->length != sizeof(blkif_be_create_t) )
  13.309 +                goto parse_error;
  13.310 +            blkif_ptfe_create((blkif_be_create_t *)&msg->msg[0]);
  13.311 +            break; 
  13.312 +        case CMSG_BLKIF_BE_DESTROY:
  13.313 +            if ( msg->length != sizeof(blkif_be_destroy_t) )
  13.314 +                goto parse_error;
  13.315 +            blkif_ptfe_destroy((blkif_be_destroy_t *)&msg->msg[0]);
  13.316 +            break;        
  13.317 +        case CMSG_BLKIF_BE_CONNECT:
  13.318 +            if ( msg->length != sizeof(blkif_be_connect_t) )
  13.319 +                goto parse_error;
  13.320 +            blkif_ptfe_connect((blkif_be_connect_t *)&msg->msg[0]);
  13.321 +            break;        
  13.322 +        case CMSG_BLKIF_BE_DISCONNECT:
  13.323 +            if ( msg->length != sizeof(blkif_be_disconnect_t) )
  13.324 +                goto parse_error;
  13.325 +            blkif_ptfe_disconnect((blkif_be_disconnect_t *)&msg->msg[0]);
  13.326 +            break;        
  13.327 +
  13.328 +        /* We just ignore anything to do with vbds for now. */
  13.329 +        
  13.330 +        case CMSG_BLKIF_BE_VBD_CREATE:
  13.331 +            DPRINTK("PT got VBD_CREATE\n");
  13.332 +            ((blkif_be_vbd_create_t *)&msg->msg[0])->status 
  13.333 +                = BLKIF_BE_STATUS_OKAY;
  13.334 +            break;
  13.335 +        case CMSG_BLKIF_BE_VBD_DESTROY:
  13.336 +            DPRINTK("PT got VBD_DESTROY\n");
  13.337 +            ((blkif_be_vbd_destroy_t *)&msg->msg[0])->status
  13.338 +                = BLKIF_BE_STATUS_OKAY;
  13.339 +            break;
  13.340 +        case CMSG_BLKIF_BE_VBD_GROW:
  13.341 +            DPRINTK("PT got VBD_GROW\n");
  13.342 +            ((blkif_be_vbd_grow_t *)&msg->msg[0])->status
  13.343 +                = BLKIF_BE_STATUS_OKAY;
  13.344 +            break;
  13.345 +        case CMSG_BLKIF_BE_VBD_SHRINK:
  13.346 +            DPRINTK("PT got VBD_SHRINK\n");
  13.347 +            ((blkif_be_vbd_shrink_t *)&msg->msg[0])->status
  13.348 +                = BLKIF_BE_STATUS_OKAY;
  13.349 +            break;
  13.350 +        default:
  13.351 +            goto parse_error;
  13.352 +        }
  13.353 +    }
  13.354 +
  13.355 +    ctrl_if_send_response(msg);
  13.356 +    return;
  13.357 +
  13.358 + parse_error:
  13.359 +    msg->length = 0;
  13.360 +    ctrl_if_send_response(msg);
  13.361 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_datapath.c	Wed Nov 24 12:07:16 2004 +0000
    14.3 @@ -0,0 +1,517 @@
    14.4 +/******************************************************************************
    14.5 + * blktap_datapath.c
    14.6 + * 
    14.7 + * XenLinux virtual block-device tap.
    14.8 + * Block request routing data path.
    14.9 + * 
   14.10 + * Copyright (c) 2004, Andrew Warfield
   14.11 + *
   14.12 + */
   14.13 + 
   14.14 +#include "blktap.h"
   14.15 +
   14.16 +/*-----[ The data paths ]-------------------------------------------------*/
   14.17 + 
   14.18 +/* Connections to the frontend domains.*/
   14.19 +blkif_t   ptfe_blkif; 
   14.20 + 
   14.21 +/* Connection to a single backend domain. */
   14.22 +blkif_ring_t *blk_ptbe_ring;   /* Ring from the PT to the BE dom    */ 
   14.23 +BLKIF_RING_IDX ptbe_resp_cons; /* Response consumer for comms ring. */
   14.24 +BLKIF_RING_IDX ptbe_req_prod;  /* Private request producer.         */
   14.25 +
   14.26 +/* Rings up to user space. */ 
   14.27 +blkif_req_ring_t fe_ring;// = BLKIF_REQ_RING_INIT;
   14.28 +blkif_rsp_ring_t be_ring;// = BLKIF_RSP_RING_INIT;
   14.29 +
   14.30 +/*-----[ Ring helpers ]---------------------------------------------------*/
   14.31 +
   14.32 +inline int BLKTAP_RING_FULL(blkif_generic_ring_t *ring)
   14.33 +{
   14.34 +    if (ring->type == BLKIF_REQ_RING_TYPE) {
   14.35 +        blkif_req_ring_t *r = (blkif_req_ring_t *)ring;
   14.36 +        return ( ( r->req_prod - r->rsp_cons ) == BLKIF_RING_SIZE );
   14.37 +    }
   14.38 +    
   14.39 +    /* for now assume that there is always room in the response path. */
   14.40 +    return 0;
   14.41 +}
   14.42 +
   14.43 +/*-----[ Tracking active requests ]---------------------------------------*/
   14.44 +
   14.45 +/* this must be the same as MAX_PENDING_REQS in blkback.c */
   14.46 +#define MAX_ACTIVE_REQS 64
   14.47 +
   14.48 +active_req_t  active_reqs[MAX_ACTIVE_REQS];
   14.49 +unsigned char active_req_ring[MAX_ACTIVE_REQS];
   14.50 +spinlock_t    active_req_lock = SPIN_LOCK_UNLOCKED;
   14.51 +typedef unsigned int ACTIVE_RING_IDX;
   14.52 +ACTIVE_RING_IDX active_prod, active_cons;
   14.53 +#define MASK_ACTIVE_IDX(_i) ((_i)&(MAX_ACTIVE_REQS-1))
   14.54 +#define ACTIVE_IDX(_ar) (_ar - active_reqs)
   14.55 +
   14.56 +inline active_req_t *get_active_req(void) 
   14.57 +{
   14.58 +    ASSERT(active_cons != active_prod);    
   14.59 +    return &active_reqs[MASK_ACTIVE_IDX(active_cons++)];
   14.60 +}
   14.61 +
   14.62 +inline void free_active_req(active_req_t *ar) 
   14.63 +{
   14.64 +    unsigned long flags;
   14.65 +        
   14.66 +    spin_lock_irqsave(&active_req_lock, flags);
   14.67 +    active_req_ring[MASK_ACTIVE_IDX(active_prod++)] = ACTIVE_IDX(ar);
   14.68 +    spin_unlock_irqrestore(&active_req_lock, flags);
   14.69 +}
   14.70 +
   14.71 +inline void active_reqs_init(void)
   14.72 +{
   14.73 +    ACTIVE_RING_IDX i;
   14.74 +    
   14.75 +    active_cons = 0;
   14.76 +    active_prod = MAX_ACTIVE_REQS;
   14.77 +    memset(active_reqs, 0, sizeof(active_reqs));
   14.78 +    for ( i = 0; i < MAX_ACTIVE_REQS; i++ )
   14.79 +        active_req_ring[i] = i;
   14.80 +}
   14.81 +
   14.82 +/*-----[ Data to/from Frontend (client) VMs ]-----------------------------*/
   14.83 +
   14.84 +irqreturn_t blkif_ptfe_int(int irq, void *dev_id, struct pt_regs *regs)
   14.85 +{
   14.86 +    /* we have pending messages from the real frontend. */
   14.87 +
   14.88 +    blkif_request_t *req_s, *req_d;
   14.89 +    BLKIF_RING_IDX fe_rp;
   14.90 +    unsigned long flags;
   14.91 +    int notify;
   14.92 +    unsigned long i;
   14.93 +    active_req_t *ar;
   14.94 +    
   14.95 +    DPRINTK("PT got FE interrupt.\n");
   14.96 +    
   14.97 +    /* lock both rings */
   14.98 +    spin_lock_irqsave(&blkif_io_lock, flags);
   14.99 +
  14.100 +    /* While there are REQUESTS on FERing: */
  14.101 +    fe_rp = ptfe_blkif.blk_ring_base->req_prod;
  14.102 +    rmb();
  14.103 +    notify = (ptfe_blkif.blk_req_cons != fe_rp);
  14.104 +
  14.105 +    for (i = ptfe_blkif.blk_req_cons; i != fe_rp; i++) {
  14.106 +
  14.107 +        /* Get the next request */
  14.108 +        req_s = &ptfe_blkif.blk_ring_base->ring[MASK_BLKIF_IDX(i)].req;
  14.109 +        
  14.110 +        /* This is a new request:  
  14.111 +         * Assign an active request record, and remap the id. 
  14.112 +         */
  14.113 +        ar = get_active_req();
  14.114 +        ar->id = req_s->id;
  14.115 +        req_s->id = ACTIVE_IDX(ar);
  14.116 +        DPRINTK("%3lu < %3lu\n", req_s->id, ar->id);
  14.117 +
  14.118 +        /* FE -> BE interposition point is here. */
  14.119 +        
  14.120 +        /* ------------------------------------------------------------- */
  14.121 +        /* BLKIF_OP_PROBE_HACK:                                          */
  14.122 +        /* Until we have grant tables, we need to allow the backent to   */
  14.123 +        /* map pages that are either from this domain, or more commonly  */
  14.124 +        /* from the real front end.  We achieve this in a terrible way,  */
  14.125 +        /* by passing the front end's domid allong with PROBE messages   */
  14.126 +        /* Once grant tables appear, this should all go away.            */
  14.127 +
  14.128 +        if (req_s->operation == BLKIF_OP_PROBE) {
  14.129 +            DPRINTK("Adding FE domid to PROBE request.\n");
  14.130 +            (domid_t)(req_s->frame_and_sects[1]) = ptfe_blkif.domid;
  14.131 +        }
  14.132 +
  14.133 +        /* ------------------------------------------------------------- */
  14.134 +
  14.135 +        /* If we are in MODE_INTERCEPT_FE or MODE_COPY_FE: */
  14.136 +        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  14.137 +             (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
  14.138 +            
  14.139 +            /* Copy the response message to UFERing */
  14.140 +            /* In MODE_INTERCEPT_FE, map attached pages into the app vma */
  14.141 +            /* In MODE_COPY_FE_PAGES, copy attached pages into the app vma */
  14.142 +
  14.143 +            /* XXX: mapping/copying of attached pages is still not done! */
  14.144 +
  14.145 +            DPRINTK("req->UFERing\n"); 
  14.146 +            blktap_write_fe_ring(req_s);
  14.147 +
  14.148 +
  14.149 +        }
  14.150 +
  14.151 +        /* If we are not in MODE_INTERCEPT_FE or MODE_INTERCEPT_BE: */
  14.152 +        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  14.153 +               (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) {
  14.154 +            
  14.155 +            /* be included to prevent noise from the fe when its off */
  14.156 +            /* copy the request message to the BERing */
  14.157 +
  14.158 +            DPRINTK("blktap: FERing[%u] -> BERing[%u]\n", 
  14.159 +                    (unsigned)MASK_BLKIF_IDX(i), 
  14.160 +                    (unsigned)MASK_BLKIF_IDX(ptbe_req_prod));
  14.161 +
  14.162 +            req_d = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(ptbe_req_prod)].req;
  14.163 +            
  14.164 +            memcpy(req_d, req_s, sizeof(blkif_request_t));
  14.165 +
  14.166 +            ptbe_req_prod++;
  14.167 +        }
  14.168 +    }
  14.169 +
  14.170 +    ptfe_blkif.blk_req_cons = i;
  14.171 +
  14.172 +    /* If we have forwarded any responses, notify the appropriate ends. */
  14.173 +    if (notify) {
  14.174 +
  14.175 +        /* we have sent stuff to the be, notify it. */
  14.176 +        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  14.177 +               (blktap_mode & BLKTAP_MODE_INTERCEPT_BE)) ) {
  14.178 +            wmb();
  14.179 +            blk_ptbe_ring->req_prod = ptbe_req_prod;
  14.180 +
  14.181 +            notify_via_evtchn(blkif_ptbe_evtchn);
  14.182 +            DPRINTK(" -- and notified.\n");
  14.183 +        }
  14.184 +
  14.185 +        /* we sent stuff to the app, notify it. */
  14.186 +        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) ||
  14.187 +             (blktap_mode & BLKTAP_MODE_COPY_FE) ) {
  14.188 +
  14.189 +            blktap_kick_user();
  14.190 +        }
  14.191 +    }
  14.192 +
  14.193 +    /* unlock rings */
  14.194 +    spin_unlock_irqrestore(&blkif_io_lock, flags);
  14.195 +
  14.196 +    return IRQ_HANDLED;
  14.197 +}
  14.198 +
  14.199 +inline int write_req_to_be_ring(blkif_request_t *req)
  14.200 +{
  14.201 +    blkif_request_t *req_d;
  14.202 +
  14.203 +    req_d = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(ptbe_req_prod)].req;
  14.204 +    memcpy(req_d, req, sizeof(blkif_request_t));
  14.205 +    ptbe_req_prod++;
  14.206 +
  14.207 +    return 0;
  14.208 +}
  14.209 +
  14.210 +inline void kick_be_domain(void) {
  14.211 +    wmb();
  14.212 +    blk_ptbe_ring->req_prod = ptbe_req_prod;
  14.213 +    notify_via_evtchn(blkif_ptbe_evtchn);
  14.214 +}
  14.215 +
  14.216 +/*-----[ Data to/from Backend (server) VM ]------------------------------*/
  14.217 +
  14.218 +
  14.219 +irqreturn_t blkif_ptbe_int(int irq, void *dev_id, 
  14.220 +                                  struct pt_regs *ptregs)
  14.221 +{
  14.222 +    blkif_response_t  *resp_s, *resp_d;
  14.223 +    BLKIF_RING_IDX be_rp;
  14.224 +    unsigned long flags;
  14.225 +    int notify;
  14.226 +    unsigned long i;
  14.227 +    active_req_t *ar;
  14.228 +
  14.229 +    DPRINTK("PT got BE interrupt.\n");
  14.230 +
  14.231 +    /* lock both rings */
  14.232 +    spin_lock_irqsave(&blkif_io_lock, flags);
  14.233 +    
  14.234 +    /* While there are RESPONSES on BERing: */
  14.235 +    be_rp = blk_ptbe_ring->resp_prod;
  14.236 +    rmb();
  14.237 +    notify = (ptbe_resp_cons != be_rp);
  14.238 +    
  14.239 +    for ( i = ptbe_resp_cons; i != be_rp; i++ )
  14.240 +    {
  14.241 +        /* BE -> FE interposition point is here. */
  14.242 +        
  14.243 +        /* Get the next response */
  14.244 +        resp_s = &blk_ptbe_ring->ring[MASK_BLKIF_IDX(i)].resp;
  14.245 +    
  14.246 +       
  14.247 +        /* If we are in MODE_INTERCEPT_BE or MODE_COPY_BE: */
  14.248 +        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  14.249 +             (blktap_mode & BLKTAP_MODE_COPY_BE) ) {
  14.250 +
  14.251 +            /* Copy the response message to UBERing */
  14.252 +            /* In MODE_INTERCEPT_BE, map attached pages into the app vma */
  14.253 +            /* In MODE_COPY_BE_PAGES, copy attached pages into the app vma */
  14.254 +
  14.255 +            /* XXX: copy/map the attached page! */
  14.256 +
  14.257 +            DPRINTK("rsp->UBERing\n"); 
  14.258 +            blktap_write_be_ring(resp_s);
  14.259 +
  14.260 +        }
  14.261 +       
  14.262 +        /* If we are NOT in MODE_INTERCEPT_BE or MODE_INTERCEPT_FE: */
  14.263 +        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  14.264 +               (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) {
  14.265 +            
  14.266 +            /* (fe included to prevent random interference from the BE) */
  14.267 +            /* Copy the response message to FERing */
  14.268 +         
  14.269 +            DPRINTK("blktap: BERing[%u] -> FERing[%u]\n", 
  14.270 +                    (unsigned) MASK_BLKIF_IDX(i), 
  14.271 +                    (unsigned) MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod));
  14.272 +
  14.273 +            /* remap id, and free the active req. blkif lookup goes here too.*/
  14.274 +            ar = &active_reqs[resp_s->id];
  14.275 +            DPRINTK("%3lu > %3lu\n", resp_s->id, ar->id);
  14.276 +            resp_s->id = ar->id;
  14.277 +            free_active_req(ar);
  14.278 +           
  14.279 +            resp_d = &ptfe_blkif.blk_ring_base->ring[
  14.280 +                MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod)].resp;
  14.281 +
  14.282 +            memcpy(resp_d, resp_s, sizeof(blkif_response_t));
  14.283 +            
  14.284 +            ptfe_blkif.blk_resp_prod++;
  14.285 +
  14.286 +        }
  14.287 +    }
  14.288 +
  14.289 +    ptbe_resp_cons = i;
  14.290 +    
  14.291 +    /* If we have forwarded any responses, notify the apropriate domains. */
  14.292 +    if (notify) {
  14.293 +
  14.294 +        /* we have sent stuff to the fe.  notify it. */
  14.295 +        if ( !((blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  14.296 +               (blktap_mode & BLKTAP_MODE_INTERCEPT_FE)) ) {
  14.297 +            wmb();
  14.298 +            ptfe_blkif.blk_ring_base->resp_prod = ptfe_blkif.blk_resp_prod;
  14.299 +        
  14.300 +            notify_via_evtchn(ptfe_blkif.evtchn);
  14.301 +            DPRINTK(" -- and notified.\n");
  14.302 +        }
  14.303 +
  14.304 +        /* we sent stuff to the app, notify it. */
  14.305 +        if ( (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) ||
  14.306 +             (blktap_mode & BLKTAP_MODE_COPY_BE) ) {
  14.307 +
  14.308 +            blktap_kick_user();
  14.309 +        }
  14.310 +    }
  14.311 +
  14.312 +    spin_unlock_irqrestore(&blkif_io_lock, flags);
  14.313 +    return IRQ_HANDLED;
  14.314 +}
  14.315 +
  14.316 +inline int write_resp_to_fe_ring(blkif_response_t *rsp)
  14.317 +{
  14.318 +    blkif_response_t *resp_d;
  14.319 +    active_req_t *ar;
  14.320 +    
  14.321 +    /* remap id, and free the active req. blkif lookup goes here too.*/
  14.322 +    ar = &active_reqs[rsp->id];
  14.323 +    DPRINTK("%3lu > %3lu\n", rsp->id, ar->id);
  14.324 +    rsp->id = ar->id;
  14.325 +    free_active_req(ar);
  14.326 +            
  14.327 +    resp_d = &ptfe_blkif.blk_ring_base->ring[
  14.328 +        MASK_BLKIF_IDX(ptfe_blkif.blk_resp_prod)].resp;
  14.329 +
  14.330 +    memcpy(resp_d, rsp, sizeof(blkif_response_t));
  14.331 +    ptfe_blkif.blk_resp_prod++;
  14.332 +
  14.333 +    return 0;
  14.334 +}
  14.335 +
  14.336 +inline void kick_fe_domain(void) {
  14.337 +    wmb();
  14.338 +    ptfe_blkif.blk_ring_base->resp_prod = ptfe_blkif.blk_resp_prod;
  14.339 +    notify_via_evtchn(ptfe_blkif.evtchn);
  14.340 +    
  14.341 +}
  14.342 +
  14.343 +static inline void flush_requests(void)
  14.344 +{
  14.345 +    wmb(); /* Ensure that the frontend can see the requests. */
  14.346 +    blk_ptbe_ring->req_prod = ptbe_req_prod;
  14.347 +    notify_via_evtchn(blkif_ptbe_evtchn);
  14.348 +}
  14.349 +
  14.350 +/*-----[ Data to/from user space ]----------------------------------------*/
  14.351 +
  14.352 +
  14.353 +int blktap_write_fe_ring(blkif_request_t *req)
  14.354 +{
  14.355 +    blkif_request_t *target;
  14.356 +    int error, i;
  14.357 +
  14.358 +    /*
  14.359 +     * This is called to pass a request from the real frontend domain's
  14.360 +     * blkif ring to the character device.
  14.361 +     */
  14.362 +
  14.363 +    if ( ! blktap_ring_ok ) {
  14.364 +        DPRINTK("blktap: fe_ring not ready for a request!\n");
  14.365 +        return 0;
  14.366 +    }
  14.367 +
  14.368 +    if ( BLKTAP_RING_FULL(RING(&fe_ring)) ) {
  14.369 +        DPRINTK("blktap: fe_ring is full, can't add.\n");
  14.370 +        return 0;
  14.371 +    }
  14.372 +
  14.373 +    target = &fe_ring.ring->ring[MASK_BLKIF_IDX(fe_ring.req_prod)].req;
  14.374 +    memcpy(target, req, sizeof(*req));
  14.375 +
  14.376 +/* maybe move this stuff out into a seperate func ------------------- */
  14.377 +
  14.378 +    /*
  14.379 +     * For now, map attached page into a fixed position into the vma.
  14.380 +     * XXX: make this map to a free page.
  14.381 +     */
  14.382 +
  14.383 +    /* Attempt to map the foreign pages directly in to the application */
  14.384 +    for (i=0; i<target->nr_segments; i++) {
  14.385 +
  14.386 +        /* get an unused virtual address from the char device */
  14.387 +        /* store the old page address */
  14.388 +        /* replace the address with the virtual address */
  14.389 +
  14.390 +        /* blktap_vma->vm_start+((2+i)*PAGE_SIZE) */
  14.391 +
  14.392 +        error = direct_remap_area_pages(blktap_vma->vm_mm, 
  14.393 +                                        MMAP_VADDR(req->id, i), 
  14.394 +                                        target->frame_and_sects[0] & PAGE_MASK,
  14.395 +                                        PAGE_SIZE,
  14.396 +                                        blktap_vma->vm_page_prot,
  14.397 +                                        ptfe_blkif.domid);
  14.398 +        if ( error != 0 ) {
  14.399 +            printk(KERN_INFO "remapping attached page failed! (%d)\n", error);
  14.400 +            return 0;
  14.401 +        }
  14.402 +    }
  14.403 +    /* fix the address of the attached page in the message. */
  14.404 +    /* TODO:      preserve the segment number stuff here... */
  14.405 +    /* target->frame_and_sects[0] = blktap_vma->vm_start + PAGE_SIZE;*/
  14.406 +/* ------------------------------------------------------------------ */
  14.407 +
  14.408 +    
  14.409 +    fe_ring.req_prod++;
  14.410 +
  14.411 +    return 0;
  14.412 +}
  14.413 +
  14.414 +int blktap_write_be_ring(blkif_response_t *rsp)
  14.415 +{
  14.416 +    blkif_response_t *target;
  14.417 +
  14.418 +    /*
  14.419 +     * This is called to pass a request from the real backend domain's
  14.420 +     * blkif ring to the character device.
  14.421 +     */
  14.422 +
  14.423 +    if ( ! blktap_ring_ok ) {
  14.424 +        DPRINTK("blktap: be_ring not ready for a request!\n");
  14.425 +        return 0;
  14.426 +    }
  14.427 +
  14.428 +    if ( BLKTAP_RING_FULL(RING(&be_ring)) ) {
  14.429 +        DPRINTK("blktap: be_ring is full, can't add.\n");
  14.430 +        return 0;
  14.431 +    }
  14.432 +
  14.433 +    target = &be_ring.ring->ring[MASK_BLKIF_IDX(be_ring.rsp_prod)].resp;
  14.434 +    memcpy(target, rsp, sizeof(*rsp));
  14.435 +
  14.436 +
  14.437 +    /* XXX: map attached pages and fix-up addresses in the copied address. */
  14.438 +
  14.439 +    be_ring.rsp_prod++;
  14.440 +
  14.441 +    return 0;
  14.442 +}
  14.443 +
  14.444 +int blktap_read_fe_ring(void)
  14.445 +{
  14.446 +    /* This is called to read responses from the UFE ring. */
  14.447 +
  14.448 +    BLKIF_RING_IDX fe_rp;
  14.449 +    unsigned long i;
  14.450 +    int notify;
  14.451 +
  14.452 +    DPRINTK("blktap_read_fe_ring()\n");
  14.453 +
  14.454 +    fe_rp = fe_ring.ring->resp_prod;
  14.455 +    rmb();
  14.456 +    notify = (fe_rp != fe_ring.rsp_cons);
  14.457 +
  14.458 +    /* if we are forwarding from UFERring to FERing */
  14.459 +    if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
  14.460 +
  14.461 +        /* for each outstanding message on the UFEring  */
  14.462 +        for ( i = fe_ring.rsp_cons; i != fe_rp; i++ ) {
  14.463 +
  14.464 +            /* XXX: remap pages on that message as necessary */
  14.465 +            /* copy the message to the UBEring */
  14.466 +
  14.467 +            DPRINTK("resp->fe_ring\n");
  14.468 +            write_resp_to_fe_ring(&fe_ring.ring->ring[MASK_BLKIF_IDX(i)].resp);
  14.469 +        }
  14.470 +    
  14.471 +        fe_ring.rsp_cons = fe_rp;
  14.472 +
  14.473 +        /* notify the fe if necessary */
  14.474 +        if ( notify ) {
  14.475 +            DPRINTK("kick_fe_domain()\n");
  14.476 +            kick_fe_domain();
  14.477 +        }
  14.478 +    }
  14.479 +
  14.480 +    return 0;
  14.481 +}
  14.482 +
  14.483 +int blktap_read_be_ring(void)
  14.484 +{
  14.485 +    /* This is called to read responses from the UBE ring. */
  14.486 +
  14.487 +    BLKIF_RING_IDX be_rp;
  14.488 +    unsigned long i;
  14.489 +    int notify;
  14.490 +
  14.491 +    DPRINTK("blktap_read_be_ring()\n");
  14.492 +
  14.493 +    be_rp = be_ring.ring->req_prod;
  14.494 +    rmb();
  14.495 +    notify = (be_rp != be_ring.req_cons);
  14.496 +
  14.497 +    /* if we are forwarding from UFERring to FERing */
  14.498 +    if (blktap_mode & BLKTAP_MODE_INTERCEPT_BE) {
  14.499 +
  14.500 +        /* for each outstanding message on the UFEring  */
  14.501 +        for ( i = be_ring.req_cons; i != be_rp; i++ ) {
  14.502 +
  14.503 +            /* XXX: remap pages on that message as necessary */
  14.504 +            /* copy the message to the UBEring */
  14.505 +
  14.506 +            DPRINTK("req->be_ring\n");
  14.507 +            write_req_to_be_ring(&be_ring.ring->ring[MASK_BLKIF_IDX(i)].req);
  14.508 +        }
  14.509 +    
  14.510 +        be_ring.req_cons = be_rp;
  14.511 +
  14.512 +        /* notify the fe if necessary */
  14.513 +        if ( notify ) {
  14.514 +            DPRINTK("kick_be_domain()\n");
  14.515 +            kick_be_domain();
  14.516 +        }
  14.517 +    }
  14.518 +
  14.519 +    return 0;
  14.520 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/linux-2.6.9-xen-sparse/drivers/xen/blktap/blktap_userdev.c	Wed Nov 24 12:07:16 2004 +0000
    15.3 @@ -0,0 +1,243 @@
    15.4 +/******************************************************************************
    15.5 + * blktap_userdev.c
    15.6 + * 
    15.7 + * XenLinux virtual block-device tap.
    15.8 + * Control interface between the driver and a character device.
    15.9 + * 
   15.10 + * Copyright (c) 2004, Andrew Warfield
   15.11 + *
   15.12 + */
   15.13 +
   15.14 +#include <linux/config.h>
   15.15 +#include <linux/module.h>
   15.16 +#include <linux/kernel.h>
   15.17 +#include <linux/fs.h>
   15.18 +#include <linux/mm.h>
   15.19 +#include <linux/miscdevice.h>
   15.20 +#include <linux/errno.h>
   15.21 +#include <linux/major.h>
   15.22 +#include <linux/gfp.h>
   15.23 +#include <linux/poll.h>
   15.24 +#include <asm/pgalloc.h>
   15.25 +
   15.26 +#include "blktap.h"
   15.27 +
   15.28 +
   15.29 +unsigned long blktap_mode = BLKTAP_MODE_PASSTHROUGH;
   15.30 +
   15.31 +/* Only one process may open /dev/xen/blktap at any time. */
   15.32 +static unsigned long blktap_dev_inuse;
   15.33 +unsigned long blktap_ring_ok; /* make this ring->state */
   15.34 +
   15.35 +/* for poll: */
   15.36 +static wait_queue_head_t blktap_wait;
   15.37 +
   15.38 +/* Where things are inside the device mapping. */
   15.39 +struct vm_area_struct *blktap_vma;
   15.40 +unsigned long mmap_vstart;
   15.41 +unsigned long rings_vstart;
   15.42 +
   15.43 +/* -------[ blktap vm ops ]------------------------------------------- */
   15.44 +
   15.45 +static struct page *blktap_nopage(struct vm_area_struct *vma,
   15.46 +                                             unsigned long address,
   15.47 +                                             int *type)
   15.48 +{
   15.49 +    /*
   15.50 +     * if the page has not been mapped in by the driver then generate
   15.51 +     * a SIGBUS to the domain.
   15.52 +     */
   15.53 +
   15.54 +    force_sig(SIGBUS, current);
   15.55 +
   15.56 +    return 0;
   15.57 +}
   15.58 +
   15.59 +struct vm_operations_struct blktap_vm_ops = {
   15.60 +    nopage:   blktap_nopage,
   15.61 +};
   15.62 +
   15.63 +/* -------[ blktap file ops ]----------------------------------------- */
   15.64 +
   15.65 +static int blktap_open(struct inode *inode, struct file *filp)
   15.66 +{
   15.67 +    if ( test_and_set_bit(0, &blktap_dev_inuse) )
   15.68 +        return -EBUSY;
   15.69 +
   15.70 +    printk(KERN_ALERT "blktap open.\n");
   15.71 +
   15.72 +    /* Allocate the fe ring. */
   15.73 +    fe_ring.ring = (blkif_ring_t *)get_zeroed_page(GFP_KERNEL);
   15.74 +    if (fe_ring.ring == NULL)
   15.75 +        goto fail_nomem;
   15.76 +
   15.77 +    SetPageReserved(virt_to_page(fe_ring.ring));
   15.78 +    
   15.79 +    fe_ring.ring->req_prod = fe_ring.ring->resp_prod
   15.80 +                           = fe_ring.req_prod
   15.81 +                           = fe_ring.rsp_cons
   15.82 +                           = 0;
   15.83 +
   15.84 +    /* Allocate the be ring. */
   15.85 +    be_ring.ring = (blkif_ring_t *)get_zeroed_page(GFP_KERNEL);
   15.86 +    if (be_ring.ring == NULL)
   15.87 +        goto fail_free_fe;
   15.88 +
   15.89 +    SetPageReserved(virt_to_page(be_ring.ring));
   15.90 +    
   15.91 +    be_ring.ring->req_prod = be_ring.ring->resp_prod
   15.92 +                           = be_ring.rsp_prod
   15.93 +                           = be_ring.req_cons
   15.94 +                           = 0;
   15.95 +
   15.96 +    DPRINTK(KERN_ALERT "blktap open.\n");
   15.97 +
   15.98 +    return 0;
   15.99 +
  15.100 + fail_free_fe:
  15.101 +    free_page( (unsigned long) fe_ring.ring);
  15.102 +
  15.103 + fail_nomem:
  15.104 +    return -ENOMEM;
  15.105 +}
  15.106 +
  15.107 +static int blktap_release(struct inode *inode, struct file *filp)
  15.108 +{
  15.109 +    blktap_dev_inuse = 0;
  15.110 +    blktap_ring_ok = 0;
  15.111 +
  15.112 +    printk(KERN_ALERT "blktap closed.\n");
  15.113 +
  15.114 +    /* Free the ring page. */
  15.115 +    ClearPageReserved(virt_to_page(fe_ring.ring));
  15.116 +    free_page((unsigned long) fe_ring.ring);
  15.117 +
  15.118 +    ClearPageReserved(virt_to_page(be_ring.ring));
  15.119 +    free_page((unsigned long) be_ring.ring);
  15.120 +    
  15.121 +    return 0;
  15.122 +}
  15.123 +
  15.124 +static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
  15.125 +{
  15.126 +    int size;
  15.127 +
  15.128 +    printk(KERN_ALERT "blktap mmap (%lx, %lx)\n",
  15.129 +           vma->vm_start, vma->vm_end);
  15.130 +
  15.131 +    vma->vm_ops = &blktap_vm_ops;
  15.132 +
  15.133 +    size = vma->vm_end - vma->vm_start;
  15.134 +    if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) {
  15.135 +        printk(KERN_INFO 
  15.136 +               "blktap: you _must_ map exactly %d pages!\n",
  15.137 +               MMAP_PAGES + RING_PAGES);
  15.138 +        return -EAGAIN;
  15.139 +    }
  15.140 +
  15.141 +    size >>= PAGE_SHIFT;
  15.142 +    printk(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
  15.143 +    
  15.144 +    rings_vstart = vma->vm_start;
  15.145 +    mmap_vstart  = rings_vstart + (RING_PAGES << PAGE_SHIFT);
  15.146 +    
  15.147 +    /* Map the ring pages to the start of the region and reserve it. */
  15.148 +
  15.149 +    /* not sure if I really need to do this... */
  15.150 +    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
  15.151 +
  15.152 +    DPRINTK("Mapping be_ring page %lx.\n", __pa(be_ring.ring));
  15.153 +    if (remap_page_range(vma, vma->vm_start, __pa(be_ring.ring), PAGE_SIZE, 
  15.154 +                         vma->vm_page_prot)) {
  15.155 +        printk(KERN_ERR "be_ring: remap_page_range failure!\n");
  15.156 +    }
  15.157 +
  15.158 +    DPRINTK("Mapping fe_ring page %lx.\n", __pa(fe_ring.ring));
  15.159 +    if (remap_page_range(vma, vma->vm_start + PAGE_SIZE, __pa(fe_ring.ring), 
  15.160 +                         PAGE_SIZE, vma->vm_page_prot)) {
  15.161 +        printk(KERN_ERR "fe_ring: remap_page_range failure!\n");
  15.162 +    }
  15.163 +
  15.164 +    blktap_vma = vma;
  15.165 +    blktap_ring_ok = 1;
  15.166 +
  15.167 +    return 0;
  15.168 +}
  15.169 +
  15.170 +static int blktap_ioctl(struct inode *inode, struct file *filp,
  15.171 +                        unsigned int cmd, unsigned long arg)
  15.172 +{
  15.173 +    switch(cmd) {
  15.174 +    case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
  15.175 +        return blktap_read_fe_ring();
  15.176 +
  15.177 +    case BLKTAP_IOCTL_KICK_BE: /* There are be messages to process. */
  15.178 +        return blktap_read_be_ring();
  15.179 +
  15.180 +    case BLKTAP_IOCTL_SETMODE:
  15.181 +        if (BLKTAP_MODE_VALID(arg)) {
  15.182 +            blktap_mode = arg;
  15.183 +            /* XXX: may need to flush rings here. */
  15.184 +            printk(KERN_INFO "blktap: set mode to %lx\n", arg);
  15.185 +            return 0;
  15.186 +        }
  15.187 +        /* XXX: return a more meaningful error case here. */
  15.188 +    }
  15.189 +    return -ENOIOCTLCMD;
  15.190 +}
  15.191 +
  15.192 +static unsigned int blktap_poll(struct file *file, poll_table *wait)
  15.193 +{
  15.194 +        poll_wait(file, &blktap_wait, wait);
  15.195 +
  15.196 +        if ( (fe_ring.req_prod != fe_ring.ring->req_prod) ||
  15.197 +             (be_ring.rsp_prod != be_ring.ring->resp_prod) ) {
  15.198 +
  15.199 +            fe_ring.ring->req_prod = fe_ring.req_prod;
  15.200 +            be_ring.ring->resp_prod = be_ring.rsp_prod;
  15.201 +            return POLLIN | POLLRDNORM;
  15.202 +        }
  15.203 +
  15.204 +        return 0;
  15.205 +}
  15.206 +
  15.207 +void blktap_kick_user(void)
  15.208 +{
  15.209 +    /* blktap_ring->req_prod = blktap_req_prod; */
  15.210 +    wake_up_interruptible(&blktap_wait);
  15.211 +}
  15.212 +
  15.213 +static struct file_operations blktap_fops = {
  15.214 +    owner:    THIS_MODULE,
  15.215 +    poll:     blktap_poll,
  15.216 +    ioctl:    blktap_ioctl,
  15.217 +    open:     blktap_open,
  15.218 +    release:  blktap_release,
  15.219 +    mmap:     blktap_mmap,
  15.220 +};
  15.221 +
  15.222 +/* -------[ blktap module setup ]------------------------------------- */
  15.223 +
  15.224 +static struct miscdevice blktap_miscdev = {
  15.225 +    .minor        = BLKTAP_MINOR,
  15.226 +    .name         = "blktap",
  15.227 +    .fops         = &blktap_fops,
  15.228 +    .devfs_name   = "misc/blktap",
  15.229 +};
  15.230 +
  15.231 +int blktap_init(void)
  15.232 +{
  15.233 +    int err;
  15.234 +
  15.235 +    err = misc_register(&blktap_miscdev);
  15.236 +    if ( err != 0 )
  15.237 +    {
  15.238 +        printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err);
  15.239 +        return err;
  15.240 +    }
  15.241 +
  15.242 +    init_waitqueue_head(&blktap_wait);
  15.243 +
  15.244 +
  15.245 +    return 0;
  15.246 +}
    16.1 --- a/tools/libxutil/Makefile	Wed Nov 24 11:51:49 2004 +0000
    16.2 +++ b/tools/libxutil/Makefile	Wed Nov 24 12:07:16 2004 +0000
    16.3 @@ -5,11 +5,18 @@ CC = gcc
    16.4  
    16.5  LIB_SRCS :=
    16.6  LIB_SRCS += allocate.c
    16.7 +LIB_SRCS += enum.c
    16.8  LIB_SRCS += file_stream.c
    16.9  LIB_SRCS += gzip_stream.c
   16.10 +LIB_SRCS += hash_table.c
   16.11  LIB_SRCS += iostream.c
   16.12 -#LIB_SRCS += sys_net.c
   16.13 +LIB_SRCS += lexis.c
   16.14 +LIB_SRCS += string_stream.c
   16.15 +LIB_SRCS += sxpr.c
   16.16 +LIB_SRCS += sxpr_parser.c
   16.17 +LIB_SRCS += sys_net.c
   16.18  LIB_SRCS += sys_string.c
   16.19 +LIB_SRCS += util.c
   16.20  
   16.21  LIB_OBJS := $(LIB_SRCS:.c=.o)
   16.22  
   16.23 @@ -29,6 +36,7 @@ LIB_NAME := libxutil
   16.24  LIB      := $(LIB_NAME).so 
   16.25  LIB      += $(LIB_NAME).so.$(MAJOR)
   16.26  LIB      += $(LIB_NAME).so.$(MAJOR).$(MINOR)
   16.27 +LIB      += $(LIB_NAME).a
   16.28  
   16.29  all: check-for-zlib
   16.30  	$(MAKE) $(LIB)
   16.31 @@ -42,6 +50,9 @@ all: check-for-zlib
   16.32  $(LIB_NAME).so.$(MAJOR).$(MINOR): $(LIB_OBJS)
   16.33  	$(CC) -Wl,-soname -Wl,$(LIB_NAME).so.$(MAJOR) -shared -o $@ $^
   16.34  
   16.35 +$(LIB_NAME).a: $(LIB_OBJS)
   16.36 +	$(AR) rc $@ $^
   16.37 +
   16.38  check-for-zlib:
   16.39  	@if [ ! -e /usr/include/zlib.h ]; then \
   16.40  	echo "***********************************************************"; \
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/libxutil/debug.h	Wed Nov 24 12:07:16 2004 +0000
    17.3 @@ -0,0 +1,72 @@
    17.4 +/*
    17.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    17.6 + *
    17.7 + * This library is free software; you can redistribute it and/or modify
    17.8 + * it under the terms of the GNU Lesser General Public License as published by
    17.9 + * the Free Software Foundation; either version 2.1 of the License, or
   17.10 + * (at your option) any later version.
   17.11 + *
   17.12 + * This library is distributed in the hope that it will be useful,
   17.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.15 + * GNU Lesser General Public License for more details.
   17.16 + *
   17.17 + * You should have received a copy of the GNU Lesser General Public License
   17.18 + * along with this library; if not, write to the Free Software
   17.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   17.20 + */
   17.21 +#ifndef _XUTIL_DEBUG_H_
   17.22 +#define _XUTIL_DEBUG_H_
   17.23 +
   17.24 +#ifndef MODULE_NAME
   17.25 +#define MODULE_NAME ""
   17.26 +#endif
   17.27 +
   17.28 +#ifdef __KERNEL__
   17.29 +#include <linux/config.h>
   17.30 +#include <linux/kernel.h>
   17.31 +
   17.32 +#ifdef DEBUG
   17.33 +
   17.34 +#define dprintf(fmt, args...) printk(KERN_DEBUG   "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
   17.35 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
   17.36 +#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
   17.37 +#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
   17.38 +
   17.39 +#else
   17.40 +
   17.41 +#define dprintf(fmt, args...) do {} while(0)
   17.42 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args)
   17.43 +#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME fmt, ##args)
   17.44 +#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME fmt, ##args)
   17.45 +
   17.46 +#endif
   17.47 +
   17.48 +#else
   17.49 +
   17.50 +#include <stdio.h>
   17.51 +
   17.52 +#ifdef DEBUG
   17.53 +
   17.54 +#define dprintf(fmt, args...) fprintf(stdout, "%d [DBG] " MODULE_NAME ">%s" fmt, getpid(), __FUNCTION__, ##args)
   17.55 +#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args)
   17.56 +#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args)
   17.57 +#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args)
   17.58 +
   17.59 +#else
   17.60 +
   17.61 +#define dprintf(fmt, args...) do {} while(0)
   17.62 +#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME fmt, getpid(), ##args)
   17.63 +#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME fmt, getpid(), ##args)
   17.64 +#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME fmt, getpid(), ##args)
   17.65 +
   17.66 +#endif
   17.67 +
   17.68 +#endif
   17.69 +
   17.70 +/** Print format for an IP address.
   17.71 + * See NIPQUAD(), HIPQUAD()
   17.72 + */
   17.73 +#define IPFMT "%u.%u.%u.%u"
   17.74 +
   17.75 +#endif /* ! _XUTIL_DEBUG_H_ */
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/libxutil/enum.c	Wed Nov 24 12:07:16 2004 +0000
    18.3 @@ -0,0 +1,61 @@
    18.4 +/*
    18.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
    18.6 + *
    18.7 + * This library is free software; you can redistribute it and/or modify
    18.8 + * it under the terms of the GNU Lesser General Public License as
    18.9 + * published by the Free Software Foundation; either version 2.1 of the
   18.10 + * License, or  (at your option) any later version. This library is 
   18.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   18.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   18.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   18.14 + * See the GNU Lesser General Public License for more details.
   18.15 + *
   18.16 + * You should have received a copy of the GNU Lesser General Public License
   18.17 + * along with this library; if not, write to the Free Software Foundation,
   18.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   18.19 + */
   18.20 +
   18.21 +#ifdef __KERNEL__
   18.22 +#include <linux/errno.h>
   18.23 +#else
   18.24 +#include <errno.h>
   18.25 +#endif
   18.26 +
   18.27 +#include "sys_string.h"
   18.28 +#include "enum.h"
   18.29 +
   18.30 +/** Map an enum name to its value using a table.
   18.31 + *
   18.32 + * @param name enum name
   18.33 + * @param defs enum definitions
   18.34 + * @return enum value or -1 if not known
   18.35 + */
   18.36 +int enum_name_to_val(char *name, EnumDef *defs){
   18.37 +    int val = -1;
   18.38 +    for(; defs->name; defs++){
   18.39 +	if(!strcmp(defs->name, name)){
   18.40 +	    val = defs->val;
   18.41 +	    break;
   18.42 +	}
   18.43 +    }
   18.44 +    return val;
   18.45 +}
   18.46 +
   18.47 +/** Map an enum value to its name using a table.
   18.48 + *
   18.49 + * @param val enum value
   18.50 + * @param defs enum definitions
   18.51 + * @param defs_n number of definitions
   18.52 + * @return enum name or NULL if not known
   18.53 + */
   18.54 +char *enum_val_to_name(int val, EnumDef *defs){
   18.55 +    char *name = NULL;
   18.56 +    for(; defs->name; defs++){
   18.57 +	if(val == defs->val){
   18.58 +	    name = defs->name;
   18.59 +	    break;
   18.60 +	}
   18.61 +    }
   18.62 +    return name;
   18.63 +}
   18.64 +
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/libxutil/enum.h	Wed Nov 24 12:07:16 2004 +0000
    19.3 @@ -0,0 +1,30 @@
    19.4 +/*
    19.5 + * Copyright (C) 2002, 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 +#ifndef _XUTIL_ENUM_H_
   19.22 +#define _XUTIL_ENUM_H_
   19.23 +
   19.24 +/** Mapping of an enum value to a name. */
   19.25 +typedef struct EnumDef {
   19.26 +    int val;
   19.27 +    char *name;
   19.28 +} EnumDef;
   19.29 +
   19.30 +extern int enum_name_to_val(char *name, EnumDef *defs);
   19.31 +extern char *enum_val_to_name(int val, EnumDef *defs);
   19.32 +
   19.33 +#endif /* _XUTIL_ENUM_H_ */
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/libxutil/hash_table.c	Wed Nov 24 12:07:16 2004 +0000
    20.3 @@ -0,0 +1,640 @@
    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 published by
    20.9 + * the Free Software Foundation; either version 2.1 of the License, or
   20.10 + * (at your option) any later version.
   20.11 + *
   20.12 + * This library is distributed in the hope that it will be useful,
   20.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   20.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20.15 + * GNU Lesser General Public License for more details.
   20.16 + *
   20.17 + * You should have received a copy of the GNU Lesser General Public License
   20.18 + * along with this library; if not, write to the Free Software
   20.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   20.20 + */
   20.21 +
   20.22 +#ifdef __KERNEL__
   20.23 +#  include <linux/config.h>
   20.24 +#  include <linux/module.h>
   20.25 +#  include <linux/kernel.h>
   20.26 +#  include <linux/errno.h>
   20.27 +#else
   20.28 +#  include <errno.h>
   20.29 +#  include <stddef.h>
   20.30 +#endif
   20.31 +
   20.32 +//#include <limits.h>
   20.33 +
   20.34 +#include "allocate.h"
   20.35 +#include "hash_table.h"
   20.36 +
   20.37 +/** @file
   20.38 + * Base support for hashtables.
   20.39 + *
   20.40 + * Hash codes are reduced modulo the number of buckets to index tables,
   20.41 + * so there is no need for hash functions to limit the range of hashcodes.
   20.42 + * In fact it is assumed that hashcodes do not change when the number of
   20.43 + * buckets in the table changes.
   20.44 + */
   20.45 +
   20.46 +/*==========================================================================*/
   20.47 +/** Number of bits in half a word. */
   20.48 +//#if __WORDSIZE == 64
   20.49 +//#define HALF_WORD_BITS 32
   20.50 +//#else
   20.51 +#define HALF_WORD_BITS 16
   20.52 +//#endif
   20.53 +
   20.54 +/** Mask for lo half of a word. On 32-bit this is 
   20.55 + * (1<<16) - 1 = 65535 = 0xffff
   20.56 + * It's 4294967295 = 0xffffffff on 64-bit.
   20.57 + */
   20.58 +#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1)
   20.59 +
   20.60 +/** Get the lo half of a word. */
   20.61 +#define LO_HALF(x) ((x) & LO_HALF_MASK)
   20.62 +
   20.63 +/** Get the hi half of a word. */
   20.64 +#define HI_HALF(x) ((x) >> HALF_WORD_BITS)
   20.65 +
   20.66 +/** Do a full hash on both inputs, using DES-style non-linear scrambling.
   20.67 + * Both inputs are replaced with the results of the hash.
   20.68 + *
   20.69 + * @param pleft input/output word
   20.70 + * @param pright input/output word
   20.71 + */
   20.72 +void pseudo_des(unsigned long *pleft, unsigned long *pright){
   20.73 +    // Bit-rich mixing constant.
   20.74 +    static const unsigned long a_mixer[] = {
   20.75 +        0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, };
   20.76 +
   20.77 +    // Bit-rich mixing constant.
   20.78 +    static const unsigned long b_mixer[] = {
   20.79 +        0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, };
   20.80 +
   20.81 +    // Number of iterations - must be 2 or 4.
   20.82 +    static const int ncycle = 4;
   20.83 +    //static const int ncycle = 2;
   20.84 +
   20.85 +    unsigned long left = *pleft, right = *pright;
   20.86 +    unsigned long v, v_hi, v_lo;
   20.87 +    int i;
   20.88 +
   20.89 +    for(i=0; i<ncycle; i++){
   20.90 +        // Flip some bits in right to get v.
   20.91 +        v = right;
   20.92 +        v ^= a_mixer[i];
   20.93 +        // Get lo and hi halves of v.
   20.94 +        v_lo = LO_HALF(v);
   20.95 +        v_hi = HI_HALF(v);
   20.96 +        // Non-linear mix of the halves of v.
   20.97 +        v = ((v_lo * v_lo) + ~(v_hi * v_hi));
   20.98 +        // Swap the halves of v.
   20.99 +        v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS));
  20.100 +        // Flip some bits.
  20.101 +        v ^= b_mixer[i];
  20.102 +        // More non-linear mixing.
  20.103 +        v += (v_lo * v_hi);
  20.104 +        v ^= left;
  20.105 +        left = right;
  20.106 +        right = v;
  20.107 +    }
  20.108 +    *pleft = left;
  20.109 +    *pright = right;
  20.110 +}
  20.111 +
  20.112 +/** Hash a string.
  20.113 + *
  20.114 + * @param s input to hash
  20.115 + * @return hashcode
  20.116 + */
  20.117 +Hashcode hash_string(char *s){
  20.118 +    Hashcode h = 0;
  20.119 +    if(s){
  20.120 +        for( ; *s; s++){
  20.121 +            h = hash_2ul(h, *s);
  20.122 +        }
  20.123 +    }
  20.124 +    return h;
  20.125 +}
  20.126 +
  20.127 +/** Get the bucket for a hashcode in a hash table.
  20.128 + *
  20.129 + * @param table to get bucket from
  20.130 + * @param hashcode to get bucket for
  20.131 + * @return bucket
  20.132 + */
  20.133 +inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){
  20.134 +    return table->buckets + (hashcode % table->buckets_n);
  20.135 +}
  20.136 +
  20.137 +/** Initialize a hash table.
  20.138 + * Can be safely called more than once.
  20.139 + *
  20.140 + * @param table to initialize
  20.141 + */
  20.142 +void HashTable_init(HashTable *table){
  20.143 +    int i;
  20.144 +
  20.145 +    if(!table->init_done){
  20.146 +        table->init_done = 1;
  20.147 +        table->next_id = 0;
  20.148 +        for(i=0; i<table->buckets_n; i++){
  20.149 +            HTBucket *bucket = get_bucket(table, i);
  20.150 +            bucket->head = 0;
  20.151 +            bucket->count = 0;
  20.152 +        }
  20.153 +        table->entry_count = 0;
  20.154 +    }
  20.155 +}
  20.156 +
  20.157 +/** Allocate a new hashtable.
  20.158 + * If the number of buckets is not positive the default is used.
  20.159 + * The number of buckets should usually be prime.
  20.160 + *
  20.161 + * @param buckets_n number of buckets
  20.162 + * @return new hashtable or null
  20.163 + */
  20.164 +HashTable *HashTable_new(int buckets_n){
  20.165 +    HashTable *z = ALLOCATE(HashTable);
  20.166 +    if(!z) goto exit;
  20.167 +    if(buckets_n <= 0){
  20.168 +        buckets_n = HT_BUCKETS_N;
  20.169 +    }
  20.170 +    z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
  20.171 +    if(!z->buckets){
  20.172 +        deallocate(z);
  20.173 +        z = 0;
  20.174 +        goto exit;
  20.175 +    }
  20.176 +    z->buckets_n = buckets_n;
  20.177 +    HashTable_init(z);
  20.178 +  exit:
  20.179 +    return z;
  20.180 +}
  20.181 +
  20.182 +/** Free a hashtable.
  20.183 + * Any entries are removed and freed.
  20.184 + *
  20.185 + * @param h hashtable (ignored if null)
  20.186 + */
  20.187 +void HashTable_free(HashTable *h){
  20.188 +    if(h){
  20.189 +        HashTable_clear(h);
  20.190 +        deallocate(h->buckets);
  20.191 +        deallocate(h);
  20.192 +    }
  20.193 +}
  20.194 +
  20.195 +/** Push an entry on the list in the bucket for a given hashcode.
  20.196 + *
  20.197 + * @param table to add entry to
  20.198 + * @param hashcode for the entry
  20.199 + * @param entry to add
  20.200 + */
  20.201 +static inline void push_on_bucket(HashTable *table, Hashcode hashcode,
  20.202 +				  HTEntry *entry){
  20.203 +    HTBucket *bucket;
  20.204 +    HTEntry *old_head;
  20.205 +
  20.206 +    bucket = get_bucket(table, hashcode);
  20.207 +    old_head = bucket->head;
  20.208 +    bucket->count++;
  20.209 +    bucket->head = entry;
  20.210 +    entry->next = old_head;
  20.211 +}
  20.212 +
  20.213 +/** Change the number of buckets in a hashtable.
  20.214 + * No-op if the number of buckets is not positive.
  20.215 + * Existing entries are reallocated to buckets based on their hashcodes.
  20.216 + * The table is unmodified if the number of buckets cannot be changed.
  20.217 + *
  20.218 + * @param table hashtable
  20.219 + * @param buckets_n new number of buckets
  20.220 + * @return 0 on success, error code otherwise
  20.221 + */
  20.222 +int HashTable_set_buckets_n(HashTable *table, int buckets_n){
  20.223 +    int err = 0;
  20.224 +    HTBucket *old_buckets = table->buckets;
  20.225 +    int old_buckets_n = table->buckets_n;
  20.226 +    int i;
  20.227 +
  20.228 +    if(buckets_n <= 0){
  20.229 +        err = -EINVAL;
  20.230 +        goto exit;
  20.231 +    }
  20.232 +    table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
  20.233 +    if(!table->buckets){
  20.234 +        err = -ENOMEM;
  20.235 +        table->buckets = old_buckets;
  20.236 +        goto exit;
  20.237 +    }
  20.238 +    table->buckets_n = buckets_n;
  20.239 +    for(i=0; i<old_buckets_n; i++){
  20.240 +        HTBucket *bucket = old_buckets + i;
  20.241 +        HTEntry *entry, *next;
  20.242 +        for(entry = bucket->head; entry; entry = next){
  20.243 +            next = entry->next;
  20.244 +            push_on_bucket(table, entry->hashcode, entry);
  20.245 +        }
  20.246 +    }
  20.247 +    deallocate(old_buckets);
  20.248 +  exit:
  20.249 +    return err;
  20.250 +}
  20.251 +
  20.252 +/** Adjust the number of buckets so the table is neither too full nor too empty.
  20.253 + * The table is unmodified if adjusting fails.
  20.254 + *
  20.255 + * @param table hash table
  20.256 + * @param buckets_min minimum number of buckets (use default if 0 or negative)
  20.257 + * @return 0 on success, error code otherwise
  20.258 + */
  20.259 +int HashTable_adjust(HashTable *table, int buckets_min){
  20.260 +    int buckets_n = 0;
  20.261 +    int err = 0;
  20.262 +    if(buckets_min <= 0) buckets_min = HT_BUCKETS_N;
  20.263 +    if(table->entry_count >= table->buckets_n){
  20.264 +        // The table is dense - expand it.
  20.265 +        buckets_n = 2 * table->buckets_n;
  20.266 +    } else if((table->buckets_n > buckets_min) &&
  20.267 +              (4 * table->entry_count < table->buckets_n)){
  20.268 +        // The table is more than minimum size and sparse - shrink it.
  20.269 +        buckets_n = 2 * table->entry_count;
  20.270 +        if(buckets_n < buckets_min) buckets_n = buckets_min;
  20.271 +    }
  20.272 +    if(buckets_n){
  20.273 +        err = HashTable_set_buckets_n(table, buckets_n);
  20.274 +    }
  20.275 +    return err;
  20.276 +}
  20.277 +
  20.278 +/** Allocate a new entry for a given value.
  20.279 + *
  20.280 + * @param value to put in the entry
  20.281 + * @return entry, or 0 on failure
  20.282 + */
  20.283 +HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){
  20.284 +    HTEntry *z = ALLOCATE(HTEntry);
  20.285 +    if(z){
  20.286 +        z->hashcode = hashcode;
  20.287 +        z->key = key;
  20.288 +        z->value = value;
  20.289 +    }
  20.290 +    return z;
  20.291 +}
  20.292 +
  20.293 +/** Free an entry.
  20.294 + *
  20.295 + * @param z entry to free
  20.296 + */
  20.297 +inline void HTEntry_free(HTEntry *z){
  20.298 +    if(z){
  20.299 +        deallocate(z);
  20.300 +    }
  20.301 +}
  20.302 +
  20.303 +/** Free an entry in a hashtable.
  20.304 + * The table's entry_free_fn is used is defined, otherwise 
  20.305 + * the HTEntry itself is freed.
  20.306 + *
  20.307 + * @param table hashtable
  20.308 + * @param entry to free
  20.309 + */
  20.310 +inline void HashTable_free_entry(HashTable *table, HTEntry *entry){
  20.311 +    if(!entry)return;
  20.312 +    if(table && table->entry_free_fn){
  20.313 +        table->entry_free_fn(table, entry);
  20.314 +    } else {
  20.315 +        HTEntry_free(entry);
  20.316 +    }
  20.317 +}
  20.318 +
  20.319 +/** Get the first entry satisfying a test from the bucket for the
  20.320 + * given hashcode.
  20.321 + *
  20.322 + * @param table to look in
  20.323 + * @param hashcode indicates the bucket
  20.324 + * @param test_fn test to apply to elements
  20.325 + * @param arg first argument to calls to test_fn
  20.326 + * @return entry found, or 0
  20.327 + */
  20.328 +inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
  20.329 +				      TableTestFn *test_fn, TableArg arg){
  20.330 +    HTBucket *bucket;
  20.331 +    HTEntry *entry = 0;
  20.332 +    HTEntry *next;
  20.333 +
  20.334 +    bucket = get_bucket(table, hashcode);
  20.335 +    for(entry = bucket->head; entry; entry = next){
  20.336 +        next = entry->next;
  20.337 +        if(test_fn(arg, table, entry)){
  20.338 +            break;
  20.339 +        }
  20.340 +    }
  20.341 +    return entry;
  20.342 +}
  20.343 +
  20.344 +/** Test hashtable keys for equality.
  20.345 + * Uses the table's key_equal_fn if defined, otherwise pointer equality.
  20.346 + *
  20.347 + * @param key1 key to compare
  20.348 + * @param key2 key to compare
  20.349 + * @return 1 if equal, 0 otherwise
  20.350 + */
  20.351 +inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){
  20.352 +    return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2);
  20.353 +}
  20.354 +
  20.355 +/** Compute the hashcode of a hashtable key.
  20.356 + * The table's key_hash_fn is used if defined, otherwise the address of
  20.357 + * the key is hashed.
  20.358 + *
  20.359 + * @param table hashtable
  20.360 + * @param key to hash
  20.361 + * @return hashcode
  20.362 + */
  20.363 +inline Hashcode HashTable_key_hash(HashTable *table, void *key){
  20.364 +    return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key));
  20.365 +}
  20.366 +
  20.367 +/** Test if an entry has a given key.
  20.368 + *
  20.369 + * @param arg containing key to test for
  20.370 + * @param table the entry is in
  20.371 + * @param entry to test
  20.372 + * @return 1 if the entry has the key, 0 otherwise
  20.373 + */
  20.374 +static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){
  20.375 +    return HashTable_key_equal(table, arg.ptr, entry->key);
  20.376 +}
  20.377 +
  20.378 +/** Get an entry with a given key.
  20.379 + *
  20.380 + * @param table to search
  20.381 + * @param key to look for
  20.382 + * @return entry if found, null otherwise
  20.383 + */
  20.384 +#if 0
  20.385 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
  20.386 +    TableArg arg = { ptr: key };
  20.387 +    return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg);
  20.388 +}
  20.389 +#else
  20.390 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
  20.391 +    Hashcode hashcode;
  20.392 +    HTBucket *bucket;
  20.393 +    HTEntry *entry = 0;
  20.394 +    HTEntry *next;
  20.395 +
  20.396 +    hashcode = HashTable_key_hash(table, key);
  20.397 +    bucket = get_bucket(table, hashcode);
  20.398 +    for(entry = bucket->head; entry; entry = next){
  20.399 +        next = entry->next;
  20.400 +        if(HashTable_key_equal(table, key, entry->key)){
  20.401 +            break;
  20.402 +        }
  20.403 +    }
  20.404 +    return entry;
  20.405 +}
  20.406 +#endif
  20.407 +
  20.408 +/** Get the value of an entry with a given key.
  20.409 + *
  20.410 + * @param table to search
  20.411 + * @param key to look for
  20.412 + * @return value if an entry was found, null otherwise
  20.413 + */
  20.414 +inline void * HashTable_get(HashTable *table, void *key){
  20.415 +    HTEntry *entry = HashTable_get_entry(table, key);
  20.416 +    return (entry ? entry->value : 0);
  20.417 +}
  20.418 +
  20.419 +/** Print the buckets in a table.
  20.420 + *
  20.421 + * @param table to print
  20.422 + */
  20.423 +void show_buckets(HashTable *table, IOStream *io){
  20.424 +    int i,j ;
  20.425 +    IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n);
  20.426 +    for(i=0; i<table->buckets_n; i++){
  20.427 +        if(0 || table->buckets[i].count>0){
  20.428 +            IOStream_print(io, "bucket %3d %3d %10p ", i,
  20.429 +                        table->buckets[i].count,
  20.430 +                        table->buckets[i].head);
  20.431 +            for(j = table->buckets[i].count; j>0; j--){
  20.432 +                IOStream_print(io, "+");
  20.433 +            }
  20.434 +            IOStream_print(io, "\n");
  20.435 +        }
  20.436 +    }
  20.437 +    HashTable_print(table, io); 
  20.438 +}
  20.439 +    
  20.440 +/** Print an entry in a table.
  20.441 + *
  20.442 + * @param entry to print
  20.443 + * @param arg a pointer to an IOStream to print to
  20.444 + * @return 0
  20.445 + */
  20.446 +static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){
  20.447 +    IOStream *io = (IOStream*)arg.ptr;
  20.448 +    IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n",
  20.449 +                entry->hashcode % table->buckets_n,
  20.450 +                entry->hashcode,
  20.451 +                entry->index,
  20.452 +                entry, entry->key, entry->value);
  20.453 +    return 0;
  20.454 +}
  20.455 +
  20.456 +/** Print a hash table.
  20.457 + *
  20.458 + * @param table to print
  20.459 + */
  20.460 +void HashTable_print(HashTable *table, IOStream *io){
  20.461 +    IOStream_print(io, "{\n");
  20.462 +    HashTable_map(table, print_entry, (TableArg){ ptr: io });
  20.463 +    IOStream_print(io, "}\n");
  20.464 +}
  20.465 +/*==========================================================================*/
  20.466 +
  20.467 +/** Get the next entry id to use for a table.
  20.468 + *
  20.469 + * @param table hash table
  20.470 + * @return non-zero entry id
  20.471 + */
  20.472 +static inline unsigned long get_next_id(HashTable *table){
  20.473 +    unsigned long id;
  20.474 +
  20.475 +    if(table->next_id == 0){
  20.476 +        table->next_id = 1;
  20.477 +    }
  20.478 +    id = table->next_id++;
  20.479 +    return id;
  20.480 +}
  20.481 +
  20.482 +/** Add an entry to the bucket for the
  20.483 + * given hashcode.
  20.484 + *
  20.485 + * @param table to insert in
  20.486 + * @param hashcode indicates the bucket
  20.487 + * @param key to add an entry for
  20.488 + * @param value to add an entry for
  20.489 + * @return entry on success, 0 on failure
  20.490 + */
  20.491 +inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){
  20.492 +    HTEntry *entry = HTEntry_new(hashcode, key, value);
  20.493 +    if(entry){
  20.494 +        entry->index = get_next_id(table);
  20.495 +        push_on_bucket(table, hashcode, entry);
  20.496 +        table->entry_count++;
  20.497 +    }
  20.498 +    return entry;
  20.499 +}
  20.500 +
  20.501 +/** Move the front entry for a bucket to the correct point in the bucket order as
  20.502 + * defined by the order function. If this is called every time a new entry is added
  20.503 + * the bucket will be maintained in sorted order.
  20.504 + *
  20.505 + * @param table to modify
  20.506 + * @param hashcode indicates the bucket
  20.507 + * @param order entry comparison function
  20.508 + * @return 0 if an entry was moved, 1 if not
  20.509 + */
  20.510 +int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){
  20.511 +    HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL;
  20.512 +    HTBucket *bucket;
  20.513 +    int err = 1;
  20.514 +
  20.515 +    bucket = get_bucket(table, hashcode);
  20.516 +    new_entry = bucket->head;
  20.517 +    if(!new_entry || !new_entry->next) goto exit;
  20.518 +    for(entry = new_entry->next; entry; prev = entry, entry = entry->next){
  20.519 +        if(order(new_entry, entry) <= 0) break;
  20.520 +    }
  20.521 +    if(prev){
  20.522 +        err = 0;
  20.523 +        bucket->head = new_entry->next; 
  20.524 +        new_entry->next = entry;
  20.525 +        prev->next = new_entry;
  20.526 +    }
  20.527 +  exit:
  20.528 +    return err;
  20.529 +}
  20.530 +
  20.531 +/** Add an entry to a hashtable.
  20.532 + * The entry is added to the bucket for its key's hashcode.
  20.533 + *
  20.534 + * @param table to insert in
  20.535 + * @param key to add an entry for
  20.536 + * @param value to add an entry for
  20.537 + * @return entry on success, 0 on failure
  20.538 + */
  20.539 +inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){
  20.540 +    return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value);
  20.541 +}
  20.542 +
  20.543 +
  20.544 +/** Remove entries satisfying a test from the bucket for the
  20.545 + * given hashcode. 
  20.546 + *
  20.547 + * @param table to remove from
  20.548 + * @param hashcode indicates the bucket
  20.549 + * @param test_fn test to apply to elements
  20.550 + * @param arg first argument to calls to test_fn
  20.551 + * @return number of entries removed
  20.552 + */
  20.553 +inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
  20.554 +				  TableTestFn *test_fn, TableArg arg){
  20.555 +    HTBucket *bucket;
  20.556 +    HTEntry *entry, *prev = 0, *next;
  20.557 +    int removed_count = 0;
  20.558 +
  20.559 +    bucket = get_bucket(table, hashcode);
  20.560 +    for(entry = bucket->head; entry; entry = next){
  20.561 +        next = entry->next;
  20.562 +        if(test_fn(arg, table, entry)){
  20.563 +            if(prev){
  20.564 +                prev->next = next;
  20.565 +            } else {
  20.566 +                bucket->head = next;
  20.567 +            }
  20.568 +            bucket->count--;
  20.569 +            table->entry_count--;
  20.570 +            removed_count++;
  20.571 +            HashTable_free_entry(table, entry);
  20.572 +            entry = 0;
  20.573 +        }
  20.574 +        prev = entry;
  20.575 +    }
  20.576 +    return removed_count;
  20.577 +}
  20.578 +
  20.579 +/** Remove entries with a given key. 
  20.580 + *
  20.581 + * @param table to remove from
  20.582 + * @param key of entries to remove
  20.583 + * @return number of entries removed
  20.584 + */
  20.585 +inline int HashTable_remove(HashTable *table, void *key){
  20.586 +#if 1
  20.587 +    Hashcode hashcode;
  20.588 +    HTBucket *bucket;
  20.589 +    HTEntry *entry, *prev = 0, *next;
  20.590 +    int removed_count = 0;
  20.591 +
  20.592 +    hashcode = HashTable_key_hash(table, key);
  20.593 +    bucket = get_bucket(table, hashcode);
  20.594 +    for(entry = bucket->head; entry; entry = next){
  20.595 +        next = entry->next;
  20.596 +        if(HashTable_key_equal(table, key, entry->key)){
  20.597 +            if(prev){
  20.598 +                prev->next = next;
  20.599 +            } else {
  20.600 +                bucket->head = next;
  20.601 +            }
  20.602 +            bucket->count--;
  20.603 +            table->entry_count--;
  20.604 +            removed_count++;
  20.605 +            HashTable_free_entry(table, entry);
  20.606 +            entry = 0;
  20.607 +        }
  20.608 +        prev = entry;
  20.609 +    }
  20.610 +    return removed_count;
  20.611 +#else
  20.612 +    return HashTable_remove_entry(table, HashTable_key_hash(table, key),
  20.613 +				  has_key, (TableArg){ ptr: key});
  20.614 +#endif
  20.615 +}
  20.616 +
  20.617 +/** Remove (and free) all the entries in a bucket.
  20.618 + *
  20.619 + * @param bucket to clear
  20.620 + */
  20.621 +static inline void bucket_clear(HashTable *table, HTBucket *bucket){
  20.622 +    HTEntry *entry, *next;
  20.623 +
  20.624 +    for(entry = bucket->head; entry; entry = next){
  20.625 +        next = entry->next;
  20.626 +        HashTable_free_entry(table, entry);
  20.627 +    }
  20.628 +    bucket->head = 0;
  20.629 +    table->entry_count -= bucket->count;
  20.630 +    bucket->count = 0;
  20.631 +}
  20.632 +
  20.633 +/** Remove (and free) all the entries in a table.
  20.634 + *
  20.635 + * @param table to clear
  20.636 + */
  20.637 +void HashTable_clear(HashTable *table){
  20.638 +    int i, n = table->buckets_n;
  20.639 +
  20.640 +    for(i=0; i<n; i++){
  20.641 +        bucket_clear(table, table->buckets + i);
  20.642 +    }
  20.643 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/libxutil/hash_table.h	Wed Nov 24 12:07:16 2004 +0000
    21.3 @@ -0,0 +1,294 @@
    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 published by
    21.9 + * the Free Software Foundation; either version 2.1 of the License, or
   21.10 + * (at your option) any later version.
   21.11 + *
   21.12 + * This library is distributed in the hope that it will be useful,
   21.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.15 + * GNU Lesser General Public License for more details.
   21.16 + *
   21.17 + * You should have received a copy of the GNU Lesser General Public License
   21.18 + * along with this library; if not, write to the Free Software
   21.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21.20 + */
   21.21 +
   21.22 +#ifndef _XUTIL_HASH_TABLE_H_
   21.23 +#define _XUTIL_HASH_TABLE_H_
   21.24 +
   21.25 +#include "iostream.h"
   21.26 +
   21.27 +typedef unsigned long Hashcode;
   21.28 +
   21.29 +/** Type used to pass parameters to table functions. */
   21.30 +typedef union TableArg {
   21.31 +    unsigned long ul;
   21.32 +    void *ptr;
   21.33 +} TableArg;
   21.34 +
   21.35 +/** An entry in a bucket list. */
   21.36 +typedef struct HTEntry {
   21.37 +    /** Hashcode of the entry's key. */
   21.38 +    Hashcode hashcode;
   21.39 +    /** Identifier for this entry in the table. */
   21.40 +    int index;
   21.41 +    /** The key for this entry. */
   21.42 +    void *key;
   21.43 +    /** The value in this entry. */
   21.44 +    void *value;
   21.45 +    /** The next entry in the list. */
   21.46 +    struct HTEntry *next;
   21.47 +} HTEntry;
   21.48 +
   21.49 +/** A bucket in a rule table. */
   21.50 +typedef struct HTBucket {
   21.51 +    /** Number of entries in the bucket. */
   21.52 +    int count;
   21.53 +    /** First entry in the bucket (may be null). */
   21.54 +    HTEntry *head;
   21.55 +} HTBucket;
   21.56 +
   21.57 +/** Default number of buckets in a hash table.
   21.58 + * You want enough buckets so the lists in the buckets will typically be short.
   21.59 + * It's a good idea if this is prime, since that will help to spread hashcodes
   21.60 + * around the table.
   21.61 + */
   21.62 +//#define HT_BUCKETS_N 1
   21.63 +//#define HT_BUCKETS_N 3
   21.64 +//#define HT_BUCKETS_N 7
   21.65 +//#define HT_BUCKETS_N 17
   21.66 +//#define HT_BUCKETS_N 97
   21.67 +//#define HT_BUCKETS_N 211
   21.68 +//#define HT_BUCKETS_N 401
   21.69 +#define HT_BUCKETS_N 1021
   21.70 +
   21.71 +typedef struct HashTable HashTable;
   21.72 +
   21.73 +/** Type for a function used to select table entries. */
   21.74 +typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry);
   21.75 +
   21.76 +/** Type for a function to map over table entries. */
   21.77 +typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry);
   21.78 +
   21.79 +/** Type for a function to free table entries. */
   21.80 +typedef void TableFreeFn(HashTable *table, HTEntry *entry);
   21.81 +
   21.82 +/** Type for a function to hash table keys. */
   21.83 +typedef Hashcode TableHashFn(void *key);
   21.84 +
   21.85 +/** Type for a function to test table keys for equality. */
   21.86 +typedef int TableEqualFn(void *key1, void *key2);
   21.87 +
   21.88 +/** Type for a function to order table entries. */
   21.89 +typedef int TableOrderFn(HTEntry *e1, HTEntry *e2);
   21.90 +
   21.91 +/** General hash table.
   21.92 + * A hash table with a list in each bucket.
   21.93 + * Functions can be supplied for freeing entries, hashing keys, and comparing keys.
   21.94 + * These all default to 0, when default behaviour treating keys as integers is used.
   21.95 + */
   21.96 +struct HashTable {
   21.97 +    /** Flag indicating whether the table has been initialised. */
   21.98 +    int init_done;
   21.99 +    /** Next value for the id field in inserted rules. */
  21.100 +    unsigned long next_id;
  21.101 +    /** Number of buckets in the bucket array. */
  21.102 +    int buckets_n;
  21.103 +    /** Array of buckets, each with its own list. */
  21.104 +    HTBucket *buckets;
  21.105 +    /** Number of entries in the table. */
  21.106 +    int entry_count;
  21.107 +    /** Function to free keys and values in entries. */
  21.108 +    TableFreeFn *entry_free_fn;
  21.109 +    /** Function to hash keys. */
  21.110 +    TableHashFn *key_hash_fn;
  21.111 +    /** Function to compare keys for equality. */
  21.112 +    TableEqualFn *key_equal_fn;
  21.113 +    /** Place for the user of the table to hang extra data. */
  21.114 +    void *user_data;
  21.115 +};
  21.116 +
  21.117 +extern HashTable *HashTable_new(int bucket_n);
  21.118 +extern void HashTable_free(HashTable *table);
  21.119 +extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value);
  21.120 +extern void HTEntry_free(HTEntry *entry);
  21.121 +extern int HashTable_set_bucket_n(HashTable *table, int bucket_n);
  21.122 +extern void HashTable_clear(HashTable *table);
  21.123 +extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value);
  21.124 +extern HTEntry * HashTable_get_entry(HashTable *table, void *key);
  21.125 +extern HTEntry * HashTable_add(HashTable *table, void *key, void *value);
  21.126 +extern void * HashTable_get(HashTable *table, void *key);
  21.127 +extern int HashTable_remove(HashTable *table, void *key);
  21.128 +extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
  21.129 +                                      TableTestFn *test_fn, TableArg arg);
  21.130 +extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
  21.131 +                                   TableTestFn *test_fn, TableArg arg);
  21.132 +//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg);
  21.133 +extern void HashTable_print(HashTable *table, IOStream *out);
  21.134 +extern int HashTable_set_buckets_n(HashTable *table, int buckets_n);
  21.135 +extern int HashTable_adjust(HashTable *table, int buckets_min);
  21.136 +extern void pseudo_des(unsigned long *pleft, unsigned long *pright);
  21.137 +extern Hashcode hash_string(char *s);
  21.138 +
  21.139 +extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order);
  21.140 +
  21.141 +/** Control whether to use hashing based on DES or simple
  21.142 + * hashing. DES hashing is `more random' but much more expensive.
  21.143 + */
  21.144 +#define HASH_PSEUDO_DES 0
  21.145 +
  21.146 +/** Hash a long using a quick and dirty linear congruential random number generator.
  21.147 + *  See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator".
  21.148 + *
  21.149 + * @param a value to hash
  21.150 + * @return hashed input
  21.151 + */
  21.152 +static inline unsigned long lcrng_hash(unsigned long a){
  21.153 +    return (1664525L * a + 1013904223L);
  21.154 +}
  21.155 +
  21.156 +/** Hash an unsigned long.
  21.157 + *
  21.158 + * @param a input to hash
  21.159 + * @return hashcode
  21.160 + */
  21.161 +static inline Hashcode hash_ul(unsigned long a){
  21.162 +#if HASH_PSEUDO_DES
  21.163 +    unsigned long left = a;
  21.164 +    unsigned long right = 0L;
  21.165 +    pseudo_des(&left, &right);
  21.166 +    return right;
  21.167 +#else
  21.168 +    a = lcrng_hash(a);
  21.169 +    a = lcrng_hash(a);
  21.170 +    return a;
  21.171 +#endif
  21.172 +}
  21.173 +
  21.174 +/** Hash two unsigned longs together.
  21.175 + *
  21.176 + * @param a input to hash
  21.177 + * @param b input to hash
  21.178 + * @return hashcode
  21.179 + */
  21.180 +static inline Hashcode hash_2ul(unsigned long a, unsigned long b){
  21.181 +#if HASH_PSEUDO_DES
  21.182 +    unsigned long left = a;
  21.183 +    unsigned long right = b;
  21.184 +    pseudo_des(&left, &right);
  21.185 +    return right;
  21.186 +#else
  21.187 +    a = lcrng_hash(a);
  21.188 +    a ^= b;
  21.189 +    a = lcrng_hash(a);
  21.190 +    return a;
  21.191 +#endif
  21.192 +}
  21.193 +
  21.194 +/** Hash a hashcode and an unsigned long together.
  21.195 + *
  21.196 + * @param a input hashcode
  21.197 + * @param b input to hash
  21.198 + * @return hashcode
  21.199 + */
  21.200 +static inline Hashcode hash_hul(Hashcode a, unsigned long b){
  21.201 +#if HASH_PSEUDO_DES
  21.202 +    unsigned long left = a;
  21.203 +    unsigned long right = b;
  21.204 +    pseudo_des(&left, &right);
  21.205 +    return right;
  21.206 +#else
  21.207 +    a ^= b;
  21.208 +    a = lcrng_hash(a);
  21.209 +    return a;
  21.210 +#endif
  21.211 +}
  21.212 +
  21.213 +/** Macro to declare variables for HashTable_for_each() to use.
  21.214 + *
  21.215 + * @param entry variable that is set to entries in the table
  21.216 + */
  21.217 +#define HashTable_for_decl(entry) \
  21.218 +  HashTable *_var_table; \
  21.219 +  HTBucket *_var_bucket; \
  21.220 +  HTBucket *_var_end; \
  21.221 +  HTEntry *_var_next; \
  21.222 +  HTEntry *entry
  21.223 +
  21.224 +/** Macro to iterate over the entries in a hashtable.
  21.225 + * Must be in a scope where HashTable_for_decl() has been used to declare
  21.226 + * variables for it to use.
  21.227 + * The variable 'entry' is iterated over entries in the table.
  21.228 + * The code produced is syntactically a loop, so it must be followed by
  21.229 + * a loop body, typically some statements in braces:
  21.230 + * HashTable_for_each(entry, table){ ...loop body... }
  21.231 + *
  21.232 + * HashTable_for_each() and HashTable_for_decl() cannot be used for nested
  21.233 + * loops as variables will clash.
  21.234 + *
  21.235 + * @note The simplest way to code a direct loop over the entries in a hashtable
  21.236 + * is to use a loop over the buckets, with a nested loop over the entries
  21.237 + * in a bucket. Using this approach in a macro means the macro contains
  21.238 + * an opening brace, and calls to it must be followed by 2 braces!
  21.239 + * To avoid this the code has been restructured so that it is a for loop.
  21.240 + * So that statements could be used in the test expression of the for loop,
  21.241 + * we have used the gcc statement expression extension ({ ... }).
  21.242 + *
  21.243 + * @param entry variable to iterate over the entries
  21.244 + * @param table to iterate over (non-null)
  21.245 + */
  21.246 +#define HashTable_for_each(entry, table) \
  21.247 +  _var_table = table; \
  21.248 +  _var_bucket = _var_table->buckets; \
  21.249 +  _var_end = _var_bucket + _var_table->buckets_n; \
  21.250 +  for(entry=0, _var_next=0; \
  21.251 +      ({ if(_var_next){ \
  21.252 +             entry = _var_next; \
  21.253 +             _var_next = entry->next; \
  21.254 +          } else { \
  21.255 +             while(_var_bucket < _var_end){ \
  21.256 +                 entry = _var_bucket->head; \
  21.257 +                 _var_bucket++; \
  21.258 +                 if(entry){ \
  21.259 +                      _var_next = entry->next; \
  21.260 +                      break; \
  21.261 +                 } \
  21.262 +             } \
  21.263 +          }; \
  21.264 +         entry; }); \
  21.265 +      entry = _var_next )
  21.266 +
  21.267 +/** Map a function over the entries in a table.
  21.268 + * Mapping stops when the function returns a non-zero value.
  21.269 + * Uses the gcc statement expression extension ({ ... }).
  21.270 + *
  21.271 + * @param table to map over
  21.272 + * @param fn function to apply to entries
  21.273 + * @param arg first argument to call the function with
  21.274 + * @return 0 if fn always returned 0, first non-zero value otherwise
  21.275 + */
  21.276 +#define HashTable_map(table, fn, arg) \
  21.277 +  ({ HashTable_for_decl(_var_entry); \
  21.278 +    TableArg _var_arg = arg; \
  21.279 +    int _var_value = 0; \
  21.280 +    HashTable_for_each(_var_entry, table){ \
  21.281 +        if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \
  21.282 +    } \
  21.283 +    _var_value; })
  21.284 +
  21.285 +/** Cast x to the type for a key or value in a hash table.
  21.286 + * This avoids compiler warnings when using short integers
  21.287 + * as keys or values (especially on 64-bit platforms).
  21.288 + */
  21.289 +#define HKEY(x) ((void*)(unsigned long)(x))
  21.290 +
  21.291 +/** Cast x from the type for a key or value in a hash table.
  21.292 + * to an unsigned long. This avoids compiler warnings when using
  21.293 + * short integers as keys or values (especially on 64-bit platforms).
  21.294 + */
  21.295 +#define HVAL(x) ((unsigned long)(x))
  21.296 +
  21.297 +#endif /* !_XUTIL_HASH_TABLE_H_ */
    22.1 --- a/tools/libxutil/iostream.c	Wed Nov 24 11:51:49 2004 +0000
    22.2 +++ b/tools/libxutil/iostream.c	Wed Nov 24 12:07:16 2004 +0000
    22.3 @@ -1,3 +1,21 @@
    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 published by
    22.9 + * the Free Software Foundation; either version 2.1 of the License, or
   22.10 + * (at your option) any later version.
   22.11 + *
   22.12 + * This library is distributed in the hope that it will be useful,
   22.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.15 + * GNU Lesser General Public License for more details.
   22.16 + *
   22.17 + * You should have received a copy of the GNU Lesser General Public License
   22.18 + * along with this library; if not, write to the Free Software
   22.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22.20 + */
   22.21 +
   22.22  #include "iostream.h"
   22.23  #include "sys_string.h"
   22.24  
    23.1 --- a/tools/libxutil/iostream.h	Wed Nov 24 11:51:49 2004 +0000
    23.2 +++ b/tools/libxutil/iostream.h	Wed Nov 24 12:07:16 2004 +0000
    23.3 @@ -1,14 +1,34 @@
    23.4 -#ifndef _XC_LINUX_SAVE_H_
    23.5 -#define _XC_LINUX_SAVE_H_
    23.6 +/*
    23.7 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    23.8 + *
    23.9 + * This library is free software; you can redistribute it and/or modify
   23.10 + * it under the terms of the GNU Lesser General Public License as published by
   23.11 + * the Free Software Foundation; either version 2.1 of the License, or
   23.12 + * (at your option) any later version.
   23.13 + *
   23.14 + * This library is distributed in the hope that it will be useful,
   23.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.17 + * GNU Lesser General Public License for more details.
   23.18 + *
   23.19 + * You should have received a copy of the GNU Lesser General Public License
   23.20 + * along with this library; if not, write to the Free Software
   23.21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   23.22 + */
   23.23 +
   23.24 +#ifndef _XUTIL_IOSTREAM_H_
   23.25 +#define _XUTIL_IOSTREAM_H_
   23.26  
   23.27  #include <stdarg.h>
   23.28 -#include <stdint.h>
   23.29 -#include <stddef.h>
   23.30  
   23.31  #ifdef __KERNEL__
   23.32 +#include <linux/config.h>
   23.33 +#include <linux/types.h>
   23.34  #include <linux/errno.h>
   23.35  #else
   23.36  #include <errno.h>
   23.37 +#include <stdint.h>
   23.38 +#include <stddef.h>
   23.39  #endif
   23.40  
   23.41  #include "allocate.h"
   23.42 @@ -240,4 +260,4 @@ static inline int IOStream_get_written(I
   23.43  }
   23.44  
   23.45  
   23.46 -#endif /* ! _XC_LINUX_SAVE_H_ */
   23.47 +#endif /* ! _XUTIL_IOSTREAM_H_ */
    24.1 --- a/tools/libxutil/kernel_stream.c	Wed Nov 24 11:51:49 2004 +0000
    24.2 +++ b/tools/libxutil/kernel_stream.c	Wed Nov 24 12:07:16 2004 +0000
    24.3 @@ -50,7 +50,7 @@ typedef struct KernelData {
    24.4      char buf[BUF_N];
    24.5  } KernelData;
    24.6  
    24.7 -static int kernel_write(IOStream *s, const char *msg, int n);
    24.8 +static int kernel_write(IOStream *s, const void *msg, size_t n);
    24.9  static void kernel_free(IOStream *s);
   24.10  static void kernel_stream_lock(IOStream *s);
   24.11  static void kernel_stream_unlock(IOStream *s);
   24.12 @@ -145,13 +145,13 @@ void kernel_stream_unlock(IOStream *s){
   24.13   * @param args print arguments
   24.14   * @return result of the print
   24.15   */
   24.16 -static int kernel_write(IOStream *stream, const char *buf, int n){
   24.17 +static int kernel_write(IOStream *stream, const void *buf, size_t n){
   24.18    KernelData *kdata = get_kernel_data(stream);
   24.19    int k;
   24.20    k = kdata->buf_n - 1;
   24.21    if(n < k) k = n;
   24.22    memcpy(kdata->buf, buf, k);
   24.23 -  kdata->buf[k] = '\0'
   24.24 +  kdata->buf[k] = '\0';
   24.25    printk(kdata->buf);
   24.26    return k;
   24.27  }
   24.28 @@ -167,7 +167,7 @@ static void kernel_free(IOStream *io){
   24.29    KernelData *kdata;
   24.30    if(io == &iokernel) return;
   24.31    kdata = get_kernel_data(io);
   24.32 -  zero(kdata, sizeof(*kdata));
   24.33 +  memset(kdata, 0, sizeof(*kdata));
   24.34    deallocate(kdata);
   24.35  }
   24.36  #endif /* __KERNEL__ */
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/tools/libxutil/lexis.c	Wed Nov 24 12:07:16 2004 +0000
    25.3 @@ -0,0 +1,94 @@
    25.4 +/*
    25.5 + * Copyright (C) 2001 - 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 +/** @file
   25.22 + * Lexical analysis.
   25.23 + */
   25.24 +
   25.25 +#include "sys_string.h"
   25.26 +#include "lexis.h"
   25.27 +#include <errno.h>
   25.28 +
   25.29 +/** Check if a value lies in a (closed) range.
   25.30 + *
   25.31 + * @param x value to test
   25.32 + * @param lo low end of the range
   25.33 + * @param hi high end of the range
   25.34 + * @return 1 if x is in the interval [lo, hi], 0 otherwise
   25.35 + */
   25.36 +inline static int in_range(int x, int lo, int hi){
   25.37 +    return (lo <= x) && (x <= hi);
   25.38 +}
   25.39 +
   25.40 +/** Determine if a string is an (unsigned) decimal number.
   25.41 + * 
   25.42 + * @param s pointer to characters to test
   25.43 + * @param n length of string
   25.44 + * @return 1 if s is a decimal number, 0 otherwise.
   25.45 + */
   25.46 +int is_decimal_number(const char *s, int n){
   25.47 +    int i;
   25.48 +    if(n <= 0)return 0;
   25.49 +    for(i = 0; i < n; i++){
   25.50 +        if(!in_decimal_digit_class(s[i])) return 0;
   25.51 +    }
   25.52 +    return 1;
   25.53 +}
   25.54 +
   25.55 +/** Determine if a string is a hex number.
   25.56 + * Hex numbers are 0, or start with 0x or 0X followed
   25.57 + * by a non-zero number of hex digits (0-9,a-f,A-F).
   25.58 + * 
   25.59 + * @param s pointer to characters to test
   25.60 + * @param n length of string
   25.61 + * @return 1 if s is a hex number, 0 otherwise.
   25.62 + */
   25.63 +int is_hex_number(const char *s, int n){
   25.64 +    int i;
   25.65 +    if(n <= 0) return 0;
   25.66 +    if(n == 1){
   25.67 +        return s[0]=='0';
   25.68 +    }
   25.69 +    if(n <= 3) return 0;
   25.70 +    if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0;
   25.71 +    for(i = 2; i < n; i++){
   25.72 +        if(!in_hex_digit_class(s[i])) return 0;
   25.73 +    }
   25.74 +    return 1;
   25.75 +}
   25.76 +
   25.77 +/** Test if a string matches a keyword.
   25.78 + * The comparison is case-insensitive.
   25.79 + * The comparison fails if either argument is null.
   25.80 + *
   25.81 + * @param s string
   25.82 + * @param k keyword
   25.83 + * @return 1 if they match, 0 otherwise
   25.84 + */
   25.85 +int is_keyword(const char *s, const char *k){
   25.86 +  return s && k && !strcasecmp(s, k);
   25.87 +}
   25.88 +
   25.89 +/** Test if a string matches a character.
   25.90 + *
   25.91 + * @param s string
   25.92 + * @param c character (non-null)
   25.93 + * @return 1 if s contains exactly c, 0 otherwise
   25.94 + */
   25.95 +int is_keychar(const char *s, char c){
   25.96 +  return c && (s[0] == c) && !s[1];
   25.97 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/tools/libxutil/lexis.h	Wed Nov 24 12:07:16 2004 +0000
    26.3 @@ -0,0 +1,128 @@
    26.4 +/*
    26.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    26.6 + *
    26.7 + * This library is free software; you can redistribute it and/or modify
    26.8 + * it under the terms of the GNU Lesser General Public License as
    26.9 + * published by the Free Software Foundation; either version 2.1 of the
   26.10 + * License, or  (at your option) any later version. This library is 
   26.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   26.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   26.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   26.14 + * See the GNU Lesser General Public License for more details.
   26.15 + *
   26.16 + * You should have received a copy of the GNU Lesser General Public License
   26.17 + * along with this library; if not, write to the Free Software Foundation,
   26.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   26.19 + */
   26.20 +
   26.21 +#ifndef _XUTIL_LEXIS_H_
   26.22 +#define _XUTIL_LEXIS_H_
   26.23 +
   26.24 +#include "sys_string.h"
   26.25 +
   26.26 +#ifdef __KERNEL__
   26.27 +#  include <linux/ctype.h>
   26.28 +#else
   26.29 +#  include <ctype.h>
   26.30 +#endif
   26.31 +
   26.32 +/** @file
   26.33 + * Lexical analysis.
   26.34 + */
   26.35 +
   26.36 +/** Class of characters treated as space. */
   26.37 +#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 })
   26.38 +
   26.39 +/** Class of separator characters. */
   26.40 +#define sep_class "{}()<>[]@!;"
   26.41 +
   26.42 +#define comment_class "#"
   26.43 +
   26.44 +/** Determine if a character is in a given class.
   26.45 + * 
   26.46 + * @param c character to test
   26.47 + * @param s null-terminated string of characters in the class
   26.48 + * @return 1 if c is in the class, 0 otherwise.
   26.49 + */
   26.50 +static inline int in_class(int c, const char *s){
   26.51 +  return s && (strchr(s, c) != 0);
   26.52 +}
   26.53 +
   26.54 +/** Determine if a character is in the space class.
   26.55 + * 
   26.56 + * @param c character to test
   26.57 + * @return 1 if c is in the class, 0 otherwise.
   26.58 + */
   26.59 +static inline int in_space_class(int c){
   26.60 +    return in_class(c, space_class);
   26.61 +}
   26.62 +
   26.63 +static inline int in_comment_class(int c){
   26.64 +    return in_class(c, comment_class);
   26.65 +}
   26.66 +
   26.67 +/** Determine if a character is in the separator class.
   26.68 + * Separator characters terminate tokens, and do not need space
   26.69 + * to separate them.
   26.70 + * 
   26.71 + * @param c character to test
   26.72 + * @return 1 if c is in the class, 0 otherwise.
   26.73 + */
   26.74 +static inline int in_sep_class(int c){
   26.75 +    return in_class(c, sep_class);
   26.76 +}
   26.77 +
   26.78 +/** Determine if a character is in the alpha class.
   26.79 + * 
   26.80 + * @param c character to test
   26.81 + * @return 1 if c is in the class, 0 otherwise.
   26.82 + */
   26.83 +static inline int in_alpha_class(int c){
   26.84 +    return isalpha(c);
   26.85 +}
   26.86 +
   26.87 +/** Determine if a character is in the octal digit class.
   26.88 + * 
   26.89 + * @param c character to test
   26.90 + * @return 1 if c is in the class, 0 otherwise.
   26.91 + */
   26.92 +static inline int in_octal_digit_class(int c){
   26.93 +    return '0' <= c && c <= '7';
   26.94 +}
   26.95 +
   26.96 +/** Determine if a character is in the decimal digit class.
   26.97 + * 
   26.98 + * @param c character to test
   26.99 + * @return 1 if c is in the class, 0 otherwise.
  26.100 + */
  26.101 +static inline int in_decimal_digit_class(int c){
  26.102 +    return isdigit(c);
  26.103 +}
  26.104 +
  26.105 +/** Determine if a character is in the hex digit class.
  26.106 + * 
  26.107 + * @param c character to test
  26.108 + * @return 1 if c is in the class, 0 otherwise.
  26.109 + */
  26.110 +static inline int in_hex_digit_class(int c){
  26.111 +    return isdigit(c) || in_class(c, "abcdefABCDEF");
  26.112 +}
  26.113 +
  26.114 +
  26.115 +static inline int in_string_quote_class(int c){
  26.116 +    return in_class(c, "'\"");
  26.117 +}
  26.118 +
  26.119 +static inline int in_printable_class(int c){
  26.120 +    return ('A' <= c && c <= 'Z')
  26.121 +        || ('a' <= c && c <= 'z')
  26.122 +        || ('0' <= c && c <= '9')
  26.123 +        || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~");
  26.124 +}
  26.125 +
  26.126 +extern int is_decimal_number(const char *s, int n);
  26.127 +extern int is_hex_number(const char *s, int n);
  26.128 +extern int is_keyword(const char *s, const char *k);
  26.129 +extern int is_keychar(const char *s, char c);
  26.130 +
  26.131 +#endif /* !_XUTIL_LEXIS_H_ */
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/tools/libxutil/socket_stream.c	Wed Nov 24 12:07:16 2004 +0000
    27.3 @@ -0,0 +1,230 @@
    27.4 +/*
    27.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    27.6 + *
    27.7 + * This library is free software; you can redistribute it and/or modify
    27.8 + * it under the terms of the GNU Lesser General Public License as published by
    27.9 + * the Free Software Foundation; either version 2.1 of the License, or
   27.10 + * (at your option) any later version.
   27.11 + *
   27.12 + * This library is distributed in the hope that it will be useful,
   27.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.15 + * GNU Lesser General Public License for more details.
   27.16 + *
   27.17 + * You should have received a copy of the GNU Lesser General Public License
   27.18 + * along with this library; if not, write to the Free Software
   27.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   27.20 + */
   27.21 +
   27.22 +/** @file
   27.23 + * An IOStream implementation using sockets.
   27.24 + */
   27.25 +#ifndef __KERNEL__
   27.26 +
   27.27 +#include <stdio.h>
   27.28 +#include <stdlib.h>
   27.29 +#include <string.h>
   27.30 +#include <unistd.h>
   27.31 +#include <errno.h>
   27.32 +#include "allocate.h"
   27.33 +#include "socket_stream.h"
   27.34 +
   27.35 +#define MODULE_NAME "sock"
   27.36 +#define DEBUG 0
   27.37 +//#undef DEBUG
   27.38 +#include "debug.h"
   27.39 +
   27.40 +static int socket_read(IOStream *s, void *buf, size_t n);
   27.41 +static int socket_write(IOStream *s, const void *buf, size_t n);
   27.42 +static int socket_error(IOStream *s);
   27.43 +static int socket_close(IOStream *s);
   27.44 +static void socket_free(IOStream *s);
   27.45 +static int socket_flush(IOStream *s);
   27.46 +
   27.47 +/** Methods used by a socket IOStream. */
   27.48 +static const IOMethods socket_methods = {
   27.49 +    read:  socket_read,
   27.50 +    write: socket_write,
   27.51 +    error: socket_error,
   27.52 +    close: socket_close,
   27.53 +    free:  socket_free,
   27.54 +    flush: socket_flush,
   27.55 +};
   27.56 +
   27.57 +/** Get the socket data.
   27.58 + * 
   27.59 + * @param io socket stream
   27.60 + * @return data
   27.61 + */
   27.62 +static inline SocketData * socket_data(IOStream *io){
   27.63 +    return (SocketData *)io->data;
   27.64 +}
   27.65 +
   27.66 +/** Test if a stream is a socket stream.
   27.67 + *
   27.68 + * @param io stream
   27.69 + * @return 0 if a socket stream, -EINVAL if not
   27.70 + */
   27.71 +int socket_stream_check(IOStream *io){
   27.72 +    return (io && io->methods == &socket_methods ? 0 : -EINVAL);
   27.73 +}
   27.74 +
   27.75 +/** Get the data for a socket stream.
   27.76 + *
   27.77 + * @param io stream
   27.78 + * @param data return value for the data
   27.79 + * @return 0 if a socket stream, -EINVAL if not
   27.80 + */
   27.81 +int socket_stream_data(IOStream *io, SocketData **data){
   27.82 +    int err = socket_stream_check(io);
   27.83 +    if(err){
   27.84 +        *data = NULL;
   27.85 +    } else {
   27.86 +        *data = socket_data(io);
   27.87 +    }
   27.88 +    return err;
   27.89 +}
   27.90 +
   27.91 +/** Set the destination address for a socket stream.
   27.92 + *
   27.93 + * @param io stream
   27.94 + * @param addr address
   27.95 + * @return 0 if a socket stream, -EINVAL if not
   27.96 + */
   27.97 +int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){
   27.98 +    int err = 0;
   27.99 +    SocketData *data = NULL;
  27.100 +    err = socket_stream_data(io, &data);
  27.101 +    if(!err){
  27.102 +        data->daddr = *addr;
  27.103 +    }
  27.104 +    return err;
  27.105 +}
  27.106 +
  27.107 +/** Set the send flags for a socket stream.
  27.108 + *
  27.109 + * @param io stream
  27.110 + * @param flags flags
  27.111 + * @return 0 if a socket stream, -EINVAL if not
  27.112 + */
  27.113 +int socket_stream_set_flags(IOStream *io, int flags){
  27.114 +    int err = 0;
  27.115 +    SocketData *data = NULL;
  27.116 +    err = socket_stream_data(io, &data);
  27.117 +    if(!err){
  27.118 +        data->flags = flags;
  27.119 +    }
  27.120 +    return err;
  27.121 +}
  27.122 +
  27.123 +/** Write to the underlying socket using sendto.
  27.124 + *
  27.125 + * @param stream input
  27.126 + * @param buf where to put input
  27.127 + * @param n number of bytes to write
  27.128 + * @return number of bytes written
  27.129 + */
  27.130 +static int socket_write(IOStream *s, const void *buf, size_t n){
  27.131 +    SocketData *data = socket_data(s);
  27.132 +    struct sockaddr *daddr = (struct sockaddr *)&data->daddr;
  27.133 +    socklen_t daddr_n = sizeof(data->daddr);
  27.134 +    int k;
  27.135 +    dprintf("> sock=%d addr=%s:%d n=%d\n",
  27.136 +            data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n);
  27.137 +    if(0){
  27.138 +        struct sockaddr_in self = {};
  27.139 +        socklen_t self_n;
  27.140 +        getsockname(data->fd, (struct sockaddr *)&self, &self_n);
  27.141 +        dprintf("> sockname sock=%d %s:%d\n",
  27.142 +                data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port));
  27.143 +    }
  27.144 +    k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n);
  27.145 +    dprintf("> sendto=%d\n", k);
  27.146 +    return k;
  27.147 +}
  27.148 +
  27.149 +/** Read from the underlying stream using recv();
  27.150 + *
  27.151 + * @param stream input
  27.152 + * @param buf where to put input
  27.153 + * @param n number of bytes to read
  27.154 + * @return number of bytes read
  27.155 + */
  27.156 +static int socket_read(IOStream *s, void *buf, size_t n){
  27.157 +    SocketData *data = socket_data(s);
  27.158 +    int k;
  27.159 +    struct sockaddr *saddr = (struct sockaddr *)&data->saddr;
  27.160 +    socklen_t saddr_n = sizeof(data->saddr);
  27.161 +    k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n);
  27.162 +    return k;
  27.163 +}
  27.164 +
  27.165 +/** Flush the socket (no-op).
  27.166 + *
  27.167 + * @param s socket stream
  27.168 + * @return 0 on success, error code otherwise
  27.169 + */
  27.170 +static int socket_flush(IOStream *s){
  27.171 +    return 0;
  27.172 +}
  27.173 +
  27.174 +/** Check if a socket stream has an error (no-op).
  27.175 + *
  27.176 + * @param s socket stream
  27.177 + * @return 1 if has an error, 0 otherwise
  27.178 + */
  27.179 +static int socket_error(IOStream *s){
  27.180 +    // Read SOL_SOCKET/SO_ERROR ?
  27.181 +    return 0;
  27.182 +}
  27.183 +
  27.184 +/** Close a socket stream.
  27.185 + *
  27.186 + * @param s socket stream to close
  27.187 + * @return result of the close
  27.188 + */
  27.189 +static int socket_close(IOStream *s){
  27.190 +    SocketData *data = socket_data(s);
  27.191 +    return close(data->fd);
  27.192 +}
  27.193 +
  27.194 +/** Free a socket stream.
  27.195 + *
  27.196 + * @param s socket stream
  27.197 + */
  27.198 +static void socket_free(IOStream *s){
  27.199 +    SocketData *data = socket_data(s);
  27.200 +    deallocate(data);
  27.201 +}
  27.202 +
  27.203 +/** Create an IOStream for a socket.
  27.204 + *
  27.205 + * @param fd socket to wtap
  27.206 + * @return new IOStream using fd for i/o
  27.207 + */
  27.208 +IOStream *socket_stream_new(int fd){
  27.209 +    int err = -ENOMEM;
  27.210 +    IOStream *io = NULL;
  27.211 +    SocketData *data = NULL;
  27.212 +
  27.213 +    io = ALLOCATE(IOStream);
  27.214 +    if(!io) goto exit;
  27.215 +    io->methods = &socket_methods;
  27.216 +    data = ALLOCATE(SocketData);
  27.217 +    if(!data) goto exit;
  27.218 +    io->data = data;
  27.219 +    data->fd = fd;
  27.220 +    data->buf_n = sizeof(data->buf);
  27.221 +    err = 0;
  27.222 +  exit:
  27.223 +    if(err){
  27.224 +        if(io){
  27.225 +            if(data) deallocate(data);
  27.226 +            deallocate(io);
  27.227 +            io = NULL;
  27.228 +        }
  27.229 +    }
  27.230 +    return io;
  27.231 +}
  27.232 +
  27.233 +#endif
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/libxutil/socket_stream.h	Wed Nov 24 12:07:16 2004 +0000
    28.3 @@ -0,0 +1,53 @@
    28.4 +/*
    28.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    28.6 + *
    28.7 + * This library is free software; you can redistribute it and/or modify
    28.8 + * it under the terms of the GNU Lesser General Public License as published by
    28.9 + * the Free Software Foundation; either version 2.1 of the License, or
   28.10 + * (at your option) any later version.
   28.11 + *
   28.12 + * This library is distributed in the hope that it will be useful,
   28.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.15 + * GNU Lesser General Public License for more details.
   28.16 + *
   28.17 + * You should have received a copy of the GNU Lesser General Public License
   28.18 + * along with this library; if not, write to the Free Software
   28.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   28.20 + */
   28.21 +
   28.22 +#ifndef _XEN_LIB_SOCKET_STREAM_H_
   28.23 +#define _XEN_LIB_SOCKET_STREAM_H_
   28.24 +
   28.25 +#ifndef __KERNEL__
   28.26 +#include "iostream.h"
   28.27 +#include <stdio.h>
   28.28 +
   28.29 +#include <sys/socket.h>
   28.30 +#include <netinet/in.h>
   28.31 +#include <arpa/inet.h>
   28.32 +
   28.33 +/** Data associated with a socket stream. */
   28.34 +typedef struct SocketData {
   28.35 +    /** The socket file descriptor. */
   28.36 +    int fd;
   28.37 +    /** Source address from last read (recvfrom). */
   28.38 +    struct sockaddr_in saddr;
   28.39 +    /** Destination address for writes (sendto). */
   28.40 +    struct sockaddr_in daddr;
   28.41 +    /** Write flags (sendto). */
   28.42 +    int flags;
   28.43 +    /** Buffer size. */
   28.44 +    int buf_n;
   28.45 +    /** Buffer for formatted printing. */
   28.46 +    char buf[1024];
   28.47 +} SocketData;
   28.48 +
   28.49 +extern IOStream *socket_stream_new(int fd);
   28.50 +extern int socket_stream_data(IOStream *io, SocketData **data);
   28.51 +extern int socket_stream_check(IOStream *io);
   28.52 +extern int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr);
   28.53 +extern int socket_stream_set_flags(IOStream *io, int flags);
   28.54 +
   28.55 +#endif
   28.56 +#endif /* !_XEN_LIB_SOCKET_STREAM_H_ */
    29.1 --- a/tools/libxutil/string_stream.c	Wed Nov 24 11:51:49 2004 +0000
    29.2 +++ b/tools/libxutil/string_stream.c	Wed Nov 24 12:07:16 2004 +0000
    29.3 @@ -1,5 +1,5 @@
    29.4  /*
    29.5 - * Copyright (C) 2001, 2002 Hewlett-Packard Company.
    29.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    29.7   *
    29.8   * This library is free software; you can redistribute it and/or modify
    29.9   * it under the terms of the GNU Lesser General Public License as published by
    30.1 --- a/tools/libxutil/string_stream.h	Wed Nov 24 11:51:49 2004 +0000
    30.2 +++ b/tools/libxutil/string_stream.h	Wed Nov 24 12:07:16 2004 +0000
    30.3 @@ -1,5 +1,5 @@
    30.4  /*
    30.5 - * Copyright (C) 2001, 2002 Hewlett-Packard Company.
    30.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    30.7   *
    30.8   * This library is free software; you can redistribute it and/or modify
    30.9   * it under the terms of the GNU Lesser General Public License as published by
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/tools/libxutil/sxpr.c	Wed Nov 24 12:07:16 2004 +0000
    31.3 @@ -0,0 +1,956 @@
    31.4 +/*
    31.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    31.6 + *
    31.7 + * This library is free software; you can redistribute it and/or modify
    31.8 + * it under the terms of the GNU Lesser General Public License as
    31.9 + * published by the Free Software Foundation; either version 2.1 of the
   31.10 + * License, or  (at your option) any later version. This library is 
   31.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   31.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   31.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   31.14 + * See the GNU Lesser General Public License for more details.
   31.15 + *
   31.16 + * You should have received a copy of the GNU Lesser General Public License
   31.17 + * along with this library; if not, write to the Free Software Foundation,
   31.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   31.19 + */
   31.20 +
   31.21 +#include <stdarg.h>
   31.22 +#include "sys_string.h"
   31.23 +#include "lexis.h"
   31.24 +#include "sys_net.h"
   31.25 +#include "hash_table.h"
   31.26 +#include "sxpr.h"
   31.27 +
   31.28 +#ifdef __KERNEL__
   31.29 +#include <linux/errno.h>
   31.30 +#else
   31.31 +#include <errno.h>
   31.32 +#endif
   31.33 +
   31.34 +#undef free
   31.35 +
   31.36 +/** @file
   31.37 + * General representation of sxprs.
   31.38 + * Includes print, equal, and free functions for the sxpr types.
   31.39 + *
   31.40 + * Zero memory containing an Sxpr will have the value ONONE - this is intentional.
   31.41 + * When a function returning an sxpr cannot allocate memory we return ONOMEM.
   31.42 + *
   31.43 + */
   31.44 +
   31.45 +static int atom_print(IOStream *io, Sxpr obj, unsigned flags);
   31.46 +static int atom_equal(Sxpr x, Sxpr y);
   31.47 +static void atom_free(Sxpr obj);
   31.48 +
   31.49 +static int string_print(IOStream *io, Sxpr obj, unsigned flags);
   31.50 +static int string_equal(Sxpr x, Sxpr y);
   31.51 +static void string_free(Sxpr obj);
   31.52 +
   31.53 +static int cons_print(IOStream *io, Sxpr obj, unsigned flags);
   31.54 +static int cons_equal(Sxpr x, Sxpr y);
   31.55 +static void cons_free(Sxpr obj);
   31.56 +
   31.57 +static int null_print(IOStream *io, Sxpr obj, unsigned flags);
   31.58 +static int none_print(IOStream *io, Sxpr obj, unsigned flags);
   31.59 +static int int_print(IOStream *io, Sxpr obj, unsigned flags);
   31.60 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags);
   31.61 +
   31.62 +/** Type definitions. */
   31.63 +static SxprType types[1024] = {
   31.64 +    [T_NONE]     { type:    T_NONE,     name: "none",       print: none_print      },
   31.65 +    [T_NULL]     { type:    T_NULL,     name: "null",       print: null_print      },
   31.66 +    [T_UINT]     { type:    T_UINT,     name: "int",        print: int_print,      },
   31.67 +    [T_BOOL]     { type:    T_BOOL,     name: "bool",       print: bool_print,     },
   31.68 +    [T_ATOM]     { type:    T_ATOM,     name: "atom",       print: atom_print,
   31.69 +		   pointer: TRUE,
   31.70 +		   free:    atom_free,
   31.71 +		   equal:   atom_equal,
   31.72 +		 },
   31.73 +    [T_STRING]   { type:    T_STRING,   name: "string",     print: string_print,
   31.74 +		   pointer: TRUE,
   31.75 +		   free:    string_free,
   31.76 +		   equal:   string_equal,
   31.77 +		 },
   31.78 +    [T_CONS]     { type:    T_CONS,     name: "cons",       print: cons_print,
   31.79 +		   pointer: TRUE,
   31.80 +		   free:    cons_free,
   31.81 +		   equal:   cons_equal,
   31.82 +		 },
   31.83 +};
   31.84 +
   31.85 +/** Number of entries in the types array. */
   31.86 +static int type_sup = sizeof(types)/sizeof(types[0]);
   31.87 +
   31.88 +/** Get the type definition for a given type code.
   31.89 + *
   31.90 + * @param ty type code
   31.91 + * @return type definition or null
   31.92 + */
   31.93 +SxprType *get_sxpr_type(int ty){
   31.94 +    if(0 <= ty && ty < type_sup){
   31.95 +        return types+ty;
   31.96 +    }
   31.97 +    return NULL;
   31.98 +}
   31.99 +
  31.100 +/** The default print function.
  31.101 + *
  31.102 + * @param io stream to print to
  31.103 + * @param x sxpr to print
  31.104 + * @param flags print flags
  31.105 + * @return number of bytes written on success
  31.106 + */
  31.107 +int default_print(IOStream *io, Sxpr x, unsigned flags){
  31.108 +    return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x));
  31.109 +}
  31.110 +
  31.111 +/** The default equal function.
  31.112 + * Uses eq().
  31.113 + *
  31.114 + * @param x sxpr to compare
  31.115 + * @param y sxpr to compare
  31.116 + * @return 1 if equal, 0 otherwise
  31.117 + */
  31.118 +int default_equal(Sxpr x, Sxpr y){
  31.119 +    return eq(x, y);
  31.120 +}
  31.121 +
  31.122 +/** General sxpr print function.
  31.123 + * Prints an sxpr on a stream using the print function for the sxpr type.
  31.124 + * Printing is controlled by flags from the PrintFlags enum.
  31.125 + * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr
  31.126 + * (for debugging).
  31.127 + *
  31.128 + * @param io stream to print to
  31.129 + * @param x sxpr to print
  31.130 + * @param flags print flags
  31.131 + * @return number of bytes written
  31.132 + */
  31.133 +int objprint(IOStream *io, Sxpr x, unsigned flags){
  31.134 +    SxprType *def = get_sxpr_type(get_type(x));
  31.135 +    ObjPrintFn *print_fn = (def && def->print ? def->print : default_print);
  31.136 +    int k = 0;
  31.137 +    if(!io) return k;
  31.138 +    if(flags & PRINT_TYPE){
  31.139 +	k += IOStream_print(io, "%s:", def->name);
  31.140 +    }
  31.141 +    k += print_fn(io, x, flags);
  31.142 +    return k;
  31.143 +}
  31.144 +
  31.145 +/** General sxpr free function.
  31.146 + * Frees an sxpr using the free function for its type.
  31.147 + * Free functions must recursively free any subsxprs.
  31.148 + * If no function is defined then the default is to
  31.149 + * free sxprs whose type has pointer true.
  31.150 + * Sxprs must not be used after freeing.
  31.151 + *
  31.152 + * @param x sxpr to free
  31.153 + */
  31.154 +void objfree(Sxpr x){
  31.155 +    SxprType *def = get_sxpr_type(get_type(x));
  31.156 +
  31.157 +    if(def){
  31.158 +	if(def->free){
  31.159 +	    def->free(x);
  31.160 +	} else if (def->pointer){
  31.161 +	    hfree(x);
  31.162 +	}
  31.163 +    }
  31.164 +}
  31.165 +
  31.166 +/** General sxpr equality function.
  31.167 + * Compares x and y using the equal function for x.
  31.168 + * Uses default_equal() if x has no equal function.
  31.169 + *
  31.170 + * @param x sxpr to compare
  31.171 + * @param y sxpr to compare
  31.172 + * @return 1 if equal, 0 otherwise
  31.173 + */
  31.174 +int objequal(Sxpr x, Sxpr y){
  31.175 +    SxprType *def = get_sxpr_type(get_type(x));
  31.176 +    ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal);
  31.177 +    return equal_fn(x, y);
  31.178 +}
  31.179 +
  31.180 +/** Search for a key in an alist.
  31.181 + * An alist is a list of conses, where the cars
  31.182 + * of the conses are the keys. Compares keys using equality.
  31.183 + *
  31.184 + * @param k key
  31.185 + * @param l alist to search
  31.186 + * @return first element of l with car k, or ONULL
  31.187 + */
  31.188 +Sxpr assoc(Sxpr k, Sxpr l){
  31.189 +    for( ; CONSP(l) ; l = CDR(l)){
  31.190 +        Sxpr x = CAR(l);
  31.191 +        if(CONSP(x) && objequal(k, CAR(x))){
  31.192 +            return x;   
  31.193 +        }
  31.194 +    }
  31.195 +    return ONULL;
  31.196 +}
  31.197 +
  31.198 +/** Search for a key in an alist.
  31.199 + * An alist is a list of conses, where the cars
  31.200 + * of the conses are the keys. Compares keys using eq.
  31.201 + *
  31.202 + * @param k key
  31.203 + * @param l alist to search
  31.204 + * @return first element of l with car k, or ONULL
  31.205 + */
  31.206 +Sxpr assocq(Sxpr k, Sxpr l){
  31.207 +    for( ; CONSP(l); l = CDR(l)){
  31.208 +        Sxpr x = CAR(l);
  31.209 +        if(CONSP(x) && eq(k, CAR(x))){
  31.210 +            return x;
  31.211 +        }
  31.212 +    }
  31.213 +    return ONULL;
  31.214 +}
  31.215 +
  31.216 +/** Add a new key and value to an alist.
  31.217 + *
  31.218 + * @param k key
  31.219 + * @param l value
  31.220 + * @param l alist
  31.221 + * @return l with the new cell added to the front
  31.222 + */
  31.223 +Sxpr acons(Sxpr k, Sxpr v, Sxpr l){
  31.224 +    Sxpr x, y;
  31.225 +    x = cons_new(k, v);
  31.226 +    if(NOMEMP(x)) return x;
  31.227 +    y = cons_new(x, l);
  31.228 +    if(NOMEMP(y)) cons_free_cells(x);
  31.229 +    return y;
  31.230 +}
  31.231 +
  31.232 +/** Test if a list contains an element.
  31.233 + * Uses sxpr equality.
  31.234 + *
  31.235 + * @param l list
  31.236 + * @param x element to look for
  31.237 + * @return a tail of l with x as car, or ONULL
  31.238 + */
  31.239 +Sxpr cons_member(Sxpr l, Sxpr x){
  31.240 +    for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){}
  31.241 +    return l;
  31.242 +}
  31.243 +
  31.244 +/** Test if a list contains an element satisfying a test.
  31.245 + * The test function is called with v and an element of the list.
  31.246 + *
  31.247 + * @param l list
  31.248 + * @param test_fn test function to use
  31.249 + * @param v value for first argument to the test
  31.250 + * @return a tail of l with car satisfying the test, or 0
  31.251 + */
  31.252 +Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
  31.253 +    for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ }
  31.254 +    return l;
  31.255 +}
  31.256 +
  31.257 +/** Test if the elements of list 't' are a subset of the elements
  31.258 + * of list 's'. Element order is not significant.
  31.259 + *
  31.260 + * @param s element list to check subset of
  31.261 + * @param t element list to check if is a subset
  31.262 + * @return 1 if is a subset, 0 otherwise
  31.263 + */
  31.264 +int cons_subset(Sxpr s, Sxpr t){
  31.265 +    for( ; CONSP(t); t = CDR(t)){
  31.266 +	if(!CONSP(cons_member(s, CAR(t)))){
  31.267 +	    return 0;
  31.268 +	}
  31.269 +    }
  31.270 +    return 1;
  31.271 +}
  31.272 +
  31.273 +/** Test if two lists have equal sets of elements.
  31.274 + * Element order is not significant.
  31.275 + *
  31.276 + * @param s list to check
  31.277 + * @param t list to check
  31.278 + * @return 1 if equal, 0 otherwise
  31.279 + */
  31.280 +int cons_set_equal(Sxpr s, Sxpr t){
  31.281 +    return cons_subset(s, t) && cons_subset(t, s);
  31.282 +}
  31.283 +
  31.284 +#ifdef USE_GC
  31.285 +/*============================================================================*/
  31.286 +/* The functions inside this ifdef are only safe if GC is used.
  31.287 + * Otherwise they may leak memory.
  31.288 + */
  31.289 +
  31.290 +/** Remove an element from a list (GC only).
  31.291 + * Uses sxpr equality and removes all instances, even
  31.292 + * if there are more than one.
  31.293 + *
  31.294 + * @param l list to remove elements from
  31.295 + * @param x element to remove
  31.296 + * @return modified input list
  31.297 + */
  31.298 +Sxpr cons_remove(Sxpr l, Sxpr x){
  31.299 +    return cons_remove_if(l, eq, x);
  31.300 +}
  31.301 +
  31.302 +/** Remove elements satisfying a test (GC only).
  31.303 + * The test function is called with v and an element of the set.
  31.304 + *
  31.305 + * @param l list to remove elements from
  31.306 + * @param test_fn function to use to decide if an element should be removed
  31.307 + * @return modified input list
  31.308 + */
  31.309 +Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
  31.310 +    Sxpr prev = ONULL, elt, next;
  31.311 +
  31.312 +    for(elt = l; CONSP(elt); elt = next){
  31.313 +        next = CDR(elt);
  31.314 +        if(test_fn(v, CAR(elt))){
  31.315 +            if(NULLP(prev)){
  31.316 +                l = next;
  31.317 +            } else {
  31.318 +                CDR(prev) = next;
  31.319 +            }
  31.320 +        }
  31.321 +    }
  31.322 +    return l;
  31.323 +}
  31.324 +
  31.325 +/** Set the value for a key in an alist (GC only).
  31.326 + * If the key is present, changes the value, otherwise
  31.327 + * adds a new cell.
  31.328 + *
  31.329 + * @param k key
  31.330 + * @param v value
  31.331 + * @param l alist
  31.332 + * @return modified or extended list
  31.333 + */
  31.334 +Sxpr setf(Sxpr k, Sxpr v, Sxpr l){
  31.335 +    Sxpr e = assoc(k, l);
  31.336 +    if(NULLP(e)){
  31.337 +        l = acons(k, v, l);
  31.338 +    } else {
  31.339 +        CAR(CDR(e)) = v;
  31.340 +    }
  31.341 +    return l;
  31.342 +}
  31.343 +/*============================================================================*/
  31.344 +#endif /* USE_GC */
  31.345 +
  31.346 +/** Create a new atom with the given name.
  31.347 + *
  31.348 + * @param name the name
  31.349 + * @return new atom
  31.350 + */
  31.351 +Sxpr atom_new(char *name){
  31.352 +    Sxpr n, obj = ONOMEM;
  31.353 +
  31.354 +    n = string_new(name);
  31.355 +    if(NOMEMP(n)) goto exit;
  31.356 +    obj = HALLOC(ObjAtom, T_ATOM);
  31.357 +    if(NOMEMP(obj)) goto exit;
  31.358 +    OBJ_ATOM(obj)->name = n;
  31.359 +  exit:
  31.360 +    return obj;
  31.361 +}
  31.362 +
  31.363 +/** Free an atom.
  31.364 + *
  31.365 + * @param obj to free
  31.366 + */
  31.367 +void atom_free(Sxpr obj){
  31.368 +    // Interned atoms are shared, so do not free.
  31.369 +    if(OBJ_ATOM(obj)->interned) return;
  31.370 +    objfree(OBJ_ATOM(obj)->name);
  31.371 +    hfree(obj);
  31.372 +}
  31.373 +
  31.374 +/** Print an atom. Prints the atom name.
  31.375 + *
  31.376 + * @param io stream to print to
  31.377 + * @param obj to print
  31.378 + * @param flags print flags
  31.379 + * @return number of bytes printed
  31.380 + */
  31.381 +int atom_print(IOStream *io, Sxpr obj, unsigned flags){
  31.382 +    //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW));
  31.383 +    return string_print(io, OBJ_ATOM(obj)->name, flags);
  31.384 +}
  31.385 +
  31.386 +/** Atom equality.
  31.387 + *
  31.388 + * @param x to compare
  31.389 + * @param y to compare
  31.390 + * @return 1 if equal, 0 otherwise
  31.391 + */
  31.392 +int atom_equal(Sxpr x, Sxpr y){
  31.393 +    int ok;
  31.394 +    ok = eq(x, y);
  31.395 +    if(ok) goto exit;
  31.396 +    ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name);
  31.397 +    if(ok) goto exit;
  31.398 +    ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y);
  31.399 +  exit:
  31.400 +    return ok;
  31.401 +}
  31.402 +
  31.403 +/** Get the name of an atom.
  31.404 + *
  31.405 + * @param obj atom
  31.406 + * @return name
  31.407 + */
  31.408 +char * atom_name(Sxpr obj){
  31.409 +    return string_string(OBJ_ATOM(obj)->name);
  31.410 +}
  31.411 +
  31.412 +/** Get the C string from a string sxpr.
  31.413 + *
  31.414 + * @param obj string sxpr
  31.415 + * @return string
  31.416 + */
  31.417 +char * string_string(Sxpr obj){
  31.418 +    return OBJ_STRING(obj);
  31.419 +}
  31.420 +
  31.421 +/** Get the length of a string.
  31.422 + *
  31.423 + * @param obj string
  31.424 + * @return length
  31.425 + */
  31.426 +int string_length(Sxpr obj){
  31.427 +    return strlen(OBJ_STRING(obj));
  31.428 +}
  31.429 +
  31.430 +/** Create a new string. The input string is copied,
  31.431 + * and must be null-terminated.
  31.432 + *
  31.433 + * @param s characters to put in the string
  31.434 + * @return new sxpr
  31.435 + */
  31.436 +Sxpr string_new(char *s){
  31.437 +    int n = (s ? strlen(s) : 0);
  31.438 +    Sxpr obj;
  31.439 +    obj = halloc(n+1, T_STRING);
  31.440 +    if(!NOMEMP(obj)){
  31.441 +        char *str = OBJ_STRING(obj);
  31.442 +        strncpy(str, s, n);
  31.443 +        str[n] = '\0';
  31.444 +    }
  31.445 +    return obj;
  31.446 +}
  31.447 +
  31.448 +/** Free a string.
  31.449 + *
  31.450 + * @param obj to free
  31.451 + */
  31.452 +void string_free(Sxpr obj){
  31.453 +    hfree(obj);
  31.454 +}
  31.455 +
  31.456 +/** Determine if a string needs escapes when printed
  31.457 + * using the given flags.
  31.458 + *
  31.459 + * @param str string to check
  31.460 + * @param flags print flags
  31.461 + * @return 1 if needs escapes, 0 otherwise
  31.462 + */
  31.463 +int needs_escapes(char *str, unsigned flags){
  31.464 +    char *c;
  31.465 +    int val = 0;
  31.466 +
  31.467 +    if(str){
  31.468 +	for(c=str; *c; c++){
  31.469 +	    if(in_alpha_class(*c)) continue;
  31.470 +	    if(in_decimal_digit_class(*c)) continue;
  31.471 +	    if(in_class(*c, "/._+:@~-")) continue;
  31.472 +	    val = 1;
  31.473 +	    break;
  31.474 +	}
  31.475 +    }
  31.476 +    //printf("\n> val=%d str=|%s|\n", val, str);
  31.477 +    return val;
  31.478 +}
  31.479 +
  31.480 +/** Print a string to a stream, with escapes if necessary.
  31.481 + *
  31.482 + * @param io stream to print to
  31.483 + * @param str string
  31.484 + * @param flags print flags
  31.485 + * @return number of bytes written
  31.486 + */
  31.487 +int _string_print(IOStream *io, char *str, unsigned flags){
  31.488 +    int k = 0;
  31.489 +    if((flags & PRINT_RAW) || !needs_escapes(str, flags)){
  31.490 +        k += IOStream_print(io, str);
  31.491 +    } else {
  31.492 +	k += IOStream_print(io, "\"");
  31.493 +	if(str){
  31.494 +            char *s;
  31.495 +            for(s = str; *s; s++){
  31.496 +                if(*s < ' ' || *s >= 127 ){
  31.497 +                    switch(*s){
  31.498 +                    case '\a': k += IOStream_print(io, "\\a");  break;
  31.499 +                    case '\b': k += IOStream_print(io, "\\b");  break;
  31.500 +                    case '\f': k += IOStream_print(io, "\\f");  break;
  31.501 +                    case '\n': k += IOStream_print(io, "\\n");  break;
  31.502 +                    case '\r': k += IOStream_print(io, "\\r");  break;
  31.503 +                    case '\t': k += IOStream_print(io, "\\t");  break;
  31.504 +                    case '\v': k += IOStream_print(io, "\\v");  break;
  31.505 +                    default:
  31.506 +                        // Octal escape;
  31.507 +                        k += IOStream_print(io, "\\%o", *s);
  31.508 +                        break;
  31.509 +                    }
  31.510 +                } else if(*s == c_double_quote ||
  31.511 +                          *s == c_single_quote ||
  31.512 +                          *s == c_escape){
  31.513 +                    k += IOStream_print(io, "\\%c", *s);
  31.514 +                } else {
  31.515 +                    k+= IOStream_print(io, "%c", *s);
  31.516 +                }
  31.517 +            }
  31.518 +	}
  31.519 +	k += IOStream_print(io, "\"");
  31.520 +    }
  31.521 +    return k;
  31.522 +}
  31.523 +
  31.524 +/** Print a string to a stream, with escapes if necessary.
  31.525 + *
  31.526 + * @param io stream to print to
  31.527 + * @param obj string
  31.528 + * @param flags print flags
  31.529 + * @return number of bytes written
  31.530 + */
  31.531 +int string_print(IOStream *io, Sxpr obj, unsigned flags){
  31.532 +    return _string_print(io, OBJ_STRING(obj), flags);
  31.533 +}
  31.534 +
  31.535 +/** Compare an sxpr with a string for equality.
  31.536 + *
  31.537 + * @param x string to compare with
  31.538 + * @param y sxpr to compare
  31.539 + * @return 1 if equal, 0 otherwise
  31.540 + */
  31.541 +int string_equal(Sxpr x, Sxpr y){
  31.542 +    int ok = 0;
  31.543 +    ok = eq(x,y);
  31.544 +    if(ok) goto exit;
  31.545 +    ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y));
  31.546 +    if(ok) goto exit;
  31.547 +    ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y));
  31.548 +  exit:
  31.549 +    return ok;
  31.550 +}
  31.551 +
  31.552 +/** Create a new cons cell.
  31.553 + * The cell is ONOMEM if either argument is.
  31.554 + *
  31.555 + * @param car sxpr for the car
  31.556 + * @param cdr sxpr for the cdr
  31.557 + * @return new cons
  31.558 + */
  31.559 +Sxpr cons_new(Sxpr car, Sxpr cdr){
  31.560 +    Sxpr obj;
  31.561 +    if(NOMEMP(car) || NOMEMP(cdr)){
  31.562 +        obj = ONOMEM;
  31.563 +    } else {
  31.564 +        obj = HALLOC(ObjCons, T_CONS);
  31.565 +        if(!NOMEMP(obj)){
  31.566 +            ObjCons *z = OBJ_CONS(obj);
  31.567 +            z->car = car;
  31.568 +            z->cdr = cdr;
  31.569 +        }
  31.570 +    }
  31.571 +    return obj;
  31.572 +}
  31.573 +
  31.574 +/** Push a new element onto a list.
  31.575 + *
  31.576 + * @param list list to add to
  31.577 + * @param elt element to add
  31.578 + * @return 0 if successful, error code otherwise
  31.579 + */
  31.580 +int cons_push(Sxpr *list, Sxpr elt){
  31.581 +    Sxpr l;
  31.582 +    l = cons_new(elt, *list);
  31.583 +    if(NOMEMP(l)) return -ENOMEM;
  31.584 +    *list = l;
  31.585 +    return 0;
  31.586 +}
  31.587 +
  31.588 +/** Free a cons. Recursively frees the car and cdr.
  31.589 + *
  31.590 + * @param obj to free
  31.591 + */
  31.592 +void cons_free(Sxpr obj){
  31.593 +    Sxpr next;
  31.594 +    for(; CONSP(obj); obj = next){
  31.595 +	next = CDR(obj);
  31.596 +	objfree(CAR(obj));
  31.597 +	hfree(obj);
  31.598 +    }
  31.599 +    if(!NULLP(obj)){
  31.600 +	objfree(obj);
  31.601 +    }
  31.602 +}
  31.603 +
  31.604 +/** Free a cons and its cdr cells, but not the car sxprs.
  31.605 + * Does nothing if called on something that is not a cons.
  31.606 + *
  31.607 + * @param obj to free
  31.608 + */
  31.609 +void cons_free_cells(Sxpr obj){
  31.610 +    Sxpr next;
  31.611 +    for(; CONSP(obj); obj = next){
  31.612 +	next = CDR(obj);
  31.613 +	hfree(obj);
  31.614 +    }
  31.615 +}
  31.616 +
  31.617 +/** Print a cons.
  31.618 + * Prints the cons in list format if the cdrs are conses.
  31.619 + * uses pair (dot) format if the last cdr is not a cons (or null).
  31.620 + *
  31.621 + * @param io stream to print to
  31.622 + * @param obj to print
  31.623 + * @param flags print flags
  31.624 + * @return number of bytes written
  31.625 + */
  31.626 +int cons_print(IOStream *io, Sxpr obj, unsigned flags){
  31.627 +    int first = 1;
  31.628 +    int k = 0;
  31.629 +    k += IOStream_print(io, "(");
  31.630 +    for( ; CONSP(obj) ; obj = CDR(obj)){
  31.631 +        if(first){ 
  31.632 +            first = 0;
  31.633 +        } else {
  31.634 +            k += IOStream_print(io, " ");
  31.635 +        }
  31.636 +        k += objprint(io, CAR(obj), flags);
  31.637 +    }
  31.638 +    if(!NULLP(obj)){
  31.639 +        k += IOStream_print(io, " . ");
  31.640 +        k += objprint(io, obj, flags);
  31.641 +    }
  31.642 +    k += IOStream_print(io, ")");
  31.643 +    return (IOStream_error(io) ? -1 : k);
  31.644 +}
  31.645 +
  31.646 +/** Compare a cons with another sxpr for equality.
  31.647 + * If y is a cons, compares the cars and cdrs recursively.
  31.648 + *
  31.649 + * @param x cons to compare
  31.650 + * @param y sxpr to compare
  31.651 + * @return 1 if equal, 0 otherwise
  31.652 + */
  31.653 +int cons_equal(Sxpr x, Sxpr y){
  31.654 +    return CONSP(y) &&
  31.655 +        objequal(CAR(x), CAR(y)) &&
  31.656 +        objequal(CDR(x), CDR(y));
  31.657 +}
  31.658 +
  31.659 +/** Return the length of a cons list.
  31.660 + *
  31.661 + * @param obj list
  31.662 + * @return length
  31.663 + */
  31.664 +int cons_length(Sxpr obj){
  31.665 +    int count = 0;
  31.666 +    for( ; CONSP(obj); obj = CDR(obj)){
  31.667 +        count++;
  31.668 +    }
  31.669 +    return count;
  31.670 +}
  31.671 +
  31.672 +/** Destructively reverse a cons list in-place.
  31.673 + * If the argument is not a cons it is returned unchanged.
  31.674 + * 
  31.675 + * @param l to reverse
  31.676 + * @return reversed list
  31.677 + */
  31.678 +Sxpr nrev(Sxpr l){
  31.679 +    if(CONSP(l)){
  31.680 +	// Iterate down the cells in the list making the cdr of
  31.681 +	// each cell point to the previous cell. The last cell 
  31.682 +	// is the head of the reversed list.
  31.683 +	Sxpr prev = ONULL;
  31.684 +	Sxpr cell = l;
  31.685 +	Sxpr next;
  31.686 +
  31.687 +	while(1){
  31.688 +	    next = CDR(cell);
  31.689 +	    CDR(cell) = prev;
  31.690 +	    if(!CONSP(next)) break;
  31.691 +	    prev = cell;
  31.692 +	    cell = next;
  31.693 +	}
  31.694 +	l = cell;
  31.695 +    }
  31.696 +    return l;
  31.697 +}
  31.698 +
  31.699 +/** Print the null sxpr.	
  31.700 + *
  31.701 + * @param io stream to print to
  31.702 + * @param obj to print
  31.703 + * @param flags print flags
  31.704 + * @return number of bytes written
  31.705 + */
  31.706 +static int null_print(IOStream *io, Sxpr obj, unsigned flags){
  31.707 +    return IOStream_print(io, "()");
  31.708 +}
  31.709 +
  31.710 +/** Print the `unspecified' sxpr none.
  31.711 + *
  31.712 + * @param io stream to print to
  31.713 + * @param obj to print
  31.714 + * @param flags print flags
  31.715 + * @return number of bytes written
  31.716 + */
  31.717 +static int none_print(IOStream *io, Sxpr obj, unsigned flags){
  31.718 +    return IOStream_print(io, "<none>");
  31.719 +}
  31.720 +
  31.721 +/** Print an integer.
  31.722 + *
  31.723 + * @param io stream to print to
  31.724 + * @param obj to print
  31.725 + * @param flags print flags
  31.726 + * @return number of bytes written
  31.727 + */
  31.728 +static int int_print(IOStream *io, Sxpr obj, unsigned flags){
  31.729 +    return IOStream_print(io, "%d", OBJ_INT(obj));
  31.730 +}
  31.731 +
  31.732 +/** Print a boolean.
  31.733 + *
  31.734 + * @param io stream to print to
  31.735 + * @param obj to print
  31.736 + * @param flags print flags
  31.737 + * @return number of bytes written
  31.738 + */
  31.739 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags){
  31.740 +    return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false));
  31.741 +}
  31.742 +
  31.743 +int sxprp(Sxpr obj, Sxpr name){
  31.744 +    return CONSP(obj) && objequal(CAR(obj), name);
  31.745 +}
  31.746 +
  31.747 +/** Get the name of an element.
  31.748 + * 
  31.749 + * @param obj element
  31.750 + * @return name
  31.751 + */
  31.752 +Sxpr sxpr_name(Sxpr obj){
  31.753 +    Sxpr val = ONONE;
  31.754 +    if(CONSP(obj)){
  31.755 +        val = CAR(obj);
  31.756 +    } else if(STRINGP(obj) || ATOMP(obj)){
  31.757 +        val = obj;
  31.758 +    }
  31.759 +    return val;
  31.760 +}
  31.761 +
  31.762 +int sxpr_is(Sxpr obj, char *s){
  31.763 +    if(ATOMP(obj)) return !strcmp(atom_name(obj), s);
  31.764 +    if(STRINGP(obj)) return !strcmp(string_string(obj), s);
  31.765 +    return 0;
  31.766 +}
  31.767 +
  31.768 +int sxpr_elementp(Sxpr obj, Sxpr name){
  31.769 +    int ok = 0;
  31.770 +    ok = CONSP(obj) && objequal(CAR(obj), name);
  31.771 +    return ok;
  31.772 +}
  31.773 +
  31.774 +/** Get the attributes of an sxpr.
  31.775 + * 
  31.776 + * @param obj sxpr
  31.777 + * @return attributes
  31.778 + */
  31.779 +Sxpr sxpr_attributes(Sxpr obj){
  31.780 +    Sxpr val = ONULL;
  31.781 +    if(CONSP(obj)){
  31.782 +        obj = CDR(obj);
  31.783 +        if(CONSP(obj)){
  31.784 +            obj = CAR(obj);
  31.785 +            if(sxprp(obj, intern("@"))){
  31.786 +                val = CDR(obj);
  31.787 +            }
  31.788 +        }
  31.789 +    }
  31.790 +    return val;
  31.791 +}
  31.792 +
  31.793 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){
  31.794 +    Sxpr val = ONONE;
  31.795 +    val = assoc(sxpr_attributes(obj), key);
  31.796 +    if(CONSP(val) && CONSP(CDR(val))){
  31.797 +        val = CADR(def);
  31.798 +    } else {
  31.799 +        val = def;
  31.800 +    }
  31.801 +    return val;
  31.802 +}
  31.803 +
  31.804 +/** Get the children of an sxpr.
  31.805 + * 
  31.806 + * @param obj sxpr
  31.807 + * @return children
  31.808 + */
  31.809 +Sxpr sxpr_children(Sxpr obj){
  31.810 +    Sxpr val = ONULL;
  31.811 +    if(CONSP(obj)){
  31.812 +        val = CDR(obj);
  31.813 +        if(CONSP(val) && sxprp(CAR(val), intern("@"))){
  31.814 +            val = CDR(val);
  31.815 +        }
  31.816 +    }
  31.817 +    return val;
  31.818 +}
  31.819 +
  31.820 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){
  31.821 +    Sxpr val = ONONE;
  31.822 +    Sxpr l;
  31.823 +    for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){
  31.824 +        if(sxprp(CAR(l), name)){
  31.825 +            val = CAR(l);
  31.826 +            break;
  31.827 +        }
  31.828 +    }
  31.829 +    if(NONEP(val)) val = def;
  31.830 +    return val;
  31.831 +}
  31.832 +
  31.833 +Sxpr sxpr_child0(Sxpr obj, Sxpr def){
  31.834 +    Sxpr val = ONONE;
  31.835 +    Sxpr l = sxpr_children(obj);
  31.836 +    if(CONSP(l)){
  31.837 +        val = CAR(l);
  31.838 +    } else {
  31.839 +        val = def;
  31.840 +    }
  31.841 +    return val;
  31.842 +}
  31.843 +
  31.844 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def){
  31.845 +    Sxpr val = def;
  31.846 +    Sxpr l;
  31.847 +    int i;
  31.848 +    for (i = 0, l = sxpr_children(obj); CONSP(l); i++, l = CDR(l)){
  31.849 +        if(i == n){
  31.850 +            val = CAR(l);
  31.851 +            break;
  31.852 +        }
  31.853 +    }
  31.854 +    return val;
  31.855 +}
  31.856 +    
  31.857 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){
  31.858 +    Sxpr val = ONONE;
  31.859 +    val = sxpr_child(obj, name, ONONE);
  31.860 +    if(NONEP(val)){
  31.861 +        val = def;
  31.862 +    } else {
  31.863 +        val = sxpr_child0(val, def);
  31.864 +    }
  31.865 +    return val;
  31.866 +}
  31.867 +
  31.868 +/** Table of interned symbols. Indexed by symbol name. */
  31.869 +static HashTable *symbols = NULL;
  31.870 +
  31.871 +/** Hash function for entries in the symbol table.
  31.872 + *
  31.873 + * @param key to hash
  31.874 + * @return hashcode
  31.875 + */
  31.876 +static Hashcode sym_hash_fn(void *key){
  31.877 +    return hash_string((char*)key);
  31.878 +}
  31.879 +
  31.880 +/** Key equality function for the symbol table.
  31.881 + *
  31.882 + * @param x to compare
  31.883 + * @param y to compare
  31.884 + * @return 1 if equal, 0 otherwise
  31.885 + */
  31.886 +static int sym_equal_fn(void *x, void *y){
  31.887 +    return !strcmp((char*)x, (char*)y);
  31.888 +}
  31.889 +
  31.890 +/** Entry free function for the symbol table.
  31.891 + *
  31.892 + * @param table the entry is in
  31.893 + * @param entry being freed
  31.894 + */
  31.895 +static void sym_free_fn(HashTable *table, HTEntry *entry){
  31.896 +    if(entry){
  31.897 +	objfree(((ObjAtom*)entry->value)->name);
  31.898 +	HTEntry_free(entry);
  31.899 +    }
  31.900 +}
  31.901 +	
  31.902 +/** Initialize the symbol table.
  31.903 + *
  31.904 + * @return 0 on sucess, error code otherwise
  31.905 + */
  31.906 +static int init_symbols(void){
  31.907 +    symbols = HashTable_new(100);
  31.908 +    if(symbols){
  31.909 +        symbols->key_hash_fn = sym_hash_fn;
  31.910 +        symbols->key_equal_fn = sym_equal_fn;
  31.911 +	symbols->entry_free_fn = sym_free_fn;
  31.912 +        return 0;
  31.913 +    }
  31.914 +    return -1;
  31.915 +}
  31.916 +
  31.917 +/** Cleanup the symbol table. Frees the table and all its symbols.
  31.918 + */
  31.919 +void cleanup_symbols(void){
  31.920 +    HashTable_free(symbols);
  31.921 +    symbols = NULL;
  31.922 +}
  31.923 +
  31.924 +/** Get the interned symbol with the given name.
  31.925 + * No new symbol is created.
  31.926 + *
  31.927 + * @return symbol or null
  31.928 + */
  31.929 +Sxpr get_symbol(char *sym){
  31.930 +    HTEntry *entry;
  31.931 +    if(!symbols){
  31.932 +	if(init_symbols()) return ONOMEM;
  31.933 +	return ONULL;
  31.934 +    }
  31.935 +    entry = HashTable_get_entry(symbols, sym);
  31.936 +    if(entry){
  31.937 +        return OBJP(T_ATOM, entry->value);
  31.938 +    } else {
  31.939 +        return ONULL;
  31.940 +    }
  31.941 +}
  31.942 +
  31.943 +/** Get the interned symbol with the given name.
  31.944 + * Creates a new symbol if necessary.
  31.945 + *
  31.946 + * @return symbol
  31.947 + */
  31.948 +Sxpr intern(char *sym){
  31.949 +    Sxpr symbol = get_symbol(sym);
  31.950 +    if(NULLP(symbol)){
  31.951 +	if(!symbols) return ONOMEM;
  31.952 +        symbol = atom_new(sym);
  31.953 +        if(!NOMEMP(symbol)){
  31.954 +	    OBJ_ATOM(symbol)->interned = TRUE;
  31.955 +            HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));
  31.956 +        }
  31.957 +    }
  31.958 +    return symbol;
  31.959 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/tools/libxutil/sxpr.h	Wed Nov 24 12:07:16 2004 +0000
    32.3 @@ -0,0 +1,420 @@
    32.4 +/*
    32.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    32.6 + *
    32.7 + * This library is free software; you can redistribute it and/or modify
    32.8 + * it under the terms of the GNU Lesser General Public License as
    32.9 + * published by the Free Software Foundation; either version 2.1 of the
   32.10 + * License, or  (at your option) any later version. This library is 
   32.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   32.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   32.14 + * See the GNU Lesser General Public License for more details.
   32.15 + *
   32.16 + * You should have received a copy of the GNU Lesser General Public License
   32.17 + * along with this library; if not, write to the Free Software Foundation,
   32.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   32.19 + */
   32.20 +#ifndef _XUTIL_SXPR_H_
   32.21 +#define _XUTIL_SXPR_H_
   32.22 +
   32.23 +#ifdef __KERNEL__
   32.24 +#include <linux/config.h>
   32.25 +#include <linux/types.h>
   32.26 +#else
   32.27 +#include <stdint.h>
   32.28 +#endif
   32.29 +
   32.30 +#include "hash_table.h"
   32.31 +#include "iostream.h"
   32.32 +#include "allocate.h"
   32.33 +
   32.34 +/** @file
   32.35 + * Definitions for rules and sxprs.
   32.36 + */
   32.37 +
   32.38 +#ifndef NULL
   32.39 +#define NULL 0
   32.40 +#endif
   32.41 +
   32.42 +#ifndef TRUE
   32.43 +#define TRUE 1
   32.44 +#endif
   32.45 +
   32.46 +#ifndef FALSE
   32.47 +#define FALSE 0
   32.48 +#endif
   32.49 +
   32.50 +/** Sxpr type. */
   32.51 +typedef int16_t TypeCode;
   32.52 +
   32.53 +/** A typed sxpr handle.*/
   32.54 +typedef struct Sxpr {
   32.55 +    /** Sxpr type. */
   32.56 +    TypeCode type;
   32.57 +    union {
   32.58 +	/** Sxpr value. */
   32.59 +        unsigned long ul;
   32.60 +	/** Pointer. */
   32.61 +        void *ptr;
   32.62 +    } v;
   32.63 +} Sxpr;
   32.64 +
   32.65 +/** Sxpr type to indicate out of memory. */
   32.66 +#define T_NOMEM      ((TypeCode)-1)
   32.67 +/** The 'unspecified' sxpr. */
   32.68 +#define T_NONE       ((TypeCode)0)
   32.69 +/** The empty list. */
   32.70 +#define T_NULL       ((TypeCode)1)
   32.71 +/** Unsigned integer. */
   32.72 +#define T_UINT       ((TypeCode)2)
   32.73 +/** A string. */
   32.74 +#define T_STRING     ((TypeCode)3)
   32.75 +/** An atom. */
   32.76 +#define T_ATOM       ((TypeCode)4)
   32.77 +/** A boolean. */
   32.78 +#define T_BOOL       ((TypeCode)5)
   32.79 +
   32.80 +/** A cons (pair or list). */
   32.81 +#define T_CONS       ((TypeCode)10)
   32.82 +
   32.83 +/** An error. */
   32.84 +#define T_ERR        ((TypeCode)40)
   32.85 +
   32.86 +/** An atom. */
   32.87 +typedef struct ObjAtom {
   32.88 +    Sxpr name;
   32.89 +    Hashcode hashcode;
   32.90 +    int interned;
   32.91 +} ObjAtom;
   32.92 +
   32.93 +/** A cons (pair). */
   32.94 +typedef struct ObjCons {
   32.95 +    Sxpr car;
   32.96 +    Sxpr cdr;
   32.97 +} ObjCons;
   32.98 +
   32.99 +/** A vector. */
  32.100 +typedef struct ObjVector {
  32.101 +    int n;
  32.102 +    Sxpr data[0];
  32.103 +} ObjVector;
  32.104 +
  32.105 +/** Flags for sxpr printing. */
  32.106 +enum PrintFlags {
  32.107 +    PRINT_RAW           = 0x001,
  32.108 +    PRINT_TYPE          = 0x002,
  32.109 +    PRINT_PRETTY        = 0x004,
  32.110 +    PRINT_NUM           = 0x008,
  32.111 +};
  32.112 +
  32.113 +/** An integer sxpr.
  32.114 + *
  32.115 + * @param ty type
  32.116 + * @param val integer value
  32.117 + */
  32.118 +#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }}
  32.119 +
  32.120 +/** A pointer sxpr.
  32.121 + * If the pointer is non-null, returns an sxpr containing it.
  32.122 + * If the pointer is null, returns ONOMEM.
  32.123 + *
  32.124 + * @param ty type
  32.125 + * @param val pointer
  32.126 + */
  32.127 +#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM)
  32.128 +
  32.129 +/** Make an integer sxpr containing a pointer.
  32.130 + *
  32.131 + * @param val pointer
  32.132 + */
  32.133 +#define PTR(val) OBJP(T_UINT, (void*)(val))
  32.134 +
  32.135 +/** Make an integer sxpr.
  32.136 + * @param x value
  32.137 + */
  32.138 +#define OINT(x)       OBJI(T_UINT,  x)
  32.139 +
  32.140 +/** Make an error sxpr.
  32.141 + *
  32.142 + * @param x value
  32.143 + */
  32.144 +#define OERR(x)       OBJI(T_ERR,   x)
  32.145 +
  32.146 +/** Out of memory constant. */
  32.147 +#define ONOMEM        OBJI(T_NOMEM, 0)
  32.148 +
  32.149 +/** The `unspecified' constant. */
  32.150 +#define ONONE         OBJI(T_NONE,  0)
  32.151 +
  32.152 +/** Empty list constant. */
  32.153 +#define ONULL         OBJI(T_NULL,  0)
  32.154 +
  32.155 +/** False constant. */
  32.156 +#define OFALSE        OBJI(T_BOOL,  0)
  32.157 +
  32.158 +/** True constant. */
  32.159 +#define OTRUE         OBJI(T_BOOL,  1)
  32.160 +
  32.161 +/* Recognizers for the various sxpr types.  */
  32.162 +#define ATOMP(obj)        has_type(obj, T_ATOM)
  32.163 +#define BOOLP(obj)        has_type(obj, T_BOOL)
  32.164 +#define CONSP(obj)        has_type(obj, T_CONS)
  32.165 +#define ERRP(obj)         has_type(obj, T_ERR)
  32.166 +#define INTP(obj)         has_type(obj, T_UINT)
  32.167 +#define NOMEMP(obj)       has_type(obj, T_NOMEM)
  32.168 +#define NONEP(obj)        has_type(obj, T_NONE)
  32.169 +#define NULLP(obj)        has_type(obj, T_NULL)
  32.170 +#define STRINGP(obj)      has_type(obj, T_STRING)
  32.171 +
  32.172 +#define TRUEP(obj)    get_ul(obj)
  32.173 +
  32.174 +/** Convert an sxpr to an unsigned integer. */
  32.175 +#define OBJ_UINT(x)   get_ul(x)
  32.176 +/** Convert an sxpr to an integer. */
  32.177 +#define OBJ_INT(x)    (int)get_ul(x)
  32.178 +
  32.179 +/* Conversions of sxprs to their values.
  32.180 + * No checking is done.
  32.181 + */
  32.182 +#define OBJ_STRING(x)  ((char*)get_ptr(x))
  32.183 +#define OBJ_CONS(x)    ((ObjCons*)get_ptr(x))
  32.184 +#define OBJ_ATOM(x)    ((ObjAtom*)get_ptr(x))
  32.185 +#define OBJ_SET(x)     ((ObjSet*)get_ptr(x))
  32.186 +#define CAR(x)         (OBJ_CONS(x)->car)
  32.187 +#define CDR(x)         (OBJ_CONS(x)->cdr)
  32.188 +
  32.189 +#define CAAR(x)        (CAR(CAR(x)))
  32.190 +#define CADR(x)        (CAR(CDR(x)))
  32.191 +#define CDAR(x)        (CDR(CAR(x)))
  32.192 +#define CDDR(x)        (CDR(CDR(x)))
  32.193 +
  32.194 +/** Get the integer value from an sxpr.
  32.195 + *
  32.196 + * @param obj sxpr
  32.197 + * @return value
  32.198 + */
  32.199 +static inline unsigned long get_ul(Sxpr obj){
  32.200 +    return obj.v.ul;
  32.201 +}
  32.202 +
  32.203 +/** Get the pointer value from an sxpr.
  32.204 + *
  32.205 + * @param obj sxpr
  32.206 + * @return value
  32.207 + */
  32.208 +static inline void * get_ptr(Sxpr obj){
  32.209 +    return obj.v.ptr;
  32.210 +}
  32.211 +
  32.212 +/** Create an sxpr containing a pointer.
  32.213 + *
  32.214 + * @param type typecode
  32.215 + * @param val pointer
  32.216 + * @return sxpr
  32.217 + */
  32.218 +static inline Sxpr obj_ptr(TypeCode type, void *val){
  32.219 +    return (Sxpr){ type: type, v: { ptr: val } };
  32.220 +}
  32.221 +
  32.222 +/** Create an sxpr containing an integer.
  32.223 + *
  32.224 + * @param type typecode
  32.225 + * @param val integer
  32.226 + * @return sxpr
  32.227 + */
  32.228 +static inline Sxpr obj_ul(TypeCode type, unsigned long val){
  32.229 +    return (Sxpr){ type: type, v: { ul: val } };
  32.230 +}
  32.231 +
  32.232 +/** Get the type of an sxpr.
  32.233 + *
  32.234 + * @param obj sxpr
  32.235 + * @return type
  32.236 + */
  32.237 +static inline TypeCode get_type(Sxpr obj){
  32.238 +    return obj.type;
  32.239 +}
  32.240 +
  32.241 +/** Check the type of an sxpr.
  32.242 + *
  32.243 + * @param obj sxpr
  32.244 + * @param type to check
  32.245 + * @return 1 if has the type, 0 otherwise
  32.246 + */
  32.247 +static inline int has_type(Sxpr obj, TypeCode type){
  32.248 +    return get_type(obj) == type;
  32.249 +}
  32.250 +
  32.251 +/** Compare sxprs for literal equality of type and value.
  32.252 + *
  32.253 + * @param x sxpr to compare
  32.254 + * @param y sxpr to compare
  32.255 + * @return 1 if equal, 0 otherwise
  32.256 + */
  32.257 +static inline int eq(Sxpr x, Sxpr y){
  32.258 +    return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y)));
  32.259 +}
  32.260 +
  32.261 +/** Checked version of CAR
  32.262 + *
  32.263 + * @param x sxpr
  32.264 + * @return CAR if a cons, x otherwise
  32.265 + */
  32.266 +static inline Sxpr car(Sxpr x){
  32.267 +    return (CONSP(x) ? CAR(x) : x);
  32.268 +}
  32.269 +
  32.270 +/** Checked version of CDR.
  32.271 + *
  32.272 + * @param x sxpr
  32.273 + * @return CDR if a cons, null otherwise
  32.274 + */
  32.275 +static inline Sxpr cdr(Sxpr x){
  32.276 +    return (CONSP(x) ? CDR(x) : ONULL);
  32.277 +}
  32.278 +
  32.279 +/** Allocate some memory and return an sxpr containing it.
  32.280 + * Returns ONOMEM if allocation failed.
  32.281 + *
  32.282 + * @param n number of bytes to allocate
  32.283 + * @param ty typecode
  32.284 + * @return sxpr
  32.285 + */
  32.286 +static inline Sxpr halloc(size_t n,  TypeCode ty){
  32.287 +    return OBJP(ty, allocate(n));
  32.288 +}
  32.289 +
  32.290 +/** Allocate an sxpr containing a pointer to the given type.
  32.291 + *
  32.292 + * @param ty type (uses sizeof to determine how many bytes to allocate)
  32.293 + * @param code typecode
  32.294 + * @return sxpr, ONOMEM if allocation failed
  32.295 + */
  32.296 +#define HALLOC(ty, code) halloc(sizeof(ty), code)
  32.297 +
  32.298 +typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags);
  32.299 +typedef int ObjEqualFn(Sxpr obj, Sxpr other);
  32.300 +typedef void ObjFreeFn(Sxpr obj);
  32.301 +
  32.302 +/** An sxpr type definition. */
  32.303 +typedef struct SxprType {
  32.304 +    TypeCode type;
  32.305 +    char *name;
  32.306 +    int pointer;
  32.307 +    ObjPrintFn *print;
  32.308 +    ObjEqualFn *equal;
  32.309 +    ObjFreeFn *free;
  32.310 +} SxprType;
  32.311 +
  32.312 +
  32.313 +extern SxprType *get_sxpr_type(int ty);
  32.314 +
  32.315 +/** Free the pointer in an sxpr.
  32.316 + *
  32.317 + * @param x sxpr containing a pointer
  32.318 + */
  32.319 +static inline void hfree(Sxpr x){
  32.320 +    deallocate(get_ptr(x));
  32.321 +}
  32.322 +
  32.323 +extern int objprint(IOStream *io, Sxpr x, unsigned flags);
  32.324 +extern int objequal(Sxpr x, Sxpr y);
  32.325 +extern void objfree(Sxpr x);
  32.326 +
  32.327 +extern void cons_free_cells(Sxpr obj);
  32.328 +extern Sxpr intern(char *s);
  32.329 +
  32.330 +extern Sxpr assoc(Sxpr k, Sxpr l);
  32.331 +extern Sxpr assocq(Sxpr k, Sxpr l);
  32.332 +extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l);
  32.333 +extern Sxpr nrev(Sxpr l);
  32.334 +extern Sxpr cons_member(Sxpr l, Sxpr x);
  32.335 +extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
  32.336 +extern int cons_subset(Sxpr s, Sxpr t);
  32.337 +extern int cons_set_equal(Sxpr s, Sxpr t);
  32.338 +
  32.339 +#ifdef USE_GC
  32.340 +extern Sxpr cons_remove(Sxpr l, Sxpr x);
  32.341 +extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
  32.342 +#endif
  32.343 +
  32.344 +extern Sxpr atom_new(char *name);
  32.345 +extern char * atom_name(Sxpr obj);
  32.346 +
  32.347 +extern Sxpr string_new(char *s);
  32.348 +extern char * string_string(Sxpr obj);
  32.349 +extern int string_length(Sxpr obj);
  32.350 +
  32.351 +extern Sxpr cons_new(Sxpr car, Sxpr cdr);
  32.352 +extern int cons_push(Sxpr *list, Sxpr elt);
  32.353 +extern int cons_length(Sxpr obj);
  32.354 +
  32.355 +Sxpr sxpr_name(Sxpr obj);
  32.356 +int sxpr_is(Sxpr obj, char *s);
  32.357 +int sxpr_elementp(Sxpr obj, Sxpr name);
  32.358 +Sxpr sxpr_attributes(Sxpr obj);
  32.359 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def);
  32.360 +Sxpr sxpr_children(Sxpr obj);
  32.361 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def);
  32.362 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def);
  32.363 +Sxpr sxpr_child0(Sxpr obj, Sxpr def);
  32.364 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def);
  32.365 +
  32.366 +/** Create a new atom.
  32.367 + *
  32.368 + * @param s atom name
  32.369 + * @return new atom
  32.370 + */
  32.371 +static inline Sxpr mkatom(char *s){
  32.372 +    return atom_new(s);
  32.373 +}
  32.374 +
  32.375 +/** Create a new string sxpr.
  32.376 + *
  32.377 + * @param s string bytes (copied)
  32.378 + * @return new string
  32.379 + */
  32.380 +static inline Sxpr mkstring(char *s){
  32.381 +    return string_new(s);
  32.382 +}
  32.383 +
  32.384 +/** Create an integer sxpr.
  32.385 + *
  32.386 + * @param i value
  32.387 + * @return sxpr
  32.388 + */
  32.389 +static inline Sxpr mkint(int i){
  32.390 +    return OBJI(T_UINT, i);
  32.391 +}
  32.392 +
  32.393 +/** Create a boolean sxpr.
  32.394 + *
  32.395 + * @param b value
  32.396 + * @return sxpr
  32.397 + */
  32.398 +static inline Sxpr mkbool(int b){
  32.399 +    return OBJI(T_BOOL, (b ? 1 : 0));
  32.400 +}
  32.401 +
  32.402 +/* Constants used in parsing and printing. */
  32.403 +#define k_list_open    "("
  32.404 +#define c_list_open    '('
  32.405 +#define k_list_close   ")"
  32.406 +#define c_list_close   ')'
  32.407 +#define k_true         "true"
  32.408 +#define k_false        "false"
  32.409 +
  32.410 +#define c_var          '$'
  32.411 +#define c_escape       '\\'
  32.412 +#define c_single_quote '\''
  32.413 +#define c_double_quote '"'
  32.414 +#define c_string_open  c_double_quote
  32.415 +#define c_string_close c_double_quote
  32.416 +#define c_data_open    '['
  32.417 +#define c_data_close   ']'
  32.418 +#define c_binary       '*'
  32.419 +#define c_eval         '!'
  32.420 +#define c_concat_open  '{'
  32.421 +#define c_concat_close '}'
  32.422 +
  32.423 +#endif /* ! _XUTIL_SXPR_H_ */
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/tools/libxutil/sxpr_parser.c	Wed Nov 24 12:07:16 2004 +0000
    33.3 @@ -0,0 +1,933 @@
    33.4 +/*
    33.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    33.6 + *
    33.7 + * This library is free software; you can redistribute it and/or modify
    33.8 + * it under the terms of the GNU Lesser General Public License as
    33.9 + * published by the Free Software Foundation; either version 2.1 of the
   33.10 + * License, or  (at your option) any later version. This library is 
   33.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   33.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   33.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   33.14 + * See the GNU Lesser General Public License for more details.
   33.15 + *
   33.16 + * You should have received a copy of the GNU Lesser General Public License
   33.17 + * along with this library; if not, write to the Free Software Foundation,
   33.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   33.19 + */
   33.20 +
   33.21 +#ifdef __KERNEL__
   33.22 +#  include <linux/config.h>
   33.23 +#  include <linux/module.h>
   33.24 +#  include <linux/kernel.h>
   33.25 +#  include <linux/string.h>
   33.26 +#  include <linux/errno.h>
   33.27 +#else
   33.28 +#  include <stdlib.h>
   33.29 +#  include <errno.h>
   33.30 +#endif
   33.31 +
   33.32 +#include "iostream.h"
   33.33 +#include "lexis.h"
   33.34 +#include "sxpr_parser.h"
   33.35 +#include "sys_string.h"
   33.36 +#include "enum.h"
   33.37 +
   33.38 +/** @file
   33.39 + * Sxpr parsing.
   33.40 + *
   33.41 + * So that the parser does not leak memory, all sxprs constructed by
   33.42 + * the parser must be freed on error.  On successful parse the sxpr
   33.43 + * returned becomes the responsibility of the caller.
   33.44 + *
   33.45 + * @author Mike Wray <mike.wray@hpl.hp.com>
   33.46 + */
   33.47 +
   33.48 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
   33.49 +#define printf(fmt, args...)   IOStream_print(iostdout, fmt, ##args)
   33.50 +
   33.51 +static void reset(Parser *z);
   33.52 +static int inputchar(Parser *p, char c);
   33.53 +static int savechar(Parser *p, char c);
   33.54 +extern void parse_error(Parser *in);
   33.55 +extern void parse_error_id(Parser *in, ParseErrorId id);
   33.56 +
   33.57 +static int begin_start(Parser *p, char c);
   33.58 +static int state_start(Parser *p, char c);
   33.59 +static int end_start(Parser *p);
   33.60 +
   33.61 +static int begin_comment(Parser *p, char c);
   33.62 +static int state_comment(Parser *p, char c);
   33.63 +static int end_comment(Parser *p);
   33.64 +
   33.65 +static int begin_string(Parser *p, char c);
   33.66 +static int state_string(Parser *p, char c);
   33.67 +static int end_string(Parser *p);
   33.68 +static int state_escape(Parser *p, char c);
   33.69 +static int state_octal(Parser *p, char c);
   33.70 +static int state_hex(Parser *p, char c);
   33.71 +
   33.72 +static int begin_atom(Parser *p, char c);
   33.73 +static int state_atom(Parser *p, char c);
   33.74 +static int end_atom(Parser *p);
   33.75 +
   33.76 +static int state_list(Parser *p, char c);
   33.77 +static int begin_list(Parser *p, char c);
   33.78 +static int end_list(Parser *p);
   33.79 +
   33.80 +/** Print a parse error.
   33.81 + *
   33.82 + * @param in parser
   33.83 + * @param msg format followed by printf arguments
   33.84 + */
   33.85 +void eprintf(Parser *in, char *msg, ...){
   33.86 +    va_list args;
   33.87 +    if(in->error_out){
   33.88 +        va_start(args, msg);
   33.89 +        IOStream_vprint(in->error_out, msg, args);
   33.90 +        va_end(args);
   33.91 +    }
   33.92 +}
   33.93 +
   33.94 +/** Print a parse warning.
   33.95 + *
   33.96 + * @param in parser
   33.97 + * @param msg format followed by printf arguments
   33.98 + */
   33.99 +void wprintf(Parser *in, char *msg, ...){
  33.100 +    va_list args;
  33.101 +    if(in->error_out){
  33.102 +        va_start(args, msg);
  33.103 +        IOStream_vprint(in->error_out, msg, args);
  33.104 +        va_end(args);
  33.105 +    }
  33.106 +}
  33.107 +
  33.108 +/*============================================================================*/
  33.109 +
  33.110 +/** Record defining the message for a parse error. */
  33.111 +typedef struct {
  33.112 +  ParseErrorId id;
  33.113 +  char *message;
  33.114 +} ParseError;
  33.115 +
  33.116 +/** Format for printing parse error messages. */
  33.117 +#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
  33.118 +
  33.119 +/** Message catalog for the parse error codes. */
  33.120 +static ParseError catalog[] = {
  33.121 +  { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
  33.122 +  { PARSE_ERR_NOMEM,                  "out of memory" },
  33.123 +  { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
  33.124 +  { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
  33.125 +  { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
  33.126 +  { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
  33.127 +  { 0, NULL }
  33.128 +};
  33.129 +
  33.130 +/** Number of entries in the message catalog. */
  33.131 +const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
  33.132 +
  33.133 +void ParserState_free(ParserState *z){
  33.134 +    if(!z) return;
  33.135 +    objfree(z->val);
  33.136 +    deallocate(z);
  33.137 +}
  33.138 +
  33.139 +int ParserState_new(ParserStateFn *fn, char *name,
  33.140 +                    ParserState *parent, ParserState **val){
  33.141 +    int err = 0;
  33.142 +    ParserState *z;
  33.143 +    z = ALLOCATE(ParserState);
  33.144 +    if(z){
  33.145 +        z->name = name;
  33.146 +        z->fn = fn;
  33.147 +        z->parent = parent;
  33.148 +        z->val = ONULL;
  33.149 +    } else {
  33.150 +        err = -ENOMEM;
  33.151 +    }
  33.152 +    if(!err) *val = z;
  33.153 +    return err;
  33.154 +}
  33.155 +
  33.156 +/** Free a parser.
  33.157 + * No-op if the parser is null.
  33.158 + *
  33.159 + * @param z parser 
  33.160 + */
  33.161 +void Parser_free(Parser *z){
  33.162 +    if(!z) return;
  33.163 +    objfree(z->val);
  33.164 +    z->val = ONONE;
  33.165 +    deallocate(z);
  33.166 +}
  33.167 +
  33.168 +/** Create a new parser. The error stream defaults to null.
  33.169 + */
  33.170 +Parser * Parser_new(void){
  33.171 +    Parser *z = ALLOCATE(Parser);
  33.172 +    int err = -ENOMEM;
  33.173 +  
  33.174 +    if(!z) goto exit;
  33.175 +    err = 0;
  33.176 +    reset(z);
  33.177 +  exit:
  33.178 +    if(err){
  33.179 +        Parser_free(z);
  33.180 +        z = NULL;
  33.181 +    }
  33.182 +    return z;
  33.183 +}
  33.184 +
  33.185 +/** Get the next character.
  33.186 + * Records the character read in the parser,
  33.187 + * and sets the line and character counts.
  33.188 + *
  33.189 + * @param p parser
  33.190 + * @return error flag: 0 on success, non-zero on error
  33.191 + */
  33.192 +static int inputchar(Parser *p, char c){
  33.193 +    int err = 0;
  33.194 +    if(c=='\n'){
  33.195 +        p->line_no++;
  33.196 +        p->char_no = 0;
  33.197 +    } else {
  33.198 +        p->char_no++;
  33.199 +    }
  33.200 +    return err;
  33.201 +}
  33.202 +
  33.203 +static int savechar(Parser *p, char c){
  33.204 +    int err = 0;
  33.205 +    if(p->buf_i >= p->buf_n){
  33.206 +        err = -ENOMEM;
  33.207 +        goto exit;
  33.208 +    }
  33.209 +    p->buf[p->buf_i] = c;
  33.210 +    p->buf_i++;
  33.211 +  exit:
  33.212 +    return err;
  33.213 +}
  33.214 +
  33.215 +int Parser_input_char(Parser *p, char c){
  33.216 +    int err = 0;
  33.217 +    if(at_eof(p)){
  33.218 +        //skip;
  33.219 +    } else {
  33.220 +        inputchar(p, c);
  33.221 +    }
  33.222 +    if(!p->state){
  33.223 +        err = begin_start(p, c);
  33.224 +        if(err) goto exit;
  33.225 +    }
  33.226 +    err = p->state->fn(p, c);
  33.227 +  exit:
  33.228 +    return err;
  33.229 +}
  33.230 +
  33.231 +int Parser_input_eof(Parser *p){
  33.232 +    int err = 0;
  33.233 +    p->eof = 1;
  33.234 +    err = Parser_input_char(p, IOSTREAM_EOF);
  33.235 +    return err;
  33.236 +}
  33.237 +
  33.238 +int Parser_input(Parser *p, char *buf, int buf_n){
  33.239 +    int err = 0;
  33.240 +    int i = 0;
  33.241 +    if(buf_n <= 0){
  33.242 +        err = Parser_input_eof(p);
  33.243 +        goto exit;
  33.244 +    }
  33.245 +    for(i = 0; i<buf_n; i++){
  33.246 +        err = Parser_input_char(p, buf[i]);
  33.247 +        if(err) goto exit;
  33.248 +    }
  33.249 +  exit:
  33.250 +    err = (err < 0 ? err : buf_n);
  33.251 +    return err;
  33.252 +}
  33.253 +
  33.254 +int Parser_push(Parser *p, ParserStateFn *fn, char *name){
  33.255 +    int err = 0;
  33.256 +    err = ParserState_new(fn, name, p->state, &p->state);
  33.257 +    return err;
  33.258 +}
  33.259 +        
  33.260 +int Parser_pop(Parser *p){
  33.261 +    int err = 0;
  33.262 +    ParserState *s = p->state;
  33.263 +    p->state = s->parent;
  33.264 +    if (p->start_state == s)
  33.265 +        p->start_state = NULL;
  33.266 +    ParserState_free(s);
  33.267 +    return err;
  33.268 +}
  33.269 +
  33.270 +int Parser_return(Parser *p){
  33.271 +    int err = 0;
  33.272 +    Sxpr val = ONONE;
  33.273 +    if(!p->state){
  33.274 +        err = -EINVAL;
  33.275 +        goto exit;
  33.276 +    }
  33.277 +    val = p->state->val;
  33.278 +    p->state->val = ONONE;
  33.279 +    err = Parser_pop(p);
  33.280 +    if(err) goto exit;
  33.281 +    if(p->state){
  33.282 +        err = cons_push(&p->state->val, val);
  33.283 +    } else {
  33.284 +        val = nrev(val);
  33.285 +        p->val = val;
  33.286 +    }
  33.287 +  exit:
  33.288 +    if(err){
  33.289 +        objfree(val);
  33.290 +    }
  33.291 +    return err;
  33.292 +}
  33.293 +
  33.294 +/** Determine if a character is a separator.
  33.295 + *
  33.296 + * @param p parser
  33.297 + * @param c character to test
  33.298 + * @return 1 if a separator, 0 otherwise
  33.299 + */
  33.300 +static int is_separator(Parser *p, char c){
  33.301 +    return in_sep_class(c);
  33.302 +}
  33.303 +
  33.304 +/** Return the current token.
  33.305 + * The return value points at the internal buffer, so
  33.306 + * it must not be modified (or freed). Use copy_token() if you need a copy.
  33.307 + *
  33.308 + * @param p parser
  33.309 + * @return token
  33.310 + */
  33.311 +char *peek_token(Parser *p){
  33.312 +    return p->buf;
  33.313 +}
  33.314 +
  33.315 +/** Return a copy of the current token.
  33.316 + * The returned value should be freed when finished with.
  33.317 + *
  33.318 + * @param p parser
  33.319 + * @return copy of token
  33.320 + */
  33.321 +char *copy_token(Parser *p){
  33.322 +    return strdup(peek_token(p));
  33.323 +}
  33.324 +
  33.325 +static int do_intern(Parser *p){
  33.326 +    int err = 0;
  33.327 +    Sxpr obj = intern(peek_token(p));
  33.328 +    if(NOMEMP(obj)){
  33.329 +        err = -ENOMEM;
  33.330 +    } else {
  33.331 +        p->state->val = obj;
  33.332 +    }
  33.333 +    return err;
  33.334 +}
  33.335 +
  33.336 +static int do_string(Parser *p){
  33.337 +    int err = 0;
  33.338 +    Sxpr obj;
  33.339 +    obj = string_new(peek_token(p));
  33.340 +    if(NOMEMP(obj)){
  33.341 +        err = -ENOMEM;
  33.342 +    } else {
  33.343 +        p->state->val = obj;
  33.344 +    }
  33.345 +    return err;
  33.346 +}
  33.347 +
  33.348 +void newtoken(Parser *p){
  33.349 +    memset(p->buf, 0, p->buf_n);
  33.350 +    p->buf_i = 0;
  33.351 +    p->tok_begin_line = p->line_no;
  33.352 +    p->tok_begin_char = p->char_no;
  33.353 +}
  33.354 +
  33.355 +int get_escape(char c, char *d){
  33.356 +    int err = 0;
  33.357 +    switch(c){
  33.358 +    case 'a':            *d = '\a'; break;
  33.359 +    case 'b':            *d = '\b'; break;
  33.360 +    case 'f':            *d = '\f'; break;
  33.361 +    case 'n':            *d = '\n'; break;
  33.362 +    case 'r':            *d = '\r'; break;
  33.363 +    case 't':            *d = '\t'; break;
  33.364 +    case 'v':            *d = '\v'; break;
  33.365 +    case c_escape:       *d = c_escape; break;
  33.366 +    case c_single_quote: *d = c_single_quote; break;
  33.367 +    case c_double_quote: *d = c_double_quote; break;
  33.368 +    default:
  33.369 +        err = -EINVAL;
  33.370 +    }
  33.371 +    return err;
  33.372 +}
  33.373 +
  33.374 +int Parser_ready(Parser *p){
  33.375 +    return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));
  33.376 +}
  33.377 +
  33.378 +Sxpr Parser_get_val(Parser *p){
  33.379 +    Sxpr v = ONONE;
  33.380 +    if(CONSP(p->val)){
  33.381 +        v = CAR(p->val);
  33.382 +        p->val = CDR(p->val);
  33.383 +    } else if (CONSP(p->start_state->val)){
  33.384 +        p->val = p->start_state->val;
  33.385 +        p->val = nrev(p->val);
  33.386 +        p->start_state->val = ONULL;
  33.387 +        v = CAR(p->val);
  33.388 +        p->val = CDR(p->val);
  33.389 +    }        
  33.390 +    return v;
  33.391 +}
  33.392 +
  33.393 +Sxpr Parser_get_all(Parser *p){
  33.394 +    Sxpr v = ONULL;
  33.395 +    if(CONSP(p->val)){
  33.396 +        v = p->val;
  33.397 +        p->val = ONONE;
  33.398 +    } else if(p->start_state && CONSP(p->start_state->val)){
  33.399 +        v = p->start_state->val;
  33.400 +        p->start_state->val = ONULL;
  33.401 +        v = nrev(v);
  33.402 +    }
  33.403 +    return v;
  33.404 +}
  33.405 +    
  33.406 +int begin_start(Parser *p, char c){
  33.407 +    int err = 0;
  33.408 +    err = Parser_push(p, state_start, "start");
  33.409 +    if(err) goto exit;
  33.410 +    p->start_state = p->state;
  33.411 +  exit:
  33.412 +    return err;
  33.413 +}
  33.414 +
  33.415 +int state_start(Parser *p, char c){
  33.416 +    int err = 0;
  33.417 +    if(at_eof(p)){
  33.418 +        err = end_start(p);
  33.419 +    } else if(in_space_class(c)){
  33.420 +        //skip
  33.421 +    } else if(in_comment_class(c)){
  33.422 +        begin_comment(p, c);
  33.423 +    } else if(c == c_list_open){
  33.424 +        begin_list(p, c);
  33.425 +    } else if(c == c_list_close){
  33.426 +        parse_error(p);
  33.427 +        err = -EINVAL;
  33.428 +    } else if(in_string_quote_class(c)){
  33.429 +        begin_string(p, c);
  33.430 +    } else if(in_printable_class(c)){
  33.431 +        begin_atom(p, c);
  33.432 +    } else if(c == 0x04){
  33.433 +        //ctrl-D, EOT: end-of-text.
  33.434 +        Parser_input_eof(p);
  33.435 +    } else {
  33.436 +        parse_error(p);
  33.437 +        err = -EINVAL;
  33.438 +    }
  33.439 +    return err;
  33.440 +}
  33.441 +
  33.442 +int end_start(Parser *p){
  33.443 +    int err = 0;
  33.444 +    err = Parser_return(p);
  33.445 +    return err;
  33.446 +}
  33.447 +
  33.448 +int begin_comment(Parser *p, char c){
  33.449 +    int err = 0;
  33.450 +    err = Parser_push(p, state_comment, "comment");
  33.451 +    if(err) goto exit;
  33.452 +    err = inputchar(p, c);
  33.453 +  exit:
  33.454 +    return err;
  33.455 +}
  33.456 +
  33.457 +int state_comment(Parser *p, char c){
  33.458 +    int err = 0;
  33.459 +    if(c == '\n' || at_eof(p)){
  33.460 +        err = end_comment(p);
  33.461 +    } else {
  33.462 +        err = inputchar(p, c);
  33.463 +    }
  33.464 +    return err;
  33.465 +}
  33.466 +
  33.467 +int end_comment(Parser *p){
  33.468 +    return Parser_pop(p);
  33.469 +}
  33.470 +
  33.471 +int begin_string(Parser *p, char c){
  33.472 +    int err = 0;
  33.473 +    err = Parser_push(p, state_string, "string");
  33.474 +    if(err) goto exit;
  33.475 +    newtoken(p);
  33.476 +    p->state->delim = c;
  33.477 +  exit:
  33.478 +    return err;
  33.479 +}
  33.480 +
  33.481 +int state_string(Parser *p, char c){
  33.482 +    int err = 0;
  33.483 +    if(at_eof(p)){
  33.484 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.485 +        err = -EINVAL;
  33.486 +    } else if(c == p->state->delim){
  33.487 +        err = end_string(p);
  33.488 +    } else if(c == '\\'){
  33.489 +        err = Parser_push(p, state_escape, "escape");
  33.490 +    } else {
  33.491 +        err = savechar(p, c);
  33.492 +    }
  33.493 +    return err;
  33.494 +}
  33.495 +
  33.496 +int end_string(Parser *p){
  33.497 +    int err = 0;
  33.498 +    err = do_string(p);
  33.499 +    if(err) goto exit;
  33.500 +    err = Parser_return(p);
  33.501 +  exit:
  33.502 +    return err;
  33.503 +}
  33.504 +
  33.505 +int state_escape(Parser *p, char c){
  33.506 +    int err = 0;
  33.507 +    char d;
  33.508 +    if(at_eof(p)){
  33.509 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.510 +        err = -EINVAL;
  33.511 +        goto exit;
  33.512 +    }
  33.513 +    if(get_escape(c, &d) == 0){
  33.514 +        err = savechar(p, d);
  33.515 +        if(err) goto exit;
  33.516 +        err = Parser_pop(p);
  33.517 +    } else if(c == 'x'){
  33.518 +        p->state->fn = state_hex;
  33.519 +        p->state->ival = 0;
  33.520 +        p->state->count = 0;
  33.521 +    } else {
  33.522 +        p->state->fn = state_octal;
  33.523 +        p->state->ival = 0;
  33.524 +        p->state->count = 0;
  33.525 +        err = Parser_input_char(p, c);
  33.526 +    }
  33.527 +  exit:
  33.528 +    return err;
  33.529 +}
  33.530 +
  33.531 +int octaldone(Parser *p){
  33.532 +    int err = 0;
  33.533 +    char d = (char)(p->state->ival & 0xff);
  33.534 +    err = Parser_pop(p);
  33.535 +    if(err) goto exit;
  33.536 +    err = Parser_input_char(p, d);
  33.537 +  exit:
  33.538 +    return err;
  33.539 +}
  33.540 +
  33.541 +int octaldigit(Parser *p, char c){
  33.542 +    int err = 0;
  33.543 +    p->state->ival *= 8;
  33.544 +    p->state->ival += c - '0'; 
  33.545 +    p->state->count++;
  33.546 +    if(err) goto exit;
  33.547 +    if(p->state->ival < 0 || p->state->ival > 0xff){
  33.548 +        parse_error(p);
  33.549 +        err = -EINVAL;
  33.550 +        goto exit;
  33.551 +    }
  33.552 +    if(p->state->count == 3){
  33.553 +        err = octaldone(p);
  33.554 +    }
  33.555 +  exit:
  33.556 +    return err;
  33.557 +}
  33.558 +
  33.559 +int state_octal(Parser *p, char c){
  33.560 +    int err = 0;
  33.561 +    if(at_eof(p)){
  33.562 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.563 +        err = -EINVAL;
  33.564 +        goto exit;
  33.565 +    } else if('0' <= c && c <= '7'){
  33.566 +        err = octaldigit(p, c);
  33.567 +    } else {
  33.568 +        err = octaldone(p);
  33.569 +        if(err) goto exit;
  33.570 +        Parser_input_char(p, c);
  33.571 +    }
  33.572 +  exit:
  33.573 +    return err;
  33.574 +}
  33.575 +
  33.576 +int hexdone(Parser *p){
  33.577 +    int err = 0;
  33.578 +    char d = (char)(p->state->ival & 0xff);
  33.579 +    err = Parser_pop(p);
  33.580 +    if(err) goto exit;
  33.581 +    err = Parser_input_char(p, d);
  33.582 +  exit:
  33.583 +    return err;
  33.584 +}
  33.585 +    
  33.586 +int hexdigit(Parser *p, char c, char d){
  33.587 +    int err = 0;
  33.588 +    p->state->ival *= 16;
  33.589 +    p->state->ival += c - d; 
  33.590 +    p->state->count++;
  33.591 +    if(err) goto exit;
  33.592 +    if(p->state->ival < 0 || p->state->ival > 0xff){
  33.593 +        parse_error(p);
  33.594 +        err = -EINVAL;
  33.595 +        goto exit;
  33.596 +    }
  33.597 +    if(p->state->count == 2){
  33.598 +        err = hexdone(p);
  33.599 +    }
  33.600 +  exit:
  33.601 +    return err;
  33.602 +}
  33.603 +    
  33.604 +int state_hex(Parser *p, char c){
  33.605 +    int err = 0;
  33.606 +    if(at_eof(p)){
  33.607 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.608 +        err = -EINVAL;
  33.609 +        goto exit;
  33.610 +    } else if('0' <= c && c <= '9'){
  33.611 +        err = hexdigit(p, c, '0');
  33.612 +    } else if('A' <= c && c <= 'F'){
  33.613 +        err = hexdigit(p, c, 'A');
  33.614 +    } else if('a' <= c && c <= 'f'){
  33.615 +        err = hexdigit(p, c, 'a');
  33.616 +    } else if(p->state->count){
  33.617 +        err =hexdone(p);
  33.618 +        if(err) goto exit;
  33.619 +        Parser_input_char(p, c);
  33.620 +    }
  33.621 +  exit:
  33.622 +    return err;
  33.623 +}
  33.624 +
  33.625 +int begin_atom(Parser *p, char c){
  33.626 +    int err = 0;
  33.627 +    err = Parser_push(p, state_atom, "atom");
  33.628 +    if(err) goto exit;
  33.629 +    newtoken(p);
  33.630 +    err = savechar(p, c);
  33.631 +  exit:
  33.632 +    return err;
  33.633 +}
  33.634 +
  33.635 +int state_atom(Parser *p, char c){
  33.636 +    int err = 0;
  33.637 +    if(at_eof(p)){
  33.638 +        err = end_atom(p);
  33.639 +    } else if(is_separator(p, c) ||
  33.640 +              in_space_class(c) ||
  33.641 +              in_comment_class(c)){
  33.642 +        err = end_atom(p);
  33.643 +        if(err) goto exit;
  33.644 +        err = Parser_input_char(p, c);
  33.645 +    } else {
  33.646 +        err = savechar(p, c);
  33.647 +    }
  33.648 +  exit:
  33.649 +    return err;
  33.650 +}
  33.651 +
  33.652 +int end_atom(Parser *p){
  33.653 +    int err = 0;
  33.654 +    err = do_intern(p);
  33.655 +    if(err) goto exit;
  33.656 +    err = Parser_return(p);
  33.657 +  exit:
  33.658 +    return err;
  33.659 +}
  33.660 +
  33.661 +int state_list(Parser *p, char c){
  33.662 +    int err = 0;
  33.663 +    if(at_eof(p)){
  33.664 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.665 +        err = -EINVAL;
  33.666 +    } else if(c == c_list_close){
  33.667 +        p->state->val = nrev(p->state->val);
  33.668 +        err = end_list(p);
  33.669 +    } else {
  33.670 +        err = state_start(p, c);
  33.671 +    }
  33.672 +    return err;
  33.673 +    
  33.674 +}
  33.675 +
  33.676 +int begin_list(Parser *p, char c){
  33.677 +    return Parser_push(p, state_list, "list");
  33.678 +}
  33.679 +
  33.680 +int end_list(Parser *p){
  33.681 +    return Parser_return(p);
  33.682 +}
  33.683 +
  33.684 +/** Reset the fields of a parser to initial values.
  33.685 + *
  33.686 + * @param z parser
  33.687 + */
  33.688 +static void reset(Parser *z){
  33.689 +  IOStream *error_out = z->error_out;
  33.690 +  int flags = z->flags;
  33.691 +  memzero(z, sizeof(Parser));
  33.692 +  z->buf_n = sizeof(z->buf) - 1;
  33.693 +  z->buf_i = 0;
  33.694 +  z->line_no = 1;
  33.695 +  z->char_no = 0;
  33.696 +  z->error_out = error_out;
  33.697 +  z->flags = flags;
  33.698 +}
  33.699 +
  33.700 +/** Set the parser error stream.
  33.701 + * Parse errors are reported on the the error stream if it is non-null.
  33.702 + * 
  33.703 + * @param z parser
  33.704 + * @param error_out error stream
  33.705 + */
  33.706 +void set_error_stream(Parser *z, IOStream *error_out){
  33.707 +  if(z){
  33.708 +    z->error_out = error_out;
  33.709 +  }
  33.710 +}
  33.711 +
  33.712 +/** Get the parser error message for an error code.
  33.713 + *
  33.714 + * @param id error code
  33.715 + * @return error message (empty string if the code is unknown)
  33.716 + */
  33.717 +static char *get_message(ParseErrorId id){
  33.718 +  int i;
  33.719 +  for(i=0; i<catalog_n; i++){
  33.720 +    if(id == catalog[i].id){
  33.721 +      return catalog[i].message;
  33.722 +    }
  33.723 +  }
  33.724 +  return "";
  33.725 +}
  33.726 +
  33.727 +/** Get the line number.
  33.728 + *
  33.729 + * @param in parser
  33.730 + */
  33.731 +int get_line(Parser *in){
  33.732 +  return in->line_no;
  33.733 +}
  33.734 +
  33.735 +/** Get the column number.
  33.736 + *
  33.737 + * @param in parser
  33.738 + */
  33.739 +int get_column(Parser *in){
  33.740 +  return in->char_no;
  33.741 +}
  33.742 +
  33.743 +/** Get the line number the current token started on.
  33.744 + *
  33.745 + * @param in parser
  33.746 + */
  33.747 +int get_tok_line(Parser *in){
  33.748 +  return in->tok_begin_line;
  33.749 +}
  33.750 +
  33.751 +/** Get the column number the current token started on.
  33.752 + *
  33.753 + * @param in parser
  33.754 + */
  33.755 +int get_tok_column(Parser *in){
  33.756 +  return in->tok_begin_char;
  33.757 +}
  33.758 +
  33.759 +/** Report a parse error.
  33.760 + * Does nothing if the error stream is null or there is no error.
  33.761 + *
  33.762 + * @param in parser
  33.763 + */
  33.764 +static void report_error(Parser *in){
  33.765 +  if(in->error_out && in->err){
  33.766 +    char *msg = get_message(in->err);
  33.767 +    char *tok = peek_token(in);
  33.768 +    IOStream_print(in->error_out, PARSE_ERR_FMT,
  33.769 +		   get_tok_line(in), get_tok_column(in), msg);
  33.770 +    if(tok && tok[0]){
  33.771 +        IOStream_print(in->error_out, " '%s'", tok);
  33.772 +    }
  33.773 +    IOStream_print(in->error_out, "\n");
  33.774 +  }
  33.775 +}
  33.776 +
  33.777 +/** Get the error message for the current parse error code.
  33.778 + * Does nothing if there is no error.
  33.779 + *
  33.780 + * @param in parser
  33.781 + * @param buf where to place the message
  33.782 + * @param n maximum number of characters to place in buf
  33.783 + * @return current error code (zero for no error)
  33.784 + */
  33.785 +int parse_error_message(Parser *in, char *buf, int n){
  33.786 +    if(in->err){
  33.787 +        char *msg = get_message(in->err);
  33.788 +        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
  33.789 +    }
  33.790 +    return in->err;
  33.791 +}
  33.792 +
  33.793 +/** Flag an unspecified parse error. All subsequent reads will fail.
  33.794 + *
  33.795 + * @param in parser
  33.796 + */
  33.797 +void parse_error(Parser *in){
  33.798 +    parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
  33.799 +}
  33.800 +
  33.801 +/** Flag a parse error. All subsequent reads will fail.
  33.802 + * Does not change the parser error code if it is already set.
  33.803 + *
  33.804 + * @param in parser
  33.805 + * @param id error code
  33.806 + */
  33.807 +void parse_error_id(Parser *in, ParseErrorId id){
  33.808 +    if(!in->err){
  33.809 +        in->err = id;
  33.810 +        report_error(in);
  33.811 +    }
  33.812 +}
  33.813 +
  33.814 +/** Test if the parser's error flag is set.
  33.815 + *
  33.816 + * @param in parser
  33.817 + * @return 1 if set, 0 otherwise
  33.818 + */
  33.819 +int has_error(Parser *in){
  33.820 +    return (in->err > 0);
  33.821 +}
  33.822 +
  33.823 +/** Test if the parser is at end of input.
  33.824 + *
  33.825 + * @param in parser
  33.826 + * @return 1 if at EOF, 0 otherwise
  33.827 + */
  33.828 +int at_eof(Parser *p){
  33.829 +    return p->eof;
  33.830 +}
  33.831 +
  33.832 +#ifdef SXPR_PARSER_MAIN
  33.833 +/* Stuff for standalone testing. */
  33.834 +
  33.835 +#include "file_stream.h"
  33.836 +#include "string_stream.h"
  33.837 +
  33.838 +extern int stringof(Sxpr exp, char **s);
  33.839 +int child_string(Sxpr exp, Sxpr key, char **s){
  33.840 +    int err = 0;
  33.841 +    Sxpr val = sxpr_child_value(exp, key, ONONE);
  33.842 +    err = stringof(val, s);
  33.843 +    return err;
  33.844 +}
  33.845 +
  33.846 +extern int intof(Sxpr exp, int *v);
  33.847 +int child_int(Sxpr exp, Sxpr key, int *v){
  33.848 +    int err = 0;
  33.849 +    Sxpr val = sxpr_child_value(exp, key, ONONE);
  33.850 +    err = intof(val, v);
  33.851 +    return err;
  33.852 +}
  33.853 +
  33.854 +int eval_vnet(Sxpr exp){
  33.855 +    int err = 0;
  33.856 +    Sxpr oid = intern("id");
  33.857 +    int id;
  33.858 +    err = child_int(exp, oid, &id);
  33.859 +    if(err) goto exit;
  33.860 +    dprintf("> vnet id=%d\n", id);
  33.861 + exit:
  33.862 +    dprintf("< err=%d\n", err);
  33.863 +    return err;
  33.864 +}
  33.865 +
  33.866 +int eval_connect(Sxpr exp){
  33.867 +    int err = 0;
  33.868 +    Sxpr ovif = intern("vif");
  33.869 +    Sxpr ovnet = intern("vnet");
  33.870 +    char *vif;
  33.871 +    int vnet;
  33.872 +
  33.873 +    err = child_string(exp, ovif, &vif);
  33.874 +    if(err) goto exit;
  33.875 +    err = child_int(exp, ovnet, &vnet);
  33.876 +    if(err) goto exit;
  33.877 +    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
  33.878 + exit:
  33.879 +    dprintf("< err=%d\n", err);
  33.880 +    return err;
  33.881 +}
  33.882 +
  33.883 +int eval(Sxpr exp){
  33.884 +    int err = 0;
  33.885 +    Sxpr oconnect = intern("connect");
  33.886 +    Sxpr ovnet = intern("vnet");
  33.887 +    
  33.888 +    if(sxpr_elementp(exp, ovnet)){
  33.889 +        err = eval_vnet(exp);
  33.890 +    } else if(sxpr_elementp(exp, oconnect)){
  33.891 +        err = eval_connect(exp);
  33.892 +    } else {
  33.893 +        err = -EINVAL;
  33.894 +    }
  33.895 +    return err;
  33.896 +}
  33.897 +
  33.898 +/** Main program for testing.
  33.899 + * Parses input and prints it.
  33.900 + *
  33.901 + * @param argc number of arguments
  33.902 + * @param argv arguments
  33.903 + * @return error code
  33.904 + */
  33.905 +int main(int argc, char *argv[]){
  33.906 +    Parser *pin;
  33.907 +    int err = 0;
  33.908 +    char buf[1024];
  33.909 +    int k;
  33.910 +    Sxpr obj;
  33.911 +    //Sxpr l, x;
  33.912 +    int i = 0;
  33.913 +
  33.914 +    pin = Parser_new();
  33.915 +    set_error_stream(pin, iostdout);
  33.916 +    dprintf("> parse...\n");
  33.917 +    while(1){
  33.918 +        k = fread(buf, 1, 1, stdin);
  33.919 +        err = Parser_input(pin, buf, k);
  33.920 +        while(Parser_ready(pin)){
  33.921 +            obj = Parser_get_val(pin);
  33.922 +            printf("obj %d\n", i++);
  33.923 +            objprint(iostdout, obj, 0); printf("\n");
  33.924 +        }
  33.925 +        if(k <= 0) break;
  33.926 +    }
  33.927 +/*     obj = Parser_get_all(pin); */
  33.928 +/*     for(l = obj ; CONSP(l); l = CDR(l)){ */
  33.929 +/*         x = CAR(l); */
  33.930 +/*         objprint(iostdout, x, 0); printf("\n"); */
  33.931 +/*         eval(x); */
  33.932 +/*     } */
  33.933 +    dprintf("> err=%d\n", err);
  33.934 +    return 0;
  33.935 +}
  33.936 +#endif
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/tools/libxutil/sxpr_parser.h	Wed Nov 24 12:07:16 2004 +0000
    34.3 @@ -0,0 +1,134 @@
    34.4 +/*
    34.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    34.6 + *
    34.7 + * This library is free software; you can redistribute it and/or modify
    34.8 + * it under the terms of the GNU Lesser General Public License as
    34.9 + * published by the Free Software Foundation; either version 2.1 of the
   34.10 + * License, or  (at your option) any later version. This library is 
   34.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   34.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   34.14 + * See the GNU Lesser General Public License for more details.
   34.15 + *
   34.16 + * You should have received a copy of the GNU Lesser General Public License
   34.17 + * along with this library; if not, write to the Free Software Foundation,
   34.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   34.19 + */
   34.20 +
   34.21 +#ifndef _XUTIL_SXPR_PARSER_H_
   34.22 +#define _XUTIL_SXPR_PARSER_H_
   34.23 +
   34.24 +#include "sxpr.h"
   34.25 +#include "iostream.h"
   34.26 +
   34.27 +/** @file
   34.28 + * Sxpr parsing definitions.
   34.29 + */
   34.30 +
   34.31 +/** Size of a parser input buffer.
   34.32 + * Tokens read must fit into this size (including trailing null).
   34.33 + */
   34.34 +#define PARSER_BUF_SIZE 1024
   34.35 +
   34.36 +struct Parser;
   34.37 +typedef int ParserStateFn(struct Parser *, char c);
   34.38 +
   34.39 +typedef struct ParserState {
   34.40 +    struct ParserState *parent;
   34.41 +    Sxpr val;
   34.42 +    int ival;
   34.43 +    int count;
   34.44 +    char delim;
   34.45 +    ParserStateFn *fn;
   34.46 +    char *name;
   34.47 +} ParserState;
   34.48 +
   34.49 +/** Structure representing an input source for the parser.
   34.50 + * Can read from any IOStream implementation.
   34.51 + */
   34.52 +typedef struct Parser {
   34.53 +    Sxpr val;
   34.54 +    /** Error reporting stream (null for no reports). */
   34.55 +    IOStream *error_out;
   34.56 +    int eof;
   34.57 +    /** Error flag. Non-zero if there has been a read error. */
   34.58 +    int err;
   34.59 +    /** Line number on input (from 1). */
   34.60 +    int line_no;
   34.61 +    /** Column number of input (reset on new line). */
   34.62 +    int char_no;
   34.63 +    /** Lookahead character. */
   34.64 +    char c;
   34.65 +    /** Buffer for reading tokens. */
   34.66 +    char buf[PARSER_BUF_SIZE];
   34.67 +    /** Size of token buffer. */
   34.68 +    int buf_n;
   34.69 +    int buf_i;
   34.70 +    /** Line the last token started on. */
   34.71 +    int tok_begin_line;
   34.72 +    /** Character number the last token started on. */
   34.73 +    int tok_begin_char;
   34.74 +    /** Parsing flags. */
   34.75 +    int flags;
   34.76 +    ParserState *state;
   34.77 +    ParserState *start_state;
   34.78 +} Parser;
   34.79 +
   34.80 +/** Parser error codes. */
   34.81 +typedef enum {
   34.82 +    PARSE_ERR_NONE=0,
   34.83 +    PARSE_ERR_UNSPECIFIED,
   34.84 +    PARSE_ERR_NOMEM,
   34.85 +    PARSE_ERR_UNEXPECTED_EOF,
   34.86 +    PARSE_ERR_TOKEN_TOO_LONG,
   34.87 +    PARSE_ERR_INVALID_SYNTAX,
   34.88 +    PARSE_ERR_INVALID_ESCAPE,
   34.89 +} ParseErrorId;
   34.90 +
   34.91 +
   34.92 +/** Parser flags. */
   34.93 +//enum {
   34.94 +//};
   34.95 +
   34.96 +/** Raise some parser flags.
   34.97 + *
   34.98 + * @param in parser
   34.99 + * @param flags flags mask
  34.100 + */
  34.101 +inline static void parser_flags_raise(Parser *in, int flags){
  34.102 +    in->flags |= flags;
  34.103 +}
  34.104 +
  34.105 +/** Lower some parser flags.
  34.106 + *
  34.107 + * @param in parser
  34.108 + * @param flags flags mask
  34.109 + */
  34.110 +inline static void parser_flags_lower(Parser *in, int flags){
  34.111 +    in->flags &= ~flags;
  34.112 +}
  34.113 +
  34.114 +/** Clear all parser flags.
  34.115 + *
  34.116 + * @param in parser
  34.117 + */
  34.118 +inline static void parser_flags_clear(Parser *in){
  34.119 +    in->flags = 0;
  34.120 +}
  34.121 +
  34.122 +extern void Parser_free(Parser *z);
  34.123 +extern Parser * Parser_new(void);
  34.124 +extern int Parser_input(Parser *p, char *buf, int buf_n);
  34.125 +extern int Parser_input_eof(Parser *p);
  34.126 +extern int Parser_input_char(Parser *p, char c);
  34.127 +extern void set_error_stream(Parser *z, IOStream *error_out);
  34.128 +
  34.129 +extern int parse_error_message(Parser *in, char *buf, int n);
  34.130 +extern int has_error(Parser *in);
  34.131 +extern int at_eof(Parser *in);
  34.132 +
  34.133 +int Parser_ready(Parser *p);
  34.134 +Sxpr Parser_get_val(Parser *p);
  34.135 +Sxpr Parser_get_all(Parser *p);
  34.136 +
  34.137 +#endif /* ! _XUTIL_SXPR_PARSER_H_ */
    35.1 --- a/tools/libxutil/sys_net.c	Wed Nov 24 11:51:49 2004 +0000
    35.2 +++ b/tools/libxutil/sys_net.c	Wed Nov 24 12:07:16 2004 +0000
    35.3 @@ -232,21 +232,17 @@ char *get_port_service(unsigned long por
    35.4  int convert_service_to_port(const char *s, unsigned long *port){
    35.5      int err = 0;
    35.6      unsigned long value;
    35.7 -    printf("%s> %s\n", __FUNCTION__, s);
    35.8      if(convert_atoul(s, &value) == 0){
    35.9          int ok = (0 <= value) && (value <= PORT_MAX);
   35.10 -        printf("> value = %ld\n", value);
   35.11          if(ok){
   35.12              value = htons((unsigned short)value);
   35.13          } else {
   35.14              err = -EINVAL;
   35.15          }
   35.16      } else {
   35.17 -        printf("> get_service_port...\n");
   35.18          err = get_service_port(s, &value);
   35.19      }
   35.20      *port = (err ? 0: value);
   35.21 -    printf("%s< err=%d\n", __FUNCTION__, err);
   35.22      return err;
   35.23  }
   35.24  
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/tools/libxutil/util.c	Wed Nov 24 12:07:16 2004 +0000
    36.3 @@ -0,0 +1,106 @@
    36.4 +/*
    36.5 + * Copyright (C) 2002 - 2004 Mike Wray <mike.wray@hp.com>.
    36.6 + *
    36.7 + * This library is free software; you can redistribute it and/or modify
    36.8 + * it under the terms of the GNU Lesser General Public License as
    36.9 + * published by the Free Software Foundation; either version 2.1 of the
   36.10 + * License, or  (at your option) any later version. This library is 
   36.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   36.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   36.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   36.14 + * See the GNU Lesser General Public License for more details.
   36.15 + *
   36.16 + * You should have received a copy of the GNU Lesser General Public License
   36.17 + * along with this library; if not, write to the Free Software Foundation,
   36.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   36.19 + */
   36.20 +
   36.21 +#include "sys_net.h"
   36.22 +#include "sys_string.h"
   36.23 +
   36.24 +#ifndef __KERNEL__
   36.25 +#  include <grp.h>   
   36.26 +#  include <pwd.h>  
   36.27 +#endif
   36.28 +
   36.29 +#include "util.h"
   36.30 +
   36.31 +
   36.32 +/** @file Various utility functions.
   36.33 + */
   36.34 +
   36.35 +/** Print an address (in network order) as an IPv4 address string
   36.36 + * in dot notation.
   36.37 + *
   36.38 + * @param io where to print address
   36.39 + * @param address to print (in network order)
   36.40 + * @return bytes printed
   36.41 + */
   36.42 +int print_address(IOStream *io, unsigned long address){
   36.43 +#ifdef __KERNEL__
   36.44 +    address = ntohl(address);
   36.45 +    return IOStream_print(io, "%u.%u.%u.%u", 
   36.46 +                          (unsigned)((address >> 24) & 0xff),
   36.47 +                          (unsigned)((address >> 16) & 0xff),
   36.48 +                          (unsigned)((address >>  8) & 0xff),
   36.49 +                          (unsigned)((address      ) & 0xff));
   36.50 +#else
   36.51 +    struct in_addr inaddr = { s_addr: address };
   36.52 +    return IOStream_print(io, inet_ntoa(inaddr));
   36.53 +#endif
   36.54 +}
   36.55 +
   36.56 +/** Get the protocol number for a protocol.
   36.57 + *
   36.58 + * @param name protocol name
   36.59 + * @param protocol where to put the protocol number
   36.60 + * @return 0 if OK, error otherwise
   36.61 + */  
   36.62 +int get_protocol_number(char *name, unsigned long *protocol){
   36.63 +#ifdef __KERNEL__
   36.64 +    return -1;
   36.65 +#else
   36.66 +    struct protoent *proto = getprotobyname(name);
   36.67 +    if(!proto){
   36.68 +	return -1;
   36.69 +    }
   36.70 +    *protocol = proto->p_proto;
   36.71 +    return 0;
   36.72 +#endif
   36.73 +}
   36.74 +
   36.75 +/** Get the protocol name for a protocol number.
   36.76 + *
   36.77 + * @param protocol number
   36.78 + * @return name or null
   36.79 + */
   36.80 +char *get_protocol_name(unsigned long protocol){
   36.81 +#ifdef __KERNEL__
   36.82 +    return 0;
   36.83 +#else
   36.84 +    struct protoent *proto = getprotobynumber(protocol);
   36.85 +    if(!proto){
   36.86 +	return 0;
   36.87 +    }
   36.88 +    return proto->p_name;
   36.89 +#endif
   36.90 +}
   36.91 +
   36.92 +/** Get the host name for an address.
   36.93 + *
   36.94 + * @param addr address
   36.95 + * @return host name or null
   36.96 + */
   36.97 +char *get_host_name(unsigned long addr){
   36.98 +#ifdef __KERNEL__
   36.99 +    return 0;
  36.100 +#else
  36.101 +    struct in_addr inaddr;
  36.102 +    struct hostent *host = 0;
  36.103 +
  36.104 +    inaddr.s_addr = addr;
  36.105 +    host = gethostbyaddr((char*)&inaddr, sizeof(inaddr), AF_INET);
  36.106 +    if(!host) return NULL;
  36.107 +    return host->h_name;
  36.108 +#endif
  36.109 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/tools/libxutil/util.h	Wed Nov 24 12:07:16 2004 +0000
    37.3 @@ -0,0 +1,28 @@
    37.4 +/*
    37.5 + * Copyright (C) 2002 - 2004 Mike Wray <mike.wray@hp.com>.
    37.6 + *
    37.7 + * This library is free software; you can redistribute it and/or modify
    37.8 + * it under the terms of the GNU Lesser General Public License as
    37.9 + * published by the Free Software Foundation; either version 2.1 of the
   37.10 + * License, or  (at your option) any later version. This library is 
   37.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   37.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   37.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   37.14 + * See the GNU Lesser General Public License for more details.
   37.15 + *
   37.16 + * You should have received a copy of the GNU Lesser General Public License
   37.17 + * along with this library; if not, write to the Free Software Foundation,
   37.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   37.19 + */
   37.20 +
   37.21 +#ifndef _XEN_LIB_UTIL_H_
   37.22 +#define _XEN_LIB_UTIL_H_
   37.23 +
   37.24 +#include "iostream.h"
   37.25 +
   37.26 +extern int print_address(IOStream *io, unsigned long address);
   37.27 +extern int get_protocol_number(char *name, unsigned long *protocol);
   37.28 +extern char *get_protocol_name(unsigned long protocol);
   37.29 +extern char *get_host_name(unsigned long addr);
   37.30 +
   37.31 +#endif /* ! _XEN_LIB_UTIL_H_ */
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/tools/vnet/00README	Wed Nov 24 12:07:16 2004 +0000
    38.3 @@ -0,0 +1,10 @@
    38.4 +This directory contains the implementation of vnets:
    38.5 +virtual private networks for virtual machines.
    38.6 +See doc/ for more information and examples/ for example
    38.7 +configurations.
    38.8 +
    38.9 +The kernel module is in vnet-module/ and the vnet forwarding
   38.10 +daemon is in vnetd/. The vnetd daemon makes vnets work across
   38.11 +subnets when multicast routing is not available.
   38.12 +
   38.13 +Mike Wray <mike.wray@hp.com>
   38.14 \ No newline at end of file
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/tools/vnet/Makefile	Wed Nov 24 12:07:16 2004 +0000
    39.3 @@ -0,0 +1,42 @@
    39.4 +
    39.5 +export LINUX_RELEASE ?=2.6
    39.6 +
    39.7 +all: compile
    39.8 +
    39.9 +compile: vnetd vnet-module
   39.10 +
   39.11 +gc.tar.gz:
   39.12 +	wget http://www.hpl.hp.com/personal/Hans_Boehm/gc/gc_source/$@
   39.13 +
   39.14 +gc: gc.tar.gz
   39.15 +	tar xfz gc.tar.gz
   39.16 +	ln -sf gc?.? gc
   39.17 +
   39.18 +gc-install: gc
   39.19 +	(cd gc && ./configure --prefix=`pwd`/install && make && make install)
   39.20 +
   39.21 +gc-clean:
   39.22 +	-$(MAKE) -C gc clean
   39.23 +
   39.24 +gc-pristine:
   39.25 +	-rm -rf gc?.? gc
   39.26 +
   39.27 +.PHONY: vnetd vnet-module install dist clean
   39.28 +
   39.29 +vnetd: gc-install
   39.30 +	$(MAKE) -C vnetd
   39.31 +
   39.32 +vnet-module:
   39.33 +	$(MAKE) -C vnet-module
   39.34 +
   39.35 +install: compile
   39.36 +	$(MAKE) -C vnetd install
   39.37 +	$(MAKE) -C vnet-module install
   39.38 +	$(MAKE) -C examples install
   39.39 +
   39.40 +dist: $(TARGET)
   39.41 +	$(MAKE) prefix=`pwd`/../../install dist=yes install
   39.42 +
   39.43 +clean:
   39.44 +	-$(MAKE) -C vnetd clean
   39.45 +	-$(MAKE) -C vnet-module clean
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/tools/vnet/doc/vnet-module.txt	Wed Nov 24 12:07:16 2004 +0000
    40.3 @@ -0,0 +1,50 @@
    40.4 +Vnet Module Command Interface
    40.5 +Mike Wray <mike.wray@hp.com>
    40.6 +2004/09/17
    40.7 +
    40.8 +When insmod the vnet-module creates /proc/vnet/policy which
    40.9 +can be used to control the module by writing commands into it.
   40.10 +The return code from the command should be returned by close.
   40.11 +
   40.12 +The commands are:
   40.13 +
   40.14 +(vnet.add (id <id>) [(security { none | auth | conf } )] )
   40.15 +
   40.16 +Create the vnet with id <id> and the given security level (default none).
   40.17 +Security levels:
   40.18 +- none: no security
   40.19 +- auth: message authentication (IPSEC hmac)
   40.20 +- conf: message confidentiality (IPSEC hmac and encryption)
   40.21 +
   40.22 +(vnet.del (id <id>))
   40.23 +
   40.24 +Delete the vnet with id <id>.
   40.25 +
   40.26 +(vif.add (vnet <vnetid>) (vmac <macaddr>))
   40.27 +
   40.28 +Add the vif with MAC address <macaddr> to the vnet with id <vnetid>.
   40.29 +This makes the vnet module respond to VARP requests for <macaddr>
   40.30 +on vnet <vnetid>.
   40.31 +
   40.32 +(vif.del (vnet <vnetid>) (vmac <macaddr>))
   40.33 +
   40.34 +Remove the vif with MAC address <macaddr> from the vnet with id <vnetid>.
   40.35 +The vnet module will stop responding to VARP for the vif.
   40.36 +
   40.37 +Examples:
   40.38 +
   40.39 +To create vnet 10 with no security:
   40.40 +
   40.41 +echo '(vnet.add (id 10))' > /proc/vnet/policy
   40.42 +
   40.43 +To create vnet 11 with message authentication:
   40.44 +
   40.45 +echo '(vnet.add (id 11) (security auth))' > /proc/vnet/policy
   40.46 +
   40.47 +To add the vif with vmac "aa:00:00:bc:34:ae" to vnet 10:
   40.48 +
   40.49 +echo '(vif.add (vnet 10) (vmac aa:00:00:bc:34:ae))' > /proc/vnet/policy
   40.50 +
   40.51 +To remove the vif from the vnet:
   40.52 +
   40.53 +echo '(vif.del (vnet 10) (vmac aa:00:00:bc:34:ae))' > /proc/vnet/policy
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/tools/vnet/doc/vnet-xend.txt	Wed Nov 24 12:07:16 2004 +0000
    41.3 @@ -0,0 +1,140 @@
    41.4 +
    41.5 +Vnets: Virtual Networks for Virtual Machines
    41.6 +
    41.7 +Mike Wray <mike.wray@hp.com>
    41.8 +
    41.9 +0) Introduction
   41.10 +---------------
   41.11 +
   41.12 +Vnets provide virtual private LANs for virtual machines.
   41.13 +This is done using bridging and tunneling. A virtual interface
   41.14 +on a vnet can only see other interfaces on the same vnet - it cannot
   41.15 +see the real network, and the real network cannot see it either.
   41.16 +
   41.17 +Virtual interfaces on the same vnet can be on the same machine
   41.18 +or on different machines, they can still talk. The hosting machines
   41.19 +can even be on different subnets if you run vnetd to forward,
   41.20 +or have multicast routing enabled.
   41.21 +
   41.22 +
   41.23 +1) Installing vnet support
   41.24 +--------------------------
   41.25 +
   41.26 +Assuming the code has been installed (make install in the parent directory),
   41.27 +configure xend to use 'network-vnet' instead of the default 'network' to
   41.28 +start up networking. This just loads the vnet module when networking starts.
   41.29 +
   41.30 +In /etc/xend/xend-config.sxp:
   41.31 +
   41.32 +Configure the network script:
   41.33 +
   41.34 +(network-script        network-vnet)
   41.35 +
   41.36 +Restart xend.
   41.37 +
   41.38 +2) Creating vnets
   41.39 +-----------------
   41.40 +
   41.41 +Xend already implements commands to add/remove vnets and
   41.42 +bridge to them. To add a vnet use
   41.43 +
   41.44 +xm call vnet_add <vnet config file>
   41.45 +
   41.46 +For example, if vnet97.sxp contains:
   41.47 +
   41.48 +(vnet (id 97) (bridge vnet97) (vnetif vnetif97) (security none))
   41.49 +
   41.50 +do
   41.51 +
   41.52 +xm call vnet_add vnet97.sxp
   41.53 +
   41.54 +This will define a vnet with id 97 and no security. The bridge for the
   41.55 +vnet is called vnet97 and the virtual interface for it is vnetif97.
   41.56 +To add an interface on a vm to this vnet simply set its bridge to vnet97
   41.57 +in its configuration.
   41.58 +
   41.59 +In Python:
   41.60 +
   41.61 +vif="bridge=vnet97"
   41.62 +
   41.63 +In sxp:
   41.64 +
   41.65 +(dev (vif (mac aa:00:00:01:02:03) (bridge vnet97)))
   41.66 +
   41.67 +Once configured, vnets are persistent in the xend database.
   41.68 +To remove a vnet use
   41.69 +
   41.70 +xm call vnet_delete <vnet id>
   41.71 +
   41.72 +To list vnets use
   41.73 +
   41.74 +xm call vnets
   41.75 +
   41.76 +To get information on a vnet id use
   41.77 +
   41.78 +xm call vnet <vnet id>
   41.79 +
   41.80 +3) Troubleshooting
   41.81 +------------------
   41.82 +
   41.83 +The vnet module should appear in 'lsmod'.
   41.84 +If a vnet has been configured it should appear in the output of 'xm call vnets'.
   41.85 +Its bridge and interface should appear in 'ifconfig'.
   41.86 +It should also show in 'brctl show', with its attached interfaces.
   41.87 +
   41.88 +You can 'see into' a vnet from dom0 if you put an IP address on the bridge.
   41.89 +For example, if you have vnet97 with a vm with ip addr 10.0.0.12 on it,
   41.90 +then
   41.91 +
   41.92 +ifconfig vnet97 10.0.0.20 up
   41.93 +
   41.94 +should let you ping 10.0.0.12 via the vnet97 bridge.
   41.95 +
   41.96 +4) Examples
   41.97 +-----------
   41.98 +
   41.99 +Here's the full config for a vm on vnet 97, using ip addr 10.0.0.12:
  41.100 +
  41.101 +(vm
  41.102 + (name dom12)
  41.103 + (memory '64')
  41.104 + (cpu '1')
  41.105 + (console '8502')
  41.106 + (image
  41.107 +  (linux
  41.108 +   (kernel /boot/vmlinuz-2.6.9-xenU)
  41.109 +   (ip 10.0.0.12:1.2.3.4::::eth0:off)
  41.110 +   (root /dev/hda1)
  41.111 +   (args 'rw fastboot 4')
  41.112 +  )
  41.113 + )
  41.114 + (device (vbd (uname phy:hda2) (dev hda1) (mode w)))
  41.115 + (device (vif (mac aa:00:00:11:00:12) (bridge vnet97)))
  41.116 +)
  41.117 +
  41.118 +If you run another vm on the same vnet:
  41.119 +
  41.120 +(vm
  41.121 + (name dom11)
  41.122 + (memory '64')
  41.123 + (cpu '1')
  41.124 + (console '8501')
  41.125 + (image
  41.126 +  (linux
  41.127 +   (kernel /boot/vmlinuz-2.6.9-xenU)
  41.128 +   (ip 10.0.0.11:1.2.3.4::::eth0:off)
  41.129 +   (root /dev/hda1)
  41.130 +   (args 'rw fastboot 4')
  41.131 +  )
  41.132 + )
  41.133 + (device (vbd (uname phy:hda3) (dev hda1) (mode w)))
  41.134 + (device (vif (mac aa:00:00:11:00:11) (bridge vnet97)))
  41.135 +)
  41.136 +
  41.137 +the vms should be able to talk over the vnet. Check with ping.
  41.138 +If they are both on the same machine the connection will simply
  41.139 +be the vnet97 bridge, if they are on separate machines their
  41.140 +packets will be tunneled in etherip. They should be able to
  41.141 +see each other, but not the real network.
  41.142 +
  41.143 +
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/tools/vnet/examples/Makefile	Wed Nov 24 12:07:16 2004 +0000
    42.3 @@ -0,0 +1,12 @@
    42.4 +# -*- mode: Makefile; -*-
    42.5 +#============================================================================
    42.6 +
    42.7 +XEN_SCRIPT_DIR:=/etc/xen/scripts
    42.8 +
    42.9 +all:
   42.10 +
   42.11 +install:
   42.12 +	install -m 0755 -d $(prefix)$(XEN_SCRIPT_DIR)
   42.13 +	install -m 0554 network-vnet $(prefix)$(XEN_SCRIPT_DIR)
   42.14 +
   42.15 +clean:
   42.16 \ No newline at end of file
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/tools/vnet/examples/network-vnet	Wed Nov 24 12:07:16 2004 +0000
    43.3 @@ -0,0 +1,218 @@
    43.4 +#!/bin/sh
    43.5 +#============================================================================
    43.6 +# Default Xen network start/stop script.
    43.7 +# Xend calls a network script when it starts.
    43.8 +# The script name to use is defined in /etc/xen/xend-config.sxp
    43.9 +# in the network-script field.
   43.10 +#
   43.11 +# This script creates a bridge (default xen-br0), adds a device
   43.12 +# (default eth0) to it, copies the IP addresses from the device
   43.13 +# to the bridge and adjusts the routes accordingly.
   43.14 +#
   43.15 +# If all goes well, this should ensure that networking stays up.
   43.16 +# However, some configurations are upset by this, especially
   43.17 +# NFS roots. If the bridged setup does not meet your needs,
   43.18 +# configure a different script, for example using routing instead.
   43.19 +#
   43.20 +# Usage:
   43.21 +#
   43.22 +# network (start|stop|status) {VAR=VAL}*
   43.23 +#
   43.24 +# Vars:
   43.25 +#
   43.26 +# bridge     The bridge to use (default xen-br0).
   43.27 +# netdev     The interface to add to the bridge (default eth0).
   43.28 +# antispoof  Whether to use iptables to prevent spoofing (default yes).
   43.29 +#
   43.30 +# start:
   43.31 +# Creates the bridge and enslaves netdev to it.
   43.32 +# Copies the IP addresses from netdev to the bridge.
   43.33 +# Deletes the routes to netdev and adds them on bridge.
   43.34 +#
   43.35 +# stop:
   43.36 +# Removes netdev from the bridge.
   43.37 +# Deletes the routes to bridge and adds them to netdev.
   43.38 +#
   43.39 +# status:
   43.40 +# Print ifconfig for netdev and bridge.
   43.41 +# Print routes.
   43.42 +#
   43.43 +#============================================================================
   43.44 +
   43.45 +# Exit if anything goes wrong.
   43.46 +set -e 
   43.47 +
   43.48 +# First arg is the operation.
   43.49 +OP=$1
   43.50 +shift
   43.51 +
   43.52 +# Pull variables in args in to environment.
   43.53 +for arg ; do export "${arg}" ; done
   43.54 +
   43.55 +bridge=${bridge:-xen-br0}
   43.56 +netdev=${netdev:-eth0}
   43.57 +antispoof=${antispoof:-yes}
   43.58 +
   43.59 +echo "network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof"
   43.60 +
   43.61 +# Usage: transfer_addrs src dst
   43.62 +# Copy all IP addresses (including aliases) from device $src to device $dst.
   43.63 +transfer_addrs () {
   43.64 +    local src=$1
   43.65 +    local dst=$2
   43.66 +    # Don't bother if $dst already has IP addresses.
   43.67 +    if ip addr show dev ${dst} | egrep -q '^ *inet' ; then
   43.68 +        return
   43.69 +    fi
   43.70 +    # Address lines start with 'inet' and have the device in them.
   43.71 +    # Replace 'inet' with 'ip addr add' and change the device name $src
   43.72 +    # to 'dev $src'. Remove netmask as we'll add routes later.
   43.73 +    ip addr show dev ${src} | egrep '^ *inet' | sed -e "
   43.74 +s/inet/ip addr add/
   43.75 +s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)/[0-9]\+@\1@
   43.76 +s/${src}/dev ${dst}/
   43.77 +" | sh -e
   43.78 +}
   43.79 +
   43.80 +# Usage: transfer_routes src dst
   43.81 +# Get all IP routes to device $src, delete them, and
   43.82 +# add the same routes to device $dst.
   43.83 +# The original routes have to be deleted, otherwise adding them
   43.84 +# for $dst fails (duplicate routes).
   43.85 +transfer_routes () {
   43.86 +    local src=$1
   43.87 +    local dst=$2
   43.88 +    # List all routes and grep the ones with $src in.
   43.89 +    # Stick 'ip route del' on the front to delete.
   43.90 +    # Change $src to $dst and use 'ip route add' to add.
   43.91 +    ip route list | grep ${src} | sed -e "
   43.92 +h
   43.93 +s/^/ip route del /
   43.94 +P
   43.95 +g
   43.96 +s/${src}/${dst}/
   43.97 +s/^/ip route add /
   43.98 +P
   43.99 +d
  43.100 +" | sh -e
  43.101 +}
  43.102 +
  43.103 +# Usage: create_bridge dev bridge
  43.104 +# Create bridge $bridge and add device $dev to it.
  43.105 +create_bridge () {
  43.106 +    local dev=$1
  43.107 +    local bridge=$2
  43.108 +
  43.109 +    # Don't create the bridge if it already exists.
  43.110 +    if ! brctl show | grep -q ${bridge} ; then
  43.111 +        brctl addbr ${bridge}
  43.112 +        brctl stp ${bridge} off
  43.113 +        brctl setfd ${bridge} 0
  43.114 +    fi
  43.115 +    ifconfig ${bridge} up
  43.116 +}
  43.117 +
  43.118 +# Usage: antispoofing dev bridge
  43.119 +# Set the default forwarding policy for $dev to drop.
  43.120 +# Allow forwarding to the bridge.
  43.121 +antispoofing () {
  43.122 +    local dev=$1
  43.123 +    local bridge=$2
  43.124 +
  43.125 +    iptables -P FORWARD DROP
  43.126 +    iptables -A FORWARD -m physdev --physdev-in ${dev} -j ACCEPT
  43.127 +}
  43.128 +
  43.129 +# Usage: show_status dev bridge
  43.130 +# Print ifconfig and routes.
  43.131 +show_status () {
  43.132 +    local dev=$1
  43.133 +    local bridge=$2
  43.134 +    
  43.135 +    echo '============================================================'
  43.136 +    ifconfig ${dev}
  43.137 +    ifconfig ${bridge}
  43.138 +    echo ' '
  43.139 +    ip route list
  43.140 +    echo ' '
  43.141 +    route -n
  43.142 +    echo '============================================================'
  43.143 +}
  43.144 +
  43.145 +# Insert the vnet module if it can be found and
  43.146 +# it's not already there.
  43.147 +vnet_insert () {
  43.148 +    local module="vnet_module"
  43.149 +    local mod_dir=/lib/modules/$(uname -r)/kernel
  43.150 +    local mod_path="${mod_dir}/${module}"
  43.151 +    local mod_obj=""
  43.152 +
  43.153 +    for ext in ".o" ".ko" ; do
  43.154 +        f=${mod_path}${ext}
  43.155 +        if [ -f ${f} ] ; then
  43.156 +            mod_obj=$f
  43.157 +            break
  43.158 +        fi
  43.159 +    done
  43.160 +    if [ "${mod_obj}" == "" ] ; then
  43.161 +        return
  43.162 +    fi
  43.163 +    if lsmod | grep -q ${module} ; then
  43.164 +        echo "VNET: ${module} loaded"
  43.165 +    else
  43.166 +        echo "VNET: Loading ${module}..."
  43.167 +               insmod ${mod_obj}
  43.168 +    fi
  43.169 +}
  43.170 +
  43.171 +op_start () {
  43.172 +    if [ "${bridge}" == "null" ] ; then
  43.173 +        return
  43.174 +    fi
  43.175 +    # Create the bridge and give it the interface IP addresses.
  43.176 +    # Move the interface routes onto the bridge.
  43.177 +    create_bridge ${netdev} ${bridge}
  43.178 +    transfer_addrs ${netdev} ${bridge}
  43.179 +    transfer_routes ${netdev} ${bridge}
  43.180 +    # Don't add $dev to $bridge if it's already on a bridge.
  43.181 +    if ! brctl show | grep -q ${netdev} ; then
  43.182 +        brctl addif ${bridge} ${netdev}
  43.183 +    fi
  43.184 +    
  43.185 +    if [ ${antispoof} == 'yes' ] ; then
  43.186 +        antispoofing ${netdev} ${bridge}
  43.187 +    fi
  43.188 +
  43.189 +    vnet_insert
  43.190 +}
  43.191 +
  43.192 +op_stop () {
  43.193 +    if [ "${bridge}" == "null" ] ; then
  43.194 +        return
  43.195 +    fi
  43.196 +    # Remove the interface from the bridge.
  43.197 +    # Move the routes back to the interface.
  43.198 +    brctl delif ${bridge} ${netdev}
  43.199 +    transfer_routes ${bridge} ${netdev}
  43.200 +
  43.201 +    # It's not our place to be enabling forwarding...
  43.202 +}
  43.203 +
  43.204 +case ${OP} in
  43.205 +    start)
  43.206 +        op_start
  43.207 +        ;;
  43.208 +    
  43.209 +    stop)
  43.210 +        op_stop
  43.211 +        ;;
  43.212 +
  43.213 +    status)
  43.214 +        show_status ${netdev} ${bridge}
  43.215 +       ;;
  43.216 +
  43.217 +    *)
  43.218 +       echo 'Unknown command: ' ${OP}
  43.219 +       echo 'Valid commands are: start, stop, status'
  43.220 +       exit 1
  43.221 +esac
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/tools/vnet/examples/vnet97.sxp	Wed Nov 24 12:07:16 2004 +0000
    44.3 @@ -0,0 +1,3 @@
    44.4 +# Vnet configuration for a vnet with id 97 and no security.
    44.5 +# Configure using 'xm call vnet_add vnet97.sxp'.
    44.6 +(vnet (id 97) (bridge vnet97) (vnetif vnetif97) (security none))
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/tools/vnet/examples/vnet98.sxp	Wed Nov 24 12:07:16 2004 +0000
    45.3 @@ -0,0 +1,3 @@
    45.4 +# Vnet configuration for a vnet with id 98 and message authentication.
    45.5 +# Configure using 'xm call vnet_add vnet98.sxp'.
    45.6 +(vnet (id 98) (bridge vnet98) (vnetif vnetif98) (security auth))
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/tools/vnet/examples/vnet99.sxp	Wed Nov 24 12:07:16 2004 +0000
    46.3 @@ -0,0 +1,3 @@
    46.4 +# Vnet configuration for a vnet with id 99 and message confidentiality.
    46.5 +# Configure using 'xm call vnet_add vnet99.sxp'.
    46.6 +(vnet (id 99) (bridge vnet99) (vnetif vnetif99) (security conf))
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/tools/vnet/vnet-module/00README	Wed Nov 24 12:07:16 2004 +0000
    47.3 @@ -0,0 +1,41 @@
    47.4 +Vnet module for network virtualization.
    47.5 +Mike Wray <mike.wray@hp.com>
    47.6 +
    47.7 +*) Compiling
    47.8 +The vnet module can be compiled for 2.4 or 2.6 series kernels.
    47.9 +The makefiles  use the following variables, which
   47.10 +can be set in your env or on the make command line:
   47.11 +
   47.12 +LINUX_RELEASE: linux release to compile for, 2.4 (default), or 2.6.
   47.13 +XENO_ROOT: root of the xen tree containing kernel source. Default '..'.
   47.14 +ROOT: root path to install in, default is XENO_ROOT/install.
   47.15 +      Set to '/' to install relative to filesystem root.
   47.16 +KERNEL_VERSION: kernel version, default got from XENO_ROOT.
   47.17 +KERNEL_MINOR: kernel minor version, default -xen0.
   47.18 +KERNEL_SRC: path to kernel source, default linux-<VERSION> under XENO_ROOT.
   47.19 +
   47.20 +*) For 2.4 kernel
   47.21 +
   47.22 +To compile from scratch:
   47.23 +
   47.24 +make clean
   47.25 +make 
   47.26 +
   47.27 +This will build vnet_module.o in the current directory.
   47.28 +To install the module use
   47.29 +
   47.30 +make install
   47.31 +
   47.32 +*) For 2.6 kernel
   47.33 +
   47.34 +To compile from scratch:
   47.35 +
   47.36 +make clean
   47.37 +make LINUX_RELEASE=2.6
   47.38 +
   47.39 +This will build vnet_module.ko in the current directory.
   47.40 +To install the module use
   47.41 +
   47.42 +make LINUX_RELEASE=2.6 install
   47.43 +
   47.44 +
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/tools/vnet/vnet-module/Makefile	Wed Nov 24 12:07:16 2004 +0000
    48.3 @@ -0,0 +1,67 @@
    48.4 +# -*- mode: Makefile; -*-
    48.5 +#============================================================================
    48.6 +#
    48.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    48.8 +#
    48.9 +# This program is free software; you can redistribute it and/or modify
   48.10 +# it under the terms of the GNU General Public License as published by the
   48.11 +# Free Software Foundation; either version 2 of the License, or (at your
   48.12 +# option) any later version.
   48.13 +#
   48.14 +# This program is distributed in the hope that it will be useful, but
   48.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   48.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   48.17 +# for more details.
   48.18 +#
   48.19 +# You should have received a copy of the GNU General Public License along
   48.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   48.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   48.22 +#============================================================================
   48.23 +
   48.24 +#============================================================================
   48.25 +ifeq ($(src),)
   48.26 +LINUX_RELEASE ?=2.6
   48.27 +
   48.28 +include Makefile-$(LINUX_RELEASE)
   48.29 +
   48.30 +#============================================================================
   48.31 +else
   48.32 +#============================================================================
   48.33 +# This section is for the 2.6 kbuild.
   48.34 +
   48.35 +#$(warning KBUILD_EXTMOD $(KBUILD_EXTMOD))
   48.36 +#$(warning src $(src))
   48.37 +#$(warning obj $(obj))
   48.38 +
   48.39 +include $(src)/Makefile.vnet
   48.40 +
   48.41 +obj-m = vnet_module.o
   48.42 +vnet_module-objs = $(VNET_OBJ)
   48.43 +vnet_module-objs += $(VNET_LIB_OBJ)
   48.44 +
   48.45 +#----------------------------------------------------------------------------
   48.46 +# The fancy stuff in the kernel build defeats 'vpath %.c' so we can't
   48.47 +# use that to get the lib files compiled.
   48.48 +# Setup explicit rules for them using the kbuild C compile rule.
   48.49 +
   48.50 +# File names in the lib dir.
   48.51 +remote_srcs = $(foreach file,$(VNET_LIB_SRC),$(LIB_DIR)/$(file))
   48.52 +
   48.53 +# Equivalent file names here.
   48.54 +local_srcs = $(foreach file,$(VNET_LIB_SRC),$(src)/$(file))
   48.55 +
   48.56 +# Objects for the local names.
   48.57 +local_objs = $(local_srcs:.c=.o)
   48.58 +
   48.59 +# Make the local objects depend on compiling the remote sources.
   48.60 +$(local_objs): $(src)/%.o: $(LIB_DIR)/%.c
   48.61 +	$(call if_changed_rule,cc_o_c)
   48.62 +#----------------------------------------------------------------------------
   48.63 +
   48.64 +vpath %.h $(LIB_DIR)
   48.65 +EXTRA_CFLAGS += -I $(LIB_DIR)
   48.66 +EXTRA_CFLAGS += -I $(src)
   48.67 +
   48.68 +endif
   48.69 +#============================================================================
   48.70 +
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/tools/vnet/vnet-module/Makefile-2.4	Wed Nov 24 12:07:16 2004 +0000
    49.3 @@ -0,0 +1,97 @@
    49.4 +# -*- mode: Makefile; -*-
    49.5 +#============================================================================
    49.6 +#
    49.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    49.8 +#
    49.9 +# This program is free software; you can redistribute it and/or modify
   49.10 +# it under the terms of the GNU General Public License as published by the
   49.11 +# Free Software Foundation; either version 2 of the License, or (at your
   49.12 +# option) any later version.
   49.13 +#
   49.14 +# This program is distributed in the hope that it will be useful, but
   49.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   49.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   49.17 +# for more details.
   49.18 +#
   49.19 +# You should have received a copy of the GNU General Public License along
   49.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   49.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   49.22 +#============================================================================
   49.23 +
   49.24 +#============================================================================
   49.25 +# Vnet module makefile for 2.4 series kernels.
   49.26 +
   49.27 +include Makefile.ver
   49.28 +
   49.29 +KERNEL_MODULE := vnet_module.o
   49.30 +
   49.31 +CONFIG_MODVERSIONS := $(shell grep 'CONFIG_MODVERSIONS=y' $(KERNEL_SRC)/.config && echo 1 || echo 0)
   49.32 +
   49.33 +include Makefile.vnet
   49.34 +
   49.35 +VNET_OBJ += $(VNET_LIB_OBJ)
   49.36 +
   49.37 +#----------------------------------------------------------------------------
   49.38 +
   49.39 +vpath %.h $(KERNEL_SRC)/include
   49.40 +INCLUDES+= -I $(KERNEL_SRC)/include
   49.41 +
   49.42 +vpath %.h $(LIB_DIR)
   49.43 +vpath %.c $(LIB_DIR)
   49.44 +INCLUDES += -I $(LIB_DIR)
   49.45 +
   49.46 +INCLUDES+= -I .
   49.47 +
   49.48 +#----------------------------------------------------------------------------
   49.49 +
   49.50 +CPPFLAGS += -D__KERNEL__
   49.51 +CPPFLAGS += -DMODULE
   49.52 +
   49.53 +ifeq ($(CONFIG_MODVERSIONS), 1)
   49.54 +CPPFLAGS += -DMODVERSIONS
   49.55 +CPPFLAGS += -include $(KERNEL_SRC)/include/linux/modversions.h
   49.56 +endif
   49.57 +
   49.58 +CPPFLAGS += $(INCLUDES)
   49.59 +
   49.60 +CFLAGS += -Wall
   49.61 +CFLAGS += -Wstrict-prototypes
   49.62 +CFLAGS += -Wno-trigraphs
   49.63 +CFLAGS += -Wno-unused-function
   49.64 +CFLAGS += -Wno-unused-parameter 
   49.65 +
   49.66 +CFLAGS += -g
   49.67 +CFLAGS += -O2
   49.68 +CFLAGS += -fno-strict-aliasing 
   49.69 +CFLAGS += -fno-common 
   49.70 +#CFLAGS += -fomit-frame-pointer
   49.71 +
   49.72 +# Dependencies. Gcc generates them for us.
   49.73 +CFLAGS += -Wp,-MD,.$(@F).d
   49.74 +VNET_DEP = .*.d
   49.75 +#----------------------------------------------------------------------------
   49.76 +
   49.77 +.PHONY: all
   49.78 +all: module
   49.79 +
   49.80 +.PHONY: module modules
   49.81 +module modules: $(KERNEL_MODULE)
   49.82 +
   49.83 +$(KERNEL_MODULE): $(VNET_OBJ)
   49.84 +	$(LD) -r -o $@ $^
   49.85 +
   49.86 +.PHONY: install install-module modules_install
   49.87 +install install-module modules_install: module
   49.88 +	install -m 0755 -d $(prefix)$(KERNEL_MODULE_DIR)
   49.89 +	install -m 0554 $(KERNEL_MODULE) $(prefix)$(KERNEL_MODULE_DIR)
   49.90 +
   49.91 +TAGS:
   49.92 +	etags *.c *.h
   49.93 +
   49.94 +.PHONY: clean
   49.95 +clean:
   49.96 +	@rm -f *.a *.o *.ko *~
   49.97 +	@rm -f $(VNET_DEP) .*.cmd *.mod.?
   49.98 +	@rm -rf .tmp_versions
   49.99 +
  49.100 +-include $(VNET_DEP)
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/tools/vnet/vnet-module/Makefile-2.6	Wed Nov 24 12:07:16 2004 +0000
    50.3 @@ -0,0 +1,51 @@
    50.4 +# -*- mode: Makefile; -*-
    50.5 +#============================================================================
    50.6 +#
    50.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    50.8 +#
    50.9 +# This program is free software; you can redistribute it and/or modify
   50.10 +# it under the terms of the GNU General Public License as published by the
   50.11 +# Free Software Foundation; either version 2 of the License, or (at your
   50.12 +# option) any later version.
   50.13 +#
   50.14 +# This program is distributed in the hope that it will be useful, but
   50.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   50.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   50.17 +# for more details.
   50.18 +#
   50.19 +# You should have received a copy of the GNU General Public License along
   50.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   50.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   50.22 +#============================================================================
   50.23 +
   50.24 +#============================================================================
   50.25 +# Vnet module makefile for 2.6 series kernels.
   50.26 +
   50.27 +LINUX_RELEASE ?= 2.6
   50.28 +include Makefile.ver
   50.29 +
   50.30 +KERNEL_MODULE = vnet_module.ko
   50.31 +
   50.32 +#----------------------------------------------------------------------------
   50.33 +#export KBUILD_VERBOSE=1
   50.34 +
   50.35 +.PHONY: all
   50.36 +all: module
   50.37 +
   50.38 +.PHONY: module
   50.39 +module modules:
   50.40 +	$(MAKE) -C $(KERNEL_SRC) M=`pwd` modules
   50.41 +
   50.42 +.PHONY: install install-module modules_install
   50.43 +install install-module modules_install: module
   50.44 +	install -m 0755 -d $(prefix)$(KERNEL_MODULE_DIR)
   50.45 +	install -m 0554 $(KERNEL_MODULE) $(prefix)$(KERNEL_MODULE_DIR)
   50.46 +
   50.47 +.PHONY: clean
   50.48 +clean:
   50.49 +	@$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean
   50.50 +	@rm -f *.a *.o *.ko *~ .*.d .*.cmd *.mod.?
   50.51 +
   50.52 +TAGS:
   50.53 +	etags *.c *.h
   50.54 +
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/tools/vnet/vnet-module/Makefile.ver	Wed Nov 24 12:07:16 2004 +0000
    51.3 @@ -0,0 +1,49 @@
    51.4 +# -*- mode: Makefile; -*-
    51.5 +#============================================================================
    51.6 +#
    51.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    51.8 +#
    51.9 +# This program is free software; you can redistribute it and/or modify
   51.10 +# it under the terms of the GNU General Public License as published by the
   51.11 +# Free Software Foundation; either version 2 of the License, or (at your
   51.12 +# option) any later version.
   51.13 +#
   51.14 +# This program is distributed in the hope that it will be useful, but
   51.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   51.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   51.17 +# for more details.
   51.18 +#
   51.19 +# You should have received a copy of the GNU General Public License along
   51.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   51.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   51.22 +#============================================================================
   51.23 +
   51.24 +#----------------------------------------------------------------------------
   51.25 +# Xeno/xen.
   51.26 +
   51.27 +# Root of xen tree.
   51.28 +XEN_ROOT ?=../../..
   51.29 +
   51.30 +# Path to relativize the install. Set to /
   51.31 +# to install relative to filesystem root.
   51.32 +prefix ?=$(XEN_ROOT)/install/
   51.33 +#----------------------------------------------------------------------------
   51.34 +
   51.35 +LINUX_RELEASE ?=2.6
   51.36 +KERNEL_MINOR ?=-xen0
   51.37 +
   51.38 +LINUX_VERSION ?= $(shell ( /bin/ls -ld $(XEN_ROOT)/linux-$(LINUX_RELEASE).*-xen-sparse ) 2>/dev/null | \
   51.39 +                      sed -e 's!^.*linux-\(.\+\)-xen-sparse!\1!' )
   51.40 +
   51.41 +ifeq ($(LINUX_VERSION),)
   51.42 +$(error Kernel source for linux $(LINUX_RELEASE) not found)
   51.43 +endif
   51.44 +
   51.45 +KERNEL_VERSION =$(LINUX_VERSION)$(KERNEL_MINOR)
   51.46 +
   51.47 +KERNEL_SRC ?= $(XEN_ROOT)/linux-$(KERNEL_VERSION)
   51.48 +
   51.49 +KERNEL_MODULE_DIR = /lib/modules/$(KERNEL_VERSION)/kernel
   51.50 +
   51.51 +#$(warning KERNEL_VERSION $(KERNEL_VERSION))
   51.52 +#$(warning KERNEL_SRC $(KERNEL_SRC))
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/tools/vnet/vnet-module/Makefile.vnet	Wed Nov 24 12:07:16 2004 +0000
    52.3 @@ -0,0 +1,57 @@
    52.4 +# -*- mode: Makefile; -*-
    52.5 +#============================================================================
    52.6 +#
    52.7 +# Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    52.8 +#
    52.9 +# This program is free software; you can redistribute it and/or modify
   52.10 +# it under the terms of the GNU General Public License as published by the
   52.11 +# Free Software Foundation; either version 2 of the License, or (at your
   52.12 +# option) any later version.
   52.13 +#
   52.14 +# This program is distributed in the hope that it will be useful, but
   52.15 +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   52.16 +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   52.17 +# for more details.
   52.18 +#
   52.19 +# You should have received a copy of the GNU General Public License along
   52.20 +# with this program; if not, write to the Free software Foundation, Inc.,
   52.21 +# 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   52.22 +#============================================================================
   52.23 +
   52.24 +ifeq ($(src),)
   52.25 +SRC_DIR=
   52.26 +else
   52.27 +SRC_DIR=$(src)/
   52.28 +endif
   52.29 +
   52.30 +LIB_DIR := $(SRC_DIR)../../libxutil
   52.31 +
   52.32 +VNET_SRC :=
   52.33 +VNET_SRC += esp.c
   52.34 +VNET_SRC += etherip.c
   52.35 +VNET_SRC += random.c
   52.36 +VNET_SRC += sa_algorithm.c
   52.37 +VNET_SRC += sa.c
   52.38 +VNET_SRC += skb_context.c
   52.39 +VNET_SRC += skb_util.c
   52.40 +VNET_SRC += tunnel.c
   52.41 +VNET_SRC += varp.c
   52.42 +VNET_SRC += varp_socket.c
   52.43 +VNET_SRC += vif.c
   52.44 +VNET_SRC += vnet.c
   52.45 +VNET_SRC += vnet_dev.c
   52.46 +VNET_SRC += vnet_ioctl.c
   52.47 +
   52.48 +VNET_LIB_SRC += allocate.c
   52.49 +VNET_LIB_SRC += enum.c
   52.50 +VNET_LIB_SRC += hash_table.c
   52.51 +VNET_LIB_SRC += iostream.c
   52.52 +VNET_LIB_SRC += kernel_stream.c
   52.53 +VNET_LIB_SRC += sxpr.c
   52.54 +VNET_LIB_SRC += sxpr_parser.c
   52.55 +VNET_LIB_SRC += sys_net.c
   52.56 +VNET_LIB_SRC += sys_string.c
   52.57 +
   52.58 +VNET_OBJ := $(VNET_SRC:.c=.o)
   52.59 +VNET_LIB_OBJ := $(VNET_LIB_SRC:.c=.o)
   52.60 +
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/tools/vnet/vnet-module/esp.c	Wed Nov 24 12:07:16 2004 +0000
    53.3 @@ -0,0 +1,863 @@
    53.4 +/*
    53.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    53.6 + *
    53.7 + * This program is free software; you can redistribute it and/or modify
    53.8 + * it under the terms of the GNU General Public License as published by the 
    53.9 + * Free Software Foundation; either version 2 of the License, or (at your
   53.10 + * option) any later version.
   53.11 + * 
   53.12 + * This program is distributed in the hope that it will be useful, but
   53.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   53.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   53.15 + * for more details.
   53.16 + *
   53.17 + * You should have received a copy of the GNU General Public License along
   53.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   53.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   53.20 + *
   53.21 + */
   53.22 +#include <linux/config.h>
   53.23 +#include <linux/module.h>
   53.24 +#include <linux/types.h>
   53.25 +#include <linux/sched.h>
   53.26 +#include <linux/kernel.h>
   53.27 +#include <asm/uaccess.h>
   53.28 +
   53.29 +#include <linux/init.h>
   53.30 +
   53.31 +#include <linux/version.h>
   53.32 +
   53.33 +#include <linux/skbuff.h>
   53.34 +#include <linux/netdevice.h>
   53.35 +#include <linux/net.h>
   53.36 +#include <linux/in.h>
   53.37 +#include <linux/inet.h>
   53.38 +
   53.39 +#include <net/ip.h>
   53.40 +#include <net/protocol.h>
   53.41 +#include <net/route.h>
   53.42 +
   53.43 +#include <linux/if_ether.h>
   53.44 +#include <linux/icmp.h>
   53.45 +
   53.46 +#include <asm/scatterlist.h>
   53.47 +#include <linux/crypto.h>
   53.48 +#include <linux/pfkeyv2.h>
   53.49 +#include <linux/random.h>
   53.50 +
   53.51 +#include <esp.h>
   53.52 +#include <sa.h>
   53.53 +#include <sa_algorithm.h>
   53.54 +#include <tunnel.h>
   53.55 +#include <vnet.h>
   53.56 +#include <skb_util.h>
   53.57 +
   53.58 +static const int DEBUG_ICV = 0;
   53.59 +
   53.60 +#define MODULE_NAME "IPSEC"
   53.61 +#define DEBUG 1
   53.62 +#undef DEBUG
   53.63 +#include "debug.h"
   53.64 +
   53.65 +/* Outgoing packet:                            [ eth | ip | data ]
   53.66 + * After etherip:        [ eth2 | ip2 |  ethip | eth | ip | data ]
   53.67 + * After esp   :   [ eth2 | ip2 | esp | {ethip | eth | ip | data} | pad | icv ]
   53.68 + *                                                        ^     +
   53.69 + * The curly braces { ... } denote encryption.
   53.70 + * The esp header includes the fixed esp headers and the iv (variable size).
   53.71 + * The point marked ^ does not move. To the left is in the header, to the right
   53.72 + * is in the frag. Remember that all outgoing skbs (from domains) have 1 frag.
   53.73 + * Data after + is added by esp, using an extra frag.
   53.74 + *
   53.75 + * Incoming as above.
   53.76 + * After decrypt:  [ eth2 | ip2 | esp |  ethip | eth | ip | data  | pad | icv ]
   53.77 + * Trim tail:      [ eth2 | ip2 | esp |  ethip | eth | ip | data ]
   53.78 + * Drop hdr:             [ eth2 | ip2 |  ethip | eth | ip | data ]
   53.79 + *                                    ^
   53.80 + * The point marked ^ does not move. Incoming skbs are linear (no frags).
   53.81 + * The tail is trimmed by adjusting skb->tail and len.
   53.82 + * The esp hdr is dropped by using memmove to move the headers and
   53.83 + * adjusting the skb pointers.
   53.84 + *
   53.85 + * todo: Now this code is in linux we can't assume 1 frag for outbound skbs,
   53.86 + * or (maybe) that memmove is safe on inbound.
   53.87 + */
   53.88 +
   53.89 +/** Round n up to a multiple of block.
   53.90 + * If block is less than 2 does nothing.
   53.91 + * Otherwise assume block is a power of 2.
   53.92 + *
   53.93 + * @param n to round up
   53.94 + * @param block size to round to a multiple of
   53.95 + * @return rounded value
   53.96 + */
   53.97 +static inline int roundup(int n, int block){
   53.98 +    if(block <= 1) return n;
   53.99 +    block--;
  53.100 +    return (n + block) & ~block;
  53.101 +}
  53.102 +
  53.103 +/** Check if n is a multiple of block.
  53.104 + * If block is less than 2 returns 1.
  53.105 + * Otherwise assumes block is a power of 2.
  53.106 + *
  53.107 + * @param n to check
  53.108 + * @param block block size
  53.109 + * @return 1 if a multiple, 0 otherwise
  53.110 + */
  53.111 +static inline int multipleof(int n, int block){
  53.112 +    if(block <= 1) return 1;
  53.113 +    block--;
  53.114 +    return !(n & block);
  53.115 +}
  53.116 +
  53.117 +/** Convert from bits to bytes.
  53.118 + *
  53.119 + * @param n number of bits
  53.120 + * @return number of bytes
  53.121 + */
  53.122 +static inline int bits_to_bytes(int n){
  53.123 +    return n / 8;
  53.124 +}
  53.125 +
  53.126 +
  53.127 +/** Insert esp padding at the end of an skb.
  53.128 + * Inserts padding bytes, number of padding bytes, protocol number.
  53.129 + *
  53.130 + * @param skb skb
  53.131 + * @param offset offset from skb end to where padding should end
  53.132 + * @param extra_n total amount of padding
  53.133 + * @param protocol protocol number (from original ip hdr)
  53.134 + * @return 0 on success, error code otherwise
  53.135 + */
  53.136 +static int esp_sa_pad(struct sk_buff *skb, int offset, int extra_n,
  53.137 +                      unsigned char protocol){
  53.138 +    int err;
  53.139 +    char *data;
  53.140 +    int pad_n = extra_n - ESP_PAD_N;
  53.141 +    int i;
  53.142 +    char buf[extra_n];
  53.143 +
  53.144 +    data = buf;
  53.145 +    for(i = 1; i <= pad_n; i++){
  53.146 +        *data++ = i;
  53.147 +    }
  53.148 +    *data++ = pad_n;
  53.149 +    *data++ = protocol;
  53.150 +    err = skb_put_bits(skb, skb->len - offset - extra_n, buf, extra_n);
  53.151 +    return err;
  53.152 +}
  53.153 +
  53.154 +/** Encrypt skb. Skips esp header and iv.
  53.155 + * Assumes skb->data points at esp header.
  53.156 + *
  53.157 + * @param esp esp state
  53.158 + * @parm esph esp header
  53.159 + * @param skb packet
  53.160 + * @param head_n size of esp header and iv
  53.161 + * @param iv_n size of iv
  53.162 + * @param text_n size of ciphertext
  53.163 + * @return 0 on success, error code otherwise
  53.164 + */
  53.165 +static int esp_sa_encrypt(ESPState *esp, ESPHdr *esph, struct sk_buff *skb,
  53.166 +                   int head_n, int iv_n, int text_n){
  53.167 +    int err = 0;
  53.168 +    int sg_n = skb_shinfo(skb)->nr_frags + 1;
  53.169 +    struct scatterlist sg[sg_n];
  53.170 +
  53.171 +    err = skb_scatterlist(skb, sg, &sg_n, head_n, text_n);
  53.172 +    if(err) goto exit;
  53.173 +    if(iv_n){
  53.174 +        crypto_cipher_set_iv(esp->cipher.tfm, esp->cipher.iv, iv_n);
  53.175 +    }
  53.176 +    crypto_cipher_encrypt(esp->cipher.tfm, sg, sg, text_n);
  53.177 +    if(iv_n){
  53.178 +        memcpy(esph->data, esp->cipher.iv, iv_n);
  53.179 +        crypto_cipher_get_iv(esp->cipher.tfm, esp->cipher.iv, iv_n);
  53.180 +    }
  53.181 +  exit:
  53.182 +    return err;
  53.183 +}
  53.184 +
  53.185 +/** Decrypt skb. Skips esp header and iv.
  53.186 + * Assumes skb->data points at esp header.
  53.187 + *
  53.188 + * @param esp esp state
  53.189 + * @parm esph esp header
  53.190 + * @param skb packet
  53.191 + * @param head_n size of esp header and iv
  53.192 + * @param iv_n size of iv
  53.193 + * @param text_n size of ciphertext
  53.194 + * @return 0 on success, error code otherwise
  53.195 + */
  53.196 +static int esp_sa_decrypt(ESPState *esp, ESPHdr *esph, struct sk_buff *skb,
  53.197 +                   int head_n, int iv_n, int text_n){
  53.198 +    int err = 0;
  53.199 +    int sg_n = skb_shinfo(skb)->nr_frags + 1;
  53.200 +    struct scatterlist sg[sg_n];
  53.201 +
  53.202 +    err = skb_scatterlist(skb, sg, &sg_n, head_n, text_n);
  53.203 +    if(err) goto exit;
  53.204 +    if(iv_n){
  53.205 +        crypto_cipher_set_iv(esp->cipher.tfm, esph->data, iv_n);
  53.206 +    }
  53.207 +    crypto_cipher_decrypt(esp->cipher.tfm, sg, sg, text_n);
  53.208 +  exit:
  53.209 +    return err;
  53.210 +}
  53.211 +
  53.212 +/** Compute icv. Includes esp header, iv and ciphertext.
  53.213 + * Assumes skb->data points at esp header.
  53.214 + *
  53.215 + * @param esp esp state
  53.216 + * @param skb packet
  53.217 + * @param digest_n number of bytes to digest
  53.218 + * @param icv_n size of icv
  53.219 + * @return 0 on success, error code otherwise
  53.220 + */
  53.221 +static int esp_sa_digest(ESPState *esp, struct sk_buff *skb, int digest_n, int icv_n){
  53.222 +    int err = 0;
  53.223 +    u8 icv[icv_n];
  53.224 +    
  53.225 +    if(DEBUG_ICV){
  53.226 +        dprintf("> skb digest_n=%d icv_n=%d\n", digest_n, icv_n);
  53.227 +        skb_print_bits(skb, 0, digest_n);
  53.228 +    }
  53.229 +    memset(icv, 0, icv_n);
  53.230 +    esp->digest.icv(esp, skb, 0, digest_n, icv);
  53.231 +    skb_put_bits(skb, digest_n, icv, icv_n);
  53.232 +    return err;
  53.233 +}
  53.234 +
  53.235 +/** Check the icv and trim it from the skb tail.
  53.236 + *
  53.237 + * @param sa sa state
  53.238 + * @param esp esp state
  53.239 + * @param esph esp header
  53.240 + * @param skb packet
  53.241 + * @return 0 on success, error code otherwise
  53.242 + */
  53.243 +static int esp_check_icv(SAState *sa, ESPState *esp, ESPHdr *esph, struct sk_buff *skb){
  53.244 +    int err = 0;
  53.245 +    int icv_n = esp->digest.icv_n;
  53.246 +    int digest_n = skb->len - icv_n;
  53.247 +    u8 icv_skb[icv_n];
  53.248 +    u8 icv_new[icv_n];
  53.249 +
  53.250 +    dprintf(">\n");
  53.251 +    if(DEBUG_ICV){
  53.252 +        dprintf("> skb len=%d digest_n=%d icv_n=%d\n",
  53.253 +                skb->len, digest_n, icv_n);
  53.254 +        skb_print_bits(skb, 0, skb->len);
  53.255 +    }
  53.256 +    if(skb_copy_bits(skb, digest_n, icv_skb, icv_n)){
  53.257 +        wprintf("> Error getting icv from skb\n");
  53.258 +        goto exit;
  53.259 +    }
  53.260 +    esp->digest.icv(esp, skb, 0, digest_n, icv_new);
  53.261 +    if(DEBUG_ICV){
  53.262 +        dprintf("> len=%d icv_n=%d", digest_n, icv_n);
  53.263 +        printk("\nskb="); buf_print(icv_skb, icv_n);
  53.264 +        printk("new="); buf_print(icv_new, icv_n);
  53.265 +    }
  53.266 +    if(unlikely(memcmp(icv_new, icv_skb, icv_n))){
  53.267 +        wprintf("> ICV check failed!\n");
  53.268 +        err = -EINVAL;
  53.269 +        sa->counts.integrity_failures++;
  53.270 +        goto exit;
  53.271 +    }
  53.272 +    skb_trim_tail(skb, icv_n);
  53.273 +  exit:
  53.274 +    dprintf("< err=%d\n", err);
  53.275 +    return err;
  53.276 +}
  53.277 +
  53.278 +/** Send a packet via an ESP SA.
  53.279 + *
  53.280 + * @param sa SA state
  53.281 + * @param skb packet to send
  53.282 + * @param tunnel underlying tunnel
  53.283 + * @return 0 on success, negative error code otherwise
  53.284 + */
  53.285 +static int esp_sa_send(SAState *sa, struct sk_buff *skb, Tunnel *tunnel){
  53.286 +    int err = 0;
  53.287 +    int ip_n;           // Size of ip header.
  53.288 +    int plaintext_n;	// Size of plaintext.
  53.289 +    int ciphertext_n;   // Size of ciphertext (including padding).
  53.290 +    int extra_n;        // Extra bytes needed for ciphertext.
  53.291 +    int icv_n = 0;      // Size of integrity check value (icv).
  53.292 +    int iv_n = 0;       // Size of initialization vector (iv).
  53.293 +    int head_n;         // Size of esp header and iv.
  53.294 +    int tail_n;         // Size of esp trailer: padding and icv.
  53.295 +    ESPState  *esp;
  53.296 +    ESPHdr *esph;
  53.297 +
  53.298 +    dprintf(">\n");
  53.299 +    esp = sa->data;
  53.300 +    ip_n = (skb->nh.iph->ihl << 2);
  53.301 +    // Assuming skb->data points at ethernet header, exclude ethernet
  53.302 +    // header and IP header.
  53.303 +    plaintext_n = skb->len - ETH_HLEN - ip_n;
  53.304 +    // Add size of padding fields.
  53.305 +    ciphertext_n = roundup(plaintext_n + ESP_PAD_N, esp->cipher.block_n);
  53.306 +    if(esp->cipher.pad_n > 0){
  53.307 +        ciphertext_n = roundup(ciphertext_n, esp->cipher.pad_n);
  53.308 +    }
  53.309 +    extra_n = ciphertext_n - plaintext_n;
  53.310 +    iv_n = esp->cipher.iv_n;
  53.311 +    icv_n = esp->digest.icv_n;
  53.312 +    dprintf("> len=%d plaintext=%d ciphertext=%d extra=%d\n",
  53.313 +            skb->len, plaintext_n, ciphertext_n, extra_n);
  53.314 +    dprintf("> iv=%d icv=%d\n", iv_n, icv_n);
  53.315 +    skb_print_bits(skb, 0, skb->len);
  53.316 +
  53.317 +    // Add headroom for esp header and iv, tailroom for the ciphertext
  53.318 +    // and icv.
  53.319 +    head_n = ESP_HDR_N + iv_n;
  53.320 +    tail_n = extra_n + icv_n;
  53.321 +    err = skb_make_room(&skb, skb, head_n, tail_n);
  53.322 +    if(err) goto exit;
  53.323 +    dprintf("> skb=%p\n", skb);
  53.324 +    // Move the headers up to make space for the esp header.  We can
  53.325 +    // use memmove() since all this data fits in the skb head.
  53.326 +    // todo: Can't assume this anymore?
  53.327 +    dprintf("> header push...\n");
  53.328 +    __skb_push(skb, head_n);
  53.329 +    if(0 && skb->mac.raw){
  53.330 +        dprintf("> skb->mac=%p\n", skb->mac.raw);
  53.331 +        dprintf("> ETH header pull...\n");
  53.332 +        memmove(skb->data, skb->mac.raw, ETH_HLEN);
  53.333 +        skb->mac.raw = skb->data; 
  53.334 +        __skb_pull(skb, ETH_HLEN);
  53.335 +    }
  53.336 +    dprintf("> IP header pull...\n");
  53.337 +    memmove(skb->data, skb->nh.raw, ip_n);
  53.338 +    skb->nh.raw = skb->data;
  53.339 +    __skb_pull(skb, ip_n);
  53.340 +    esph = (void*)skb->data;
  53.341 +    // Add spi and sequence number.
  53.342 +    esph->spi = sa->ident.spi;
  53.343 +    esph->seq = htonl(++sa->replay.send_seq);
  53.344 +    // Insert the padding bytes: extra bytes less the pad fields
  53.345 +    // themselves.
  53.346 +    dprintf("> esp_sa_pad ...\n");
  53.347 +    esp_sa_pad(skb, icv_n, extra_n, skb->nh.iph->protocol);
  53.348 +    if(sa->security & SA_CONF){
  53.349 +        dprintf("> esp_sa_encrypt...\n");
  53.350 +        err = esp_sa_encrypt(esp, esph, skb, head_n, iv_n, ciphertext_n);
  53.351 +        if(err) goto exit;
  53.352 +    }
  53.353 +    if(icv_n){
  53.354 +        dprintf("> esp_sa_digest...\n");
  53.355 +        err = esp_sa_digest(esp, skb, head_n + ciphertext_n, icv_n);
  53.356 +        if(err) goto exit;
  53.357 +    }
  53.358 +    dprintf("> IP header push...\n");
  53.359 +    __skb_push(skb, ip_n);
  53.360 +    if(0 && skb->mac.raw){
  53.361 +        dprintf("> ETH header push...\n");
  53.362 +        __skb_push(skb, ETH_HLEN);
  53.363 +    }
  53.364 +    // Fix ip header. Adjust length field, set protocol, zero
  53.365 +    // checksum.
  53.366 +    {
  53.367 +        // Total packet length (bytes).
  53.368 +        int tot_len = ntohs(skb->nh.iph->tot_len);
  53.369 +        tot_len += head_n;
  53.370 +        tot_len += tail_n;
  53.371 +        skb->nh.iph->protocol = IPPROTO_ESP;
  53.372 +        skb->nh.iph->tot_len  = htons(tot_len);
  53.373 +        skb->nh.iph->check    = 0;
  53.374 +    }
  53.375 +    err = Tunnel_send(tunnel, skb);
  53.376 +  exit:
  53.377 +    dprintf("< err=%d\n", err);
  53.378 +    return err;
  53.379 +}
  53.380 +
  53.381 +/** Release an skb context.
  53.382 + * Drops the refcount on the SA.
  53.383 + *
  53.384 + * @param context to free
  53.385 + */
  53.386 +static void esp_context_free_fn(SkbContext *context){
  53.387 +    SAState *sa;
  53.388 +    if(!context) return;
  53.389 +    sa = context->data;
  53.390 +    if(!sa) return;
  53.391 +    context->data = NULL;
  53.392 +    SAState_decref(sa);
  53.393 +}   
  53.394 +
  53.395 +/** Receive a packet via an ESP SA.
  53.396 + * Does ESP receive processing (check icv, decrypt), strips
  53.397 + * ESP header and re-receives.
  53.398 + *
  53.399 + * @param sa SA
  53.400 + * @param skb packet
  53.401 + * @return 0 on success, negative error code otherwise
  53.402 + */
  53.403 +static int esp_sa_recv(SAState *sa, struct sk_buff *skb){
  53.404 +    int err = -EINVAL;
  53.405 +    int mine = 0;
  53.406 +    int vnet = 0; //todo: fixme - need to record skb vnet somewhere
  53.407 +    ESPState *esp;
  53.408 +    ESPHdr *esph;
  53.409 +    ESPPadding *pad;
  53.410 +    int block_n;	// Cipher blocksize.
  53.411 +    int icv_n;          // Size of integrity check value (icv).
  53.412 +    int iv_n;           // Size of initialization vector (iv).
  53.413 +    int text_n;         // Size of text (ciphertext or plaintext).
  53.414 +    int head_n;         // Size of esp header and iv.
  53.415 +
  53.416 +    dprintf("> skb=%p\n", skb);
  53.417 +    // Assumes skb->data points at esp hdr.
  53.418 +    esph = (void*)skb->data;
  53.419 +    esp = sa->data;
  53.420 +    block_n = crypto_tfm_alg_blocksize(esp->cipher.tfm);
  53.421 +    icv_n = esp->digest.icv_n;
  53.422 +    iv_n = esp->cipher.iv_n;
  53.423 +    head_n = ESP_HDR_N + iv_n;
  53.424 +    text_n = skb->len - head_n - icv_n;
  53.425 +    if(text_n < ESP_PAD_N || !multipleof(text_n, block_n)){
  53.426 +        wprintf("> Invalid size: text_n=%d tfm:block_n=%d esp:block_n=%d\n",
  53.427 +                text_n, block_n, esp->cipher.block_n);
  53.428 +        goto exit;
  53.429 +    }
  53.430 +    if(icv_n){
  53.431 +        err = esp_check_icv(sa, esp, esph, skb);
  53.432 +        if(err) goto exit;
  53.433 +    }
  53.434 +    mine = 1;
  53.435 +    if(sa->security & SA_CONF){
  53.436 +        err = esp_sa_decrypt(esp, esph, skb, head_n, iv_n, text_n);
  53.437 +        if(err) goto exit;
  53.438 +    }
  53.439 +    // Strip esp header by moving the other headers down.
  53.440 +    //todo Maybe not safe to do this anymore.
  53.441 +    memmove(skb->mac.raw + head_n, skb->mac.raw, (skb->data - skb->mac.raw));
  53.442 +    skb->mac.raw += head_n;
  53.443 +    skb->nh.raw  += head_n;
  53.444 +    // Move skb->data back to ethernet header.
  53.445 +    // Do in 2 moves to ensure offsets are +ve,
  53.446 +    // since args to skb_pull/skb_push are unsigned.
  53.447 +    __skb_pull(skb, head_n);
  53.448 +    __skb_push(skb, skb->data - skb->mac.raw);
  53.449 +    // After this esph is invalid.
  53.450 +    esph = NULL;
  53.451 +    // Trim padding, restore protocol in IP header.
  53.452 +    pad = skb_trim_tail(skb, ESP_PAD_N);
  53.453 +    text_n -= ESP_PAD_N;
  53.454 +    if((pad->pad_n > 255) | (pad->pad_n > text_n)){
  53.455 +        wprintf("> Invalid padding: pad_n=%d text_n=%d\n", pad->pad_n, text_n);
  53.456 +        goto exit;
  53.457 +    }
  53.458 +    skb_trim_tail(skb, pad->pad_n);
  53.459 +    skb->nh.iph->protocol = pad->protocol;
  53.460 +    err = skb_push_context(skb, vnet, sa->ident.addr, IPPROTO_ESP,
  53.461 +                           sa, esp_context_free_fn);
  53.462 +    if(err) goto exit;
  53.463 +    // Increase sa refcount now the skb context refers to it.
  53.464 +    SAState_incref(sa);
  53.465 +    err = netif_rx(skb);
  53.466 +  exit:
  53.467 +    if(mine) err = 1;
  53.468 +    dprintf("< skb=%p err=%d\n", skb, err);
  53.469 +    return err;
  53.470 +}
  53.471 +
  53.472 +/** Estimate the packet size for some data using ESP processing.    
  53.473 + *
  53.474 + * @param sa ESP SA
  53.475 + * @param data_n data size
  53.476 + * @return size after ESP processing
  53.477 + */
  53.478 +static u32 esp_sa_size(SAState *sa, int data_n){
  53.479 +    // Even in transport mode have to round up to blocksize.
  53.480 +    // Have to add some padding for alignment even if pad_n is zero.
  53.481 +    ESPState *esp = sa->data;
  53.482 +    
  53.483 +    data_n = roundup(data_n + ESP_PAD_N, esp->cipher.block_n);
  53.484 +    if(esp->cipher.pad_n > 0){
  53.485 +        data_n = roundup(data_n, esp->cipher.pad_n);
  53.486 +    }
  53.487 +    data_n += esp->digest.icv_n;
  53.488 +    //data_n += esp->cipher.iv_n;
  53.489 +    data_n += ESP_HDR_N;
  53.490 +    return data_n;
  53.491 +}
  53.492 +
  53.493 +/** Compute an icv using HMAC digest.
  53.494 + *
  53.495 + * @param esp ESP state
  53.496 + * @param skb packet to digest
  53.497 + * @param offset offset to start at
  53.498 + * @param len number of bytes to digest
  53.499 + * @param icv return parameter for ICV
  53.500 + * @return 0 on success, negative error code otherwise
  53.501 + */
  53.502 +static inline void esp_hmac_digest(ESPState *esp, struct sk_buff *skb,
  53.503 +                                   int offset, int len, u8 *icv){
  53.504 +    int err = 0;
  53.505 +    struct crypto_tfm *digest = esp->digest.tfm;
  53.506 +    char *icv_tmp = esp->digest.icv_tmp;
  53.507 +    int sg_n = skb_shinfo(skb)->nr_frags + 1;
  53.508 +    struct scatterlist sg[sg_n];
  53.509 +
  53.510 +    dprintf("> offset=%d len=%d\n", offset, len);
  53.511 +    memset(icv, 0, esp->digest.icv_n);
  53.512 +    if(DEBUG_ICV){
  53.513 +        dprintf("> key len=%d\n", esp->digest.key_n);
  53.514 +        printk("\nkey=");
  53.515 +        buf_print(esp->digest.key,esp->digest.key_n); 
  53.516 +    }
  53.517 +    crypto_hmac_init(digest, esp->digest.key, &esp->digest.key_n);
  53.518 +    err = skb_scatterlist(skb, sg, &sg_n, offset, len);
  53.519 +    crypto_hmac_update(digest, sg, sg_n);
  53.520 +    crypto_hmac_final(digest, esp->digest.key, &esp->digest.key_n, icv_tmp);
  53.521 +    if(DEBUG_ICV){
  53.522 +        dprintf("> digest len=%d ", esp->digest.icv_n);
  53.523 +        printk("\nval=");
  53.524 +        buf_print(icv_tmp, esp->digest.icv_n);
  53.525 +    }
  53.526 +    memcpy(icv, icv_tmp, esp->digest.icv_n);
  53.527 +    dprintf("<\n");
  53.528 +}
  53.529 +
  53.530 +/** Finish up an esp state.
  53.531 + * Releases the digest, cipher, iv and frees the state.
  53.532 + *
  53.533 + * @parma esp state
  53.534 + */
  53.535 +static void esp_fini(ESPState *esp){
  53.536 +    if(!esp) return;
  53.537 +    if(esp->digest.tfm){
  53.538 +        crypto_free_tfm(esp->digest.tfm);
  53.539 +        esp->digest.tfm = NULL; 
  53.540 +    }
  53.541 +    if(esp->digest.icv_tmp){
  53.542 +        kfree(esp->digest.icv_tmp);
  53.543 +        esp->digest.icv_tmp = NULL;
  53.544 +    }
  53.545 +    if(esp->cipher.tfm){
  53.546 +        crypto_free_tfm(esp->cipher.tfm);
  53.547 +        esp->cipher.tfm = NULL;
  53.548 +    }
  53.549 +    if(esp->cipher.iv){
  53.550 +        kfree(esp->cipher.iv);
  53.551 +        esp->cipher.iv = NULL;
  53.552 +    }
  53.553 +    kfree(esp);
  53.554 +}
  53.555 +
  53.556 +/** Release an ESP SA.
  53.557 + *
  53.558 + * @param sa ESO SA
  53.559 + */
  53.560 +static void esp_sa_fini(SAState *sa){
  53.561 +    ESPState *esp;
  53.562 +    if(!sa) return;
  53.563 +    esp = sa->data;
  53.564 +    if(!esp) return;
  53.565 +    esp_fini(esp);
  53.566 +    sa->data = NULL;
  53.567 +}
  53.568 +
  53.569 +/** Initialize the cipher for an ESP SA.
  53.570 + *
  53.571 + * @param sa ESP SA
  53.572 + * @param esp ESP state
  53.573 + * @return 0 on success, negative error code otherwise
  53.574 + */
  53.575 +static int esp_cipher_init(SAState *sa, ESPState *esp){
  53.576 +    int err = 0; 
  53.577 +    SAAlgorithm *algo = NULL;
  53.578 +    int cipher_mode = CRYPTO_TFM_MODE_CBC;
  53.579 +
  53.580 +    dprintf("> sa=%p esp=%p\n", sa, esp);
  53.581 +    dprintf("> cipher=%s\n", sa->cipher.name);
  53.582 +    algo = sa_cipher_by_name(sa->cipher.name);
  53.583 +    if(!algo){
  53.584 +        wprintf("> Cipher unavailable: %s\n", sa->cipher.name);
  53.585 +        err = -EINVAL;
  53.586 +        goto exit;
  53.587 +    }
  53.588 +    esp->cipher.key_n = roundup(sa->cipher.bits, 8);
  53.589 +    // If cipher is null must use ECB because CBC algo does not support blocksize 1.
  53.590 +    if(strcmp(sa->cipher.name, "cipher_null")){
  53.591 +        cipher_mode = CRYPTO_TFM_MODE_ECB;
  53.592 +    }
  53.593 +    esp->cipher.tfm = crypto_alloc_tfm(sa->cipher.name, cipher_mode);
  53.594 +    if(!esp->cipher.tfm){
  53.595 +        err = -ENOMEM;
  53.596 +        goto exit;
  53.597 +    }
  53.598 +    esp->cipher.block_n = roundup(crypto_tfm_alg_blocksize(esp->cipher.tfm), 4);
  53.599 +    esp->cipher.iv_n = crypto_tfm_alg_ivsize(esp->cipher.tfm);
  53.600 +    esp->cipher.pad_n = 0;
  53.601 +    if(esp->cipher.iv_n){
  53.602 +        esp->cipher.iv = kmalloc(esp->cipher.iv_n, GFP_KERNEL);
  53.603 +        get_random_bytes(esp->cipher.iv, esp->cipher.iv_n);
  53.604 +    }
  53.605 +    crypto_cipher_setkey(esp->cipher.tfm, esp->cipher.key, esp->cipher.key_n);
  53.606 +    err = 0;
  53.607 +  exit:
  53.608 +    dprintf("< err=%d\n", err);
  53.609 +    return err;
  53.610 +}
  53.611 +
  53.612 +/** Initialize the digest for an ESP SA.
  53.613 + *
  53.614 + * @param sa ESP SA
  53.615 + * @param esp ESP state
  53.616 + * @return 0 on success, negative error code otherwise
  53.617 + */
  53.618 +static int esp_digest_init(SAState *sa, ESPState *esp){
  53.619 +    int err = 0;
  53.620 +    SAAlgorithm *algo = NULL;
  53.621 +    
  53.622 +    dprintf(">\n");
  53.623 +    esp->digest.key = sa->digest.key;
  53.624 +    esp->digest.key_n = bits_to_bytes(roundup(sa->digest.bits, 8));
  53.625 +    esp->digest.tfm = crypto_alloc_tfm(sa->digest.name, 0);
  53.626 +    if(!esp->digest.tfm){
  53.627 +        err = -ENOMEM;
  53.628 +        goto exit;
  53.629 +    }
  53.630 +    algo = sa_digest_by_name(sa->digest.name);
  53.631 +    if(!algo){
  53.632 +        wprintf("> Digest unavailable: %s\n", sa->digest.name);
  53.633 +        err = -EINVAL;
  53.634 +        goto exit;
  53.635 +    }
  53.636 +    esp->digest.icv = esp_hmac_digest;
  53.637 +    esp->digest.icv_full_n = bits_to_bytes(algo->info.digest.icv_fullbits);
  53.638 +    esp->digest.icv_n = bits_to_bytes(algo->info.digest.icv_truncbits);
  53.639 +    
  53.640 +    if(esp->digest.icv_full_n != crypto_tfm_alg_digestsize(esp->digest.tfm)){
  53.641 +        err = -EINVAL;
  53.642 +        wprintf("> digest %s, size %u != %hu\n",
  53.643 +                sa->digest.name,
  53.644 +                crypto_tfm_alg_digestsize(esp->digest.tfm),
  53.645 +                esp->digest.icv_full_n);
  53.646 +        goto exit;
  53.647 +    }
  53.648 +    
  53.649 +    esp->digest.icv_tmp = kmalloc(esp->digest.icv_full_n, GFP_KERNEL);
  53.650 +    if(!esp->digest.icv_tmp){
  53.651 +        err = -ENOMEM;
  53.652 +        goto exit;
  53.653 +    }
  53.654 +  exit:
  53.655 +    dprintf("< err=%d\n", err);
  53.656 +    return err;
  53.657 +}
  53.658 +
  53.659 +/** Initialize an ESP SA.
  53.660 + *
  53.661 + * @param sa ESP SA
  53.662 + * @param args arguments
  53.663 + * @return 0 on success, negative error code otherwise
  53.664 + */
  53.665 +static int esp_sa_init(SAState *sa, void *args){
  53.666 +    int err = 0;
  53.667 +    ESPState *esp = NULL;
  53.668 +    
  53.669 +    dprintf("> sa=%p\n", sa);
  53.670 +    esp = kmalloc(sizeof(*esp), GFP_KERNEL);
  53.671 +    if(!esp){
  53.672 +        err = -ENOMEM;
  53.673 +        goto exit;
  53.674 +    }
  53.675 +    *esp = (ESPState){};
  53.676 +    err = esp_cipher_init(sa, esp);
  53.677 +    if(err) goto exit;
  53.678 +    err = esp_digest_init(sa, esp);
  53.679 +    if(err) goto exit;
  53.680 +    sa->data = esp;
  53.681 +  exit:
  53.682 +    if(err){
  53.683 +        if(esp) esp_fini(esp);
  53.684 +    }
  53.685 +    dprintf("< err=%d\n", err);
  53.686 +    return err;
  53.687 +}
  53.688 +
  53.689 +/** SA type for ESP.
  53.690 + */
  53.691 +static SAType esp_sa_type = {
  53.692 +    .name     = "ESP",
  53.693 +    .protocol = IPPROTO_ESP,
  53.694 +    .init     = esp_sa_init,
  53.695 +    .fini     = esp_sa_fini,
  53.696 +    .size     = esp_sa_size,
  53.697 +    .recv     = esp_sa_recv,
  53.698 +    .send     = esp_sa_send
  53.699 +};
  53.700 +
  53.701 +/** Get the ESP header from a packet.
  53.702 + *
  53.703 + * @param skb packet
  53.704 + * @param esph return parameter for header
  53.705 + * @return 0 on success, negative error code otherwise
  53.706 + */
  53.707 +static int esp_skb_header(struct sk_buff *skb, ESPHdr **esph){
  53.708 +    int err = 0;
  53.709 +    if(skb->len < ESP_HDR_N){
  53.710 +        err = -EINVAL;
  53.711 +        goto exit;
  53.712 +    }
  53.713 +    *esph = (ESPHdr*)skb->data;
  53.714 +  exit:
  53.715 +    return err;
  53.716 +}
  53.717 +
  53.718 +/** Handle an incoming skb with ESP protocol.
  53.719 + *
  53.720 + * Lookup spi, if state found hand to the state.
  53.721 + * If no state, check spi, if ok, create state and pass to it.
  53.722 + * If spi not ok, drop.
  53.723 + * 
  53.724 + * @param skb packet
  53.725 + * @return 0 on sucess, negative error code otherwise
  53.726 + */
  53.727 +static int esp_protocol_recv(struct sk_buff *skb){
  53.728 +    int err = 0;
  53.729 +    const int eth_n = ETH_HLEN;
  53.730 +    int ip_n;
  53.731 +    ESPHdr *esph = NULL;
  53.732 +    SAState *sa = NULL;
  53.733 +    u32 addr;
  53.734 +    
  53.735 +    dprintf(">\n");
  53.736 +    dprintf("> recv skb=\n"); skb_print_bits(skb, 0, skb->len);
  53.737 +    ip_n = (skb->nh.iph->ihl << 2);
  53.738 +    if(skb->data == skb->mac.raw){
  53.739 +        // skb->data points at ethernet header.
  53.740 +        if (!pskb_may_pull(skb, eth_n + ip_n)){
  53.741 +            wprintf("> Malformed skb\n");
  53.742 +            err = -EINVAL;
  53.743 +            goto exit;
  53.744 +        }
  53.745 +        skb_pull(skb, eth_n + ip_n);
  53.746 +    }
  53.747 +    addr = skb->nh.iph->daddr;
  53.748 +    err = esp_skb_header(skb, &esph);
  53.749 +    if(err) goto exit;
  53.750 +    dprintf("> spi=%08x protocol=%d addr=" IPFMT "\n",
  53.751 +            esph->spi, IPPROTO_ESP, NIPQUAD(addr));
  53.752 +    sa = sa_table_lookup_spi(esph->spi, IPPROTO_ESP, addr);
  53.753 +    if(!sa){
  53.754 +        err = vnet_sa_create(esph->spi, IPPROTO_ESP, addr, &sa);
  53.755 +        if(err) goto exit;
  53.756 +    }
  53.757 +    err = SAState_recv(sa, skb);
  53.758 +  exit:
  53.759 +    if(sa) SAState_decref(sa);
  53.760 +    dprintf("< err=%d\n", err);
  53.761 +    return err;
  53.762 +}
  53.763 +
  53.764 +/** Handle an ICMP error related to ESP.
  53.765 + *
  53.766 + * @param skb ICMP error packet
  53.767 + * @param info
  53.768 + */
  53.769 +static void esp_protocol_icmp_err(struct sk_buff *skb, u32 info){
  53.770 +    struct iphdr *iph = (struct iphdr*)skb->data;
  53.771 +    ESPHdr *esph;
  53.772 +    SAState *sa;
  53.773 +    
  53.774 +    dprintf("> ICMP error type=%d code=%d\n",
  53.775 +            skb->h.icmph->type, skb->h.icmph->code);
  53.776 +    if(skb->h.icmph->type != ICMP_DEST_UNREACH ||
  53.777 +       skb->h.icmph->code != ICMP_FRAG_NEEDED){
  53.778 +        return;
  53.779 +    }
  53.780 +    
  53.781 +    //todo: need to check skb has enough len to do this.
  53.782 +    esph = (ESPHdr*)(skb->data + (iph->ihl << 2));
  53.783 +    sa = sa_table_lookup_spi(esph->spi, IPPROTO_ESP, iph->daddr);
  53.784 +    if(!sa) return;
  53.785 +    wprintf("> ICMP unreachable on SA ESP spi=%08x addr=" IPFMT "\n",
  53.786 +            ntohl(esph->spi), NIPQUAD(iph->daddr));
  53.787 +    SAState_decref(sa);
  53.788 +}
  53.789 +
  53.790 +//============================================================================
  53.791 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  53.792 +// Code for 2.6 kernel.
  53.793 +
  53.794 +/** Protocol handler for ESP.
  53.795 + */
  53.796 +static struct net_protocol esp_protocol = {
  53.797 +    .handler     = esp_protocol_recv,
  53.798 +    .err_handler = esp_protocol_icmp_err
  53.799 +};
  53.800 +
  53.801 +static int esp_protocol_add(void){
  53.802 +    return inet_add_protocol(&esp_protocol, IPPROTO_ESP);
  53.803 +}
  53.804 +
  53.805 +static int esp_protocol_del(void){
  53.806 +    return inet_del_protocol(&esp_protocol, IPPROTO_ESP);
  53.807 +}
  53.808 +
  53.809 +//============================================================================
  53.810 +#else
  53.811 +//============================================================================
  53.812 +// Code for 2.4 kernel.
  53.813 +
  53.814 +/** Protocol handler for ESP.
  53.815 + */
  53.816 +static struct inet_protocol esp_protocol = {
  53.817 +    .name        = "ESP",
  53.818 +    .protocol    = IPPROTO_ESP,
  53.819 +    .handler     = esp_protocol_recv,
  53.820 +    .err_handler = esp_protocol_icmp_err
  53.821 +};
  53.822 +
  53.823 +static int esp_protocol_add(void){
  53.824 +    inet_add_protocol(&esp_protocol);
  53.825 +    return 0;
  53.826 +}
  53.827 +
  53.828 +static int esp_protocol_del(void){
  53.829 +    return inet_del_protocol(&esp_protocol);
  53.830 +}
  53.831 +
  53.832 +#endif
  53.833 +//============================================================================
  53.834 +
  53.835 +
  53.836 +/** Initialize the ESP module.
  53.837 + * Registers the ESP protocol and SA type.
  53.838 + *
  53.839 + * @return 0 on success, negative error code otherwise
  53.840 + */
  53.841 +int __init esp_module_init(void){
  53.842 +    int err = 0;
  53.843 +    dprintf(">\n");
  53.844 +    err = SAType_add(&esp_sa_type);
  53.845 +    if(err < 0){
  53.846 +        eprintf("> Error adding esp sa type\n");
  53.847 +        goto exit;
  53.848 +    }
  53.849 +    esp_protocol_add();
  53.850 +  exit:
  53.851 +    dprintf("< err=%d\n", err);
  53.852 +    return err;
  53.853 +}
  53.854 +
  53.855 +/** Finalize the ESP module.
  53.856 + * Deregisters the ESP protocol and SA type.
  53.857 + */
  53.858 +void __exit esp_module_exit(void){
  53.859 +    if(esp_protocol_del() < 0){
  53.860 +        eprintf("> Error removing esp protocol\n");
  53.861 +    }
  53.862 +    if(SAType_del(&esp_sa_type) < 0){
  53.863 +        eprintf("> Error removing esp sa type\n");
  53.864 +    }
  53.865 +}
  53.866 +
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/tools/vnet/vnet-module/esp.h	Wed Nov 24 12:07:16 2004 +0000
    54.3 @@ -0,0 +1,111 @@
    54.4 +/*
    54.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    54.6 + *
    54.7 + * This program is free software; you can redistribute it and/or modify
    54.8 + * it under the terms of the GNU General Public License as published by the 
    54.9 + * Free Software Foundation; either version 2 of the License, or (at your
   54.10 + * option) any later version.
   54.11 + * 
   54.12 + * This program is distributed in the hope that it will be useful, but
   54.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   54.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   54.15 + * for more details.
   54.16 + *
   54.17 + * You should have received a copy of the GNU General Public License along
   54.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   54.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   54.20 + *
   54.21 + */
   54.22 +#ifndef __VNET_ESP_H__
   54.23 +#define __VNET_ESP_H__
   54.24 +
   54.25 +#include <linux/config.h>
   54.26 +#include <linux/types.h>
   54.27 +#include <linux/crypto.h>
   54.28 +
   54.29 +/** Header used by IPSEC ESP (Encapsulated Security Payload). */
   54.30 +typedef struct ESPHdr {
   54.31 +    /** The spi (security parameters index). */
   54.32 +    u32 spi;
   54.33 +    /** Sequence number. */
   54.34 +    u32 seq;
   54.35 +    /* Variable length data (depends on crypto suite).
   54.36 +       Mind the 64 bit alignment! */
   54.37 +    u8  data[0];
   54.38 +} ESPHdr;
   54.39 +
   54.40 +/** Padding trailer used by IPSEC ESP.
   54.41 + * Follows the padding itself with the padding length and the
   54.42 + * protocol being encapsulated.
   54.43 + */
   54.44 +typedef struct ESPPadding {
   54.45 +    u8 pad_n;
   54.46 +    u8 protocol;
   54.47 +} ESPPadding;
   54.48 +
   54.49 +/** Size of the esp header (spi and seq). */
   54.50 +static const int ESP_HDR_N = sizeof(ESPHdr);
   54.51 +
   54.52 +/** Size of the esp pad and next protocol field. */
   54.53 +static const int ESP_PAD_N = sizeof(ESPPadding);
   54.54 +
   54.55 +enum {
   54.56 +    SASTATE_VOID,
   54.57 +    SASTATE_ACQUIRE,
   54.58 +    SASTATE_VALID,
   54.59 +    SASTATE_ERROR,
   54.60 +    SASTATE_EXPIRED,
   54.61 +    SASTATE_DEAD,
   54.62 +};
   54.63 +
   54.64 +struct ESPState;
   54.65 +
   54.66 +/** A cipher instance. */
   54.67 +typedef struct ESPCipher {
   54.68 +    /** Cipher key. */
   54.69 +    u8 *key;
   54.70 +    /** Key size (bytes). */
   54.71 +    int key_n;
   54.72 +    /** Initialization vector (IV). */
   54.73 +    u8 *iv;
   54.74 +    /** IV size (bytes). */
   54.75 +    int iv_n;
   54.76 +    /** Block size for padding (bytes). */
   54.77 +    int pad_n;
   54.78 +    /** Cipher block size (bytes). */
   54.79 +    int block_n;
   54.80 +    /** Cipher crypto transform. */
   54.81 +    struct crypto_tfm *tfm;
   54.82 +} ESPCipher;
   54.83 +
   54.84 +/** A digest instance. */
   54.85 +typedef struct ESPDigest {
   54.86 +    /** Digest key. */
   54.87 +    u8 *key;
   54.88 +    /** Key size (bytes) */
   54.89 +    int key_n;
   54.90 +    /** ICV size used (bytes). */
   54.91 +    u8 icv_n;
   54.92 +    /** Full ICV size when computed (bytes). */
   54.93 +    u8 icv_full_n;
   54.94 +    /** Working storage for computing ICV. */
   54.95 +    u8 *icv_tmp;
   54.96 +    /** Function used to compute ICV (e.g. HMAC). */
   54.97 +    void (*icv)(struct ESPState *esp,
   54.98 +                struct sk_buff *skb,
   54.99 +                int offset,
  54.100 +                int len,
  54.101 +                u8 *icv);
  54.102 +    /** Digest crypto transform (e.g. SHA). */
  54.103 +    struct crypto_tfm *tfm;
  54.104 +} ESPDigest;
  54.105 +
  54.106 +typedef struct ESPState {
  54.107 +    struct ESPCipher cipher;
  54.108 +    struct ESPDigest digest;
  54.109 +} ESPState;
  54.110 +
  54.111 +extern int esp_module_init(void);
  54.112 +extern void esp_module_exit(void);
  54.113 +
  54.114 +#endif /* !__VNET_ESP_H__ */
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/tools/vnet/vnet-module/etherip.c	Wed Nov 24 12:07:16 2004 +0000
    55.3 @@ -0,0 +1,411 @@
    55.4 +/*
    55.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    55.6 + *
    55.7 + * This program is free software; you can redistribute it and/or modify
    55.8 + * it under the terms of the GNU General Public License as published by the 
    55.9 + * Free Software Foundation; either version 2 of the License, or (at your
   55.10 + * option) any later version.
   55.11 + * 
   55.12 + * This program is distributed in the hope that it will be useful, but
   55.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   55.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   55.15 + * for more details.
   55.16 + *
   55.17 + * You should have received a copy of the GNU General Public License along
   55.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   55.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   55.20 + *
   55.21 + */
   55.22 +#include <linux/config.h>
   55.23 +#include <linux/module.h>
   55.24 +#include <linux/types.h>
   55.25 +#include <linux/kernel.h>
   55.26 +#include <linux/init.h>
   55.27 +
   55.28 +#include <linux/version.h>
   55.29 +
   55.30 +#include <linux/skbuff.h>
   55.31 +#include <linux/net.h>
   55.32 +#include <linux/netdevice.h>
   55.33 +#include <linux/in.h>
   55.34 +#include <linux/inet.h>
   55.35 +#include <linux/netfilter_ipv4.h>
   55.36 +#include <linux/icmp.h>
   55.37 +
   55.38 +#include <net/ip.h>
   55.39 +#include <net/protocol.h>
   55.40 +#include <net/route.h>
   55.41 +#include <net/checksum.h>
   55.42 +
   55.43 +#include <etherip.h>
   55.44 +#include <tunnel.h>
   55.45 +#include <vnet.h>
   55.46 +#include <varp.h>
   55.47 +#include <if_varp.h>
   55.48 +#include <skb_util.h>
   55.49 +
   55.50 +#define MODULE_NAME "VNET"
   55.51 +//#define DEBUG 1
   55.52 +#undef DEBUG
   55.53 +#include "debug.h"
   55.54 +
   55.55 +/** @file Etherip implementation.
   55.56 + * The etherip protocol is used to transport Ethernet frames in IP packets.
   55.57 + */
   55.58 +
   55.59 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
   55.60 +#define MAC_ETH(_skb) ((struct ethhdr *)(_skb)->mac.raw)
   55.61 +#else
   55.62 +#define MAC_ETH(_skb) ((_skb)->mac.ethernet)
   55.63 +#endif
   55.64 +
   55.65 +/** Get the vnet label from an etherip header.
   55.66 + *
   55.67 + * @param hdr header
   55.68 + * @return vnet (in host order)
   55.69 + */
   55.70 +int etheriphdr_get_vnet(struct etheriphdr *hdr){
   55.71 +#ifdef CONFIG_ETHERIP_EXT
   55.72 +    return ntohl(hdr->vnet);
   55.73 +#else
   55.74 +    return hdr->reserved;
   55.75 +#endif
   55.76 +}
   55.77 +
   55.78 +/** Set the vnet label in an etherip header.
   55.79 + * Also sets the etherip version.
   55.80 + *
   55.81 + * @param hdr header
   55.82 + * @param vnet vnet label (in host order)
   55.83 + */
   55.84 +void etheriphdr_set_vnet(struct etheriphdr *hdr, int vnet){
   55.85 +#ifdef CONFIG_ETHERIP_EXT
   55.86 +    hdr->version = 4;
   55.87 +    hdr->vnet = htonl(vnet);
   55.88 +#else
   55.89 +    hdr->version = 3;
   55.90 +    hdr->reserved = vnet & 0x0fff;
   55.91 +#endif
   55.92 +}
   55.93 +
   55.94 +/** Open an etherip tunnel.
   55.95 + *
   55.96 + * @param tunnel to open
   55.97 + * @return 0 on success, error code otherwise
   55.98 + */
   55.99 +static int etherip_tunnel_open(Tunnel *tunnel){
  55.100 +    return 0;
  55.101 +}
  55.102 +
  55.103 +/** Close an etherip tunnel.
  55.104 + *
  55.105 + * @param tunnel to close
  55.106 + */
  55.107 +static void etherip_tunnel_close(Tunnel *tunnel){
  55.108 +}
  55.109 +
  55.110 +
  55.111 +/** Send a packet via an etherip tunnel.
  55.112 + * Adds etherip header, new ip header, new ethernet header around
  55.113 + * ethernet frame.
  55.114 + *
  55.115 + * @param tunnel tunnel
  55.116 + * @param skb packet
  55.117 + * @return 0 on success, error code otherwise
  55.118 + */
  55.119 +static int etherip_tunnel_send(Tunnel *tunnel, struct sk_buff *skb){
  55.120 +    int err = 0;
  55.121 +    const int etherip_n = sizeof(struct etheriphdr);
  55.122 +    const int ip_n = sizeof(struct iphdr);
  55.123 +    const int eth_n = ETH_HLEN;
  55.124 +    int head_n = 0;
  55.125 +    int vnet = tunnel->key.vnet;
  55.126 +    struct etheriphdr *etheriph;
  55.127 +    struct ethhdr *ethh;
  55.128 +    u32 saddr = 0;
  55.129 +
  55.130 +    dprintf("> skb=%p vnet=%d\n", skb, vnet);
  55.131 +    head_n = etherip_n + ip_n + eth_n;
  55.132 +    err = skb_make_room(&skb, skb, head_n, 0);
  55.133 +    if(err) goto exit;
  55.134 +
  55.135 +    //err = vnet_get_device_address(skb->dev, &saddr);
  55.136 +    //if(err) goto exit;
  55.137 +    
  55.138 +    // The original ethernet header.
  55.139 +    ethh = MAC_ETH(skb);
  55.140 +    //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len);
  55.141 +    // Null the pointer as we are pushing a new IP header.
  55.142 +    skb->mac.raw = NULL;
  55.143 +
  55.144 +    // Setup the etherip header.
  55.145 +    //dprintf("> push etherip header...\n");
  55.146 +    etheriph = (struct etheriphdr *)skb_push(skb, etherip_n);
  55.147 +    etheriphdr_set_vnet(etheriph, vnet);
  55.148 +
  55.149 +    // Setup the IP header.
  55.150 +    //dprintf("> push IP header...\n");
  55.151 +    skb->nh.raw = skb_push(skb, ip_n); 
  55.152 +    skb->nh.iph->version  = 4;			// Standard version.
  55.153 +    skb->nh.iph->ihl      = ip_n / 4;		// IP header length (32-bit words).
  55.154 +    skb->nh.iph->tos      = 0;			// No special type-of-service.
  55.155 +    skb->nh.iph->tot_len  = htons(skb->len);    // Total packet length (bytes).
  55.156 +    skb->nh.iph->id       = 0;			// No flow id (since no frags).
  55.157 +    skb->nh.iph->frag_off = htons(IP_DF);	// Don't fragment - can't handle frags.
  55.158 +    skb->nh.iph->ttl      = 64;			// Linux default time-to-live.
  55.159 +    skb->nh.iph->protocol = IPPROTO_ETHERIP;    // IP protocol number.
  55.160 +    skb->nh.iph->saddr    = saddr;		// Source address.
  55.161 +    skb->nh.iph->daddr    = tunnel->key.addr;	// Destination address.
  55.162 +    skb->nh.iph->check    = 0;
  55.163 +
  55.164 +    // Ethernet header will be filled-in by device.
  55.165 +    err = Tunnel_send(tunnel->base, skb);
  55.166 +    skb = NULL;
  55.167 +  exit:
  55.168 +    if(err && skb) dev_kfree_skb(skb);
  55.169 +    //dprintf("< err=%d\n", err);
  55.170 +    return err;
  55.171 +}
  55.172 +
  55.173 +/** Tunnel type for etherip.
  55.174 + */
  55.175 +static TunnelType _etherip_tunnel_type = {
  55.176 +    .name	= "ETHERIP",
  55.177 +    .open	= etherip_tunnel_open,
  55.178 +    .close	= etherip_tunnel_close,
  55.179 +    .send 	= etherip_tunnel_send
  55.180 +};
  55.181 +
  55.182 +TunnelType *etherip_tunnel_type = &_etherip_tunnel_type;
  55.183 +
  55.184 +/* Defeat compiler warnings about unused functions. */
  55.185 +static void print_str(char *s, int n) __attribute__((unused));
  55.186 +
  55.187 +static void print_str(char *s, int n) {
  55.188 +    int i;
  55.189 +
  55.190 +    for(i=0; i<n; s++, i++){
  55.191 +        if(i && i % 40 == 0) printk("\n");
  55.192 +        if(('a'<= *s && *s <= 'z') ||
  55.193 +           ('A'<= *s && *s <= 'Z') ||
  55.194 +           ('0'<= *s && *s <= '9')){
  55.195 +            printk("%c", *s);
  55.196 +        } else {
  55.197 +            printk("<%x>", (unsigned)(0xff & *s));
  55.198 +        }
  55.199 +    }
  55.200 +    printk("\n");
  55.201 +}
  55.202 +
  55.203 +/** Do etherip receive processing.
  55.204 + * Strips etherip header to extract the ethernet frame, sets
  55.205 + * the vnet from the header and re-receives the frame.
  55.206 + *
  55.207 + * @param skb packet
  55.208 + * @return 0 on success, error code otherwise
  55.209 + */
  55.210 +static int etherip_protocol_recv(struct sk_buff *skb){
  55.211 +    int err = 0;
  55.212 +    int mine = 0;
  55.213 +    const int eth_n = ETH_HLEN;
  55.214 +    int ip_n;
  55.215 +    const int etherip_n = sizeof(struct etheriphdr);
  55.216 +    struct etheriphdr *etheriph;
  55.217 +    struct ethhdr *ethhdr;
  55.218 +    Vnet *vinfo = NULL;
  55.219 +    u32 vnet;
  55.220 +
  55.221 +    ethhdr = MAC_ETH(skb);
  55.222 +    if(MULTICAST(skb->nh.iph->daddr) &&
  55.223 +       (skb->nh.iph->daddr != varp_mcast_addr)){
  55.224 +        // Ignore multicast packets not addressed to us.
  55.225 +        dprintf("> dst=%u.%u.%u.%u varp_mcast_addr=%u.%u.%u.%u\n",
  55.226 +                NIPQUAD(skb->nh.iph->daddr),
  55.227 +                NIPQUAD(varp_mcast_addr));
  55.228 +        goto exit;
  55.229 +    }
  55.230 +    ip_n = (skb->nh.iph->ihl << 2);
  55.231 +    if(skb->data == skb->mac.raw){
  55.232 +        // skb->data points at ethernet header.
  55.233 +        //dprintf("> len=%d\n", skb->len);
  55.234 +        if (!pskb_may_pull(skb, eth_n + ip_n)){
  55.235 +            wprintf("> Malformed skb\n");
  55.236 +            err = -EINVAL;
  55.237 +            goto exit;
  55.238 +        }
  55.239 +        skb_pull(skb, eth_n + ip_n);
  55.240 +    }
  55.241 +    // Assume skb->data points at etherip header.
  55.242 +    etheriph = (void*)skb->data;
  55.243 +    if(!pskb_may_pull(skb, etherip_n)){
  55.244 +        wprintf("> Malformed skb\n");
  55.245 +        err = -EINVAL;
  55.246 +        goto exit;
  55.247 +    }
  55.248 +    vnet = etheriphdr_get_vnet(etheriph);
  55.249 +    dprintf("> Rcvd skb=%p vnet=%d\n", skb, vnet);
  55.250 +    // If vnet is secure, context must include IPSEC ESP.
  55.251 +    err = vnet_check_context(vnet, SKB_CONTEXT(skb), &vinfo);
  55.252 +    Vnet_decref(vinfo);
  55.253 +    if(err){
  55.254 +        wprintf("> Failed security check\n");
  55.255 +        goto exit;
  55.256 +    }
  55.257 +    mine = 1;
  55.258 +    // Point at the headers in the contained ethernet frame.
  55.259 +    skb->mac.raw = skb_pull(skb, etherip_n);
  55.260 +
  55.261 +    // Know source ip, vnet, vmac, so could update varp cache.
  55.262 +    // But if traffic comes to us over a vnetd tunnel this points the coa
  55.263 +    // at the vnetd rather than the endpoint. So don't do it.
  55.264 +    //varp_update(htonl(vnet), MAC_ETH(skb)->h_source, skb->nh.iph->saddr);
  55.265 +
  55.266 +    // Assuming a standard Ethernet frame.
  55.267 +    skb->nh.raw = skb_pull(skb, ETH_HLEN);
  55.268 +
  55.269 +#ifdef CONFIG_NETFILTER
  55.270 +#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
  55.271 +    // This stops our new pkt header being clobbered by a subsequent
  55.272 +    // call to nf_bridge_maybe_copy_header. Just replicate the
  55.273 +    // corresponding nf_bridge_save_header.
  55.274 +    if(skb->nf_bridge){
  55.275 +        int header_size = 16;
  55.276 +        if(MAC_ETH(skb)->h_proto == __constant_htons(ETH_P_8021Q)) {
  55.277 +            header_size = 18;
  55.278 +        }
  55.279 +        memcpy(skb->nf_bridge->data, skb->data - header_size, header_size);
  55.280 +    }
  55.281 +#endif
  55.282 +#endif
  55.283 +    
  55.284 +    if(1){
  55.285 +	struct ethhdr *eth = MAC_ETH(skb);
  55.286 +        // Devices use eth_type_trans() to set skb->pkt_type and skb->protocol.
  55.287 +        // Set them from contained ethhdr, or leave as received?
  55.288 +        // 'Ware use of hard_header_len in eth_type_trans().
  55.289 +
  55.290 +        //skb->protocol = htons(ETH_P_IP);
  55.291 +
  55.292 +        if(ntohs(eth->h_proto) >= 1536){
  55.293 +            skb->protocol = eth->h_proto;
  55.294 +        } else {
  55.295 +            skb->protocol = htons(ETH_P_802_2);
  55.296 +        }
  55.297 +        
  55.298 +	if(mac_is_multicast(eth->h_dest)){
  55.299 +            if(mac_is_broadcast(eth->h_dest)){
  55.300 +                skb->pkt_type = PACKET_BROADCAST;
  55.301 +	    } else {
  55.302 +                skb->pkt_type = PACKET_MULTICAST;
  55.303 +            }
  55.304 +        } else {
  55.305 +            skb->pkt_type = PACKET_HOST;
  55.306 +	}
  55.307 +
  55.308 +        memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
  55.309 +        if (skb->ip_summed == CHECKSUM_HW){
  55.310 +            skb->ip_summed = CHECKSUM_NONE;
  55.311 +            //skb->csum = csum_sub(skb->csum,
  55.312 +            //                     csum_partial(skb->mac.raw, skb->nh.raw - skb->mac.raw, 0));
  55.313 +        }
  55.314 +        dst_release(skb->dst);
  55.315 +        skb->dst = NULL;
  55.316 +#ifdef CONFIG_NETFILTER
  55.317 +        nf_conntrack_put(skb->nfct);
  55.318 +        skb->nfct = NULL;
  55.319 +#ifdef CONFIG_NETFILTER_DEBUG
  55.320 +        skb->nf_debug = 0;
  55.321 +#endif
  55.322 +#endif
  55.323 +    }
  55.324 +
  55.325 +    //print_skb_data(__FUNCTION__, 0, skb, skb->mac.raw, skb->len + ETH_HLEN);
  55.326 +
  55.327 +    err = vnet_skb_recv(skb, vnet, (Vmac*)MAC_ETH(skb)->h_dest);
  55.328 +  exit:
  55.329 +    if(mine) err = 1;
  55.330 +    dprintf("< skb=%p err=%d\n", skb, err);
  55.331 +    return err;
  55.332 +}
  55.333 +
  55.334 +/** Handle an ICMP error related to etherip.
  55.335 + *
  55.336 + * @param skb ICMP error packet
  55.337 + * @param info
  55.338 + */
  55.339 +static void etherip_protocol_icmp_err(struct sk_buff *skb, u32 info){
  55.340 +    struct iphdr *iph = (struct iphdr*)skb->data;
  55.341 +    
  55.342 +    wprintf("> ICMP error type=%d code=%d addr=" IPFMT "\n",
  55.343 +            skb->h.icmph->type, skb->h.icmph->code, NIPQUAD(iph->daddr));
  55.344 +
  55.345 +    if (skb->h.icmph->type != ICMP_DEST_UNREACH ||
  55.346 +        skb->h.icmph->code != ICMP_FRAG_NEEDED){
  55.347 +        return;
  55.348 +    }
  55.349 +    wprintf("> MTU too big addr= " IPFMT "\n", NIPQUAD(iph->daddr)); 
  55.350 +}
  55.351 +
  55.352 +//============================================================================
  55.353 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
  55.354 +// Code for 2.6 kernel.
  55.355 +
  55.356 +/** Etherip protocol. */
  55.357 +static struct net_protocol etherip_protocol = {
  55.358 +    .handler	 = etherip_protocol_recv,
  55.359 +    .err_handler = etherip_protocol_icmp_err,
  55.360 +};
  55.361 +
  55.362 +static int etherip_protocol_add(void){
  55.363 +    return inet_add_protocol(&etherip_protocol, IPPROTO_ETHERIP);
  55.364 +}
  55.365 +
  55.366 +static int etherip_protocol_del(void){
  55.367 +    return inet_del_protocol(&etherip_protocol, IPPROTO_ETHERIP);
  55.368 +}
  55.369 +
  55.370 +//============================================================================
  55.371 +#else
  55.372 +//============================================================================
  55.373 +// Code for 2.4 kernel.
  55.374 +
  55.375 +/** Etherip protocol. */
  55.376 +static struct inet_protocol etherip_protocol = {
  55.377 +    .name        = "ETHERIP",
  55.378 +    .protocol    = IPPROTO_ETHERIP,
  55.379 +    .handler	 = etherip_protocol_recv,
  55.380 +    .err_handler = etherip_protocol_icmp_err,
  55.381 +};
  55.382 +
  55.383 +static int etherip_protocol_add(void){
  55.384 +    inet_add_protocol(&etherip_protocol);
  55.385 +    return 0;
  55.386 +}
  55.387 +
  55.388 +static int etherip_protocol_del(void){
  55.389 +    return inet_del_protocol(&etherip_protocol);
  55.390 +}
  55.391 +
  55.392 +#endif
  55.393 +//============================================================================
  55.394 +
  55.395 +
  55.396 +/** Initialize the etherip module.
  55.397 + * Registers the etherip protocol.
  55.398 + *
  55.399 + * @return 0 on success, error code otherwise
  55.400 + */
  55.401 +int __init etherip_module_init(void) {
  55.402 +    int err = 0;
  55.403 +    etherip_protocol_add();
  55.404 +    return err;
  55.405 +}
  55.406 +
  55.407 +/** Finalize the etherip module.
  55.408 + * Deregisters the etherip protocol.
  55.409 + */
  55.410 +void __exit etherip_module_exit(void) {
  55.411 +    if(etherip_protocol_del() < 0){
  55.412 +        printk(KERN_INFO "%s: can't remove etherip protocol\n", __FUNCTION__);
  55.413 +    }
  55.414 +}
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/tools/vnet/vnet-module/etherip.h	Wed Nov 24 12:07:16 2004 +0000
    56.3 @@ -0,0 +1,27 @@
    56.4 +/*
    56.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    56.6 + *
    56.7 + * This program is free software; you can redistribute it and/or modify
    56.8 + * it under the terms of the GNU General Public License as published by the 
    56.9 + * Free Software Foundation; either version 2 of the License, or (at your
   56.10 + * option) any later version.
   56.11 + * 
   56.12 + * This program is distributed in the hope that it will be useful, but
   56.13 + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   56.14 + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   56.15 + * for more details.
   56.16 + *
   56.17 + * You should have received a copy of the GNU General Public License along
   56.18 + * with this program; if not, write to the Free software Foundation, Inc.,
   56.19 + * 59 Temple Place, suite 330, Boston, MA 02111-1307 USA
   56.20 + *
   56.21 + */
   56.22 +#ifndef _VNET_ETHERIP_H_
   56.23 +#define _VNET_ETHERIP_H_
   56.24 +
   56.25 +#include "if_etherip.h"
   56.26 +
   56.27 +extern int etherip_module_init(void);
   56.28 +extern void etherip_module_exit(void);
   56.29 +
   56.30 +#endif
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/tools/vnet/vnet-module/if_etherip.h	Wed Nov 24 12:07:16 2004 +0000
    57.3 @@ -0,0 +1,51 @@
    57.4