Esempio n. 1
0
int send_can_ping(int can_socket, int verbose) {
    if (frame_to_can(can_socket, M_CAN_PING) < 0) {
	fprintf(stderr, "can't send CAN Ping\n");
	syslog(LOG_ERR, "%s: can't send CAN Ping\n", __func__);
	return -1;
    } else {
	if (verbose) {
	    /* printf("                CAN Ping sent\n"); */
	    print_can_frame(CAN_FORMAT_STRG, M_CAN_PING, verbose);
	}
    }
    return 0;
}
Esempio n. 2
0
int send_magic_start_60113_frame(int can_socket, int verbose) {
    int ret;
    ret = frame_to_can(can_socket, &M_GLEISBOX_MAGIC_START_SEQUENCE[0]);
    if (ret < 0 ) {
	perror("error CAN magic 60113 start write\n");
	return -1;
    } else {
	if (verbose)
	    printf("                CAN magic 60113 start write\n");
	    print_can_frame(CAN_FORMAT_STRG, M_GLEISBOX_MAGIC_START_SEQUENCE);
    }
    return 0;
}
Esempio n. 3
0
int send_start_60113_frames(int can_socket, int verbose) {
    if (frame_to_can(can_socket, M_GLEISBOX_MAGIC_START_SEQUENCE) < 0) {
	fprintf(stderr, "can't send CAN magic 60113 start sequence\n");
	syslog(LOG_ERR, "%s: can't send CAN magic 60113 start sequence\n", __func__);
	return -1;
    } else {
	if (verbose) {
	    printf("                CAN magic 60113 start written\n");
	    print_can_frame(CAN_FORMAT_STRG, M_GLEISBOX_MAGIC_START_SEQUENCE, verbose);
	}
    }
    if (frame_to_can(can_socket, M_GLEISBOX_ALL_PROTO_ENABLE) < 0) {
	fprintf(stderr, "can't enable all loco protos\n");
	syslog(LOG_ERR, "%s: can't enable all loco protos\n", __func__);
	return -1;
    } else {
	if (verbose) {
	    printf("                CAN enabled all loco protos\n");
	    print_can_frame(CAN_FORMAT_STRG, M_GLEISBOX_ALL_PROTO_ENABLE, verbose);
	}
    }

    return 0;
}
Esempio n. 4
0
int main(int argc, char **argv) {
    pid_t pid;
    int n, i, max_fds, opt, max_tcp_i, nready, conn_fd, timeout, tcp_client[MAX_TCP_CONN];
    struct can_frame frame;
    char timestamp[16];
    /* UDP incoming socket , CAN socket, UDP broadcast socket, TCP socket */
    int sa, sc, sb, st, st2, tcp_socket;
    struct sockaddr_in saddr, baddr, tcp_addr, tcp_addr2;
    /* vars for determing broadcast address */
    struct ifaddrs *ifap, *ifa;
    struct sockaddr_in *bsa;
    struct sockaddr_can caddr;
    struct ifreq ifr;
    socklen_t caddrlen = sizeof(caddr);
    socklen_t tcp_client_length = sizeof(tcp_addr);
    fd_set all_fds, read_fds;
    int s, ret;
    struct timeval tv;
    char *udp_dst_address;
    char *bcast_interface;
    struct cs2_config_data_t cs2_config_data;

    int local_udp_port = 15731;
    int local_tcp_port = 15731;
    int local2_tcp_port = 15732;
    int destination_port = 15730;
    int background = 1;
    /* const int off = 0; */
    const int on = 1;
    uint32_t canid;
    char buffer[64];

    /* clear timestamp for last CAN frame sent */
    memset(&last_sent, 0, sizeof(last_sent));

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

    page_name = calloc(MAX_TRACK_PAGE, sizeof(char *));
    if (!page_name) {
	fprintf(stderr, "can't alloc memory for page_name: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    };

    cs2_page_name = calloc(MAX_TRACK_PAGE, sizeof(char *));
    if (!cs2_page_name) {
	fprintf(stderr, "can't alloc memory for cs2_page_name: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    };

    ms1_workaround = 0;
    cs2fake_ping = 0;

    cs2_config_data.verbose = 0;
    cs2_config_data.state = CS2_STATE_INACTIVE;
    cs2_config_data.page_name = cs2_page_name;
    cs2_config_data.cs2_config_copy = 0;
    cs2_config_data.cs2_tcp_socket = 0;
    cs2_config_data.track_index = MAX_TRACK_PAGE;

    memset(ifr.ifr_name, 0, sizeof(ifr.ifr_name));
    strcpy(ifr.ifr_name, "can0");
    memset(config_dir, 0, sizeof(config_dir));

    udp_dst_address = (char *)calloc(MAXIPLEN, 1);
    if (!udp_dst_address) {
	fprintf(stderr, "can't alloc memory for udp_dst_address: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    };

    bcast_interface = (char *)calloc(MAXIPLEN, 1);
    if (!bcast_interface) {
	fprintf(stderr, "can't alloc memory for bcast_interface: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    };

    timeout = MAX_UDP_BCAST_RETRY;
    strcpy(udp_dst_address, "255.255.255.255");
    strcpy(bcast_interface, "br-lan");

    config_file[0] = '\0';

    while ((opt = getopt(argc, argv, "c:u:s:t:d:b:i:kT:gmvhf?")) != -1) {
	switch (opt) {
	case 'c':
	    if (strnlen(optarg, MAXLINE) < MAXLINE) {
		strncpy(config_dir, optarg, sizeof(config_dir) - 1);
	    } else {
		fprintf(stderr, "config file dir to long\n");
		exit(EXIT_FAILURE);
	    }
	    break;
	case 'u':
	    local_udp_port = strtoul(optarg, (char **)NULL, 10);
	    break;
	case 't':
	    local_tcp_port = strtoul(optarg, (char **)NULL, 10);
	    break;
	case 's':
	    local2_tcp_port = strtoul(optarg, (char **)NULL, 10);
	    break;
	case 'd':
	    destination_port = strtoul(optarg, (char **)NULL, 10);
	    break;
	case 'b':
	    if (strnlen(optarg, MAXIPLEN) <= MAXIPLEN - 1) {
		/* IP address begins with a number */
		if ((optarg[0] >= '0') && (optarg[0] <= '9')) {
		    memset(udp_dst_address, 0, MAXIPLEN);
		    strncpy(udp_dst_address, optarg, MAXIPLEN - 1);
		} else {
		    memset(udp_dst_address, 0, MAXIPLEN);
		    memset(bcast_interface, 0, MAXIPLEN);
		    strncpy(bcast_interface, optarg, MAXIPLEN - 1);
		}
	    } else {
		fprintf(stderr, "UDP broadcast address or interface error: %s\n", optarg);
		exit(EXIT_FAILURE);
	    }
	    break;
	case 'i':
	    strncpy(ifr.ifr_name, optarg, sizeof(ifr.ifr_name) - 1);
	    break;
	case 'k':
	    cs2_config_data.cs2_config_copy = 1;
	    break;
	case 'T':
	    timeout = strtoul(optarg, (char **)NULL, 10);
	    break;
	case 'g':
	    cs2fake_ping = 1;
	    break;
	case 'm':
	    ms1_workaround = 1;
	    break;
	case 'v':
	    cs2_config_data.verbose = 1;
	    break;
	case 'f':
	    background = 0;
	    break;
	case 'h':
	case '?':
	    print_usage(basename(argv[0]));
	    exit(EXIT_SUCCESS);
	default:
	    fprintf(stderr, "Unknown option %c\n", opt);
	    print_usage(basename(argv[0]));
	    exit(EXIT_FAILURE);
	}
    }

    /* read track file */
    if (config_dir[0] == 0) {
	strcat(config_file, ".");
    }

    strcat(config_file, config_dir);
    if (config_dir[strlen(config_dir) - 1] != '/') {
	strcat(config_file, "/");
    }
    strncpy(config_dir, config_file, sizeof(config_dir) - 1);
    strcat(config_file, "gleisbild.cs2");

    cs2_config_data.dir = config_dir;

    page_name = read_track_file(config_file, page_name);

    /* we are trying to setup a UDP socket */
    for (i = 0; i < timeout; i++) {
	/* trying to get the broadcast address */
	getifaddrs(&ifap);
	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
	    if (ifa->ifa_addr) {
		if (ifa->ifa_addr->sa_family == AF_INET) {
		    bsa = (struct sockaddr_in *)ifa->ifa_broadaddr;
		    if (strncmp(ifa->ifa_name, bcast_interface, strlen(bcast_interface)) == 0)
			udp_dst_address = inet_ntoa(bsa->sin_addr);
		}
	    }
	}
	/* try to prepare UDP sending socket struct */
	memset(&baddr, 0, sizeof(baddr));
	baddr.sin_family = AF_INET;
	baddr.sin_port = htons(destination_port);
	s = inet_pton(AF_INET, udp_dst_address, &baddr.sin_addr);
	if (s > 0)
	    break;
	sleep(1);
    }
    /* check if we got a real UDP socket after MAX_UDP_BCAST_TRY seconds */
    if (s <= 0) {
	if (s == 0) {
	    fprintf(stderr, "UDP IP address invalid\n");
	} else {
	    fprintf(stderr, "invalid address family\n");
	}
	exit(EXIT_FAILURE);
    }

    if (cs2_config_data.verbose & !background)
	printf("using broadcast address %s\n", udp_dst_address);

    /* prepare UDP sending socket */
    sb = socket(AF_INET, SOCK_DGRAM, 0);
    if (sb < 0) {
	fprintf(stderr, "error creating UDP sending socket: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    if (setsockopt(sb, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
	fprintf(stderr, "error setup UDP broadcast option: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }

    /* prepare reading UDP socket */
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(local_udp_port);
    sa = socket(PF_INET, SOCK_DGRAM, 0);
    if (sa < 0) {
	fprintf(stderr, "creating UDP reading socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    if (bind(sa, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
	fprintf(stderr, "binding UDP reading socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }

    /* prepare TCP socket */
    st = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (st < 0) {
	fprintf(stderr, "creating TCP socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    /* disable Nagle */
    /*if (setsockopt(st, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0) {
	fprintf(stderr, "error disabling Nagle - TCP_NODELAY on: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    */
    /* disable TCP_CORK */
    /*
    if (setsockopt(st, IPPROTO_TCP, TCP_CORK, &off, sizeof(off)) < 0) {
	fprintf(stderr, "error disabling Nagle - TCP_CORK off: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    } */
    tcp_addr.sin_family = AF_INET;
    tcp_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    tcp_addr.sin_port = htons(local_tcp_port);
    if (bind(st, (struct sockaddr *)&tcp_addr, sizeof(tcp_addr)) < 0) {
	fprintf(stderr, "binding TCP socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    if (listen(st, MAXPENDING) < 0) {
	fprintf(stderr, "starting TCP listener error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    /* prepare TCP clients array */
    max_tcp_i = -1;		/* index into tcp_client[] array */
    for (i = 0; i < MAX_TCP_CONN; i++)
	tcp_client[i] = -1;	/* -1 indicates available entry */

    /* prepare second TCP socket */
    st2 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (st2 < 0) {
	fprintf(stderr, "creating second TCP socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    tcp_addr2.sin_family = AF_INET;
    tcp_addr2.sin_addr.s_addr = htonl(INADDR_ANY);
    tcp_addr2.sin_port = htons(local2_tcp_port);
    if (bind(st2, (struct sockaddr *)&tcp_addr2, sizeof(tcp_addr2)) < 0) {
	fprintf(stderr, "binding second TCP socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    if (listen(st2, MAXPENDING) < 0) {
	fprintf(stderr, "starting TCP listener error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
#if 0
    /* prepare TCP clients array */
    max_tcp_i = -1;		/* index into tcp_client[] array */
    for (i = 0; i < MAX_TCP_CONN; i++)
	tcp_client[i] = -1;	/* -1 indicates available entry */
#endif

    /* prepare CAN socket */
    memset(&caddr, 0, sizeof(caddr));
    sc = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (sc < 0) {
	fprintf(stderr, "creating CAN socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    caddr.can_family = AF_CAN;
    if (ioctl(sc, SIOCGIFINDEX, &ifr) < 0) {
	fprintf(stderr, "setup CAN error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    caddr.can_ifindex = ifr.ifr_ifindex;

    if (bind(sc, (struct sockaddr *)&caddr, caddrlen) < 0) {
	fprintf(stderr, "binding CAN socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }

    /* start Maerklin 60113 box */
    if (send_start_60113_frames(sc, cs2_config_data.verbose))
	exit(EXIT_FAILURE);

    /* daemonize the process if requested */
    if (background) {
	/* fork off the parent process */
	pid = fork();
	if (pid < 0)
	    exit(EXIT_FAILURE);
	/* if we got a good PID, then we can exit the parent process */
	if (pid > 0) {
	    printf("Going into background ...\n");
	    exit(EXIT_SUCCESS);
	}
    }

    setlogmask(LOG_UPTO(LOG_NOTICE));
    openlog("can2lan", LOG_CONS | LOG_NDELAY, LOG_DAEMON);

    /* set select timeout -> send periodic CAN Ping */
    memset(&tv, 0, sizeof(tv));
    tv.tv_sec = 1;
    tv.tv_usec = 0;

    FD_ZERO(&all_fds);
    FD_SET(sc, &all_fds);
    FD_SET(sa, &all_fds);
    FD_SET(st, &all_fds);
    FD_SET(st2, &all_fds);
    max_fds = MAX(MAX(MAX(sc, sa), st), st2);

    while (1) {
	read_fds = all_fds;
	nready = select(max_fds + 1, &read_fds, NULL, NULL, &tv);
	if (nready == 0) {
	    /*    send_can_ping(sc); */
	    tv.tv_sec = 1;
	    tv.tv_usec = 0;
	    continue;
	} else if (nready < 0)
	    fprintf(stderr, "select error: %s\n", strerror(errno));

	tv.tv_sec = 1;
	tv.tv_usec = 0;

	/* received a CAN frame */
	if (FD_ISSET(sc, &read_fds)) {
	    /* reading via SockatCAN */
	    if (read(sc, &frame, sizeof(struct can_frame)) < 0) {
		fprintf(stderr, "reading CAN frame error: %s\n", strerror(errno));
		syslog(LOG_ERR, "%s: reading CAN frame error: %s\n", __func__, strerror(errno));
	    }
	    /* if CAN Frame is EFF do it */
	    if (frame.can_id & CAN_EFF_FLAG) {	/* only EFF frames are valid */
		/* send UDP frame */
		frame_to_net(sb, (struct sockaddr *)&baddr, (struct can_frame *)&frame);
		print_can_frame(UDP_FORMAT_STRG, netframe, cs2_config_data.verbose & !background);
		/* send CAN frame to all connected TCP clients */
		/* TODO: need all clients the packets ? */
		for (i = 0; i <= max_tcp_i; i++) {	/* check all clients for data */
		    tcp_socket = tcp_client[i];
		    if (tcp_socket < 0)
			continue;
		    frame_to_net(tcp_socket, (struct sockaddr *)&tcp_addr, (struct can_frame *)&frame);
		    print_can_frame(CAN_TCP_FORMAT_STRG, netframe, cs2_config_data.verbose & !background);
		}
	    }
	}
	/* received a UDP packet */
	if (FD_ISSET(sa, &read_fds)) {
	    if (read(sa, netframe, MAXDG) == CAN_ENCAP_SIZE) {
		/* check for S88 events on send them to TCP connected clients */
		memcpy(&canid, netframe, 4);
		canid = ntohl(canid);
		if ((canid & 0x00230000) == 0x00230000) {
		    printf("UDP : canid 0x%08x\n", canid);
		    for (i = 0; i <= max_tcp_i; i++) {
			tcp_socket = tcp_client[i];
			if (tcp_socket < 0)
			    continue;
			net_to_net(tcp_socket, NULL, netframe, CAN_ENCAP_SIZE);
			print_can_frame(UDP_TCP_FORMAT_STRG, netframe, cs2_config_data.verbose & !background);
	    		net_to_net(sb, (struct sockaddr *)&baddr, netframe, CAN_ENCAP_SIZE);
			print_can_frame(UDP_UDP_FORMAT_STRG, netframe, cs2_config_data.verbose & !background);
		    }
		} else {
		/* send packet on CAN */
		    ret = frame_to_can(sc, netframe);
		    print_can_frame(NET_UDP_FORMAT_STRG, netframe, cs2_config_data.verbose & !background);
		    check_data_udp(sb, (struct sockaddr *)&baddr, &cs2_config_data, netframe);
		}
	    }
	}
	/* received a TCP packet */
	if (FD_ISSET(st, &read_fds)) {
	    conn_fd = accept(st, (struct sockaddr *)&tcp_addr, &tcp_client_length);
	    if (cs2_config_data.verbose && !background) {
		printf("new client: %s, port %d conn fd: %d max fds: %d\n", inet_ntop(AF_INET, &(tcp_addr.sin_addr),
			buffer, sizeof(buffer)), ntohs(tcp_addr.sin_port), conn_fd, max_fds);
	    }
	    syslog(LOG_NOTICE, "%s: new client: %s port %d conn fd: %d max fds: %d\n", __func__,
			 inet_ntop(AF_INET, &(tcp_addr.sin_addr), buffer, sizeof(buffer)), ntohs(tcp_addr.sin_port), conn_fd, max_fds);
	    for (i = 0; i < MAX_TCP_CONN; i++) {
		if (tcp_client[i] < 0) {
		    tcp_client[i] = conn_fd;	/* save new TCP client descriptor */
		    break;
		}
	    }
	    if (i == MAX_TCP_CONN) {
		fprintf(stderr, "too many TCP clients\n");
		syslog(LOG_ERR, "%s: too many TCP clients\n", __func__);
	    }

	    FD_SET(conn_fd, &all_fds);		/* add new descriptor to set */
	    max_fds = MAX(conn_fd, max_fds);	/* for select */
	    max_tcp_i = MAX(i, max_tcp_i);	/* max index in tcp_client[] array */
	    /* send embedded CAN ping */
	    memcpy(netframe, M_CAN_PING, CAN_ENCAP_SIZE);
	    net_to_net(conn_fd, NULL, netframe, CAN_ENCAP_SIZE);
	    if (cs2_config_data.verbose && !background)
		printf("send embedded CAN ping\n");

	    if (--nready <= 0)
		continue;	/* no more readable descriptors */
	}
	/* received a packet on second TCP port */
	if (FD_ISSET(st2, &read_fds)) {
	    conn_fd = accept(st2, (struct sockaddr *)&tcp_addr2, &tcp_client_length);

	    /* TODO : close missing */
	    if (cs2_config_data.verbose && !background) {
		printf("new client: %s, port %d conn fd: %d max fds: %d\n", inet_ntop(AF_INET, &(tcp_addr2.sin_addr),
			buffer, sizeof(buffer)), ntohs(tcp_addr2.sin_port), conn_fd, max_fds);
	    }
	    syslog(LOG_NOTICE, "%s: new client: %s port %d conn fd: %d max fds: %d\n", __func__,
			 inet_ntop(AF_INET, &(tcp_addr2.sin_addr), buffer, sizeof(buffer)), ntohs(tcp_addr2.sin_port), conn_fd, max_fds);
	    FD_SET(conn_fd, &all_fds);	/* add new descriptor to set */
	    max_fds = MAX(conn_fd, max_fds);	/* for select */
	    max_tcp_i = MAX(i, max_tcp_i);	/* max index in tcp_client[] array */
	}

	/* check for already connected TCP clients */
	for (i = 0; i <= max_tcp_i; i++) {	/* check all clients for data */
	    tcp_socket = tcp_client[i];
	    if (tcp_socket < 0)
		continue;
	    /* printf("%s tcp packet received from client #%d  max_tcp_i:%d todo:%d\n", time_stamp(timestamp), i, max_tcp_i,nready); */
	    if (FD_ISSET(tcp_socket, &read_fds)) {
		if (cs2_config_data.verbose && !background) {
		    time_stamp(timestamp);
		    printf("%s packet from: %s\n", timestamp, inet_ntop(AF_INET, &tcp_addr.sin_addr, buffer, sizeof(buffer)));
		}
		n = read(tcp_socket, netframe, MAXDG);
		if (!n) {
		    /* connection closed by client */
		    if (cs2_config_data.verbose && !background) {
			time_stamp(timestamp);
			printf("%s client %s closed connection\n", timestamp, inet_ntop(AF_INET, &tcp_addr.sin_addr, buffer, sizeof(buffer)));
		    }
		    syslog(LOG_NOTICE, "%s: client %s closed connection\n", __func__, inet_ntop(AF_INET, &tcp_addr.sin_addr, buffer, sizeof(buffer)));
		    close(tcp_socket);
		    FD_CLR(tcp_socket, &all_fds);
		    tcp_client[i] = -1;
		} else {
		    /* check the whole TCP packet, if there are more than one CAN frame included */
		    /* TCP packets with size modulo 13 !=0 are ignored though */
		    if (n % 13) {
			time_stamp(timestamp);
			if (!background)
			    fprintf(stderr, "%s received packet %% 13 : length %d - maybe close connection\n", timestamp, n);
			syslog(LOG_ERR, "%s: received packet %% 13 : length %d - maybe close connection\n", __func__, n);
		    } else {
			for (i = 0; i < n; i += CAN_ENCAP_SIZE) {
			    /* check if we need to forward the message to CAN */
			    if (!check_data(tcp_socket, &cs2_config_data, &netframe[i])) {
				ret = frame_to_can(sc, &netframe[i]);
				if (!ret) {
				    if (i > 0)
					print_can_frame(TCP_FORMATS_STRG, &netframe[i], cs2_config_data.verbose & !background);
				    else
					print_can_frame(TCP_FORMAT_STRG, &netframe[i], cs2_config_data.verbose & !background);
				}
				net_to_net(sb, (struct sockaddr *)&baddr, netframe, CAN_ENCAP_SIZE);
				print_can_frame(UDP_FORMAT_STRG, netframe, cs2_config_data.verbose & !background);
			    }
			}
		    }
		}
		if (--nready <= 0)
		    break;	/* no more readable descriptors */
	    }
	}
    }
    closelog();
    close(sc);
    close(sa);
    close(sb);
    close(st);
    close(st2);
    return 0;
}
Esempio n. 5
0
int main(int argc, char **argv) {
    pid_t pid;
    int n, i, max_fds, opt, max_tcp_i, nready, conn_fd, tcp_client[MAX_TCP_CONN];
    struct can_frame frame;
    char timestamp[16];
    /* UDP incoming socket , CAN socket, UDP broadcast socket, TCP socket */
    int sc, st, tcp_socket;
    struct sockaddr_in tcp_addr;
    /* vars for determing broadcast address */
    struct sockaddr_can caddr;
    struct ifreq ifr;
    socklen_t caddrlen = sizeof(caddr);
    socklen_t tcp_client_length = sizeof(tcp_addr);
    fd_set all_fds, read_fds;
    int ret;
    struct timeval tv;

    int local_tcp_port = DEF_TCP_PORT;
    int background = 1;
    /* const int off = 0; */
    char buffer[64];

    /* clear timestamp for last CAN frame sent */
    memset(&last_sent, 0, sizeof(last_sent));

    memset(ifr.ifr_name, 0, sizeof(ifr.ifr_name));
    strcpy(ifr.ifr_name, "can0");

    while ((opt = getopt(argc, argv, "t:i:vhf?")) != -1) {
	switch (opt) {
	case 't':
	    local_tcp_port = strtoul(optarg, (char **)NULL, 10);
	    break;
	case 'i':
	    strncpy(ifr.ifr_name, optarg, sizeof(ifr.ifr_name) - 1);
	    break;
	case 'f':
	    background = 0;
	    break;
	case 'h':
	case '?':
	    print_usage(basename(argv[0]));
	    exit(EXIT_SUCCESS);
	default:
	    fprintf(stderr, "Unknown option %c\n", opt);
	    print_usage(basename(argv[0]));
	    exit(EXIT_FAILURE);
	}
    }

    /* prepare TCP socket */
    st = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (st < 0) {
	fprintf(stderr, "creating TCP socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }

    tcp_addr.sin_family = AF_INET;
    tcp_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    tcp_addr.sin_port = htons(local_tcp_port);
    if (bind(st, (struct sockaddr *)&tcp_addr, sizeof(tcp_addr)) < 0) {
	fprintf(stderr, "binding TCP socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    if (listen(st, MAXPENDING) < 0) {
	fprintf(stderr, "starting TCP listener error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    /* prepare TCP clients array */
    max_tcp_i = -1;		/* index into tcp_client[] array */
    for (i = 0; i < MAX_TCP_CONN; i++)
	tcp_client[i] = -1;	/* -1 indicates available entry */

    /* prepare CAN socket */
    memset(&caddr, 0, sizeof(caddr));
    sc = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (sc < 0) {
	fprintf(stderr, "creating CAN socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    caddr.can_family = AF_CAN;
    if (ioctl(sc, SIOCGIFINDEX, &ifr) < 0) {
	fprintf(stderr, "setup CAN error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }
    caddr.can_ifindex = ifr.ifr_ifindex;

    if (bind(sc, (struct sockaddr *)&caddr, caddrlen) < 0) {
	fprintf(stderr, "binding CAN socket error: %s\n", strerror(errno));
	exit(EXIT_FAILURE);
    }

    /* daemonize the process if requested */
    if (background) {
	/* fork off the parent process */
	pid = fork();
	if (pid < 0)
	    exit(EXIT_FAILURE);
	/* if we got a good PID, then we can exit the parent process */
	if (pid > 0) {
	    printf("Going into background ...\n");
	    exit(EXIT_SUCCESS);
	}
    }

    setlogmask(LOG_UPTO(LOG_NOTICE));
    openlog("lan-schnitte", LOG_CONS | LOG_NDELAY, LOG_DAEMON);

    /* set select timeout -> send periodic CAN Ping */
    memset(&tv, 0, sizeof(tv));
    tv.tv_sec = 1;
    tv.tv_usec = 0;

    FD_ZERO(&all_fds);
    FD_SET(sc, &all_fds);
    FD_SET(st, &all_fds);
    max_fds = MAX(sc, st);

    while (1) {
	read_fds = all_fds;
	nready = select(max_fds + 1, &read_fds, NULL, NULL, &tv);
	if (nready == 0) {
	    /*    send_can_ping(sc); */
	    tv.tv_sec = 1;
	    tv.tv_usec = 0;
	    continue;
	} else if (nready < 0)
	    fprintf(stderr, "select error: %s\n", strerror(errno));

	tv.tv_sec = 1;
	tv.tv_usec = 0;

	/* received a CAN frame */
	if (FD_ISSET(sc, &read_fds)) {
	    /* reading via SockatCAN */
	    if (read(sc, &frame, sizeof(struct can_frame)) < 0) {
		fprintf(stderr, "reading CAN frame error: %s\n", strerror(errno));
		syslog(LOG_ERR, "%s: reading CAN frame error: %s\n", __func__, strerror(errno));
	    }
	    /* if CAN Frame is EFF do it */
	    if (frame.can_id & CAN_EFF_FLAG) {	/* only EFF frames are valid */
		/* send CAN frame to all connected TCP clients */
		for (i = 0; i <= max_tcp_i; i++) {	/* check all clients for data */
		    tcp_socket = tcp_client[i];
		    if (tcp_socket < 0)
			continue;
		    frame_to_net(tcp_socket, (struct sockaddr *)&tcp_addr, (struct can_frame *)&frame);
		    print_can_frame(CAN_TCP_FORMAT_STRG, netframe, !background);
		}
	    }
	}

	/* received a TCP packet */
	if (FD_ISSET(st, &read_fds)) {
	    conn_fd = accept(st, (struct sockaddr *)&tcp_addr, &tcp_client_length);
	    if (!background) {
		printf("new client: %s, port %d conn fd: %d max fds: %d\n", inet_ntop(AF_INET, &(tcp_addr.sin_addr),
			buffer, sizeof(buffer)), ntohs(tcp_addr.sin_port), conn_fd, max_fds);
	    }
	    syslog(LOG_NOTICE, "%s: new client: %s port %d conn fd: %d max fds: %d\n", __func__,
		   inet_ntop(AF_INET, &(tcp_addr.sin_addr), buffer, sizeof(buffer)), ntohs(tcp_addr.sin_port),
		   conn_fd, max_fds);
	    for (i = 0; i < MAX_TCP_CONN; i++) {
		if (tcp_client[i] < 0) {
		    tcp_client[i] = conn_fd;	/* save new TCP client descriptor */
		    break;
		}
	    }
	    if (i == MAX_TCP_CONN) {
		fprintf(stderr, "too many TCP clients\n");
		syslog(LOG_ERR, "%s: too many TCP clients\n", __func__);
	    }

	    FD_SET(conn_fd, &all_fds);	/* add new descriptor to set */
	    max_fds = MAX(conn_fd, max_fds);	/* for select */
	    max_tcp_i = MAX(i, max_tcp_i);	/* max index in tcp_client[] array */

	    if (--nready <= 0)
		continue;		/* no more readable descriptors */
	}

	/* check for already connected TCP clients */
	for (i = 0; i <= max_tcp_i; i++) {	/* check all clients for data */
	    tcp_socket = tcp_client[i];
	    if (tcp_socket < 0)
		continue;
	    if (FD_ISSET(tcp_socket, &read_fds)) {
		if (!background) {
		    time_stamp(timestamp);
		    printf("%s packet from: %s\n", timestamp,
			   inet_ntop(AF_INET, &tcp_addr.sin_addr, buffer, sizeof(buffer)));
		}
		n = read(tcp_socket, netframe, MAXDG);
		if (!n) {
		    /* connection closed by client */
		    if (!background) {
			time_stamp(timestamp);
			printf("%s client %s closed connection\n", timestamp,
			       inet_ntop(AF_INET, &tcp_addr.sin_addr, buffer, sizeof(buffer)));
		    }
		    syslog(LOG_NOTICE, "%s: client %s closed connection\n", __func__,
			   inet_ntop(AF_INET, &tcp_addr.sin_addr, buffer, sizeof(buffer)));
		    close(tcp_socket);
		    FD_CLR(tcp_socket, &all_fds);
		    tcp_client[i] = -1;
		} else {
		    /* check the whole TCP packet, if there are more than one CAN frame included */
		    /* TCP packets with size modulo 13 !=0 are ignored though */
		    if (n % 13) {
			time_stamp(timestamp);
			if (!background)
			    fprintf(stderr, "%s received packet %% 13 : length %d - maybe close connection\n", timestamp, n);
			syslog(LOG_ERR, "%s: received packet %% 13 : length %d - maybe close connection\n", __func__, n);
		    } else {
			for (i = 0; i < n; i += CAN_ENCAP_SIZE) {
			    ret = frame_to_can(sc, &netframe[i]);
			    if (!ret) {
				if (i > 0)
				    print_can_frame(TCP_FORMATS_STRG, &netframe[i], !background);
				else
				    print_can_frame(TCP_FORMAT_STRG, &netframe[i], !background);
			    }
			}
		    }
		}
		if (--nready <= 0)
		    break;	/* no more readable descriptors */
	    }
	}
    }
    closelog();
    close(sc);
    close(st);
    return 0;
}
Esempio n. 6
0
int main(int argc, char **argv) {
    pid_t pid;
    extern int optind, opterr, optopt;
    int n, i, max_fds, opt, max_tcp_i, nready, conn_fd, tcp_client[MAX_TCP_CONN];;
    struct can_frame frame;

    int sa, sc, sb, st, tcp_socket;		/* UDP socket , CAN socket, UDP Broadcast Socket, TCP Socket */
    struct sockaddr_in saddr, baddr, tcp_addr;
    struct sockaddr_can caddr;
    struct ifreq ifr;
    socklen_t caddrlen = sizeof(caddr);
    socklen_t tcp_client_length = sizeof(tcp_addr);

    fd_set all_fds, read_fds;

    uint32_t	canid;
    int s, nbytes, ret;

    int local_udp_port = 15731;
    int local_tcp_port = 15731;
    int destination_port = 15730;
    int verbose = 1;
    int background = 1;
    const int on = 1;
    char udp_dst_address[] = "255.255.255.255";
    char buffer[64];
    strcpy(ifr.ifr_name, "can0");

    while ((opt = getopt(argc, argv, "u:t:d:b:i:vhf?")) != -1) {
	switch (opt) {
	case 'u':
	    local_udp_port = strtoul(optarg, (char **) NULL, 10);
	    break;
	case 't':
	    local_tcp_port = strtoul(optarg, (char **) NULL, 10);
	    break;
	case 'd':
	    destination_port = strtoul(optarg, (char **) NULL, 10);
	    break;
	case 'b':
	    if ( strlen(optarg) <=15 ) {
		strcpy(udp_dst_address, optarg);
	    } else {
		fprintf(stderr, "UDP broadcast address error: %s\n", optarg);
	    }
	    break;
	case 'i':
	    strcpy(ifr.ifr_name, optarg);
	    break;
	case 'v':
	    verbose = 1;
	    break;
	case 'f':
	    background = 0;
	    break;
	case 'h':
	case '?':
	    print_usage(basename(argv[0]));
	    exit(0);
	    break;
	default:
	    fprintf(stderr, "Unknown option %c\n", opt);
	    print_usage(basename(argv[0]));
	    exit(1);
	    break;
	}
    }

    /* prepare udp sending socket struct */
    bzero(&baddr, sizeof(baddr));
    baddr.sin_family = AF_INET;
    baddr.sin_port = htons(destination_port);
    s = inet_pton(AF_INET, udp_dst_address, &baddr.sin_addr);
    if (s <= 0) {
	if (s == 0) {
	    fprintf(stderr, "error: UDP sending port not in presentation format\n");
	} else {
	    perror("inet_pton error\n");
	}
    	exit(1);
    }

    /* prepare UDP sending socket */
    if ((sb = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("error creating UDP sending socket");
	exit(1);
    }
    if (setsockopt(sb, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
	perror("error setup UDP broadcast option\n");
	exit(1);
    }

    /* prepare reading UDP socket */
    bzero(&saddr, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    saddr.sin_port = htons(local_udp_port);
    if ((sa = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
	perror("error creating UDP reading socket\n");
	exit(1);
    }
    while (bind(sa, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
	printf(".");
	fflush(NULL);
	usleep(100000);
    }

    /* prepare TCP socket */
    if ((st = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
	perror("error creating TCP socket\n");
	exit(1);
    }
    tcp_addr.sin_family = AF_INET;
    tcp_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    tcp_addr.sin_port = htons(local_tcp_port);
    if (bind(st, (struct sockaddr *)&tcp_addr, sizeof(tcp_addr)) < 0) {
	perror("error binding TCP socket\n");	
	exit(1);
    }
    if (listen(st, MAXPENDING) < 0) {
	perror("error starting TCP listener\n");
	exit(1);
    }
    /* prepare TCP clients array */
    max_tcp_i = -1;			/* index into tcp_client[] array */
    for (i = 0; i < MAX_TCP_CONN; i++)
	tcp_client[i] = -1;		/* -1 indicates available entry */

    /* prepare CAN socket */
    if ((sc = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
	perror("error creating CAN socket\n");
	exit(1);
    }
    caddr.can_family = AF_CAN;
    if (ioctl(sc, SIOCGIFINDEX, &ifr) < 0) {
	perror("SIOCGIFINDEX error\n");
	exit(1);
    }
    caddr.can_ifindex = ifr.ifr_ifindex;

    if (bind(sc, (struct sockaddr *) &caddr, caddrlen) < 0) {
	perror("error binding CAN socket\n");
	exit(1);
    }

    /* start Maerklin 60113 box */
    send_magic_start_60113_frame(sc, verbose);

    /* daemonize the process if requested */
    if (background) {
	/* fork off the parent process */
	pid = fork();
	if (pid < 0) {
	    exit(EXIT_FAILURE);
	}
	/* if we got a good PID, then we can exit the parent process */
	if (pid > 0) {
	    printf("Going into background ...\n");
	    exit(EXIT_SUCCESS);
	}
    }

    FD_ZERO(&all_fds);
    FD_SET(sc, &all_fds);
    FD_SET(sa, &all_fds);
    FD_SET(st, &all_fds);
    max_fds = MAX(MAX(sc, sa),st);

    while (1) {
	read_fds = all_fds;
	nready = select(max_fds + 1 , &read_fds, NULL, NULL, NULL);
	if (nready<0)
	    perror("select error\n");

	/* received a CAN frame */
	if (FD_ISSET(sc, &read_fds)) {
            if ((nbytes = read(sc, &frame, sizeof(struct can_frame))) < 0) {
		perror("error reading CAN frame\n");
	    } else if (frame.can_id & CAN_EFF_FLAG) {	/* only EFF frames are valid */
		/* send UDP frame */
		frame_to_net(sb, (struct sockaddr *) &baddr, (struct can_frame *) &frame);
		if (verbose && !background)
	            print_can_frame(UDP_FORMAT_STRG, netframe);
		/* send CAN frame to all connected TCP clients */
		/* TODO: need all clients the packets ? */ 
		for (i = 0; i <= max_tcp_i; i++) {	/* check all clients for data */
		    if ( (tcp_socket = tcp_client[i]) < 0)
			continue;
		    frame_to_net(tcp_socket, (struct sockaddr *) &tcp_addr, (struct can_frame *) &frame);
		    if (verbose && !background)
			print_can_frame(CAN_TCP_FORMAT_STRG, netframe);
		}
	    // printf("%s tcp packet received from client #%d  max_tcp_i:%d todo:%d\n", time_stamp(), i, max_tcp_i,nready);
	    }
	}
	/* received a UDP packet */
	if (FD_ISSET(sa, &read_fds)) {
	    if (read(sa, netframe, MAXDG) == 13) {
		/* send packet on CAN */
		ret = frame_to_can(sc, netframe);
		if (verbose && !background)
		    print_can_frame(NET_UDP_FORMAT_STRG, netframe);
    		memcpy(&canid, netframe, 4);
    		canid=ntohl(canid);
		/* answer to encapsulated CAN ping from LAN to LAN */
		if (((canid & 0x00FF0000UL) == 0x00310000UL) 
		      && (netframe[11] = 0xEE) && (netframe[12] = 0xEE)) {
		    printf("                received CAN ping\n");
		    netframe[0] = 0x00;
		    netframe[1] = 0x30;
		    netframe[2] = 0x00;
		    netframe[3] = 0x00;
		    netframe[4] = 0x00;
		    s = sendto(sb, netframe, 13, 0, (struct sockaddr *) &baddr, sizeof(baddr));
		    if (s != 13) {
			perror("error sending UDP data (CAN Ping)\n");
		    } else if (verbose & !background) {
			print_can_frame(NET_UDP_FORMAT_STRG, netframe);
			printf("                replied CAN ping\n");
		    }
		}
	    }
	}
	/* received a TCP packet */
        if (FD_ISSET(st, &read_fds)) {
	    conn_fd = accept(st, (struct sockaddr *) &tcp_addr, &tcp_client_length);
	    if (verbose && !background) {
		printf("new client: %s, port %d conn fd: %d max fds: %d\n", inet_ntop(AF_INET,
		    &(tcp_addr.sin_addr), buffer, sizeof(buffer)), ntohs(tcp_addr.sin_port), conn_fd, max_fds);
	    }
	    for (i = 0; i < MAX_TCP_CONN; i++) {
		if (tcp_client[i] < 0) {
		    tcp_client[i] = conn_fd;		/* save new TCP client descriptor */
		    break;
		}
	    }
	    if (i == MAX_TCP_CONN)
		perror("too many TCP clients\n");

	    FD_SET(conn_fd, &all_fds);		/* add new descriptor to set */
	    max_fds = MAX(conn_fd,max_fds);	/* for select */
	    max_tcp_i = MAX(i, max_tcp_i);	/* max index in tcp_client[] array */
	    if (--nready <= 0)
		continue;			/* no more readable descriptors */
	}
	/* check for already connected TCP clients */
	for (i = 0; i <= max_tcp_i; i++) {                   /* check all clients for data */
	    if ( (tcp_socket = tcp_client[i]) < 0)
		continue;
	    // printf("%s tcp packet received from client #%d  max_tcp_i:%d todo:%d\n", time_stamp(), i, max_tcp_i,nready);
	    if (FD_ISSET(tcp_socket, &read_fds)) {
		if (verbose && !background) {
		    printf("%s packet from: %s\n", time_stamp(),  inet_ntop(AF_INET,
			&tcp_addr.sin_addr, buffer, sizeof(buffer)));
		}
		if ( (n = read(tcp_socket, netframe, MAXDG)) == 0) {
		    /* connection closed by client */
		    close(tcp_socket);
		    FD_CLR(tcp_socket, &all_fds);
		    tcp_client[i] = -1;
		} else {
		    if (n == 13) {
			ret = frame_to_can(sc, netframe);
			if ((ret == 0) && (verbose && !background))
			    print_can_frame(TCP_FORMAT_STRG, netframe);
		    } else {
			fprintf(stderr, "%s received package =!13 : %d\n", time_stamp(), n);
		    }
		}
		if (--nready <= 0)
		    break;                  /* no more readable descriptors */
	    }
	}
    }
    close(sc);
    close(sa);
    close(sb);
    close(st);
    return 0;
}