diff --git a/README b/README index ed584d2..42ab963 100644 --- a/README +++ b/README @@ -24,6 +24,9 @@ Functions: ; :read - There was an error reading the message ; :closed - The connection was closed before a message could be read ; :message - The message was invalid or outside the acceptable size bounds (TODO make this runtime instead of compile-time constant) + ; :checksum - The message had an invalid checksum + ;; there are also ignorable/recoverable errors, which are sent to the error callback as suck '(:warning ). These are treated differently. If the error callback returns T, let the message be carried on. If the error callback returns NIL, discard it. Available ones are: + ; (:warning :checksum) - The message had no checksum. (note: if this is not allowed to pass then :CHECKSUM error is raised). ;; (see libsipc/include/sipc.h for more details) ;; available types are: ; :string - Normal string @@ -129,7 +132,6 @@ Terminal 1: --- -TODO: Add proper signing. TODO: Internal error handling. TODO: Have libsipc built on system load TODO: better .so loading diff --git a/cl-sipc.asd b/cl-sipc.asd index 05649ec..7fbbff1 100644 --- a/cl-sipc.asd +++ b/cl-sipc.asd @@ -4,7 +4,7 @@ :description "AF_UNIX IPC for CL" :author "Avril " :license "None" - :version "0.0.3" + :version "0.0.4" :serial t :depends-on ( :cffi ) :components ((:file "package") diff --git a/cl-sipc.lisp b/cl-sipc.lisp index 826e960..6189131 100644 --- a/cl-sipc.lisp +++ b/cl-sipc.lisp @@ -90,6 +90,7 @@ :error - send() error :failure - send failed :message - invalid response message + :checksum - invalid checksum :unknown - unknown error code :unknown-type - key argument :type is unknown :type can be: @@ -125,7 +126,7 @@ (cond ((= rc #.+si-send-partial+) :partial) ((= rc #.+si-send-error+) :error) ((= rc #.+si-send-failure+) :failure) - (t :unknown)))) + (t (marshal-ec rc))))) rc))) (defun respond (value &optional (type :string)) @@ -150,7 +151,7 @@ ((= rc #.+si-send-partial+) :partial) ((= rc #.+si-send-error+) :error) ((= rc #.+si-send-failure+) :failure) - (t :unknown)) + (t (marshal-ec rc))) rc)) :response-invalid))) diff --git a/ffi.lisp b/ffi.lisp index 1f415c5..35d5a2f 100644 --- a/ffi.lisp +++ b/ffi.lisp @@ -15,6 +15,11 @@ (defconstant +sie-r-invalid+ 4) (defconstant +sie-r-multi+ 5) (defconstant +sie-r-disable+ 6) +(defconstant +sie-checksum+ 7) + +;; recoverable ("warning") error codes +(defconstant +sief-warning+ #xAFF000) +(defconstant +siw-checksum+ #.(+ +sief-warning+ 1)) (defctype si-send-rc :int) (defconstant +si-send-okay+ 0) @@ -51,13 +56,15 @@ ((= err #.+sie-read+) :read) ((= err #.+sie-pconcls+) :closed) ((= err #.+sie-invalid+) :message) + ((= err #.+sie-checksum+) :checksum) + ((= err #.+siw-checksum+) '(:warning :checksum)) (t :unknown))) (defcallback si-error-callback :int ((err si-error)) (when (symbol-value '*on-error*) (if (funcall (symbol-value '*on-error*) (marshal-ec err)) 0 - 1))) + -1))) (defun si-typecase (message &key string binary close) (let* ((type (sif-type message)) @@ -68,7 +75,7 @@ ((= type #.+si-binary+) (funcall binary (make-pointer :memory data :size size)))))) (if rval 0 - 1))) + -1))) (defcallback si-callback :int ((message :pointer)) diff --git a/libsipc/include/sipc.h b/libsipc/include/sipc.h index 19ffa53..75ca030 100644 --- a/libsipc/include/sipc.h +++ b/libsipc/include/sipc.h @@ -1,6 +1,7 @@ #ifndef _LIBSIPC_H #define _LIBSIPC_H #include +#include #define SI_MAX_MESSAGE_SIZE 1024 @@ -21,19 +22,22 @@ typedef enum { _SI_ERROR, } si_type; -#define SI_NORESP (1<<0) -#define SI_DISCARD (1<<1) +#define SI_NORESP (1<<0) //Do not expect a response. +#define SI_DISCARD (1<<1) //Do not process this. +#define SI_NOSIGN (1<<2) //This message is not signed. -#define _SI_HEADER_CHECK 0xbeefbeefabad1dea; +#define _SI_HEADER_CHECK 0xbeefbeefabad1deaul typedef struct { si_type type; unsigned int flags; unsigned int data_len; - unsigned long check; + unsigned long check0; + uint64_t check; unsigned char data[]; } si_message; +#define SIEF_WARNING 0xaff000 typedef enum { SIE_ACCEPT= 0, //Sock accept failure SIE_READ, //Sock read failure @@ -43,6 +47,12 @@ typedef enum { SIE_R_INVALID, //This message cannot be responded to like that SIE_R_MULTI, //A response has already been sent SIE_R_DISABLE, //The client asked to not be responded to + + SIE_CHECKSUM, //Bad checksum + + //Recoverable errors (warnings) + + SIW_CHECKSUM = (SIEF_WARNING)+1, //No checksum. } si_error; typedef int (*si_callback)(const si_message *msg); @@ -60,7 +70,7 @@ char* si_type_string(si_type ty); int si_connect(const char* file); //Returns sd, or -1 on failure. int si_sendmsg_r(int sd, const si_message* msg, si_message** response); //si_sendmmsg but optionally receive response (make sure to free() *response after you're done, NULL to discard response, if there is no response *response is not modified) int si_sendmsg(int sd, const si_message *msg); //Returns 0 on okay, 1 if whole message could not be sent, -1 on send error, -2 on weird send error. (see SI_SEND_*) -void si_sign(si_message *msg); //Sign message. Use this before sending one. +void si_sign(si_message *msg); //Sign message. Use this before sending one. (note: you still have to call this, even when setting SI_NOSIGN flag. //Quick funcs int siqs_string_r(int sd, const char* string, unsigned int flags, si_message** resp); //quick send string diff --git a/libsipc/src/cli.c b/libsipc/src/cli.c index 2456ede..45887c4 100644 --- a/libsipc/src/cli.c +++ b/libsipc/src/cli.c @@ -6,6 +6,7 @@ #include int silent_level=0; +int signing=1; #define Vprintf(...) if(silent_level<0) printf("[l] " __VA_ARGS__) #define Eprintf(...) if(silent_level <2) fprintf(stderr, "[e] " __VA_ARGS__) @@ -13,7 +14,15 @@ int silent_level=0; int on_error(si_error err) { - Eprintf("<- %s\n", si_error_string(err)); + + if(err & SIEF_WARNING) { //Different handler for warnings + Eprintf("<- (w) %s\n", si_error_string(err)); + if(err == SIW_CHECKSUM && signing) { + return -1; //We don't want to accept this, we're expecting signed packets. + } else return 0; + } else { + Eprintf("<- %s\n", si_error_string(err)); + } return 0; } @@ -184,6 +193,8 @@ int client(const char* conto, const char* string, int bin) Vprintf("timeout set to %d\n", timeout); } si_message *response = NULL; + if(!signing) + msg->flags |= SI_NOSIGN; si_sign(msg); int rrc = si_sendmsg_r(sd, msg, &response); if(response) { @@ -221,6 +232,8 @@ int client_close(const char* conto) Vprintf("timeout set to %d\n", timeout); } si_message* response = NULL; + if(!signing) + msg->flags |= SI_NOSIGN; si_sign(msg); int rrc = si_sendmsg_r(sd, msg, &response); if(response) { @@ -256,6 +269,9 @@ int pfa(char** argv) case 'v': silent_level =-1; break; + case 'u': + signing = 0; + break; case 't': nrc+=1; timeout = atoi(*(argv+1+nrc)); @@ -343,7 +359,7 @@ int main(int argc, char** argv) } else { argv = _av; - printf("usage: %s [-qQvt] [] -l[fe] \nusage: %s [-qQvt] [] -p[b] \nusage: %s [-qQvt] [] -c[f] \nusage: %s [-qQvt] [] -h \n", argv[0], argv[0], argv[0], argv[0]); + printf("usage: %s [-uqQvt] [] -l[fe] \nusage: %s [-uqQvt] [] -p[b] \nusage: %s [-uqQvt] [] -c[f] \nusage: %s [-qQvt] [] -h \n", argv[0], argv[0], argv[0], argv[0]); printf("\n-l[fe]\tlisten on socket. (f to unlink file first, e to send response)\n"); printf("-p[b]\twrite to socket. (b to send as binary)\n"); printf("-c[f]\tsend cose signal to socket. (f to unlink file after)\n"); @@ -353,6 +369,7 @@ int main(int argc, char** argv) printf(" -Q\tsilent mode, only print responses\n"); printf(" -v\tverbose mode, print additional messages\n"); printf(" -t\tset socket timeout to next arg (in seconds)\n"); + printf(" -u\tdo not sign messages (or do not verify, for server)\n"); } return rc; } diff --git a/libsipc/src/crc64.c b/libsipc/src/crc64.c new file mode 100644 index 0000000..ecdba90 --- /dev/null +++ b/libsipc/src/crc64.c @@ -0,0 +1,191 @@ +/* Redis uses the CRC64 variant with "Jones" coefficients and init value of 0. + * + * Specification of this CRC64 variant follows: + * Name: crc-64-jones + * Width: 64 bites + * Poly: 0xad93d23594c935a9 + * Reflected In: True + * Xor_In: 0xffffffffffffffff + * Reflected_Out: True + * Xor_Out: 0x0 + * Check("123456789"): 0xe9c6d914c4b8d9ca + * + * Copyright (c) 2012, Salvatore Sanfilippo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Redis nor the names of its contributors may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ + +#include + +static const uint64_t crc64_tab[256] = { + UINT64_C(0x0000000000000000), UINT64_C(0x7ad870c830358979), + UINT64_C(0xf5b0e190606b12f2), UINT64_C(0x8f689158505e9b8b), + UINT64_C(0xc038e5739841b68f), UINT64_C(0xbae095bba8743ff6), + UINT64_C(0x358804e3f82aa47d), UINT64_C(0x4f50742bc81f2d04), + UINT64_C(0xab28ecb46814fe75), UINT64_C(0xd1f09c7c5821770c), + UINT64_C(0x5e980d24087fec87), UINT64_C(0x24407dec384a65fe), + UINT64_C(0x6b1009c7f05548fa), UINT64_C(0x11c8790fc060c183), + UINT64_C(0x9ea0e857903e5a08), UINT64_C(0xe478989fa00bd371), + UINT64_C(0x7d08ff3b88be6f81), UINT64_C(0x07d08ff3b88be6f8), + UINT64_C(0x88b81eabe8d57d73), UINT64_C(0xf2606e63d8e0f40a), + UINT64_C(0xbd301a4810ffd90e), UINT64_C(0xc7e86a8020ca5077), + UINT64_C(0x4880fbd87094cbfc), UINT64_C(0x32588b1040a14285), + UINT64_C(0xd620138fe0aa91f4), UINT64_C(0xacf86347d09f188d), + UINT64_C(0x2390f21f80c18306), UINT64_C(0x594882d7b0f40a7f), + UINT64_C(0x1618f6fc78eb277b), UINT64_C(0x6cc0863448deae02), + UINT64_C(0xe3a8176c18803589), UINT64_C(0x997067a428b5bcf0), + UINT64_C(0xfa11fe77117cdf02), UINT64_C(0x80c98ebf2149567b), + UINT64_C(0x0fa11fe77117cdf0), UINT64_C(0x75796f2f41224489), + UINT64_C(0x3a291b04893d698d), UINT64_C(0x40f16bccb908e0f4), + UINT64_C(0xcf99fa94e9567b7f), UINT64_C(0xb5418a5cd963f206), + UINT64_C(0x513912c379682177), UINT64_C(0x2be1620b495da80e), + UINT64_C(0xa489f35319033385), UINT64_C(0xde51839b2936bafc), + UINT64_C(0x9101f7b0e12997f8), UINT64_C(0xebd98778d11c1e81), + UINT64_C(0x64b116208142850a), UINT64_C(0x1e6966e8b1770c73), + UINT64_C(0x8719014c99c2b083), UINT64_C(0xfdc17184a9f739fa), + UINT64_C(0x72a9e0dcf9a9a271), UINT64_C(0x08719014c99c2b08), + UINT64_C(0x4721e43f0183060c), UINT64_C(0x3df994f731b68f75), + UINT64_C(0xb29105af61e814fe), UINT64_C(0xc849756751dd9d87), + UINT64_C(0x2c31edf8f1d64ef6), UINT64_C(0x56e99d30c1e3c78f), + UINT64_C(0xd9810c6891bd5c04), UINT64_C(0xa3597ca0a188d57d), + UINT64_C(0xec09088b6997f879), UINT64_C(0x96d1784359a27100), + UINT64_C(0x19b9e91b09fcea8b), UINT64_C(0x636199d339c963f2), + UINT64_C(0xdf7adabd7a6e2d6f), UINT64_C(0xa5a2aa754a5ba416), + UINT64_C(0x2aca3b2d1a053f9d), UINT64_C(0x50124be52a30b6e4), + UINT64_C(0x1f423fcee22f9be0), UINT64_C(0x659a4f06d21a1299), + UINT64_C(0xeaf2de5e82448912), UINT64_C(0x902aae96b271006b), + UINT64_C(0x74523609127ad31a), UINT64_C(0x0e8a46c1224f5a63), + UINT64_C(0x81e2d7997211c1e8), UINT64_C(0xfb3aa75142244891), + UINT64_C(0xb46ad37a8a3b6595), UINT64_C(0xceb2a3b2ba0eecec), + UINT64_C(0x41da32eaea507767), UINT64_C(0x3b024222da65fe1e), + UINT64_C(0xa2722586f2d042ee), UINT64_C(0xd8aa554ec2e5cb97), + UINT64_C(0x57c2c41692bb501c), UINT64_C(0x2d1ab4dea28ed965), + UINT64_C(0x624ac0f56a91f461), UINT64_C(0x1892b03d5aa47d18), + UINT64_C(0x97fa21650afae693), UINT64_C(0xed2251ad3acf6fea), + UINT64_C(0x095ac9329ac4bc9b), UINT64_C(0x7382b9faaaf135e2), + UINT64_C(0xfcea28a2faafae69), UINT64_C(0x8632586aca9a2710), + UINT64_C(0xc9622c4102850a14), UINT64_C(0xb3ba5c8932b0836d), + UINT64_C(0x3cd2cdd162ee18e6), UINT64_C(0x460abd1952db919f), + UINT64_C(0x256b24ca6b12f26d), UINT64_C(0x5fb354025b277b14), + UINT64_C(0xd0dbc55a0b79e09f), UINT64_C(0xaa03b5923b4c69e6), + UINT64_C(0xe553c1b9f35344e2), UINT64_C(0x9f8bb171c366cd9b), + UINT64_C(0x10e3202993385610), UINT64_C(0x6a3b50e1a30ddf69), + UINT64_C(0x8e43c87e03060c18), UINT64_C(0xf49bb8b633338561), + UINT64_C(0x7bf329ee636d1eea), UINT64_C(0x012b592653589793), + UINT64_C(0x4e7b2d0d9b47ba97), UINT64_C(0x34a35dc5ab7233ee), + UINT64_C(0xbbcbcc9dfb2ca865), UINT64_C(0xc113bc55cb19211c), + UINT64_C(0x5863dbf1e3ac9dec), UINT64_C(0x22bbab39d3991495), + UINT64_C(0xadd33a6183c78f1e), UINT64_C(0xd70b4aa9b3f20667), + UINT64_C(0x985b3e827bed2b63), UINT64_C(0xe2834e4a4bd8a21a), + UINT64_C(0x6debdf121b863991), UINT64_C(0x1733afda2bb3b0e8), + UINT64_C(0xf34b37458bb86399), UINT64_C(0x8993478dbb8deae0), + UINT64_C(0x06fbd6d5ebd3716b), UINT64_C(0x7c23a61ddbe6f812), + UINT64_C(0x3373d23613f9d516), UINT64_C(0x49aba2fe23cc5c6f), + UINT64_C(0xc6c333a67392c7e4), UINT64_C(0xbc1b436e43a74e9d), + UINT64_C(0x95ac9329ac4bc9b5), UINT64_C(0xef74e3e19c7e40cc), + UINT64_C(0x601c72b9cc20db47), UINT64_C(0x1ac40271fc15523e), + UINT64_C(0x5594765a340a7f3a), UINT64_C(0x2f4c0692043ff643), + UINT64_C(0xa02497ca54616dc8), UINT64_C(0xdafce7026454e4b1), + UINT64_C(0x3e847f9dc45f37c0), UINT64_C(0x445c0f55f46abeb9), + UINT64_C(0xcb349e0da4342532), UINT64_C(0xb1eceec59401ac4b), + UINT64_C(0xfebc9aee5c1e814f), UINT64_C(0x8464ea266c2b0836), + UINT64_C(0x0b0c7b7e3c7593bd), UINT64_C(0x71d40bb60c401ac4), + UINT64_C(0xe8a46c1224f5a634), UINT64_C(0x927c1cda14c02f4d), + UINT64_C(0x1d148d82449eb4c6), UINT64_C(0x67ccfd4a74ab3dbf), + UINT64_C(0x289c8961bcb410bb), UINT64_C(0x5244f9a98c8199c2), + UINT64_C(0xdd2c68f1dcdf0249), UINT64_C(0xa7f41839ecea8b30), + UINT64_C(0x438c80a64ce15841), UINT64_C(0x3954f06e7cd4d138), + UINT64_C(0xb63c61362c8a4ab3), UINT64_C(0xcce411fe1cbfc3ca), + UINT64_C(0x83b465d5d4a0eece), UINT64_C(0xf96c151de49567b7), + UINT64_C(0x76048445b4cbfc3c), UINT64_C(0x0cdcf48d84fe7545), + UINT64_C(0x6fbd6d5ebd3716b7), UINT64_C(0x15651d968d029fce), + UINT64_C(0x9a0d8ccedd5c0445), UINT64_C(0xe0d5fc06ed698d3c), + UINT64_C(0xaf85882d2576a038), UINT64_C(0xd55df8e515432941), + UINT64_C(0x5a3569bd451db2ca), UINT64_C(0x20ed197575283bb3), + UINT64_C(0xc49581ead523e8c2), UINT64_C(0xbe4df122e51661bb), + UINT64_C(0x3125607ab548fa30), UINT64_C(0x4bfd10b2857d7349), + UINT64_C(0x04ad64994d625e4d), UINT64_C(0x7e7514517d57d734), + UINT64_C(0xf11d85092d094cbf), UINT64_C(0x8bc5f5c11d3cc5c6), + UINT64_C(0x12b5926535897936), UINT64_C(0x686de2ad05bcf04f), + UINT64_C(0xe70573f555e26bc4), UINT64_C(0x9ddd033d65d7e2bd), + UINT64_C(0xd28d7716adc8cfb9), UINT64_C(0xa85507de9dfd46c0), + UINT64_C(0x273d9686cda3dd4b), UINT64_C(0x5de5e64efd965432), + UINT64_C(0xb99d7ed15d9d8743), UINT64_C(0xc3450e196da80e3a), + UINT64_C(0x4c2d9f413df695b1), UINT64_C(0x36f5ef890dc31cc8), + UINT64_C(0x79a59ba2c5dc31cc), UINT64_C(0x037deb6af5e9b8b5), + UINT64_C(0x8c157a32a5b7233e), UINT64_C(0xf6cd0afa9582aa47), + UINT64_C(0x4ad64994d625e4da), UINT64_C(0x300e395ce6106da3), + UINT64_C(0xbf66a804b64ef628), UINT64_C(0xc5bed8cc867b7f51), + UINT64_C(0x8aeeace74e645255), UINT64_C(0xf036dc2f7e51db2c), + UINT64_C(0x7f5e4d772e0f40a7), UINT64_C(0x05863dbf1e3ac9de), + UINT64_C(0xe1fea520be311aaf), UINT64_C(0x9b26d5e88e0493d6), + UINT64_C(0x144e44b0de5a085d), UINT64_C(0x6e963478ee6f8124), + UINT64_C(0x21c640532670ac20), UINT64_C(0x5b1e309b16452559), + UINT64_C(0xd476a1c3461bbed2), UINT64_C(0xaeaed10b762e37ab), + UINT64_C(0x37deb6af5e9b8b5b), UINT64_C(0x4d06c6676eae0222), + UINT64_C(0xc26e573f3ef099a9), UINT64_C(0xb8b627f70ec510d0), + UINT64_C(0xf7e653dcc6da3dd4), UINT64_C(0x8d3e2314f6efb4ad), + UINT64_C(0x0256b24ca6b12f26), UINT64_C(0x788ec2849684a65f), + UINT64_C(0x9cf65a1b368f752e), UINT64_C(0xe62e2ad306bafc57), + UINT64_C(0x6946bb8b56e467dc), UINT64_C(0x139ecb4366d1eea5), + UINT64_C(0x5ccebf68aecec3a1), UINT64_C(0x2616cfa09efb4ad8), + UINT64_C(0xa97e5ef8cea5d153), UINT64_C(0xd3a62e30fe90582a), + UINT64_C(0xb0c7b7e3c7593bd8), UINT64_C(0xca1fc72bf76cb2a1), + UINT64_C(0x45775673a732292a), UINT64_C(0x3faf26bb9707a053), + UINT64_C(0x70ff52905f188d57), UINT64_C(0x0a2722586f2d042e), + UINT64_C(0x854fb3003f739fa5), UINT64_C(0xff97c3c80f4616dc), + UINT64_C(0x1bef5b57af4dc5ad), UINT64_C(0x61372b9f9f784cd4), + UINT64_C(0xee5fbac7cf26d75f), UINT64_C(0x9487ca0fff135e26), + UINT64_C(0xdbd7be24370c7322), UINT64_C(0xa10fceec0739fa5b), + UINT64_C(0x2e675fb4576761d0), UINT64_C(0x54bf2f7c6752e8a9), + UINT64_C(0xcdcf48d84fe75459), UINT64_C(0xb71738107fd2dd20), + UINT64_C(0x387fa9482f8c46ab), UINT64_C(0x42a7d9801fb9cfd2), + UINT64_C(0x0df7adabd7a6e2d6), UINT64_C(0x772fdd63e7936baf), + UINT64_C(0xf8474c3bb7cdf024), UINT64_C(0x829f3cf387f8795d), + UINT64_C(0x66e7a46c27f3aa2c), UINT64_C(0x1c3fd4a417c62355), + UINT64_C(0x935745fc4798b8de), UINT64_C(0xe98f353477ad31a7), + UINT64_C(0xa6df411fbfb21ca3), UINT64_C(0xdc0731d78f8795da), + UINT64_C(0x536fa08fdfd90e51), UINT64_C(0x29b7d047efec8728), +}; + +uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l) { + uint64_t j; + + for (j = 0; j < l; j++) { + uint8_t byte = s[j]; + crc = crc64_tab[(uint8_t)crc ^ byte] ^ (crc >> 8); + } + return crc; +} + +/* Test main */ +#ifdef TEST_MAIN +#include +int main(void) { + printf("e9c6d914c4b8d9ca == %016llx\n", + (unsigned long long) crc64(0,(unsigned char*)"123456789",9)); + return 0; +} +#endif diff --git a/libsipc/src/crc64.h b/libsipc/src/crc64.h new file mode 100644 index 0000000..2de437d --- /dev/null +++ b/libsipc/src/crc64.h @@ -0,0 +1,7 @@ +#ifndef _CRC64_H +#define _CRC64_H +#include + +uint64_t crc64(uint64_t crc, const unsigned char * s, uint64_t l); + +#endif /* _CRC64_H */ diff --git a/libsipc/src/sipc.c b/libsipc/src/sipc.c index 7eced98..2d95f42 100644 --- a/libsipc/src/sipc.c +++ b/libsipc/src/sipc.c @@ -9,6 +9,7 @@ #include #include +#include "crc64.h" #define _SIRH_CHECK 0xabad struct si_response_header { @@ -42,10 +43,26 @@ int si_bind(const char* file) return sd; } +int si_validate_message(const si_message *msg) +{ + char buffer[sizeof(si_message)]; + + if(msg->flags & SI_NOSIGN) + return 0; //Don't bother checking if it says there's no sign. + + memset(buffer,0,sizeof(si_message)); + si_message *head = (si_message*)buffer; + memcpy(buffer,msg,sizeof(si_message)); + head->check = _SI_HEADER_CHECK; + uint64_t crc0 = crc64(0, (unsigned char*)head, sizeof(si_message)); + uint64_t crc = crc64(crc0, msg->data, head->data_len); + return msg->check == crc; +} + static int _si_valid_header(const si_message *msg) { int kk = (int)msg->type; - return kk>=0 && kk<_SI_ERROR && msg->data_len < SI_MAX_MESSAGE_SIZE && msg->check == _SI_HEADER_CHECK; + return kk>=0 && kk<_SI_ERROR && msg->data_len < SI_MAX_MESSAGE_SIZE && msg->check0 == _SI_HEADER_CHECK; } static int _si_read_rest(int sd, si_message *message) @@ -135,6 +152,7 @@ int si_listen(int sd, si_error_callback on_error, si_callback on_message) memcpy(full, message, sizeof(si_message)); rc = _si_read_rest(csd, full); + int valid=0; if(rc!=0) { if(rc==-1) @@ -147,26 +165,46 @@ int si_listen(int sd, si_error_callback on_error, si_callback on_message) break; } } - else { + else if( (valid=si_validate_message(full)) || (full->flags & SI_NOSIGN) ){ //Message has been read. - - rc = (full->flags & SI_DISCARD) ? 0 : on_message(full); - - if(!full0->resp_sent && !(full->flags & SI_NORESP)) - { - //Send blank response. (Unless client asked for none.) - si_message *resp = malloc(sizeof(si_message)); - resp->type = SI_BINARY; - resp->flags = SI_DISCARD | SI_NORESP; - resp->data_len = 0; - si_sign(resp); - int rc2 = si_sendmsg(csd, resp); - - if (rc2 != SI_SEND_OKAY) - rc = on_error((si_error)rc2); - - free(resp); - + + if(!valid) { + valid = on_error(SIW_CHECKSUM) == 0; + } + if(valid) { + rc = (full->flags & SI_DISCARD) ? 0 : on_message(full); + + if(!full0->resp_sent && !(full->flags & SI_NORESP)) + { + //Send blank response. (Unless client asked for none.) + si_message *resp = malloc(sizeof(si_message)); + resp->type = SI_BINARY; + resp->flags = SI_DISCARD | SI_NORESP; + resp->data_len = 0; + si_sign(resp); + int rc2 = si_sendmsg(csd, resp); + + if (rc2 != SI_SEND_OKAY) + rc = on_error((si_error)rc2); + + free(resp); + + } + } else { + rc = on_error(SIE_CHECKSUM); + if(rc<0) + { + close(csd); + free(full0); + break; + } + } + } else { // Bad checksum + rc = on_error(SIE_CHECKSUM); + if(rc<0) { + close(csd); + free(full0); + break; } } free(full0); @@ -207,13 +245,19 @@ char *si_error_string(si_error err) put("SIE_INVALID: Bad message"); break; case SIE_R_INVALID: - puts("SIE_R_INVALID: Cannot respond to this"); + put("SIE_R_INVALID: Cannot respond to this"); break; case SIE_R_MULTI: - puts("SIE_R_MULTI: A response has already been sent"); + put("SIE_R_MULTI: A response has already been sent"); break; case SIE_R_DISABLE: - puts("SIE_R_DISABLE: A response is not expected"); + put("SIE_R_DISABLE: A response is not expected"); + break; + case SIE_CHECKSUM: + put("SIE_CHECKSUM: Bad checksum"); + break; + case SIW_CHECKSUM: + put("SIW_CHECKSUM: No checksum"); break; default: put("SIE_UNKNOWN: Unknown EC %d", (int)err); @@ -299,13 +343,20 @@ int si_read_response(int sd, si_message** resp) memset(full,0,sizeof(si_message)+head->data_len+1); memcpy(full, head, sizeof(si_message)); rc = _si_read_rest(sd, full); + int valid=0; switch(rc) { case 0: - if(full->flags & SI_DISCARD) + + if((valid=si_validate_message(full)) || (full->flags & SI_NOSIGN)) { + if(full->flags & SI_DISCARD) + free(full); + else + *resp = full; + return valid?0:(int)SIW_CHECKSUM; + } else { free(full); - else - *resp = full; - return 0; + return (int)SIE_CHECKSUM; + } case -1: free(full); return (int)SIE_READ; @@ -341,7 +392,10 @@ static int _si_sendmsg(int sd, const si_message* msg) void si_sign(si_message* msg) { - msg->check = _SI_HEADER_CHECK; + msg->check = (uint64_t)(msg->check0 = _SI_HEADER_CHECK); + if(msg->flags & SI_NOSIGN) return; + uint64_t crc = crc64(0, (unsigned char*)msg, sizeof(si_message)+msg->data_len); + msg->check = crc; } int si_sendmsg_r(int sd, const si_message *msg, si_message** resp) @@ -543,3 +597,5 @@ int siqr_printf(const si_message* sd, const char* format, ...) return rc; } + +#include "crc64.c" //why not keep single translation unit? diff --git a/tools/test-server.lisp b/tools/test-server.lisp index b77f908..640c54b 100644 --- a/tools/test-server.lisp +++ b/tools/test-server.lisp @@ -6,6 +6,7 @@ (defparameter *socket-file* "sipc.socket") (defparameter *timeout* 5) ;; read timeout in seconds. (defparameter *respond* t) ;; should the server echo responses to client? +(defparameter *allow-no-checksums* t) ;; should we process unsigned messages? (when (probe-file *socket-file*) (delete-file *socket-file*)) @@ -22,7 +23,7 @@ #'(lambda (err) ;; Callback ran if there is an error (format t "[e] <- ~a~%" err) (force-output) - t) ;;returning NIL to the listener stops, t lets it continue + (or (atom err) *allow-no-checksums*) ) ;;returning NIL to the listener stops, t lets it continue. err will only be not atom() if it's a warning, which are handled differently. T lets the pipe continue and pass the message to the message callback, nil does not. #'(lambda (type message) ;; Callback ran when a message is received (when *respond* (format t