#include "efuns.h" #include "array.h" #include "comm.h" #include "socket_err.h" #include "socket_efuns.h" #include "simulate.h" #include "stralloc.h" extern struct lpc_socket lpc_socks[MAX_EFUN_SOCKS]; /* define this to make socket_write slower */ /* #define PARANOID_SECURITY */ /* obs: this might be useful in the lpc code: */ /* #define NULL (lambda() {}) */ static int i; #ifdef F_SOCKET_CREATE void f_socket_create(int num_arg,struct svalue *argp) { int fd; struct svalue *ret; struct vector *info; if(num_arg==3) check_argument(2,T_FUNCTION,F_SOCKET_CREATE); info = allocate_array(4); info->ref--; info->item[0].type = T_NUMBER; info->item[0].u.number = -1; assign_socket_owner(info->item + 1, current_object); info->item[3].type = T_NUMBER; info->item[3].u.number = -1; push_object(current_object); push_new_shared_string("create"); push_vector(info); APPLY_MASTER_OB(ret=,"valid_socket", 3); if (!IS_ZERO(ret)) { switch(num_arg) { default: /* make gcc happy */ case 3: fd = socket_create(argp[0].u.number, argp+1, argp+2); break; case 2: fd = socket_create(argp[0].u.number, NULL, argp+1); break; case 1: fd = socket_create(argp[0].u.number, NULL, NULL); break; } } else { fd=EESECURITY; } pop_n_elems(num_arg); push_number(fd); } #endif #ifdef F_SOCKET_BIND void f_socket_bind(int num_arg,struct svalue *argp) { int fd, port; struct svalue *ret; struct vector *info; char addr[ADDR_BUF_SIZE]; fd = argp[0].u.number; get_socket_address(fd, addr, &port); info = allocate_array(4); info->ref--; info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], get_socket_owner(fd)); SET_STR(info->item,make_shared_string(addr)); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_new_shared_string("bind"); push_vector(info); APPLY_MASTER_OB(ret=,"valid_socket", 3); if (!IS_ZERO(ret)) { i = socket_bind(fd, sp->u.number); } else { i=EESECURITY; } pop_n_elems(2); /* pop both args off stack */ push_number(i); /* push return int onto stack */ } #endif #ifdef F_SOCKET_LISTEN void f_socket_listen(int num_arg,struct svalue *argp) { int fd, port; struct svalue *ret; struct vector *info; char addr[ADDR_BUF_SIZE]; int err; fd = argp[0].u.number; err=get_socket_address(fd, addr, &port); if(err<0) { pop_n_elems(2); push_number(err); return; } info = allocate_array(4); info->ref--; info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], get_socket_owner(fd)); SET_STR(info->item,make_shared_string(addr)); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_new_shared_string("listen"); push_vector(info); APPLY_MASTER_OB(ret=,"valid_socket",3); if (!IS_ZERO(ret)) { i = socket_listen(fd, argp+1); } else { i=EESECURITY; } pop_n_elems(2); /* pop both args off stack */ push_number(i); /* push return int onto stack */ } #endif #ifdef F_SOCKET_ACCEPT void f_socket_accept(int num_arg,struct svalue *argp) { int fd, port; struct svalue *ret; struct vector *info; char addr[ADDR_BUF_SIZE]; int err; check_argument(2,T_FUNCTION,F_SOCKET_ACCEPT); fd = argp[0].u.number; err=get_socket_address(fd, addr, &port); if(err<0) { pop_n_elems(3); push_number(err); return; } info = allocate_array(4); info->ref--; info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], get_socket_owner(fd)); SET_STR(info->item,make_shared_string(addr)); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_new_shared_string("accept"); push_vector(info); APPLY_MASTER_OB(ret=,"valid_socket", 3); if (!IS_ZERO(ret)) { i = socket_accept(fd, argp+1,argp+2); }else{ i=EESECURITY; } pop_n_elems(3); /* pop both args off stack */ push_number(i); /* push return int onto stack */ } #endif #ifdef F_SOCKET_CONNECT void f_socket_connect(int num_arg,struct svalue *argp) { int fd, port; struct svalue *ret; struct vector *info; char addr[ADDR_BUF_SIZE]; int err; check_argument(2,T_FUNCTION,F_SOCKET_CONNECT); check_argument(3,T_FUNCTION,F_SOCKET_CONNECT); fd = argp[0].u.number; err=get_socket_address(fd, addr, &port); if(err<0) { pop_n_elems(3); push_number(err); return; } info = allocate_array(4); info->ref--; info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], get_socket_owner(fd)); SET_STR(info->item,make_shared_string(addr)); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_new_shared_string("connect"); push_vector(info); APPLY_MASTER_OB(ret=,"valid_socket", 3); if (!IS_ZERO(ret)) { i = socket_connect(fd, strptr(argp+1), argp+2,argp+3); } else { i=EESECURITY; } pop_n_elems(4); /* pop all args off stack */ push_number(i); /* push return int onto stack */ } #endif #ifdef F_SOCKET_WRITE void f_socket_write(int num_arg,struct svalue *argp) { int fd, port; char addr[ADDR_BUF_SIZE]; int err; if(num_arg==3) { check_argument(2,T_STRING,F_SOCKET_WRITE); } fd = argp[0].u.number; err=get_socket_address(fd, addr, &port); if(err<0) { pop_n_elems(3); push_number(err); return; } #ifdef PARANOID_SECURITY get_socket_address(fd, addr, &port); info = allocate_array(4); info->ref--; info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], get_socket_owner(fd)); SET_STR(info->item,make_shared_string(addr)); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_new_shared_string("write"); push_vector(info); APPLY_MASTER_OB(ret=,"valid_socket", 3); if (!IS_ZERO(ret)) { i = socket_write(fd, argp+1, (num_arg == 3) ? strptr(argp+2) : (char *)NULL); } else { i=EESECURITY; } #else i = socket_write(fd, argp+1, (num_arg == 3) ? strptr(argp+2) : (char *)NULL); #endif pop_n_elems(num_arg); push_number(i); /* push return int onto stack */ } #endif #ifdef F_SOCKET_CLOSE void f_socket_close(int num_arg,struct svalue *argp) { int fd, port; struct svalue *ret; struct vector *info; char addr[ADDR_BUF_SIZE]; int err; fd = argp[0].u.number; err=get_socket_address(fd, addr, &port); if(err<0) { pop_n_elems(1); push_number(err); return; } info = allocate_array(4); info->ref--; info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], get_socket_owner(fd)); SET_STR(info->item,make_shared_string(addr)); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_new_shared_string("close"); push_vector(info); APPLY_MASTER_OB(ret=,"valid_socket", 3); if (!IS_ZERO(ret)) { i = socket_close(fd,0); } else { i=EESECURITY; } pop_stack(); /* pop int arg off stack */ push_number(i); /* Security violation attempted */ } #endif #ifdef F_SOCKET_RELEASE void f_socket_release(int num_arg,struct svalue *argp) { int fd, port; struct svalue *ret; struct vector *info; char addr[ADDR_BUF_SIZE]; int err; fd = argp[0].u.number; err=get_socket_address(fd, addr, &port); if(err<0) { pop_n_elems(2); push_number(err); return; } info = allocate_array(4); info->ref--; info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], get_socket_owner(fd)); SET_STR(info->item,make_shared_string(addr)); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_new_shared_string("release"); push_vector(info); APPLY_MASTER_OB(ret=,"valid_socket", 3); if (!IS_ZERO(ret)) { i = socket_release(argp[0].u.number, argp+1); } else { i=EESECURITY; } pop_n_elems(2); /* pop all args off stack */ push_number(i); /* push return int onto stack */ } #endif #ifdef F_SOCKET_ACQUIRE void f_socket_acquire(int num_arg,struct svalue *argp) { int fd, port; struct svalue *ret; struct vector *info; char addr[ADDR_BUF_SIZE]; int err; check_argument(2,T_FUNCTION,F_SOCKET_ACQUIRE); check_argument(3,T_FUNCTION,F_SOCKET_ACQUIRE); fd = argp[0].u.number; err=get_socket_address(fd, addr, &port); if(err<0) { pop_n_elems(3); push_number(err); return; } info = allocate_array(4); info->ref--; info->item[0].type = T_NUMBER; info->item[0].u.number = fd; assign_socket_owner(&info->item[1], get_socket_owner(fd)); SET_STR(info->item,make_shared_string(addr)); info->item[3].type = T_NUMBER; info->item[3].u.number = port; push_object(current_object); push_new_shared_string("acquire"); push_vector(info); APPLY_MASTER_OB(ret=,"valid_socket", 3); if (!IS_ZERO(ret)) { i = socket_acquire(fd,argp+1,argp+2,argp+3); } else { i=EESECURITY; } pop_n_elems(4); /* pop both args off stack */ push_number(i); /* push return int onto stack */ } #endif #ifdef F_SOCKET_ERROR void f_socket_error(int num_arg,struct svalue *argp) { char *error; extern char *socket_error(int); error = socket_error(sp->u.number); pop_stack(); /* pop int arg off stack */ push_new_shared_string(error); /* push return string onto stack */ } #endif #ifdef F_SOCKET_ADDRESS void f_socket_address(int num_arg,struct svalue *argp) { char addr[50]; int port,ret; ret=get_socket_address(argp[0].u.number,addr,&port); pop_stack(); if(ret==EESUCCESS) { push_new_shared_string(addr); }else{ push_number(ret); } } #endif #ifdef F_SOCKET_ADDRESS void f_socket_port(int num_arg,struct svalue *argp) { char addr[50]; int port,ret; ret=get_socket_address(argp[0].u.number,addr,&port); pop_stack(); if(ret==EESUCCESS) { push_number(port); }else{ push_number(ret); } } #endif #ifdef F_DUMP_SOCKET_STATUS void f_dump_socket_status(int num_arg,struct svalue *argp) { push_shared_string((char *)dump_socket_status()); } #endif #ifdef F_SET_SOCKET_READ void f_set_socket_read(int num_arg,struct svalue *argp) { int fd; fd=argp[0].u.number; if(fd < 0 || fd >= MAX_EFUN_SOCKS) { pop_stack(); pop_stack(); push_number(EEFDRANGE); }else if(current_object!=lpc_socks[fd].owner_ob){ pop_stack(); pop_stack(); push_number(EESECURITY); }else{ assign_svalue(&lpc_socks[fd].read_callback,argp+1); pop_stack(); pop_stack(); push_number(EESUCCESS); } } #endif #ifdef F_SET_SOCKET_WRITE void f_set_socket_write(int num_arg,struct svalue *argp) { int fd; fd=argp[0].u.number; if(fd < 0 || fd >= MAX_EFUN_SOCKS) { pop_stack(); pop_stack(); push_number(EEFDRANGE); }else if(current_object!=lpc_socks[fd].owner_ob){ pop_stack(); pop_stack(); push_number(EESECURITY); }else{ assign_svalue(&lpc_socks[fd].write_callback,argp+1); pop_stack(); pop_stack(); push_number(EESUCCESS); } } #endif #ifdef F_SET_SOCKET_CLOSE void f_set_socket_close(int num_arg,struct svalue *argp) { int fd; fd=argp[0].u.number; if(fd < 0 || fd >= MAX_EFUN_SOCKS) { pop_stack(); pop_stack(); push_number(EEFDRANGE); }else if(current_object!=lpc_socks[fd].owner_ob){ pop_stack(); pop_stack(); push_number(EESECURITY); }else { assign_svalue(&lpc_socks[fd].close_callback,argp+1); pop_stack(); pop_stack(); push_number(EESUCCESS); } } #endif #ifdef F_SET_SOCKET_MODE void f_set_socket_mode(int num_arg,struct svalue *argp) { int fd,mode; fd=argp[0].u.number; mode=argp[1].u.number; pop_stack(); pop_stack(); if(fd < 0 || fd >= MAX_EFUN_SOCKS) { push_number(EEFDRANGE); }else if(current_object!=lpc_socks[fd].owner_ob){ push_number(EESECURITY); }else if((mode & S_MODE_MASK) != (lpc_socks[fd].mode & S_MODE_MASK)){ push_number(EEMODENOTSUPP); }else{ lpc_socks[fd].mode=mode; push_number(EESUCCESS); } } #endif #ifdef F_SOCKET_FROM_STDIN void f_socket_from_stdin(int num_arg,struct svalue *argp) { extern int stdin_is_sock; if(stdin_is_sock) { push_number(socket_from_stdin()); }else{ error("Stdin is not a socket.\n"); } } #endif