📄 connection.c
字号:
if (h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; c -> bytes_needed = bytes; if (c -> bytes_needed <= c -> in_bytes) { return ISC_R_SUCCESS; } return ISC_R_NOTYET;}/* Return the socket on which the dispatcher should wait for readiness to read, for a connection object. If we already have more bytes than we need to do the next thing, and we have at least a single full input buffer, then don't indicate that we're ready to read. */int omapi_connection_readfd (omapi_object_t *h){ omapi_connection_object_t *c; if (h -> type != omapi_type_connection) return -1; c = (omapi_connection_object_t *)h; if (c -> state != omapi_connection_connected) return -1; if (c -> in_bytes >= OMAPI_BUF_SIZE - 1 && c -> in_bytes > c -> bytes_needed) return -1; return c -> socket;}/* Return the socket on which the dispatcher should wait for readiness to write, for a connection object. If there are no bytes buffered for writing, then don't indicate that we're ready to write. */int omapi_connection_writefd (omapi_object_t *h){ omapi_connection_object_t *c; if (h -> type != omapi_type_connection) return -1; c = (omapi_connection_object_t *)h; if (c -> state == omapi_connection_connecting) return c -> socket; if (c -> out_bytes) return c -> socket; else return -1;}isc_result_t omapi_connection_connect (omapi_object_t *h){ isc_result_t status; status = omapi_connection_connect_internal (h); if (status != ISC_R_SUCCESS) omapi_signal (h, "status", status); return ISC_R_SUCCESS;}static isc_result_t omapi_connection_connect_internal (omapi_object_t *h){ int error; omapi_connection_object_t *c; SOCKLEN_T sl; isc_result_t status; if (h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; if (c -> state == omapi_connection_connecting) { sl = sizeof error; if (getsockopt (c -> socket, SOL_SOCKET, SO_ERROR, (char *)&error, &sl) < 0) { omapi_disconnect (h, 1); return ISC_R_SUCCESS; } if (!error) c -> state = omapi_connection_connected; } if (c -> state == omapi_connection_connecting || c -> state == omapi_connection_unconnected) { if (c -> cptr >= c -> connect_list -> count) { switch (error) { case ECONNREFUSED: status = ISC_R_CONNREFUSED; break; case ENETUNREACH: status = ISC_R_NETUNREACH; break; default: status = uerr2isc (error); break; } omapi_disconnect (h, 1); return status; } if (c -> connect_list -> addresses [c -> cptr].addrtype != AF_INET) { omapi_disconnect (h, 1); return ISC_R_INVALIDARG; } memcpy (&c -> remote_addr.sin_addr, &c -> connect_list -> addresses [c -> cptr].address, sizeof c -> remote_addr.sin_addr); c -> remote_addr.sin_family = AF_INET; c -> remote_addr.sin_port = htons (c -> connect_list -> addresses [c -> cptr].port);#if defined (HAVE_SA_LEN) c -> remote_addr.sin_len = sizeof c -> remote_addr;#endif memset (&c -> remote_addr.sin_zero, 0, sizeof c -> remote_addr.sin_zero); ++c -> cptr; error = connect (c -> socket, (struct sockaddr *)&c -> remote_addr, sizeof c -> remote_addr); if (error < 0) { error = errno; if (error != EINPROGRESS) { omapi_disconnect (h, 1); switch (error) { case ECONNREFUSED: status = ISC_R_CONNREFUSED; break; case ENETUNREACH: status = ISC_R_NETUNREACH; break; default: status = uerr2isc (error); break; } return status; } c -> state = omapi_connection_connecting; return ISC_R_INCOMPLETE; } c -> state = omapi_connection_connected; } /* I don't know why this would fail, so I'm tempted not to test the return value. */ sl = sizeof (c -> local_addr); if (getsockname (c -> socket, (struct sockaddr *)&c -> local_addr, &sl) < 0) { } /* Disconnect from I/O object, if any. */ if (h -> outer) omapi_unregister_io_object (h); status = omapi_register_io_object (h, omapi_connection_readfd, omapi_connection_writefd, omapi_connection_reader, omapi_connection_writer, omapi_connection_reaper); if (status != ISC_R_SUCCESS) { omapi_disconnect (h, 1); return status; } omapi_signal_in (h, "connect"); omapi_addr_list_dereference (&c -> connect_list, MDL); return ISC_R_SUCCESS;}/* Reaper function for connection - if the connection is completely closed, reap it. If it's in the disconnecting state, there were bytes left to write when the user closed it, so if there are now no bytes left to write, we can close it. */isc_result_t omapi_connection_reaper (omapi_object_t *h){ omapi_connection_object_t *c; if (h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; if (c -> state == omapi_connection_disconnecting && c -> out_bytes == 0) {#ifdef DEBUG_PROTOCOL log_debug ("omapi_connection_reaper(): disconnect");#endif omapi_disconnect (h, 1); } if (c -> state == omapi_connection_closed) {#ifdef DEBUG_PROTOCOL log_debug ("omapi_connection_reaper(): closed");#endif return ISC_R_NOTCONNECTED; } return ISC_R_SUCCESS;}static isc_result_t make_dst_key (DST_KEY **dst_key, omapi_object_t *a) { omapi_value_t *name = (omapi_value_t *)0; omapi_value_t *algorithm = (omapi_value_t *)0; omapi_value_t *key = (omapi_value_t *)0; int algorithm_id; char *name_str; isc_result_t status = ISC_R_SUCCESS; if (status == ISC_R_SUCCESS) status = omapi_get_value_str (a, (omapi_object_t *)0, "name", &name); if (status == ISC_R_SUCCESS) status = omapi_get_value_str (a, (omapi_object_t *)0, "algorithm", &algorithm); if (status == ISC_R_SUCCESS) status = omapi_get_value_str (a, (omapi_object_t *)0, "key", &key); if (status == ISC_R_SUCCESS) { if ((algorithm -> value -> type == omapi_datatype_data || algorithm -> value -> type == omapi_datatype_string) && strncasecmp ((char *)algorithm -> value -> u.buffer.value, NS_TSIG_ALG_HMAC_MD5 ".", algorithm -> value -> u.buffer.len) == 0) { algorithm_id = KEY_HMAC_MD5; } else { status = ISC_R_INVALIDARG; } } if (status == ISC_R_SUCCESS) { name_str = dmalloc (name -> value -> u.buffer.len + 1, MDL); if (!name_str) status = ISC_R_NOMEMORY; } if (status == ISC_R_SUCCESS) { memcpy (name_str, name -> value -> u.buffer.value, name -> value -> u.buffer.len); name_str [name -> value -> u.buffer.len] = 0; *dst_key = dst_buffer_to_key (name_str, algorithm_id, 0, 0, key -> value -> u.buffer.value, key -> value -> u.buffer.len); if (!*dst_key) status = ISC_R_NOMEMORY; } if (name_str) dfree (name_str, MDL); if (key) omapi_value_dereference (&key, MDL); if (algorithm) omapi_value_dereference (&algorithm, MDL); if (name) omapi_value_dereference (&name, MDL); return status;}isc_result_t omapi_connection_sign_data (int mode, DST_KEY *key, void **context, const unsigned char *data, const unsigned len, omapi_typed_data_t **result){ omapi_typed_data_t *td = (omapi_typed_data_t *)0; isc_result_t status; int r; if (mode & SIG_MODE_FINAL) { status = omapi_typed_data_new (MDL, &td, omapi_datatype_data, dst_sig_size (key)); if (status != ISC_R_SUCCESS) return status; } r = dst_sign_data (mode, key, context, data, len, td ? td -> u.buffer.value : (u_char *)0, td ? td -> u.buffer.len : 0); /* dst_sign_data() really should do this for us, shouldn't it? */ if (mode & SIG_MODE_FINAL) *context = (void *)0; if (r < 0) { if (td) omapi_typed_data_dereference (&td, MDL); return ISC_R_INVALIDKEY; } if (result && td) { omapi_typed_data_reference (result, td, MDL); } if (td) omapi_typed_data_dereference (&td, MDL); return ISC_R_SUCCESS;}isc_result_t omapi_connection_output_auth_length (omapi_object_t *h, unsigned *l){ omapi_connection_object_t *c; if (h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; if (!c -> out_key) return ISC_R_NOTFOUND; *l = dst_sig_size (c -> out_key); return ISC_R_SUCCESS;}isc_result_t omapi_connection_set_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value){ omapi_connection_object_t *c; isc_result_t status; if (h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; if (omapi_ds_strcmp (name, "input-authenticator") == 0) { if (value && value -> type != omapi_datatype_object) return ISC_R_INVALIDARG; if (c -> in_context) { omapi_connection_sign_data (SIG_MODE_FINAL, c -> in_key, &c -> in_context, 0, 0, (omapi_typed_data_t **) 0); } if (c -> in_key) { dst_free_key (c -> in_key); c -> in_key = (DST_KEY *)0; } if (value) { status = make_dst_key (&c -> in_key, value -> u.object); if (status != ISC_R_SUCCESS) return status; } return ISC_R_SUCCESS; } else if (omapi_ds_strcmp (name, "output-authenticator") == 0) { if (value && value -> type != omapi_datatype_object) return ISC_R_INVALIDARG; if (c -> out_context) { omapi_connection_sign_data (SIG_MODE_FINAL, c -> out_key, &c -> out_context, 0, 0, (omapi_typed_data_t **) 0); } if (c -> out_key) { dst_free_key (c -> out_key); c -> out_key = (DST_KEY *)0; } if (value) { status = make_dst_key (&c -> out_key, value -> u.object); if (status != ISC_R_SUCCESS) return status; } return ISC_R_SUCCESS; } if (h -> inner && h -> inner -> type -> set_value) return (*(h -> inner -> type -> set_value)) (h -> inner, id, name, value); return ISC_R_NOTFOUND;}isc_result_t omapi_connection_get_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_value_t **value){ omapi_connection_object_t *c; omapi_typed_data_t *td = (omapi_typed_data_t *)0; isc_result_t status; if (h -> type != omapi_type_connection) return ISC_R_INVALIDARG; c = (omapi_connection_object_t *)h; if (omapi_ds_strcmp (name, "input-signature") == 0) { if (!c -> in_key || !c -> in_context) return ISC_R_NOTFOUND; status = omapi_connection_sign_data (SIG_MODE_FINAL, c -> in_key, &c -> in_context, 0, 0, &td); if (status != ISC_R_SUCCESS) return status; status = omapi_make_value (value, name, td, MDL); omapi_typed_data_dereference (&td, MDL); return status; } else if (omapi_ds_strcmp (name, "input-signature-size") == 0) { if (!c -> in_key) return ISC_R_NOTFOUND; return omapi_make_int_value (value, name, dst_sig_size (c -> in_key), MDL); } else if (omapi_ds_strcmp (name, "output-signature") == 0) { if (!c -> out_key || !c -> out_context) return ISC_R_NOTFOUND; status = omapi_connection_sign_data (SIG_MODE_FINAL, c -> out_key, &c -> out_context, 0, 0, &td); if (status != ISC_R_SUCCESS) return status; status = omapi_make_value (value, name, td, MDL); omapi_typed_data_dereference (&td, MDL); return status; } else if (omapi_ds_strcmp (name, "output-signature-size") == 0) { if (!c -> out_key) return ISC_R_NOTFOUND; return omapi_make_int_value (value, name, dst_sig_size (c -> out_key), MDL); } if (h -> inner && h -> inner -> type -> get_value) return (*(h -> inner -> type -> get_value)) (h -> inner, id, name, value); return ISC_R_NOTFOUND;}isc_result_t omapi_connection_destroy (omapi_object_t *h, const char *file, int line){ omapi_connection_object_t *c;#ifdef DEBUG_PROTOCOL log_debug ("omapi_connection_destroy()");#endif if (h -> type != omapi_type_connection) return ISC_R_UNEXPECTED; c = (omapi_connection_object_t *)(h); if (c -> state == omapi_connection_connected) omapi_disconnect (h, 1); if (c -> listener) omapi_listener_dereference (&c -> listener, file, line); if (c -> connect_list) omapi_addr_list_dereference (&c -> connect_list, file, line); return ISC_R_SUCCESS;}isc_result_t omapi_connection_signal_handler (omapi_object_t *h, const char *name, va_list ap){ if (h -> type != omapi_type_connection) return ISC_R_INVALIDARG;#ifdef DEBUG_PROTOCOL log_debug ("omapi_connection_signal_handler(%s)", name);#endif if (h -> inner && h -> inner -> type -> signal_handler) return (*(h -> inner -> type -> signal_handler)) (h -> inner, name, ap); return ISC_R_NOTFOUND;}/* Write all the published values associated with the object through the specified connection. */isc_result_t omapi_connection_stuff_values (omapi_object_t *c, omapi_object_t *id, omapi_object_t *m){ int i; if (m -> type != omapi_type_connection) return ISC_R_INVALIDARG; if (m -> inner && m -> inner -> type -> stuff_values) return (*(m -> inner -> type -> stuff_values)) (c, id, m -> inner); return ISC_R_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -