/** * Finish a DLEP signal/message * @param writer dlep writer * @param source logging source for error messages * @return -1 if an error happened, 0 otherwise */ int dlep_writer_finish_signal(struct dlep_writer *writer, enum oonf_log_source source) { size_t length; uint16_t tmp16; char *dst; if (abuf_has_failed(writer->out)) { OONF_WARN(source, "Could not build signal: %u", writer->signal_type); return -1; } length = abuf_getlen(writer->out) - writer->signal_start; if (length > 65535 + 4) { OONF_WARN(source, "Signal %u became too long: %" PRINTF_SIZE_T_SPECIFIER, writer->signal_type, abuf_getlen(writer->out)); return -1; } /* calculate network ordered size */ tmp16 = htons(length - 4); /* put it into the signal */ dst = abuf_getptr(writer->out); memcpy(&dst[writer->signal_start + 2], &tmp16, sizeof(tmp16)); OONF_DEBUG_HEX(source, &dst[writer->signal_start], length, "Finished signal %u:", writer->signal_type); return 0; }
static void test_validate_fractional_minmax_miss(void) { START_TEST(); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "%s", abuf_getptr(&out)); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional_minmax", "10.0001"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, &out), "validation missed int out of range"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional_minmax", "10.0000"); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "validation had false positive (border case)"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional_minmax", "9.9999"); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "validation had false positive inside valid interval"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional_minmax", "-10.0001"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, &out), "validation missed int out of range"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional_minmax", "-10.0000"); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "validation had false positive (border case)"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional_minmax", "-9.9999"); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "validation had false positive inside valid interval"); END_TEST(); }
/** * Callback to send multicast over interface * @param session dlep session * @param af_family address family for multicast */ static void _cb_send_multicast(struct dlep_session *session, int af_family) { struct dlep_if *interf; if (abuf_getlen(session->writer.out) <= sizeof(_DLEP_PREFIX) - 1 || !netaddr_socket_is_unspec(&session->remote_socket)) { return; } /* get pointer to radio interface */ interf = container_of(session, struct dlep_if, session); if (interf->session_tree.count > 0 && interf->single_session) { /* do not produce UDP traffic as long as we are connected */ return; } OONF_DEBUG(session->log_source, "Send multicast %" PRINTF_SIZE_T_SPECIFIER " bytes", abuf_getlen(session->writer.out)); oonf_packet_send_managed_multicast(&interf->udp, abuf_getptr(session->writer.out), abuf_getlen(session->writer.out), af_family); abuf_clear(session->writer.out); /* add dlep prefix to buffer */ abuf_memcpy(session->writer.out, _DLEP_PREFIX, sizeof(_DLEP_PREFIX) - 1); }
static void test_validate_fractional_miss(void) { START_TEST(); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "%s", abuf_getptr(&out)); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional", "a"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, NULL), "validation missed bad integer"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional", "3..4"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, NULL), "validation missed bad integer"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional", "3.4.5"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, NULL), "validation missed bad integer"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "fractional", "0"); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, NULL), "validation had a false positive"); END_TEST(); }
static void test_validate_success(void) { START_TEST(); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "%s", abuf_getptr(&out)); END_TEST(); }
static void test_validate_printable_miss(void) { START_TEST(); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "%s", abuf_getptr(&out)); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "printable", "1234\n5678"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, NULL), "validation missed non-printable character"); END_TEST(); }
static void test_validate_stringarray_miss(void) { START_TEST(); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "%s", abuf_getptr(&out)); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "stringarray", "12345678"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, NULL), "validation missed too long string value"); END_TEST(); }
static void test_validate_choice_miss(void) { START_TEST(); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "%s", abuf_getptr(&out)); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, "choice", "choice42"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, NULL), "validation missed bad choice"); END_TEST(); }
static void test_validate_netaddr_ipv46_prefix_miss(void) { const char *key = "p_ipv46"; START_TEST(); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "%s", abuf_getptr(&out)); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, key, "xxxxxxx"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, &out), "validation missed with bad address"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, key, "10:00:00:00:00:00"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, &out), "validation missed with bad mac48"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, key, "11-22-33-44-55-66-77-88"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, &out), "validation missed with bad eui64"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, key, "10.0.0.1"); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "validation had false positive with ipv4"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, key, "10::1"); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "validation had false positive with ipv6"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, key, "10:00:00:00:00:00/10"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, &out), "validation missed with bad mac48 prefix"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, key, "11-22-33-44-55-66-77-88/11"); CHECK_TRUE(0 != cfg_schema_validate(db, false, false, &out), "validation missed with bad eui64 prefix"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, key, "10.0.0.1/12"); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "validation had false positive with ipv4 prefix"); cfg_db_add_entry(db, CFG_SEC, CFG_SECNAME, key, "10::1/13"); CHECK_TRUE(0 == cfg_schema_validate(db, false, false, &out), "validation had false positive with ipv6 prefix"); END_TEST(); }
/** * Callback to handle data from the olsr socket scheduler * @param fd filedescriptor to read data from * @param data custom data pointer * @param event_read true if read-event is incoming * @param event_write true if write-event is incoming */ static void _cb_packet_event(struct oonf_socket_entry *entry, bool multicast __attribute__((unused))) { struct oonf_packet_socket *pktsocket; union netaddr_socket sock; uint16_t length; char *pkt; ssize_t result; struct netaddr_str netbuf; #ifdef OONF_LOG_DEBUG_INFO const char *interf = ""; #endif pktsocket = container_of(entry, typeof(*pktsocket), scheduler_entry); #ifdef OONF_LOG_DEBUG_INFO if (pktsocket->os_if) { interf = pktsocket->os_if->name; } #endif if (oonf_socket_is_read(entry)) { uint8_t *buf; /* clear recvfrom memory */ memset(&sock, 0, sizeof(sock)); /* handle incoming data */ buf = pktsocket->config.input_buffer; result = os_fd_recvfrom(&entry->fd, buf, pktsocket->config.input_buffer_length-1, &sock, pktsocket->os_if); if (result > 0 && pktsocket->config.receive_data != NULL) { /* handle raw socket */ if (pktsocket->protocol) { buf = os_fd_skip_rawsocket_prefix(buf, &result, pktsocket->local_socket.std.sa_family); if (!buf) { OONF_WARN(LOG_PACKET, "Error while skipping IP header for socket %s:", netaddr_socket_to_string(&netbuf, &pktsocket->local_socket)); return; } } /* null terminate it */ buf[result] = 0; /* received valid packet */ OONF_DEBUG(LOG_PACKET, "Received %"PRINTF_SSIZE_T_SPECIFIER" bytes from %s %s (%s)", result, netaddr_socket_to_string(&netbuf, &sock), interf, multicast ? "multicast" : "unicast"); pktsocket->config.receive_data(pktsocket, &sock, buf, result); } else if (result < 0 && (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)) { OONF_WARN(LOG_PACKET, "Cannot read packet from socket %s: %s (%d)", netaddr_socket_to_string(&netbuf, &pktsocket->local_socket), strerror(errno), errno); } } if (oonf_socket_is_write(entry) && abuf_getlen(&pktsocket->out) > 0) { /* handle outgoing data */ pkt = abuf_getptr(&pktsocket->out); /* copy remote socket */ memcpy(&sock, pkt, sizeof(sock)); pkt += sizeof(sock); /* copy length */ memcpy(&length, pkt, 2); pkt += 2; /* try to send packet */ result = os_fd_sendto(&entry->fd, pkt, length, &sock, pktsocket->config.dont_route); if (result < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) { /* try again later */ OONF_DEBUG(LOG_PACKET, "Sending to %s %s could block, try again later", netaddr_socket_to_string(&netbuf, &sock), interf); return; } if (result < 0) { /* display error message */ OONF_WARN(LOG_PACKET, "Cannot send UDP packet to %s: %s (%d)", netaddr_socket_to_string(&netbuf, &sock), strerror(errno), errno); } else { OONF_DEBUG(LOG_PACKET, "Sent %"PRINTF_SSIZE_T_SPECIFIER" bytes to %s %s", result, netaddr_socket_to_string(&netbuf, &sock), interf); } /* remove data from outgoing buffer (both for success and for final error */ abuf_pull(&pktsocket->out, sizeof(sock) + 2 + length); } if (abuf_getlen(&pktsocket->out) == 0) { /* nothing left to send, disable outgoing events */ oonf_socket_set_write(&pktsocket->scheduler_entry, false); } }
/** * Callback to receive UDP data through oonf_packet_managed API * @param pkt packet socket * @param from network socket the packet was received from * @param ptr pointer to packet data * @param length length of packet data */ static void _cb_receive_udp(struct oonf_packet_socket *pkt, union netaddr_socket *from, void *ptr, size_t length) { struct dlep_if *interf; uint8_t *buffer; ssize_t processed; struct netaddr_str nbuf; interf = pkt->config.user; buffer = ptr; if (interf->session_tree.count > 0 && interf->single_session) { /* ignore UDP traffic as long as we have a connection */ return; } if (length < sizeof(_DLEP_PREFIX) - 1) { /* ignore unknown prefix */ return; } if (memcmp(buffer, _DLEP_PREFIX, sizeof(_DLEP_PREFIX)-1) != 0) { OONF_WARN(interf->session.log_source, "Incoming UDP packet with unknown signature"); return; } /* advance pointer and fix length */ buffer += (sizeof(_DLEP_PREFIX) - 1); length -= (sizeof(_DLEP_PREFIX) - 1); /* copy socket information */ memcpy(&interf->session.remote_socket, from, sizeof(interf->session.remote_socket)); processed = dlep_session_process_buffer(&interf->session, buffer, length); if (processed < 0) { return ; } if ((size_t)processed < length) { OONF_WARN(interf->session.log_source, "Received malformed or too short UDP packet from %s", netaddr_socket_to_string(&nbuf, from)); /* incomplete or bad packet, just ignore it */ return; } if (abuf_getlen(interf->session.writer.out) > sizeof(_DLEP_PREFIX) - 1) { /* send an unicast response */ oonf_packet_send_managed(&interf->udp, from, abuf_getptr(interf->session.writer.out), abuf_getlen(interf->session.writer.out)); abuf_clear(interf->session.writer.out); /* add dlep prefix to buffer */ abuf_memcpy(interf->session.writer.out, _DLEP_PREFIX, sizeof(_DLEP_PREFIX) - 1); } netaddr_socket_invalidate(&interf->session.remote_socket); }
} } static void write_packet(struct rfc5444_writer *w __attribute__ ((unused)), struct rfc5444_writer_target *iface __attribute__((unused)), void *buffer __attribute((unused)), size_t length) { struct autobuf out; CHECK_TRUE(length < MSG_MTU + 1, "RFC5444 packet with %zd bytes!", length); abuf_init(&out); abuf_appendf(&out, "Packet with %zd bytes:\n", length); abuf_hexdump(&out, "", buffer, length); rfc5444_print_direct(&out, buffer, length); printf("%s\n", abuf_getptr(&out)); abuf_free(&out); } static void clear_elements(void) { } static void test(void) { START_TEST(); CHECK_TRUE(0 == rfc5444_writer_create_message_alltarget(&writer, 1, 4), "Parser should return 0"); rfc5444_writer_flush(&writer, &out_if, false); END_TEST(); }