From a4f23f73e94a21d0d68858a67f5f8f8ac965b788 Mon Sep 17 00:00:00 2001 From: luqiuwen Date: Tue, 21 May 2019 17:15:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9C=A8scm=20acceptor=E4=B8=AD=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=A7=A3=E6=9E=90=E5=BA=94=E7=94=A8=E5=B1=82=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platform/src/acceptor_scm.cpp | 233 +++++++++++++++++++++++++++++++--- 1 file changed, 218 insertions(+), 15 deletions(-) diff --git a/platform/src/acceptor_scm.cpp b/platform/src/acceptor_scm.cpp index 861b56a..7ff8f75 100644 --- a/platform/src/acceptor_scm.cpp +++ b/platform/src/acceptor_scm.cpp @@ -56,7 +56,7 @@ struct acceptor_scm void * logger; /* CONFIG */ - char str_scm_socket_file[TFE_STRING_MAX]; + char str_scm_socket[TFE_STRING_MAX]; /* PERSIST RUNTIME RESOURCE */ int fd_scm_socket; @@ -65,11 +65,209 @@ struct acceptor_scm pthread_t thread; }; +enum tcp_restore_info_tlv_type +{ + TCP_RESTORE_INFO_TLV_SEQ, + TCP_RESTORE_INFO_TLV_ACK, + TCP_RESTORE_INFO_TLV_MSS_CLIENT, + TCP_RESTORE_INFO_TLV_MSS_SERVER, + TCP_RESTORE_INFO_TLV_WSACLE_CLIENT, + TCP_RESTORE_INFO_TLV_WSACLE_SERVER, + TCP_RESTORE_INFO_TLV_SACK_CLIENT, + TCP_RESTORE_INFO_TLV_SACK_SERVER, + TCP_RESTORE_INFO_TLV_TS_CLIENT, + TCP_RESTORE_INFO_TLV_TS_SERVER, + TCP_RESTORE_INFO_TLV_PROTOCOL, + TCP_RESTORE_INFO_TLV_USER_DEFINED +}; + +struct tcp_restore_info_endpoint +{ + struct sockaddr_storage addr; + uint32_t seq; + uint32_t ack; + bool wscale_perm; + bool timestamp_perm; + bool sack_perm; + uint16_t mss; + uint8_t wscale; +}; + +struct tcp_restore_info +{ + struct tcp_restore_info_endpoint client; + struct tcp_restore_info_endpoint server; + unsigned int protocol; +}; + +struct tcp_restore_info_tlv +{ + uint16_t type; + uint16_t length; + + union + { + uint8_t value_as_uint8[0]; + uint16_t value_as_uint16[0]; + uint32_t value_as_uint32[0]; + unsigned char value_as_string[0]; + }; + +} __attribute__((packed)); + +struct tcp_restore_info_header +{ + uint8_t __magic__[2]; /* Must be 0x4d, 0x5a */ + uint16_t nr_tlvs; + struct tcp_restore_info_tlv tlvs[0]; +} __attribute__((packed)); + +#define TCP_RESTORE_TCPOPT_KIND 88 +#define TCP_RESTORE_TCPOPT_LENGTH 4 + +/* Copy from tfe-kmod */ +int tcp_restore_info_parse_from_cmsg(struct acceptor_scm * ctx, + const char * data, unsigned int datalen, struct tcp_restore_info * out) +{ + struct tcp_restore_info_header * header = (struct tcp_restore_info_header *)data; + unsigned int tlv_iter; + unsigned int nr_tlvs; + + if(unlikely(header->__magic__[0] != 0x4d || header->__magic__[1] != 0x5a)) + { + TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: wrong magic, drop it.\n"); + goto invalid_format; + } + + nr_tlvs = ntohs(header->nr_tlvs); + if (unlikely(nr_tlvs >= 256)) + { + TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: numbers of tlvs is larger than 256, drop it.\n"); + goto invalid_format; + } + + if (unlikely(datalen < sizeof(struct tcp_restore_info_header))) + { + TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: length is shorter than tlv header, drop it.\n"); + goto invalid_format; + } + + datalen -= sizeof(struct tcp_restore_info_header); + data += sizeof(struct tcp_restore_info_header); + + for(tlv_iter = 0; tlv_iter < nr_tlvs; tlv_iter++) + { + struct tcp_restore_info_tlv * tlv = (struct tcp_restore_info_tlv *)data; + uint16_t tlv_type = ntohs(tlv->type); + uint16_t tlv_length = ntohs(tlv->length); + + unsigned int __length = tlv_length; + if(unlikely(datalen < __length)) + { + TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: left space is smaller than tlv's length, " + "datalen is %u, tlv's length is %u, drop it.", datalen, __length); + goto invalid_format; + } + + if(unlikely(tlv_length < sizeof(uint16_t) * 2)) + { + TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: invalid tlv length, " + "should larger than sizeof(type) + sizeof(length)."); + goto invalid_format; + } + + tlv_length -= sizeof(uint16_t) * 2; + +#define __CHECK_TLV_LENGTH(x) do { if(unlikely(x != tlv_length)) { \ + TFE_LOG_ERROR(ctx->logger, "Invalid restore format: invalid tlv length, should be %u, actually is %u, drop it.", \ + (unsigned int)x, (unsigned int)tlv_length); goto invalid_format; }} while(0) + + switch(tlv_type) + { + case TCP_RESTORE_INFO_TLV_SEQ: + __CHECK_TLV_LENGTH(sizeof(uint32_t)); + out->client.seq = ntohl(tlv->value_as_uint32[0]); + out->server.ack = ntohl(tlv->value_as_uint32[0]); + break; + + case TCP_RESTORE_INFO_TLV_ACK: + __CHECK_TLV_LENGTH(sizeof(uint32_t)); + out->client.ack = ntohl(tlv->value_as_uint32[0]); + out->server.seq = ntohl(tlv->value_as_uint32[0]); + break; + + case TCP_RESTORE_INFO_TLV_TS_CLIENT: + __CHECK_TLV_LENGTH(sizeof(uint8_t)); + out->client.timestamp_perm = !!(tlv->value_as_uint8[0]); + break; + + case TCP_RESTORE_INFO_TLV_TS_SERVER: + __CHECK_TLV_LENGTH(sizeof(uint8_t)); + out->server.timestamp_perm = !!(tlv->value_as_uint8[0]); + break; + + case TCP_RESTORE_INFO_TLV_WSACLE_CLIENT: + __CHECK_TLV_LENGTH(sizeof(uint8_t)); + out->client.wscale_perm = true; + out->client.wscale = tlv->value_as_uint8[0]; + break; + + case TCP_RESTORE_INFO_TLV_WSACLE_SERVER: + __CHECK_TLV_LENGTH(sizeof(uint8_t)); + out->server.wscale_perm = true; + out->server.wscale = tlv->value_as_uint8[0]; + break; + + case TCP_RESTORE_INFO_TLV_SACK_CLIENT: + __CHECK_TLV_LENGTH(sizeof(uint8_t)); + out->client.sack_perm = true; + break; + + case TCP_RESTORE_INFO_TLV_SACK_SERVER: + __CHECK_TLV_LENGTH(sizeof(uint8_t)); + out->server.sack_perm = true; + break; + + case TCP_RESTORE_INFO_TLV_MSS_CLIENT: + __CHECK_TLV_LENGTH(sizeof(uint16_t)); + out->client.mss = ntohs(tlv->value_as_uint16[0]); + break; + + case TCP_RESTORE_INFO_TLV_MSS_SERVER: + __CHECK_TLV_LENGTH(sizeof(uint16_t)); + out->server.mss = ntohs(tlv->value_as_uint16[0]); + break; + + case TCP_RESTORE_INFO_TLV_PROTOCOL: + __CHECK_TLV_LENGTH(sizeof(uint8_t)); + out->protocol = tlv->value_as_uint8[0]; + break; + + case TCP_RESTORE_INFO_TLV_USER_DEFINED: + break; + + default: + TFE_LOG_ERROR(ctx->logger, "Invalid restore info format: unsupported type %x, drop it.\n", tlv_type); + goto invalid_format; + } + + data += __length; + datalen -= __length; + } + + return 0; + +invalid_format: + return -EINVAL; +} + + void acceptor_scm_event(evutil_socket_t fd, short what, void * user) { struct acceptor_scm * __ctx = (struct acceptor_scm *) user; struct cmsghdr * __cmsghdr; struct tfe_proxy_accept_para __accept_para{}; + struct tcp_restore_info restore_info{}; int * __fds = NULL; assert(__ctx != NULL && __ctx->thread == pthread_self()); @@ -124,17 +322,15 @@ void acceptor_scm_event(evutil_socket_t fd, short what, void * user) goto __die; } -#if 0 - if (unlikely(__kni_parse_tlv_data(__ctx, &__accept_para, __buffer, (size_t) rd) < 0)) + if (tcp_restore_info_parse_from_cmsg(__ctx, __buffer, (size_t)rd, &restore_info) < 0) { - TFE_LOG_ERROR(__ctx->logger, "Failed at parsing TLV format, close KNI connection."); - goto __close_kni_connection; + TFE_LOG_ERROR(__ctx->logger, "Failed at parsing TLV format, drop the connection."); + goto __drop_recieved_fds; } -#endif __accept_para.downstream_fd = __fds[0]; __accept_para.upstream_fd = __fds[1]; - __accept_para.session_type = STREAM_PROTO_SSL; + __accept_para.session_type = restore_info.protocol ? STREAM_PROTO_SSL : STREAM_PROTO_PLAIN; TFE_PROXY_STAT_INCREASE(STAT_FD_OPEN_BY_KNI_ACCEPT, 2); if (tfe_proxy_fds_accept(__ctx->proxy, &__accept_para) < 0) @@ -188,6 +384,7 @@ struct acceptor_scm * acceptor_scm_create(struct tfe_proxy * proxy, const char * { struct acceptor_scm * __ctx = ALLOC(struct acceptor_scm, 1); struct sockaddr_un __sockaddr_un{}; + int ret = 0; __ctx->proxy = proxy; @@ -195,11 +392,17 @@ struct acceptor_scm * acceptor_scm_create(struct tfe_proxy * proxy, const char * __ctx->logger = logger; /* Read the unix domain socket file, this file is used to recieve fds from KNI */ - MESA_load_profile_string_def(profile, "acceptor_scm", "scm_socket_file", __ctx->str_scm_socket_file, - sizeof(__ctx->str_scm_socket_file), TFE_CONFIG_SCM_SOCKET_FILE); + MESA_load_profile_string_def(profile, "acceptor_scm", "scm_socket_file", __ctx->str_scm_socket, + sizeof(__ctx->str_scm_socket), TFE_CONFIG_SCM_SOCKET_FILE); __sockaddr_un.sun_family = AF_UNIX; - strncpy(__sockaddr_un.sun_path, __ctx->str_scm_socket_file, sizeof(__sockaddr_un.sun_path)); + strncpy(__sockaddr_un.sun_path, __ctx->str_scm_socket, sizeof(__sockaddr_un.sun_path)); + + if (remove(__ctx->str_scm_socket) < 0 && errno != ENOENT) + { + TFE_LOG_ERROR(__ctx->logger, "Failed at remove(%s) : %s", __ctx->str_scm_socket, strerror(errno)); + goto __errout; + } /* Create new event base, this event base will be dispatched at separated thread */ __ctx->ev_base = event_base_new(); @@ -216,11 +419,11 @@ struct acceptor_scm * acceptor_scm_create(struct tfe_proxy * proxy, const char * goto __errout; } - ret = connect(__ctx->fd_scm_socket, (struct sockaddr *)&__sockaddr_un, sizeof(__sockaddr_un)); - if (unlikely(ret < 0)) + ret = bind(__ctx->fd_scm_socket, (struct sockaddr *)&__sockaddr_un, sizeof(__sockaddr_un)); + if (unlikely(ret < 0)) { - TFE_LOG_ERROR(__ctx->logger, "Failed at connecting to %s: %s", __sockaddr_un.sun_path, strerror(errno)); - goto __errout; + TFE_LOG_ERROR(__ctx->logger, "Failed at binding to %s: %s", __sockaddr_un.sun_path, strerror(errno)); + goto __errout; } __ctx->ev_scm_socket = event_new(__ctx->ev_base, __ctx->fd_scm_socket, @@ -247,7 +450,7 @@ struct acceptor_scm * acceptor_scm_create(struct tfe_proxy * proxy, const char * goto __errout; } - TFE_LOG_INFO(__ctx->logger, "KNI scm socket file: %s", __ctx->str_scm_socket_file); + TFE_LOG_INFO(__ctx->logger, "scm socket file: %s", __ctx->str_scm_socket); return __ctx; __errout: