void rcp_dict_send_as_command( rcp_type_ref type, rcp_data_ref data, rcp_connection_ref con) { { struct cmd_set_value cmd; rcp_type_ref cmd_type=rcp_command_type(CMD_SET_VALUE); rcp_init(cmd_type, (rcp_data_ref)&cmd); cmd.command = rcp_string_new_rec(CMD_STR_SET_VALUE); cmd.loginID = 0; cmd.value = rcp_record_new(type); rcp_connection_send_data(con, cmd_type, (rcp_data_ref)&cmd); rcp_deinit(cmd_type, (rcp_data_ref)&cmd); } rcp_dict_ref dict = (rcp_dict_ref)data; rcp_dict_node_ref node = rcp_dict_begin(dict); rcp_type_ref key_type = rcp_dict_type_key_type(type); rcp_type_ref data_type = rcp_dict_type_data_type(type); while (node){ struct cmd_set_value cmd; rcp_type_ref cmd_type=rcp_command_type(CMD_SET_VALUE); rcp_init(cmd_type, (rcp_data_ref)&cmd); cmd.command = rcp_string_new_rec(CMD_STR_SET_VALUE); cmd.loginID = 0; if (key_type == rcp_ref_type){ rcp_copy(rcp_dict_type_key_type(type), rcp_dict_node_key(type, node), (rcp_data_ref)&cmd.path); } else{ cmd.path = rcp_record_new_with(key_type, rcp_dict_node_key(type, node)); } if (data_type == rcp_ref_type){ rcp_copy(rcp_dict_type_data_type(type), rcp_dict_node_data(type, node), (rcp_data_ref)&cmd.value); } else{ cmd.value = rcp_record_new_with(data_type, rcp_dict_node_data(type, node)); } rcp_connection_send_data(con, cmd_type, (rcp_data_ref)&cmd); rcp_deinit(cmd_type, (rcp_data_ref)&cmd); node = rcp_dict_node_next(node); } }
void rcp_array_send_as_command( rcp_type_ref type, rcp_data_ref data, rcp_connection_ref con) { if (rcp_array_type_data_type(type) != rcp_ref_type){ rcp_error("Unsupported array type."); return; } { struct cmd_set_value cmd_ini; rcp_type_ref cmd_type=rcp_command_type(CMD_SET_VALUE); rcp_init(cmd_type, (rcp_data_ref)&cmd_ini); cmd_ini.command = rcp_string_new_rec(CMD_STR_SET_VALUE); cmd_ini.loginID = 0; cmd_ini.value = rcp_record_new(type); rcp_connection_send_data(con, cmd_type, (rcp_data_ref)&cmd_ini); rcp_deinit(cmd_type, (rcp_data_ref)&cmd_ini); } rcp_record_ref tmp_record = rcp_record_new(type); rcp_array_ref tmp_array = (rcp_array_ref)rcp_record_data(tmp_record); rcp_record_ref *tmp_val; { rcp_record_ref null_rec = NULL; rcp_array_append_data(type, tmp_array, (rcp_data_ref)&null_rec); tmp_val = rcp_array_raw_data(tmp_array); } rcp_array_ref array = (rcp_array_ref)data; rcp_array_iterater_ref node = rcp_array_begin(array); struct cmd_replace_value cmd; rcp_type_ref cmd_type=rcp_command_type(CMD_REPLACE_VALUE); rcp_init(cmd_type, (rcp_data_ref)&cmd); cmd.command = rcp_string_new_rec(CMD_STR_REPLACE_VALUE); cmd.begin = -1; cmd.end = -1; cmd.loginID = 0; cmd.value = tmp_record; while (node){ *tmp_val = *(rcp_record_ref*)rcp_array_iterater_data(node); rcp_connection_send_data(con, cmd_type, (rcp_data_ref)&cmd); node = rcp_array_iterater_next(type, array, node); } *tmp_val = NULL; rcp_deinit(cmd_type, (rcp_data_ref)&cmd); }
void rcp_std_send_as_command( rcp_type_ref type, rcp_data_ref data, rcp_connection_ref con) { struct cmd_set_value cmd_ini; rcp_type_ref cmd_type=rcp_command_type(CMD_SET_VALUE); rcp_init(cmd_type, (rcp_data_ref)&cmd_ini); cmd_ini.command = rcp_string_new_rec(CMD_STR_SET_VALUE); cmd_ini.loginID = 0; cmd_ini.value = rcp_record_new_with(type, data); rcp_connection_send_data(con, cmd_type, (rcp_data_ref)&cmd_ini); rcp_deinit(cmd_type, (rcp_data_ref)&cmd_ini); }
void rcp_array_copied(rcp_type_ref type, rcp_data_ref data) { rcp_type_ref data_type = rcp_array_type_data_type(type); rcp_array_ref core = (rcp_array_ref)data; if (!rcp_array_owning_data(core)) return; const void *old_data = core->array; const size_t old_data_count = core->data_count; rcp_init(type, data); rcp_array_resize(type, core, old_data_count); core->data_count = old_data_count; memcpy(core->array, old_data, old_data_count*data_type->size); int i; for (i = 0; i<old_data_count; i++) { rcp_copied(data_type, core->array+i*data_type->size); } }
void rcp_array_copy( rcp_type_ref type, rcp_data_ref src, rcp_data_ref dst) { rcp_type_ref data_type = rcp_array_type_data_type(type); rcp_array_ref src_core = (rcp_array_ref)src; rcp_array_ref dst_core = (rcp_array_ref)dst; rcp_init(type, dst);//not required dst_core->array = malloc(type->size*src_core->data_count); dst_core->data_count = src_core->data_count; dst_core->capacity = src_core->capacity; int i; for (i = 0; i<src_core->data_count; i++) { size_t offset = i*data_type->size; rcp_data_ref src_data = src_core->array+offset; rcp_data_ref dst_data = dst_core->array+offset; rcp_copy(data_type, src_data, dst_data); } }
int main(int argc, char **argv) { // parse arguments int i; for (i = 0; i < MAX_INTREMOVED; i++) intremoved[i] = NULL; for (i = 1; i < argc; i++) { if (strcmp(argv[i], "-h") == 0) { help(); return 0; } else if (strcmp(argv[i], "-r") == 0) { if (argc == (i + 1)) { help(); return 1; } if (intremoved_cnt >= MAX_INTREMOVED) { help(); return 1; } intremoved[intremoved_cnt++] = argv[++i]; } else { fprintf(stderr, "Error: process %s, unrecognized argument\n", rcpGetProcName()); help(); return 1; } } // initialize rcp rcp_init(RCP_PROC_ROUTER); // set interface configuration in shared memory router_detect_interfaces(); RcpPkt *pkt; pkt = malloc(sizeof(RcpPkt) + RCP_PKT_DATA_LEN); if (pkt == NULL) { fprintf(stderr, "Error: process %s, cannot allocate memory, exiting...\n", rcpGetProcName()); return 1; } // delete all static routes - default routes are not deleted int v = system("/opt/rcp/bin/rtclean static >> /opt/rcp/var/log/restart"); if (v == -1) { fprintf(stderr, "Error: process %s, cannot delete existing static routes, exiting...\n", rcpGetProcName()); return 1; } // receive loop int reconnect_timer = 0; struct timeval ts; ts.tv_sec = 1; // 1 second ts.tv_usec = 0; // use this timer to speed up rx loop when the system is busy uint32_t rcptic = rcpTic(); // forever while (1) { // reconnect mux socket if connection failed if (reconnect_timer >= 5) { ASSERT(muxsock == 0); muxsock = rcpConnectMux(RCP_PROC_ROUTER, NULL, NULL, NULL); if (muxsock == 0) reconnect_timer = 1; // start reconnect timer else { reconnect_timer = 0; pstats->mux_reconnect++; } } fd_set fds; FD_ZERO(&fds); if (muxsock != 0) FD_SET(muxsock, &fds); int maxfd = muxsock; // wait for data errno = 0; int nready = select(maxfd + 1, &fds, (fd_set *) 0, (fd_set *) 0, &ts); if (nready < 0) { fprintf(stderr, "Error: process %s, select nready %d, errno %d\n", rcpGetProcName(), nready, errno); } else if (nready == 0) { // watchdog pstats->wproc++; // one second timeout router_if_timeout(); // muxsocket reconnect timeout if (muxsock == 0) reconnect_timer++; // reload ts rcptic++; if (rcpTic() > rcptic) { // speed up the clock ts.tv_sec = 0; ts.tv_usec = 800000; // 0.8 seconds pstats->select_speedup++; } else { ts.tv_sec = 1; // 1 second ts.tv_usec = 0; } } else if (muxsock != 0 && FD_ISSET(muxsock, &fds)) { errno = 0; int nread = recv(muxsock, pkt, sizeof(RcpPkt), 0); if(nread < sizeof(RcpPkt) || errno != 0) { // printf("Error: process %s, muxsocket nread %d, errno %d, disconnecting...\n", // rcpGetProcName(), nread, errno); close(muxsock); muxsock = 0; continue; } // read the packet data if (pkt->data_len != 0) { nread += recv(muxsock, (unsigned char *) pkt + sizeof(RcpPkt), pkt->data_len, 0); } ASSERT(nread == sizeof(RcpPkt) + pkt->data_len); // process cli packet if (pkt->type == RCP_PKT_TYPE_CLI && pkt->destination == RCP_PROC_ROUTER) { processCli(pkt); // forward the response back send(muxsock, pkt, sizeof(RcpPkt) + pkt->data_len, 0); } else ASSERT(0); } } return 0; }
int main(int argc, char **argv) { //rcpDebugEnable(); // initialize rcplib rcp_init(RCP_PROC_ACL); RcpPkt *pkt; pkt = malloc(sizeof(RcpPkt) + RCP_PKT_DATA_LEN); if (pkt == NULL) { fprintf(stderr, "Error: process %s, cannot allocate memory, exiting...\n", rcpGetProcName()); exit(1); } // clear firewall table netfilter_generate(); // receive loop int reconnect_timer = 0; struct timeval ts; ts.tv_sec = 1; // 1 second ts.tv_usec = 0; // use this timer to speed up rx loop when the system is busy uint32_t rcptic = rcpTic(); while (1) { // reconnect mux socket if connection failed if (reconnect_timer >= 5) { ASSERT(muxsock == 0); muxsock = rcpConnectMux(RCP_PROC_ACL, NULL, NULL, NULL); if (muxsock == 0) reconnect_timer = 1; // start reconnect timer else { reconnect_timer = 0; pstats->mux_reconnect++; } } // set descriptors fd_set fds; FD_ZERO(&fds); int maxfd = 0; if (muxsock != 0) { FD_SET(muxsock, &fds); maxfd = (muxsock > maxfd)? muxsock: maxfd; } // wait for data errno = 0; int nready = select(maxfd + 1, &fds, (fd_set *) 0, (fd_set *) 0, &ts); if (nready < 0) { fprintf(stderr, "Error: process %s, select nready %d, errno %d\n", rcpGetProcName(), nready, errno); } else if (nready == 0) { // watchdog pstats->wproc++; // muxsocket reconnect timeout if (reconnect_timer > 0) reconnect_timer++; // netfilter update if (netfilter_update > 0) { if (--netfilter_update == 0) netfilter_generate(); } // reload ts rcptic++; if (rcpTic() > rcptic) { // speed up the clock ts.tv_sec = 0; ts.tv_usec = 800000; // 0.8 seconds pstats->select_speedup++; } else { ts.tv_sec = 1; // 1 second ts.tv_usec = 0; } } // cli data else if (muxsock != 0 && FD_ISSET(muxsock, &fds)) { errno = 0; int nread = recv(muxsock, pkt, sizeof(RcpPkt), 0); if(nread < sizeof(RcpPkt) || errno != 0) { // fprintf(stderr, "Error: process %s, muxsocket nread %d, errno %d, disconnecting...\n", // rcpGetProcName(), nread, errno); close(muxsock); reconnect_timer = 1; muxsock = 0; continue; } // read the packet data if (pkt->data_len != 0) { nread += recv(muxsock, (unsigned char *) pkt + sizeof(RcpPkt), pkt->data_len, 0); } ASSERT(nread == sizeof(RcpPkt) + pkt->data_len); // process the cli packet if (pkt->type == RCP_PKT_TYPE_CLI && pkt->destination == RCP_PROC_ACL) { processCli(pkt); // forward the packet back to rcp send(muxsock, pkt, sizeof(RcpPkt) + pkt->data_len, 0); } else ASSERT(0); } else ASSERT(0); } return 0; }
int main(int argc, char **argv) { //rcpDebugEnable(); // initialize shared memory rcp_init(RCP_PROC_DNS); RcpPkt *pkt; pkt = malloc(sizeof(RcpPkt) + RCP_PKT_DATA_LEN); if (pkt == NULL) { fprintf(stderr, "Error: process %s, cannot allocate memory, exiting...\n", rcpGetProcName()); exit(1); } struct stat s; if (stat("/opt/rcp/var/log/dnsproxy_at_startup", &s) == 0) proxy_disabled = 1; // open sockets if necessary if (shm->config.dns_server) { if (proxy_disabled) { rcpLog(muxsock, RCP_PROC_DNS, RLOG_WARNING, RLOG_FC_DNS, "an external DNS proxy is already running on the system, RCP DNS proxy will be disabled"); } else { client_sock = rx_open(DNS_SERVER_PORT); // the socket open to clients listens on the server socket if (client_sock == 0) { fprintf(stderr, "Error: process %s, cannot open sockets, exiting...\n", rcpGetProcName()); exit(1); } } } // set the static cache entries cache_update_static(); // drop privileges rcpDropPriv(); // initialize request list rq_list_init(); // receive loop int reconnect_timer = 0; struct timeval ts; ts.tv_sec = 1; // 1 second ts.tv_usec = 0; // use this timer to speed up rx loop when the system is busy uint32_t rcptic = rcpTic(); while (1) { // reconnect mux socket if connection failed if (reconnect_timer >= 10) { // a regular reconnect will fail, this process runs with dropped privileges // end the process and restart it again break; } // set descriptors fd_set fds; FD_ZERO(&fds); int maxfd = 0; if (muxsock != 0) { FD_SET(muxsock, &fds); maxfd = (muxsock > maxfd)? muxsock: maxfd; } if (client_sock != 0) { FD_SET(client_sock, &fds); maxfd = (client_sock > maxfd)? client_sock: maxfd; } // set all server sockets DnsReq *rq = rq_active(); while (rq) { if (rq->sock != 0) { FD_SET(rq->sock, &fds); maxfd = (rq->sock > maxfd)? rq->sock: maxfd; } rq = rq->next; } // wait for data errno = 0; int nready = select(maxfd + 1, &fds, (fd_set *) 0, (fd_set *) 0, &ts); if (nready < 0) { fprintf(stderr, "Error: process %s, select nready %d, errno %d\n", rcpGetProcName(), nready, errno); } else if (nready == 0) { // watchdog pstats->wproc++; // muxsocket reconnect timeout if (reconnect_timer > 0) reconnect_timer++; // age cache entries cache_timer(); // age request queue entries rq_timer(); // reset rate-limit counter rate_limit = 0; // reload ts rcptic++; if (rcpTic() > rcptic) { // speed up the clock ts.tv_sec = 0; ts.tv_usec = 800000; // 0.8 seconds pstats->select_speedup++; } else { ts.tv_sec = 1; // 1 second ts.tv_usec = 0; } } // cli data else if (muxsock != 0 && FD_ISSET(muxsock, &fds)) { errno = 0; int nread = recv(muxsock, pkt, sizeof(RcpPkt), 0); if(nread < sizeof(RcpPkt) || errno != 0) { // fprintf(stderr, "Error: process %s, muxsocket nread %d, errno %d, disconnecting...\n", // rcpGetProcName(), nread, errno); close(muxsock); reconnect_timer = 1; muxsock = 0; continue; } // read the packet data if (pkt->data_len != 0) { nread += recv(muxsock, (unsigned char *) pkt + sizeof(RcpPkt), pkt->data_len, 0); } ASSERT(nread == sizeof(RcpPkt) + pkt->data_len); // process the cli packet if (pkt->type == RCP_PKT_TYPE_CLI && pkt->destination == RCP_PROC_DNS) { processCli(pkt); // forward the packet back to rcp send(muxsock, pkt, sizeof(RcpPkt) + pkt->data_len, 0); } // dns updates packet else if (pkt->type == RCP_PKT_TYPE_UPDATEDNS) { rcpLog(muxsock, RCP_PROC_DNS, RLOG_DEBUG, RLOG_FC_IPC, "processing DNS updates packet"); cache_update_static(); } else ASSERT(0); } // DNS packets from clients else if (client_sock != 0 && FD_ISSET(client_sock, &fds)) { rx_packet(client_sock); } // DNS packets from servers else { DnsReq *rq = rq_active(); while (rq) { if (rq->sock != 0 && FD_ISSET(rq->sock, &fds)) { rx_packet(rq->sock); break; } rq = rq->next; } } if (force_restart) { rcpLog(muxsock, RCP_PROC_DNS, RLOG_NOTICE, RLOG_FC_IPC, "process %s exiting for configuration purposes", rcpGetProcName()); if (pstats->wmonitor != 0) pstats->wproc = pstats->wmonitor; // tigger a restart in the next monitoring cycle pstats->no_logging = 1; break; // exit from while(1) } if (force_shutdown) break; } fflush(0); sleep(1); // close sockets if (muxsock != 0) { close(muxsock); } if (client_sock != 0) { close(client_sock); } // remove cli memory cliRemoveFunctions(); // clear request memory rq_clear_inactive(); // remove cache memory cache_clear(); // remove packet memory if (pkt) free(pkt); return 0; }