Ejemplo n.º 1
1
int main(int argc,char **argv)
{
	int sock_fd;
	int msg_flags;	// 記錄要傳送訊息時的相關設定,包括association...
	char readbuf[BUFFERSIZE];
	struct sockaddr_in cliaddr, servaddr;
	struct sctp_sndrcvinfo sri;
	struct sctp_event_subscribe evnts;
	socklen_t len;
	size_t rd_sz;	// size_t指的就是unsigned long
	int ret_value=0;
	struct sockaddr *laddrs;	// 用來記錄local addresses
	struct sockaddr *paddrs;
	union sctp_notification *snp;		// 用來轉換傳送過來的訊息
	struct sctp_shutdown_event *sse;	// 當傳送過來的是shutdown event,則可以用這一個指標指到傳送過來的資料
	struct sctp_assoc_change *sac;
	struct sctp_paddr_change *spc;
	struct sctp_remote_error *sre;
	struct sctp_send_failed *ssf;
#ifdef UN_MOD
	struct sctp_adaptation_event *ae;
#else
	struct sctp_adaption_event *ae;
#endif
	struct sctp_pdapi_event *pdapi;
	int close_time = 30;
	const char *str;

	if (argc < 2) {
		printf("Error, use %s [list of addresses to bind]\n",argv[0]);
		exit(-1);
	}
	// 建立socket的型態為SCTP的one-to-many的型態
	sock_fd = Socket(AF_INET,SOCK_SEQPACKET, IPPROTO_SCTP);
	if (sock_fd == -1) {
		printf("socket error\n");
		exit(-1);
	}

	// 初始化要bind的server資料,連續加入多個要綁的ip address
	int i;
	for (i=1;i<argc;i++) {
		memset(&servaddr,0,sizeof(servaddr));
		servaddr.sin_family = AF_INET;
		inet_pton(AF_INET,argv[i],&servaddr.sin_addr);	// 把socket與此ip綁在一起
		servaddr.sin_port = htons(SERV_PORT);

		// 把這一個ip與socket綁在一起
		if ((ret_value=sctp_bindx(sock_fd,(struct sockaddr*) &servaddr,1,SCTP_BINDX_ADD_ADDR))==-1) {
			printf("Can't bind the address %s\n",argv[i]);
			exit(-1);
		}
		else
		{
			// 無論如何一定會bind成功,因為,若給錯的ip,則會bind此host端的所有ip
			printf("Bind %s success!!\n",argv[i]);
		}
	}

	// 設定事件
	bzero(&evnts,sizeof(evnts));
	evnts.sctp_data_io_event=1;	// Enable sctp_sndrcvinfo to come with each recvmsg,否則就接收不到對方的資訊了
	evnts.sctp_shutdown_event=1;	// 喔耶!當client端shutdown時,會通知server
	evnts.sctp_association_event=1;	// 監測
	evnts.sctp_address_event = 1;
	evnts.sctp_send_failure_event = 1;
	evnts.sctp_peer_error_event = 1;
	evnts.sctp_partial_delivery_event = 1;
#ifdef UN_MOD
	evnts.sctp_adaptation_layer_event = 1;
#else
	evnts.sctp_adaption_layer_event = 1;
#endif
	ret_value = setsockopt(sock_fd,IPPROTO_SCTP,SCTP_EVENTS,&evnts,sizeof(evnts));
	if (ret_value == -1) {
		printf("setsockopt error\n");
		exit(-1);
	}
	ret_value = setsockopt(sock_fd,IPPROTO_SCTP,SCTP_AUTOCLOSE,&close_time,sizeof(close_time));
	if (ret_value == -1) {
		printf("setsockopt error\n");
		exit(-1);
	}

	// 設定多少個client可以連線
	ret_value = listen(sock_fd,LISTENQ);
	if (ret_value == -1) {
		printf("listen error\n");
		exit(-1);
	}

	printf("start wait...\n");
	for (;;) {
		memset(readbuf,0,sizeof(readbuf));
		len = sizeof(struct sockaddr_in);
		rd_sz = sctp_recvmsg(sock_fd,readbuf,sizeof(readbuf),(struct sockaddr *) &cliaddr,&len,&sri,&msg_flags);
		//========================================================================
		// test the sctp_getladdrs function - start
		ret_value = sctp_getladdrs(sock_fd,sri.sinfo_assoc_id,&laddrs);
		printf("The sctp_getladdrs return value is %d\n",ret_value);
		// test the sctp_getladdrs function - end
		// test the sctp_getpaddrs function - start
		ret_value = sctp_getpaddrs(sock_fd,sri.sinfo_assoc_id,&paddrs);
		printf("The sctp_getpaddrs return value is %d\n",ret_value);
		// test the sctp_getpaddrs function - end
		//========================================================================
		if (msg_flags & MSG_NOTIFICATION) {	// 表示收到一個事件通告,而非一個資料
			snp = (union sctp_notification *) readbuf;
			switch (snp->sn_header.sn_type) {
				case SCTP_SHUTDOWN_EVENT:
					sse = &snp->sn_shutdown_event;
					printf("SCTP_SHUTDOWN_EVENT: assoc=0x%x\n",(uint32_t) sse->sse_assoc_id);
					break;
				case SCTP_ASSOC_CHANGE:
					sac = &snp->sn_assoc_change;
					switch (sac->sac_state) {
						case SCTP_COMM_UP:
							printf("COMMUNICATION UP\n");
							break;
						case SCTP_COMM_LOST:
							printf("COMMUNICATION LOST\n");
							break;
						case SCTP_RESTART:
							printf("RESTART\n");
							break;
						case SCTP_SHUTDOWN_COMP:
							printf("SHUTDOWN COMPLETE\n");
							break;
						case SCTP_CANT_STR_ASSOC:
							printf("CAN'T START ASSOC\n");
							break;
						default:
							printf("UNKNOW\n");
							break;
					}
					break;
				case SCTP_PEER_ADDR_CHANGE:
					spc = &snp->sn_paddr_change;
					switch(spc->spc_state) {
						case SCTP_ADDR_AVAILABLE:
							str = "ADDRESS AVAILABLE";
							break;
						case SCTP_ADDR_UNREACHABLE:
							str = "ADDRESS UNREACHABLE";
							break;
						case SCTP_ADDR_REMOVED:
							str = "ADDRESS REMOVED";
							break;
						case SCTP_ADDR_ADDED:
							str = "ADDRESS ADDED";
							break;
						case SCTP_ADDR_MADE_PRIM:
							str = "ADDRESS MADE PRIMARY";
							break;
						case SCTP_ADDR_CONFIRMED:
							str = "ADDRESS MADE CONFIRMED";
							break;
						default:
							str = "UNKNOW";
							break;
					}
					printf("SCTP_PEER_ADDR_CHANGE: %s\n",str);
					break;
				case SCTP_REMOTE_ERROR:
					sre = &snp->sn_remote_error;
					printf("SCTP_REMOTE_ERROR\n");
					break;
				case SCTP_SEND_FAILED:
					ssf = &snp->sn_send_failed;
					printf("SCTP_SEND_FAILED\n");
					break;
#ifdef UN_MOD
				case SCTP_ADAPTATION_INDICATION:
					ae = &snp->sn_adaptation_event;
					printf("SCTP_ADAPTION_INDICATION\n");
					break;
#else
				case SCTP_ADAPTION_INDICATION:
					ae = &snp->sn_adaption_event;
					printf("SCTP_ADAPTION_INDICATION\n");
					break;
#endif
				case SCTP_PARTIAL_DELIVERY_EVENT:
					pdapi = &snp->sn_pdapi_event;
					if (pdapi->pdapi_indication == SCTP_PARTIAL_DELIVERY_ABORTED)
						printf("SCTP_PARTIAL_DELIEVERY_ABORTED\n");
					else
						printf("Unknown SCTP_PARTIAL_DELIVERY_EVENT\n");
					break;
				default:
					printf("UNKNOWN notification\n");
					break;
			}
			continue;
		}
		printf("%s",readbuf);
		ret_value = sctp_sendmsg(sock_fd,readbuf,rd_sz,(struct sockaddr *) &cliaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0);
		if (ret_value == -1) {
			printf("sctp_sendmsg error\n");
			exit(-1);
		}

	}

	return 0;
}
Ejemplo n.º 2
0
void check_notification(int sock_fd, char *recvline, int rd_len)
{
	union sctp_notification *snp;
	struct sctp_assoc_change *sac;
	struct sockaddr_storage *sa1, *sar;
	int	num_rem, num_loc;

	snp = (union sctp_notification *)recvline;
	if (snp->sn_header.sn_type == SCTP_ASSOC_CHANGE) {
		sac = &snp->sn_assoc_change;
		if ((sac->sac_state == SCTP_ASSOC_CHANGE) ||
				(sac->sac_state == SCTP_RESTART)) {
			num_rem = sctp_getpaddrs(sock_fd, sac->sac_assoc_id,
					&sar);
			printf("There are %d remote addresses and they"
			       " are: \n", num_rem);
			sctp_print_addresses(sar, num_rem);
			sctp_freepaddrs(sar);

			num_loc = sctp_getladdrs(sock_fd, sac->sac_assoc_id,
					&sal);
			printf("There are %d local addresses and they are: \n",
					num_loc);
			sctp_print_addresses(sal, num_loc);
			sctp_freepaddrs(sal);
		}
	}
}
Ejemplo n.º 3
0
static void printLocalAddresses(int socket)
{
  struct sockaddr* addresses;
  int retVal;
  if ((retVal = sctp_getladdrs(socket, 0, &addresses)) < 0)
  {
    printf("printLocalAddresses sctp_getladdrs error\n");
  }
  else
  {
    int i;
    for (i = 0; i < retVal; ++i)
    {
      struct AddrPortStrings addrPortStrings;
      socklen_t addressSize = 0;
      if (addresses[i].sa_family == AF_INET)
      {
        addressSize = sizeof(struct sockaddr_in);
      }
      else if (addresses[i].sa_family == AF_INET6)
      {
        addressSize = sizeof(struct sockaddr_in6);
      }
      if (addressToNameAndPort(&addresses[i], addressSize, &addrPortStrings) == 0)
      {
        printf("local address %d %s:%s\n", i, addrPortStrings.addrString, addrPortStrings.portString);
      }
    }
    sctp_freeladdrs(addresses);
  }
}
Ejemplo n.º 4
0
static PyObject* getladdrs(PyObject* dummy, PyObject* args)
{
	PyObject* ret = 0;
	int fd;
	int assoc_id;
	struct sockaddr* saddrs;
	int count;
	int x;
	char addr[256];

	if (! PyArg_ParseTuple(args, "ii", &fd, &assoc_id)) {
		return ret;
	}

	count = sctp_getladdrs(fd, assoc_id, &saddrs);

	if (count < 0) {
		PyErr_SetFromErrno(PyExc_IOError);
	} else {
		if (count == 0) {
			saddrs = 0;
		}
		
		ret = PyTuple_New(count);
		char *p = (char*) saddrs;
	
		for(x = 0; x < count; ++x) {
			int len;
			int family;
			int port;
			PyObject* oaddr;

			if (from_sockaddr((struct sockaddr*) p, &family, &len, &port, 
										addr, sizeof(addr))) {
				oaddr = PyTuple_New(2);
				PyTuple_SetItem(oaddr, 0, PyString_FromString(addr));
				PyTuple_SetItem(oaddr, 1, PyInt_FromLong(port));
				PyTuple_SetItem(ret, x, oaddr);
			} else {
				// something's wrong; not safe to continue
				break;
			}
			
			p += len;
		}

		sctp_freeladdrs(saddrs);

		// If something went wrong, the remaining expected addresses will be set to None.
		for(; x < count; ++x) {
			PyTuple_SetItem(ret, x, Py_None);
			Py_INCREF(Py_None);

		}
	}

	return ret;
}
Ejemplo n.º 5
0
int SctpSocket::getladdrs(sctp_assoc_t id,std::list<std::string>& vec)
{
	struct sockaddr *p = NULL;
	int n = sctp_getladdrs(GetSocket(), id, &p);
	if (!n || n == -1)
	{
		Handler().LogError(this, "SctpSocket", -1, "sctp_getladdrs failed", LOG_LEVEL_WARNING);
		return n;
	}
	for (int i = 0; i < n; i++)
	{
		vec.push_back(Utility::Sa2String(&p[i]));
	}
	sctp_freeladdrs(p);
	return n;
}
Ejemplo n.º 6
0
int
ACE_SOCK_SEQPACK_Association::get_local_addrs (ACE_INET_Addr *addrs, size_t &size) const
{
  ACE_TRACE ("ACE_SOCK_SEQPACK_Association::get_local_addrs");

#if defined (ACE_HAS_LKSCTP)
  /*
    The size of ACE_INET_Addr must be large enough to hold the number of
    local addresses on the machine.  If the array is too small, the function
    will only return the number of addresses that will fit.  If the array is
    too large, the 'size' parameter will be modified to indicate the number
    of addrs.

    We will call sctp_getladdrs() which accepts 3 parameters
    1. a socket fd
    2. a sctp association_id which will be ignored since we are using
       tcp sockets
    3. a pointer to sockaddr

    lksctp/draft will allocate memory and we are responsible for freeing
    it by calling sctp_freeladdrs().
  */

  sockaddr_in *si = 0;
  sockaddr *laddrs = 0;
  int err = 0;
  size_t len = 0;

#ifndef ACE_HAS_VOID_PTR_SCTP_GETLADDRS
  err = sctp_getladdrs(this->get_handle(), 0, &laddrs);
#else
  err = sctp_getladdrs(this->get_handle(), 0, reinterpret_cast<void**>(&laddrs));
#endif /* ACE_HAS_VOID_PTR_SCTP_GETPADDRS */
  if (err > 0)
  {
    len = err;
    // check to see if we have more addresses than we have
    // space in our ACE_INET_Addr array
    if (len > size)
    {
      // since our array is too small, we will only copy the first
      // few that fit
      len = size;
    }

    for (size_t i = 0; i < len; i++)
    {
      // first we cast the sockaddr to sockaddr_in
      // since we only support ipv4 at this time.
      si = (sockaddr_in *) (&(laddrs[i]));

      // now we fillup the ace_inet_addr array
      addrs[i].set_addr(si, sizeof(sockaddr_in));
      addrs[i].set_type(si->sin_family);
      addrs[i].set_size(sizeof(sockaddr_in));
    }
  }
  else /* err < 0 */
  {
    // sctp_getladdrs will return -1 on error
    return -1;
  }

  // indicate the num of addrs returned to the calling function
  size = len;

  // make sure we free the struct using the system function
  sctp_freeladdrs(laddrs);

#else

  /*
    We will be calling ACE_OS::getsockname, which accepts (and
    potentially modifies) two reference parameters:

    1.  a sockaddr_in* that points to a buffer
    2.  an int* that points to the size of this buffer

    The OpenSS7 implementation of SCTP copies an array of ipv4
    sockaddr_in into the buffer.  Then, if the size of the buffer is
    greater than the size used, the size parameter is reduced
    accordingly.

  */

  // The array of sockaddr_in will be stored in an ACE_Auto_Array_Ptr,
  // which causes dynamically-allocated memory to be released as soon
  // as the ACE_Auto_Array_Ptr goes out of scope.
  ACE_Auto_Array_Ptr<sockaddr_in> addr_structs;

  // Allocate memory for this array.  Return -1 if the memory cannot
  // be allocated.  (This activity requires a temporary variable---a
  // bare sockaddr_in* --- because ACE_NEW_RETURN cannot act directory on
  // an ACE_Auto_Array_Ptr.)
  {
    sockaddr_in *addr_structs_bootstrap = 0;
#if defined(ACE_HAS_ALLOC_HOOKS)
    ACE_ALLOCATOR_RETURN (addr_structs_bootstrap, static_cast<sockaddr_in*>(ACE_Allocator::instance()->malloc(sizeof(sockaddr_in) * size)), -1);
#else
    ACE_NEW_RETURN (addr_structs_bootstrap, sockaddr_in[size], -1);
#endif
    addr_structs.reset(addr_structs_bootstrap);
  }

  // Physical size of this array is its logical size multiplied by
  // the physical size of one of its elements.
  size_t physical_size = size * sizeof(sockaddr_in);

  /* Clear the array */
  ACE_OS::memset(addr_structs.get(),
                 0,
                 physical_size);

  /*
  ** Populate the array with real values from the getsockname system
  ** call.  addr_structs is modified, and name_size is modified to contain
  ** the number of bytes written to addr_structs.
  ** Use name_size to get the data types right across the call.
  */
  int name_size = static_cast<int> (physical_size);
  if (ACE_OS::getsockname (this->get_handle (),
                           reinterpret_cast<sockaddr *> (addr_structs.get()),
                           &name_size) == -1)
    return -1;

  /* Calculate the NEW physical size of the array */
  name_size /= sizeof (sockaddr_in);
  size = static_cast<size_t> (name_size);

  /* Copy each sockaddr_in to the address structure of an ACE_Addr from
     the passed-in array */
  const int addrlen (static_cast<int> (sizeof (sockaddr_in)));
  for (int i = 0; i < name_size; ++i)
    {
      addrs[i].set_addr (&(addr_structs[i]), addrlen);
      addrs[i].set_type (addr_structs[i].sin_family);
      addrs[i].set_size (addrlen);
    }
#endif /* ACE_HAS_LKSCTP */
  return 0;
}
Ejemplo n.º 7
0
void
process_notification(int fd, char *notify_buf)
{
   char buf[256];
   union sctp_notification *snp;
   struct sctp_assoc_change *sac;
   struct sctp_paddr_change *spc;
   struct sctp_remote_error *sre;
   struct sctp_send_failed *ssf;
   struct sctp_shutdown_event *sse;
   struct sctp_pdapi_event *pdapi;
   struct sockaddr_in *msin;
   struct sockaddr_in6 *msin6;
   const char *str;
   struct sockaddr *sal;
   int num_loc;

   snp = (union sctp_notification *)notify_buf;
   switch(snp->sn_header.sn_type) {
   case SCTP_ASSOC_CHANGE:
      sac = &snp->sn_assoc_change;
      switch(sac->sac_state) {
      case SCTP_COMM_UP:
         str = "COMMUNICATION UP";
         break;
      case SCTP_COMM_LOST:
         str = "COMMUNICATION LOST";
         break;
      case SCTP_RESTART:
              str = "RESTART";
         break;
      case SCTP_SHUTDOWN_COMP:
         str = "SHUTDOWN COMPLETE";
         break;
      case SCTP_CANT_STR_ASSOC:
         str = "CANT START ASSOC";
         break;
      default:
         str = "UNKNOWN";
      } /* end switch(sac->sac_state) */
      printf("SCTP_ASSOC_CHANGE: %s, assoc=%xh\n", str, (uint32_t)sac->sac_assoc_id);
      
      if((sac->sac_state == SCTP_COMM_UP) ||
           (sac->sac_state == SCTP_RESTART)) {
              assoc_id = sac->sac_assoc_id;
           num_rem = sctp_getpaddrs(fd, sac->sac_assoc_id, &sar);
            printf("There are %d remote addresses and they are:\n", num_rem);
            print_addresses(sar, num_rem);

            num_loc = sctp_getladdrs(fd,sac->sac_assoc_id, &sal);
            printf("There are %d local addresses and they are:\n", num_loc);
            print_addresses(sal, num_loc);
            sctp_freeladdrs(sal);
        }
      break;
   case SCTP_PEER_ADDR_CHANGE:
      spc = &snp->sn_paddr_change;
      switch(spc->spc_state) {
      case SCTP_ADDR_REACHABLE:
         str = "ADDRESS REACHABLE";
         break;
      case SCTP_ADDR_UNREACHABLE:
         str = "ADDRESS UNAVAILABLE";
         break;
      case SCTP_ADDR_REMOVED:
         str = "ADDRESS REMOVED";
         break;
      case SCTP_ADDR_ADDED:
         str = "ADDRESS ADDED";
         break;
      case SCTP_ADDR_MADE_PRIM:
         str = "ADDRESS MADE PRIMARY";
         break;
      case SCTP_ADDR_CONFIRMED:
         str = "ADDRESS CONFIRMED";
         break;
      default:
         str = "UNKNOWN";
      } /* end switch */
      msin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
      if (msin6->sin6_family == AF_INET6) {
         inet_ntop(AF_INET6, (char*)&msin6->sin6_addr, buf, sizeof(buf));
      } else {
         msin = (struct sockaddr_in *)&spc->spc_aaddr;
         inet_ntop(AF_INET, (char*)&msin->sin_addr, buf, sizeof(buf));
      }
      printf("SCTP_PEER_ADDR_CHANGE: %s (%d), addr=%s, assoc=%xh\n", str, spc->spc_state, buf, (uint32_t)spc->spc_assoc_id);
      break;
   case SCTP_REMOTE_ERROR:
      sre = &snp->sn_remote_error;
      printf("SCTP_REMOTE_ERROR: assoc=%xh\n", (uint32_t)sre->sre_assoc_id);
      break;
   case SCTP_SEND_FAILED:
      ssf = &snp->sn_send_failed;
      printf("SCTP_SEND_FAILED: assoc=%xh\n", (uint32_t)ssf->ssf_assoc_id);
      break;
   case SCTP_ADAPTION_INDICATION:
     {
       struct sctp_adaption_event *ae;
       ae = &snp->sn_adaption_event;
       printf("SCTP_adaption_indication:0x%x\n", (unsigned int)ae->sai_adaption_ind);
     }
     break;
   case SCTP_PARTIAL_DELIVERY_EVENT:
     {
       pdapi = &snp->sn_pdapi_event;
       if(pdapi->pdapi_indication == SCTP_PARTIAL_DELIVERY_ABORTED){
          printf("SCTP_PD-API ABORTED\n");
       } else {
          printf("Unknown SCTP_PD-API EVENT %x\n", pdapi->pdapi_indication);
       }
     }
     break;
   case SCTP_SHUTDOWN_EVENT:
        sse = &snp->sn_shutdown_event;
      printf("SCTP_SHUTDOWN_EVENT: assoc=%xh\n", (uint32_t)sse->sse_assoc_id);
      break;
   default:
      printf("Unknown notification event type=%xh\n",  snp->sn_header.sn_type);
   }
}
Ejemplo n.º 8
0
int
main(int argc, char *argv[])
{
        int error;
	socklen_t len;
	int sk,lstn_sk,clnt_sk,acpt_sk,pf_class,sk1;
	struct msghdr outmessage;
        struct msghdr inmessage;
        char *message = "hello, world!\n";
        struct iovec iov;
        struct iovec iov_rcv;
        struct sctp_sndrcvinfo *sinfo;
        int msg_count;
        char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
        struct cmsghdr *cmsg;
        struct iovec out_iov;
        char * buffer_snd;
        char * buffer_rcv;
	char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))];
	struct sockaddr *laddrs, *paddrs;

        struct sockaddr_in conn_addr,lstn_addr,acpt_addr;
	struct sockaddr_in *addr;

	/* Rather than fflush() throughout the code, set stdout to
         * be unbuffered.
         */
        setvbuf(stdout, NULL, _IONBF, 0);
        setvbuf(stderr, NULL, _IONBF, 0);

        pf_class = PF_INET;

        sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);

	/*Creating a regular socket*/
	clnt_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);

	/*Creating a listen socket*/
        lstn_sk = test_socket(pf_class, SOCK_STREAM, IPPROTO_SCTP);

	conn_addr.sin_family = AF_INET;
        conn_addr.sin_addr.s_addr = SCTP_IP_LOOPBACK;
        conn_addr.sin_port = htons(SCTP_TESTPORT_1);

	lstn_addr.sin_family = AF_INET;
        lstn_addr.sin_addr.s_addr = SCTP_IP_LOOPBACK;
        lstn_addr.sin_port = htons(SCTP_TESTPORT_1);

	/*Binding the listen socket*/
	test_bind(lstn_sk, (struct sockaddr *) &lstn_addr, sizeof(lstn_addr));

	/*Listening many sockets as we are calling too many connect here*/
	test_listen(lstn_sk, 1);

	len = sizeof(struct sockaddr_in);

	test_connect(clnt_sk, (struct sockaddr *) &conn_addr, len);

	acpt_sk = test_accept(lstn_sk, (struct sockaddr *) &acpt_addr, &len);

	memset(&inmessage, 0, sizeof(inmessage));
        buffer_rcv = malloc(REALLY_BIG);

        iov_rcv.iov_base = buffer_rcv;
        iov_rcv.iov_len = REALLY_BIG;
        inmessage.msg_iov = &iov_rcv;
        inmessage.msg_iovlen = 1;
        inmessage.msg_control = incmsg;
        inmessage.msg_controllen = sizeof(incmsg);

        msg_count = strlen(message) + 1;

	memset(&outmessage, 0, sizeof(outmessage));
        buffer_snd = malloc(REALLY_BIG);

        outmessage.msg_name = &lstn_addr;
        outmessage.msg_namelen = sizeof(lstn_addr);
        outmessage.msg_iov = &out_iov;
        outmessage.msg_iovlen = 1;
        outmessage.msg_control = outcmsg;
        outmessage.msg_controllen = sizeof(outcmsg);
        outmessage.msg_flags = 0;

        cmsg = CMSG_FIRSTHDR(&outmessage);
        cmsg->cmsg_level = IPPROTO_SCTP;
        cmsg->cmsg_type = SCTP_SNDRCV;
        cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
        outmessage.msg_controllen = cmsg->cmsg_len;
        sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
        memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));

        iov.iov_base = buffer_snd;
	iov.iov_len = REALLY_BIG;
        outmessage.msg_iov->iov_base = message;

        outmessage.msg_iov->iov_len = msg_count;
	test_sendmsg(clnt_sk, &outmessage, MSG_NOSIGNAL, msg_count);

	test_recvmsg(acpt_sk, &inmessage, MSG_NOSIGNAL);

	/*sctp_getladdrs() TEST1: Bad socket descriptor, EBADF Expected error*/
	error = sctp_getladdrs(-1, 0, &laddrs);
	if (error != -1 || errno != EBADF)
		tst_brkm(TBROK, NULL, "sctp_getladdrs with a bad socket "
			 "descriptor error:%d, errno:%d", error, errno);

	tst_resm(TPASS, "sctp_getladdrs() with a bad socket descriptor - "
		 "EBADF");

	/*sctp_getladdrs() TEST2: Invalid socket, ENOTSOCK Expected error*/
	error = sctp_getladdrs(0, 0, &laddrs);
	if (error != -1 || errno != ENOTSOCK)
		tst_brkm(TBROK, NULL, "sctp_getladdrs with invalid socket "
			 "error:%d, errno:%d", error, errno);

	tst_resm(TPASS, "sctp_getladdrs() with invalid socket - ENOTSOCK");

	/*sctp_getladdrs() TEST3: socket of different protocol
	EOPNOTSUPP Expected error*/
        sk1 = socket(pf_class, SOCK_STREAM, IPPROTO_IP);
	error = sctp_getladdrs(sk1, 0, &laddrs);
	if (error != -1 || errno != EOPNOTSUPP)
		tst_brkm(TBROK, NULL, "sctp_getladdrs with socket of "
			 "different protocol error:%d, errno:%d", error, errno);

	tst_resm(TPASS, "sctp_getladdrs() with socket of different protocol - "
		 "EOPNOTSUPP");

	/*sctp_getladdrs() TEST4: Getting the local addresses*/
	error = sctp_getladdrs(lstn_sk, 0, &laddrs);
	if (error < 0)
		tst_brkm(TBROK, NULL, "sctp_getladdrs with valid socket "
			 "error:%d, errno:%d", error, errno);

	addr = (struct sockaddr_in *)laddrs;
	if (addr->sin_port != lstn_addr.sin_port ||
	    addr->sin_family != lstn_addr.sin_family ||
	    addr->sin_addr.s_addr != lstn_addr.sin_addr.s_addr)
		tst_brkm(TBROK, NULL, "sctp_getladdrs comparision failed");

	tst_resm(TPASS, "sctp_getladdrs() - SUCCESS");

	/*sctp_freealddrs() TEST5: freeing the local address*/
	if ((sctp_freeladdrs(laddrs)) < 0)
		tst_brkm(TBROK, NULL, "sctp_freeladdrs "
			 "error:%d, errno:%d", error, errno);

	tst_resm(TPASS, "sctp_freeladdrs() - SUCCESS");

	/*sctp_getpaddrs() TEST6: Bad socket descriptor, EBADF Expected error*/
	error = sctp_getpaddrs(-1, 0, &paddrs);
	if (error != -1 || errno != EBADF)
		tst_brkm(TBROK, NULL, "sctp_getpaddrs with a bad socket "
			 "descriptor error:%d, errno:%d", error, errno);

	tst_resm(TPASS, "sctp_getpaddrs() with a bad socket descriptor - "
		 "EBADF");

	/*sctp_getpaddrs() TEST7: Invalid socket, ENOTSOCK Expected error*/
	error = sctp_getpaddrs(0, 0, &paddrs);
	if (error != -1 || errno != ENOTSOCK)
		tst_brkm(TBROK, NULL, "sctp_getpaddrs with invalid socket "
			 "error:%d, errno:%d", error, errno);

	tst_resm(TPASS, "sctp_getpaddrs() with invalid socket - ENOTSOCK");

	/*sctp_getpaddrs() TEST8: socket of different protocol
	EOPNOTSUPP Expected error*/
	error = sctp_getpaddrs(sk1, 0, &laddrs);
	if (error != -1 || errno != EOPNOTSUPP)
		tst_brkm(TBROK, NULL, "sctp_getpaddrs with socket of "
			 "different protocol error:%d, errno:%d", error, errno);

	tst_resm(TPASS, "sctp_getpaddrs() with socket of different protocol - "
		 "EOPNOTSUPP");

	/*sctp_getpaddrs() TEST9: Getting the peer addresses*/
	error = sctp_getpaddrs(acpt_sk, 0, &paddrs);
	if (error < 0)
		tst_brkm(TBROK, NULL, "sctp_getpaddrs with valid socket "
			 "error:%d, errno:%d", error, errno);

	addr = (struct sockaddr_in *)paddrs;
	if (addr->sin_port != acpt_addr.sin_port ||
            addr->sin_family != acpt_addr.sin_family ||
            addr->sin_addr.s_addr != acpt_addr.sin_addr.s_addr)
		tst_brkm(TBROK, NULL, "sctp_getpaddrs comparision failed");

	tst_resm(TPASS, "sctp_getpaddrs() - SUCCESS");

	/*sctp_freeapddrs() TEST10: freeing the peer address*/
	if ((sctp_freepaddrs(paddrs)) < 0)
		tst_brkm(TBROK, NULL, "sctp_freepaddrs "
			 "error:%d, errno:%d", error, errno);

	tst_resm(TPASS, "sctp_freepaddrs() - SUCCESS");

	close(clnt_sk);

	tst_exit();
}
Ejemplo n.º 9
0
int main(int argc,char **argv)
{
	int echo_to_all = 0;

	int ret_value;
	int sock_fd;
	int msg_flags;	// 記錄要傳送訊息時的相關設定
	char readbuf[BUFFERSIZE];
	struct sockaddr_in servaddr,cliaddr;
	struct sctp_sndrcvinfo sri;	// 記錄send, recv, association的相關資訊
	struct sctp_event_subscribe evnts;
	int stream_increment = 1;
	socklen_t len;
	size_t rd_sz;	// size_t指的就是unsigned long:rd_sz表示recv,send-size
	struct sockaddr *addrs;
	int addrcnt;
	int temp_step;

	if (argc == 2) {
		// 把字串轉換成數字
		stream_increment = atoi(argv[1]);
	}

	// 建立socket的型態為SCTP的one-to-many的型態
	sock_fd = socket(AF_INET,SOCK_SEQPACKET,IPPROTO_SCTP);
	if (sock_fd == -1) {
		printf("socket error\n");
		exit(-1);
	}
	// 初始化server address的設定
	memset(&servaddr,0,sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(SERV_PORT);
	
	// 把socket與所建立的address綁在一起
	ret_value = bind(sock_fd,(struct sockaddr *) &servaddr,sizeof(servaddr));
	if (ret_value == -1) {
		printf("bind error\n");
		exit(-1);
	}

	// Set up for notifications of internet
	bzero(&evnts,sizeof(evnts));
	evnts.sctp_data_io_event = 1;	// 使得sctp_sndrcvinfo可以伴隨資料傳送過來
	ret_value = setsockopt(sock_fd,IPPROTO_SCTP,SCTP_EVENTS,&evnts,sizeof(evnts));
	if (ret_value == -1) {
		printf("setsockopt error\n");
		exit(-1);
	}

	// 設定等待多少個client端連線
	ret_value = listen(sock_fd,LISTENQ);
	if (ret_value == -1) {
		printf("listen error\n");
		exit(-1);
	}
	printf("start wait...\n");

	for (;;) {
		len = sizeof(struct sockaddr_in);
		// 等待client端連線
		rd_sz = sctp_recvmsg(sock_fd,readbuf,sizeof(readbuf),(struct sockaddr *) &cliaddr,&len,&sri,&msg_flags);

		// 分別印出local與peer端的address - start
		if ((addrcnt = sctp_getladdrs(sock_fd,sri.sinfo_assoc_id,&addrs))==-1) {
			printf("sctp_getladdrs error\n");
			exit(-1);
		}
		printf("the local has %d address(es)\n",addrcnt);
		for (temp_step=0;temp_step<addrcnt;temp_step++) {
			printf("the address is %s\n",inet_ntoa(((struct sockaddr_in *) addrs+temp_step)->sin_addr));
		}
		sctp_freeladdrs(addrs);
		if ((addrcnt = sctp_getpaddrs(sock_fd,sri.sinfo_assoc_id,&addrs))==-1) {
			printf("sctp_getpaddrs error\n");
			exit(-1);
		}
		printf("the peer has %d address(es)\n",addrcnt);
		for (temp_step=0;temp_step<addrcnt;temp_step++) {
			printf("the address is %s\n",inet_ntoa(((struct sockaddr_in *) addrs+temp_step)->sin_addr));
		}
		sctp_freepaddrs(addrs);
		// 分別印出local與peer端的address - start

		if (stream_increment) {
			sri.sinfo_stream++;
			if (sri.sinfo_stream >= 100) {
				sri.sinfo_stream = 0;
			}
		}
		// 把接收到的資料回送給client
		ret_value = sctp_sendmsg(sock_fd,readbuf,rd_sz,(struct sockaddr *) &cliaddr,len,sri.sinfo_ppid,sri.sinfo_flags,sri.sinfo_stream,0,0);
		if (ret_value == -1) {
			printf("sctp_sendmsg error\n");
			exit(-1);
		}
	}
	return 0;
}
int
initRegistrar() {
    struct sockaddr *addrs;
    struct sockaddr *addr;
    struct sockaddr_in6 *pin6;
    struct sockaddr_in *pin4;
    char *offset;
    char addrBuf[INET6_ADDRSTRLEN + 1];
    struct timeval now;
    unsigned int seed;
    int addrCnt = 0;
    int i;

    logDebug("initializing own registrar");

    /* init own id */
	if (ownId == 0) {
		getTime(&now);
		seed = now.tv_sec | now.tv_usec;
		srand(seed);
		ownId = (uint32) rand();
		logDebug("server id is: 0x%08x", ownId);
	}

    this = registrarServerNew(ownId);
    registrarServerListAddServer(this);
    this->rsEnrpPort = enrpLocalPort;
    this->rsAsapPort = asapLocalPort;

    /* don't need a timeout timer for us */
    timerStop(this->rsLastHeardTimeout);
    timerDelete(this->rsLastHeardTimeout);
    this->rsLastHeardTimeout = NULL;
    this->rsLastHeardTimeoutCnt = 0;

    /* parse enrp sctp addrs */
    if ((addrCnt = sctp_getladdrs(enrpSctpFd, 0, &addrs)) > 0) {
        offset = (char *) addrs;
        logDebug("enrp sctp: we are locally bound to %d adresses", addrCnt);
        for (i = 0; i < addrCnt && i < MAX_ADDR_CNT; i++) {
            addr = (struct sockaddr *) offset;
            pin4 = (struct sockaddr_in  *) offset;
            pin6 = (struct sockaddr_in6 *) offset;

            if (addr->sa_family == AF_INET) {
                if (!useLoopback && pin4->sin_addr.s_addr == INADDR_LOOPBACK)
                    continue;

                this->rsEnrpAddr[i].type = AF_INET;
                memcpy(&this->rsEnrpAddr[i].addr.in4, &pin4->sin_addr, sizeof(struct in_addr));
                logDebug("addrs[%d]: AF_INET  %s", i, inet_ntop(AF_INET, (void *) &pin4->sin_addr, addrBuf, INET6_ADDRSTRLEN));
                offset += sizeof(struct sockaddr_in);
            } else if (addr->sa_family == AF_INET6) {
                if (!useLoopback && memcmp((const void *) &pin6->sin6_addr, (const void *) &in6addr_loopback, sizeof(struct in6_addr)) == 0)
                    continue;

                this->rsEnrpAddr[i].type = AF_INET6;
                memcpy(&this->rsEnrpAddr[i].addr.in6, &pin6->sin6_addr, sizeof(struct in6_addr));
                logDebug("addrs[%d]: AF_INET6 %s", i, inet_ntop(AF_INET6, (void *) &pin6->sin6_addr, addrBuf, INET6_ADDRSTRLEN));
                offset += sizeof(struct sockaddr_in6);
            }
        }

        sctp_freeladdrs(addrs);
    }

    /* parse asap sctp addrs */
    if ((addrCnt = sctp_getladdrs(asapSctpFd, 0, &addrs)) > 0) {
        offset = (char *) addrs;
        logDebug("asap sctp: we are locally bound to %d adresses", addrCnt);
        for (i = 0; i < addrCnt && i < MAX_ADDR_CNT; i++) {
            addr = (struct sockaddr *) offset;
            pin4 = (struct sockaddr_in  *) offset;
            pin6 = (struct sockaddr_in6 *) offset;

            if (addr->sa_family == AF_INET) {
                if (!useLoopback && pin4->sin_addr.s_addr == INADDR_LOOPBACK)
                    continue;

                this->rsAsapAddr[i].type = AF_INET;
                memcpy(&this->rsAsapAddr[i].addr.in4, &pin4->sin_addr, sizeof(struct in_addr));
                logDebug("addrs[%d]: AF_INET  %s", i, inet_ntop(AF_INET, (void *) &pin4->sin_addr, addrBuf, INET6_ADDRSTRLEN));
                offset += sizeof(struct sockaddr_in);
            } else if (addr->sa_family == AF_INET6) {
                if (!useLoopback && memcmp((const void *) &pin6->sin6_addr, (const void *) &in6addr_loopback, sizeof(struct in6_addr)) == 0)
                    continue;

                this->rsAsapAddr[i].type = AF_INET6;
                memcpy(&this->rsAsapAddr[i].addr.in6, &pin6->sin6_addr, sizeof(struct in6_addr));
                logDebug("addrs[%d]: AF_INET6 %s", i, inet_ntop(AF_INET6, (void *) &pin6->sin6_addr, addrBuf, INET6_ADDRSTRLEN));
                offset += sizeof(struct sockaddr_in6);
            }
        }

        sctp_freeladdrs(addrs);
    }

    return 1;
}