#include #include #include #include "stellar/packet.h" #include "stellar/session_mq.h" #include "packet_inject_main.h" struct packet_inject_plugin_ctx { struct stellar *st; int sess_plug_id; int tcp_topic_id; int udp_topic_id; char name[64]; }; static void *on_sess_new(struct session *sess, void *plugin_ctx) { struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)plugin_ctx; printf("[%s] pluign handle session new: %s\n", ctx->name, session_get0_readable_addr(sess)); return NULL; } static void on_sess_free(struct session *sess, void *sess_ctx, void *plugin_ctx) { struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)plugin_ctx; printf("[%s] pluign handle session free: %s\n", ctx->name, session_get0_readable_addr(sess)); } static void on_sess_msg(struct session *sess, int topic_id, const void *msg, void *sess_ctx, void *plugin_ctx) { struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)plugin_ctx; printf("[%s] pluign handle session msg: %s (C2S received packets: %lu, S2C received packets: %lu)\n", ctx->name, session_get0_readable_addr(sess), session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_RAW_PACKETS_RECEIVED), session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_RAW_PACKETS_RECEIVED)); struct packet *pkt = (struct packet *)msg; char buffer[1024] = {0}; uint16_t src_port = 0; uint16_t dst_port = 0; struct address src_addr = {0}; struct address dst_addr = {0}; packet_get_addr(pkt, &src_addr, &dst_addr); packet_get_port(pkt, &src_port, &dst_port); if (rule.addr.family == AF_INET && memcmp(&src_addr.data.v4, &rule.addr.data.v4, sizeof(struct in_addr)) && memcmp(&dst_addr.data.v4, &rule.addr.data.v4, sizeof(struct in_addr))) { return; } if (rule.addr.family == AF_INET6 && memcmp(&src_addr.data.v6, &rule.addr.data.v6, sizeof(struct in6_addr)) && memcmp(&dst_addr.data.v6, &rule.addr.data.v6, sizeof(struct in6_addr))) { return; } if (rule.port != 0 && src_port != rule.port && dst_port != rule.port) { return; } if (session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_INJECTED_PACKETS_SUCCESS) > 0 || session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_INJECTED_PACKETS_SUCCESS) > 0) { return; } if (rule.direction == AFTER_RECV_C2S_N_PACKET && session_get_stat(sess, FLOW_DIRECTION_C2S, STAT_RAW_PACKETS_RECEIVED) != rule.number) { return; } if (rule.direction == AFTER_RECV_S2C_N_PACKET && session_get_stat(sess, FLOW_DIRECTION_S2C, STAT_RAW_PACKETS_RECEIVED) != rule.number) { return; } switch (rule.inject_type) { case INJECT_TYPE_TCP_RST: stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_C2S); stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_S2C); session_set_discard(sess); break; case INJECT_TYPE_TCP_FIN: stellar_inject_tcp_fin(ctx->st, sess, FLOW_DIRECTION_C2S); stellar_inject_tcp_fin(ctx->st, sess, FLOW_DIRECTION_S2C); session_set_discard(sess); break; case INJECT_TYPE_TCP_PAYLOAD: snprintf(buffer, sizeof(buffer), "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", 5 + 5 + 2, "Hello"); stellar_inject_tcp_payload(ctx->st, sess, FLOW_DIRECTION_S2C, buffer, strlen(buffer)); // inject payload to client stellar_inject_tcp_payload(ctx->st, sess, FLOW_DIRECTION_S2C, "World\r\n", 7); // inject payload to client stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_S2C); // inject RST to client stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_C2S); // inject RST to server session_set_discard(sess); break; case INJECT_TYPE_TCP_PAYLOAD_FIN_RST: snprintf(buffer, sizeof(buffer), "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n%s", 5 + 5 + 2, "Hello"); stellar_inject_tcp_payload(ctx->st, sess, FLOW_DIRECTION_S2C, buffer, strlen(buffer)); // inject payload to client stellar_inject_tcp_payload(ctx->st, sess, FLOW_DIRECTION_S2C, "World\r\n", 7); // inject payload to client stellar_inject_tcp_fin(ctx->st, sess, FLOW_DIRECTION_S2C); // inject FIN to client stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_S2C); // inject RST to client stellar_inject_tcp_fin(ctx->st, sess, FLOW_DIRECTION_C2S); // inject FIN to server stellar_inject_tcp_rst(ctx->st, sess, FLOW_DIRECTION_C2S); // inject RST to server session_set_discard(sess); break; case INJECT_TYPE_UDP_PAYLOAD: stellar_inject_udp_payload(ctx->st, sess, FLOW_DIRECTION_C2S, "Hello Server", 12); stellar_inject_udp_payload(ctx->st, sess, FLOW_DIRECTION_S2C, "Hello Client", 12); session_set_discard(sess); break; case INJECT_TYPE_CTRL_MSG: // TOOD break; default: break; } } extern "C" { void *packet_inject_plugin_init(struct stellar *st) { struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)calloc(1, sizeof(struct packet_inject_plugin_ctx)); if (ctx == NULL) { return NULL; } ctx->st = st; ctx->sess_plug_id = stellar_session_plugin_register(st, on_sess_new, on_sess_free, ctx); ctx->tcp_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_TCP); ctx->udp_topic_id = stellar_session_mq_get_topic_id(st, TOPIC_UDP); snprintf(ctx->name, sizeof(ctx->name), "packet_inject"); stellar_session_mq_subscribe(st, ctx->tcp_topic_id, on_sess_msg, ctx->sess_plug_id); stellar_session_mq_subscribe(st, ctx->udp_topic_id, on_sess_msg, ctx->sess_plug_id); printf("[%s] plugin init\n", ctx->name); return ctx; } void packet_inject_plugin_exit(void *plugin_ctx) { struct packet_inject_plugin_ctx *ctx = (struct packet_inject_plugin_ctx *)plugin_ctx; if (ctx) { printf("[%s] plugin exit\n", ctx->name); free(ctx); } } }