#include <assert.h>
#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
#include <tcl.h>
/* from hbytes.c */
+int Hbytes_Init(Tcl_Interp *ip); /* called by Tcl's "load" */
+
/* Internal representation details: */
#define HBYTES_ISEMPTY(hb) (!(hb)->begin_complex && !(hb)->end_0)
#define HBYTES_ISSENTINEL(hb) (!(hb)->begin_complex && (hb)->end_0)
/* The value made by hbytes_sentinel should not be passed to
* anything except HBYTES_IS..., and hbytes_free. */
+/* from sockaddr.c */
+
+typedef struct {
+ Byte *begin, *end;
+} SockAddr_Value;
+
+extern Tcl_ObjType sockaddr_type;
+
+void sockaddr_clear(SockAddr_Value*);
+void sockaddr_create(SockAddr_Value*, const struct sockaddr *addr, int len);
+int sockaddr_len(const SockAddr_Value*);
+const struct sockaddr *sockaddr_addr(const SockAddr_Value*);
+void sockaddr_free(const SockAddr_Value*);
+
+/* from dgram.c */
+
+extern Tcl_ObjType sockid_type;
+
/* from hook.c */
int staticerr(Tcl_Interp *ip, const char *m);
+int posixerr(Tcl_Interp *ip, int errnoval, const char *m);
void objfreeir(Tcl_Obj *o);
-void obj_updatestr_array(Tcl_Obj *o, const Byte *array, int l);
int get_urandom(Tcl_Interp *ip, Byte *buffer, int l);
+void obj_updatestr_array(Tcl_Obj *o, const Byte *array, int l);
+void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte,
+ int l, const char *prefix);
+
/* from parse.c */
typedef struct {
extern const BlockCipherModeInfo blockciphermodeinfos[];
+/* from misc.c */
+
+int setnonblock(int fd, int isnonblock);
+
/* useful macros */
#define OBJ_HBYTES(o) ((HBytes_Value*)&(o)->internalRep.twoPtrValue)
+#define OBJ_SOCKADDR(o) ((SockAddr_Value*)&(o)->internalRep.twoPtrValue)
#define TALLOC(s) ((void*)Tcl_Alloc((s)))
#define TFREE(f) (Tcl_Free((void*)(f)))
hbytes_free(OBJ_HBYTES(o));
}
-void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
+void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte,
+ int l, const char *prefix) {
char *str;
+ int pl;
+
+ pl= strlen(prefix);
+ o->length= l*2+pl;
+ str= o->bytes= TALLOC(o->length+1);
+
+ memcpy(str,prefix,pl);
+ str += pl;
- str= o->bytes= TALLOC(l*2+1);
- o->length= l*2;
while (l>0) {
sprintf(str,"%02x",*byte);
str+=2; byte++; l--;
*str= 0;
}
+void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
+ obj_updatestr_array_prefix(o,byte,l,"");
+}
+
static void hbytes_t_ustr(Tcl_Obj *o) {
obj_updatestr_array(o,
hbytes_data(OBJ_HBYTES(o)),
return subcmd->func(0,ip,objc,objv);
}
+int do__dgram_socket(ClientData cd, Tcl_Interp *ip,
+ const DgramSocket_SubCommand *subcmd,
+ int objc, Tcl_Obj *const *objv) {
+ return subcmd->func(0,ip,objc,objv);
+}
+
#define URANDOM "/dev/urandom"
int get_urandom(Tcl_Interp *ip, Byte *buffer, int l) {
Tcl_RegisterObjType(&blockcipherkey_type);
Tcl_RegisterObjType(&enum_nearlytype);
Tcl_RegisterObjType(&enum1_nearlytype);
- Tcl_CreateObjCommand(ip,"hbytes", pa__hbytes,0,0);
+ Tcl_RegisterObjType(&sockaddr_type);
+ Tcl_RegisterObjType(&sockid_type);
+ Tcl_CreateObjCommand(ip, "hbytes", pa__hbytes, 0,0);
+ Tcl_CreateObjCommand(ip, "dgram-socket", pa__dgram_socket, 0,0);
return TCL_OK;
}
rc= Tcl_ConvertToType(ip,val,&hbytes_type);
if (rc) return rc;
- agg->hb= OBJ_HBYTES(val);
- return TCL_OK;
-}
+ agg->hb= OBJ_HBYTES(val); return TCL_OK; }
void fini_hbv(Tcl_Interp *ip, int rc, HBytes_Var *agg) {
Tcl_Obj *ro;
Type hb: HBytes_Value @
Init hb hbytes_sentinel(&@);
+
Type hbv: HBytes_Var @
Init hbv @.hb=0; @.obj=0; @.var=0;
Fini hbv fini_hbv(ip, rc, &@);
+Type sockaddr: SockAddr_Value @
+Init sockaddr sockaddr_clear(&@);
+
+Type sockid: int @
+Init sockid @=-1;
+
H-Include "hbytes.h"
Untabled
hbytes
subcmd enum(HBytes_SubCommand, "hbytes subcommand")
obj ...
+ dgram-socket
+ subcmd enum(DgramSocket_SubCommand,"dgram-socket subcommand")
+ obj ...
Table hbytes HBytes_SubCommand
raw2h
length int
=> hb
-#Table udp UDP_SubCommand
-# create
-#
+Table dgram_socket DgramSocket_SubCommand
+ create
+ local sockaddr
+ => sockid
+# transmit
+#
OBJS= tables.o \
hbytes.o \
enum.o \
+ sockaddr.o \
+ dgram.o \
chop.o \
hook.o \
bcmode.o \
+ misc.o \
algtables.o \
serpent.o \
sha1.o \
TARGETS= hbytes.so
CC_CRYPTO= $(CC) $(CFLAGS) $(CPPFLAGS) -O3
-CFLAGS= -g -Wall $(OPTIMISE)
+CFLAGS= -g -Wall -Wmissing-prototypes -Wstrict-prototypes -Werror \
+ $(OPTIMISE)
OPTIMISE= -O2
all: $(TARGETS) $(AUTOS)
#include "hbytes.h"
-const char *mode_cbc_encrypt(Byte *data, int blocks,
- const Byte *iv, Byte *chain,
- const BlockCipherAlgInfo *alg, int encr,
- int blocksize, const void *sch) {
+static const char *mode_cbc_encrypt(Byte *data, int blocks,
+ const Byte *iv, Byte *chain,
+ const BlockCipherAlgInfo *alg, int encr,
+ int blocksize, const void *sch) {
memcpy(chain,iv,blocksize);
alg->byteswap(chain);
return 0;
}
-const char *mode_cbc_decrypt(Byte *data, int blocks,
- const Byte *iv, Byte *chain,
- const BlockCipherAlgInfo *alg, int encr,
- int blocksize, const void *sch) {
+static const char *mode_cbc_decrypt(Byte *data, int blocks,
+ const Byte *iv, Byte *chain,
+ const BlockCipherAlgInfo *alg, int encr,
+ int blocksize, const void *sch) {
int cchain= 0;
memcpy(chain,iv,blocksize);
return 0;
}
-const char *mode_ecb(Byte *data, int blocks,
- const Byte *iv, Byte *chain,
- const BlockCipherAlgInfo *alg, int encr,
- int blocksize, const void *sch) {
+static const char *mode_ecb(Byte *data, int blocks,
+ const Byte *iv, Byte *chain,
+ const BlockCipherAlgInfo *alg, int encr,
+ int blocksize, const void *sch) {
while (blocks > 0) {
alg->byteswap(data);
(encr ? &alg->encrypt : &alg->decrypt)->crypt(sch, data, data);
key_t_free, key_t_dup, key_t_ustr, key_t_sfa
};
-CiphKeyValue *get_key(Tcl_Interp *ip, Tcl_Obj *key_obj,
- const void *alg, int want_bufferslen) {
+static CiphKeyValue *get_key(Tcl_Interp *ip, Tcl_Obj *key_obj,
+ const void *alg, int want_bufferslen) {
CiphKeyValue *key;
int rc;
--- /dev/null
+/*
+ */
+/*
+ * dgram-socket create <local> => <sockid>
+ * dgram-socket close <sockid>
+ * dgram-socket transmit <sockid> <data> <remote>
+ * dgram-socket on-receive <sockid> <script>
+ * calls, effectively, eval <script> [list <data> <remote-addr> <socket>]
+ */
+
+#include "tables.h"
+#include "hbytes.h"
+
+static int sockfail(Tcl_Interp *ip, int fd, const char *m) {
+ int e;
+ e= errno;
+ close(fd);
+ return posixerr(ip,e,m);
+}
+
+int do_dgram_socket_create(ClientData cd, Tcl_Interp *ip,
+ SockAddr_Value local, int *result) {
+ int fd, al, r;
+ const struct sockaddr *sa;
+
+ sa= sockaddr_addr(&local);
+ al= sockaddr_len(&local);
+
+ fd= socket(sa->sa_family, SOCK_DGRAM, 0);
+ if (fd<0) return posixerr(ip,errno,"socket");
+ r= bind(fd, sa, al); if (r) return sockfail(ip,fd,"bind");
+ r= setnonblock(fd, 1); if (r) return sockfail(ip,fd,"setnonblock");
+ *result= fd;
+ return TCL_OK;
+}
+
+/* Arg parsing */
+
+int pat_sockid(Tcl_Interp *ip, Tcl_Obj *o, int *val) {
+ int rc;
+
+ rc= Tcl_ConvertToType(ip,o,&sockid_type);
+ if (rc) return rc;
+
+ *val= o->internalRep.longValue;
+ return TCL_OK;
+}
+
+Tcl_Obj *ret_sockid(Tcl_Interp *ip, int val) {
+ Tcl_Obj *o;
+
+ o= Tcl_NewObj();
+ Tcl_InvalidateStringRep(o);
+ o->internalRep.longValue= val;
+ o->typePtr= &sockid_type;
+ return o;
+}
+
+static void sockid_t_free(Tcl_Obj *o) { }
+
+static void sockid_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
+ dup->internalRep= src->internalRep;
+}
+
+static void sockid_t_ustr(Tcl_Obj *o) {
+ char buf[100];
+ int l;
+
+ snprintf(buf,sizeof(buf),"dgramsock%d", (int)o->internalRep.longValue);
+ l= o->length= strlen(buf);
+ o->bytes= TALLOC(l+1);
+ strcpy(o->bytes, buf);
+}
+
+static int sockid_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
+ unsigned long ul;
+ char *ep, *str;
+
+ str= Tcl_GetStringFromObj(o,0);
+ if (memcmp(str,"dgramsock",9)) return staticerr(ip,"bad dgram socket id");
+ errno=0; ul=strtoul(str+9,&ep,10);
+ if (errno || *ep) return staticerr(ip,"bad dgram socket id number");
+ if (ul > INT_MAX) return staticerr(ip,"out of range dgram socket id");
+ o->internalRep.longValue= ul;
+ return TCL_OK;
+}
+
+Tcl_ObjType sockid_type = {
+ "sockid-nearly",
+ sockid_t_free, sockid_t_dup, sockid_t_ustr, sockid_t_sfa
+};
/**/
-#include "all.h"
+#include "hbytes.h"
int setnonblock(int fd, int isnonblock) {
int r;
--- /dev/null
+/*
+ * struct sockaddr
+ *
+ * syntaxes:
+ * ddd.ddd.ddd.ddd,nnnn IPv4 address and port
+ * ... host or port may be `*'
+ * /abs/path/to/socket AF_UNIX
+ * ./rel/path/to/socket AF_UNIX
+ */
+
+#include "hbytes.h"
+#include "tables.h"
+
+#define SOCKADDR_LEN(sa) ((sa)->end - (sa)->begin)
+
+/* parsing */
+
+int pat_sockaddr(Tcl_Interp *ip, Tcl_Obj *o, SockAddr_Value *val) {
+ int rc;
+
+ rc= Tcl_ConvertToType(ip,o,&sockaddr_type);
+ if (rc) return rc;
+
+ *val= *OBJ_SOCKADDR(o);
+ return TCL_OK;
+}
+
+Tcl_Obj *ret_sockaddr(Tcl_Interp *ip, SockAddr_Value val) {
+ Tcl_Obj *o;
+
+ o= Tcl_NewObj();
+ Tcl_InvalidateStringRep(o);
+ *OBJ_SOCKADDR(o)= val;
+ o->typePtr= &sockaddr_type;
+ return o;
+}
+
+/* native type methods */
+
+void sockaddr_clear(SockAddr_Value *v) { v->begin= v->end= 0; }
+
+void sockaddr_create(SockAddr_Value *v, const struct sockaddr *addr, int len) {
+ Byte *begin;
+
+ v->begin= begin= TALLOC(len);
+ memcpy(begin, addr, len);
+ v->end= begin + len;
+}
+
+int sockaddr_len(const SockAddr_Value *v) {
+ return SOCKADDR_LEN(v);
+}
+
+const struct sockaddr *sockaddr_addr(const SockAddr_Value *v) {
+ return (const void*)v->begin;
+}
+
+void sockaddr_free(const SockAddr_Value *v) {
+ TFREE(v->begin);
+}
+
+/* Sockaddr Tcl type */
+
+static void sockaddr_t_dup(Tcl_Obj *src, Tcl_Obj *dup) {
+ objfreeir(dup);
+ sockaddr_create(OBJ_SOCKADDR(dup),
+ sockaddr_addr(OBJ_SOCKADDR(src)),
+ sockaddr_len(OBJ_SOCKADDR(src)));
+}
+
+static void sockaddr_t_free(Tcl_Obj *o) {
+ sockaddr_free(OBJ_SOCKADDR(o));
+}
+
+static void sockaddr_t_ustr(Tcl_Obj *o) {
+ const struct sockaddr *sa;
+ char i46buf[INET6_ADDRSTRLEN];
+ int al, sl, pl;
+ const char *string, *prepend;
+
+ sa= sockaddr_addr(OBJ_SOCKADDR(o));
+ al= sockaddr_len(OBJ_SOCKADDR(o));
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ assert(sizeof(i46buf) >= INET_ADDRSTRLEN);
+ assert(al >= sizeof(struct sockaddr_in));
+ inet_ntop(sa->sa_family, sa, i46buf, al);
+ string= i46buf;
+ prepend= "";
+ break;
+
+ case AF_UNIX:
+ assert(al >= sizeof(struct sockaddr_un));
+ string= ((const struct sockaddr_un*)sa)->sun_path;
+ prepend= "";
+ if (!string[0]) string="//";
+ else if (string[0] != '/' || string[1] == '/') prepend= "./";
+
+ default: /* ouch ! */
+ obj_updatestr_array_prefix(o,(const void*)sa,al,"?");
+ return;
+ }
+
+ pl= strlen(prepend);
+ sl= strlen(string);
+ o->bytes= TALLOC(sl+1);
+ memcpy(o->bytes, prepend, pl);
+ memcpy(o->bytes+pl, string, sl+1);
+}
+
+static int sockaddr_t_sfa(Tcl_Interp *ip, Tcl_Obj *o) {
+ union {
+ struct sockaddr_un sun;
+ struct sockaddr_in sin;
+ } s;
+ unsigned long port_l;
+
+ char *str, *ep, *copy;
+ int sl, pl, iprv;
+ const char *comma, *path;
+
+ str= Tcl_GetStringFromObj(o,0); assert(str);
+ objfreeir(o);
+ memset(&s,0,sizeof(s));
+
+ if (str[0]=='/' || (str[0]=='.' && str[1]=='/')) {
+
+ sl= sizeof(s.sun);
+ s.sun.sun_family= AF_UNIX;
+
+ if (strcmp(str,"//")) path= "";
+ else if (memcmp(str,"./",2) && str[2]) path= str+2;
+ else { assert(str[0]=='/' && str[1]!='/'); path=str; }
+
+ if (strlen(str) >= sizeof(s.sun.sun_path))
+ return staticerr(ip, "AF_UNIX path too long");
+
+ strcpy(s.sun.sun_path, str);
+
+ } else if ((comma= strchr(str, ','))) {
+
+ sl= sizeof(s.sin);
+ s.sin.sin_family= AF_INET;
+
+ pl= comma - str;
+ copy= TALLOC(pl+1);
+ memcpy(copy, str, pl);
+ copy[pl]= 0;
+
+ if (!strcmp(copy,"*")) {
+ s.sin.sin_addr.s_addr= INADDR_ANY;
+ iprv= 1;
+ } else {
+ iprv= inet_pton(AF_INET, copy, &s.sin.sin_addr);
+ }
+ TFREE(copy);
+
+ if (!iprv) return staticerr(ip, "bad IPv4 address syntax");
+
+ comma++;
+ if (!strcmp(comma,"*")) {
+ s.sin.sin_port= 0;
+ } else {
+ errno=0; port_l=strtoul(comma,&ep,10);
+ if (errno || *ep) return staticerr(ip, "bad IPv4 port");
+ if (port_l > 65535) return staticerr(ip, "IPv4 port out of range");
+ s.sin.sin_port= htons(port_l);
+ }
+
+ } else {
+
+ return staticerr(ip, "bad socket address syntax");
+
+ }
+
+ sockaddr_create(OBJ_SOCKADDR(o), (void*)&s, sl);
+
+ o->typePtr = &sockaddr_type;
+ return TCL_OK;
+}
+
+Tcl_ObjType sockaddr_type = {
+ "sockaddr",
+ sockaddr_t_free, sockaddr_t_dup, sockaddr_t_ustr, sockaddr_t_sfa
+};
#include <string.h>
#include "hbytes.h"
+#include "tables.h"
static int strs1(Tcl_Interp *ip, int strc, Tcl_Obj *const *strv, int *l_r) {
int rc, l, i;
return newpart;
}
-HBytes_ComplexValue *prechop(HBytes_Value *hb, int cl, const Byte **rv) {
+static HBytes_ComplexValue*
+prechop(HBytes_Value *hb, int cl, const Byte **rv) {
HBytes_ComplexValue *cx;
if (cl<0) { *rv=0; return 0; }
#include <assert.h>
#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <arpa/inet.h>
#include <tcl.h>
/* from hbytes.c */
+int Hbytes_Init(Tcl_Interp *ip); /* called by Tcl's "load" */
+
/* Internal representation details: */
#define HBYTES_ISEMPTY(hb) (!(hb)->begin_complex && !(hb)->end_0)
#define HBYTES_ISSENTINEL(hb) (!(hb)->begin_complex && (hb)->end_0)
/* The value made by hbytes_sentinel should not be passed to
* anything except HBYTES_IS..., and hbytes_free. */
+/* from sockaddr.c */
+
+typedef struct {
+ Byte *begin, *end;
+} SockAddr_Value;
+
+extern Tcl_ObjType sockaddr_type;
+
+void sockaddr_clear(SockAddr_Value*);
+void sockaddr_create(SockAddr_Value*, const struct sockaddr *addr, int len);
+int sockaddr_len(const SockAddr_Value*);
+const struct sockaddr *sockaddr_addr(const SockAddr_Value*);
+void sockaddr_free(const SockAddr_Value*);
+
+/* from dgram.c */
+
+extern Tcl_ObjType sockid_type;
+
/* from hook.c */
int staticerr(Tcl_Interp *ip, const char *m);
+int posixerr(Tcl_Interp *ip, int errnoval, const char *m);
void objfreeir(Tcl_Obj *o);
-void obj_updatestr_array(Tcl_Obj *o, const Byte *array, int l);
int get_urandom(Tcl_Interp *ip, Byte *buffer, int l);
+void obj_updatestr_array(Tcl_Obj *o, const Byte *array, int l);
+void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte,
+ int l, const char *prefix);
+
/* from parse.c */
typedef struct {
extern const BlockCipherModeInfo blockciphermodeinfos[];
+/* from misc.c */
+
+int setnonblock(int fd, int isnonblock);
+
/* useful macros */
#define OBJ_HBYTES(o) ((HBytes_Value*)&(o)->internalRep.twoPtrValue)
+#define OBJ_SOCKADDR(o) ((SockAddr_Value*)&(o)->internalRep.twoPtrValue)
#define TALLOC(s) ((void*)Tcl_Alloc((s)))
#define TFREE(f) (Tcl_Free((void*)(f)))
hbytes_free(OBJ_HBYTES(o));
}
-void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
+void obj_updatestr_array_prefix(Tcl_Obj *o, const Byte *byte,
+ int l, const char *prefix) {
char *str;
+ int pl;
+
+ pl= strlen(prefix);
+ o->length= l*2+pl;
+ str= o->bytes= TALLOC(o->length+1);
+
+ memcpy(str,prefix,pl);
+ str += pl;
- str= o->bytes= TALLOC(l*2+1);
- o->length= l*2;
while (l>0) {
sprintf(str,"%02x",*byte);
str+=2; byte++; l--;
*str= 0;
}
+void obj_updatestr_array(Tcl_Obj *o, const Byte *byte, int l) {
+ obj_updatestr_array_prefix(o,byte,l,"");
+}
+
static void hbytes_t_ustr(Tcl_Obj *o) {
obj_updatestr_array(o,
hbytes_data(OBJ_HBYTES(o)),
return subcmd->func(0,ip,objc,objv);
}
+int do__dgram_socket(ClientData cd, Tcl_Interp *ip,
+ const DgramSocket_SubCommand *subcmd,
+ int objc, Tcl_Obj *const *objv) {
+ return subcmd->func(0,ip,objc,objv);
+}
+
#define URANDOM "/dev/urandom"
int get_urandom(Tcl_Interp *ip, Byte *buffer, int l) {
Tcl_RegisterObjType(&blockcipherkey_type);
Tcl_RegisterObjType(&enum_nearlytype);
Tcl_RegisterObjType(&enum1_nearlytype);
- Tcl_CreateObjCommand(ip,"hbytes", pa__hbytes,0,0);
+ Tcl_RegisterObjType(&sockaddr_type);
+ Tcl_RegisterObjType(&sockid_type);
+ Tcl_CreateObjCommand(ip, "hbytes", pa__hbytes, 0,0);
+ Tcl_CreateObjCommand(ip, "dgram-socket", pa__dgram_socket, 0,0);
return TCL_OK;
}
rc= Tcl_ConvertToType(ip,val,&hbytes_type);
if (rc) return rc;
- agg->hb= OBJ_HBYTES(val);
- return TCL_OK;
-}
+ agg->hb= OBJ_HBYTES(val); return TCL_OK; }
void fini_hbv(Tcl_Interp *ip, int rc, HBytes_Var *agg) {
Tcl_Obj *ro;