/* Processed by ecpg (15.18 (Debian 15.18-0+deb12u1)) */ /* These include files are added by the preprocessor */ #include #include #include /* End of automatic include section */ #line 1 "app/online/mg_ol_0019.pgc" /* @tier medium @module mg @transform msg-gateway-online */ /* * mg_ol_0019.pgc - 전문게이트웨이 공통헤더 파싱 서비스 (MG_OL_0019) [tier=medium] * * 표준 고정 공통헤더를 원시전문(RAWMSG)에서 오프셋 단위로 파싱한다. * 공통헤더 레이아웃(총 25바이트): * [전문길이 5][전문종별 4][채널 2][일자 8][시각 6] * 각 필드의 형식(숫자/종별화이트리스트)을 검증하고, 선언된 전문길이와 * 실제 본문길이의 일치 여부를 교차검증하여 헤더 필드들을 응답한다. */ #include #include #include #include "txcore.h" #include "acq_util.h" #include "mg_core.h" #line 1 "/usr/include/postgresql/sqlca.h" #ifndef POSTGRES_SQLCA_H #define POSTGRES_SQLCA_H #ifndef PGDLLIMPORT #if defined(WIN32) || defined(__CYGWIN__) #define PGDLLIMPORT __declspec (dllimport) #else #define PGDLLIMPORT #endif /* __CYGWIN__ */ #endif /* PGDLLIMPORT */ #define SQLERRMC_LEN 150 #ifdef __cplusplus extern "C" { #endif struct sqlca_t { char sqlcaid[8]; long sqlabc; long sqlcode; struct { int sqlerrml; char sqlerrmc[SQLERRMC_LEN]; } sqlerrm; char sqlerrp[8]; long sqlerrd[6]; /* Element 0: empty */ /* 1: OID of processed tuple if applicable */ /* 2: number of rows processed */ /* after an INSERT, UPDATE or */ /* DELETE statement */ /* 3: empty */ /* 4: empty */ /* 5: empty */ char sqlwarn[8]; /* Element 0: set to 'W' if at least one other is 'W' */ /* 1: if 'W' at least one character string */ /* value was truncated when it was */ /* stored into a host variable. */ /* * 2: if 'W' a (hopefully) non-fatal notice occurred */ /* 3: empty */ /* 4: empty */ /* 5: empty */ /* 6: empty */ /* 7: empty */ char sqlstate[5]; }; struct sqlca_t *ECPGget_sqlca(void); #ifndef POSTGRES_ECPG_INTERNAL #define sqlca (*ECPGget_sqlca()) #endif #ifdef __cplusplus } #endif #endif #line 19 "app/online/mg_ol_0019.pgc" #define HDR_LEN 25 #define OFF_LEN 0 #define OFF_TYPE 5 #define OFF_CHAN 9 #define OFF_DATE 11 #define OFF_TIME 19 /* 지정 구간이 전부 숫자인지 검사 */ static int all_digit(const char *p, int n) { int i; for (i = 0; i < n; i++) if (p[i] < '0' || p[i] > '9') return 0; return 1; } TX_SERVICE(MG_OL_0019, ctx) { char raw[256]; char declen[6]; char mtype[5]; char chan[3]; char cdate[9]; char ctime[7]; int rawlen; long decl_body; long real_body; tx_log(TX_LOG_INFO, "[MG_OL_0019] 공통헤더 파싱 서비스 진입"); rawlen = tx_buf_get(ctx->in, "RAWMSG", raw, sizeof(raw)); if (rawlen <= 0) { tx_log(TX_LOG_ERROR, "[MG_OL_0019] RAWMSG 누락"); tx_return(ctx, TX_EINVAL, ctx->out); return; } rawlen = (int)strlen(raw); if (rawlen < HDR_LEN) { tx_log(TX_LOG_WARN, "[MG_OL_0019] 헤더 길이부족 len=%d", rawlen); tx_buf_reset(ctx->out); tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID); tx_return(ctx, TX_FAIL, ctx->out); return; } /* 오프셋 파싱 */ memset(declen, 0, sizeof(declen)); memset(mtype, 0, sizeof(mtype)); memset(chan, 0, sizeof(chan)); memset(cdate, 0, sizeof(cdate)); memset(ctime, 0, sizeof(ctime)); memcpy(declen, raw + OFF_LEN, 5); memcpy(mtype, raw + OFF_TYPE, 4); memcpy(chan, raw + OFF_CHAN, 2); memcpy(cdate, raw + OFF_DATE, 8); memcpy(ctime, raw + OFF_TIME, 6); /* 형식 검증: 길이/일자/시각은 숫자, 종별은 화이트리스트 */ if (!all_digit(declen, 5) || !all_digit(cdate, 8) || !all_digit(ctime, 6)) { tx_log(TX_LOG_WARN, "[MG_OL_0019] 숫자필드 형식 오류"); tx_buf_reset(ctx->out); tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID); tx_return(ctx, TX_FAIL, ctx->out); return; } if (strcmp(mtype, MSG_TYPE_RECV) != 0 && strcmp(mtype, MSG_TYPE_RESP) != 0 && strcmp(mtype, MSG_TYPE_RECON) != 0) { tx_log(TX_LOG_WARN, "[MG_OL_0019] 전문종별 미허용 type=%s", mtype); tx_buf_reset(ctx->out); tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID); tx_return(ctx, TX_FAIL, ctx->out); return; } if (!date_is_valid(cdate)) { tx_log(TX_LOG_WARN, "[MG_OL_0019] 일자 유효성 오류 date=%s", cdate); tx_buf_reset(ctx->out); tx_buf_sets(ctx->out, "RESPCODE", RESP_INVALID); tx_return(ctx, TX_FAIL, ctx->out); return; } /* 선언 전문길이와 실제 본문길이 교차검증 */ decl_body = (long)atoi(declen); real_body = (long)(rawlen - HDR_LEN); if (decl_body != real_body) tx_log(TX_LOG_WARN, "[MG_OL_0019] 길이불일치 decl=%ld real=%ld", decl_body, real_body); tx_buf_reset(ctx->out); tx_buf_sets(ctx->out, "RESPCODE", RESP_OK); tx_buf_sets(ctx->out, "MSGTYPE", mtype); tx_buf_sets(ctx->out, "CHAN", chan); tx_buf_sets(ctx->out, "TXNDATE", cdate); tx_buf_sets(ctx->out, "TXNTIME", ctime); tx_buf_setlong(ctx->out, "DECLLEN", decl_body); tx_buf_setlong(ctx->out, "REALLEN", real_body); tx_buf_sets(ctx->out, "LENMATCH", (decl_body == real_body) ? "Y" : "N"); tx_log(TX_LOG_INFO, "[MG_OL_0019] 헤더파싱 완료 type=%s chan=%s date=%s time=%s", mtype, chan, cdate, ctime); tx_return(ctx, TX_OK, ctx->out); }