OpenSS7 SS7 for the Common Man |
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |
||||||||||||||||||||||||||
Home | Overview | Status | News | Documentation | Resources | About | |||||||||||||||||||||
File /code/strss7/test/etsi_m3ua/test_sctp_server.c#ident "@(#) $RCSfile: test_sctp_server.c,v $ $Name: $($Revision: 0.8 $) $Date: 2002/04/02 08:22:51 $" static char const ident[] = "$RCSfile: test_sctp_server.c,v $ $Name: $($Revision: 0.8 $) $Date: 2002/04/02 08:22:51 $"; #include <stropts.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <sys/time.h> #include <sys/poll.h> #include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <signal.h> #include <getopt.h> #include <sys/npi.h> #include <sys/npi_sctp.h> #include <ss7/ua_lm.h> #include <ss7/ua_lm_ioctl.h> #define M3UA_PORT_NUMBER 2905 #define RC_DEFAULT 1 #define NA_DEFAULT 1 #define ASPID_DEFAULT 1 #define PCX_DEFAULT 0x00ffffff #define PCZ_DEFAULT 0x00fffffe #define ASP_ADDR_DEFAULT "127.0.0.1" #define ASP_PORT_DEFAULT 0 #define SGP_ADDR_DEFAULT "127.0.0.2" #define SGP_PORT_DEFAULT M3UA_PORT_NUMBER int routing_context = RC_DEFAULT; int network_appearance = NA_DEFAULT; int aspid = ASPID_DEFAULT; uint32_t pcx = PCX_DEFAULT; uint32_t pcz = PCZ_DEFAULT; #define HOST_BUF_LEN 256 char *aspadd = ASP_ADDR_DEFAULT; char *sgpadd = SGP_ADDR_DEFAULT; int asp_port = ASP_PORT_DEFAULT; int sgp_port = SGP_PORT_DEFAULT; char **aspp = &aspadd; char **sgpp = &sgpadd; char aspbuf[HOST_BUF_LEN] = "\0"; char sgpbuf[HOST_BUF_LEN] = "\0"; typedef struct addr { uint16_t port __attribute__((packed)); struct in_addr addr[1] __attribute__((packed)); } addr_t; static addr_t asp_addr = { 0, { { INADDR_ANY } } }; static addr_t sgp_addr = { 0, { { INADDR_ANY } } }; void usage(void) { fprintf(stderr,"\n"); fprintf(stderr,"Usage: test_server [options]\n"); fprintf(stderr," Tests SCTP server connection.\n"); fprintf(stderr,"\n"); fprintf(stderr,"Options:\n"); fprintf(stderr," -s --sgp-address (default: %s)\n",SGP_ADDR_DEFAULT); fprintf(stderr," address (or hostname) of SGP for test\n"); fprintf(stderr," -w --sgp-port (default: %d)\n",SGP_PORT_DEFAULT); fprintf(stderr," well-known port for test\n"); fprintf(stderr,"\n"); } #define BUFSIZE 4096 union { np_ulong prim; union N_primitives npi; union LM_primitives lm; char cbuf[BUFSIZE]; } cmd; char dbuf[BUFSIZE]; struct strbuf ctrl = { BUFSIZE, 0, cmd.cbuf }; struct strbuf data = { BUFSIZE, 0, dbuf }; N_qos_sel_data_sctp_t qos_data = { N_QOS_SEL_DATA_SCTP, /* n_qos_type */ 3, /* ppi */ 0, /* sid */ 0, /* ssn */ 0, /* tsn */ 0 /* more */ }; N_qos_sel_conn_sctp_t qos_conn = { N_QOS_SEL_CONN_SCTP, /* n_qos_type */ 3, /* i_streams */ 3 /* o_streams */ }; N_qos_sel_info_sctp_t qos_info = { N_QOS_SEL_INFO_SCTP, /* n_qos_type */ 3, /* i_streams */ 3, /* o_streams */ 3, /* ppi */ 0, /* sid */ 8, /* max_inits */ 12, /* max_retrans */ -1UL, /* ck_life */ -1UL, /* ck_inc */ SCTP_HMAC_NONE, /* hmac */ -1UL, /* throttle */ 20, /* max_sack */ 100, /* rto_ini */ 50, /* rto_min */ 200, /* rto_max */ 12, /* rtx_path */ 200, /* hb_itvl */ 0x00 /* options */ }; int sctp_get(int fd, int wait) { int ret; int flags = 0; while ( (ret = getmsg(fd, &ctrl, &data, &flags)) < 0 ) { switch ( errno ) { default: case EPROTO: case EINVAL: perror("sctp_get: getmsg"); return -1; case EINTR: case ERESTART: continue; case EAGAIN: break; } break; } if ( !ret ) return cmd.prim; if ( !wait ) { /* fprintf(stderr,"\t...sctp_get: no data and no wait specified\n"); */ return -1; } do { struct pollfd pfd[] = { { fd, POLLIN|POLLPRI, 0 } }; if ( !(ret = poll(pfd, 1, wait)) ) { if ( errno != EAGAIN ) perror("sctp_get: poll"); return -1; } if ( (ret == 1) | (ret == 2) ) { if ( pfd[0].revents & (POLLIN|POLLPRI) ) { flags = 0; while ( (ret = getmsg(fd, &ctrl, &data, &flags)) < 0 ) { switch ( errno ) { case EINTR: case ERESTART: continue; } } if ( ret < 0 ) { perror("sctp_get: getmsg"); return -1; } return cmd.prim; } continue; } if ( ret == -1 ) { perror("sctp_get: poll"); return -1; } } while(1); } int sctp_options(int fd, ulong flags, N_qos_sel_info_sctp_t *qos) { int ret; ctrl.len = sizeof(cmd.npi.optmgmt_req)+sizeof(*qos); cmd.prim = N_OPTMGMT_REQ; cmd.npi.optmgmt_req.OPTMGMT_flags = flags; cmd.npi.optmgmt_req.QOS_length = sizeof(*qos); cmd.npi.optmgmt_req.QOS_offset = sizeof(cmd.npi.optmgmt_req); bcopy(qos, (cmd.cbuf + sizeof(cmd.npi.optmgmt_req)), sizeof(*qos)); while ( (ret = putmsg(fd, &ctrl, NULL, MSG_HIPRI)) < 0 ) { switch ( errno ) { case EINTR: case ERESTART: continue; } break; } if ( ret < 0 ) { perror("sctp_options: putmsg"); return -1; } if ( (ret = sctp_get(fd, 0)) < 0 ) { fprintf(stderr,"\t...sctp_options: couldn't get message\n"); return -1; } if ( ret != N_OK_ACK ) { fprintf(stderr,"\t...sctp_options: didn't get N_OK_ACK\n"); return -1; } fprintf(stderr,"\t...Options set\n"); return 0; } int sctp_bind(int fd, addr_t *addr, int coninds) { int ret; ctrl.len = sizeof(cmd.npi.bind_req)+sizeof(*addr); cmd.prim = N_BIND_REQ; cmd.npi.bind_req.ADDR_length = sizeof(*addr); cmd.npi.bind_req.ADDR_offset = sizeof(cmd.npi.bind_req); cmd.npi.bind_req.CONIND_number = coninds; cmd.npi.bind_req.BIND_flags = TOKEN_REQUEST; cmd.npi.bind_req.PROTOID_length = 0; cmd.npi.bind_req.PROTOID_offset = 0; bcopy(addr, (&cmd.npi.bind_req)+1, sizeof(*addr)); while ( (ret = putmsg(fd, &ctrl, NULL, MSG_HIPRI)) < 0 ) { switch ( errno ) { case EINTR: case ERESTART: continue; } break; } if ( ret < 0 ) { perror("sctp_bind: putmsg"); return -1; } if ( (ret = sctp_get(fd, 0)) < 0 ) { fprintf(stderr,"\t...sctp_bind: couldn't get message\n"); return -1; } if ( ret != N_BIND_ACK ) { fprintf(stderr,"\t...sctp_bind: didn't get N_BIND_ACK\n"); return -1; } fprintf(stderr,"\t...STREAM bound\n"); return 0; } int sctp_connect(int fd, addr_t *addr, N_qos_sel_conn_sctp_t *qos) { int ret; ctrl.len = sizeof(cmd.npi.conn_req)+sizeof(*addr)+sizeof(*qos); cmd.prim = N_CONN_REQ; cmd.npi.conn_req.DEST_length = sizeof(*addr); cmd.npi.conn_req.DEST_offset = sizeof(cmd.npi.conn_req); cmd.npi.conn_req.CONN_flags = REC_CONF_OPT|EX_DATA_OPT; cmd.npi.conn_req.QOS_length = sizeof(*qos); cmd.npi.conn_req.QOS_offset = sizeof(cmd.npi.conn_req)+sizeof(*addr); bcopy(addr, (cmd.cbuf + sizeof(cmd.npi.conn_req)), sizeof(*addr)); bcopy(qos, (cmd.cbuf + sizeof(cmd.npi.conn_req)+sizeof(*addr)), sizeof(*qos)); while ( (ret = putmsg(fd, &ctrl, NULL, 0)) < 0 ) { switch ( errno ) { case EINTR: case ERESTART: continue; } break; } if ( ret < 0 ) { perror("sctp_connect: putmsg"); return -1; } if ( (ret = sctp_get(fd, 120000)) < 0 ) { fprintf(stderr,"\t...sctp_connect: couldn't get message\n"); return -1; } if ( ret != N_CONN_CON ) { fprintf(stderr,"\t...sctp_connect: didn't get N_CONN_CON\n"); return -1; } fprintf(stderr,"\t...STREAM connected\n"); return 0; } int sctp_accept(int fd, int fd2, int tok) { int ret, seq; if ( (ret = sctp_get(fd, -1)) < 0 ) { fprintf(stderr,"sctp_accept: couldn't get message on listener\n"); return -1; } if ( ret != N_CONN_IND ) { fprintf(stderr,"sctp_accept: didn't get N_CONN_IND\n"); return -1; } seq = cmd.npi.conn_ind.SEQ_number; ctrl.len = sizeof(cmd.npi.conn_res); cmd.prim = N_CONN_RES; cmd.npi.conn_res.TOKEN_value = tok; cmd.npi.conn_res.RES_offset = 0; cmd.npi.conn_res.RES_length = 0; cmd.npi.conn_res.SEQ_number = seq; cmd.npi.conn_res.CONN_flags = REC_CONF_OPT|EX_DATA_OPT; cmd.npi.conn_res.QOS_offset = 0; cmd.npi.conn_res.QOS_length = 0; if ( putmsg(fd, &ctrl, NULL, 0) < 0 ) { perror("sctp_accept: putmsg"); return -1; } if ( (ret = sctp_get(fd, 0)) < 0 ) { fprintf(stderr,"sctp_accept: couldn't get message\n"); return -1; } if ( ret != N_OK_ACK ) { fprintf(stderr,"sctp_accept: didn't get N_OK_ACK\n"); return -1; } fprintf(stderr,"Connection Indication accepted\n"); return 0; } int sctp_write(int fd, void *msg, size_t len, int flags, N_qos_sel_data_sctp_t *qos) { data.buf = msg; data.len = len; data.maxlen = len; ctrl.len = sizeof(cmd.npi.data_req)+sizeof(*qos); cmd.prim = N_DATA_REQ; cmd.npi.data_req.DATA_xfer_flags = flags; bcopy(qos, cmd.cbuf + sizeof(cmd.npi.data_req), sizeof(*qos)); if ( putmsg(fd, &ctrl, &data, 0) < 0 ) { if ( errno != EAGAIN ) perror("sctp_write: putmsg"); return -1; } return(0); } int sctp_read(int fd, void *msg, size_t len) { int ret; data.buf = msg; data.len = 0; data.maxlen = len; if ( (ret = sctp_get(fd, 0)) < 0 ) { /* fprintf(stderr,"sctp_read: couldn't get message\n"); */ return -1; } if ( ret != N_DATA_IND ) { fprintf(stderr,"sctp_read: didn't get N_DATA_IND\n"); return -1; } return 0; } int test_sctp_server(void) { int lfd, fd; uint32_t token = 0; struct pollfd pfd[1] = { { 0, POLLIN|POLLOUT|POLLERR|POLLHUP, 0 } }; unsigned char ur_msg[4096]; printf("\n"); printf("SCTP Test Program (Server):\n"); printf("-----------------------------\n"); printf("\n"); printf("Configuration:\n"); printf(" SGP Address = %s:%d\n",*sgpp,sgp_port); printf("\n"); printf("Opening accepting SCTP STREAM\n"); if ( (fd = open("/dev/sctp_n",O_NONBLOCK|O_RDWR)) < 0 ) { perror("open"); exit(2); } printf(" Setting IOCTL on accepting SCTP STREAM\n"); if ( ioctl(fd, I_SRDOPT, RMSGD) < 0 ) { perror("ioctl"); exit(2); } printf(" Binding accepting SCTP STREAM\n"); if ( sctp_bind(fd, &sgp_addr, 0) < 0 ) exit(2); token = cmd.npi.bind_ack.TOKEN_value; printf("\n"); printf("\n"); printf(" Opening Listening SCTP STREAM\n"); if ( (lfd = open("/dev/sctp_n",O_NONBLOCK|O_RDWR)) < 0 ) { perror("open"); exit(2); } printf(" Setting IOCTL on Listening SCTP STREAM\n"); if ( ioctl(lfd, I_SRDOPT, RMSGD) < 0 ) { perror("ioctl"); exit(2); } printf(" Setting Options on Listening STREAM\n"); if ( sctp_options(lfd, 0, &qos_info) < 0 ) exit(2); printf(" Binding STREAM\n"); if ( sctp_bind(lfd, &sgp_addr, 1) < 0 ) exit(2); printf("Waiting for ASP connection:\n"); if ( sctp_accept(lfd, fd, token) < 0 ) exit(2); printf("\n"); for (;;) { pfd[0].fd = fd; pfd[0].events = POLLIN; pfd[0].revents = 0; if ( poll(&pfd[0], 1, -1) < 0 ) { switch ( errno ) { case EINTR: case ERESTART: continue; } perror("poll"); exit(2); } if ( pfd[0].revents & POLLIN ) { if ( sctp_read(fd, ur_msg, sizeof(ur_msg)) < 0 ) { if ( errno != EAGAIN ) { fprintf(stderr,"sctp_read: couldn't read message\n"); exit(2); } pfd[0].revents &= ~POLLIN; } printf("Got one.\n"); printf("Sending one.\n"); if ( sctp_write(fd, ur_msg, data.len, 0, &qos_data) < 0 ) { if ( errno != EAGAIN ) { fprintf(stderr,"sctp_write: couldn't write message\n"); exit(2); } pfd[0].revents &= ~POLLOUT; } } } } int main(int argc, char**argv) { int c; struct hostent *haddr; while (1) { int option_index = 0; static struct option long_options[] = { { "sgp-address", 1, 0, 's' }, { "sgp-port", 1, 0, 'w' }, { "asp-address", 1, 0, 'a' }, { "asp-port", 1, 0, 'p' }, { "routing-context", 1, 0, 'r' }, { "network-appearance", 1, 0, 'n' }, { "aspid", 1, 0, 'i' }, { "point-code-X", 1, 0, 'x' }, { "point-code-Z", 1, 0, 'z' }, { "help", 0, 0, 'h' } }; c = getopt_long(argc,argv,"s:w:a:p:r:n:i:x:z:h",long_options,&option_index); if ( c == -1 ) break; switch ( c ) { case 0: switch ( option_index ) { case 0: goto option_s; case 1: goto option_w; case 2: goto option_a; case 3: goto option_p; case 4: goto option_r; case 5: goto option_n; case 6: goto option_i; case 7: goto option_x; case 8: goto option_z; case 9: goto option_h; default: usage(); exit(1); } break; case 's': option_s: strncpy(sgpbuf,optarg,HOST_BUF_LEN); sgpadd = sgpbuf; sgpp = &sgpadd; break; case 'w': option_w: sgp_port = atoi(optarg); break; case 'a': option_a: strncpy(aspbuf,optarg,HOST_BUF_LEN); aspadd = aspbuf; aspp = &aspadd; break; case 'p': option_p: asp_port = atoi(optarg); break; case 'r': option_r: routing_context = atoi(optarg); break; case 'n': option_n: network_appearance = atoi(optarg); break; case 'i': option_i: aspid = atoi(optarg); break; case 'x': option_x: pcx = atoi(optarg); break; case 'z': option_z: pcz = atoi(optarg); break; case 'h': option_h: usage(); exit(0); default: fprintf(stderr, "ERROR: Unrecognized option `%c'.\n",c); usage(); exit(1); } } if ( optind < argc ) { fprintf(stderr, "ERROR: Option syntax: "); while ( optind < argc ) fprintf(stderr, "%s ",argv[optind++]); fprintf(stderr,"\n"); usage(); exit(1); } haddr = gethostbyname(*aspp); asp_addr.port = asp_port; asp_addr.addr[0].s_addr = *(uint32_t *)(haddr->h_addr); haddr = gethostbyname(*sgpp); sgp_addr.port = sgp_port; sgp_addr.addr[0].s_addr = *(uint32_t *)(haddr->h_addr); return test_sctp_server(); }
|
|||||||||||||||||||||||||||
OpenSS7 SS7 for the Common Man |
Home | Overview | Status | News | Documentation | Resources | About | ||||||||||||||||||||
© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved. |