Beispiel #1
0
void
handle_socket_error(osi_socket so)
{
    struct msghdr msg;
    struct cmsghdr *cmsg;
    struct sock_extended_err *err;
    struct sockaddr_in addr;
    struct sockaddr *offender;
    char *controlmsgbuf;
    int code;
    struct socket *sop = (struct socket *)so;

    if (!(controlmsgbuf=rxi_Alloc(256)))
	return;
    msg.msg_name = &addr;
    msg.msg_namelen = sizeof(addr);
    msg.msg_control = controlmsgbuf;
    msg.msg_controllen = 256;
    msg.msg_flags = 0;

    code = kernel_recvmsg(sop, &msg, NULL, 0, 0,
			  MSG_ERRQUEUE|MSG_DONTWAIT|MSG_TRUNC);

    if (code < 0 || !(msg.msg_flags & MSG_ERRQUEUE))
	goto out;

    for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
	if (CMSG_OK(&msg, cmsg) && cmsg->cmsg_level == SOL_IP &&
	    cmsg->cmsg_type == IP_RECVERR)
	    break;
    }
    if (!cmsg)
	goto out;
    err = CMSG_DATA(cmsg);
    offender = SO_EE_OFFENDER(err);
    
    if (offender->sa_family != AF_INET)
       goto out;

    memcpy(&addr, offender, sizeof(addr));

    if (err->ee_origin == SO_EE_ORIGIN_ICMP &&
	err->ee_type == ICMP_DEST_UNREACH &&
	err->ee_code == ICMP_FRAG_NEEDED) {
	rxi_SetPeerMtu(NULL, ntohl(addr.sin_addr.s_addr), ntohs(addr.sin_port),
		       err->ee_info);
    }
    /* other DEST_UNREACH's and TIME_EXCEEDED should be dealt with too */

out:
    rxi_Free(controlmsgbuf, 256);
    return;
}
Beispiel #2
0
/**
 * return:
 *      0 if no error
 *      1 if TTL exceeded
 *     >1 if other icmp-like error
 */
static int
handleRecvErrSEE(struct sock_extended_err *see,
                 int returnttl,
                 const char *tos,
                 double lastPingTime)
{
	int isicmp = 0;
        int ret = 0;

	if (!see) {
		fprintf(stderr, "%s: Error, but no error info\n", argv0);
		return ret;
	}

	/* print "From ...: */
        if (see->ee_origin == SO_EE_ORIGIN_LOCAL) {
		printf("From local system: ");
	} else {
		struct sockaddr *offender = SO_EE_OFFENDER(see);
		char abuf[NI_MAXHOST];
		int err;
		
		if (offender->sa_family == AF_UNSPEC) {
                        if (!options.traceroute) { printf("From "); }
                        printf("<unknown>: ");
		} else if ((err = getnameinfo(offender,
					      sizeof(struct sockaddr_storage),
					      abuf, NI_MAXHOST,
					      NULL, 0,
					      NI_NUMERICHOST))) {
			fprintf(stderr, "%s: getnameinfo(): %s\n",
				argv0, gai_strerror(err));
                        if (!options.traceroute) { printf("From "); }
                        printf("<unknown>");
                        if (tos) {
                                printf(" %s", tos);
                        }
                        if (returnttl > 0) {
                                printf(" ttl=%d", returnttl);
                        }
                        printf(": ");
		} else {
                        if (!options.traceroute) { printf("From "); }
                        printf("%s", abuf);
                        if (tos) {
                                printf(" %s", tos);
                        }
                        if (returnttl > 0) {
                                printf(" ttl=%d", returnttl);
                        }
                        if (lastPingTime) {
                                printf(" time=%.2f ms",
                                       1000*(clock_get_dbl()-lastPingTime));
                        }
                        printf(": ");
		}
	}
	
	if (see->ee_origin == SO_EE_ORIGIN_ICMP6
	    || see->ee_origin == SO_EE_ORIGIN_ICMP) {
		isicmp = 1;
	}

	/* Print error message */
	switch (see->ee_errno) {
	case ECONNREFUSED:
		printf("Port closed");
                ret = 2;
		break;
	case EMSGSIZE:
		printf("PMTU %d", see->ee_info);
                ret = 2;
		break;
	case EPROTO:
		printf("Protocol error");
                ret = 2;
		break;
	case ENETUNREACH:
		printf("Network unreachable");
                ret = 2;
		break;
	case EACCES:
		printf("Access denied");
                ret = 2;
		break;
	case EHOSTUNREACH:
		if (isicmp && see->ee_type == 11 && see->ee_code == 0) {
                        printf("TTL exceeded");
                        ret = 1;
                } else {
			printf("Host unreachable");
                        ret = 2;
		}
		break;
	default:
		printf("%s", strerror(see->ee_errno));
                ret = 2;
		break;
	}
        icmpError++;
	if (options.verbose && (0 < returnttl)) {
		printf(". return TTL: %d.", returnttl);
	}
	printf("\n");
        return ret;
}
Beispiel #3
0
/** Process UDP error event. */
int tport_udp_error(tport_t const *self, su_sockaddr_t name[1])
{
  struct cmsghdr *c;
  struct sock_extended_err *ee;
  su_sockaddr_t *from;
  char control[512];
  char errmsg[64 + 768];
  struct iovec iov[1];
  struct msghdr msg[1] = {{ 0 }};
  int n;

  msg->msg_name = name, msg->msg_namelen = sizeof(*name);
  msg->msg_iov = iov, msg->msg_iovlen = 1;
  iov->iov_base = errmsg, iov->iov_len = sizeof(errmsg);
  msg->msg_control = control, msg->msg_controllen = sizeof(control);

  n = recvmsg(self->tp_socket, msg, MSG_ERRQUEUE);

  if (n < 0) {
    int err = su_errno();
    if (!su_is_blocking(err))
      SU_DEBUG_1(("%s: recvmsg: %s\n", __func__, su_strerror(err)));
    return 0;
  }

  if ((msg->msg_flags & MSG_ERRQUEUE) != MSG_ERRQUEUE) {
    SU_DEBUG_1(("%s: recvmsg: no errqueue\n", __func__));
    return 0;
  }

  if (msg->msg_flags & MSG_CTRUNC) {
    SU_DEBUG_1(("%s: extended error was truncated\n", __func__));
    return 0;
  }

  if (msg->msg_flags & MSG_TRUNC) {
    /* ICMP message may contain original message... */
    SU_DEBUG_3(("%s: icmp(6) message was truncated (at %d)\n", __func__, n));
  }

  /* Go through the ancillary data */
  for (c = CMSG_FIRSTHDR(msg); c; c = CMSG_NXTHDR(msg, c)) {
    if (0
#if HAVE_IP_RECVERR
	|| (c->cmsg_level == IPPROTO_IP && c->cmsg_type == IP_RECVERR)
#endif
#if HAVE_IPV6_RECVERR
	|| (c->cmsg_level == IPPROTO_IPV6 && c->cmsg_type == IPV6_RECVERR)
#endif
	) {
      char info[128];
      char const *origin;

      ee = (struct sock_extended_err *)CMSG_DATA(c);
      from = (su_sockaddr_t *)SO_EE_OFFENDER(ee);
      info[0] = '\0';

      switch (ee->ee_origin) {
      case SO_EE_ORIGIN_LOCAL:
	origin = "local";
	break;
      case SO_EE_ORIGIN_ICMP:
	origin = "icmp";
	snprintf(info, sizeof(info), " type=%u code=%u",
		 ee->ee_type, ee->ee_code);
	break;
      case SO_EE_ORIGIN_ICMP6:
	origin = "icmp6";
	snprintf(info, sizeof(info), " type=%u code=%u",
		ee->ee_type, ee->ee_code);
	break;
      case SO_EE_ORIGIN_NONE:
	origin = "none";
	break;
      default:
	origin = "unknown";
	break;
      }

      if (ee->ee_info)
	snprintf(info + strlen(info), sizeof(info) - strlen(info),
		 " info=%08x", ee->ee_info);

      SU_DEBUG_3(("%s: %s (%d) [%s%s]\n",
		  __func__, su_strerror(ee->ee_errno), ee->ee_errno,
		  origin, info));
      if (from->su_family != AF_UNSPEC)
	SU_DEBUG_3(("\treported by [%s]:%u\n",
		    su_inet_ntop(from->su_family, SU_ADDR(from),
				 info, sizeof(info)),
		    ntohs(from->su_port)));

      if (msg->msg_namelen == 0)
	name->su_family = AF_UNSPEC;

      SU_CANONIZE_SOCKADDR(name);

      return ee->ee_errno;
    }
  }

  return 0;
}
Beispiel #4
0
int	NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
{
	if (NET_GetLoopPacket (sock, net_from, net_message))
		return 1;

	int net_socket = ip_sockets[sock];

	if (!net_socket)
		return 0;

	struct sockaddr_in	from;
	uint32 fromlen = sizeof(from);

	int ret = recvfrom (net_socket, net_message->data, net_message->maxsize
		, 0, (struct sockaddr *)&from, &fromlen);

	if (ret == -1)
	{
		//linux makes this needlessly complex, couldn't just return the source of the error in from, oh no...
		struct probehdr	rcvbuf;
		struct iovec	iov;
		struct msghdr	msg;
		struct cmsghdr	*cmsg;

		char		cbuf[1024];

#ifdef SOCK_EXTENDED_ERR
		struct sock_extended_err *e;
#endif  // SOCK_EXTENDED_ERR

		int err = errno;

		memset (&rcvbuf, 0, sizeof(rcvbuf));

		iov.iov_base = &rcvbuf;
		iov.iov_len = sizeof (rcvbuf);

		memset (&from, 0, sizeof(from));

		msg.msg_name = (void *)&from;
		msg.msg_namelen = sizeof (from);
		msg.msg_iov = &iov;
		msg.msg_iovlen = 1;
		msg.msg_flags = 0;
		msg.msg_control = cbuf;
		msg.msg_controllen = sizeof (cbuf);

		for (;;)
		{
			ret = recvmsg (net_socket, &msg, MSG_ERRQUEUE);
			if (ret == -1)
			{
				if (errno == EWOULDBLOCK || errno == EAGAIN)
				{
					if (err == EWOULDBLOCK || err == EAGAIN)
					{
						return 0;
					}
					else
					{
						errno = err;
						Com_Printf ("NET_GetPacket: %s\n", LOG_NET, NET_ErrorString());
						return 0;
					}
				}
				else
				{
					Com_DPrintf ("NET_GetPacket: recvmsg(): %s\n", NET_ErrorString());
					return 0;
				}
			}
			else if (!ret)
			{
				Com_DPrintf ("NET_GetPacket: recvmsg(): EOF\n");
				return 0;
			}

			errno = err;
			Com_DPrintf ("NET_GetPacket: Called recvmsg() for extended error details for %s\n", NET_ErrorString());

			//linux 2.2 (maybe others) fails to properly fill in the msg_name structure.
			Com_DPrintf ("(msgname) family %d, host: %s, port: %d, flags: %d\n", from.sin_family, inet_ntoa (from.sin_addr), from.sin_port, msg.msg_flags);

#ifdef SOCK_EXTENDED_ERR
			e = NULL;

			for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
			{
				if (cmsg->cmsg_level == SOL_IP)
				{
					if (cmsg->cmsg_type == IP_RECVERR)
					{
						e = (struct sock_extended_err *) CMSG_DATA (cmsg);
					}
					else
						Com_DPrintf ("cmsg type = %d\n", cmsg->cmsg_type);
				}
			}

			if (!e)
			{
				Com_DPrintf ("NET_GetPacket: recvmsg(): no extended info available\n");
				continue;
			}

			if (e->ee_origin == SO_EE_ORIGIN_ICMP)
			{
				//for some unknown reason, the kernel zeroes out the port in SO_EE_OFFENDER, so this is pretty much useless
				struct sockaddr_in *sin = (struct sockaddr_in *)SO_EE_OFFENDER(e);
				Com_DPrintf ("(ICMP) family %d, host: %s, port: %d\n", sin->sin_family, inet_ntoa (sin->sin_addr), sin->sin_port);

				//but better than nothing if using  buggy kernel?
				if (from.sin_family == AF_UNSPEC)
				{
					memcpy (&from, sin, sizeof(from));
					//can't trust port, may be buggy kernel (again)
					from.sin_port = 0;
				}
			}
			else
			{
				Com_DPrintf ("NET_GetPacket: recvmsg(): error origin is %d\n", e->ee_origin);
				continue;
			}

			SockadrToNetadr (&from, net_from);

			switch (e->ee_errno)
			{
				case ECONNREFUSED:
				case EHOSTUNREACH:
				case ENETUNREACH:
					Com_Printf ("NET_GetPacket: %s from %s\n", LOG_NET, strerror(e->ee_errno), NET_AdrToString (net_from));
					if (net_ignore_icmp->intvalue)
						return 0;
					else
						return -1;
				default:
					Com_Printf ("NET_GetPacket: %s from %s\n", LOG_NET, strerror(e->ee_errno), NET_AdrToString (net_from));
					continue;
			}
#endif  // SOCK_EXTENDED_ERR
		}

		//errno = err;
		//Com_Printf ("NET_GetPacket: %s\n", LOG_NET, NET_ErrorString());
		return 0;
	}

	net_packets_in++;
	net_total_in += ret;

	SockadrToNetadr (&from, net_from);

	if (ret == net_message->maxsize)
	{
		Com_Printf ("Oversize packet from %s\n", LOG_NET, NET_AdrToString (net_from));
		return 0;
	}

	net_message->cursize = ret;
	
	return 1;
}
Beispiel #5
0
int main(int argc, char *argv[]) {
	printf("SOCK_RAW=%u\n", SOCK_RAW);
	printf("SOCK_STREAM=%u\n", SOCK_STREAM);
	printf("SOCK_DGRAM=%u\n", SOCK_DGRAM);

	printf("IPPROTO_ICMP=%u\n", IPPROTO_ICMP);
	printf("IPPROTO_TCP=%u\n", IPPROTO_TCP);
	printf("IPPROTO_IP=%u\n", IPPROTO_IP);

	int sock;
	struct sockaddr_in server_addr;
	struct sockaddr_in client_addr;
	int addr_len = sizeof(struct sockaddr);
	int numbytes;
	//struct hostent *host;
	int send_len = 200000;
	char send_data[send_len + 24];
	int port;
	int client_port;
	pid_t pID;

	memset(send_data, 89, send_len);
	send_data[send_len] = '\0';

	//host= (struct hostent *) gethostbyname((char *)"127.0.0.1");

	//if ((sock = socket(PF_INET, SOCK_RAW, IPPROTO_UDP)) == -1) {
	//if ((sock = socket(PF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0)) == -1) {
	if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
		perror("socket");
		exit(1);
	}

	int val = 0;
	setsockopt(sock, SOL_IP, IP_MTU_DISCOVER, &val, sizeof(val));
	val = 1;
	setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, sizeof(val));
	val = 1;
	setsockopt(sock, SOL_IP, IP_RECVTTL, &val, sizeof(val));
	val = 1;
	setsockopt(sock, SOL_IP, IP_RECVERR, &val, sizeof(val));

	//fcntl64(3, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
	//fstat64(1, {st_dev=makedev(0, 11), st_ino=3, st_mode=S_IFCHR|0620, st_nlink=1, st_uid=1000, st_gid=5, st_blksize=1024, st_blocks=0, st_rdev=makedev(136, 0), st_atime=2012/10/16-22:31:09, st_mtime=2012/10/16-22:31:09, st_ctime=2012/10/16-19:33:02}) = 0

	val = 3;
	setsockopt(sock, SOL_IP, IP_TTL, &val, sizeof(val));

	if (argc > 1) {
		port = atoi(argv[1]);
	} else {
		port = 45454;
	}

	printf("MY DEST PORT BEFORE AND AFTER\n");
	printf("%d, %d\n", port, htons(port));
	fflush(stdout);
	server_addr.sin_family = PF_INET;
	server_addr.sin_port = htons(port);
	//server_addr.sin_port = htons(53);

	server_addr.sin_addr.s_addr = xxx(192,168,1,5);
	//server_addr.sin_addr.s_addr = xxx(127,0,0,1);
	//server_addr.sin_addr.s_addr = xxx(74,125,224,72);
	//server_addr.sin_addr.s_addr = INADDR_LOOPBACK;
	server_addr.sin_addr.s_addr = htonl(server_addr.sin_addr.s_addr);
	bzero(&(server_addr.sin_zero), 8);

	printf("\n UDP Client sending to server at server_addr=%s:%d, netw=%u\n", inet_ntoa(server_addr.sin_addr), ntohs(server_addr.sin_port),
			server_addr.sin_addr.s_addr);
	fflush(stdout);

	if (argc > 2) {
		client_port = atoi(argv[2]);
	} else {
		client_port = 55555;
	}
	client_addr.sin_family = PF_INET;
	client_addr.sin_port = htons(client_port);

	//client_addr.sin_addr.s_addr = xxx(127,0,0,1);
	client_addr.sin_addr.s_addr = INADDR_ANY;
	//client_addr.sin_addr.s_addr = INADDR_LOOPBACK;
	client_addr.sin_addr.s_addr = htonl(client_addr.sin_addr.s_addr);
	//bzero(&(client_addr.sin_zero), 8);

	printf("Binding to client_addr=%s:%d, netw=%u\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), client_addr.sin_addr.s_addr);
	fflush(stdout);
	if (bind(sock, (struct sockaddr *) &client_addr, sizeof(struct sockaddr_in)) == -1) {
		perror("Bind");
		printf("Failure");
		exit(1);
	}

	printf("Bound to client_addr=%s:%d, netw=%u\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), client_addr.sin_addr.s_addr);
	fflush(stdout);

	int nfds = 2;
	struct pollfd fds[nfds];
	fds[0].fd = -1;
	fds[0].events = POLLIN | POLLERR; //| POLLPRI;
	fds[1].fd = sock;
	fds[1].events = POLLIN | 0;
	//fds[1].events = POLLIN | POLLPRI | POLLOUT | POLLERR | POLLHUP | POLLNVAL | POLLRDNORM | POLLRDBAND | POLLWRNORM | POLLWRBAND;
	printf("\n fd: sock=%d, events=%x\n", sock, fds[1].events);
	fflush(stdout);
	int time = 1000;

	//pID = fork();
	if (pID == 0) { // child -- Capture process
		send_data[0] = 65;
	} else if (pID < 0) { // failed to fork
		printf("Failed to Fork \n");
		fflush(stdout);
		exit(1);
	} else { //parent
		send_data[0] = 89;
	}

	int ret = 0;

	struct msghdr recv_msg;
	int name_len = 64;
	char name_buf[name_len];
	struct iovec iov[1];
	int recv_len = 1000;
	char recv_buf[recv_len];
	int control_len = 4000;
	char control_buf[control_len];
	iov[0].iov_len = recv_len;
	iov[0].iov_base = recv_buf;

	recv_msg.msg_namelen = name_len;
	recv_msg.msg_name = name_buf;

	recv_msg.msg_iovlen = 1;
	recv_msg.msg_iov = iov;

	recv_msg.msg_controllen = control_len;
	recv_msg.msg_control = control_buf;

	struct cmsghdr *cmsg;
	int *ttlptr;
	int received_ttl;

	struct timeval curr;
	struct timeval *stamp;

	if (0) {
		int len;
		int i = 0;
		while (1) {
			i++;
			if (1) {
				printf("(%d) Input msg (q or Q to quit):", i);
				fflush(stdout);
				gets(send_data);

				//len = strlen(send_data);
				len = 1000;
				printf("\nlen=%d, str='%s'\n", len, send_data);
				fflush(stdout);
				if (len > 0 && len < send_len) {
					gettimeofday(&curr, 0);
					numbytes = sendto(sock, send_data, len, 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in));
					//sleep(1);

					ret = poll(fds, nfds, time);
					if (ret || 0) {
						if (1) {
							printf("poll: ret=%d, revents=%x\n", ret, fds[ret].revents);
							printf(
									"POLLIN=%x POLLPRI=%x POLLOUT=%x POLLERR=%x POLLHUP=%x POLLNVAL=%x POLLRDNORM=%x POLLRDBAND=%x POLLWRNORM=%x POLLWRBAND=%x\n",
									(fds[ret].revents & POLLIN) > 0, (fds[ret].revents & POLLPRI) > 0, (fds[ret].revents & POLLOUT) > 0, (fds[ret].revents
											& POLLERR) > 0, (fds[ret].revents & POLLHUP) > 0, (fds[ret].revents & POLLNVAL) > 0,
									(fds[ret].revents & POLLRDNORM) > 0, (fds[ret].revents & POLLRDBAND) > 0, (fds[ret].revents & POLLWRNORM) > 0,
									(fds[ret].revents & POLLWRBAND) > 0);
							fflush(stdout);
						}

						int recv_bytes;
						if ((fds[ret].revents & (POLLERR)) || 0) {
							recv_bytes = recvmsg(sock, &recv_msg, MSG_ERRQUEUE);
							if (recv_bytes > 0) {
								printf("recv_bytes=%d, msg_controllen=%d\n", recv_bytes, recv_msg.msg_controllen);

								/* Receive auxiliary data in msgh */
								for (cmsg = CMSG_FIRSTHDR(&recv_msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&recv_msg, cmsg)) {
									printf("cmsg_len=%u, cmsg_level=%u, cmsg_type=%u\n", cmsg->cmsg_len, cmsg->cmsg_level, cmsg->cmsg_type);

									if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) {
										received_ttl = *(int *) CMSG_DATA(cmsg);
										printf("received_ttl=%d\n", received_ttl);
										//break;
									} else if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) {
										struct sock_extended_err *err = (struct sock_extended_err *) CMSG_DATA(cmsg);
										printf("ee_errno=%u, ee_origin=%u, ee_type=%u, ee_code=%u, ee_pad=%u, ee_info=%u, ee_data=%u\n", err->ee_errno,
												err->ee_origin, err->ee_type, err->ee_code, err->ee_pad, err->ee_info, err->ee_data);

										struct sockaddr_in *offender = (struct sockaddr_in *) SO_EE_OFFENDER(err);
										printf("family=%u, addr=%s/%u\n", offender->sin_family, inet_ntoa(offender->sin_addr), ntohs(offender->sin_port));
									} else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
										struct timeval *stamp = (struct timeval *) CMSG_DATA(cmsg);
										printf("stamp=%u.%u\n", (uint32_t) stamp->tv_sec, (uint32_t) stamp->tv_usec);
										printf("diff=%f\n", time_diff(&curr, stamp));
									}
								}
								if (cmsg == NULL) {
									/*
									 * Error: IP_TTL not enabled or small buffer
									 * or I/O error.
									 */
								}

							} else {
								printf("errno=%d\n", errno);
								perror("recvmsg");
							}
						} else if ((fds[ret].revents & (POLLIN | POLLRDNORM)) || 0) {
							recv_bytes = recvmsg(sock, &recv_msg, 0);
							if (recv_bytes > 0) {
								printf("recv_bytes=%d, msg_controllen=%d\n", recv_bytes, recv_msg.msg_controllen);

								/* Receive auxiliary data in msgh */
								for (cmsg = CMSG_FIRSTHDR(&recv_msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&recv_msg, cmsg)) {
									printf("cmsg_len=%u, cmsg_level=%u, cmsg_type=%u\n", cmsg->cmsg_len, cmsg->cmsg_level, cmsg->cmsg_type);

									if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_TTL) {
										received_ttl = *(int *) CMSG_DATA(cmsg);
										printf("received_ttl=%d\n", received_ttl);
										//break;
									} else if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP) {
										struct timeval *stamp = (struct timeval *) CMSG_DATA(cmsg);
									}
								}
								if (cmsg == NULL) {
									/*
									 * Error: IP_TTL not enabled or small buffer
									 * or I/O error.
									 */
								}

							}
						}
					}
				} else {
					printf("Error string len, len=%d\n", len);
				}
			}

			if (0) {
				if (pID == 0) {
					numbytes = sendto(sock, send_data, 1, 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in));
					printf("\n sent=%d", numbytes);
					numbytes = sendto(sock, send_data, 1, 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in));
					printf("\n sent=%d", numbytes);
				} else {
					//numbytes = recvfrom(sock, send_data, 1024, 0, (struct sockaddr *) &client_addr, &addr_len);
					printf("\n read=%d", numbytes);
				}
				fflush(stdout);
			}

			if ((strcmp(send_data, "q") == 0) || strcmp(send_data, "Q") == 0) {
				break;
			}
		}
	}

	if (1) {
		struct timeval start, end;
		int its = 10;//10000;

		int data_len = 1000;
		while (data_len < 4000) {
			gets(send_data);
			//data_len += 100;
			//data_len = 1000;

			int total_bytes = 0;
			double total_time = 0;
			int total_success = 0;
			double diff;

			int i = 0;
			while (i < its) {
				i++;

				gettimeofday(&start, 0);
				numbytes = sendto(sock, send_data, data_len, 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr));
				gettimeofday(&end, 0);
				diff = time_diff(&start, &end);

				if (numbytes > 0) {
					total_success++;
					total_bytes += numbytes;
					total_time += diff;
				}

				//usleep(100);
			}

			//printf("\n diff=%f, len=%d, avg=%f ms, calls=%f, bits=%f", diff, data_len, diff / its, 1000 / (diff / its), 1000 / (diff / its) * data_len);
			printf("\n len=%d, time=%f, suc=%d, bytes=%d, avg=%f ms, eff=%f, thr=%f, calls=%f, act=%f", data_len, total_time, total_success, total_bytes,
					total_time / total_success, total_success / (double) its, total_bytes / (double) its / data_len, 1000 / (total_time / total_success), 1000
							/ (total_time / total_success) * data_len * 8);
			fflush(stdout);

			//sleep(5);
		}
	}

	if (0) {
		int i = 0;
		int its = 10000;
		double speed = 15000000;
		int len = 1000;
		double time = 8 * len / speed * 1000000;
		int use = (int) (time + .5);//ceil(time);

		printf("time=%f, used=%u\n", time, use);
		fflush(stdout);

		int *data = (int *) send_data;
		*(data + 1) = 0;

		double diff;
		struct timeval start, end;
		gettimeofday(&start, 0);

		while (1) {
			*data = htonl(i);
			numbytes = sendto(sock, send_data, len, 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in));
			if (numbytes != len) {
				break;
			}

			if (1) {
				gettimeofday(&end, 0);
				diff = time_diff(&start, &end) / 1000;
				printf("time=%f, frames=%d, speed=%f\n", diff, i, 8 * len * i / diff);
				fflush(stdout);
			}

			i++;
			//usleep(use);
		}
	}

	printf("\n Closing socket");
	fflush(stdout);
	close(sock);

	printf("\n FIN");
	fflush(stdout);
	while (1)
		;

	return 0;
}