int main(int argc, char *argv[]) { int i; test_init(argc, argv); fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (fd<0){ pr_perror("socket"); goto out; } // setup local address & bind using // this address bzero(&la, sizeof(la)); la.nl_family = AF_NETLINK; la.nl_pid = getpid(); if (bind(fd, (struct sockaddr*) &la, sizeof(la))){ pr_perror("bind failed"); goto out; } //Preperation: form_request_del(); send_request(); recv_reply(); test_daemon(); while (test_go()){ for (i=0; i < CMD_NUM; i++){ cmd[i](); if (send_request() < 0){ fail("send_request failed"); goto out; }; if (recv_reply() < 0){ fail("RTNETLINK answers: %m"); goto out; }; #ifdef DEBUG if (read_reply() < 0){ fail("read_reply failed"); goto out; } #endif } } pass(); out: return 0; }
/* * Send index to the relayd. */ int relayd_send_index(struct lttcomm_relayd_sock *rsock, struct ctf_packet_index *index, uint64_t relay_stream_id, uint64_t net_seq_num) { int ret; struct lttcomm_relayd_index msg; struct lttcomm_relayd_generic_reply reply; /* Code flow error. Safety net. */ assert(rsock); if (rsock->minor < 4) { DBG("Not sending indexes before protocol 2.4"); ret = 0; goto error; } DBG("Relayd sending index for stream ID %" PRIu64, relay_stream_id); memset(&msg, 0, sizeof(msg)); msg.relay_stream_id = htobe64(relay_stream_id); msg.net_seq_num = htobe64(net_seq_num); /* The index is already in big endian. */ msg.packet_size = index->packet_size; msg.content_size = index->content_size; msg.timestamp_begin = index->timestamp_begin; msg.timestamp_end = index->timestamp_end; msg.events_discarded = index->events_discarded; msg.stream_id = index->stream_id; /* Send command */ ret = send_command(rsock, RELAYD_SEND_INDEX, &msg, sizeof(msg), 0); if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(rsock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } reply.ret_code = be32toh(reply.ret_code); /* Return session id or negative ret code. */ if (reply.ret_code != LTTNG_OK) { ret = -1; ERR("Relayd send index replied error %d", reply.ret_code); } else { /* Success */ ret = 0; } error: return ret; }
/* * Send a RELAYD_CREATE_SESSION command to the relayd with the given socket and * set session_id of the relayd if we have a successful reply from the relayd. * * On success, return 0 else a negative value which is either an errno error or * a lttng error code from the relayd. */ int relayd_create_session(struct lttcomm_relayd_sock *rsock, uint64_t *session_id, char *session_name, char *hostname, int session_live_timer, unsigned int snapshot) { int ret; struct lttcomm_relayd_status_session reply; assert(rsock); assert(session_id); DBG("Relayd create session"); switch(rsock->minor) { case 1: case 2: case 3: ret = relayd_create_session_2_1(rsock, session_id); break; case 4: default: ret = relayd_create_session_2_4(rsock, session_id, session_name, hostname, session_live_timer, snapshot); break; } if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(rsock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } reply.session_id = be64toh(reply.session_id); reply.ret_code = be32toh(reply.ret_code); /* Return session id or negative ret code. */ if (reply.ret_code != LTTNG_OK) { ret = -1; ERR("Relayd create session replied error %d", reply.ret_code); goto error; } else { ret = 0; *session_id = reply.session_id; } DBG("Relayd session created with id %" PRIu64, reply.session_id); error: return ret; }
int search_mrr_device(SEARCH_RESULT_T **ppresult_out) { unsigned char reply_buf[MAX_BUFFER_LEN] = {0}; struct sockaddr_in addr_dest; bzero(&addr_dest, sizeof(struct sockaddr_in)); addr_dest.sin_family=AF_INET; addr_dest.sin_addr.s_addr=htonl(INADDR_BROADCAST); addr_dest.sin_port=htons(DEST_PORT); int sock = create_udp_socket(); //从广播地址发送搜索指令 int recv_len = 0; unsigned char cmd[] = {"0123456789012345678901234567890123456789"}; int ret = send_boardcast_cmd(sock, (struct sockaddr*)&addr_dest, cmd, strlen((char*)cmd)); if(ret<0) { printf("send search cmd error....\n"); return -1; } else { printf("send search cmd ok!\n"); } while(1) { recv_len = recv_reply(sock, (struct sockaddr*)&addr_dest, reply_buf); if(recv_len <= 0) { printf("recv error....\n"); break; } else if(recv_len % SEARCH_REPLY_LEN == 0) { ret = parse_search_result(reply_buf, recv_len, ppresult_out); if(ret >= 0) break; } sleep(1); } close_udp_socket(sock); return 0; }
/* * Add stream on the relayd and assign stream handle to the stream_id argument. * * On success return 0 else return ret_code negative value. */ int relayd_add_stream(struct lttcomm_sock *sock, const char *channel_name, const char *pathname, uint64_t *stream_id) { int ret; struct lttcomm_relayd_add_stream msg; struct lttcomm_relayd_status_stream reply; /* Code flow error. Safety net. */ assert(sock); assert(channel_name); assert(pathname); DBG("Relayd adding stream for channel name %s", channel_name); strncpy(msg.channel_name, channel_name, sizeof(msg.channel_name)); strncpy(msg.pathname, pathname, sizeof(msg.pathname)); /* Send command */ ret = send_command(sock, RELAYD_ADD_STREAM, (void *) &msg, sizeof(msg), 0); if (ret < 0) { goto error; } /* Waiting for reply */ ret = recv_reply(sock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } /* Back to host bytes order. */ reply.handle = be64toh(reply.handle); reply.ret_code = be32toh(reply.ret_code); /* Return session id or negative ret code. */ if (reply.ret_code != LTTNG_OK) { ret = -1; ERR("Relayd add stream replied error %d", reply.ret_code); } else { /* Success */ ret = 0; *stream_id = reply.handle; } DBG("Relayd stream added successfully with handle %" PRIu64, reply.handle); error: return ret; }
/* * Inform the relay that all the streams for the current channel has been sent. * * On success return 0 else return ret_code negative value. */ int relayd_streams_sent(struct lttcomm_relayd_sock *rsock) { int ret; struct lttcomm_relayd_generic_reply reply; /* Code flow error. Safety net. */ assert(rsock); DBG("Relayd sending streams sent."); /* This feature was introduced in 2.4, ignore it for earlier versions. */ if (rsock->minor < 4) { ret = 0; goto end; } /* Send command */ ret = send_command(rsock, RELAYD_STREAMS_SENT, NULL, 0, 0); if (ret < 0) { goto error; } /* Waiting for reply */ ret = recv_reply(rsock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } /* Back to host bytes order. */ reply.ret_code = be32toh(reply.ret_code); /* Return session id or negative ret code. */ if (reply.ret_code != LTTNG_OK) { ret = -1; ERR("Relayd streams sent replied error %d", reply.ret_code); goto error; } else { /* Success */ ret = 0; } DBG("Relayd streams sent success"); error: end: return ret; }
/* * Check for data availability for a given stream id. * * Return 0 if NOT pending, 1 if so and a negative value on error. */ int relayd_data_pending(struct lttcomm_relayd_sock *rsock, uint64_t stream_id, uint64_t last_net_seq_num) { int ret; struct lttcomm_relayd_data_pending msg; struct lttcomm_relayd_generic_reply reply; /* Code flow error. Safety net. */ assert(rsock); DBG("Relayd data pending for stream id %" PRIu64, stream_id); memset(&msg, 0, sizeof(msg)); msg.stream_id = htobe64(stream_id); msg.last_net_seq_num = htobe64(last_net_seq_num); /* Send command */ ret = send_command(rsock, RELAYD_DATA_PENDING, (void *) &msg, sizeof(msg), 0); if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(rsock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } reply.ret_code = be32toh(reply.ret_code); /* Return session id or negative ret code. */ if (reply.ret_code >= LTTNG_OK) { ERR("Relayd data pending replied error %d", reply.ret_code); } /* At this point, the ret code is either 1 or 0 */ ret = reply.ret_code; DBG("Relayd data is %s pending for stream id %" PRIu64, ret == 1 ? "" : "NOT", stream_id); error: return ret; }
/* * Send close stream command to the relayd. */ int relayd_send_close_stream(struct lttcomm_relayd_sock *rsock, uint64_t stream_id, uint64_t last_net_seq_num) { int ret; struct lttcomm_relayd_close_stream msg; struct lttcomm_relayd_generic_reply reply; /* Code flow error. Safety net. */ assert(rsock); DBG("Relayd closing stream id %" PRIu64, stream_id); memset(&msg, 0, sizeof(msg)); msg.stream_id = htobe64(stream_id); msg.last_net_seq_num = htobe64(last_net_seq_num); /* Send command */ ret = send_command(rsock, RELAYD_CLOSE_STREAM, (void *) &msg, sizeof(msg), 0); if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(rsock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } reply.ret_code = be32toh(reply.ret_code); /* Return session id or negative ret code. */ if (reply.ret_code != LTTNG_OK) { ret = -1; ERR("Relayd close stream replied error %d", reply.ret_code); } else { /* Success */ ret = 0; } DBG("Relayd close stream id %" PRIu64 " successfully", stream_id); error: return ret; }
/* * End a data pending command for a specific session id. * * Return 0 on success and set is_data_inflight to 0 if no data is being * streamed or 1 if it is the case. */ int relayd_end_data_pending(struct lttcomm_relayd_sock *rsock, uint64_t id, unsigned int *is_data_inflight) { int ret, recv_ret; struct lttcomm_relayd_end_data_pending msg; struct lttcomm_relayd_generic_reply reply; /* Code flow error. Safety net. */ assert(rsock); DBG("Relayd end data pending"); memset(&msg, 0, sizeof(msg)); msg.session_id = htobe64(id); /* Send command */ ret = send_command(rsock, RELAYD_END_DATA_PENDING, &msg, sizeof(msg), 0); if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(rsock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } recv_ret = be32toh(reply.ret_code); if (recv_ret < 0) { ret = recv_ret; goto error; } *is_data_inflight = recv_ret; DBG("Relayd end data pending is data inflight: %d", recv_ret); return 0; error: return ret; }
/* * Check on the relayd side for a quiescent state on the control socket. */ int relayd_quiescent_control(struct lttcomm_relayd_sock *rsock, uint64_t metadata_stream_id) { int ret; struct lttcomm_relayd_quiescent_control msg; struct lttcomm_relayd_generic_reply reply; /* Code flow error. Safety net. */ assert(rsock); DBG("Relayd checking quiescent control state"); memset(&msg, 0, sizeof(msg)); msg.stream_id = htobe64(metadata_stream_id); /* Send command */ ret = send_command(rsock, RELAYD_QUIESCENT_CONTROL, &msg, sizeof(msg), 0); if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(rsock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } reply.ret_code = be32toh(reply.ret_code); /* Return session id or negative ret code. */ if (reply.ret_code != LTTNG_OK) { ret = -1; ERR("Relayd quiescent control replied error %d", reply.ret_code); goto error; } /* Control socket is quiescent */ return 0; error: return ret; }
/* * Begin a data pending command for a specific session id. */ int relayd_begin_data_pending(struct lttcomm_relayd_sock *rsock, uint64_t id) { int ret; struct lttcomm_relayd_begin_data_pending msg; struct lttcomm_relayd_generic_reply reply; /* Code flow error. Safety net. */ assert(rsock); DBG("Relayd begin data pending"); memset(&msg, 0, sizeof(msg)); msg.session_id = htobe64(id); /* Send command */ ret = send_command(rsock, RELAYD_BEGIN_DATA_PENDING, &msg, sizeof(msg), 0); if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(rsock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } reply.ret_code = be32toh(reply.ret_code); /* Return session id or negative ret code. */ if (reply.ret_code != LTTNG_OK) { ret = -1; ERR("Relayd begin data pending replied error %d", reply.ret_code); goto error; } return 0; error: return ret; }
/* * Send a RELAYD_CREATE_SESSION command to the relayd with the given socket and * set session_id of the relayd if we have a successful reply from the relayd. * * On success, return 0 else a negative value which is either an errno error or * a lttng error code from the relayd. */ int relayd_create_session(struct lttcomm_sock *sock, uint64_t *session_id) { int ret; struct lttcomm_relayd_status_session reply; assert(sock); assert(session_id); DBG("Relayd create session"); /* Send command */ ret = send_command(sock, RELAYD_CREATE_SESSION, NULL, 0, 0); if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(sock, (void *) &reply, sizeof(reply)); if (ret < 0) { goto error; } reply.session_id = be64toh(reply.session_id); reply.ret_code = be32toh(reply.ret_code); /* Return session id or negative ret code. */ if (reply.ret_code != LTTNG_OK) { ret = -1; ERR("Relayd create session replied error %d", reply.ret_code); goto error; } else { ret = 0; *session_id = reply.session_id; } DBG("Relayd session created with id %" PRIu64, reply.session_id); error: return ret; }
/* * main function */ int main(int argc, char *argv[]) { int sock = -1, ret; unsigned groups; /* set option */ ret = set_options(argc, argv); if(ret < 0) close_exit(sock, 0, ret); /* open log file */ ret = open_log(log_file); if(ret < 0) close_exit(sock, 0, ret); /* open debug file */ if(log_opts & L_DEBUG) { ret = open_dbg(dbg_file); if(ret < 0) close_exit(sock, 0, ret); } /* create lock file */ ret = open_lock(); if(ret < 0) close_exit(sock, 0, ret); /* set signal handlers */ ret = set_signal_handlers(); if(ret < 0) close_exit(sock, 0, ret); /* initizlize daemon */ ret = init_daemon(); if(ret < 0) close_exit(sock, 0, ret); rec_log("info: nield %s started(PID: %ld)", VERSION, (long)getpid()); /* write pid to lock file */ ret = write_lock(); if(ret < 0) close_exit(sock, 0, ret); /* open netlink socket to create list */ groups = 0; sock = open_netlink_socket(groups, NETLINK_ROUTE); if(sock < 0) close_exit(sock, 1, ret); /* request interface list */ ret = send_request(sock, RTM_GETLINK, AF_UNSPEC); if(ret < 0) close_exit(sock, 1, ret); /* receive interface list */ ret = recv_reply(sock, RTM_GETLINK); if(ret != 0) close_exit(sock, 1, ret); /* request bridge interface list */ ret = send_request(sock, RTM_GETLINK, AF_BRIDGE); if(ret < 0) close_exit(sock, 1, ret); /* receive bridge interface list */ ret = recv_reply(sock, RTM_GETLINK); if(ret != 0) close_exit(sock, 1, ret); /* request neighbor cache list */ ret = send_request(sock, RTM_GETNEIGH, AF_UNSPEC); if(ret < 0) close_exit(sock, 1, ret); /* receive & create interface list */ ret = recv_reply(sock, RTM_GETNEIGH); if(ret != 0) close_exit(sock, 1, ret); /* close socket */ close(sock); /* set rtnetlink multicast groups */ groups = set_rtnetlink_groups(); sock = open_netlink_socket(groups, NETLINK_ROUTE); if(sock < 0) close_exit(sock, 1, ret); /* recevie events */ ret = recv_events(sock); close_exit(sock, 1, ret); return(0); }
/* * Check version numbers on the relayd. * If major versions are compatible, we assign minor_to_use to the * minor version of the procotol we are going to use for this session. * * Return 0 if compatible else negative value. */ int relayd_version_check(struct lttcomm_relayd_sock *rsock) { int ret; struct lttcomm_relayd_version msg; /* Code flow error. Safety net. */ assert(rsock); DBG("Relayd version check for major.minor %u.%u", rsock->major, rsock->minor); memset(&msg, 0, sizeof(msg)); /* Prepare network byte order before transmission. */ msg.major = htobe32(rsock->major); msg.minor = htobe32(rsock->minor); /* Send command */ ret = send_command(rsock, RELAYD_VERSION, (void *) &msg, sizeof(msg), 0); if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(rsock, (void *) &msg, sizeof(msg)); if (ret < 0) { goto error; } /* Set back to host bytes order */ msg.major = be32toh(msg.major); msg.minor = be32toh(msg.minor); /* * Only validate the major version. If the other side is higher, * communication is not possible. Only major version equal can talk to each * other. If the minor version differs, the lowest version is used by both * sides. */ if (msg.major != rsock->major) { /* Not compatible */ ret = -1; DBG2("Relayd version is NOT compatible. Relayd version %u != %u (us)", msg.major, rsock->major); goto error; } /* * If the relayd's minor version is higher, it will adapt to our version so * we can continue to use the latest relayd communication data structure. * If the received minor version is higher, the relayd should adapt to us. */ if (rsock->minor > msg.minor) { rsock->minor = msg.minor; } /* Version number compatible */ DBG2("Relayd version is compatible, using protocol version %u.%u", rsock->major, rsock->minor); ret = 0; error: return ret; }
/* * Check version numbers on the relayd. * * Return 0 if compatible else negative value. */ int relayd_version_check(struct lttcomm_sock *sock, uint32_t major, uint32_t minor) { int ret; struct lttcomm_relayd_version msg; /* Code flow error. Safety net. */ assert(sock); DBG("Relayd version check for major.minor %u.%u", major, minor); /* Prepare network byte order before transmission. */ msg.major = htobe32(major); msg.minor = htobe32(minor); /* Send command */ ret = send_command(sock, RELAYD_VERSION, (void *) &msg, sizeof(msg), 0); if (ret < 0) { goto error; } /* Receive response */ ret = recv_reply(sock, (void *) &msg, sizeof(msg)); if (ret < 0) { goto error; } /* Set back to host bytes order */ msg.major = be32toh(msg.major); msg.minor = be32toh(msg.minor); /* * Only validate the major version. If the other side is higher, * communication is not possible. Only major version equal can talk to each * other. If the minor version differs, the lowest version is used by both * sides. * * For now, before 2.1.0 stable release, we don't have to check the minor * because this new mechanism with the relayd will only be available with * 2.1 and NOT 2.0.x. */ if (msg.major == major) { /* Compatible */ ret = 0; DBG2("Relayd version is compatible"); goto error; } /* * After 2.1.0 release, for the 2.2 release, at this point will have to * check the minor version in order for the session daemon to know which * structure to use to communicate with the relayd. If the relayd's minor * version is higher, it will adapt to our version so we can continue to * use the latest relayd communication data structure. */ /* Version number not compatible */ DBG2("Relayd version is NOT compatible. Relayd version %u != %u (us)", msg.major, major); ret = -1; error: return ret; }