From: Radek Matějka Date: Thu, 24 Jan 2013 23:46:08 +0000 (-0600) Subject: cegw improved, test distro dns lookup added X-Git-Url: http://rtime.felk.cvut.cz/gitweb/can-eth-gw.git/commitdiff_plain/356ba1469d336a9e1abe26c646ab890864f3bd14 cegw improved, test distro dns lookup added --- diff --git a/can-utils b/can-utils index b5c645f..0d6378d 160000 --- a/can-utils +++ b/can-utils @@ -1 +1 @@ -Subproject commit b5c645f83c7fc395b36918f79634ea553eae4e43 +Subproject commit 0d6378dffe86fecbbb5b02c4c59a3e1b01fcff75 diff --git a/distro/customroot/etc/host.conf b/distro/customroot/etc/host.conf new file mode 100644 index 0000000..ca6e762 --- /dev/null +++ b/distro/customroot/etc/host.conf @@ -0,0 +1,3 @@ +order hosts,bind +multi on + diff --git a/distro/customroot/etc/hosts b/distro/customroot/etc/hosts new file mode 100644 index 0000000..33ed302 --- /dev/null +++ b/distro/customroot/etc/hosts @@ -0,0 +1 @@ +127.0.0.1 localhost diff --git a/distro/customroot/etc/nsswitch.conf b/distro/customroot/etc/nsswitch.conf new file mode 100644 index 0000000..847e31e --- /dev/null +++ b/distro/customroot/etc/nsswitch.conf @@ -0,0 +1,8 @@ +passwd: files +group: files +hosts: files dns +networks: files dns +services: files +protocols: files +netmasks: files + diff --git a/distro/customroot/lib/libnss_files.so.2 b/distro/customroot/lib/libnss_files.so.2 new file mode 100644 index 0000000..e2d6982 Binary files /dev/null and b/distro/customroot/lib/libnss_files.so.2 differ diff --git a/distro/customroot/sbin/mkcegwdev b/distro/customroot/sbin/mkcegwdev index 9d59a31..1d55735 100755 --- a/distro/customroot/sbin/mkcegwdev +++ b/distro/customroot/sbin/mkcegwdev @@ -1,4 +1,4 @@ #/bin/sh modprobe canethgw -mknod /dev/cegw c 10 59 +mknod /dev/canethgw c 10 59 diff --git a/utils/cegw/cegw.c b/utils/cegw/cegw.c index 3e0e9d5..feb083a 100644 --- a/utils/cegw/cegw.c +++ b/utils/cegw/cegw.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -25,42 +26,47 @@ #include #include #include +#include +#include #include unsigned int cegw_errno = 0; -enum -{ +enum { CEGW_ERR_UNKNOWN, CEGW_ERR_COLON, - CEGW_ERR_UNEXLEN, - CEGW_ERR_ATON, - CEGW_ERR_PORT + CEGW_ERR_GETADDRI, + CEGW_ERR_FLTALCK, + CEGW_ERR_FLTPARSE }; -char* cegw_errlist[] = -{ - [CEGW_ERR_UNKNOWN] = "", - [CEGW_ERR_COLON ] = "expected ':' (:)", - [CEGW_ERR_UNEXLEN] = "unexpected ip address length, please use dot notation" - " (eg. 127.0.0.1)", - [CEGW_ERR_ATON ] = "ip address mismatch", - [CEGW_ERR_PORT ] = "port number" +char *cegw_errlist[] = { + + [CEGW_ERR_UNKNOWN ] = "", + [CEGW_ERR_COLON ] = "expected ':' (:)", + [CEGW_ERR_GETADDRI] = "getaddrinfo failed", + [CEGW_ERR_FLTALCK ] = "filter alloc failed", + [CEGW_ERR_FLTPARSE] = "filter parsing failed" }; static const char help_msg[] = "usage:\n" - " %s : :\n" - " [list of additional udp recipients ]\n" + " %s [,filter]* : :\n" + " [list of additional udp recipients :]\n" "example:\n" " %s can0 192.168.0.1:10501 192.168.0.4:980 192.168.0.7:1160\n\n" " Executing this command will set the gateway so that it will\n" " listen for udp messages on 192.168.0.1:10501 and send them\n" " to can0. Simultaneously, it will send all messages from can0\n" " to 192.168.0.4:980 and 192.168.0.7:1160 via udp. The message is\n" - " therefore cloned. Notice that there can be any number\n" - " of udp recipients.\n"; + " therefore cloned. Notice that there can be more udp recipients.\n" + " The can filter is specified in the same way as in candump utility.\n"; + +const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_DGRAM +}; -static void perr(char* s) +static void perr(char *s) { if (s) { if (cegw_errno == 0) { @@ -76,66 +82,115 @@ static void perr(char* s) } /** - * read_addrport - parses @in for eth address. + * readsockaddr - parses @in for eth address. * Valid input is e.g. 127.0.0.1:10502. If parsing fails - * the cause is stored in cegw_errno. + * the cause is stored in cegw_errno. Please note that + * the function modifies content of arg. * - * @param[in] in string to search in - * @param[out] addr ip address - * @param[out] port transport layer port + * @param[in] arg hostname:port string + * @param[out] addr filled sockaddr_in structure * @return 0 on success, -1 otherwise */ -int read_addrport(char* in, struct in_addr* addr, unsigned short* port) +int readsockaddr(char *arg, struct sockaddr_in *addr) { - char* delim = NULL; - const int addrstr_len = 16; - char addrstr[addrstr_len]; - int addrlen; + int ret; + char *delim; + struct addrinfo *res; + + delim = strchr(arg, ':'); - if ((delim = strchr(in, ':')) == NULL) { + if (delim == NULL) { cegw_errno = CEGW_ERR_COLON; return -1; } - /* get address */ - addrlen = delim - in; - if (addrlen > addrstr_len) { - cegw_errno = CEGW_ERR_UNEXLEN; + *delim = '\0'; + delim++; + + ret = getaddrinfo(arg, delim, &hints, &res); + if (ret != 0) { + fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret)); + cegw_errno = CEGW_ERR_GETADDRI; return -1; } - memcpy(addrstr, in, addrlen); - addrstr[addrlen] = '\0'; - if (inet_aton(addrstr, addr) == 0) { - cegw_errno = CEGW_ERR_ATON; - return -1; + memcpy(addr, res->ai_addr, sizeof(*addr)); + + freeaddrinfo(res); + return 0; +} + +/** + * readfilter - reads can filter definition from nptr + */ +int readfilter(char *nptr, struct can_filter **filter, int *out_numfilter, can_err_mask_t *err_mask) +{ + char *ptr; + int numfilter; + struct can_filter *rfilter; + + numfilter = 0; + ptr = nptr; + while (ptr) { + numfilter++; + ptr++; /* hop behind the ',' */ + ptr = strchr(ptr, ','); /* exit condition */ } - /* get port */ - /* ToDo: handle overflow */ - if (sscanf(delim, ":%hu", port) != 1) { - cegw_errno = CEGW_ERR_PORT; + rfilter = malloc(numfilter * sizeof(*rfilter)); + if (!rfilter) { + cegw_errno = CEGW_ERR_FLTALCK; 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) { + cegw_errno = CEGW_ERR_FLTPARSE; + free(rfilter); + return -1; + } + } + + *filter = rfilter; + *out_numfilter = numfilter; return 0; } -int main(int argc, char* argv[]) +int main(int argc, char *argv[]) { int i; int fd; int tmpi; int dstcnt; - unsigned short port; + char *nptr; + int numfilter = 0; int udp_sock, can_sock; + can_err_mask_t err_mask = 0; struct sockaddr_in udp_addr; struct sockaddr_can can_addr; - struct sockaddr_in* dst = NULL; - struct cegw_ioctl* gwctl = NULL; + struct sockaddr_in *dst = NULL; + struct cegw_ioctl *gwctl = NULL; + struct can_filter *filter = NULL; - if (argc == 1) - { + if (argc == 1) { printf(help_msg, argv[0], argv[0]); return 0; } @@ -153,6 +208,11 @@ int main(int argc, char* argv[]) for (i=1; iudp_dst[i-3]; - dst->sin_family = AF_INET; - if (read_addrport(argv[i], &dst->sin_addr, &port) != 0) { - perr("udp destination mismatch"); + if (readsockaddr(argv[i], dst) != 0) { + perr("reading udp destination failed"); free(gwctl); return 1; } - dst->sin_port = htons(port); break; } } @@ -212,6 +268,22 @@ int main(int argc, char* argv[]) return 1; } + /* can filter */ + if (nptr && (readfilter(nptr, &filter, &numfilter, &err_mask) != 0)) { + perr("can filter"); + free(gwctl); + return 1; + } + + if (err_mask) + setsockopt(can_sock, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, + &err_mask, sizeof(err_mask)); + + if (numfilter) + setsockopt(can_sock, SOL_CAN_RAW, CAN_RAW_FILTER, + filter, numfilter * sizeof(struct can_filter)); + free(filter); + /* send it to kernel gateway */ fd = open("/dev/canethgw", O_RDONLY); if (fd == -1) { @@ -238,3 +310,4 @@ int main(int argc, char* argv[]) return 0; } +