/** * z_dispatch_connection: * @chain this * @conn The new connection to dispatch * * Iterates through the chain and dispatches the connection to the * chain items by passing it to their callbacks (for example to * z_py_zorp_dispatch_accept, which passes it to Dispatcher.accepted). */ static void z_dispatch_connection(ZDispatchChain *chain, ZConnection *conn) { GList *p; ZDispatchEntry *entry; gchar buf[256]; z_enter(); z_dispatch_chain_lock(chain); /* the list is ordered by priority */ for (p = chain->elements; p; p = g_list_next(p)) { entry = (ZDispatchEntry *) p->data; /*LOG This message reports that a new connections is coming. */ z_log(entry->session_id, CORE_DEBUG, 6, "Incoming connection; %s", conn ? z_connection_format(conn, buf, sizeof(buf)) : "conn=NULL"); if ((entry->callback)(conn, entry->callback_data)) { z_dispatch_chain_unlock(chain); z_return(); } } z_dispatch_chain_unlock(chain); /* nobody needed this connection, destroy it */ /*LOG This message indicates that a new connection was accepted, but no Listenet/Receiver/Proxy was interested in it. */ z_log(NULL, CORE_ERROR, 3, "Nobody was interested in this connection; %s", z_connection_format(conn, buf, sizeof(buf))); z_connection_destroy(conn, TRUE); z_return(); }
/** * z_policy_load: * @self: this * * Load and run a policy file. If the file doesn't exist or a parse error * happens, produces an error message in the log. * * Returns: * TRUE on success */ gboolean z_policy_load(ZPolicy *self) { FILE *script; int res = -1; script = fopen(self->policy_filename, "r"); if (script) { z_policy_thread_acquire(self->main_thread); res = PyRun_SimpleFile(script, self->policy_filename); fclose(script); z_policy_thread_release(self->main_thread); } else { /*LOG This message indicates that Zorp was unable to open the policy file. Check the permissions of your policy file. */ z_log(NULL, CORE_ERROR, 0, "Error opening policy file; filename='%s'", self->policy_filename); } if (res == -1) { /*LOG This message indicates that Zorp was unable to parse the policy file. Check the logs for further information on where the error occurred in the policy. */ z_log(NULL, CORE_ERROR, 0, "Error parsing policy file; filename='%s'", self->policy_filename); /* let the error message out */ } return res != -1; }
/** * Decrease reference count of a blob system; destroy it if the count reaches zero. * * @param[in] self the blob system object * * This function decreases the reference count of the blob system * object given. If the reference count reaches zero, the blob system * will be destroyed. If there were pending requests in a to-be-destroyed * blob system, this fact will be logged. **/ void z_blob_system_unref(ZBlobSystem *self) { ZBlob *blob; GList *cur, *next; gint n; z_enter(); g_assert(self); if (z_refcount_dec(&self->ref_cnt)) { self->active = FALSE; /** @todo FIXME: itt lockolni kell */ g_async_queue_push(self->req_queue, Z_BLOB_THREAD_KILL); g_thread_join(self->thr_management); n = 0; for (cur = self->waiting_list; cur; cur = next) { next = cur->next; blob = (ZBlob*) cur->data; blob->approved = FALSE; z_blob_signal_ready(blob); self->waiting_list = g_list_delete_link(self->waiting_list, cur); n++; } if (n) z_log(NULL, CORE_INFO, 5, "Pending requests found for a to-be-destroyed blob system; num_requests='%d'", n); n = 0; for (cur = self->blobs; cur; cur = next) { next = cur->next; blob = (ZBlob*)cur->data; z_blob_unref(blob); n++; } if (n) z_log(NULL, CORE_INFO, 5, "Active blobs found in a to-be-destroyed blob system; num_blobs='%d'", n); if (self->dir) g_free(self->dir); if (g_mutex_trylock(self->mtx_blobsys)) { g_mutex_unlock(self->mtx_blobsys); g_mutex_free(self->mtx_blobsys); } else { /* Some blob operations are in progress: z_blob_new, _unref, _alloc, _get_file */ } g_cond_free(self->cond_thread_started); g_async_queue_unref(self->req_queue); g_list_free(self->waiting_list); g_free(self); } z_return(); }
/** * Write some data into the given position of the blob, expanding it if necessary. * * @param[in] self this * @param[in] pos position to write to * @param[in] data data to write * @param[in] req_datalen length of data * @param[in] timeout timeout * * @returns The amount of data written. **/ gsize z_blob_add_copy(ZBlob *self, gint64 pos, const gchar* data, gsize req_datalen, gint timeout) { off_t err; gssize written = 0; z_enter(); g_assert(self); g_assert(data); g_assert(pos >= 0); if (z_blob_lock(self, timeout)) { if (self->alloc_size < (pos + (gssize) req_datalen)) z_blob_alloc(self, pos + req_datalen); if (self->is_in_file) { gssize remain; err = lseek(self->fd, pos, SEEK_SET); if (err < 0) { z_log(NULL, CORE_ERROR, 0, "Blob error, lseek() failed; file='%s', error='%s'", self->filename, g_strerror(errno)); g_assert(0); } remain = req_datalen; while (remain > 0) { written = write(self->fd, data, remain); if (written < 0) { if (errno == EINTR) { continue; } else { z_log(NULL, CORE_ERROR, 0, "Blob error, write() failed; file='%s', error='%s'", self->filename, g_strerror(errno)); g_assert(0); } } remain -= written; } } else { memmove(self->data + pos, data, req_datalen); written = req_datalen; } if (self->size < (pos + written)) self->size = pos + written; self->stat.req_wr++; self->stat.total_wr += written; self->stat.last_accessed = time(NULL); z_blob_unlock(self); } z_return(written); }
/** * Reads some data from the blob into a buffer. * * @param[in] self this * @param[in] pos position to read from * @param[in] data buffer to read into * @param[in] req_datalen bytes to read * @param[in] timeout timeout * * @returns The amount of data actually read. **/ gsize z_blob_get_copy(ZBlob *self, gint64 pos, gchar* data, gsize req_datalen, gint timeout) { off_t err; gssize rd = 0; z_enter(); g_assert(self); g_assert(data); g_assert(pos >= 0); if (pos < self->size) { if (req_datalen > (guint64) (self->size - pos)) req_datalen = self->size - pos; if (z_blob_lock(self, timeout)) { if (self->is_in_file) { gssize remain; err = lseek(self->fd, pos, SEEK_SET); if (err < 0) { z_log(NULL, CORE_ERROR, 0, "Blob error, lseek() failed; file='%s', error='%s'", self->filename, g_strerror(errno)); g_assert(0); } remain = req_datalen; while (remain > 0) { rd = read(self->fd, data, remain); if (rd < 0) { if (errno == EINTR) { continue; } else { z_log(NULL, CORE_ERROR, 0, "Blob error, read() failed; file='%s', error='%s'", self->filename, g_strerror(errno)); g_assert(0); } } remain -= rd; } } else { memmove(data, self->data + pos, req_datalen); rd = req_datalen; } self->stat.req_rd++; self->stat.total_rd += rd; self->stat.last_accessed = time(NULL); z_blob_unlock(self); } } z_return(rd); }
/** * This function enables or disables the non-blocking mode of operation on * the given fd. * * @param[in] fd file descriptor to change * @param[in] enable specifies whether to enable or disable O_NONBLOCK * * @returns whether the operation was successful **/ gboolean z_fd_set_nonblock(int fd, gboolean enable) { #ifdef G_OS_WIN32 /* Note: this assumes the fd is a socket. */ unsigned long argp; argp = enable; if (!enable) { if (WSAEventSelect(fd, (WSAEVENT) NULL, 0) == SOCKET_ERROR) { z_log(NULL, CORE_ERROR, 3, "Disabling socket events failed; fd='%d', error='%08x'", fd, z_errno_get()); return FALSE; } } if (ioctlsocket(fd, FIONBIO, &argp) == SOCKET_ERROR) { /*LOG This message indicates that changing the blocking state on the given fd failed for the given reason. Please report this event to the Zorp QA team. */ z_log(NULL, CORE_ERROR, 3, "Changing blocking mode failed; fd='%d', enable='%d', error='%08x'", fd, enable, z_errno_get()); return FALSE; } #else int flags; if ((flags = fcntl(fd, F_GETFL)) == -1) return FALSE; if (enable) flags |= O_NONBLOCK; else flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) < 0) { /*LOG This message indicates that changing the blocking state on the given fd failed for the given reason. Please report this event to the Zorp QA team. */ z_log(NULL, CORE_ERROR, 3, "Changing blocking mode failed; fd='%d', enable='%d', error='%s'", fd, enable, g_strerror(errno)); return FALSE; } #endif return TRUE; }
/** * Get the (absolute) filename assigned to the blob. * * @param[in] self this * @param[in] user Owner of the created file or NULL * @param[in] group Group of the created file or NULL * @param[in] mode Mode of the created file of -1 * @param[in] timeout timeout * * @returns The filename **/ const gchar * z_blob_get_file(ZBlob *self, const gchar *user, const gchar *group, gint mode, gint timeout) { const gchar *res = NULL; z_enter(); g_assert(self); if (!self->filename || !self->system) z_return(NULL); if (z_blob_lock(self, timeout)) { if (!self->is_in_file) { if (self->storage_locked) goto exit; g_mutex_lock(self->system->mtx_blobsys); /* swap_out() accesses the blob systems data directly, so it needs to be locked */ z_blob_swap_out(self); g_mutex_unlock(self->system->mtx_blobsys); } if (group || user) { uid_t user_id = -1; gid_t group_id = -1; if (user && !z_resolve_user(user, &user_id)) { z_log(NULL, CORE_ERROR, 3, "Cannot resolve user; user='******'", user); goto exit; } if (group && !z_resolve_group(group, &group_id)) { z_log(NULL, CORE_ERROR, 3, "Cannot resolve group; group='%s'", group); goto exit; } if (chown(self->filename, user_id, group_id) == -1) goto exit; } if ((mode != -1) && (chmod(self->filename, mode) == -1)) goto exit; res = self->filename; exit: if (res == NULL) z_blob_unlock(self); } z_return(res); }
/** * binary -> base64 conversion * * @param[in] s this * @param[in] from_ source buffer * @param[in] fromlen source buffer length * * @returns Whether conversion succeeded **/ static gboolean z_code_base64_encode_transform(ZCode *s, const void *from_, gsize fromlen) { ZCodeBase64Encode *self = (ZCodeBase64Encode *) s; gsize pos, buf_used_orig; const guchar *from = from_; z_enter(); z_code_grow((ZCode*)self, z_code_calculate_growing(self->super.buf_used, fromlen, self->linelen)); /* This may allocate 4 excess bytes - but requires no further realloc()s. * Since the calculation uses buf_used, these 4 bytes won't accumulate, but * will be used in the future write()s, so the extra 4 is a grand total. */ z_log(NULL, CORE_DUMP, 8, "Encoding base64 data; len='%" G_GSIZE_FORMAT"', phase='%d', used='%" G_GSIZE_FORMAT "', partial='0x%02x'", fromlen, self->phase, self->super.buf_used, self->super.buf[self->super.buf_used]); z_log_data_dump(NULL, CORE_DEBUG, 8, from, fromlen); buf_used_orig = self->super.buf_used; for (pos = 0; pos < fromlen; pos++) { switch (self->phase) { case 0: /* no previous partial content, (00.. ...., 00.. ....) -> (00xx xxxx, 00xx ....) */ self->super.buf[self->super.buf_used] = from[pos] >> 2; z_code_base64_encode_fix(self, FALSE); self->super.buf[self->super.buf_used] = (from[pos] & 0x03) << 4; break; case 1: /* 2 upper bits already set, (00yy ...., 00.. ....) -> (00yy xxxx, 00xx xx..) */ self->super.buf[self->super.buf_used] |= from[pos] >> 4; z_code_base64_encode_fix(self, FALSE); self->super.buf[self->super.buf_used] = (from[pos] & 0x0f) << 2; break; case 2: /* 4 upper bits already set, (00yy yy.., 00.. ....) -> (00yy yyxx, 00xx xxxx) */ self->super.buf[self->super.buf_used] |= from[pos] >> 6; z_code_base64_encode_fix(self, FALSE); self->super.buf[self->super.buf_used] = from[pos] & 0x3f; z_code_base64_encode_fix(self, FALSE); break; } self->phase = (self->phase + 1) % 3; } z_log(NULL, CORE_DUMP, 8, "Encoded base64 data; len='%" G_GSIZE_FORMAT "', phase='%d', used='%" G_GSIZE_FORMAT "', partial='0x%02x'", self->super.buf_used - buf_used_orig, self->phase, self->super.buf_used, self->super.buf[self->super.buf_used]); z_log_data_dump(NULL, CORE_DEBUG, 8, self->super.buf + buf_used_orig, self->super.buf_used - buf_used_orig); z_leave(); return TRUE; }
/** * z_policy_call_object: * @func: Python method to call * @args: Arguments to pass to @func * @session_id: Session ID for logging * * Calls @func with @args, and if an error happened, sends log messages * (containing @session_id) to the log. * * Returns: * The return value of @func */ PyObject * z_policy_call_object(PyObject *func, PyObject *args, gchar *session_id) { PyObject *res; PyErr_Clear(); res = PyObject_CallObject(func, args); Py_XDECREF(args); if (!res) { PyObject *m = PyImport_AddModule("sys"); PyObject *exc, *value, *tb, *what_str; PyErr_Fetch(&exc, &value, &tb); what_str = PyString_FromString("what"); if (PyObject_HasAttr(value, what_str)) { PyObject *what = PyObject_GetAttr(value, what_str); PyObject *detail_str = PyString_FromString("detail"); if (PyObject_HasAttr(value, detail_str)) { PyObject *detail = PyObject_GetAttr(value, detail_str); z_log(session_id, CORE_ERROR, 3, "%s; reason='%s'", PyString_AsString(what), PyString_AsString(detail)); Py_XDECREF(detail); } else { z_log(session_id, CORE_ERROR, 3, "%s;", PyString_AsString(what)); } Py_XDECREF(what); Py_XDECREF(detail_str); Py_XDECREF(exc); Py_XDECREF(value); Py_XDECREF(tb); } else { PyErr_Restore(exc, value, tb); PyErr_Print(); } Py_XDECREF(what_str); PyObject_SetAttrString(m, "last_traceback", Py_None); } return res; }
/** * General function to allocate and initialize a ZSockAddr structure, * and convert a libc style sockaddr * pointer to our representation. * * @param[in] sa libc sockaddr * pointer to convert * @param[in] salen size of sa * * @returns new ZSockAddr instance **/ ZSockAddr * z_sockaddr_new(struct sockaddr *sa, gsize salen) { z_enter(); switch (sa->sa_family) { #ifndef G_OS_WIN32 case AF_INET6: if (salen >= sizeof(struct sockaddr_in6)) z_return(z_sockaddr_inet6_new2((struct sockaddr_in6 *) sa)); break; #endif case AF_INET: if (salen == sizeof(struct sockaddr_in)) z_return(z_sockaddr_inet_new2((struct sockaddr_in *) sa)); break; #ifndef G_OS_WIN32 case AF_UNIX: /* NOTE: the sockaddr_un structure might be less than struct sockaddr_un */ z_return(z_sockaddr_unix_new2((struct sockaddr_un *) sa, salen)); #endif default: /*LOG This message indicates an internal error, the program tried to use an unsupported address family. Please report this error to the Zorp QA team. */ z_log(NULL, CORE_ERROR, 3, "Unsupported socket family in z_sockaddr_new(); family='%d'", sa->sa_family); z_return(NULL); } z_return(NULL); }
static void call_data_received(TelnetProtocol *self) { if (!telnet_protocol_is_running(self)) return; if (z_pktbuf_length(self->data_buffer) == 0) return; z_pktbuf_seek(self->data_buffer, G_SEEK_SET, 0); if (self->data_received) { gboolean res = self->data_received(self->data_buffer, self->data_received_user_data); if (!res) { z_log(self->session_id, TELNET_DEBUG, 5, "Data received callback returned error, aborting;"); change_state(self, PROTO_STATE_QUIT); } } z_pktbuf_resize(self->data_buffer, 0); }
void z_fd_get_peer_tos(gint fd, guint8 *tos) { gint tmp; gchar buf[256]; gboolean tos_found = FALSE; socklen_t buflen, len; z_enter(); *tos = 0; tmp = 1; if (setsockopt(fd, SOL_IP, IP_RECVTOS, &tmp, sizeof(tmp)) < 0) { z_log(NULL, CORE_ERROR, 8, "Error in setsockopt(SOL_IP, IP_RECVTOS); fd='%d', error='%s'", fd, g_strerror(errno)); z_leave(); return; } buflen = sizeof(buf); if (getsockopt(fd, SOL_IP, IP_PKTOPTIONS, &buf, &buflen) >= 0) { struct msghdr msg; struct cmsghdr *cmsg; msg.msg_controllen = buflen; msg.msg_control = buf; for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TOS) { *tos = *(guchar *) CMSG_DATA(cmsg); tos_found = TRUE; break; } } } if (!tos_found) { len = sizeof(*tos); if (getsockopt(fd, SOL_IP, IP_TOS, tos, &len) == -1) { z_log(NULL, CORE_ERROR, 2, "Error in getsockopt(SOL_IP, IP_PKTOPTIONS) || getsockopt(SOL_IP, IP_TOS); fd='%d', error='%s'", fd, g_strerror(errno)); *tos = 0; } } z_leave(); }
/** * z_policy_call_object: * @func: Python method to call * @args: Arguments to pass to @func * @session_id: Session ID for logging * * Calls @func with @args, and if an error happened, sends log messages * (containing @session_id) to the log. * * Returns: * The return value of @func */ PyObject * z_policy_call_object(PyObject *func, PyObject *args, gchar *session_id) { PyObject *res; PyErr_Clear(); res = PyObject_CallObject(func, args); Py_XDECREF(args); if (!res) { PyObject *m = PyImport_AddModule("sys"); if (!PyString_Check(PyErr_Occurred())) { PyErr_Print(); } else { PyObject *exc, *value, *tb, *str; PyErr_Fetch(&exc, &value, &tb); PyErr_NormalizeException(&exc, &value, &tb); str = PyObject_Str(value); if (!str) { /*NOLOG*/ z_log(session_id, CORE_ERROR, 3, "%s;", PyString_AsString(exc)); } else { /*NOLOG*/ z_log(session_id, CORE_ERROR, 3, "%s; reason='%s'", PyString_AsString(exc), PyString_AsString(str)); } Py_XDECREF(exc); Py_XDECREF(value); Py_XDECREF(tb); Py_XDECREF(str); } PyObject_SetAttrString(m, "last_traceback", Py_None); } return res; }
static inline void change_state(TelnetProtocol *self, TelnetProtocolState new_state) { z_log(self->session_id, TELNET_DEBUG, 6, "Protocol changing state; old='%d', new='%d'", self->state, new_state); self->state = new_state; }
/** * Writes a blob out to disk, called only from z_blob_system_threadproc() * * @param[in] self this * * @warning Caller must hold a lock BOTH on the blob AND the blob system! **/ static void z_blob_swap_out(ZBlob *self) { off_t err; gssize written, remain; z_enter(); g_assert(self); if (!self->storage_locked && !self->is_in_file && self->system) { err = lseek(self->fd, 0, SEEK_SET); if (err < 0) { z_log(NULL, CORE_ERROR, 0, "Blob error, lseek() failed; file='%s', error='%s'", self->filename, g_strerror(errno)); g_assert(0); } remain = self->size; while (remain > 0) { written = write(self->fd, self->data, remain); if (written < 0) { if (errno == EINTR) { continue; } else { z_log(NULL, CORE_ERROR, 0, "Blob error, write() failed; file='%s', error='%s'", self->filename, g_strerror(errno)); g_assert(0); } } remain -= written; } self->is_in_file = 1; g_free(self->data); self->data = NULL; self->stat.swap_count++; self->stat.last_accessed = time(NULL); self->system->mem_used -= self->alloc_size; self->system->disk_used += self->alloc_size; } z_return(); }
/** * Allocate and initialize a Zorp thread identified by a name, and * using the given thread function. * * @param[in] name name to identify this thread with * @param[in] func thread function * @param[in] arg pointer to pass to thread function * * @returns TRUE to indicate success **/ gboolean z_thread_new(gchar *name, GThreadFunc func, gpointer arg) { ZThread *self = g_new0(ZThread, 1); GError *error = NULL; static gint thread_id = 1; self->thread_id = thread_id++; self->func = func; self->arg = arg; strncpy(self->name, name, sizeof(self->name) - 1); g_async_queue_lock(queue); if (num_threads >= max_threads) { /*LOG This message reports that the maximal thread limit is reached. Try to increase the maximal thread limit. */ z_log(NULL, CORE_ERROR, 3, "Too many running threads, waiting for one to become free; num_threads='%d', max_threads='%d'", num_threads, max_threads); g_async_queue_push_unlocked(queue, self); g_async_queue_unlock(queue); } else { num_threads++; g_async_queue_ref_unlocked(queue); g_async_queue_unlock(queue); if (!g_thread_create_full(z_thread_func, self, max_stack_size, FALSE, TRUE, G_THREAD_PRIORITY_NORMAL, &error)) { /*LOG This message indicates that creating a new thread failed. It is likely that the system is running low on some resources or some limit is reached. */ z_log(NULL, CORE_ERROR, 2, "Error starting new thread; error='%s'", error->message); g_async_queue_lock(queue); num_threads--; g_async_queue_unlock(queue); return FALSE; } } return TRUE; }
/** * z_dispatch_chain_thread: * @st this * * The thread routine of a dispatcher chain, pops new connections from the * accept_queue and processes them by calling z_dispatch_connection. * When the popped connection is the special value Z_DISPATCH_THREAD_EXIT_MAGIC, * exits the processing loop and finishes the thread. * * Returns: NULL */ static gpointer z_dispatch_chain_thread(gpointer st) { ZDispatchChain *self = (ZDispatchChain *) st; ZConnection *conn; glong acceptq_sum; gint count; /* g_thread_set_priority(g_thread_self(), G_THREAD_PRIORITY_HIGH); */ /*LOG This message reports that a new dispatcher thread is starting. This is used if threaded dispatching is enabled. @see: Dispatcher */ z_log(NULL, CORE_DEBUG, 4, "Dispatch thread starting;"); acceptq_sum = 0; count = 0; while (1) { acceptq_sum += g_async_queue_length(self->accept_queue); if (count % 1000 == 0) { /*LOG This message reports the dispatcher average accept queue length status. */ z_log(NULL, CORE_DEBUG, 4, "Accept queue stats; avg_length='%ld'", acceptq_sum / 1000); acceptq_sum = 0; } conn = g_async_queue_pop(self->accept_queue); if (conn == Z_DISPATCH_THREAD_EXIT_MAGIC) break; z_dispatch_connection(self, conn); count++; } /*LOG This message reports that the dispatcher thread is exiting. It it likely that Zorp unbinds from that address. */ z_log(NULL, CORE_DEBUG, 4, "Dispatch thread exiting;"); z_dispatch_chain_unref(self); return NULL; }
/** * Decrease reference count of blob; destroy it if the count reaches zero. * * @param[in] self this **/ void z_blob_unref(ZBlob *self) { z_enter(); if (self && z_refcount_dec(&self->ref_cnt)) { g_mutex_lock(self->system->mtx_blobsys); self->alloc_req = -self->alloc_size; self->system->blobs = g_list_remove(self->system->blobs, self); z_blob_check_alloc(self); g_mutex_unlock(self->system->mtx_blobsys); if (self->data) g_free(self->data); if (self->fd >= 0) close(self->fd); if (self->filename) { if (unlink(self->filename)) z_log(NULL, CORE_ERROR, 3, "Error removing blob file, unlink() failed; file='%s', error='%s'", self->filename, strerror(errno)); g_free(self->filename); self->filename = NULL; } g_mutex_free(self->mtx_reply); g_cond_free(self->cond_reply); if (g_mutex_trylock(self->mtx_lock)) { g_mutex_unlock(self->mtx_lock); g_mutex_free(self->mtx_lock); } else { z_log(NULL, CORE_ERROR, 3, "Error while destroying blob, someone still has a lock on it;"); /* someone has locked the blob by z_blob_get_file or _get_ptr, and forgot to release it */ } g_free(self); } z_return(); }
void z_fd_get_our_tos(gint fd, guint8 *tos) { socklen_t len; *tos = 0; len = sizeof(*tos); if (getsockopt(fd, SOL_IP, IP_TOS, tos, &len) < 0) { z_log(NULL, CORE_ERROR, 2, "Error in getsockopt(SOL_IP, IP_TOS); fd='%d', error='%s'", fd, g_strerror(errno)); } }
/** * This function is called upon thread startup and performs thread specific * initialization. It calls thread-start and thread-exit callbacks. * * @param[in] self thread specific variables * @param user_data pointer to pass to real thread function (unused) **/ static void z_thread_func_core(ZThread *self, gpointer user_data G_GNUC_UNUSED) { g_private_set(current_thread, self); self->thread = g_thread_self(); z_thread_iterate_callbacks(self, start_callbacks); /*LOG This message indicates that a thread is starting. */ z_log(self->name, CORE_DEBUG, 6, "thread starting;"); (*self->func)(self->arg); /*LOG This message indicates that a thread is ending. */ z_log(self->name, CORE_DEBUG, 6, "thread exiting;"); z_thread_iterate_callbacks(self, stop_callbacks); z_thread_free(self); }
void z_fd_set_our_tos(gint fd, guint8 tos) { socklen_t len; cap_t saved_caps; saved_caps = cap_save(); len = sizeof(tos); cap_enable(CAP_NET_ADMIN); if (setsockopt(fd, SOL_IP, IP_TOS, &tos, len) < 0) { if (errno != ENOTSOCK && errno != EOPNOTSUPP) { z_log(NULL, CORE_ERROR, 3, "Error setting ToS value on socket; fd='%d', tos='%d', error='%s', errno='%d'", fd, tos, g_strerror(errno), errno); } } else { z_log(NULL, CORE_DEBUG, 6, "Setting socket ToS value; fd='%d', tos='%d'", fd, tos); } cap_restore(saved_caps); }
/** * Release the lock on the blob after z_blob_get_file. * * @param[in] self this * * Besides releasing the lock itself, this function also updates the * blob size from the file size. **/ void z_blob_release_file(ZBlob *self) { struct stat st; z_enter(); g_assert(self); if (!fstat(self->fd, &st)) self->size = self->alloc_size = st.st_size; else z_log(NULL, CORE_ERROR, 3, "Cannot stat file on release, blob size may be incorrect from now;"); z_blob_unlock(self); z_return(); }
gboolean z_kzorp_get_lookup_result(gint fd, struct z_kzorp_lookup_result *result) { socklen_t size = sizeof(*result); z_enter(); if (getsockopt(fd, SOL_IP, SO_KZORP_RESULT, result, &size) < 0) { z_log(NULL, CORE_ERROR, 3, "Error querying KZorp lookup result; fd='%d', error='%s'", fd, g_strerror(errno)); z_return(FALSE); } z_return(TRUE); }
/** * This function enables or disables the TCP SO_OOBINLINE feature for socket * specified by fd. * * @param[in] fd file descriptor of a socket * @param[in] enable whether to enable or disable TCP SO_OOBINLINE * * @returns whether the operation was successful **/ gboolean z_fd_set_oobinline(int fd, gboolean enable) { if (setsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char *)(&enable), sizeof(enable)) == -1) { /*LOG This message indicates that changing the OOBINLINE state on the given fd failed for the given reason. Please report this event to the Zorp QA team. */ z_log(NULL, CORE_ERROR, 4, "setsockopt(SOL_SOCKET, SO_OOBINLINE) failed; fd='%d', enable='%d', error='%s'", fd, enable, g_strerror(errno)); return FALSE; } return TRUE; }
/** * Create a new blob. * * @param[in] sys Blob system to create the blob into * @param[in] initial_size Initial size to allocate. * * This function creates a new blob. If sys is NULL, z_blob_system_default will be used. * * @returns The new blob instance **/ ZBlob* z_blob_new(ZBlobSystem *sys, gsize initial_size) { ZBlob *self; z_enter(); if (!sys) sys = z_blob_system_default; if (!sys || !sys->active) z_return(NULL); self = g_new0(ZBlob, 1); self->system = sys; self->filename = g_strdup_printf("%s/blob_XXXXXX", self->system->dir); self->fd = mkstemp(self->filename); if (self->fd < 0) { z_log(NULL, CORE_ERROR, 2, "Error creating blob file: file='%s', error='%s'", self->filename, strerror(errno)); g_free(self->filename); g_free(self); z_return(NULL); } z_refcount_set(&self->ref_cnt, 1); self->size = 0; self->alloc_size = 0; self->data = NULL; self->is_in_file = FALSE; self->mtx_reply = g_mutex_new(); self->cond_reply = g_cond_new(); self->mapped_ptr = NULL; self->mapped_length = 0; self->storage_locked = FALSE; z_blob_statistic_init(&self->stat); self->mtx_lock = g_mutex_new(); g_mutex_lock(self->system->mtx_blobsys); self->system->blobs = g_list_append(self->system->blobs, self); g_mutex_unlock(self->system->mtx_blobsys); if (initial_size > 0) z_blob_alloc(self, initial_size); z_return(self); }
static void call_command_received(TelnetProtocol *self) { if (!telnet_protocol_is_running(self)) return; if (self->command_received) { gboolean res = self->command_received(self->command, self->command_received_user_data); if (!res) { z_log(self->session_id, TELNET_DEBUG, 5, "Command callback returned error, aborting;"); change_state(self, PROTO_STATE_QUIT); } } }
/** * z_policy_stream_new: * @str: ZStream instance * * This function allocates a Python object representing the Zorp stream * @str. It is to be called from C code, the Python version of this * constructor is below. * * Returns: the newly allocated Python object **/ PyObject * z_policy_stream_new(ZStream *str) { ZPolicyStream *self; if (str == NULL) { /*LOG This message indicates an internal error, please contact your Zorp support for assistance. */ z_log(NULL, CORE_ERROR, 3, "Internal error in z_policy_stream_new: input ZStream is NULL;"); return NULL; } self = PyObject_New(ZPolicyStream, &z_policy_stream_type); z_stream_ref(str); self->stream = str; return (PyObject *) self; }
void z_fatal_signal_handler(int signo) { ZSignalContext *p = z_stackdump_get_context(p); struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = SIG_DFL; sigaction(signo, &act, NULL); /*LOG This message is logged when Zorp caught a fatal signal. Possible reason is bad RAM or other hardware. */ z_log(NULL, CORE_ERROR, 0, "Signal received, stackdump follows; signo='%d'", signo); z_mem_trace_stats(); z_stackdump_log(p); kill(getpid(), signo); }
static inline void append_byte(TelnetProtocol *self, ZPktBuf *buf, guint8 byte) { /* stop on buffer overrun */ if (z_pktbuf_length(buf) >= TELNET_BUFFER_SIZE) { /*LOG This message indicates that the Telnet protocol contained a sequence of protocol elements that would have needed an unreasonably large buffer to process. These structures are not commonly found in normal Telnet streams but could be used to mount a denial of service attack on a Telnet client or server by a malicious host. */ z_log(self->session_id, TELNET_VIOLATION, 1, "Buffer overflow during protocol decoding, aborting session; buffer_length='%" G_GSIZE_FORMAT "'", z_pktbuf_length(buf)); change_state(self, PROTO_STATE_QUIT); } else z_pktbuf_put_u8(buf, byte); }
/** * Finalize Base64 decoding. * * @param[in] s ZCodeBase64Decode instance * * Checks if the input was complete (if so, we returned to phase 0). * If it wasn't, the error is logged; and if we're not error_tolerant, * the return value also indicates this error condition. * * @return always TRUE if error_tolerant; otherwise FALSE if the input was incomplete **/ static gboolean z_code_base64_decode_finish(ZCode *s) { ZCodeBase64Decode *self = (ZCodeBase64Decode *) s; z_enter(); if (self->phase != 0) { z_log(NULL, CORE_ERROR, 3, "Unfinished base64 encoding; phase='%d'", self->phase); self->phase = 0; if (!self->error_tolerant) { z_leave(); return FALSE; } } z_leave(); return TRUE; }