OpenSS7
SS7 for the
Common Man

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified:

Home Overview Status News Documentation Resources About
   
 Overview
 Status
 News
 Documentation
 Resources
 About

   
Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/test/etsi_m3ua/test_sctp_server.c


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();
}


Home Index Prev Next More Download Info FAQ Mail   Home -> Resources -> Browse Source -> strss7/test/etsi_m3ua/test_sctp_server.c

OpenSS7
SS7 for the
Common Man
Home Overview Status News Documentation Resources About

© Copyright 1997-2004,OpenSS7 Corporation, All Rights Reserved.
Last modified: