/* * Mapper function is used to avoid multiple connections for each session * write or read requests. After processing the request, it does not close * the connection, but waits for the next request. */ static int on_mp_write_session_mapper(struct query_state *qstate) { ssize_t result; int elem_type; TRACE_IN(on_mp_write_session_mapper); if (qstate->kevent_watermark == 0) { qstate->kevent_watermark = sizeof(int); } else { result = qstate->read_func(qstate, &elem_type, sizeof(int)); if (result != sizeof(int)) { LOG_ERR_3("on_mp_write_session_mapper", "read failed"); TRACE_OUT(on_mp_write_session_mapper); return (-1); } switch (elem_type) { case CET_MP_WRITE_SESSION_WRITE_REQUEST: qstate->kevent_watermark = sizeof(size_t); qstate->process_func = on_mp_write_session_write_request_read1; break; case CET_MP_WRITE_SESSION_ABANDON_NOTIFICATION: qstate->kevent_watermark = 0; qstate->process_func = on_mp_write_session_abandon_notification; break; case CET_MP_WRITE_SESSION_CLOSE_NOTIFICATION: qstate->kevent_watermark = 0; qstate->process_func = on_mp_write_session_close_notification; break; default: qstate->kevent_watermark = 0; qstate->process_func = NULL; LOG_ERR_2("on_mp_write_session_mapper", "unknown element type"); TRACE_OUT(on_mp_write_session_mapper); return (-1); } } TRACE_OUT(on_mp_write_session_mapper); return (0); }
static int on_transform_request_process(struct query_state *qstate) { struct cache_transform_request *transform_request; struct cache_transform_response *transform_response; struct configuration_entry *config_entry; size_t i, size; TRACE_IN(on_transform_request_process); init_comm_element(&qstate->response, CET_TRANSFORM_RESPONSE); transform_response = get_cache_transform_response(&qstate->response); transform_request = get_cache_transform_request(&qstate->request); switch (transform_request->transformation_type) { case TT_USER: if (transform_request->entry == NULL) { size = configuration_get_entries_size(s_configuration); for (i = 0; i < size; ++i) { config_entry = configuration_get_entry( s_configuration, i); if (config_entry->perform_actual_lookups == 0) clear_config_entry_part(config_entry, qstate->eid_str, qstate->eid_str_length); } } else { qstate->config_entry = configuration_find_entry( s_configuration, transform_request->entry); if (qstate->config_entry == NULL) { LOG_ERR_2("transform_request", "can't find configuration" " entry '%s'. aborting request", transform_request->entry); transform_response->error_code = -1; goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) { LOG_ERR_2("transform_request", "can't transform the cache entry %s" ", because it ised for actual lookups", transform_request->entry); transform_response->error_code = -1; goto fin; } clear_config_entry_part(qstate->config_entry, qstate->eid_str, qstate->eid_str_length); } break; case TT_ALL: if (qstate->euid != 0) transform_response->error_code = -1; else { if (transform_request->entry == NULL) { size = configuration_get_entries_size( s_configuration); for (i = 0; i < size; ++i) { clear_config_entry( configuration_get_entry( s_configuration, i)); } } else { qstate->config_entry = configuration_find_entry( s_configuration, transform_request->entry); if (qstate->config_entry == NULL) { LOG_ERR_2("transform_request", "can't find configuration" " entry '%s'. aborting request", transform_request->entry); transform_response->error_code = -1; goto fin; } clear_config_entry(qstate->config_entry); } } break; default: transform_response->error_code = -1; } fin: qstate->kevent_watermark = 0; qstate->process_func = on_transform_response_write1; TRACE_OUT(on_transform_request_process); return (0); }
static int on_read_request_process(struct query_state *qstate) { struct cache_read_request *read_request; struct cache_read_response *read_response; cache_entry c_entry, neg_c_entry; struct agent *lookup_agent; struct common_agent *c_agent; int res; TRACE_IN(on_read_request_process); init_comm_element(&qstate->response, CET_READ_RESPONSE); read_response = get_cache_read_response(&qstate->response); read_request = get_cache_read_request(&qstate->request); qstate->config_entry = configuration_find_entry( s_configuration, read_request->entry); if (qstate->config_entry == NULL) { read_response->error_code = ENOENT; LOG_ERR_2("read_request", "can't find configuration " "entry '%s'. aborting request", read_request->entry); goto fin; } if (qstate->config_entry->enabled == 0) { read_response->error_code = EACCES; LOG_ERR_2("read_request", "configuration entry '%s' is disabled", read_request->entry); goto fin; } /* * if we perform lookups by ourselves, then we don't need to separate * cache entries by euid and egid */ if (qstate->config_entry->perform_actual_lookups != 0) memset(read_request->cache_key, 0, qstate->eid_str_length); else { #ifdef NS_NSCD_EID_CHECKING if (check_query_eids(qstate) != 0) { /* if the lookup is not self-performing, we check for clients euid/egid */ read_response->error_code = EPERM; goto fin; } #endif } configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, qstate->config_entry->positive_cache_params.entry_name); neg_c_entry = find_cache_entry(s_cache, qstate->config_entry->negative_cache_params.entry_name); configuration_unlock(s_configuration); if ((c_entry != NULL) && (neg_c_entry != NULL)) { configuration_lock_entry(qstate->config_entry, CELT_POSITIVE); qstate->config_entry->positive_cache_entry = c_entry; read_response->error_code = cache_read(c_entry, read_request->cache_key, read_request->cache_key_size, NULL, &read_response->data_size); if (read_response->error_code == -2) { read_response->data = (char *)malloc( read_response->data_size); assert(read_response != NULL); read_response->error_code = cache_read(c_entry, read_request->cache_key, read_request->cache_key_size, read_response->data, &read_response->data_size); } configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE); configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE); qstate->config_entry->negative_cache_entry = neg_c_entry; if (read_response->error_code == -1) { read_response->error_code = cache_read(neg_c_entry, read_request->cache_key, read_request->cache_key_size, NULL, &read_response->data_size); if (read_response->error_code == -2) { read_response->error_code = 0; read_response->data = NULL; read_response->data_size = 0; } } configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE); if ((read_response->error_code == -1) && (qstate->config_entry->perform_actual_lookups != 0)) { free(read_response->data); read_response->data = NULL; read_response->data_size = 0; lookup_agent = find_agent(s_agent_table, read_request->entry, COMMON_AGENT); if ((lookup_agent != NULL) && (lookup_agent->type == COMMON_AGENT)) { c_agent = (struct common_agent *)lookup_agent; res = c_agent->lookup_func( read_request->cache_key + qstate->eid_str_length, read_request->cache_key_size - qstate->eid_str_length, &read_response->data, &read_response->data_size); if (res == NS_SUCCESS) { read_response->error_code = 0; configuration_lock_entry( qstate->config_entry, CELT_POSITIVE); cache_write(c_entry, read_request->cache_key, read_request->cache_key_size, read_response->data, read_response->data_size); configuration_unlock_entry( qstate->config_entry, CELT_POSITIVE); } else if ((res == NS_NOTFOUND) || (res == NS_RETURN)) { configuration_lock_entry( qstate->config_entry, CELT_NEGATIVE); cache_write(neg_c_entry, read_request->cache_key, read_request->cache_key_size, negative_data, sizeof(negative_data)); configuration_unlock_entry( qstate->config_entry, CELT_NEGATIVE); read_response->error_code = 0; read_response->data = NULL; read_response->data_size = 0; } } } if ((qstate->config_entry->common_query_timeout.tv_sec != 0) || (qstate->config_entry->common_query_timeout.tv_usec != 0)) memcpy(&qstate->timeout, &qstate->config_entry->common_query_timeout, sizeof(struct timeval)); } else read_response->error_code = -1; fin: qstate->kevent_filter = EVFILT_WRITE; if (read_response->error_code == 0) qstate->kevent_watermark = sizeof(int) + sizeof(size_t); else qstate->kevent_watermark = sizeof(int); qstate->process_func = on_read_response_write1; TRACE_OUT(on_read_request_process); return (0); }
static int on_negative_write_request_process(struct query_state *qstate) { struct cache_write_request *write_request; struct cache_write_response *write_response; cache_entry c_entry; TRACE_IN(on_negative_write_request_process); init_comm_element(&qstate->response, CET_WRITE_RESPONSE); write_response = get_cache_write_response(&qstate->response); write_request = get_cache_write_request(&qstate->request); qstate->config_entry = configuration_find_entry( s_configuration, write_request->entry); if (qstate->config_entry == NULL) { write_response->error_code = ENOENT; LOG_ERR_2("negative_write_request", "can't find configuration" " entry '%s'. aborting request", write_request->entry); goto fin; } if (qstate->config_entry->enabled == 0) { write_response->error_code = EACCES; LOG_ERR_2("negative_write_request", "configuration entry '%s' is disabled", write_request->entry); goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) { write_response->error_code = EOPNOTSUPP; LOG_ERR_2("negative_write_request", "entry '%s' performs lookups by itself: " "can't write to it", write_request->entry); goto fin; } else { #ifdef NS_NSCD_EID_CHECKING if (check_query_eids(qstate) != 0) { write_response->error_code = EPERM; goto fin; } #endif } configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, qstate->config_entry->negative_cache_params.entry_name); configuration_unlock(s_configuration); if (c_entry != NULL) { configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE); qstate->config_entry->negative_cache_entry = c_entry; write_response->error_code = cache_write(c_entry, write_request->cache_key, write_request->cache_key_size, negative_data, sizeof(negative_data)); configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE); if ((qstate->config_entry->common_query_timeout.tv_sec != 0) || (qstate->config_entry->common_query_timeout.tv_usec != 0)) memcpy(&qstate->timeout, &qstate->config_entry->common_query_timeout, sizeof(struct timeval)); } else write_response->error_code = -1; fin: qstate->kevent_filter = EVFILT_WRITE; qstate->kevent_watermark = sizeof(int); qstate->process_func = on_write_response_write1; TRACE_OUT(on_negative_write_request_process); return (0); }
static int on_mp_write_session_request_process(struct query_state *qstate) { struct cache_mp_write_session_request *c_mp_ws_request; struct cache_mp_write_session_response *c_mp_ws_response; cache_mp_write_session ws; cache_entry c_entry; char *dec_cache_entry_name; TRACE_IN(on_mp_write_session_request_process); init_comm_element(&qstate->response, CET_MP_WRITE_SESSION_RESPONSE); c_mp_ws_response = get_cache_mp_write_session_response( &qstate->response); c_mp_ws_request = get_cache_mp_write_session_request(&qstate->request); qstate->config_entry = configuration_find_entry( s_configuration, c_mp_ws_request->entry); if (qstate->config_entry == NULL) { c_mp_ws_response->error_code = ENOENT; LOG_ERR_2("write_session_request", "can't find configuration entry '%s'. " "aborting request", c_mp_ws_request->entry); goto fin; } if (qstate->config_entry->enabled == 0) { c_mp_ws_response->error_code = EACCES; LOG_ERR_2("write_session_request", "configuration entry '%s' is disabled", c_mp_ws_request->entry); goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) { c_mp_ws_response->error_code = EOPNOTSUPP; LOG_ERR_2("write_session_request", "entry '%s' performs lookups by itself: " "can't write to it", c_mp_ws_request->entry); goto fin; } else { #ifdef NS_NSCD_EID_CHECKING if (check_query_eids(qstate) != 0) { c_mp_ws_response->error_code = EPERM; goto fin; } #endif } /* * All multipart entries are separated by their name decorations. * For one configuration entry there will be a lot of multipart * cache entries - each with its own decorated name. */ asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str, qstate->config_entry->mp_cache_params.cep.entry_name); assert(dec_cache_entry_name != NULL); configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, dec_cache_entry_name); configuration_unlock(s_configuration); if (c_entry == INVALID_CACHE_ENTRY) c_entry = register_new_mp_cache_entry(qstate, dec_cache_entry_name); free(dec_cache_entry_name); assert(c_entry != NULL); configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); ws = open_cache_mp_write_session(c_entry); if (ws == INVALID_CACHE_MP_WRITE_SESSION) c_mp_ws_response->error_code = -1; else { qstate->mdata = ws; qstate->destroy_func = on_mp_write_session_destroy; if ((qstate->config_entry->mp_query_timeout.tv_sec != 0) || (qstate->config_entry->mp_query_timeout.tv_usec != 0)) memcpy(&qstate->timeout, &qstate->config_entry->mp_query_timeout, sizeof(struct timeval)); } configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); fin: qstate->process_func = on_mp_write_session_response_write1; qstate->kevent_watermark = sizeof(int); qstate->kevent_filter = EVFILT_WRITE; TRACE_OUT(on_mp_write_session_request_process); return (0); }
/* * The main configuration routine. Its implementation is hugely inspired by the * the same routine implementation in Solaris NSCD. */ int parse_config_file(struct configuration *config, const char *fname, char const **error_str, int *error_line) { FILE *fin; char buffer[255]; char *fields[128]; int field_count, line_num, value; int res; TRACE_IN(parse_config_file); assert(config != NULL); assert(fname != NULL); fin = fopen(fname, "r"); if (fin == NULL) { TRACE_OUT(parse_config_file); return (-1); } res = 0; line_num = 0; memset(buffer, 0, sizeof(buffer)); while ((res == 0) && (fgets(buffer, sizeof(buffer) - 1, fin) != NULL)) { field_count = strbreak(buffer, fields, sizeof(fields)); ++line_num; if (field_count == 0) continue; switch (fields[0][0]) { case '#': case '\0': continue; case 'e': if ((field_count == 3) && (strcmp(fields[0], "enable-cache") == 0) && (check_cachename(fields[1]) == 0) && ((value = get_yesno(fields[2])) != -1)) { enable_cache(config, fields[1], value); continue; } break; case 'd': if ((field_count == 2) && (strcmp(fields[0], "debug-level") == 0) && ((value = get_number(fields[1], 0, 10)) != -1)) { continue; } break; case 'p': if ((field_count == 3) && (strcmp(fields[0], "positive-time-to-live") == 0) && (check_cachename(fields[1]) == 0) && ((value = get_number(fields[2], 0, -1)) != -1)) { set_positive_time_to_live(config, fields[1], value); continue; } else if ((field_count == 3) && (strcmp(fields[0], "positive-confidence-threshold") == 0) && ((value = get_number(fields[2], 1, -1)) != -1)) { set_positive_confidence_threshold(config, fields[1], value); continue; } else if ((field_count == 3) && (strcmp(fields[0], "positive-policy") == 0) && (check_cachename(fields[1]) == 0) && ((value = get_policy(fields[2])) != -1)) { set_positive_policy(config, fields[1], value); continue; } else if ((field_count == 3) && (strcmp(fields[0], "perform-actual-lookups") == 0) && (check_cachename(fields[1]) == 0) && ((value = get_yesno(fields[2])) != -1)) { set_perform_actual_lookups(config, fields[1], value); continue; } break; case 'n': if ((field_count == 3) && (strcmp(fields[0], "negative-time-to-live") == 0) && (check_cachename(fields[1]) == 0) && ((value = get_number(fields[2], 0, -1)) != -1)) { set_negative_time_to_live(config, fields[1], value); continue; } else if ((field_count == 3) && (strcmp(fields[0], "negative-confidence-threshold") == 0) && ((value = get_number(fields[2], 1, -1)) != -1)) { set_negative_confidence_threshold(config, fields[1], value); continue; } else if ((field_count == 3) && (strcmp(fields[0], "negative-policy") == 0) && (check_cachename(fields[1]) == 0) && ((value = get_policy(fields[2])) != -1)) { set_negative_policy(config, fields[1], value); continue; } break; case 's': if ((field_count == 3) && (strcmp(fields[0], "suggested-size") == 0) && (check_cachename(fields[1]) == 0) && ((value = get_number(fields[2], 1, -1)) != -1)) { set_suggested_size(config, fields[1], value); continue; } break; case 't': if ((field_count == 2) && (strcmp(fields[0], "threads") == 0) && ((value = get_number(fields[1], 1, -1)) != -1)) { set_threads_num(config, value); continue; } break; case 'k': if ((field_count == 3) && (strcmp(fields[0], "keep-hot-count") == 0) && (check_cachename(fields[1]) == 0) && ((value = get_number(fields[2], 0, -1)) != -1)) { set_keep_hot_count(config, fields[1], value); continue; } break; case 'c': if ((field_count == 3) && (strcmp(fields[0], "check-files") == 0) && (check_cachename(fields[1]) == 0) && ((value = get_yesno(fields[2])) != -1)) { check_files(config, fields[1], value); continue; } break; default: break; } LOG_ERR_2("config file parser", "error in file " "%s on line %d", fname, line_num); *error_str = "syntax error"; *error_line = line_num; res = -1; } fclose(fin); TRACE_OUT(parse_config_file); return (res); }
static struct configuration_entry * create_configuration_entry(const char *name, struct timeval const *common_timeout, struct timeval const *mp_timeout, struct common_cache_entry_params const *positive_params, struct common_cache_entry_params const *negative_params, struct mp_cache_entry_params const *mp_params) { struct configuration_entry *retval; size_t size; int res; TRACE_IN(create_configuration_entry); assert(name != NULL); assert(positive_params != NULL); assert(negative_params != NULL); assert(mp_params != NULL); retval = calloc(1, sizeof(*retval)); assert(retval != NULL); res = pthread_mutex_init(&retval->positive_cache_lock, NULL); if (res != 0) { free(retval); LOG_ERR_2("create_configuration_entry", "can't create positive cache lock"); TRACE_OUT(create_configuration_entry); return (NULL); } res = pthread_mutex_init(&retval->negative_cache_lock, NULL); if (res != 0) { pthread_mutex_destroy(&retval->positive_cache_lock); free(retval); LOG_ERR_2("create_configuration_entry", "can't create negative cache lock"); TRACE_OUT(create_configuration_entry); return (NULL); } res = pthread_mutex_init(&retval->mp_cache_lock, NULL); if (res != 0) { pthread_mutex_destroy(&retval->positive_cache_lock); pthread_mutex_destroy(&retval->negative_cache_lock); free(retval); LOG_ERR_2("create_configuration_entry", "can't create negative cache lock"); TRACE_OUT(create_configuration_entry); return (NULL); } memcpy(&retval->positive_cache_params, positive_params, sizeof(struct common_cache_entry_params)); memcpy(&retval->negative_cache_params, negative_params, sizeof(struct common_cache_entry_params)); memcpy(&retval->mp_cache_params, mp_params, sizeof(struct mp_cache_entry_params)); size = strlen(name); retval->name = calloc(1, size + 1); assert(retval->name != NULL); memcpy(retval->name, name, size); memcpy(&retval->common_query_timeout, common_timeout, sizeof(struct timeval)); memcpy(&retval->mp_query_timeout, mp_timeout, sizeof(struct timeval)); asprintf(&retval->positive_cache_params.cep.entry_name, "%s+", name); assert(retval->positive_cache_params.cep.entry_name != NULL); asprintf(&retval->negative_cache_params.cep.entry_name, "%s-", name); assert(retval->negative_cache_params.cep.entry_name != NULL); asprintf(&retval->mp_cache_params.cep.entry_name, "%s*", name); assert(retval->mp_cache_params.cep.entry_name != NULL); TRACE_OUT(create_configuration_entry); return (retval); }
static int on_mp_read_session_request_process(struct query_state *qstate) { struct cache_mp_read_session_request *c_mp_rs_request; struct cache_mp_read_session_response *c_mp_rs_response; cache_mp_read_session rs; cache_entry c_entry; char *dec_cache_entry_name; char *buffer; size_t buffer_size; cache_mp_write_session ws; struct agent *lookup_agent; struct multipart_agent *mp_agent; void *mdata; int res; TRACE_IN(on_mp_read_session_request_process); init_comm_element(&qstate->response, CET_MP_READ_SESSION_RESPONSE); c_mp_rs_response = get_cache_mp_read_session_response( &qstate->response); c_mp_rs_request = get_cache_mp_read_session_request(&qstate->request); qstate->config_entry = configuration_find_entry( s_configuration, c_mp_rs_request->entry); if (qstate->config_entry == NULL) { c_mp_rs_response->error_code = ENOENT; LOG_ERR_2("read_session_request", "can't find configuration entry '%s'." " aborting request", c_mp_rs_request->entry); goto fin; } if (qstate->config_entry->enabled == 0) { c_mp_rs_response->error_code = EACCES; LOG_ERR_2("read_session_request", "configuration entry '%s' is disabled", c_mp_rs_request->entry); goto fin; } if (qstate->config_entry->perform_actual_lookups != 0) dec_cache_entry_name = strdup( qstate->config_entry->mp_cache_params.cep.entry_name); else { #ifdef NS_NSCD_EID_CHECKING if (check_query_eids(qstate) != 0) { c_mp_rs_response->error_code = EPERM; goto fin; } #endif asprintf(&dec_cache_entry_name, "%s%s", qstate->eid_str, qstate->config_entry->mp_cache_params.cep.entry_name); } assert(dec_cache_entry_name != NULL); configuration_lock_rdlock(s_configuration); c_entry = find_cache_entry(s_cache, dec_cache_entry_name); configuration_unlock(s_configuration); if ((c_entry == INVALID_CACHE) && (qstate->config_entry->perform_actual_lookups != 0)) c_entry = register_new_mp_cache_entry(qstate, dec_cache_entry_name); free(dec_cache_entry_name); if (c_entry != INVALID_CACHE_ENTRY) { configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); rs = open_cache_mp_read_session(c_entry); configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); if ((rs == INVALID_CACHE_MP_READ_SESSION) && (qstate->config_entry->perform_actual_lookups != 0)) { lookup_agent = find_agent(s_agent_table, c_mp_rs_request->entry, MULTIPART_AGENT); if ((lookup_agent != NULL) && (lookup_agent->type == MULTIPART_AGENT)) { mp_agent = (struct multipart_agent *) lookup_agent; mdata = mp_agent->mp_init_func(); /* * Multipart agents read the whole snapshot * of the data at one time. */ configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); ws = open_cache_mp_write_session(c_entry); configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); if (ws != NULL) { do { buffer = NULL; res = mp_agent->mp_lookup_func(&buffer, &buffer_size, mdata); if ((res & NS_TERMINATE) && (buffer != NULL)) { configuration_lock_entry( qstate->config_entry, CELT_MULTIPART); if (cache_mp_write(ws, buffer, buffer_size) != 0) { abandon_cache_mp_write_session(ws); ws = NULL; } configuration_unlock_entry( qstate->config_entry, CELT_MULTIPART); free(buffer); buffer = NULL; } else { configuration_lock_entry( qstate->config_entry, CELT_MULTIPART); close_cache_mp_write_session(ws); configuration_unlock_entry( qstate->config_entry, CELT_MULTIPART); free(buffer); buffer = NULL; } } while ((res & NS_TERMINATE) && (ws != NULL)); } configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); rs = open_cache_mp_read_session(c_entry); configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); } } if (rs == INVALID_CACHE_MP_READ_SESSION) c_mp_rs_response->error_code = -1; else { qstate->mdata = rs; qstate->destroy_func = on_mp_read_session_destroy; configuration_lock_entry(qstate->config_entry, CELT_MULTIPART); if ((qstate->config_entry->mp_query_timeout.tv_sec != 0) || (qstate->config_entry->mp_query_timeout.tv_usec != 0)) memcpy(&qstate->timeout, &qstate->config_entry->mp_query_timeout, sizeof(struct timeval)); configuration_unlock_entry(qstate->config_entry, CELT_MULTIPART); } } else c_mp_rs_response->error_code = -1; fin: qstate->process_func = on_mp_read_session_response_write1; qstate->kevent_watermark = sizeof(int); qstate->kevent_filter = EVFILT_WRITE; TRACE_OUT(on_mp_read_session_request_process); return (0); }