commit ed055f88e82498a15a60ed42ada7a48f905b146c
parent 35980a88b773e09e9ab64afbee3161ec3424edec
Author: Tomas Hlavaty <tom@logand.com>
Date: Sun, 7 Dec 2014 17:05:40 +0100
deal with little and big endian
Diffstat:
M | dns.lisp | | | 40 | ++++++++++++++++++++-------------------- |
M | rw.lisp | | | 115 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
M | tls.lisp | | | 99 | ++++++++++++++++++++++++++++++++++++++++--------------------------------------- |
M | wire.lisp | | | 56 | ++++++++++---------------------------------------------- |
4 files changed, 185 insertions(+), 125 deletions(-)
diff --git a/dns.lisp b/dns.lisp
@@ -111,7 +111,7 @@
(rw:write-u8 writer (length b))
(rw:write-octets writer b)))
-(rw.wire:defenum $type (:nbits 16)
+(rw.wire:defenum $type (:type rw:u16be)
(A . 1)
(NS . 2)
(MD . 3)
@@ -137,7 +137,7 @@
(MAILA . 254)
(ANY . 255))
-(rw.wire:defenum $class (:nbits 16)
+(rw.wire:defenum $class (:type rw:u16be)
(IN . 1)
(CS . 2)
(CH . 3)
@@ -158,30 +158,30 @@
($name emailbx))
(rw.wire:defstruc $mx ()
- (rw.wire:u16 preference)
+ (rw:u16be preference)
($name name))
(rw.wire:defstruc $soa ()
($name mname)
($name rname)
- (rw.wire:u32 serial)
- (rw.wire:u32 refresh)
- (rw.wire:u32 retry)
- (rw.wire:u32 expire)
- (rw.wire:u32 minimum))
+ (rw:u32be serial)
+ (rw:u32be refresh)
+ (rw:u32be retry)
+ (rw:u32be expire)
+ (rw:u32be minimum))
(rw.wire:defstruc $srv ()
- (rw.wire:u16 priority)
- (rw.wire:u16 weight)
- (rw.wire:u16 port)
+ (rw:u16be priority)
+ (rw:u16be weight)
+ (rw:u16be port)
($name target))
(rw.wire:defstruc $resource ()
($name name)
($type type)
($class class)
- (rw.wire:u32 ttl)
- #+nil(rw.wire:u8 data :length rw.wire:u16)
+ (rw:u32be ttl)
+ #+nil(rw:u8 data :length rw:u16be)
((ecase type
(A $ipv4-address)
(AAAA $ipv6-address)
@@ -201,15 +201,15 @@
(SRV $srv)
#+nil(TXT $txt) ;; 1+ char-strings
#+nil(WKS $wks))
- data :length rw.wire:u16))
+ data :length rw:u16be))
(rw.wire:defstruc $message ()
- (rw.wire:u16 tid)
- (rw.wire:u16 flags)
- (rw.wire:u16 nquestion)
- (rw.wire:u16 nanswer)
- (rw.wire:u16 nauthority)
- (rw.wire:u16 nadditional)
+ (rw:u16be tid)
+ (rw:u16be flags)
+ (rw:u16be nquestion)
+ (rw:u16be nanswer)
+ (rw:u16be nauthority)
+ (rw:u16be nadditional)
($question question :size nquestion)
($resource answer :size nanswer)
($resource authority :size nauthority)
diff --git a/rw.lisp b/rw.lisp
@@ -22,7 +22,8 @@
(defpackage :rw
(:use :cl)
- (:export :byte-reader
+ (:export :*endian*
+ :byte-reader
:byte-writer
:char-reader
:char-writer
@@ -33,8 +34,14 @@
:next
:next-octets
:next-u16
+ :next-u16be
+ :next-u16le
:next-u24
+ :next-u24be
+ :next-u24le
:next-u32
+ :next-u32be
+ :next-u32le
:next-u8
:next-z0
:peek
@@ -45,11 +52,28 @@
:skip
:slurp
:till
+ :u8
+ :u16
+ :u16be
+ :u16le
+ :u24
+ :u24be
+ :u24le
+ :u32
+ :u32be
+ :u32le
:wrap-reader
:wrap-writer
:write-octets
:write-u16
+ :write-u16be
+ :write-u16le
+ :write-u24
+ :write-u24be
+ :write-u24le
:write-u32
+ :write-u32be
+ :write-u32le
:write-u8
:writer))
@@ -234,22 +258,56 @@
(assert (<= 0 x 255))
x))
-(defun next-u16 (reader) ;; TODO little endian
+(defparameter *endian* (or (find :little-endian *features*)
+ (find :big-endian *features*)))
+
+(defun next-u16be (reader)
(let? x (next-u8 reader)
(let? y (next-u8 reader)
(logior (ash x 8) y))))
-(defun next-u24 (reader) ;; TODO little endian
+(defun next-u16le (reader)
+ (let? x (next-u8 reader)
+ (let? y (next-u8 reader)
+ (logior (ash y 8) x))))
+
+(defun next-u16 (reader)
+ (ecase *endian*
+ (:big-endian (next-u16be reader))
+ (:little-endian (next-u16le reader))))
+
+(defun next-u24be (reader)
(let? x (next-u8 reader)
(let? y (next-u8 reader)
(let? z (next-u8 reader)
(logior (ash x 16) (ash y 8) z)))))
-(defun next-u32 (reader) ;; TODO little endian
- (let? x (next-u16 reader)
- (let? y (next-u16 reader)
+(defun next-u24le (reader)
+ (let? x (next-u8 reader)
+ (let? y (next-u8 reader)
+ (let? z (next-u8 reader)
+ (logior (ash z 16) (ash y 8) x)))))
+
+(defun next-u24 (reader)
+ (ecase *endian*
+ (:big-endian (next-u24be reader))
+ (:little-endian (next-u24le reader))))
+
+(defun next-u32be (reader)
+ (let? x (next-u16be reader)
+ (let? y (next-u16be reader)
(logior (ash x 16) y))))
+(defun next-u32le (reader)
+ (let? x (next-u16le reader)
+ (let? y (next-u16le reader)
+ (logior (ash y 16) x))))
+
+(defun next-u32 (reader)
+ (ecase *endian*
+ (:big-endian (next-u32be reader))
+ (:little-endian (next-u32le reader))))
+
(defun next-octets (reader n)
(let ((z (make-array n
:element-type '(unsigned-byte 8)
@@ -290,15 +348,52 @@
(assert (<= 0 x 255))
(funcall writer x))
-(defun write-u16 (writer x) ;; TODO little endian
+(defun write-u16be (writer x)
(assert (<= 0 x 65535))
(write-u8 writer (ash x -8))
(write-u8 writer (logand #xff x)))
-(defun write-u32 (writer x) ;; TODO little endian
+(defun write-u16le (writer x)
+ (assert (<= 0 x 65535))
+ (write-u8 writer (logand #xff x))
+ (write-u8 writer (ash x -8)))
+
+(defun write-u16 (writer x)
+ (ecase *endian*
+ (:big-endian (write-u16be writer x))
+ (:little-endian (write-u16le writer x))))
+
+(defun write-u24be (writer x)
+ (assert (<= 0 x #.(1- (expt 2 24))))
+ (write-u8 writer (ash x -16))
+ (write-u8 writer (logand #xff (ash x -8)))
+ (write-u8 writer (logand #xff x)))
+
+(defun write-u24le (writer x)
+ (assert (<= 0 x #.(1- (expt 2 24))))
+ (write-u8 writer (logand #xff x))
+ (write-u8 writer (logand #xff (ash x -8)))
+ (write-u8 writer (ash x -16)))
+
+(defun write-u24 (writer x)
+ (ecase *endian*
+ (:big-endian (write-u24be writer x))
+ (:little-endian (write-u24le writer x))))
+
+(defun write-u32be (writer x)
(assert (<= 0 x #.(1- (expt 2 32))))
- (write-u16 writer (ash x -16))
- (write-u16 writer (logand #xffff x)))
+ (write-u16be writer (ash x -16))
+ (write-u16be writer (logand #xffff x)))
+
+(defun write-u32le (writer x)
+ (assert (<= 0 x #.(1- (expt 2 32))))
+ (write-u16le writer (logand #xffff x))
+ (write-u16le writer (ash x -16)))
+
+(defun write-u32 (writer x)
+ (ecase *endian*
+ (:big-endian (write-u32be writer x))
+ (:little-endian (write-u32le writer x))))
(defun copy (reader writer)
(do (x)
diff --git a/tls.lisp b/tls.lisp
@@ -34,11 +34,11 @@
;; https://tools.ietf.org/html/rfc5246
;; https://tools.ietf.org/html/rfc4492
-(rw.wire:defenum $AlertLevel (:nbits 8)
+(rw.wire:defenum $AlertLevel (:type rw:u8)
(WARNING . 1)
(FATAL . 2))
-(rw.wire:defenum $AlertDescription (:nbits 8)
+(rw.wire:defenum $AlertDescription (:type rw:u8)
(CLOSE_NOTIFY . 0)
(UNEXPECTED_MESSAGE . 10)
(BAD_RECORD_MAC . 20)
@@ -65,7 +65,7 @@
(NO_RENEGOTIATION . 100)
(UNSUPPORTED_EXTENSION . 110))
-(rw.wire:defenum $CipherSuite (:nbits 16)
+(rw.wire:defenum $CipherSuite (:type rw:u16be)
(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA . #X0013)
(TLS_DHE_DSS_WITH_AES_128_CBC_SHA . #X0032)
(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 . #X0040)
@@ -153,7 +153,7 @@
(TLS_RSA_WITH_RC4_128_MD5 . #X0004)
(TLS_RSA_WITH_RC4_128_SHA . #X0005))
-(rw.wire:defenum $ClientCertificateType (:nbits 8)
+(rw.wire:defenum $ClientCertificateType (:type rw:u8)
(rsa_sign . 1)
(dss_sign . 2)
(rsa_fixed_dh . 3)
@@ -162,20 +162,20 @@
(dss_ephemeral_dh_RESERVED . 6)
(fortezza_dms_RESERVED . 20))
-(rw.wire:defenum $CompressionMethod (:nbits 8)
+(rw.wire:defenum $CompressionMethod (:type rw:u8)
(null . 0))
-(rw.wire:defenum $ContentType (:nbits 8)
+(rw.wire:defenum $ContentType (:type rw:u8)
(CHANGE_CIPHER_SPEC . 20)
(ALERT . 21)
(HANDSHAKE . 22)
(APPLICATION_DATA . 23))
-(rw.wire:defenum $ContentVersion (:nbits 16)
+(rw.wire:defenum $ContentVersion (:type rw:u16be)
(SSL3.0 . #x0300)
(TLS1.2 . #x0303))
-(rw.wire:defenum $ExtensionType (:nbits 16)
+(rw.wire:defenum $ExtensionType (:type rw:u16be)
(ec_point_formats . #x000b)
(elliptic_curves . #x000a)
(renegotiation_info . #xff01)
@@ -184,7 +184,7 @@
(signature_algorithms . #x000d)
(status_request . #x0005))
-(rw.wire:defenum $HandshakeType (:nbits 8)
+(rw.wire:defenum $HandshakeType (:type rw:u8)
(HELLO_REQUEST . 0)
(CLIENT_HELLO . 1)
(SERVER_HELLO . 2)
@@ -196,7 +196,7 @@
(CLIENT_KEY_EXCHANGE . 16)
(FINISHED . 20))
-(rw.wire:defenum $HashAlgorithm (:nbits 8)
+(rw.wire:defenum $HashAlgorithm (:type rw:u8)
(none . 0)
(md5 . 1)
(sha1 . 2)
@@ -205,13 +205,13 @@
(sha384 . 5)
(sha512 . 6))
-(rw.wire:defenum $ECCurveType (:nbits 8)
+(rw.wire:defenum $ECCurveType (:type rw:u8)
(explicit_prime . 1)
(explicit_char2 . 2)
(named_curve . 3)
#+nil(reserved 248..255))
-(rw.wire:defenum $NamedCurve (:nbits 16)
+(rw.wire:defenum $NamedCurve (:type rw:u16be)
(sect163k1 . 1)
(sect163r1 . 2)
(sect163r2 . 3)
@@ -241,10 +241,10 @@
(arbitrary_explicit_prime_curves . #xff01)
(arbitrary_explicit_char2_curves . #xff02))
-(rw.wire:defenum %$SignatureHashAlgorithmSignature (:nbits 8)
+(rw.wire:defenum %$SignatureHashAlgorithmSignature (:type rw:u8)
(rsa . 1))
-(rw.wire:defenum $ECPointFormat (:nbits 8)
+(rw.wire:defenum $ECPointFormat (:type rw:u8)
(uncompressed . 0)
(ansiX962_compressed_prime . 1)
(ansiX962_compressed_char2 . 2)
@@ -258,7 +258,7 @@
;;'ecdhe_rsa
'ec_diffie_hellman)
-;; (rw.wire:defenum $KeyExchangeAlgorithm (:nbits 8)
+;; (rw.wire:defenum $KeyExchangeAlgorithm (:type rw:u8)
;; (dhe_dss . 0)
;; (dhe_rsa . 1)
;; (dh_anon . 2)
@@ -288,20 +288,20 @@
#+nil
(rw.wire:defstruc $ASN.1Cert ()
- (rw.wire:u8 data :min 0 :max #.(1- (expt 2 24))))
+ (rw:u8 data :min 0 :max #.(1- (expt 2 24))))
(rw.wire:defstruc %$Certificate ()
- (rw.wire:u8 #+nil $ASN.1Cert data :length rw.wire:u24 :min 0 :max #.(1- (expt 2 24)))
+ (rw:u8 #+nil $ASN.1Cert data :length rw:u24be :min 0 :max #.(1- (expt 2 24)))
(rw.wire::computed der :next (rw.der:decode (rw:reader data))))
(rw.wire:defstruc $Certificate ()
- (%$Certificate list :length rw.wire:u24 :min 0 :max #.(1- (expt 2 24)) :size t))
+ (%$Certificate list :length rw:u24be :min 0 :max #.(1- (expt 2 24)) :size t))
(rw.wire:defstruc %$ECPointFormatList ()
- ($ECPointFormat ec_point_format_list :length rw.wire:u8 :min 1 :size t))
+ ($ECPointFormat ec_point_format_list :length rw:u8 :min 1 :size t))
(rw.wire:defstruc $ECPointFormatList ()
- (%$ECPointFormatList data :length rw.wire:u16))
+ (%$ECPointFormatList data :length rw:u16be))
(rw.wire:defstruc $Extension ()
($ExtensionType type)
@@ -314,24 +314,24 @@
(ec_point_formats $ECPointFormatList)
#+nil(signature_algorithms))
data)
- #+nil(rw.wire:u8 data :length rw.wire:u16 :min 0 :max #.(1- (expt 2 16)) :size t))
+ #+nil(rw:u8 data :length rw:u16be :min 0 :max #.(1- (expt 2 16)) :size t))
(rw.wire:defstruc $ClientHello ()
($ContentVersion #+nil $ProtocolVersion version)
($Random random)
($SessionID session_id)
- ($CipherSuite cipher_suites :length rw.wire:u16 :min 2 :max #.(- (expt 2 16) 2) :size t)
- ($CompressionMethod compression_methods :length rw.wire:u8 :min 1 :max #.(1- (expt 2 8)) :size t)
- ($Extension extensions :length rw.wire:u16 :min 0 :max #.(1- (expt 2 16)) :size t))
+ ($CipherSuite cipher_suites :length rw:u16be :min 2 :max #.(- (expt 2 16) 2) :size t)
+ ($CompressionMethod compression_methods :length rw:u8 :min 1 :max #.(1- (expt 2 8)) :size t)
+ ($Extension extensions :length rw:u16be :min 0 :max #.(1- (expt 2 16)) :size t))
(rw.wire:defstruc $ServerDHParams ()
- (rw.wire:u8 dh_p :length rw.wire:u16 :min 1 :max #.(1- (expt 2 16)))
- (rw.wire:u8 dh_g :length rw.wire:u16 :min 1 :max #.(1- (expt 2 16)))
- (rw.wire:u8 dh_Ys :length rw.wire:u16 :min 1 :max #.(1- (expt 2 16))))
+ (rw:u8 dh_p :length rw:u16be :min 1 :max #.(1- (expt 2 16)))
+ (rw:u8 dh_g :length rw:u16be :min 1 :max #.(1- (expt 2 16)))
+ (rw:u8 dh_Ys :length rw:u16be :min 1 :max #.(1- (expt 2 16))))
(rw.wire:defstruc $signed_params ()
- (rw.wire:u8 client_random :size 32)
- (rw.wire:u8 server_random :size 32)
+ (rw:u8 client_random :size 32)
+ (rw:u8 server_random :size 32)
($ServerDHParams params2))
(rw.wire:defstruc %$ServerDHParams ()
@@ -339,17 +339,18 @@
($signed_params signed_params))
(rw.wire:defstruc $ECCurve ()
- (rw.wire:u8 a :length rw.wire:u8 :min 1)
- (rw.wire:u8 b :length rw.wire:u8 :min 1))
+ (rw:u8 a :length rw:u8 :min 1)
+ (rw:u8 b :length rw:u8 :min 1))
;;http://stackoverflow.com/questions/10936171/how-do-i-compress-or-encode-the-elliptic-curve-public-key-and-put-it-over-the-ne
(rw.wire:defstruc $ECPoint ()
- ;;(rw.wire:u8 data :length rw.wire:u8 :min 1 :size t)
- (rw.wire:u8 length)
- (rw.wire:u8 #+nil $ECPointFormat format #+nil :check #+nil(= 4 format)) ;; 4=uncompressed 2|3=compressed
+ ;;(rw:u8 data :length rw:u8 :min 1 :size t)
+ (rw:u8 length)
+ (rw:u8 #+nil $ECPointFormat format #+nil :check #+nil(= 4 format)) ;; 4=uncompressed 2|3=compressed
;;(rw.wire::computed format :compute (progn (assert (= 4 %format)) %format))
- (rw.wire:u8 x :size (floor length 2))
- (rw.wire:u8 y :size (floor length 2)))
+ (rw:u8 x :size (floor length 2))
+ (rw:u8 y :size (floor length 2)))
+
;; (rw.wire:defstruc %$ExplicitPrime ()
;; opaque prime_p <1..2^8-1>
@@ -392,8 +393,8 @@
(rw.wire:defstruc %$ECSASignature () ;; digitally-signed
(%$SignatureHashAlgorithm algorithm)
- (rw.wire:u16 length #+nil :compute #+nil(ShaSize))
- (rw.wire:u8 sha_hash :size length))
+ (rw:u16be length #+nil :compute #+nil(ShaSize))
+ (rw:u8 sha_hash :size length))
(rw.wire:defstruc $Signature ()
(rw.wire::computed algorithm :compute (SignatureAlgorithm))
@@ -406,7 +407,7 @@
($Signature signed_params))
(rw.wire:defstruc $ServerKeyExchange ()
- ;;(rw.wire:u8 data :length rw.wire:u16 :min 1 :max #.(1- (expt 2 16)))
+ ;;(rw:u8 data :length rw:u16be :min 1 :max #.(1- (expt 2 16)))
(rw.wire::computed type :compute (KeyExchangeAlgorithm))
((ecase type
;;(dh_anon $ServerDHParams)
@@ -416,11 +417,11 @@
data))
(rw.wire:defstruc $SessionID ()
- (rw.wire:u8 data :length rw.wire:u8 :min 0 :max 32 :size t))
+ (rw:u8 data :length rw:u8 :min 0 :max 32 :size t))
(rw.wire:defstruc $Random ()
- (rw.wire:u32 gmt_unix_time)
- (rw.wire:u8 random_bytes :size 28))
+ (rw:u32be gmt_unix_time)
+ (rw:u8 random_bytes :size 28))
(rw.wire:defstruc $ServerHello ()
($ContentVersion #+nil ProtocolVersion version)
@@ -428,10 +429,10 @@
($SessionID session_id)
($CipherSuite cipher_suite)
($CompressionMethod compression_method)
- ($Extension extensions :length rw.wire:u16 :min 0 :max #.(1- (expt 2 16)) :size t))
+ ($Extension extensions :length rw:u16be :min 0 :max #.(1- (expt 2 16)) :size t))
(rw.wire:defstruc $dh_Yc ()
- (rw.wire:u8 data :length rw.wire:u16 :min 1 :max #.(1- (expt 2 16))))
+ (rw:u8 data :length rw:u16be :min 1 :max #.(1- (expt 2 16))))
(rw.wire:defstruc $EncryptedPreMasterSecret ()
($PreMasterSecret pubkey_encrypted))
@@ -467,21 +468,21 @@
(SERVER_HELLO $ServerHello)
(SERVER_HELLO_DONE)
(SERVER_KEY_EXCHANGE $ServerKeyExchange))
- data :length rw.wire:u24))
+ data :length rw:u24be))
(rw.wire:defstruc $PreMasterSecret ()
($ContentVersion #+nil ProtocolVersion client_version)
- (rw.wire:u8 random :size 46))
+ (rw:u8 random :size 46))
(rw.wire:defstruc $Record ()
($ContentType type)
- (rw.wire:u16 #+nil ContentVersion version)
+ (rw:u16be #+nil ContentVersion version)
((ecase type
(ALERT $Alert)
(HANDSHAKE $Handshake))
- data :length rw.wire:u16 :min 1 :max 16383)
+ data :length rw:u16be :min 1 :max 16383)
#+nil
- (rw.wire:u8 data :length rw.wire:u16 :min 1 :max 16383 :size t))
+ (rw:u8 data :length rw:u16be :min 1 :max 16383 :size t))
;; struct {
;; HashAlgorithm hash
diff --git a/wire.lisp b/wire.lisp
@@ -26,11 +26,7 @@
:defstruc
:flush
:make-octet-buffer
- :packet-writer
- :u8
- :u16
- :u24
- :u32))
+ :packet-writer))
(in-package :rw.wire)
@@ -43,33 +39,6 @@
:adjustable t
:fill-pointer 0))
-(defun next-u8 (reader)
- (rw:next-u8 reader))
-
-(defun next-u16 (reader)
- (rw:next-u16 reader))
-
-(defun next-u24 (reader)
- (rw:next-u24 reader))
-
-(defun next-u32 (reader)
- (rw:next-u32 reader))
-
-(defun write-u8 (writer x)
- (rw:write-u8 writer x))
-
-(defun write-u16 (writer x)
- (rw:write-u16 writer x))
-
-(defun write-u24 (writer x)
- (assert (<= 0 x #.(1- (expt 2 24))))
- (write-u8 writer (ash x -16))
- (write-u8 writer (logand #xff (ash x -8)))
- (write-u8 writer (logand #xff x)))
-
-(defun write-u32 (writer x)
- (rw:write-u32 writer x))
-
(defun %intern (pre x post)
(intern (format nil "~a~a~a" pre x post) (symbol-package x)))
@@ -85,7 +54,7 @@
(defun wname (x)
(%intern "WRITE-" x ""))
-(defmacro defenum (name (&key nbits) &body alist)
+(defmacro defenum (name (&key type) &body alist)
(let ((fname (fname name))
(sname (%intern "" name "-SYMBOLS"))
(cname (%intern "" name "-CODES"))
@@ -101,20 +70,15 @@
(defun ,sname () symbols)
(defun ,cname () codes)
(defun ,rname (reader)
- (let ((z (,fname (, (ecase nbits
- (8 'rw:next-u8)
- (16 'rw:next-u16))
- reader))))
+ (let ((z (,fname (,(rname type) reader))))
(assert z)
z))
(defun ,wname (writer x)
- (, (ecase nbits
- (8 'rw:write-u8)
- (16 'rw:write-u16))
- writer
- (etypecase x
- (symbol (,fname x))
- (integer (when (member x codes) x))))))))
+ (,(wname type)
+ writer
+ (etypecase x
+ (symbol (,fname x))
+ (integer (when (member x codes) x))))))))
(defun aname (struc &optional slot)
(intern (format nil "~a-~a" struc slot) (symbol-package struc)))
@@ -143,7 +107,7 @@
,@(when max `((assert (<= l ,max))))
,@(when (integerp size) `((assert (= l ,size))))
(dotimes (i l)
- (vector-push-extend (next-u8 r) b))
+ (vector-push-extend (rw:next-u8 r) b))
,(if (eq 'u8 ty)
'b
(if size
@@ -209,7 +173,7 @@
,@(when max `((assert (<= l ,max))))
,@(when (integerp size) `((assert (= l ,size))))
(,(wname length) w l))
- (loop for e across b do (write-u8 w e))))
+ (loop for e across b do (rw:write-u8 w e))))
(size
;;(assert (eq 'u8 ty)) ;; TODO how?
`(let ((v (,(aname name na) x)))