Пример #1
0
int BIO_dgram_sctp_wait_for_dry(BIO *b)
{
	int is_dry = 0;
	int n, sockflags, ret;
	union sctp_notification snp;
	struct msghdr msg;
	struct iovec iov;
#ifdef SCTP_EVENT
	struct sctp_event event;
#else
	struct sctp_event_subscribe event;
	socklen_t eventsize;
#endif
	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;

	/* set sender dry event */
#ifdef SCTP_EVENT
	memset(&event, 0, sizeof(struct sctp_event));
	event.se_assoc_id = 0;
	event.se_type = SCTP_SENDER_DRY_EVENT;
	event.se_on = 1;
	ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
#else
	eventsize = sizeof(struct sctp_event_subscribe);
	ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
	if (ret < 0)
		return -1;
	
	event.sctp_sender_dry_event = 1;
	
	ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
#endif
	if (ret < 0)
		return -1;

	/* peek for notification */
	memset(&snp, 0x00, sizeof(union sctp_notification));
	iov.iov_base = (char *)&snp;
	iov.iov_len = sizeof(union sctp_notification);
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = 0;

	n = recvmsg(b->num, &msg, MSG_PEEK);
	if (n <= 0)
		{
		if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
			return -1;
		else
			return 0;
		}

	/* if we find a notification, process it and try again if necessary */
	while (msg.msg_flags & MSG_NOTIFICATION)
		{
		memset(&snp, 0x00, sizeof(union sctp_notification));
		iov.iov_base = (char *)&snp;
		iov.iov_len = sizeof(union sctp_notification);
		msg.msg_name = NULL;
		msg.msg_namelen = 0;
		msg.msg_iov = &iov;
		msg.msg_iovlen = 1;
		msg.msg_control = NULL;
		msg.msg_controllen = 0;
		msg.msg_flags = 0;

		n = recvmsg(b->num, &msg, 0);
		if (n <= 0)
			{
			if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
				return -1;
			else
				return is_dry;
			}
		
		if (snp.sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
			{
			is_dry = 1;

			/* disable sender dry event */
#ifdef SCTP_EVENT
			memset(&event, 0, sizeof(struct sctp_event));
			event.se_assoc_id = 0;
			event.se_type = SCTP_SENDER_DRY_EVENT;
			event.se_on = 0;
			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
#else
			eventsize = (socklen_t) sizeof(struct sctp_event_subscribe);
			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
			if (ret < 0)
				return -1;

			event.sctp_sender_dry_event = 0;

			ret = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
#endif
			if (ret < 0)
				return -1;
			}

#ifdef SCTP_AUTHENTICATION_EVENT
		if (snp.sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
			dgram_sctp_handle_auth_free_key_event(b, &snp);
#endif

		if (data->handle_notifications != NULL)
			data->handle_notifications(b, data->notification_context, (void*) &snp);

		/* found notification, peek again */
		memset(&snp, 0x00, sizeof(union sctp_notification));
		iov.iov_base = (char *)&snp;
		iov.iov_len = sizeof(union sctp_notification);
		msg.msg_name = NULL;
		msg.msg_namelen = 0;
		msg.msg_iov = &iov;
		msg.msg_iovlen = 1;
		msg.msg_control = NULL;
		msg.msg_controllen = 0;
		msg.msg_flags = 0;

		/* if we have seen the dry already, don't wait */
		if (is_dry)
			{
			sockflags = fcntl(b->num, F_GETFL, 0);
			fcntl(b->num, F_SETFL, O_NONBLOCK);
			}

		n = recvmsg(b->num, &msg, MSG_PEEK);

		if (is_dry)
			{
			fcntl(b->num, F_SETFL, sockflags);
			}

		if (n <= 0)
			{
			if ((n < 0) && (get_last_socket_error() != EAGAIN) && (get_last_socket_error() != EWOULDBLOCK))
				return -1;
			else
				return is_dry;
			}
		}

	/* read anything else */
	return is_dry;
}
Пример #2
0
static int send_netlink(struct nlmsghdr *hdr)
{
	int s;
	pid_t mypid = getpid ();
	struct sockaddr_nl nl;
	struct iovec iov;
	struct msghdr msg;
	static unsigned int seq;
	char *buffer;
	int bytes;
	union
	{
		char *buffer;
		struct nlmsghdr *nlm;
	} h;

	if ((s = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) {
		logger (LOG_ERR, "socket: %s", strerror (errno));
		return -1;
	}

	memset (&nl, 0, sizeof (struct sockaddr_nl));
	nl.nl_family = AF_NETLINK;
	if (bind (s, (struct sockaddr *) &nl, sizeof (nl)) == -1) {
		logger (LOG_ERR, "bind: %s", strerror (errno));
		close (s);
		return -1;
	}

	memset (&iov, 0, sizeof (struct iovec));
	iov.iov_base = hdr;
	iov.iov_len = hdr->nlmsg_len;

	memset (&msg, 0, sizeof (struct msghdr));
	msg.msg_name = &nl;
	msg.msg_namelen = sizeof (nl);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	/* Request a reply */
	hdr->nlmsg_flags |= NLM_F_ACK;
	hdr->nlmsg_seq = ++seq;

	if (sendmsg (s, &msg, 0) == -1) {
		logger (LOG_ERR, "write: %s", strerror (errno));
		close (s);
		return -1;
	}

	buffer = xmalloc (sizeof (char) * BUFFERLEN);
	memset (buffer, 0, BUFFERLEN);
	iov.iov_base = buffer;

	while (1) {
		iov.iov_len = BUFFERLEN;
		bytes = recvmsg (s, &msg, 0);

		if (bytes == -1) {
			if (errno != EINTR)
				logger (LOG_ERR, "netlink: overrun");
			continue;
		}

		if (bytes == 0) {
			logger (LOG_ERR, "netlink: EOF");
			goto eexit;
		}

		if (msg.msg_namelen != sizeof (nl)) {
			logger (LOG_ERR, "netlink: sender address length mismatch");
			goto eexit;
		}

		for (h.buffer = buffer; bytes >= (signed) sizeof (*h.nlm); ) {
			int len = h.nlm->nlmsg_len;
			int l = len - sizeof (*h.nlm);

			if (l < 0 || len > bytes) {
				if (msg.msg_flags & MSG_TRUNC)
					logger (LOG_ERR, "netlink: truncated message");
				else
					logger (LOG_ERR, "netlink: malformed message");
				goto eexit;
			}

			if (nl.nl_pid != 0 ||
				(pid_t) h.nlm->nlmsg_pid != mypid ||
				h.nlm->nlmsg_seq != seq)
				/* Message isn't for us, so skip it */
				goto next;

			/* We get an NLMSG_ERROR back with a code of zero for success */
			if (h.nlm->nlmsg_type == NLMSG_ERROR) {
				struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h.nlm);
				if ((unsigned) l < sizeof (struct nlmsgerr))
					logger (LOG_ERR, "netlink: truncated error message");
				else {
					errno = -err->error;
					if (errno == 0) {
						close (s);
						free (buffer);
						return 0;
					}

					/* Don't report on something already existing */
					if (errno != EEXIST)
						logger (LOG_ERR, "netlink: %s", strerror (errno));
				}
				goto eexit;
			}

			logger (LOG_ERR, "netlink: unexpected reply");
next:
			bytes -= NLMSG_ALIGN (len);
			h.buffer += NLMSG_ALIGN (len);
		}

		if (msg.msg_flags & MSG_TRUNC) {
			logger (LOG_ERR, "netlink: truncated message");
			continue;
		}

		if (bytes) {
			logger (LOG_ERR, "netlink: remnant of size %d", bytes);
			goto eexit;
		}
	}

eexit:
	close (s);
	free (buffer);
	return -1;
}
Пример #3
0
void main(int argc, char * argv[])
{
    /* this program is command line tool to help us communicate with the kernel 
     * it needs the following arguments to run: 1. filename_to_save_to, 2. message string
       or istead of "message string" have a -f tag, and then filename for input  */
    char * file_name;
    char message[MAX_NETCONNECT_INPUT];
    char * input_file_name;
    FILE * input_file;
    FILE * file;
    FILE * bytes;
    char payload[MAX_PAYLOAD];
    int payload_number = 0;
    int i;
    unsigned long recieved = 0;
    memset(message, 0, MAX_NETCONNECT_INPUT);
    if (argc != 3 && argc != 4) //thired argument is the programs name
    {
        //printf("Wrong parameters supplied. [LEAVING]\n");
        return;
    }
    if (argc == 3)
    {
        //use regular input 
        file_name = argv[1];
        strncpy(message, argv[2], MAX_NETCONNECT_INPUT);
    }
    else if(argc == 4)
    {
        //check if -f tag given
        if (!strcmp(argv[2], FILE_TAG))
        {
            input_file_name = argv[3];
            input_file = fopen(input_file_name, "rt");
            if (!input_file)
            {
                printf("WHAT");
            }
            printf("GOT HERE\n");
            cpy_from_file(input_file, message, MAX_NETCONNECT_INPUT);
            fclose(input_file);

        }
    }
    else {printf ("WRONG PARAMETERS SUPPLIED [LEAVING]\n"); return;}
    file_name = argv[1];

    if (!strstr(file_name,".txt"))
    {
        printf("BAD parameters, file_name needs to be supplied with .txt ending.\n");
        return;
    }

    file = fopen(file_name,"a+");

    sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_LISTEN_PROTOCOL);
    if (sock_fd < 0)
        return;

    memset(&src_addr, 0, sizeof(src_addr));
    src_addr.nl_family = AF_NETLINK;
    src_addr.nl_pid = getpid(); /* self pid */

    bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr));

    memset(&dest_addr, 0, sizeof(dest_addr));
    dest_addr.nl_family = AF_NETLINK;
    dest_addr.nl_pid = 0; /* For Linux Kernel */
    dest_addr.nl_groups = 0; /* unicast */

    /* message header */
    nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
    memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
    nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
    nlh->nlmsg_pid = getpid();
    nlh->nlmsg_flags = 0;

    strcpy(NLMSG_DATA(nlh), message);

    iov.iov_base = (void *)nlh;
    iov.iov_len = nlh->nlmsg_len;
    msg.msg_name = (void *)&dest_addr;
    msg.msg_namelen = sizeof(dest_addr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    printf("Letting kernel know our PID\n");
    sendmsg(sock_fd, &msg, 0);
    printf("Waiting for report from kernel\n");

    //delay to avoid rereading buffer

    recvmsg(sock_fd, &msg, 0);

    if (!strcmp(NLMSG_DATA(nlh),message))
    {
        //delay -> and read again ignoring first
        recvmsg(sock_fd, &msg,0);
        printf("Buffer reread, avoiding crash...\n" );
    }

         //check if empty
    if (strcmp(NLMSG_DATA(nlh),"EMPTY") == 0)
    {
        printf("No data to be read... [LEAVING]\n");
        return;
    }



    payload_number = atoi(NLMSG_DATA(nlh)) / MAX_PAYLOAD;
    if (atoi(NLMSG_DATA(nlh)) % MAX_PAYLOAD != 0)
    {
        payload_number++;
    }

    save_read_bytes(bytes, NLMSG_DATA(nlh));

    printf("Exepecting [%d] bytes in [%d] payloads\n", atoi(NLMSG_DATA(nlh)),payload_number);
    memset(payload, 0, MAX_PAYLOAD);
    memset(NLMSG_DATA(nlh), 0, MAX_PAYLOAD);

    for (i=0; i<payload_number; i++)
    {
        recvmsg(sock_fd, &msg, 0);
        strncpy(payload,NLMSG_DATA(nlh), MAX_PAYLOAD);
        recieved += strlen(payload);
        printf("Recieved [%d] bytes of total [%lu]\n",(int)strlen(payload), recieved);
        fprintf(file,"%s\n",payload);
        memset(NLMSG_DATA(nlh), 0, MAX_PAYLOAD);
        memset(payload, 0, MAX_PAYLOAD);
    }

    printf("OKAY [LEAVING]\n");
    fclose(file);
    close(sock_fd);

}
Пример #4
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;
}
Пример #5
0
void rxpacket(int sock) {
	Packet pkt;
	memset(&pkt, 0, sizeof(pkt));

	// using recvmsg
	int size;				  // size of the received data
	struct msghdr msg;
	memset(&msg,   0, sizeof(msg));
	struct sockaddr_in from;
	int fromlen=sizeof(from);
	msg.msg_name = &from;
	msg.msg_namelen = fromlen;

	char anciliary[2048];
	msg.msg_control = anciliary;
	msg.msg_controllen = sizeof(anciliary);

	struct iovec   iov[1];
	memset(iov,    0, sizeof(iov));
	iov[0].iov_base = &pkt.data;
	iov[0].iov_len  = sizeof(pkt.data);
	msg.msg_iov     = iov;
	msg.msg_iovlen  = 1;

	struct cmsghdr *cmsg;
	unsigned int ifindex;			  // interface index
	struct in_addr hdraddr;			  // destination IP address in IP header
	size = recvmsg(sock, &msg, 0);
	if (size == -1) {
		ASSERT(0);
		rcpLog(muxsock, RCP_PROC_RIP, RLOG_ERR, RLOG_FC_RIP,
			"cannot read data on socket, attempting recovery...");
		exit(1);
	}
	
	// verify packet size
	int sz = size - 4;
	if (sz<= 0 || (sz % sizeof(RipRoute)) != 0) {
		rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP,
			"Invalid RIP packet size");
		return;
	}
	int routes = sz / sizeof(RipRoute);
	
	int found = 0;
	for(cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
		if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
			//    struct in_pktinfo {
			//        unsigned int   ipi_ifindex;  /* Interface index */
			//        struct in_addr ipi_spec_dst; /* Local address */
			//        struct in_addr ipi_addr;     /* Header Destination
			//                                        address */
			//    };
			hdraddr = ((struct in_pktinfo*)CMSG_DATA(cmsg))->ipi_addr;
			ifindex = ((struct in_pktinfo*)CMSG_DATA(cmsg))->ipi_ifindex;
			found = 1;
		}
	}
	if (!found)
		return;
		
	pkt.ip_source = ntohl(from.sin_addr.s_addr);
	pkt.ip_dest = ntohl(hdraddr.s_addr);
	pkt.if_index = ifindex;

	// is the source ip address one of our addresses?
	RcpInterface *rxif  = rcpFindInterface(shm, pkt.ip_source);
	if (rxif) {
		// on Linux, packets we send to the multicast group will be received back on the socket
		return;
	}

	char *cmd[] = {"", "request", "response"};
	rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP,
		"Receiving RIP packet of size %d, from %d.%d.%d.%d, destination %d.%d.%d.%d, RIP %s, protocol version %d",
		size,
		RCP_PRINT_IP(pkt.ip_source),
		RCP_PRINT_IP(pkt.ip_dest),
		cmd[(pkt.data.command <= 2) ? pkt.data.command: 0],
		pkt.data.version);


	// update neighbor list
	RipNeighbor *neigh = neighbors;
	while (neigh != NULL) {
		if (neigh->ip == pkt.ip_source) {
			neigh->rx_time = 0;
			break;
		}
		neigh = neigh->next;
	}
	if (neigh == NULL) {
		RipNeighbor *newneigh = malloc(sizeof(RipNeighbor));
		if (newneigh != NULL) {
			memset(newneigh, 0, sizeof(RipNeighbor));
			newneigh->ip = pkt.ip_source;
			newneigh->next = neighbors;
			neighbors = newneigh;
			neigh = newneigh;
		}
		else {
			ASSERT(0);
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_ERR, RLOG_FC_RIP,
				"cannot allocate memory, attempting recovery...");
			exit(1);
		}
	}

	// do we have a valid interface?
	rxif =rcpFindInterfaceByKIndex(shm, pkt.if_index);
	if (rxif == NULL) {
		neigh->errors++;
		rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid interface, dropping...");
		return;
	}


	// do we have a configured neighbor?
	RcpRipPartner *rxnetwork = NULL;
	RcpRipPartner *net;
	int i;
	for (i = 0, net = shm->config.rip_neighbor; i < RCP_RIP_NEIGHBOR_LIMIT; i++, net++) {
		if (!net->valid)
			continue;

		// matching both source and destination addresses
		if (net->ip == pkt.ip_source && rxif->ip == pkt.ip_dest) {
			rxnetwork = net;
			break;
		}
	}
	
	// if no configured neighbor was found, try to find a configured network
	if (rxnetwork == NULL)
		rxnetwork = find_network_for_interface(rxif);
			
	// no network or neighbor configured, just drop the packet
	if (rxnetwork == NULL) {
		neigh->errors++;
		// the network can get disabled while receiving packets
		rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid network or neighbor, dropping...");
		return;
	}

	
	// the source of the datagram must be on a directly-connected network
	if ((pkt.ip_source & rxif->mask) != (rxif->ip & rxif->mask)) {
		neigh->errors++;
		// interface ip addresses are changing dynamically via CLI
		rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid source IP address, dropping...");
		return;
	}
	
	// drop invalid command packets
	if (pkt.data.command > 2) {
		neigh->errors++;
		rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid RIP command, dropping...");
		return;
	}
	
	if (pkt.data.command == 1) {
		rxnetwork->req_rx++;
		// force a response in one second
		rxif->rip_timeout = 1;
		return;
	}
	else
		rxnetwork->resp_rx++;

	ASSERT(sizeof(RipAuthMd5) == sizeof(RipAuthSimple));
	ASSERT(sizeof(RipAuthSimple) == sizeof(RipRoute));

	RipRoute *ptr = &pkt.data.routes[0];
	int rt = 0;
	
	// if md5 auth configured, and the packet is missing the auth header, drop the packet
	if (rxif->rip_passwd[0] != '\0') {
		if (ptr->family != 0xffff ||  ntohs(ptr->tag) != 3) {
			neigh->md5_errors++;		
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   missing MD5 authentication header");
			return;
		}
	}
	
	// checking auth header and calculate md5
	if (ptr->family == 0xffff) {
		// we don't care about simple auth
		if (ntohs(ptr->tag) == 3 && rxif->rip_passwd[0] != '\0') {
			RipAuthMd5 *md5 = (RipAuthMd5 *) ptr;
			uint16_t offset = ntohs(md5->offset);
			uint32_t seq = ntohl(md5->seq);
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   MD5 auth offset %u, key id %d, auth_len %d, seq %u",
				offset,
				md5->key_id,
				md5->auth_len,
				ntohl(md5->seq));

			// check offset
			if ((offset + sizeof(RipRoute)) != size) {
				neigh->md5_errors++;		
				rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid offset");
				return;
			}

			// check seq
			if (seq != 0 && seq < neigh->auth_seq) {
				neigh->md5_errors++;		
				rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid sequence number");
				return;
			}
			neigh->auth_seq = seq;
			
			// calculate md5
			uint8_t secret[16];
			memset(secret, 0, 16);
			memcpy(secret, rxif->rip_passwd, strlen(rxif->rip_passwd));
			
			MD5_CTX context;
			uint8_t digest[16];
			MD5Init (&context);
			MD5Update (&context, (uint8_t *) &pkt, size - 16);
			MD5Update (&context, secret, 16);
			MD5Final (digest, &context);
#if 0
{
int i;		
uint8_t *p = digest;
printf("rx digest:\n");
for (i = 0; i < 16; i++,p++)
	printf("%02x ", *p);
printf("\n");
}
#endif
			// compare md5
			if (memcmp((uint8_t *) ptr + offset, digest, 16) != 0) {
				neigh->md5_errors++;		
				rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid MD5 digest");
				return;
			}	
		}
		ptr++;
		rt++;
		routes--;	// the last route is the digest
	}		
	
	// parsing routes
	while (rt < routes) {
		uint32_t metric = ntohl(ptr->metric);
		uint32_t mask = ntohl(ptr->mask);
		uint32_t ip = ntohl(ptr->ip);
		uint32_t gw = ntohl(ptr->gw);
		
//		if (trace_prefix == 0 || 
//		      (trace_prefix != 0 && trace_prefix == ip)) {
//		      	if (gw == 0)
//				rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP,
//					"   %d.%d.%d.%d/%d metric %u",
//					RCP_PRINT_IP(ip),
//					mask2bits(mask),
//					metric);
//			else
//				rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP,
//					"   %d.%d.%d.%d/%d metric %u next hop %d.%d.%d.%d",
//					RCP_PRINT_IP(ip),
//					mask2bits(mask),
//					metric,
//					RCP_PRINT_IP(gw));
//		}
		
		// only AF_INET family is supported
		if (ntohs(ptr->family) != AF_INET) {
			neigh->route_errors++;
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid route family");
			goto next_element;
		}			

		// check destination for loopback addresses
		if (isLoopback(ip)) {
			neigh->route_errors++;
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid loopback route prefix");
			goto next_element;
		}			
		
		// check destination for broadcast addresses
		if (isBroadcast(ip)) {
			neigh->route_errors++;
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid broadcast route prefix");
			goto next_element;
		}			
		
		// check destination for multicast addresses
		if (isMulticast(ip)) {
			neigh->route_errors++;
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid multicast route prefix");
			goto next_element;
		}			
		
		

		// validate route metric
		else if (metric > 16 || metric == 0) {
			neigh->route_errors++;
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid metric");
			goto next_element;
		}		
		
		// validate route entry
		if (ip == 0 && mask == 0) {
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   received default route metric %d",
				metric);
		}
		else if (pkt.data.version == 2 && mask == 0) {
			neigh->route_errors++;
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid RIP route");
			goto next_element;
		}		
		else if (pkt.data.version == 1 && mask != 0) {
			neigh->route_errors++;
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid RIP route");
			goto next_element;
		}		
		
		// check if the mask is contiguous
		if (mask != 0 && !maskContiguous(mask)) {
			neigh->route_errors++;
			rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid mask");
			goto next_element;
		}		
		
		// validate next hop
		if (gw) {
			if (isLoopback(gw) || isMulticast(gw) || isBroadcast(gw)) {
				neigh->route_errors++;
				rcpLog(muxsock, RCP_PROC_RIP, RLOG_DEBUG, RLOG_FC_RIP, "   invalid next hop");
				goto next_element;
			}
		}		
		
		// manufacture mask for rip v1
		if (pkt.data.version == 1)
			mask = classMask(ip);
			
		// RFC metric = metric + interface cost
		// we assume a cost of 1 for each interface
		metric++;
		
		// add the route in the database
		if (metric < 16) {
//RFC
//- Setting the destination address to the destination address in the
//     RTE
//
//   - Setting the metric to the newly calculated metric (as described 
//     above)
//
//   - Set the next hop address to be the address of the router from which
//     the datagram came
//
//   - Initialize the timeout for the route.  If the garbage-collection
//     timer is running for this route, stop it (see section 3.6 for a
//     discussion of the timers)
//
//   - Set the route change flag
//
//   - Signal the output process to trigger an update (see section 3.8.1)

			// a next hop of 0 means send the packets to me
			if (gw == 0)
				gw = pkt.ip_source;
			ripdb_add(RCP_ROUTE_RIP, ip, mask, gw, metric, pkt.ip_source, rxif);
		}
		else {
			// a next hop of 0 means send the packets to me
			if (gw == 0)
				gw = pkt.ip_source;
			ripdb_delete(RCP_ROUTE_RIP, ip, mask, gw, pkt.ip_source);
		}
next_element:
		ptr++;
		rt++;
	}
}
Пример #6
0
static void uv__udp_recvmsg(uv_loop_t* loop,
                            uv__io_t* w,
                            unsigned int revents) {
  struct sockaddr_storage peer;
  struct msghdr h;
  uv_udp_t* handle;
  ssize_t nread;
  uv_buf_t buf;
  int flags;
  int count;

  handle = container_of(w, uv_udp_t, io_watcher);
  assert(handle->type == UV_UDP);
  assert(revents & UV__POLLIN);

  assert(handle->recv_cb != NULL);
  assert(handle->alloc_cb != NULL);

  /* Prevent loop starvation when the data comes in as fast as (or faster than)
   * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
   */
  count = 32;

  memset(&h, 0, sizeof(h));
  h.msg_name = &peer;

  do {
    buf = handle->alloc_cb((uv_handle_t*)handle, 64 * 1024);
    assert(buf.len > 0);
    assert(buf.base != NULL);

    h.msg_namelen = sizeof(peer);
    h.msg_iov = (void*) &buf;
    h.msg_iovlen = 1;

    do {
      nread = recvmsg(handle->io_watcher.fd, &h, 0);
    }
    while (nread == -1 && errno == EINTR);

    if (nread == -1) {
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
        uv__set_sys_error(handle->loop, EAGAIN);
        handle->recv_cb(handle, 0, buf, NULL, 0);
      }
      else {
        uv__set_sys_error(handle->loop, errno);
        handle->recv_cb(handle, -1, buf, NULL, 0);
      }
    }
    else {
      flags = 0;

      if (h.msg_flags & MSG_TRUNC)
        flags |= UV_UDP_PARTIAL;

      handle->recv_cb(handle,
                      nread,
                      buf,
                      (struct sockaddr*)&peer,
                      flags);
    }
  }
  /* recv_cb callback may decide to pause or close the handle */
  while (nread != -1
      && count-- > 0
      && handle->io_watcher.fd != -1
      && handle->recv_cb != NULL);
}
Пример #7
0
static int recv_fd(int c)
{
    int fd;
    uint8_t msgbuf[CMSG_SPACE(sizeof(fd))];
    struct msghdr msg = {
        .msg_control = msgbuf,
        .msg_controllen = sizeof(msgbuf),
    };
    struct cmsghdr *cmsg;
    struct iovec iov;
    uint8_t req[1];
    ssize_t len;

    cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
    msg.msg_controllen = cmsg->cmsg_len;

    iov.iov_base = req;
    iov.iov_len = sizeof(req);

    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    len = recvmsg(c, &msg, 0);
    if (len > 0) {
        memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
        return fd;
    }

    return len;
}

static int net_bridge_run_helper(const char *helper, const char *bridge)
{
    sigset_t oldmask, mask;
    int pid, status;
    char *args[5];
    char **parg;
    int sv[2];

    sigemptyset(&mask);
    sigaddset(&mask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &mask, &oldmask);

    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
        return -1;
    }

    /* try to launch bridge helper */
    pid = fork();
    if (pid == 0) {
        int open_max = sysconf(_SC_OPEN_MAX), i;
        char fd_buf[6+10];
        char br_buf[6+IFNAMSIZ] = {0};
        char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15];

        for (i = 0; i < open_max; i++) {
            if (i != STDIN_FILENO &&
                i != STDOUT_FILENO &&
                i != STDERR_FILENO &&
                i != sv[1]) {
                close(i);
            }
        }

        snprintf(fd_buf, sizeof(fd_buf), "%s%d", "--fd=", sv[1]);

        if (strrchr(helper, ' ') || strrchr(helper, '\t')) {
            /* assume helper is a command */

            if (strstr(helper, "--br=") == NULL) {
                snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
            }

            snprintf(helper_cmd, sizeof(helper_cmd), "%s %s %s %s",
                     helper, "--use-vnet", fd_buf, br_buf);

            parg = args;
            *parg++ = (char *)"sh";
            *parg++ = (char *)"-c";
            *parg++ = helper_cmd;
            *parg++ = NULL;

            execv("/bin/sh", args);
        } else {
            /* assume helper is just the executable path name */

            snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);

            parg = args;
            *parg++ = (char *)helper;
            *parg++ = (char *)"--use-vnet";
            *parg++ = fd_buf;
            *parg++ = br_buf;
            *parg++ = NULL;

            execv(helper, args);
        }
        _exit(1);

    } else if (pid > 0) {
        int fd;

        close(sv[1]);

        do {
            fd = recv_fd(sv[0]);
        } while (fd == -1 && errno == EINTR);

        close(sv[0]);

        while (waitpid(pid, &status, 0) != pid) {
            /* loop */
        }
        sigprocmask(SIG_SETMASK, &oldmask, NULL);
        if (fd < 0) {
            fprintf(stderr, "failed to recv file descriptor\n");
            return -1;
        }

        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
            return fd;
        }
    }
    fprintf(stderr, "failed to launch bridge helper\n");
    return -1;
}
Пример #8
0
static int sco_ipc_cmd(uint8_t service_id, uint8_t opcode, uint16_t len,
			void *param, size_t *rsp_len, void *rsp, int *fd)
{
	ssize_t ret;
	struct msghdr msg;
	struct iovec iv[2];
	struct ipc_hdr cmd;
	char cmsgbuf[CMSG_SPACE(sizeof(int))];
	struct ipc_status s;
	size_t s_len = sizeof(s);

	pthread_mutex_lock(&sk_mutex);

	if (ipc_sk < 0) {
		error("sco: Invalid cmd socket passed to sco_ipc_cmd");
		goto failed;
	}

	if (!rsp || !rsp_len) {
		memset(&s, 0, s_len);
		rsp_len = &s_len;
		rsp = &s;
	}

	memset(&msg, 0, sizeof(msg));
	memset(&cmd, 0, sizeof(cmd));

	cmd.service_id = service_id;
	cmd.opcode = opcode;
	cmd.len = len;

	iv[0].iov_base = &cmd;
	iv[0].iov_len = sizeof(cmd);

	iv[1].iov_base = param;
	iv[1].iov_len = len;

	msg.msg_iov = iv;
	msg.msg_iovlen = 2;

	ret = sendmsg(ipc_sk, &msg, 0);
	if (ret < 0) {
		error("sco: Sending command failed:%s", strerror(errno));
		goto failed;
	}

	/* socket was shutdown */
	if (ret == 0) {
		error("sco: Command socket closed");
		goto failed;
	}

	memset(&msg, 0, sizeof(msg));
	memset(&cmd, 0, sizeof(cmd));

	iv[0].iov_base = &cmd;
	iv[0].iov_len = sizeof(cmd);

	iv[1].iov_base = rsp;
	iv[1].iov_len = *rsp_len;

	msg.msg_iov = iv;
	msg.msg_iovlen = 2;

	if (fd) {
		memset(cmsgbuf, 0, sizeof(cmsgbuf));
		msg.msg_control = cmsgbuf;
		msg.msg_controllen = sizeof(cmsgbuf);
	}

	ret = recvmsg(ipc_sk, &msg, 0);
	if (ret < 0) {
		error("sco: Receiving command response failed:%s",
							strerror(errno));
		goto failed;
	}

	if (ret < (ssize_t) sizeof(cmd)) {
		error("sco: Too small response received(%zd bytes)", ret);
		goto failed;
	}

	if (cmd.service_id != service_id) {
		error("sco: Invalid service id (%u vs %u)", cmd.service_id,
								service_id);
		goto failed;
	}

	if (ret != (ssize_t) (sizeof(cmd) + cmd.len)) {
		error("sco: Malformed response received(%zd bytes)", ret);
		goto failed;
	}

	if (cmd.opcode != opcode && cmd.opcode != SCO_OP_STATUS) {
		error("sco: Invalid opcode received (%u vs %u)",
						cmd.opcode, opcode);
		goto failed;
	}

	if (cmd.opcode == SCO_OP_STATUS) {
		struct ipc_status *s = rsp;

		if (sizeof(*s) != cmd.len) {
			error("sco: Invalid status length");
			goto failed;
		}

		if (s->code == SCO_STATUS_SUCCESS) {
			error("sco: Invalid success status response");
			goto failed;
		}

		pthread_mutex_unlock(&sk_mutex);

		return s->code;
	}

	pthread_mutex_unlock(&sk_mutex);

	/* Receive auxiliary data in msg */
	if (fd) {
		struct cmsghdr *cmsg;

		*fd = -1;

		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg;
					cmsg = CMSG_NXTHDR(&msg, cmsg)) {
			if (cmsg->cmsg_level == SOL_SOCKET
					&& cmsg->cmsg_type == SCM_RIGHTS) {
				memcpy(fd, CMSG_DATA(cmsg), sizeof(int));
				break;
			}
		}

		if (*fd < 0)
			goto failed;
	}

	if (rsp_len)
		*rsp_len = cmd.len;

	return SCO_STATUS_SUCCESS;

failed:
	/* Some serious issue happen on IPC - recover */
	shutdown(ipc_sk, SHUT_RDWR);
	pthread_mutex_unlock(&sk_mutex);

	return SCO_STATUS_FAILED;
}
Пример #9
0
static inline int ufw_recv(ufw_sk *sk){
	struct cmsghdr* cmsg;
	char ctlbuf[4096];
	struct iovec iov;
	struct msghdr msg = {NULL, 0, &iov, 1, ctlbuf, sizeof(ctlbuf), 0};
	ssize_t s;
	struct node *cur;
	struct hookinfo *hki;
	struct timeval time;
	struct iphdr *ip;

	if(!sk){
		errno = EBADF;
		return -1;
	}

	iov.iov_base = sk->recvbuf;
	iov.iov_len = sizeof(sk->recvbuf);
	ip = (struct iphdr *)sk->recvbuf;

	for(;;){
	next:
		s = recvmsg(sk->fd, &msg, MSG_WAITALL);
		if(s < 0){
			if(errno == EAGAIN)
				return 0;
			else {
				if(sk->opts & FATAL)die("recvmsg");
				return -1;
			}
		}

		/* filter */
		if((sk->opts & FILTER_SADDR) && ip->daddr != sk->saddr)
			continue;
		if((sk->opts & FILTER_DADDR) && ip->saddr != sk->daddr)
			continue;
		if((sk->opts & FILTER_SPORT) 
			&& *(u_int16_t *)(sk->recvbuf + (ip->ihl << 2) + 2) != sk->sport)
			continue;
		if((sk->opts & FILTER_DPORT) 
			&& *(u_int16_t *)(sk->recvbuf + (ip->ihl << 2)) != sk->dport)
			continue;

		sk->received = 1;

		/* get timestamp */
		for(cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
			if(cmsg->cmsg_level == SOL_SOCKET
			&& cmsg->cmsg_type == SO_TIMESTAMP
			&& cmsg->cmsg_len >= CMSG_LEN(sizeof(struct timeval))){
				time = *(struct timeval *)CMSG_DATA(cmsg);
				break;
			}

		if(!sk->first_packet.tv_sec)
			sk->first_packet = time;

		for(cur = sk->recvhook; cur; cur = cur->next){
			hki = cur->data;
			if(!hki->func(sk->recvbuf, &time, 1, hki->user))
				goto next;
		}

		if((sk->opts & DUMP_RECV) && sk->dump)
			dump_write(sk->dump, sk->recvbuf, 0, &time);

		time.tv_sec -= sk->first_packet.tv_sec;
		time.tv_usec -= sk->first_packet.tv_usec;
		if(time.tv_usec < 0)time.tv_usec += 1000000;

		if(sk->opts & PRINT_RECV)
			print_packet(sk->recvbuf, &time, 0);
	}

	return -1;//never
}
Пример #10
0
ssize_t pa_iochannel_read_with_ancil_data(pa_iochannel*io, void*data, size_t l, pa_cmsg_ancil_data *ancil_data) {
    ssize_t r;
    struct msghdr mh;
    struct iovec iov;
    union {
        struct cmsghdr hdr;
        uint8_t data[CMSG_SPACE(sizeof(struct ucred)) + CMSG_SPACE(sizeof(int) * MAX_ANCIL_DATA_FDS)];
    } cmsg;

    pa_assert(io);
    pa_assert(data);
    pa_assert(l);
    pa_assert(io->ifd >= 0);
    pa_assert(ancil_data);

    if (io->ifd_type > 0) {
        ancil_data->creds_valid = false;
        ancil_data->nfd = 0;
        return pa_iochannel_read(io, data, l);
    }

    iov.iov_base = data;
    iov.iov_len = l;

    pa_zero(mh);
    mh.msg_iov = &iov;
    mh.msg_iovlen = 1;
    mh.msg_control = &cmsg;
    mh.msg_controllen = sizeof(cmsg);

    if ((r = recvmsg(io->ifd, &mh, 0)) >= 0) {
        struct cmsghdr *cmh;

        ancil_data->creds_valid = false;
        ancil_data->nfd = 0;

        for (cmh = CMSG_FIRSTHDR(&mh); cmh; cmh = CMSG_NXTHDR(&mh, cmh)) {

            if (cmh->cmsg_level != SOL_SOCKET)
                continue;

            if (cmh->cmsg_type == SCM_CREDENTIALS) {
                struct ucred u;
                pa_assert(cmh->cmsg_len == CMSG_LEN(sizeof(struct ucred)));
                memcpy(&u, CMSG_DATA(cmh), sizeof(struct ucred));

                ancil_data->creds.gid = u.gid;
                ancil_data->creds.uid = u.uid;
                ancil_data->creds_valid = true;
            }
            else if (cmh->cmsg_type == SCM_RIGHTS) {
                int nfd = (cmh->cmsg_len - CMSG_LEN(0)) / sizeof(int);
                if (nfd > MAX_ANCIL_DATA_FDS) {
                    int i;
                    pa_log("Trying to receive too many file descriptors!");
                    for (i = 0; i < nfd; i++)
                        pa_close(((int*) CMSG_DATA(cmh))[i]);
                    continue;
                }
                memcpy(ancil_data->fds, CMSG_DATA(cmh), nfd * sizeof(int));
                ancil_data->nfd = nfd;
                ancil_data->close_fds_on_cleanup = true;
            }
        }

        io->readable = io->hungup = false;
        enable_events(io);
    }

    if (r == -1 && errno == ENOTSOCK) {
        io->ifd_type = 1;
        return pa_iochannel_read_with_ancil_data(io, data, l, ancil_data);
    }

    return r;
}
Пример #11
0
int
mm_receive_fd(int sock)
{
	struct msghdr msg;
	union {
		struct cmsghdr hdr;
		char buf[1024];
	} cmsgbuf;
	struct cmsghdr *cmsg;
	struct iovec vec;
	ssize_t n;
	char ch;
	int fd;
	struct pollfd pfd;

	if (sizeof(cmsgbuf.buf) < CMSG_SPACE(sizeof(int))) {
		error("%s: %zu < %zu, recompile", __func__, 
		    sizeof(cmsgbuf.buf), CMSG_SPACE(sizeof(int)));
		return -1;
	}

	memset(&msg, 0, sizeof(msg));
	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
	vec.iov_base = &ch;
	vec.iov_len = 1;
	msg.msg_iov = &vec;
	msg.msg_iovlen = 1;
	msg.msg_control = &cmsgbuf.buf;
	msg.msg_controllen = CMSG_SPACE(sizeof(int));

	pfd.fd = sock;
	pfd.events = POLLIN;
	while ((n = recvmsg(sock, &msg, 0)) == -1 &&
	    (errno == EAGAIN || errno == EINTR)) {
		debug3("%s: recvmsg: %s", __func__, strerror(errno));
		(void)poll(&pfd, 1, -1);
	}
	if (n == -1) {
		error("%s: recvmsg: %s", __func__, strerror(errno));
		return -1;
	}

	if (n != 1) {
		error("%s: recvmsg: expected received 1 got %ld",
		    __func__, (long)n);
		return -1;
	}

	cmsg = CMSG_FIRSTHDR(&msg);
	if (cmsg == NULL) {
		error("%s: no message header", __func__);
		return -1;
	}

	if (cmsg->cmsg_type != SCM_RIGHTS) {
		error("%s: expected type %d got %d", __func__,
		    SCM_RIGHTS, cmsg->cmsg_type);
		return -1;
	}
	fd = (*(int *)CMSG_DATA(cmsg));
	return fd;
}
Пример #12
0
ssize_t
recvfromto(int s, void *buf, size_t len, int flags, struct sockaddr *from,
    socklen_t *fromlen, struct sockaddr *to, socklen_t *tolen)
{
	struct iovec		 iov;
	struct msghdr		 msg;
	struct cmsghdr		*cmsg;
	struct in6_pktinfo	*pkt6;
	struct sockaddr_in	*in;
	struct sockaddr_in6	*in6;
	ssize_t			 ret;
	union {
		struct cmsghdr hdr;
		char	buf[CMSG_SPACE(sizeof(struct sockaddr_storage))];
	} cmsgbuf;
#if !defined(IP_RECVDSTADDR) && defined(IP_PKTINFO)
	struct in_pktinfo	*pkt;
#endif

	bzero(&msg, sizeof(msg));
	bzero(&cmsgbuf.buf, sizeof(cmsgbuf.buf));

	iov.iov_base = buf;
	iov.iov_len = len;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_name = from;
	msg.msg_namelen = *fromlen;
	msg.msg_control = &cmsgbuf.buf;
	msg.msg_controllen = sizeof(cmsgbuf.buf);

	if ((ret = recvmsg(s, &msg, 0)) == -1)
		return (-1);

	*fromlen = SA_LEN(from);
	*tolen = 0;

	if (getsockname(s, to, tolen) != 0)
		*tolen = 0;

	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
	    cmsg = CMSG_NXTHDR(&msg, cmsg)) {
		switch (from->sa_family) {
		case AF_INET:
#if defined(IP_RECVDSTADDR)
			if (cmsg->cmsg_level == IPPROTO_IP &&
			    cmsg->cmsg_type == IP_RECVDSTADDR) {
				in = (struct sockaddr_in *)to;
				in->sin_family = AF_INET;
				in->sin_len = *tolen = sizeof(*in);
				memcpy(&in->sin_addr, CMSG_DATA(cmsg),
				    sizeof(struct in_addr));
			}
#elif defined(IP_PKTINFO)
			if (cmsg->cmsg_level == IPPROTO_IP &&
			    cmsg->cmsg_type == IP_PKTINFO) {
				in = (struct sockaddr_in *)to;
				in->sin_family = AF_INET;
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
				in->sin_len = *tolen = sizeof(*in);
#else
				*tolen = sizeof(*in);
#endif
				pkt = (struct in_pktinfo *)CMSG_DATA(cmsg);
				memcpy(&in->sin_addr, &pkt->ipi_addr,
				    sizeof(struct in_addr));
			}
#endif
			break;
		case AF_INET6:
			if (cmsg->cmsg_level == IPPROTO_IPV6 &&
			    cmsg->cmsg_type == IPV6_PKTINFO) {
				in6 = (struct sockaddr_in6 *)to;
				in6->sin6_family = AF_INET6;
#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_LEN
				in6->sin6_len = *tolen = sizeof(*in6);
#else
				*tolen = sizeof(*in6);
#endif
				pkt6 = (struct in6_pktinfo *)CMSG_DATA(cmsg);
				memcpy(&in6->sin6_addr, &pkt6->ipi6_addr,
				    sizeof(struct in6_addr));
				if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
					in6->sin6_scope_id =
					    pkt6->ipi6_ifindex;
			}
			break;
		}
	}

	return (ret);
}
Пример #13
0
int netl_listen(struct netl_handle *h, void *args)
{
	int len, buflen, err;
	ssize_t status;
	struct nlmsghdr *hdr;
	struct sockaddr_nl nladdr;
	struct iovec iov;
	struct msghdr msg = {
		.msg_name = &nladdr,
		.msg_namelen = sizeof(nladdr),
		.msg_iov = &iov,
		.msg_iovlen = 1,
	};
	char buf[8192];
	struct pollfd fds[1];

	if (h == NULL)
		return -1;

	iov.iov_base = buf;

	if (h->cb.init != NULL) {
		err = h->cb.init(args);
		if (err != 0)
			return err;
	}
	fds[0].events = POLLIN;
	fds[0].fd = h->fd;

	while (h->closing != 1) {
		int res = poll(fds, 1, NETL_POLL_TIMEOUT);
		if (res < 0 && errno != EINTR) {
			perror("error during cmdline_run poll");
			return 0;
		}
		if (fds[0].revents & POLLIN) {
			iov.iov_len = sizeof(buf);
			status = recvmsg(h->fd, &msg, 0);
			if (status < 0) {
				// TODO: EINT / EAGAIN / ENOBUF should continue
				return -1;
			}

			if (status == 0) {
				// EOF
				return -1;
			}

			if (msg.msg_namelen != sizeof(nladdr)) {
				// Invalid length
				return -1;
			}

			for (hdr = (struct nlmsghdr *) buf;
				 (size_t) status >= sizeof(*hdr);) {
				len = hdr->nlmsg_len;
				buflen = len - sizeof(*hdr);

				if (buflen < 0 || buflen > status) {
					// truncated
					return -1;
				}

				err = netl_handler(h, &nladdr, hdr, args);
				if (err < 0)
					return err;

				status -= NLMSG_ALIGN(len);
				hdr =
					(struct nlmsghdr *) ((char *) hdr + NLMSG_ALIGN(len));
			}

			if (status) {
				// content not read
				return -1;
			}
		}
	}

	return 1;
}

static inline __u32 nl_mgrp(__u32 group)
{
	return group ? (1 << (group - 1)) : 0;
}


struct netl_handle *netl_create(void)
{
	struct netl_handle *netl_handle;
	int rcvbuf = 1024 * 1024 * 1024;
	socklen_t addr_len;
	unsigned subscriptions = 0;

	// get notified whenever interface change (new vlans / ...)
	subscriptions |= nl_mgrp(RTNLGRP_LINK);

	// get notified whenever ip changes
	subscriptions |= nl_mgrp(RTNLGRP_IPV4_IFADDR);
	subscriptions |= nl_mgrp(RTNLGRP_IPV6_IFADDR);

	// get notified on new routes
	subscriptions |= nl_mgrp(RTNLGRP_IPV4_ROUTE);
	subscriptions |= nl_mgrp(RTNLGRP_IPV6_ROUTE);

	// subscriptions |= RTNLGRP_IPV6_PREFIX;
	// prefix is for ipv6 RA

	// get notified by arp or ipv6 nd
	subscriptions |= nl_mgrp(RTNLGRP_NEIGH);

	// called whenever an iface is added/removed
	// subscriptions |= RTNLGRP_IPV4_NETCONF;
	// subscriptions |= RTNLGRP_IPV6_NETCONF;


	netl_handle =
		pktj_calloc("netl_handle", 1, sizeof(struct netl_handle), 0,
					 SOCKET_ID_ANY);
	if (netl_handle == NULL)
		return NULL;

	netl_handle->fd =
		socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
	if (netl_handle->fd < 0) {
		perror("Cannot open netlink socket");
		goto free_netl_handle;
	}

	if (setsockopt
		(netl_handle->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf,
		 sizeof(rcvbuf)) < 0) {
		perror("Cannot set RCVBUF");
		goto free_netl_handle;
	}

	memset(&netl_handle->local, 0, sizeof(netl_handle->local));
	netl_handle->local.nl_family = AF_NETLINK;
	netl_handle->local.nl_groups = subscriptions;

	netl_handle->cb.neighbor4 = NULL;
	netl_handle->cb.route4 = NULL;

	if (bind
		(netl_handle->fd, (struct sockaddr *) &(netl_handle->local),
		 sizeof(netl_handle->local)) < 0) {
		perror("Cannot bind netlink socket");
		goto free_netl_handle;
	}

	addr_len = sizeof(netl_handle->local);
	if (getsockname
		(netl_handle->fd, (struct sockaddr *) &netl_handle->local,
		 &addr_len) < 0) {
		perror("Cannot getsockname");
		goto free_netl_handle;
	}

	if (addr_len != sizeof(netl_handle->local)) {
		perror("Wrong address length");
		goto free_netl_handle;
	}

	if (netl_handle->local.nl_family != AF_NETLINK) {
		perror("Wrong address family");
		goto free_netl_handle;
	}

	netl_handle->closing = 0;

	return netl_handle;

  free_netl_handle:
	pktj_free(netl_handle);
	return NULL;
}

int netl_free(struct netl_handle *h)
{
	if (h != NULL) {
		if (h->fd > 0) {
			close(h->fd);
			h->fd = -1;
		}

		pktj_free(h);
	}

	return 0;
}
Пример #14
0
/*
 * Dispatch kernel routing socket messages.
 */
static int
rtm_dispatch(void)
{
        struct msghdr mh;
        struct iovec iov[1];
        struct rt_msghdr *rtm;
        struct rtm_dispinfo *di;
        ssize_t len;
        int retval;

        di = malloc(sizeof(*di));
        if (di == NULL) {
                daemon_log(LOG_ERR, "malloc(%d): %s", sizeof(*di),
                    strerror(errno));
                return (-1);
        }
        di->di_buflen = MAX_RTMSG_SIZE;
        di->di_buf = calloc(MAX_RTMSG_SIZE, 1);
        if (di->di_buf == NULL) {
                free(di);
                daemon_log(LOG_ERR, "calloc(%d): %s", MAX_RTMSG_SIZE,
                    strerror(errno));
                return (-1);
        }

        memset(&mh, 0, sizeof(mh));
        iov[0].iov_base = di->di_buf;
        iov[0].iov_len = di->di_buflen;
        mh.msg_iov = iov;
        mh.msg_iovlen = 1;

        retval = 0;
        for (;;) {
                len = recvmsg(fd, &mh, MSG_DONTWAIT);
                if (len == -1) {
                        if (errno == EWOULDBLOCK)
                                break;
                        else {
                                daemon_log(LOG_ERR, "recvmsg(): %s",
                                    strerror(errno));
                                retval = -1;
                                break;
                        }
                }

                rtm = (void *)di->di_buf;
                if (rtm->rtm_version != RTM_VERSION) {
                        daemon_log(LOG_ERR,
                            "unknown routing socket message (version %d)\n",
                            rtm->rtm_version);
                        /* this is non-fatal; just ignore it for now. */
                        continue;
                }

                switch (rtm->rtm_type) {
                case RTM_NEWADDR:
                case RTM_DELADDR:
                        retval = rtm_dispatch_newdeladdr(di);
                        break;
                case RTM_IFANNOUNCE:
                        retval = rtm_dispatch_ifannounce(di);
                        break;
                default:
                        daemon_log(LOG_DEBUG, "%s: rtm_type %d ignored", __func__, rtm->rtm_type);
                        break;
                }

                /*
                 * If we got an error; assume our position on the call
                 * stack is enclosed by a level-triggered event loop,
                 * and signal the error condition.
                 */
                if (retval != 0)
                        break;
        }
        free(di->di_buf);
        free(di);

        return (retval);
}
Пример #15
0
void
loop_udp(int sockfd)
{
	int						maxfdp1, nread, ntowrite, stdineof,
							clilen, servlen, flags;
	fd_set					rset;
	struct sockaddr_in		cliaddr;		/* for UDP server */
	struct sockaddr_in		servaddr;		/* for UDP client */

#ifdef	HAVE_MSGHDR_MSG_CONTROL
	struct iovec			iov[1];
	struct msghdr			msg;

#ifdef	IP_RECVDSTADDR		/* 4.3BSD Reno and later */
	static struct cmsghdr  *cmptr = NULL;	/* malloc'ed */
	struct in_addr			dstinaddr;		/* for UDP server */
#define	CONTROLLEN	(sizeof(struct cmsghdr) + sizeof(struct in_addr))
#endif	/* IP_RECVDSTADDR */

#endif	/* MSG_TRUNC */

	if (pauseinit)
		sleep_us(pauseinit*1000);	/* intended for server */

	flags = 0;
	stdineof = 0;
	FD_ZERO(&rset);
	maxfdp1 = sockfd + 1;	/* check descriptors [0..sockfd] */

		/* If UDP client issues connect(), recv() and write() are used.
		   Server is harder since cannot issue connect().  We use recvfrom()
		   or recvmsg(), depending on OS. */

	for ( ; ; ) {
		if (stdineof == 0)
			FD_SET(STDIN_FILENO, &rset);
		FD_SET(sockfd, &rset);

		if (select(maxfdp1, &rset, NULL, NULL, NULL) < 0)
			err_sys("select error");

		if (FD_ISSET(STDIN_FILENO, &rset)) {	/* data to read on stdin */
			if ( (nread = read(STDIN_FILENO, rbuf, readlen)) < 0)
				err_sys("read error from stdin");
			else if (nread == 0) {	/* EOF on stdin */
				if (halfclose) {
					if (shutdown(sockfd, SHUT_WR) < 0)
						err_sys("shutdown() error");

					FD_CLR(STDIN_FILENO, &rset);
					stdineof = 1;	/* don't read stdin anymore */
					continue;		/* back to select() */
				}
				break;		/* default: stdin EOF -> done */
			}

			if (crlf) {
				ntowrite = crlf_add(wbuf, writelen, rbuf, nread);
				if (connectudp) {
					if (write(sockfd, wbuf, ntowrite) != ntowrite)
						err_sys("write error");
				} else {
					if (sendto(sockfd, wbuf, ntowrite, 0,
						  (struct sockaddr *) &servaddr, sizeof(servaddr))
																   != ntowrite)
						err_sys("sendto error");
				}
			} else {
				if (connectudp) {
					if (write(sockfd, rbuf, nread) != nread)
						err_sys("write error");
				} else {
					if (sendto(sockfd, rbuf, nread, 0,
						  (struct sockaddr *) &servaddr, sizeof(servaddr))
																      != nread)
						err_sys("sendto error");
				}
			}
		}

		if (FD_ISSET(sockfd, &rset)) {	/* data to read from socket */
			if (server) {
				clilen = sizeof(cliaddr);
#ifndef	MSG_TRUNC	/* vanilla BSD sockets */
				nread = recvfrom(sockfd, rbuf, readlen, 0,
									(struct sockaddr *) &cliaddr, &clilen);

#else	/* 4.3BSD Reno and later; use recvmsg() to get at MSG_TRUNC flag */
		/* Also lets us get at control information (destination address) */


				iov[0].iov_base = rbuf;
				iov[0].iov_len  = readlen;
				msg.msg_iov          = iov;
				msg.msg_iovlen       = 1;
				msg.msg_name         = (caddr_t) &cliaddr;
				msg.msg_namelen      = clilen;

#ifdef	IP_RECVDSTADDR
				if (cmptr == NULL && (cmptr = malloc(CONTROLLEN)) == NULL)
					err_sys("malloc error for control buffer");

				msg.msg_control      = (caddr_t) cmptr;	/* for dest address */
				msg.msg_controllen   = CONTROLLEN;
#else
				msg.msg_control      = (caddr_t) 0;	/* no ancillary data */
				msg.msg_controllen   = 0;
#endif	/* IP_RECVDSTADDR */
				msg.msg_flags        = 0;			/* flags returned here */

				nread = recvmsg(sockfd, &msg, 0);
#endif	/* HAVE_MSGHDR_MSG_CONTROL */
				if (nread < 0)
					err_sys("datagram receive error");

				if (verbose) {
					printf("from %s", INET_NTOA(cliaddr.sin_addr));
#ifdef	HAVE_MSGHDR_MSG_CONTROL
#ifdef	IP_RECVDSTADDR
					if (recvdstaddr) {
						if (cmptr->cmsg_len != CONTROLLEN)
							err_quit("control length (%d) != %d",
									 cmptr->cmsg_len, CONTROLLEN);
						if (cmptr->cmsg_level != IPPROTO_IP)
							err_quit("control level != IPPROTO_IP");
						if (cmptr->cmsg_type != IP_RECVDSTADDR)
							err_quit("control type != IP_RECVDSTADDR");
						bcopy(CMSG_DATA(cmptr), &dstinaddr,
							  sizeof(struct in_addr));
						bzero(cmptr, CONTROLLEN);

						printf(", to %s", INET_NTOA(dstinaddr));
					}
#endif	/* IP_RECVDSTADDR */
#endif	/* HAVE_MSGHDR_MSG_CONTROL */
					printf(": ");
					fflush(stdout);
				}

#ifdef	MSG_TRUNC
				if (msg.msg_flags & MSG_TRUNC)
					printf("(datagram truncated)\n");
#endif

			} else if (connectudp) {
					/* msgpeek = 0 or MSG_PEEK */
				flags = msgpeek;
			oncemore:
				if ( (nread = recv(sockfd, rbuf, readlen, flags)) < 0)
					err_sys("recv error");
				else if (nread == 0) {
					if (verbose)
						fprintf(stderr, "connection closed by peer\n");
					break;		/* EOF, terminate */
				}

			} else {
				/* Must use recvfrom() for unconnected UDP client */
				servlen = sizeof(servaddr);
				nread = recvfrom(sockfd, rbuf, readlen, 0,
								 (struct sockaddr *) &servaddr, &servlen);
				if (nread < 0)
					err_sys("datagram recvfrom() error");

				if (verbose) {
					printf("from %s", INET_NTOA(servaddr.sin_addr));
					printf(": ");
					fflush(stdout);
				}
			}

			if (crlf) {
				ntowrite = crlf_strip(wbuf, writelen, rbuf, nread);
				if (writen(STDOUT_FILENO, wbuf, ntowrite) != ntowrite)
					err_sys("writen error to stdout");
			} else {
				if (writen(STDOUT_FILENO, rbuf, nread) != nread)
					err_sys("writen error to stdout");
			}

			if (flags != 0) {
				flags = 0;		/* no infinite loop */
				goto oncemore;	/* read the message again */
			}
		}
	}

	if (pauseclose) {
		if (verbose)
				fprintf(stderr, "pausing before close\n");
		sleep_us(pauseclose*1000);
	}

	if (close(sockfd) < 0)
		err_sys("close error");		/* since SO_LINGER may be set */
}
Пример #16
0
static int manager_receive_response(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
        Manager *m = userdata;
        struct ntp_msg ntpmsg;

        struct iovec iov = {
                .iov_base = &ntpmsg,
                .iov_len = sizeof(ntpmsg),
        };
        union {
                struct cmsghdr cmsghdr;
                uint8_t buf[CMSG_SPACE(sizeof(struct timeval))];
        } control;
        union sockaddr_union server_addr;
        struct msghdr msghdr = {
                .msg_iov = &iov,
                .msg_iovlen = 1,
                .msg_control = &control,
                .msg_controllen = sizeof(control),
                .msg_name = &server_addr,
                .msg_namelen = sizeof(server_addr),
        };
        struct cmsghdr *cmsg;
        struct timespec now_ts;
        struct timeval *recv_time;
        ssize_t len;
        double origin, receive, trans, dest;
        double delay, offset;
        bool spike;
        int leap_sec;
        int r;

        assert(source);
        assert(m);

        if (revents & (EPOLLHUP|EPOLLERR)) {
                log_warning("Server connection returned error.");
                return manager_connect(m);
        }

        len = recvmsg(fd, &msghdr, MSG_DONTWAIT);
        if (len < 0) {
                if (errno == EAGAIN)
                        return 0;

                log_warning("Error receiving message. Disconnecting.");
                return manager_connect(m);
        }

        if (iov.iov_len < sizeof(struct ntp_msg)) {
                log_warning("Invalid response from server. Disconnecting.");
                return manager_connect(m);
        }

        if (!m->current_server_name ||
            !m->current_server_address ||
            !sockaddr_equal(&server_addr, &m->current_server_address->sockaddr)) {
                log_debug("Response from unknown server.");
                return 0;
        }

        recv_time = NULL;
        for (cmsg = CMSG_FIRSTHDR(&msghdr); cmsg; cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
                if (cmsg->cmsg_level != SOL_SOCKET)
                        continue;

                switch (cmsg->cmsg_type) {
                case SCM_TIMESTAMP:
                        recv_time = (struct timeval *) CMSG_DATA(cmsg);
                        break;
                }
        }
        if (!recv_time) {
                log_error("Invalid packet timestamp.");
                return -EINVAL;
        }

        if (!m->pending) {
                log_debug("Unexpected reply. Ignoring.");
                return 0;
        }

        /* check our "time cookie" (we just stored nanoseconds in the fraction field) */
        if (be32toh(ntpmsg.origin_time.sec) != m->trans_time.tv_sec + OFFSET_1900_1970 ||
            be32toh(ntpmsg.origin_time.frac) != m->trans_time.tv_nsec) {
                log_debug("Invalid reply; not our transmit time. Ignoring.");
                return 0;
        }

        m->event_timeout = sd_event_source_unref(m->event_timeout);

        if (be32toh(ntpmsg.recv_time.sec) < TIME_EPOCH + OFFSET_1900_1970 ||
            be32toh(ntpmsg.trans_time.sec) < TIME_EPOCH + OFFSET_1900_1970) {
                log_debug("Invalid reply, returned times before epoch. Ignoring.");
                return manager_connect(m);
        }

        if (NTP_FIELD_LEAP(ntpmsg.field) == NTP_LEAP_NOTINSYNC) {
                log_debug("Server is not synchronized. Disconnecting.");
                return manager_connect(m);
        }

        if (!IN_SET(NTP_FIELD_VERSION(ntpmsg.field), 3, 4)) {
                log_debug("Response NTPv%d. Disconnecting.", NTP_FIELD_VERSION(ntpmsg.field));
                return manager_connect(m);
        }

        if (NTP_FIELD_MODE(ntpmsg.field) != NTP_MODE_SERVER) {
                log_debug("Unsupported mode %d. Disconnecting.", NTP_FIELD_MODE(ntpmsg.field));
                return manager_connect(m);
        }

        /* valid packet */
        m->pending = false;
        m->retry_interval = 0;

        /* announce leap seconds */
        if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_PLUSSEC)
                leap_sec = 1;
        else if (NTP_FIELD_LEAP(ntpmsg.field) & NTP_LEAP_MINUSSEC)
                leap_sec = -1;
        else
                leap_sec = 0;

        /*
         * "Timestamp Name          ID   When Generated
         *  ------------------------------------------------------------
         *  Originate Timestamp     T1   time request sent by client
         *  Receive Timestamp       T2   time request received by server
         *  Transmit Timestamp      T3   time reply sent by server
         *  Destination Timestamp   T4   time reply received by client
         *
         *  The round-trip delay, d, and system clock offset, t, are defined as:
         *  d = (T4 - T1) - (T3 - T2)     t = ((T2 - T1) + (T3 - T4)) / 2"
         */
        assert_se(clock_gettime(clock_boottime_or_monotonic(), &now_ts) >= 0);
        origin = tv_to_d(recv_time) - (ts_to_d(&now_ts) - ts_to_d(&m->trans_time_mon)) + OFFSET_1900_1970;
        receive = ntp_ts_to_d(&ntpmsg.recv_time);
        trans = ntp_ts_to_d(&ntpmsg.trans_time);
        dest = tv_to_d(recv_time) + OFFSET_1900_1970;

        offset = ((receive - origin) + (trans - dest)) / 2;
        delay = (dest - origin) - (trans - receive);

        spike = manager_sample_spike_detection(m, offset, delay);

        manager_adjust_poll(m, offset, spike);

        log_debug("NTP response:\n"
                  "  leap         : %u\n"
                  "  version      : %u\n"
                  "  mode         : %u\n"
                  "  stratum      : %u\n"
                  "  precision    : %.6f sec (%d)\n"
                  "  reference    : %.4s\n"
                  "  origin       : %.3f\n"
                  "  receive      : %.3f\n"
                  "  transmit     : %.3f\n"
                  "  dest         : %.3f\n"
                  "  offset       : %+.3f sec\n"
                  "  delay        : %+.3f sec\n"
                  "  packet count : %"PRIu64"\n"
                  "  jitter       : %.3f%s\n"
                  "  poll interval: " USEC_FMT "\n",
                  NTP_FIELD_LEAP(ntpmsg.field),
                  NTP_FIELD_VERSION(ntpmsg.field),
                  NTP_FIELD_MODE(ntpmsg.field),
                  ntpmsg.stratum,
                  exp2(ntpmsg.precision), ntpmsg.precision,
                  ntpmsg.stratum == 1 ? ntpmsg.refid : "n/a",
                  origin - OFFSET_1900_1970,
                  receive - OFFSET_1900_1970,
                  trans - OFFSET_1900_1970,
                  dest - OFFSET_1900_1970,
                  offset, delay,
                  m->packet_count,
                  m->samples_jitter, spike ? " spike" : "",
                  m->poll_interval_usec / USEC_PER_SEC);

        if (!spike) {
                m->sync = true;
                r = manager_adjust_clock(m, offset, leap_sec);
                if (r < 0)
                        log_error("Failed to call clock_adjtime(): %m");
        }

        log_info("interval/delta/delay/jitter/drift " USEC_FMT "s/%+.3fs/%.3fs/%.3fs/%+ippm%s",
                 m->poll_interval_usec / USEC_PER_SEC, offset, delay, m->samples_jitter, m->drift_ppm,
                 spike ? " (ignored)" : "");

        r = manager_arm_timer(m, m->poll_interval_usec);
        if (r < 0) {
                log_error("Failed to rearm timer: %s", strerror(-r));
                return r;
        }

        return 0;
}

static int manager_listen_setup(Manager *m) {
        union sockaddr_union addr = {};
        static const int tos = IPTOS_LOWDELAY;
        static const int on = 1;
        int r;

        assert(m);

        assert(m->server_socket < 0);
        assert(!m->event_receive);
        assert(m->current_server_address);

        addr.sa.sa_family = m->current_server_address->sockaddr.sa.sa_family;

        m->server_socket = socket(addr.sa.sa_family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
        if (m->server_socket < 0)
                return -errno;

        r = bind(m->server_socket, &addr.sa, m->current_server_address->socklen);
        if (r < 0)
                return -errno;

        r = setsockopt(m->server_socket, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on));
        if (r < 0)
                return -errno;

        setsockopt(m->server_socket, IPPROTO_IP, IP_TOS, &tos, sizeof(tos));

        return sd_event_add_io(m->event, &m->event_receive, m->server_socket, EPOLLIN, manager_receive_response, m);
}

static int manager_begin(Manager *m) {
        _cleanup_free_ char *pretty = NULL;
        int r;

        assert(m);
        assert_return(m->current_server_name, -EHOSTUNREACH);
        assert_return(m->current_server_address, -EHOSTUNREACH);

        m->poll_interval_usec = NTP_POLL_INTERVAL_MIN_SEC * USEC_PER_SEC;

        server_address_pretty(m->current_server_address, &pretty);
        log_info("Using NTP server %s (%s).", strna(pretty), m->current_server_name->string);
        sd_notifyf(false, "STATUS=Using Time Server %s (%s).", strna(pretty), m->current_server_name->string);

        r = manager_listen_setup(m);
        if (r < 0) {
                log_warning("Failed to setup connection socket: %s", strerror(-r));
                return r;
        }

        r = manager_clock_watch_setup(m);
        if (r < 0)
                return r;

        return manager_send_request(m);
}

void manager_set_server_name(Manager *m, ServerName *n) {
        assert(m);

        if (m->current_server_name == n)
                return;

        m->current_server_name = n;
        m->current_server_address = NULL;

        manager_disconnect(m);

        if (n)
                log_debug("Selected server %s.", n->string);
}
Пример #17
0
int recverr(int fd, int ttl)
{
	int res;
	struct probehdr rcvbuf;
	char cbuf[512];
	struct iovec  iov;
	struct msghdr msg;
	struct cmsghdr *cmsg;
	struct sock_extended_err *e;
	struct sockaddr_in addr;
	struct timeval tv;
	struct timeval *rettv;
	int slot;
	int rethops;
	int sndhops;
	int progress = -1;
	int broken_router;
	
restart:
	memset(&rcvbuf, -1, sizeof(rcvbuf));
	iov.iov_base = &rcvbuf;
	iov.iov_len = sizeof(rcvbuf);
	msg.msg_name = (__u8*)&addr;
	msg.msg_namelen = sizeof(addr);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_flags = 0;
	msg.msg_control = cbuf;
	msg.msg_controllen = sizeof(cbuf);

	gettimeofday(&tv, NULL);
	res = recvmsg(fd, &msg, MSG_ERRQUEUE);
	if (res < 0) {
		if (errno == EAGAIN)
			return progress;
		goto restart;
	}

	progress = mtu;

	rethops = -1;
	sndhops = -1;
	e = NULL;
	rettv = NULL;
	slot = ntohs(addr.sin_port) - base_port;
	if (slot>=0 && slot < 63 && his[slot].hops) {
		sndhops = his[slot].hops;
		rettv = &his[slot].sendtime;
		his[slot].hops = 0;
	}
	broken_router = 0;
	if (res == sizeof(rcvbuf)) {
		if (rcvbuf.ttl == 0 || rcvbuf.tv.tv_sec == 0) {
			broken_router = 1;
		} else {
			sndhops = rcvbuf.ttl;
			rettv = &rcvbuf.tv;
		}
	}

	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 if (cmsg->cmsg_type == IP_TTL) {
				rethops = *(int*)CMSG_DATA(cmsg);
			} else { 
				printf("cmsg:%d\n ", cmsg->cmsg_type); 
			}
		}
	}
	if (e == NULL) {
		printf("no info\n");
		return 0;
	}
	if (e->ee_origin == SO_EE_ORIGIN_LOCAL) {
		printf("%2d?: %-15s ", ttl, "[LOCALHOST]");
	} else if (e->ee_origin == SO_EE_ORIGIN_ICMP) {
		char abuf[128];
		struct sockaddr_in *sin = (struct sockaddr_in*)(e+1);

		inet_ntop(AF_INET, &sin->sin_addr, abuf, sizeof(abuf));

		if (sndhops>0)
			printf("%2d:  ", sndhops);
		else
			printf("%2d?: ", ttl);

		if(!no_resolve) {
			char fabuf[256];
			struct hostent *h;
			fflush(stdout);
			h = gethostbyaddr((char *) &sin->sin_addr, sizeof(sin->sin_addr), AF_INET);
			snprintf(fabuf, sizeof(fabuf), "%s (%s)", h ? h->h_name : abuf, abuf);
			printf("%-52s ", fabuf);
		} else {
			printf("%-15s ", abuf);
		}
	}

	if (rethops>=0) {
		if (rethops<=64)
			rethops = 65-rethops;
		else if (rethops<=128)
			rethops = 129-rethops;
		else
			rethops = 256-rethops;
		if (sndhops>=0 && rethops != sndhops)
			printf("asymm %2d ", rethops);
		else if (sndhops<0 && rethops != ttl)
			printf("asymm %2d ", rethops);
	}

	if (rettv) {
		int diff = (tv.tv_sec-rettv->tv_sec)*1000000+(tv.tv_usec-rettv->tv_usec);
		printf("%3d.%03dms ", diff/1000, diff%1000);
		if (broken_router)
			printf("(This broken router returned corrupted payload) ");
	}

	switch (e->ee_errno) {
	case ETIMEDOUT:
		printf("\n");
		break;
	case EMSGSIZE:
		printf("pmtu %d\n", e->ee_info);
		mtu = e->ee_info;
		progress = mtu;
		break;
	case ECONNREFUSED:
		printf("reached\n");
		hops_to = sndhops<0 ? ttl : sndhops;
		hops_from = rethops;
		return 0;
	case EPROTO:
		printf("!P\n");
		return 0;
	case EHOSTUNREACH:
		if (e->ee_origin == SO_EE_ORIGIN_ICMP &&
		    e->ee_type == 11 &&
		    e->ee_code == 0) {
			printf("\n");
			break;
		}
		printf("!H\n");
		return 0;
	case ENETUNREACH:
		printf("!N\n");
		return 0;
	case EACCES:
		printf("!A\n");
		return 0;
	default:
		printf("\n");
		errno = e->ee_errno;
		perror("NET ERROR");
		return 0;
	}
	goto restart;
}
Пример #18
0
int main(int argc, char **argv)
{
	fd_set rdfs;
	int s[MAXSOCK];
	int bridge = 0;
	useconds_t bridge_delay = 0;
	unsigned char timestamp = 0;
	unsigned char dropmonitor = 0;
	unsigned char extra_msg_info = 0;
	unsigned char silent = SILENT_INI;
	unsigned char silentani = 0;
	unsigned char color = 0;
	unsigned char view = 0;
	unsigned char log = 0;
	unsigned char logfrmt = 0;
	int count = 0;
	int rcvbuf_size = 0;
	int opt, ret;
	int currmax, numfilter;
	char *ptr, *nptr;
	struct sockaddr_can addr;
	char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
	struct iovec iov;
	struct msghdr msg;
	struct cmsghdr *cmsg;
	struct can_filter *rfilter;
	can_err_mask_t err_mask;
	struct canfd_frame frame;
	int nbytes, i, maxdlen;
	struct ifreq ifr;
	struct timeval tv, last_tv;
	FILE *logfile = NULL;

	signal(SIGTERM, sigterm);
	signal(SIGHUP, sigterm);
	signal(SIGINT, sigterm);

	last_tv.tv_sec  = 0;
	last_tv.tv_usec = 0;

	while ((opt = getopt(argc, argv, "t:ciaSs:b:B:u:ldxLn:r:he?")) != -1) {
		switch (opt) {
		case 't':
			timestamp = optarg[0];
			if ((timestamp != 'a') && (timestamp != 'A') &&
			    (timestamp != 'd') && (timestamp != 'z')) {
				fprintf(stderr, "%s: unknown timestamp mode '%c' - ignored\n",
				       basename(argv[0]), optarg[0]);
				timestamp = 0;
			}
			break;

		case 'c':
			color++;
			break;

		case 'i':
			view |= CANLIB_VIEW_BINARY;
			break;

		case 'a':
			view |= CANLIB_VIEW_ASCII;
			break;

		case 'S':
			view |= CANLIB_VIEW_SWAP;
			break;

		case 'e':
			view |= CANLIB_VIEW_ERROR;
			break;

		case 's':
			silent = atoi(optarg);
			if (silent > SILENT_ON) {
				print_usage(basename(argv[0]));
				exit(1);
			}
			break;

		case 'b':
		case 'B':
			if (strlen(optarg) >= IFNAMSIZ) {
				fprintf(stderr, "Name of CAN device '%s' is too long!\n\n", optarg);
				return 1;
			} else {
				bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW);
				if (bridge < 0) {
					perror("bridge socket");
					return 1;
				}
				addr.can_family = AF_CAN;
				strcpy(ifr.ifr_name, optarg);
				if (ioctl(bridge, SIOCGIFINDEX, &ifr) < 0)
					perror("SIOCGIFINDEX");
				addr.can_ifindex = ifr.ifr_ifindex;
		
				if (!addr.can_ifindex) {
					perror("invalid bridge interface");
					return 1;
				}

				/* disable default receive filter on this write-only RAW socket */
				setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

				if (opt == 'B') {
					const int loopback = 0;

					setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
						   &loopback, sizeof(loopback));
				}

				if (bind(bridge, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
					perror("bridge bind");
					return 1;
				}
			}
			break;
	    
		case 'u':
			bridge_delay = (useconds_t)strtoul(optarg, (char **)NULL, 10);
			break;

		case 'l':
			log = 1;
			break;

		case 'd':
			dropmonitor = 1;
			break;

		case 'x':
			extra_msg_info = 1;
			break;

		case 'L':
			logfrmt = 1;
			break;

		case 'n':
			count = atoi(optarg);
			if (count < 1) {
				print_usage(basename(argv[0]));
				exit(1);
			}
			break;

		case 'r':
			rcvbuf_size = atoi(optarg);
			if (rcvbuf_size < 1) {
				print_usage(basename(argv[0]));
				exit(1);
			}
			break;

		default:
			print_usage(basename(argv[0]));
			exit(1);
			break;
		}
	}

	if (optind == argc) {
		print_usage(basename(argv[0]));
		exit(0);
	}
	
	if (logfrmt && view) {
		fprintf(stderr, "Log file format selected: Please disable ASCII/BINARY/SWAP options!\n");
		exit(0);
	}

	if (silent == SILENT_INI) {
		if (log) {
			fprintf(stderr, "Disabled standard output while logging.\n");
			silent = SILENT_ON; /* disable output on stdout */
		} else
			silent = SILENT_OFF; /* default output */
	}

	currmax = argc - optind; /* find real number of CAN devices */

	if (currmax > MAXSOCK) {
		fprintf(stderr, "More than %d CAN devices given on commandline!\n", MAXSOCK);
		return 1;
	}

	for (i=0; i < currmax; i++) {

		ptr = argv[optind+i];
		nptr = strchr(ptr, ',');

#ifdef DEBUG
		printf("open %d '%s'.\n", i, ptr);
#endif

		s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
		if (s[i] < 0) {
			perror("socket");
			return 1;
		}

		cmdlinename[i] = ptr; /* save pointer to cmdline name of this socket */

		if (nptr)
			nbytes = nptr - ptr;  /* interface name is up the first ',' */
		else
			nbytes = strlen(ptr); /* no ',' found => no filter definitions */

		if (nbytes >= IFNAMSIZ) {
			fprintf(stderr, "name of CAN device '%s' is too long!\n", ptr);
			return 1;
		}

		if (nbytes > max_devname_len)
			max_devname_len = nbytes; /* for nice printing */

		addr.can_family = AF_CAN;

		memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
		strncpy(ifr.ifr_name, ptr, nbytes);

#ifdef DEBUG
		printf("using interface name '%s'.\n", ifr.ifr_name);
#endif

		if (strcmp(ANYDEV, ifr.ifr_name)) {
			if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
				perror("SIOCGIFINDEX");
				exit(1);
			}
			addr.can_ifindex = ifr.ifr_ifindex;
		} else
			addr.can_ifindex = 0; /* any can interface */

		if (nptr) {

			/* found a ',' after the interface name => check for filters */

			/* determine number of filters to alloc the filter space */
			numfilter = 0;
			ptr = nptr;
			while (ptr) {
				numfilter++;
				ptr++; /* hop behind the ',' */
				ptr = strchr(ptr, ','); /* exit condition */
			}

			rfilter = malloc(sizeof(struct can_filter) * numfilter);
			if (!rfilter) {
				fprintf(stderr, "Failed to create filter space!\n");
				return 1;
			}

			numfilter = 0;
			err_mask = 0;

			while (nptr) {

				ptr = nptr+1; /* hop behind the ',' */
				nptr = strchr(ptr, ','); /* update exit condition */

				if (sscanf(ptr, "%x:%x",
					   &rfilter[numfilter].can_id, 
					   &rfilter[numfilter].can_mask) == 2) {
 					rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
					numfilter++;
				} else if (sscanf(ptr, "%x~%x",
						  &rfilter[numfilter].can_id, 
						  &rfilter[numfilter].can_mask) == 2) {
 					rfilter[numfilter].can_id |= CAN_INV_FILTER;
 					rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
					numfilter++;
				} else if (sscanf(ptr, "#%x", &err_mask) != 1) { 
					fprintf(stderr, "Error in filter option parsing: '%s'\n", ptr);
					return 1;
				}
			}

			if (err_mask)
				setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
					   &err_mask, sizeof(err_mask));

			if (numfilter)
				setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
					   rfilter, numfilter * sizeof(struct can_filter));

			free(rfilter);

		} /* if (nptr) */

		/* try to switch the socket into CAN FD mode */
		setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on));

		if (rcvbuf_size) {

			int curr_rcvbuf_size;
			socklen_t curr_rcvbuf_size_len = sizeof(curr_rcvbuf_size);

			/* try SO_RCVBUFFORCE first, if we run with CAP_NET_ADMIN */
			if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUFFORCE,
				       &rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
#ifdef DEBUG
				printf("SO_RCVBUFFORCE failed so try SO_RCVBUF ...\n");
#endif
				if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
					       &rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
					perror("setsockopt SO_RCVBUF");
					return 1;
				}

				if (getsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
					       &curr_rcvbuf_size, &curr_rcvbuf_size_len) < 0) {
					perror("getsockopt SO_RCVBUF");
					return 1;
				}

				/* Only print a warning the first time we detect the adjustment */
				/* n.b.: The wanted size is doubled in Linux in net/sore/sock.c */
				if (!i && curr_rcvbuf_size < rcvbuf_size*2)
					fprintf(stderr, "The socket receive buffer size was "
						"adjusted due to /proc/sys/net/core/rmem_max.\n");
			}
		}

		if (timestamp || log || logfrmt) {

			const int timestamp_on = 1;

			if (setsockopt(s[i], SOL_SOCKET, SO_TIMESTAMP,
				       &timestamp_on, sizeof(timestamp_on)) < 0) {
				perror("setsockopt SO_TIMESTAMP");
				return 1;
			}
		}

		if (dropmonitor) {

			const int dropmonitor_on = 1;

			if (setsockopt(s[i], SOL_SOCKET, SO_RXQ_OVFL,
				       &dropmonitor_on, sizeof(dropmonitor_on)) < 0) {
				perror("setsockopt SO_RXQ_OVFL not supported by your Linux Kernel");
				return 1;
			}
		}

		if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
			perror("bind");
			return 1;
		}
	}

	if (log) {
		time_t currtime;
		struct tm now;
		char fname[sizeof("candump-2006-11-20_202026.log")+1];

		if (time(&currtime) == (time_t)-1) {
			perror("time");
			return 1;
		}

		localtime_r(&currtime, &now);

		sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log",
			now.tm_year + 1900,
			now.tm_mon + 1,
			now.tm_mday,
			now.tm_hour,
			now.tm_min,
			now.tm_sec);

		if (silent != SILENT_ON)
			printf("\nWarning: console output active while logging!");

		fprintf(stderr, "\nEnabling Logfile '%s'\n\n", fname);

		logfile = fopen(fname, "w");
		if (!logfile) {
			perror("logfile");
			return 1;
		}
	}

	/* these settings are static and can be held out of the hot path */
	iov.iov_base = &frame;
	msg.msg_name = &addr;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = &ctrlmsg;

	while (running) {

		FD_ZERO(&rdfs);
		for (i=0; i<currmax; i++)
			FD_SET(s[i], &rdfs);

		if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
			//perror("select");
			running = 0;
			continue;
		}

		for (i=0; i<currmax; i++) {  /* check all CAN RAW sockets */

			if (FD_ISSET(s[i], &rdfs)) {

				int idx;

				/* these settings may be modified by recvmsg() */
				iov.iov_len = sizeof(frame);
				msg.msg_namelen = sizeof(addr);
				msg.msg_controllen = sizeof(ctrlmsg);  
				msg.msg_flags = 0;

				nbytes = recvmsg(s[i], &msg, 0);
				if (nbytes < 0) {
					perror("read");
					return 1;
				}

				if ((size_t)nbytes == CAN_MTU)
					maxdlen = CAN_MAX_DLEN;
				else if ((size_t)nbytes == CANFD_MTU)
					maxdlen = CANFD_MAX_DLEN;
				else {
					fprintf(stderr, "read: incomplete CAN frame\n");
					return 1;
				}

				if (count && (--count == 0))
					running = 0;

				if (bridge) {
					if (bridge_delay)
						usleep(bridge_delay);

					nbytes = write(bridge, &frame, nbytes);
					if (nbytes < 0) {
						perror("bridge write");
						return 1;
					} else if ((size_t)nbytes != CAN_MTU && (size_t)nbytes != CANFD_MTU) {
						fprintf(stderr,"bridge write: incomplete CAN frame\n");
						return 1;
					}
				}
		    
				for (cmsg = CMSG_FIRSTHDR(&msg);
				     cmsg && (cmsg->cmsg_level == SOL_SOCKET);
				     cmsg = CMSG_NXTHDR(&msg,cmsg)) {
					if (cmsg->cmsg_type == SO_TIMESTAMP)
						tv = *(struct timeval *)CMSG_DATA(cmsg);
					else if (cmsg->cmsg_type == SO_RXQ_OVFL)
						dropcnt[i] = *(__u32 *)CMSG_DATA(cmsg);
				}

				/* check for (unlikely) dropped frames on this specific socket */
				if (dropcnt[i] != last_dropcnt[i]) {

					__u32 frames;

					if (dropcnt[i] > last_dropcnt[i])
						frames = dropcnt[i] - last_dropcnt[i];
					else
						frames = 4294967295U - last_dropcnt[i] + dropcnt[i]; /* 4294967295U == UINT32_MAX */

					if (silent != SILENT_ON)
						printf("DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n",
						       frames, (frames > 1)?"s":"", cmdlinename[i], dropcnt[i]);

					if (log)
						fprintf(logfile, "DROPCOUNT: dropped %d CAN frame%s on '%s' socket (total drops %d)\n",
							frames, (frames > 1)?"s":"", cmdlinename[i], dropcnt[i]);

					last_dropcnt[i] = dropcnt[i];
				}

				idx = idx2dindex(addr.can_ifindex, s[i]);

				/* once we detected a EFF frame indent SFF frames accordingly */
				if (frame.can_id & CAN_EFF_FLAG)
					view |= CANLIB_VIEW_INDENT_SFF;

				if (log) {
					/* log CAN frame with absolute timestamp & device */
					fprintf(logfile, "(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
					fprintf(logfile, "%*s ", max_devname_len, devname[idx]);
					/* without seperator as logfile use-case is parsing */
					fprint_canframe(logfile, &frame, "\n", 0, maxdlen);
				}

				if (logfrmt) {
					/* print CAN frame in log file style to stdout */
					printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
					printf("%*s ", max_devname_len, devname[idx]);
					fprint_canframe(stdout, &frame, "\n", 0, maxdlen);
					goto out_fflush; /* no other output to stdout */
				}

				if (silent != SILENT_OFF){
					if (silent == SILENT_ANI) {
						printf("%c\b", anichar[silentani%=MAXANI]);
						silentani++;
					}
					goto out_fflush; /* no other output to stdout */
				}
		      
				printf(" %s", (color>2)?col_on[idx%MAXCOL]:"");

				switch (timestamp) {

				case 'a': /* absolute with timestamp */
					printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
					break;

				case 'A': /* absolute with date */
				{
					struct tm tm;
					char timestring[25];

					tm = *localtime(&tv.tv_sec);
					strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
					printf("(%s.%06ld) ", timestring, tv.tv_usec);
				}
				break;

				case 'd': /* delta */
				case 'z': /* starting with zero */
				{
					struct timeval diff;

					if (last_tv.tv_sec == 0)   /* first init */
						last_tv = tv;
					diff.tv_sec  = tv.tv_sec  - last_tv.tv_sec;
					diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
					if (diff.tv_usec < 0)
						diff.tv_sec--, diff.tv_usec += 1000000;
					if (diff.tv_sec < 0)
						diff.tv_sec = diff.tv_usec = 0;
					printf("(%03ld.%06ld) ", diff.tv_sec, diff.tv_usec);
				
					if (timestamp == 'd')
						last_tv = tv; /* update for delta calculation */
				}
				break;

				default: /* no timestamp output */
					break;
				}

				printf(" %s", (color && (color<3))?col_on[idx%MAXCOL]:"");
				printf("%*s", max_devname_len, devname[idx]);

				if (extra_msg_info) {

					if (msg.msg_flags & MSG_DONTROUTE)
						printf ("  TX %s", extra_m_info[frame.flags & 3]);
					else
						printf ("  RX %s", extra_m_info[frame.flags & 3]);
				}

				printf("%s  ", (color==1)?col_off:"");

				fprint_long_canframe(stdout, &frame, NULL, view, maxdlen);

				printf("%s", (color>1)?col_off:"");
				printf("\n");
			}

		out_fflush:
			fflush(stdout);
		}
	}

	for (i=0; i<currmax; i++)
		close(s[i]);

	if (bridge)
		close(bridge);

	if (log)
		fclose(logfile);

	return 0;
}
Пример #19
0
/* See comment for "process_child" regarding reverse roles */
int process_parent( int sv[2] )
{
    /* Some of the run options mean that we terminate before our "child". We don't want to confuse
     * the child with SIGCHLD of which it is not aware.
     */
    int grandchild_pid=fork();

    if( grandchild_pid==-1 ) {
        perror("privbind: Error creating grandchild process");

        return 1;
    }

    if( grandchild_pid!=0 ) {
        /* We are the grandchild's parent. Terminate cleanly to indicate to our parent that it's ok
         * to start the actual program.
         */
        return 0;
    }

    /* Close the child socket */
    close(sv[0]);

    /* wait for request from the child */
    do {
        struct msghdr msghdr={0};
        struct cmsghdr *cmsg;
        char buf[CMSG_SPACE(sizeof(int))];
        struct ipc_msg_req request;
        struct iovec iov;
        struct ipc_msg_reply reply = {0};
        int recvbytes;

        msghdr.msg_control=buf;
        msghdr.msg_controllen=sizeof(buf);

        iov.iov_base = &request;
        iov.iov_len = sizeof request;

        msghdr.msg_iov = &iov;
        msghdr.msg_iovlen = 1;

        if ( (recvbytes = recvmsg( sv[1], &msghdr, 0)) > 0) {
            if ((cmsg = (struct cmsghdr *)CMSG_FIRSTHDR(&msghdr)) != NULL) {
                switch (request.type) {
                case MSG_REQ_NONE:
                    reply.type = MSG_REP_NONE;
                    if (send(sv[1], &reply, sizeof reply, 0) != sizeof reply)
                        perror("privbind: send");
                    break;
                case MSG_REQ_BIND:
                    reply.type = MSG_REP_STAT;
                    int sock;
                    if (cmsg->cmsg_len == CMSG_LEN(sizeof(int))
                            && cmsg->cmsg_level == SOL_SOCKET
                            && cmsg->cmsg_type == SCM_RIGHTS)
                        sock = *((int*)CMSG_DATA(cmsg));
                    else {
                        sock = -1;
                    }
                    reply.data.stat.retval =
                        bind(sock, (struct sockaddr *)&request.data.bind.addr,
                                sizeof request.data.bind.addr);
                    if (reply.data.stat.retval < 0)
                        reply.data.stat.error = errno;
                    
#if DEBUG_TESTING
                    /* Sleep to check for races */
                    if( options.wait!=0 )
                        sleep(options.wait);
#endif

                    if (send(sv[1], &reply, sizeof reply, 0) != sizeof reply)
                        perror("privbind: send");
                    if (sock > -1 && close(sock))
                        perror("privbind: close");
                    break;
                default:
                    fprintf(stderr, "privbind: bad request type: %d\n",
                            request.type);
                    break;
                }
            } else {
                fprintf(stderr, "privbind: empty request\n");
            }
        } else if (recvbytes == 0) {
            /* If the child closed its end of the socket, it means the
               child has exited. We have nothing more to do. */

            return 0;
        } else {
            perror("privbind: recvmsg");
        }
    } while (options.numbinds == 0 || --options.numbinds > 0);


    /* If we got here, the child has done the number of binds
       specified by the -n option, and we have nothing more to do
       and should exit, leaving behind no helper process */

    return 0;
}
Пример #20
0
int
main(int argc, char *argv[])
{
    struct msghdr msgh;
    struct iovec iov;
    int data, lfd, sfd, fd, opt;
    ssize_t nr;
    int use_datagram_socket;
    union {
        struct cmsghdr cmh;
        char   control[CMSG_SPACE(sizeof(int))];
                        /* Space large enough to hold an 'int' */
    } control_un;
    struct cmsghdr *cmhp;

    /* Parse command-line arguments */
    use_datagram_socket = 0;
    while ((opt = getopt(argc, argv, "d")) != -1) {
        switch (opt) {
        case 'd':
            use_datagram_socket = 1;
            break;
        default:
            usage(stderr, argv[0]);
            exit(EXIT_FAILURE);
        }
    }

    /* Create socket bound to well-known address */

    if (remove(SOCK_PATH) == -1 && errno != ENOENT) {
        fprintf(stderr, "remove-%s\n", SOCK_PATH);
        exit(EXIT_FAILURE);
    }

    if (use_datagram_socket) {
        fprintf(stderr, "Receiving via datagram socket\n");
        sfd = unix_bind(SOCK_PATH, SOCK_DGRAM);
        if (sfd == -1) {
            perror("unix_bind");
            exit(EXIT_FAILURE);
        }
    } else {
        fprintf(stderr, "Receiving via stream socket\n");
        lfd = unix_listen(SOCK_PATH, 5);
        if (lfd == -1) {
            perror("unix_listen");
            exit(EXIT_FAILURE);
        }
        sfd = accept(lfd, NULL, 0);
        if (sfd == -1) {
            perror("accept");
            exit(EXIT_FAILURE);
        }
    }

    /* Set 'control_un' to describe ancillary data that we want to receive */

    control_un.cmh.cmsg_len = CMSG_LEN(sizeof(int));
    control_un.cmh.cmsg_level = SOL_SOCKET;
    control_un.cmh.cmsg_type = SCM_RIGHTS;

    /* Set 'msgh' fields to describe 'control_un' */

    msgh.msg_control = control_un.control;
    msgh.msg_controllen = sizeof(control_un.control);

    /* Set fields of 'msgh' to point to buffer used to receive (real)
       data read by recvmsg() */

    msgh.msg_iov = &iov;
    msgh.msg_iovlen = 1;
    iov.iov_base = &data;
    iov.iov_len = sizeof(int);

    msgh.msg_name = NULL;               /* We don't need address of peer */
    msgh.msg_namelen = 0;

    /* Receive real plus ancillary data */

    nr = recvmsg(sfd, &msgh, 0);
    if (nr == -1) {
        perror("recvmsg");
        exit(EXIT_FAILURE);
    }
    fprintf(stderr, "recvmsg() returned %ld\n", (long) nr);

    if (nr > 0) {
        fprintf(stderr, "Received data = %d\n", data);
    }

    /* Get the received file descriptor (which is typically a different
       file descriptor number than was used in the sending process) */

    cmhp = CMSG_FIRSTHDR(&msgh);
    if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(int))) {
        fprintf(stderr, "bad cmsg header / message length\n");
        exit(EXIT_FAILURE);
    }
    if (cmhp->cmsg_level != SOL_SOCKET) {
        fprintf(stderr, "cmsg_level != SOL_SOCKET\n");
        exit(EXIT_FAILURE);
    }
    if (cmhp->cmsg_type != SCM_RIGHTS) {
        fprintf(stderr, "cmsg_type != SCM_RIGHTS\n");
        exit(EXIT_FAILURE);
    }

    fd = *((int *) CMSG_DATA(cmhp));
    fprintf(stderr, "Received fd=%d\n", fd);

    /* Having obtained the file descriptor, read the file's contents and
       print them on standard output */

    while (1) {
        char buf[BUF_SIZE];
        ssize_t numRead;

        numRead = read(fd, buf, BUF_SIZE);
        if (numRead == -1) {
            perror("read");
            exit(EXIT_FAILURE);
        }
        if (numRead == 0) {
            break;
        }
        write(STDOUT_FILENO, buf, numRead);
    }

    exit(EXIT_SUCCESS);
}
Пример #21
0
/**
 * Process the message and add/drop multicast membership if needed
 */
int
ProcessInterfaceWatch(int s, int s_ssdp, int s_ssdp6,
                      int n_if_addr, const char * * if_addr)
{
	ssize_t len;
	int i;
	char buffer[4096];
#ifdef __linux__
	struct iovec iov;
	struct msghdr hdr;
	struct nlmsghdr *nlhdr;
	struct ifaddrmsg *ifa;
	struct rtattr *rta;
	int ifa_len;

	iov.iov_base = buffer;
	iov.iov_len = sizeof(buffer);

	memset(&hdr, 0, sizeof(hdr));
	hdr.msg_iov = &iov;
	hdr.msg_iovlen = 1;

	len = recvmsg(s, &hdr, 0);
	if(len < 0) {
		syslog(LOG_ERR, "recvmsg(s, &hdr, 0): %m");
		return -1;
	}

	for(nlhdr = (struct nlmsghdr *)buffer;
		NLMSG_OK(nlhdr, len);
		nlhdr = NLMSG_NEXT(nlhdr, len)) {
		int is_del = 0;
		char address[48];
		char ifname[IFNAMSIZ];
		address[0] = '\0';
		ifname[0] = '\0';
		if(nlhdr->nlmsg_type == NLMSG_DONE)
			break;
		switch(nlhdr->nlmsg_type) {
		/* case RTM_NEWLINK: */
		/* case RTM_DELLINK: */
		case RTM_DELADDR:
			is_del = 1;
		case RTM_NEWADDR:
			/* http://linux-hacks.blogspot.fr/2009/01/sample-code-to-learn-netlink.html */
			ifa = (struct ifaddrmsg *)NLMSG_DATA(nlhdr);
			rta = (struct rtattr *)IFA_RTA(ifa);
			ifa_len = IFA_PAYLOAD(nlhdr);
			syslog(LOG_DEBUG, "%s %s index=%d fam=%d prefixlen=%d flags=%d scope=%d",
			       "ProcessInterfaceWatchNotify", is_del ? "RTM_DELADDR" : "RTM_NEWADDR",
			       ifa->ifa_index, ifa->ifa_family, ifa->ifa_prefixlen,
			       ifa->ifa_flags, ifa->ifa_scope);
			for(;RTA_OK(rta, ifa_len); rta = RTA_NEXT(rta, ifa_len)) {
				/*RTA_DATA(rta)*/
				/*rta_type : IFA_ADDRESS, IFA_LOCAL, etc. */
				char tmp[128];
				memset(tmp, 0, sizeof(tmp));
				switch(rta->rta_type) {
				case IFA_ADDRESS:
				case IFA_LOCAL:
				case IFA_BROADCAST:
				case IFA_ANYCAST:
					inet_ntop(ifa->ifa_family, RTA_DATA(rta), tmp, sizeof(tmp));
					if(rta->rta_type == IFA_ADDRESS)
						strncpy(address, tmp, sizeof(address));
					break;
				case IFA_LABEL:
					strncpy(tmp, RTA_DATA(rta), sizeof(tmp));
					strncpy(ifname, tmp, sizeof(ifname));
					break;
				case IFA_CACHEINFO:
					{
						struct ifa_cacheinfo *cache_info;
						cache_info = RTA_DATA(rta);
						snprintf(tmp, sizeof(tmp), "valid=%u prefered=%u",
						         cache_info->ifa_valid, cache_info->ifa_prefered);
					}
					break;
				default:
					strncpy(tmp, "*unknown*", sizeof(tmp));
				}
				syslog(LOG_DEBUG, " rta_len=%d rta_type=%d '%s'", rta->rta_len, rta->rta_type, tmp);
			}
			syslog(LOG_INFO, "%s: %s/%d %s",
			       is_del ? "RTM_DELADDR" : "RTM_NEWADDR",
			       address, ifa->ifa_prefixlen, ifname);
			for(i = 0; i < n_if_addr; i++) {
				if((0 == strcmp(address, if_addr[i])) ||
				   (0 == strcmp(ifname, if_addr[i])) ||
				   (ifa->ifa_index == if_nametoindex(if_addr[i]))) {
					if(ifa->ifa_family == AF_INET && address[0] != '\0')
						AddDropMulticastMembership(s_ssdp, address, 0, is_del);
					else if(ifa->ifa_family == AF_INET6)
						AddDropMulticastMembership(s_ssdp6, if_addr[i], 1, is_del);
					break;
				}
			}
			break;
		default:
			syslog(LOG_DEBUG, "unknown nlmsg_type=%d", nlhdr->nlmsg_type);
		}
	}
#else /* __linux__ */
	struct rt_msghdr * rtm;
	struct ifa_msghdr * ifam;
	int is_del = 0;
	char tmp[64];
	char * p;
	struct sockaddr * sa;
	int addr;
	char address[48];
	char ifname[IFNAMSIZ];
	int family = AF_UNSPEC;
	int prefixlen = 0;

	address[0] = '\0';
	ifname[0] = '\0';

	len = recv(s, buffer, sizeof(buffer), 0);
	if(len < 0) {
		syslog(LOG_ERR, "%s recv: %m", "ProcessInterfaceWatchNotify");
		return -1;
	}
	rtm = (struct rt_msghdr *)buffer;
	switch(rtm->rtm_type) {
	case RTM_DELADDR:
		is_del = 1;
	case RTM_NEWADDR:
		ifam = (struct ifa_msghdr *)buffer;
		syslog(LOG_DEBUG, "%s %s len=%d/%hu index=%hu addrs=%x flags=%x",
		       "ProcessInterfaceWatchNotify", is_del?"RTM_DELADDR":"RTM_NEWADDR",
		       (int)len, ifam->ifam_msglen,
		       ifam->ifam_index, ifam->ifam_addrs, ifam->ifam_flags);
		p = buffer + sizeof(struct ifa_msghdr);
		addr = 1;
		while(p < buffer + len) {
			sa = (struct sockaddr *)p;
			while(!(addr & ifam->ifam_addrs) && (addr <= ifam->ifam_addrs))
				addr = addr << 1;
			sockaddr_to_string(sa, tmp, sizeof(tmp));
			syslog(LOG_DEBUG, " %s", tmp);
			switch(addr) {
			case RTA_DST:
			case RTA_GATEWAY:
				break;
			case RTA_NETMASK:
				if(sa->sa_family == AF_INET
#if defined(__OpenBSD__)
				   || (sa->sa_family == 0 &&
				       sa->sa_len <= sizeof(struct sockaddr_in))
#endif
				   ) {
					uint32_t sin_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
					while((prefixlen < 32) &&
					      ((sin_addr & (1 << (31 - prefixlen))) != 0))
						prefixlen++;
				} else if(sa->sa_family == AF_INET6
#if defined(__OpenBSD__)
				          || (sa->sa_family == 0 &&
				              sa->sa_len == sizeof(struct sockaddr_in6))
#endif
				          ) {
					int i = 0;
					uint8_t * q =  ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr;
					while((*q == 0xff) && (i < 16)) {
						prefixlen += 8;
						q++; i++;
					}
					if(i < 16) {
						i = 0;
						while((i < 8) &&
						      ((*q & (1 << (7 - i))) != 0))
							i++;
						prefixlen += i;
					}
				}
				break;
			case RTA_GENMASK:
				break;
			case RTA_IFP:
#ifdef AF_LINK
				if(sa->sa_family == AF_LINK) {
					struct sockaddr_dl * sdl = (struct sockaddr_dl *)sa;
					memset(ifname, 0, sizeof(ifname));
					memcpy(ifname, sdl->sdl_data, sdl->sdl_nlen);
				}
#endif
				break;
			case RTA_IFA:
				family = sa->sa_family;
				if(sa->sa_family == AF_INET) {
					inet_ntop(sa->sa_family,
					          &((struct sockaddr_in *)sa)->sin_addr,
					          address, sizeof(address));
				} else if(sa->sa_family == AF_INET6) {
					inet_ntop(sa->sa_family,
					          &((struct sockaddr_in6 *)sa)->sin6_addr,
					          address, sizeof(address));
				}
				break;
			case RTA_AUTHOR:
				break;
			case RTA_BRD:
				break;
			}
#if 0
			syslog(LOG_DEBUG, " %d.%d.%d.%d %02x%02x%02x%02x",
			       (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3],
			       (uint8_t)p[0], (uint8_t)p[1], (uint8_t)p[2], (uint8_t)p[3]); 
			syslog(LOG_DEBUG, " %d.%d.%d.%d %02x%02x%02x%02x",
			       (uint8_t)p[4], (uint8_t)p[5], (uint8_t)p[6], (uint8_t)p[7],
			       (uint8_t)p[4], (uint8_t)p[5], (uint8_t)p[6], (uint8_t)p[7]); 
#endif
			p += SA_RLEN(sa);
			addr = addr << 1;
		}
		syslog(LOG_INFO, "%s: %s/%d %s",
		       is_del ? "RTM_DELADDR" : "RTM_NEWADDR",
		       address, prefixlen, ifname);
		for(i = 0; i < n_if_addr; i++) {
			if(0 == strcmp(address, if_addr[i]) ||
			   0 == strcmp(ifname, if_addr[i]) ||
			   ifam->ifam_index == if_nametoindex(if_addr[i])) {
				if(family == AF_INET && address[0] != '\0')
					AddDropMulticastMembership(s_ssdp, address, 0, is_del);
				else if(family == AF_INET6)
					AddDropMulticastMembership(s_ssdp6, if_addr[i], 1, is_del);
				break;
			}
		}
		break;
	default:
		syslog(LOG_DEBUG, "Unknown RTM message : rtm->rtm_type=%d len=%d",
		       rtm->rtm_type, (int)len);
	}
#endif
	return 0;
}
Пример #22
0
static void uv__read(uv_stream_t* stream) {
  uv_buf_t buf;
  ssize_t nread;
  struct msghdr msg;
  struct cmsghdr* cmsg;
  char cmsg_space[64];
  int count;

  /* Prevent loop starvation when the data comes in as fast as (or faster than)
   * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O.
   */
  count = 32;

  /* XXX: Maybe instead of having UV_STREAM_READING we just test if
   * tcp->read_cb is NULL or not?
   */
  while ((stream->read_cb || stream->read2_cb)
      && (stream->flags & UV_STREAM_READING)
      && (count-- > 0)) {
    assert(stream->alloc_cb);
    buf = stream->alloc_cb((uv_handle_t*)stream, 64 * 1024);

    assert(buf.len > 0);
    assert(buf.base);
    assert(uv__stream_fd(stream) >= 0);

    if (stream->read_cb) {
      do {
        nread = read(uv__stream_fd(stream), buf.base, buf.len);
      }
      while (nread < 0 && errno == EINTR);
    } else {
      assert(stream->read2_cb);
      /* read2_cb uses recvmsg */
      msg.msg_flags = 0;
      msg.msg_iov = (struct iovec*) &buf;
      msg.msg_iovlen = 1;
      msg.msg_name = NULL;
      msg.msg_namelen = 0;
      /* Set up to receive a descriptor even if one isn't in the message */
      msg.msg_controllen = 64;
      msg.msg_control = (void *) cmsg_space;

      do {
        nread = recvmsg(uv__stream_fd(stream), &msg, 0);
      }
      while (nread < 0 && errno == EINTR);
    }

#define INVOKE_READ_CB(stream, status, buf, type)                             \
    do {                                                                      \
      if ((stream)->read_cb != NULL)                                          \
        (stream)->read_cb((stream), (status), (buf));                         \
      else                                                                    \
        (stream)->read2_cb((uv_pipe_t*) (stream), (status), (buf), (type));   \
    }                                                                         \
    while (0)

    if (nread < 0) {
      /* Error */
      if (errno == EAGAIN || errno == EWOULDBLOCK) {
        /* Wait for the next one. */
        if (stream->flags & UV_STREAM_READING) {
          uv__io_start(stream->loop, &stream->io_watcher, UV__POLLIN);
        }
        uv__set_sys_error(stream->loop, EAGAIN);
        INVOKE_READ_CB(stream, 0, buf, UV_UNKNOWN_HANDLE);
      } else {
        /* Error. User should call uv_close(). */
        uv__set_sys_error(stream->loop, errno);
        INVOKE_READ_CB(stream, -1, buf, UV_UNKNOWN_HANDLE);
        assert(!uv__io_active(&stream->io_watcher, UV__POLLIN) &&
               "stream->read_cb(status=-1) did not call uv_close()");
      }
      return;
    } else if (nread == 0) {
      /* EOF */
      uv__io_stop(stream->loop, &stream->io_watcher, UV__POLLIN);
      if (!uv__io_active(&stream->io_watcher, UV__POLLOUT))
        uv__handle_stop(stream);
      uv__set_artificial_error(stream->loop, UV_EOF);
      INVOKE_READ_CB(stream, -1, buf, UV_UNKNOWN_HANDLE);
      return;
    } else {
      /* Successful read */
      ssize_t buflen = buf.len;

      if (stream->read_cb) {
        stream->read_cb(stream, nread, buf);
      } else {
        assert(stream->read2_cb);

        /*
         * XXX: Some implementations can send multiple file descriptors in a
         * single message. We should be using CMSG_NXTHDR() to walk the
         * chain to get at them all. This would require changing the API to
         * hand these back up the caller, is a pain.
         */

        for (cmsg = CMSG_FIRSTHDR(&msg);
             msg.msg_controllen > 0 && cmsg != NULL;
             cmsg = CMSG_NXTHDR(&msg, cmsg)) {

          if (cmsg->cmsg_type == SCM_RIGHTS) {
            if (stream->accepted_fd != -1) {
              fprintf(stderr, "(libuv) ignoring extra FD received\n");
            }

            /* silence aliasing warning */
            {
              void* pv = CMSG_DATA(cmsg);
              int* pi = pv;
              stream->accepted_fd = *pi;
            }

          } else {
            fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n",
                cmsg->cmsg_type);
          }
        }


        if (stream->accepted_fd >= 0) {
          stream->read2_cb((uv_pipe_t*)stream, nread, buf,
              uv__handle_type(stream->accepted_fd));
        } else {
          stream->read2_cb((uv_pipe_t*)stream, nread, buf, UV_UNKNOWN_HANDLE);
        }
      }

      /* Return if we didn't fill the buffer, there is no more data to read. */
      if (nread < buflen) {
        return;
      }
    }
  }
}
Пример #23
0
int
myrecvfrom (int s, void *buf, int len, unsigned int flags,
            struct sockaddr *from, int *fromlen, struct sockaddr_in *myaddr)
{
    struct msghdr msg;

    struct iovec iov[1];

    int n;

    struct cmsghdr *cmptr;

    union
    {
        struct cmsghdr cm;
#ifdef IP_PKTINFO
        char control[CMSG_SPACE (sizeof (struct in_addr)) + CMSG_SPACE (sizeof (struct in_pktinfo))];
#else
        char control[CMSG_SPACE (sizeof (struct in_addr))];
#endif
    } control_un;

    int on = 1;

#ifdef IP_PKTINFO
    struct in_pktinfo pktinfo;
#endif

    /* Try to enable getting the return address */
#ifdef IP_RECVDSTADDR
    setsockopt (s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof (on));
#endif
#ifdef IP_PKTINFO
    setsockopt (s, IPPROTO_IP, IP_PKTINFO, &on, sizeof (on));
#endif

    msg.msg_control = control_un.control;
    msg.msg_controllen = sizeof (control_un.control);
    msg.msg_flags = 0;

    msg.msg_name = from;
    msg.msg_namelen = *fromlen;
    iov[0].iov_base = buf;
    iov[0].iov_len = len;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    if ((n = recvmsg (s, &msg, flags)) < 0)
        return n;                /* Error */

    *fromlen = msg.msg_namelen;

    if (myaddr)
    {
        bzero (myaddr, sizeof (struct sockaddr_in));
        myaddr->sin_family = AF_INET;

        if (msg.msg_controllen < sizeof (struct cmsghdr) || (msg.msg_flags & MSG_CTRUNC))
            return n;            /* No information available */

        for (cmptr = CMSG_FIRSTHDR (&msg); cmptr != NULL; cmptr = CMSG_NXTHDR (&msg, cmptr))
        {

#ifdef IP_RECVSTDADDR
            if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
            {
                memcpy (&myaddr->sin_addr, CMSG_DATA (cmptr), sizeof (struct in_addr));
            }
#endif

#ifdef IP_PKTINFO
            if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
            {
                memcpy (&pktinfo, CMSG_DATA (cmptr), sizeof (struct in_pktinfo));
                memcpy (&myaddr->sin_addr, &pktinfo.ipi_addr, sizeof (struct in_addr));
            }
#endif

        }
    }

    return n;
}
Пример #24
0
void main_loop(ping_func_set_st *fset, socket_st *sock, __u8 *packet, int packlen)
{
	char addrbuf[128];
	char ans_data[4096];
	struct iovec iov;
	struct msghdr msg;
	struct cmsghdr *c;
	int cc;
	int next;
	int polling;

	iov.iov_base = (char *)packet;

	for (;;) {
		/* Check exit conditions. */
		if (exiting)
			break;
		if (npackets && nreceived + nerrors >= npackets)
			break;
		if (deadline && nerrors)
			break;
		/* Check for and do special actions. */
		if (status_snapshot)
			status();

		/* Send probes scheduled to this time. */
		do {
			next = pinger(fset, sock);
			next = schedule_exit(next);
		} while (next <= 0);

		/* "next" is time to send next probe, if positive.
		 * If next<=0 send now or as soon as possible. */

		/* Technical part. Looks wicked. Could be dropped,
		 * if everyone used the newest kernel. :-)
		 * Its purpose is:
		 * 1. Provide intervals less than resolution of scheduler.
		 *    Solution: spinning.
		 * 2. Avoid use of poll(), when recvmsg() can provide
		 *    timed waiting (SO_RCVTIMEO). */
		polling = 0;
		if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
			int recv_expected = in_flight();

			/* If we are here, recvmsg() is unable to wait for
			 * required timeout. */
			if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) {
				/* Very short timeout... So, if we wait for
				 * something, we sleep for MININTERVAL.
				 * Otherwise, spin! */
				if (recv_expected) {
					next = MININTERVAL;
				} else {
					next = 0;
					/* When spinning, no reasons to poll.
					 * Use nonblocking recvmsg() instead. */
					polling = MSG_DONTWAIT;
					/* But yield yet. */
					sched_yield();
				}
			}

			if (!polling &&
			    ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
				struct pollfd pset;
				pset.fd = sock->fd;
				pset.events = POLLIN;
				pset.revents = 0;
				if (poll(&pset, 1, next) < 1 ||
				    !(pset.revents&(POLLIN|POLLERR)))
					continue;
				polling = MSG_DONTWAIT;
			}
		}

		for (;;) {
			struct timeval *recv_timep = NULL;
			struct timeval recv_time;
			int not_ours = 0; /* Raw socket can receive messages
					   * destined to other running pings. */

			iov.iov_len = packlen;
			memset(&msg, 0, sizeof(msg));
			msg.msg_name = addrbuf;
			msg.msg_namelen = sizeof(addrbuf);
			msg.msg_iov = &iov;
			msg.msg_iovlen = 1;
			msg.msg_control = ans_data;
			msg.msg_controllen = sizeof(ans_data);

			cc = recvmsg(sock->fd, &msg, polling);
			polling = MSG_DONTWAIT;

			if (cc < 0) {
				if (errno == EAGAIN || errno == EINTR)
					break;
				if (!fset->receive_error_msg(sock)) {
					if (errno) {
						perror("ping: recvmsg");
						break;
					}
					not_ours = 1;
				}
			} else {

#ifdef SO_TIMESTAMP
				for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
					if (c->cmsg_level != SOL_SOCKET ||
					    c->cmsg_type != SO_TIMESTAMP)
						continue;
					if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
						continue;
					recv_timep = (struct timeval*)CMSG_DATA(c);
				}
#endif

				if ((options&F_LATENCY) || recv_timep == NULL) {
					if ((options&F_LATENCY) ||
					    ioctl(sock->fd, SIOCGSTAMP, &recv_time))
						gettimeofday(&recv_time, NULL);
					recv_timep = &recv_time;
				}

				not_ours = fset->parse_reply(sock, &msg, cc, addrbuf, recv_timep);
			}

			/* See? ... someone runs another ping on this host. */
			if (not_ours && sock->socktype == SOCK_RAW)
				fset->install_filter(sock);

			/* If nothing is in flight, "break" returns us to pinger. */
			if (in_flight() == 0)
				break;

			/* Otherwise, try to recvmsg() again. recvmsg()
			 * is nonblocking after the first iteration, so that
			 * if nothing is queued, it will receive EAGAIN
			 * and return to pinger. */
		}
	}
	finish();
}
Пример #25
0
int receive_fd(int unix_socket, void* data, int data_len, int* fd)
{
	struct msghdr msg;
	struct iovec iov[1];
	int new_fd;
	int ret;
	int n;
#ifdef HAVE_MSGHDR_MSG_CONTROL
	struct cmsghdr* cmsg;
	union{
		struct cmsghdr cm;
		char control[CMSG_SPACE(sizeof(new_fd))];
	}control_un;
	
	msg.msg_control=control_un.control;
	msg.msg_controllen=sizeof(control_un.control);
#else
	msg.msg_accrights=(caddr_t) &new_fd;
	msg.msg_accrightslen=sizeof(int);
#endif
	
	msg.msg_name=0;
	msg.msg_namelen=0;
	
	iov[0].iov_base=data;
	iov[0].iov_len=data_len;
	msg.msg_iov=iov;
	msg.msg_iovlen=1;
	
again:
	ret=recvmsg(unix_socket, &msg, MSG_WAITALL);
	if (ret<0){
		if (errno==EINTR) goto again;
		LOG(L_CRIT, "ERROR: receive_fd: recvmsg on %d failed: %s\n",
				unix_socket, strerror(errno));
		goto error;
	}
	if (ret==0){
		/* EOF */
		LOG(L_CRIT, "ERROR: receive_fd: EOF on %d\n", unix_socket);
		goto error;
	}
	if (ret<data_len){
		LOG(L_WARN, "WARNING: receive_fd: too few bytes read (%d from %d)"
				    "trying to fix...\n", ret, data_len);
		n=recv_all(unix_socket, (char*)data+ret, data_len-ret);
		if (n>=0) ret+=n;
		else{
			ret=n;
			goto error;
		}
	}
	
#ifdef HAVE_MSGHDR_MSG_CONTROL
	cmsg=CMSG_FIRSTHDR(&msg);
	if ((cmsg!=0) && (cmsg->cmsg_len==CMSG_LEN(sizeof(new_fd)))){
		if (cmsg->cmsg_type!= SCM_RIGHTS){
			LOG(L_ERR, "ERROR: receive_fd: msg control type != SCM_RIGHTS\n");
			ret=-1;
			goto error;
		}
		if (cmsg->cmsg_level!= SOL_SOCKET){
			LOG(L_ERR, "ERROR: receive_fd: msg level != SOL_SOCKET\n");
			ret=-1;
			goto error;
		}
		*fd=*((int*) CMSG_DATA(cmsg));
	}else{
		LOG(L_ERR, "ERROR: receive_fd: no descriptor passed, cmsg=%p,"
				"len=%d\n", cmsg, (unsigned)cmsg->cmsg_len);
		*fd=-1;
		/* it's not really an error */
	}
#else
	if (msg.msg_accrightslen==sizeof(int)){
		*fd=new_fd;
	}else{
		LOG(L_ERR, "ERROR: receive_fd: no descriptor passed,"
				" accrightslen=%d\n", msg.msg_accrightslen);
		*fd=-1;
	}
#endif
	
error:
	return ret;
}
Пример #26
0
static void recvaddrs(int fd, struct ifaddrs **ifa, __u32 seq)
{
	char	buf[8192];
	struct sockaddr_nl nladdr;
	struct iovec iov = { buf, sizeof(buf) };
	struct ifaddrmsg *m;
	struct rtattr * rta_tb[IFA_MAX+1];
	struct ifaddrs *I;

	while (1) {
		int status;
		struct nlmsghdr *h;

		struct msghdr msg = {
			(void*)&nladdr, sizeof(nladdr),
			&iov,	1,
			NULL,	0,
			0
		};

		status = recvmsg(fd, &msg, 0);

		if (status < 0)
			continue;

		if (status == 0)
			return;

		h = (struct nlmsghdr*)buf;
		while (NLMSG_OK(h, status)) {
			if (h->nlmsg_seq != seq)
				goto skip_it;

			if (h->nlmsg_type == NLMSG_DONE)
				return;

			if (h->nlmsg_type == NLMSG_ERROR)
				return;

			if (h->nlmsg_type != RTM_NEWADDR)
				goto skip_it;

			m = NLMSG_DATA(h);

			if (m->ifa_family != AF_INET &&
			    m->ifa_family != AF_INET6)
				goto skip_it;

			if (m->ifa_flags&IFA_F_TENTATIVE)
				goto skip_it;

			memset(rta_tb, 0, sizeof(rta_tb));
			parse_rtattr(rta_tb, IFA_MAX, IFA_RTA(m), h->nlmsg_len - NLMSG_LENGTH(sizeof(*m)));

			if (rta_tb[IFA_LOCAL] == NULL)
				rta_tb[IFA_LOCAL] = rta_tb[IFA_ADDRESS];
			if (rta_tb[IFA_LOCAL] == NULL)
				goto skip_it;
			
			I = malloc(sizeof(struct ifaddrs));
			if (!I)
				return;
			memset(I, 0, sizeof(*I));

			I->ifa_ifindex = m->ifa_index;
			I->ifa_addr = (struct sockaddr*)&I->ifa_addrbuf;
			I->ifa_addr->sa_family = m->ifa_family;
			if (m->ifa_family == AF_INET) {
				struct sockaddr_in *sin = (void*)I->ifa_addr;
				memcpy(&sin->sin_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 4);
			} else {
				struct sockaddr_in6 *sin = (void*)I->ifa_addr;
				memcpy(&sin->sin6_addr, RTA_DATA(rta_tb[IFA_LOCAL]), 16);
				if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr))
					sin->sin6_scope_id = I->ifa_ifindex;
			}
			I->ifa_next = *ifa;
			*ifa = I;

skip_it:
			h = NLMSG_NEXT(h, status);
		}
		if (msg.msg_flags & MSG_TRUNC)
			continue;
	}
	return;
}
Пример #27
0
/*
 * This function runs in the context of the background proxy process.
 * Receive a control message from the parent (sent by the port_share_sendmsg
 * function above) and act on it.  Return false if the proxy process should
 * exit, true otherwise.
 */
static bool
control_message_from_parent(const socket_descriptor_t sd_control,
                            struct proxy_connection **list,
                            struct event_set *es,
                            const struct sockaddr_in server_addr,
                            const int max_initial_buf,
                            const char *journal_dir)
{
    /* this buffer needs to be large enough to handle the largest buffer
     * that might be returned by the link_socket_read call in read_incoming_link. */
    struct buffer buf = alloc_buf(max_initial_buf);

    struct msghdr mesg;
    struct cmsghdr *h;
    struct iovec iov[2];
    char command = 0;
    ssize_t status;
    int ret = true;

    CLEAR(mesg);

    iov[0].iov_base = &command;
    iov[0].iov_len = sizeof(command);
    iov[1].iov_base = BPTR(&buf);
    iov[1].iov_len = BCAP(&buf);
    mesg.msg_iov = iov;
    mesg.msg_iovlen = 2;

    mesg.msg_controllen = cmsg_size();
    mesg.msg_control = (char *) malloc(mesg.msg_controllen);
    check_malloc_return(mesg.msg_control);
    mesg.msg_flags = 0;

    h = CMSG_FIRSTHDR(&mesg);
    h->cmsg_len = CMSG_LEN(sizeof(socket_descriptor_t));
    h->cmsg_level = SOL_SOCKET;
    h->cmsg_type = SCM_RIGHTS;
    static const socket_descriptor_t socket_undefined = SOCKET_UNDEFINED;
    memcpy(CMSG_DATA(h), &socket_undefined, sizeof(socket_undefined));

    status = recvmsg(sd_control, &mesg, MSG_NOSIGNAL);
    if (status != -1)
    {
        if (h == NULL
            || h->cmsg_len    != CMSG_LEN(sizeof(socket_descriptor_t))
            || h->cmsg_level  != SOL_SOCKET
            || h->cmsg_type   != SCM_RIGHTS)
        {
            msg(M_WARN, "PORT SHARE PROXY: received unknown message");
        }
        else
        {
            socket_descriptor_t received_fd;
            memcpy(&received_fd, CMSG_DATA(h), sizeof(received_fd));
            dmsg(D_PS_PROXY_DEBUG, "PORT SHARE PROXY: RECEIVED sd=%d", (int)received_fd);

            if (status >= 2 && command == COMMAND_REDIRECT)
            {
                buf.len = status - 1;
                if (proxy_entry_new(list,
                                    es,
                                    server_addr,
                                    received_fd,
                                    &buf,
                                    journal_dir))
                {
                    CLEAR(buf); /* we gave the buffer to proxy_entry_new */
                }
                else
                {
                    openvpn_close_socket(received_fd);
                }
            }
            else if (status >= 1 && command == COMMAND_EXIT)
            {
                dmsg(D_PS_PROXY_DEBUG, "PORT SHARE PROXY: RECEIVED COMMAND_EXIT");
                openvpn_close_socket(received_fd); /* null socket */
                ret = false;
            }
        }
    }
    free(mesg.msg_control);
    free_buf(&buf);
    return ret;
}
Пример #28
0
/* Query all of the listed hosts */
static void
query_loop(char *argv[], int argc, int soc)
{
#define	NA0 (OMSG.rip_auths[0])
#define	NA2 (OMSG.rip_auths[2])
	struct seen {
		struct seen *next;
		struct in_addr addr;
	} *seen, *sp;
	int answered = 0;
	int cc;
	fd_set bits;
	struct timeval now, delay;
	struct sockaddr_in from;
	MD5_CTX md5_ctx;
	struct msghdr msg;
	uint_t	ifindex;
	struct iovec iov;
	uint8_t ancillary_data[CONTROL_BUFSIZE];


	OMSG.rip_cmd = (pflag) ? RIPCMD_POLL : RIPCMD_REQUEST;
	if (ripv2) {
		OMSG.rip_vers = RIPv2;
		if (auth_type == RIP_AUTH_PW) {
			OMSG.rip_nets[1] = OMSG.rip_nets[0];
			NA0.a_family = RIP_AF_AUTH;
			NA0.a_type = RIP_AUTH_PW;
			(void) memcpy(NA0.au.au_pw, passwd, RIP_AUTH_PW_LEN);
			omsg_len += sizeof (OMSG.rip_nets[0]);

		} else if (auth_type == RIP_AUTH_MD5) {
			OMSG.rip_nets[1] = OMSG.rip_nets[0];
			NA0.a_family = RIP_AF_AUTH;
			NA0.a_type = RIP_AUTH_MD5;
			NA0.au.a_md5.md5_keyid = (int8_t)keyid;
			NA0.au.a_md5.md5_auth_len = RIP_AUTH_MD5_LEN;
			NA0.au.a_md5.md5_seqno = 0;
			cc = (char *)&NA2-(char *)&OMSG;
			NA0.au.a_md5.md5_pkt_len = htons(cc);
			NA2.a_family = RIP_AF_AUTH;
			NA2.a_type = RIP_AUTH_TRAILER;
			MD5Init(&md5_ctx);
			MD5Update(&md5_ctx, (uchar_t *)&OMSG, cc+4);
			MD5Update(&md5_ctx,
			    (uchar_t *)passwd, RIP_AUTH_MD5_LEN);
			MD5Final(NA2.au.au_pw, &md5_ctx);
			omsg_len += 2*sizeof (OMSG.rip_nets[0]);
		}

	} else {
		OMSG.rip_vers = RIPv1;
		OMSG.rip_nets[0].n_mask = 0;
	}

	/* ask the first (valid) host */
	seen = NULL;
	while (0 > out(*argv++, soc)) {
		if (*argv == NULL)
			exit(EXIT_FAILURE);
		answered++;
	}

	iov.iov_base = &imsg_buf;
	iov.iov_len = sizeof (imsg_buf);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_name = &from;
	msg.msg_control = &ancillary_data;

	(void) FD_ZERO(&bits);
	FD_SET(soc, &bits);
	for (;;) {
		delay.tv_sec = 0;
		delay.tv_usec = STIME;
		cc = select(soc+1, &bits, 0, 0, &delay);
		if (cc > 0) {
			msg.msg_namelen = sizeof (from);
			msg.msg_controllen = sizeof (ancillary_data);
			cc = recvmsg(soc, &msg, 0);
			if (cc < 0) {
				perror("rtquery: recvmsg");
				exit(EXIT_FAILURE);
			}

			/* avoid looping on high traffic */
			if (answered > argc + 200)
				break;

			/*
			 * count the distinct responding hosts.
			 * You cannot match responding hosts with
			 * addresses to which queries were transmitted,
			 * because a router might respond with a
			 * different source address.
			 */
			for (sp = seen; sp != NULL; sp = sp->next) {
				if (sp->addr.s_addr == from.sin_addr.s_addr)
					break;
			}
			if (sp == NULL) {
				sp = malloc(sizeof (*sp));
				if (sp != NULL) {
					sp->addr = from.sin_addr;
					sp->next = seen;
					seen = sp;
				} else {
					perror("rtquery: malloc");
				}
				answered++;
			}

			ifindex = incoming_interface(&msg);
			rip_input(&from, cc, ifindex);
			continue;
		}

		if (cc < 0) {
			if (errno == EINTR)
				continue;
			perror("rtquery: select");
			exit(EXIT_FAILURE);
		}

		/*
		 * After a pause in responses, probe another host.
		 * This reduces the intermingling of answers.
		 */
		while (*argv != NULL && 0 > out(*argv++, soc))
			answered++;

		/*
		 * continue until no more packets arrive
		 * or we have heard from all hosts
		 */
		if (answered >= argc)
			break;

		/* or until we have waited a long time */
		if (gettimeofday(&now, 0) < 0) {
			perror("rtquery: gettimeofday");
			exit(EXIT_FAILURE);
		}
		if (sent.tv_sec + wtime <= now.tv_sec)
			break;
	}

	/* fail if there was no answer */
	exit(answered >= argc ? EXIT_SUCCESS : EXIT_FAILURE);
}
Пример #29
0
static int print_interfaces() {
	int sock, len;
	struct nlmsghdr *nlm;
	struct iovec iov;
	struct msghdr rtnl_msg;
	struct sockaddr_nl s_nl;
	struct {
		struct nlmsghdr nh;
		struct rtgenmsg rtgm;
	} req;
	char buf[8192];

	printf("Network interfaces:\n");

	/* open netlink socket */
	sock = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
	if (sock < 0) {
		perror("sock");
		return 1;
	}

	/* initialize request */
	memset(&req, 0, sizeof(req));
	req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(req.rtgm));
	req.nh.nlmsg_type = RTM_GETLINK;
	req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
	req.nh.nlmsg_seq = 1;
	req.nh.nlmsg_pid = getpid();
	req.rtgm.rtgen_family = AF_PACKET;

	memset(&s_nl, 0, sizeof(s_nl));
	s_nl.nl_family = AF_NETLINK;

	iov.iov_base = &req;
	iov.iov_len = req.nh.nlmsg_len;

	memset(&rtnl_msg, 0, sizeof(rtnl_msg));
	rtnl_msg.msg_iov = &iov;
	rtnl_msg.msg_iovlen = 1;
	rtnl_msg.msg_name = &s_nl;
	rtnl_msg.msg_namelen = sizeof(s_nl);

	/* send request */
	len = sendmsg(sock, &rtnl_msg, 0);
	if (len < 0) {
		perror("sendmsg");
		close(sock);
		return 1;
	}

	int end = 0;
	while (!end) {
		iov.iov_base = buf;
		iov.iov_len = sizeof(buf);

		memset(&rtnl_msg, 0, sizeof(rtnl_msg));
		rtnl_msg.msg_iov = &iov;
		rtnl_msg.msg_iovlen = 1;
		rtnl_msg.msg_name = &s_nl;
		rtnl_msg.msg_namelen = sizeof(s_nl);

		/* receive response */
		len = recvmsg(sock, &rtnl_msg, 0);
		if (len < 0) {
			perror("recvmsg");
			close(sock);
			return 1;
		}

		/* read response */
		nlm = (struct nlmsghdr*)buf;
		while (NLMSG_OK(nlm, len)) {
			if (nlm->nlmsg_type == NLMSG_DONE) {
				end = 1;
				break;
			} else if (nlm->nlmsg_type == RTM_NEWLINK) {
				struct ifinfomsg *ifinfo;
				struct rtattr *rta;
				int iflen;

				ifinfo = NLMSG_DATA(nlm);
				rta = IFLA_RTA(ifinfo);
				iflen = IFLA_PAYLOAD(nlm);

				while (RTA_OK(rta, iflen)) {
					if (rta->rta_type == IFLA_IFNAME)
						printf("  %s\n", (char*)RTA_DATA(rta));
					rta = RTA_NEXT(rta, iflen);
				}
			}
			nlm = NLMSG_NEXT(nlm, len);
		}
	}

	close(sock);
	return 0;
}
Пример #30
0
static int dgram_sctp_read(BIO *b, char *out, int outl)
	{
	int ret = 0, n = 0, i, optval;
	socklen_t optlen;
	bio_dgram_sctp_data *data = (bio_dgram_sctp_data *)b->ptr;
	union sctp_notification *snp;
	struct msghdr msg;
	struct iovec iov;
	struct cmsghdr *cmsg;
	char cmsgbuf[512];

	if (out != NULL)
		{
		clear_socket_error();

		do
			{
			memset(&data->rcvinfo, 0x00, sizeof(struct bio_dgram_sctp_rcvinfo));
			iov.iov_base = out;
			iov.iov_len = outl;
			msg.msg_name = NULL;
			msg.msg_namelen = 0;
			msg.msg_iov = &iov;
			msg.msg_iovlen = 1;
			msg.msg_control = cmsgbuf;
			msg.msg_controllen = 512;
			msg.msg_flags = 0;
			n = recvmsg(b->num, &msg, 0);

			if (n <= 0)
				{
				if (n < 0)
					ret = n;
				break;
				}

			if (msg.msg_controllen > 0)
				{
				for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg))
					{
					if (cmsg->cmsg_level != IPPROTO_SCTP)
						continue;
#ifdef SCTP_RCVINFO
					if (cmsg->cmsg_type == SCTP_RCVINFO)
						{
						struct sctp_rcvinfo *rcvinfo;

						rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
						data->rcvinfo.rcv_sid = rcvinfo->rcv_sid;
						data->rcvinfo.rcv_ssn = rcvinfo->rcv_ssn;
						data->rcvinfo.rcv_flags = rcvinfo->rcv_flags;
						data->rcvinfo.rcv_ppid = rcvinfo->rcv_ppid;
						data->rcvinfo.rcv_tsn = rcvinfo->rcv_tsn;
						data->rcvinfo.rcv_cumtsn = rcvinfo->rcv_cumtsn;
						data->rcvinfo.rcv_context = rcvinfo->rcv_context;
						}
#endif
#ifdef SCTP_SNDRCV
					if (cmsg->cmsg_type == SCTP_SNDRCV)
						{
						struct sctp_sndrcvinfo *sndrcvinfo;

						sndrcvinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
						data->rcvinfo.rcv_sid = sndrcvinfo->sinfo_stream;
						data->rcvinfo.rcv_ssn = sndrcvinfo->sinfo_ssn;
						data->rcvinfo.rcv_flags = sndrcvinfo->sinfo_flags;
						data->rcvinfo.rcv_ppid = sndrcvinfo->sinfo_ppid;
						data->rcvinfo.rcv_tsn = sndrcvinfo->sinfo_tsn;
						data->rcvinfo.rcv_cumtsn = sndrcvinfo->sinfo_cumtsn;
						data->rcvinfo.rcv_context = sndrcvinfo->sinfo_context;
						}
#endif
					}
				}

			if (msg.msg_flags & MSG_NOTIFICATION)
				{
				snp = (union sctp_notification*) out;
				if (snp->sn_header.sn_type == SCTP_SENDER_DRY_EVENT)
					{
#ifdef SCTP_EVENT
					struct sctp_event event;
#else
					struct sctp_event_subscribe event;
					socklen_t eventsize;
#endif
					/* If a message has been delayed until the socket
					 * is dry, it can be sent now.
					 */
					if (data->saved_message.length > 0)
						{
						dgram_sctp_write(data->saved_message.bio, data->saved_message.data,
						                 data->saved_message.length);
						OPENSSL_free(data->saved_message.data);
						data->saved_message.length = 0;
						}

					/* disable sender dry event */
#ifdef SCTP_EVENT
					memset(&event, 0, sizeof(struct sctp_event));
					event.se_assoc_id = 0;
					event.se_type = SCTP_SENDER_DRY_EVENT;
					event.se_on = 0;
					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(struct sctp_event));
					OPENSSL_assert(i >= 0);
#else
					eventsize = sizeof(struct sctp_event_subscribe);
					i = getsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, &eventsize);
					OPENSSL_assert(i >= 0);

					event.sctp_sender_dry_event = 0;

					i = setsockopt(b->num, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(struct sctp_event_subscribe));
					OPENSSL_assert(i >= 0);
#endif
					}

#ifdef SCTP_AUTHENTICATION_EVENT
				if (snp->sn_header.sn_type == SCTP_AUTHENTICATION_EVENT)
					dgram_sctp_handle_auth_free_key_event(b, snp);
#endif

				if (data->handle_notifications != NULL)
					data->handle_notifications(b, data->notification_context, (void*) out);

				memset(out, 0, outl);
				}
			else
				ret += n;
			}
		while ((msg.msg_flags & MSG_NOTIFICATION) && (msg.msg_flags & MSG_EOR) && (ret < outl));

		if (ret > 0 && !(msg.msg_flags & MSG_EOR))
			{
			/* Partial message read, this should never happen! */

			/* The buffer was too small, this means the peer sent
			 * a message that was larger than allowed. */
			if (ret == outl)
				return -1;

			/* Test if socket buffer can handle max record
			 * size (2^14 + 2048 + 13)
			 */
			optlen = (socklen_t) sizeof(int);
			ret = getsockopt(b->num, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);
			OPENSSL_assert(ret >= 0);
			OPENSSL_assert(optval >= 18445);

			/* Test if SCTP doesn't partially deliver below
			 * max record size (2^14 + 2048 + 13)
			 */
			optlen = (socklen_t) sizeof(int);
			ret = getsockopt(b->num, IPPROTO_SCTP, SCTP_PARTIAL_DELIVERY_POINT,
			                 &optval, &optlen);
			OPENSSL_assert(ret >= 0);
			OPENSSL_assert(optval >= 18445);

			/* Partially delivered notification??? Probably a bug.... */
			OPENSSL_assert(!(msg.msg_flags & MSG_NOTIFICATION));

			/* Everything seems ok till now, so it's most likely
			 * a message dropped by PR-SCTP.
			 */
			memset(out, 0, outl);
			BIO_set_retry_read(b);
			return -1;
			}

		BIO_clear_retry_flags(b);
		if (ret < 0)
			{
			if (BIO_dgram_should_retry(ret))
				{
				BIO_set_retry_read(b);
				data->_errno = get_last_socket_error();
				}
			}

		/* Test if peer uses SCTP-AUTH before continuing */
		if (!data->peer_auth_tested)
			{
			int ii, auth_data = 0, auth_forward = 0;
			unsigned char *p;
			struct sctp_authchunks *authchunks;

			optlen = (socklen_t)(sizeof(sctp_assoc_t) + 256 * sizeof(uint8_t));
			authchunks = OPENSSL_malloc(optlen);
			memset(authchunks, 0, optlen);
			ii = getsockopt(b->num, IPPROTO_SCTP, SCTP_PEER_AUTH_CHUNKS, authchunks, &optlen);
			OPENSSL_assert(ii >= 0);

			for (p = (unsigned char*) authchunks->gauth_chunks;
				 p < (unsigned char*) authchunks + optlen;
				 p += sizeof(uint8_t))
				{
				if (*p == OPENSSL_SCTP_DATA_CHUNK_TYPE) auth_data = 1;
				if (*p == OPENSSL_SCTP_FORWARD_CUM_TSN_CHUNK_TYPE) auth_forward = 1;
				}

			OPENSSL_free(authchunks);

			if (!auth_data || !auth_forward)
				{
				BIOerr(BIO_F_DGRAM_SCTP_READ,BIO_R_CONNECT_ERROR);
				return -1;
				}

			data->peer_auth_tested = 1;
			}
		}
	return(ret);
	}