#include #include #include #include #include #include #include #include #include #include #include #include #include /* Определяем порт и адрес АТС. */ #define PORTNUM 33333 #define SERVER "192.168.0.101" int s; int write_out(const void *buffer, size_t size, void *app_key); typedef struct buffer_s { char *buf; int len; } buffer_t; void parseEventReport(char *data, int length) { CSTAEventReportArgument_t *rep = 0; /* Type to decode */ asn_dec_rval_t rval; /* Decoder return value */ size_t size; /* Number of bytes read */ /* Decode the input buffer */ rval = ber_decode(0, &asn_DEF_CSTAEventReportArgument, (void **) &rep, data, length); if (rval.code != RC_OK) fprintf(stderr, "Broken encoding at byte %ld\n", (long) rval.consumed); /* Print the decoded Rectangle type as XML */ xer_fprint(stdout, &asn_DEF_CSTAEventReportArgument, rep); return 0; /* Decoding finished successfully */ } void dump(unsigned char *buf, int len) { int i, j; for (i = 0; i < len; i += 16) { for (j = 0; j < 16; j++) if (i + j < len) printf("%02X ", (unsigned char) buf[i + j]); else printf(" "); for (j = 0; j < 16; j++) if (i + j < len) { if (buf[i + j] >= 0x20) printf("%c", (unsigned char) buf[i + j]); else printf("."); } printf("\n"); } } void * memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen) { register const char *pn; register const char *ph; const char *plast; size_t n; if (needlelen == 0) { return (void *) haystack; } if (haystacklen >= needlelen) { ph = (const char *) haystack; pn = (const char *) needle; plast = ph + (haystacklen - needlelen); do { n = 0; while (ph[n] == pn[n]) { if (++n == needlelen) { return (void *) ph; } } } while (++ph <= plast); } return NULL; } #define READ 0 #define WRITE 1 void timestamp(int dir) { time_t t; struct tm *l; t = time(NULL); l = localtime(&t); printf("\n[%02d:%02d:%02d %02d.%02d.%4d] ", l->tm_hour, l->tm_min, l->tm_sec, l->tm_mday, l->tm_mon + 1, l->tm_year + 1900); if (dir == READ) printf("---- PBX -> PC ----\n"); else printf("---- PC -> PBX ----\n"); } void pktdump(char *buf, int len) { int i, j; char id[256], *cp, type, tmp[256], *c, *orig; long seq, l, origlen; CSTAapdu_t *apdu = 0; /* Type to decode */ RORSapdu_t *rors; asn_dec_rval_t rval; /* Decoder return value */ size_t size; /* Number of bytes read */ buffer_t *out; buf += 2; len -= 2; timestamp(READ); /* Decode the input buffer */ rval = ber_decode(0, &asn_DEF_CSTAapdu, (void **) &apdu, buf, len); if (rval.code != RC_OK) { fprintf(stderr, "Broken encoding at byte %ld\n", (long) rval.consumed); return 1; } switch (apdu->present) { case CSTAapdu_PR_svcRequest: printf("invokeID %d, serviceID %d\n", apdu->choice.svcRequest.invokeID, apdu->choice.svcRequest.serviceID); switch (apdu->choice.svcRequest.serviceID) { case 211: printf("SystemStatus Request\n"); // send SystemStatus responce rors = calloc(1, sizeof(RORSapdu_t)); rors->invokeID = apdu->choice.svcRequest.invokeID; rors->result.serviceID = apdu->choice.svcRequest.serviceID; out = calloc(1, sizeof(buffer_t)); out->buf = malloc(1024); der_encode(&asn_DEF_RORSapdu, rors, write_out, out); timestamp(WRITE); printf("invokeID %d, serviceID %d\n", rors->invokeID, rors->result.serviceID); printf("SystemStatus Responce\n"); // xer_fprint(stdout, &asn_DEF_RORSapdu, rors); memmove(out->buf + 2, out->buf, out->len); out->buf[0] = 0x00; out->buf[1] = out->len; out->len += 2; send(s, out->buf, out->len, 0); free(out->buf); break; case CSTAServices_cSTAeventReportSID: parseEventReport(apdu->choice.svcRequest. serviceArgs.buf, apdu->choice.svcRequest.serviceArgs.size); break; default: printf("Unknown svcRequest:\n"); dump(apdu->choice.svcRequest.serviceArgs.buf, apdu->choice.svcRequest.serviceArgs.size); break; } break; case CSTAapdu_PR_svcResult: case CSTAapdu_PR_svcError: case CSTAapdu_PR_svcReject: default: xer_fprint(stdout, &asn_DEF_CSTAapdu, apdu); break; } } int write_out(const void *buffer, size_t size, void *app_key) { buffer_t *dest = app_key; u_char *buf = buffer; int i; for (i = 0; i < size; i++) dest->buf[dest->len + i] = buf[i]; dest->len += size; return 0; } int sendID = 1; void start_monitor(char *numer) { ROIVapdu_t *pdu; MonitorStartArgument_t *rep; int i; buffer_t *buf; rep = calloc(1, sizeof(MonitorStartArgument_t)); rep->monitorObject.present = CSTAObject_PR_deviceObject; rep->monitorObject.choice.deviceObject.deviceIdentifier.present = DeviceID__deviceIdentifier_PR_dialingNumber; rep->monitorObject.choice.deviceObject.deviceIdentifier. choice.dialingNumber.buf = numer; rep->monitorObject.choice.deviceObject.deviceIdentifier. choice.dialingNumber.size = strlen(numer); pdu = calloc(1, sizeof(ROIVapdu_t)); pdu->invokeID = sendID++; pdu->serviceID = CSTAServices_monitorStartSID; pdu->serviceArgs.buf = malloc(1024); buf = calloc(1, sizeof(buffer_t)); buf->buf = pdu->serviceArgs.buf; der_encode(&asn_DEF_MonitorStartArgument, rep, write_out, buf); pdu->serviceArgs.size = buf->len; buf->len = 0; buf->buf = malloc(1024); der_encode(&asn_DEF_ROIVapdu, pdu, write_out, buf); timestamp(WRITE); xer_fprint(stdout, &asn_DEF_MonitorStartArgument, rep); memmove(buf->buf + 2, buf->buf, buf->len); buf->buf[0] = 0x00; buf->buf[1] = buf->len; buf->len += 2; send(s, buf->buf, buf->len, 0); free(buf->buf); free(pdu->serviceArgs.buf); // read_pkt(); } int read_pkt(int s, unsigned char *buf) { int nbytes, total = 0, length; while (total < 2) { nbytes = recv(s, &buf[total], 2 - total, 0); if (nbytes == 0) return 0; // соединение закрыто удаленно if (nbytes < 0) return -1; // ошибка чтения из сокета total += nbytes; } if (buf[0] != 0) return -2; // испорченный пакет if (buf[1] == 0) return 2; // прочли 2 байта - пустой пакет length = ((unsigned char *) buf)[1] + 2; while (total < length) { nbytes = recv(s, &buf[total], length - total, 0); if (nbytes == 0) return 0; // соединение закрыто удаленно if (nbytes < 0) return -1; // ошибка чтения из сокета total += nbytes; } return total; } main(argc, argv) int argc; char *argv[]; { int nbytes; int pid; int nport; /* Начало программы. */ struct sockaddr_in serv_addr; unsigned char buf[242] = { 0x00, 0x25, 0x60, 0x23, 0x80, 0x02, 0x07, 0x80, 0xA1, 0x07, 0x06, 0x05, 0x2B, 0x0C, 0x00, 0x81, 0x5A, 0xBE, 0x14, 0x28, 0x12, 0x06, 0x07, 0x2B, 0x0C, 0x00, 0x82, 0x1D, 0x81, 0x48, 0xA0, 0x07, 0xA0, 0x05, 0x03, 0x03, 0x00, 0x08, 0x00 }; int addrlen; unsigned long addr; nport = htons((u_short) PORTNUM); if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("Error calling socket()"); return 1; } /* В serv_addr заносим адрес и порт АТС. */ bzero(&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(SERVER); serv_addr.sin_port = nport; if (connect(s, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -1) { perror("Error calling connect()"); return 1; } // посылаем #A-ASSOCIATE Request // dump(buf, 39); send(s, buf, 39, 0); // Получаем ответ от АТС. nbytes = recv(s, buf, sizeof(buf), 0); // printf("%d", nbytes) dump(buf, nbytes); if (nbytes < 0) { perror("Error calling recv()"); return 1; } // проверяем на rejected-permanent const unsigned char seek[] = { 0xA2, 0x03, 0x02, 0x01, 0x01 }; unsigned char *off_ptr = memmem(buf, sizeof(buf), seek, sizeof(seek)); if (off_ptr) { printf("rejected-permanent\n"); close(s); return 0; } // шлём #StartMonitor start_monitor("101"); start_monitor("102"); start_monitor("111"); start_monitor("112"); start_monitor("113"); start_monitor("114"); start_monitor("115"); while (1) { //цикл nbytes = read_pkt(s, buf); if (nbytes < 0) { perror("Error calling recv()"); return 1; } else if (nbytes == 0) { printf("socket closed\n"); return 1; } // dump(buf, nbytes); pktdump(buf, nbytes); } close(s); return 0; }