/*** * * tools/rtroute.c * manages IP host and network routes for RTnet * * rtnet - real-time networking subsystem * Copyright (C) 2004 Jan Kiszka * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include int f; struct ipv4_cmd cmd; struct in_addr addr; /* help gcc a bit... */ void help(void) __attribute__((noreturn)); void help(void) { fprintf(stderr, "Usage:\n" "\trtroute\n" "\trtroute solicit dev \n" "\trtroute add dev \n" "\trtroute add netmask gw \n" "\trtroute del [dev ]\n" "\trtroute del netmask \n" "\trtroute get [dev ]\n" "\trtroute -f \n" ); exit(1); } void print_routes(void) { char buf[4096]; int proc; size_t size; const char host_route[] = "/proc/rtnet/ipv4/host_route"; const char net_route[] = "/proc/rtnet/ipv4/net_route"; if ((proc = open(host_route, O_RDONLY)) < 0) { perror(host_route); exit(1); } printf("Host Routing Table\n"); while ((size = read(proc, buf, sizeof(buf))) > 0) write(STDOUT_FILENO, buf, size); close(f); if ((proc = open(net_route, O_RDONLY)) < 0) { if (errno == ENOENT) { /* Network routing is not available */ exit(0); } perror(net_route); exit(1); } printf("\nNetwork Routing Table\n"); while ((size = read(proc, buf, sizeof(buf))) > 0) write(STDOUT_FILENO, buf, size); close(f); exit(0); } void route_solicit(int argc, char *argv[]) { int ret; if ((argc != 5) || (strcmp(argv[3], "dev") != 0)) help(); strncpy(cmd.head.if_name, argv[4], IFNAMSIZ); cmd.args.solicit.ip_addr = addr.s_addr; ret = ioctl(f, IOC_RT_HOST_ROUTE_SOLICIT, &cmd); if (ret < 0) { perror("ioctl"); exit(1); } exit(0); } void route_add(int argc, char *argv[]) { struct ether_addr dev_addr; int ret; if (argc == 6) { /*** add host route ***/ if ((ether_aton_r(argv[3], &dev_addr) == NULL) || (strcmp(argv[4], "dev") != 0)) help(); cmd.args.addhost.ip_addr = addr.s_addr; memcpy(cmd.args.addhost.dev_addr, dev_addr.ether_addr_octet, sizeof(dev_addr.ether_addr_octet)); strncpy(cmd.head.if_name, argv[5], IFNAMSIZ); ret = ioctl(f, IOC_RT_HOST_ROUTE_ADD, &cmd); } else if (argc == 7) { /*** add network route ***/ if ((strcmp(argv[3], "netmask") != 0) || (strcmp(argv[5], "gw") != 0)) help(); cmd.args.addnet.net_addr = addr.s_addr; if (!inet_aton(argv[4], &addr)) help(); cmd.args.addnet.net_mask = addr.s_addr; if (!inet_aton(argv[6], &addr)) help(); cmd.args.addnet.gw_addr = addr.s_addr; ret = ioctl(f, IOC_RT_NET_ROUTE_ADD, &cmd); } else help(); if (ret < 0) { perror("ioctl"); exit(1); } exit(0); } void invalid_line_format(int line, char *file) { fprintf(stderr, "error on line %u of file %s, expected file format:\n" "# comment\n" " \n" "...\n", line, file); } void route_listadd(char *name) { FILE *fp; int line = 0; int argc = 0; int ret; struct ether_addr dev_addr; char buf[100]; char *sp; char *args[4]; const char space[] = " \t"; /*** try to open file ***/ fp = fopen(name, "r"); if (!fp) { ret = errno; fprintf(stderr, "opening file %s", name); perror(NULL); exit(1); } /*** fill buffer from file and add route ***/ while (fgets(buf, sizeof(buf), fp)) { line++; /* find newline char and make it end of string */ sp = strchr(buf, '\n'); if (sp) *sp = '\0'; /* ignore comments and empty lines */ if ((buf[0] == '#') || (buf[0] == '\0')) continue; /* split string into tokens */ argc = 0; args[argc] = strtok(buf, space); do { if (++argc > 3) break; args[argc] = strtok(NULL, space); } while (args[argc]); /* wrong number of arguments? */ if (argc != 3) { invalid_line_format(line, name); continue; } /*** check data ***/ /* check MAC */ if (ether_aton_r(args[1], &dev_addr) == NULL) { invalid_line_format(line, name); continue; } /* check IP */ if (!inet_aton(args[0], &addr)) { invalid_line_format(line, name); continue; } /*** turn it all into a cmd for rtnet and execute ***/ cmd.args.addhost.ip_addr = addr.s_addr; memcpy(cmd.args.addhost.dev_addr, dev_addr.ether_addr_octet, sizeof(dev_addr.ether_addr_octet)); /* use device */ strncpy(cmd.head.if_name, args[2], IFNAMSIZ); ret = ioctl(f, IOC_RT_HOST_ROUTE_ADD, &cmd); if (ret < 0) { perror("ioctl"); exit(1); } } fclose(fp); exit(0); } void route_delete(int argc, char *argv[]) { int ret; if (argc == 3) { /*** delete host route ***/ cmd.args.delhost.ip_addr = addr.s_addr; ret = ioctl(f, IOC_RT_HOST_ROUTE_DELETE, &cmd); } else if (argc == 5) { /*** delete device specific route ***/ if (strcmp(argv[3], "dev") == 0) { cmd.args.delhost.ip_addr = addr.s_addr; strncpy(cmd.head.if_name, argv[4], IFNAMSIZ); ret = ioctl(f, IOC_RT_HOST_ROUTE_DELETE_DEV, &cmd); } /*** delete network route ***/ else if (strcmp(argv[3], "netmask") == 0) { cmd.args.delnet.net_addr = addr.s_addr; if (!inet_aton(argv[4], &addr)) help(); cmd.args.delnet.net_mask = addr.s_addr; ret = ioctl(f, IOC_RT_NET_ROUTE_DELETE, &cmd); } else help(); } else help(); if (ret < 0) { if (errno == ENOENT) fprintf(stderr, "Specified route not found\n"); else perror("ioctl"); exit(1); } exit(0); } void route_get(int argc, char *argv[]) { int ret; if (argc == 3) { /*** get host route ***/ cmd.args.gethost.ip_addr = addr.s_addr; ret = ioctl(f, IOC_RT_HOST_ROUTE_GET, &cmd); } else if (argc == 5) { /*** get device specific route ***/ if (strcmp(argv[3], "dev") == 0) { cmd.args.delhost.ip_addr = addr.s_addr; strncpy(cmd.head.if_name, argv[4], IFNAMSIZ); ret = ioctl(f, IOC_RT_HOST_ROUTE_GET_DEV, &cmd); } else help(); } else help(); if (ret >= 0) { unsigned char *p = cmd.args.gethost.dev_addr; printf("Destination\tHW Address\t\tDevice\n" "%s\t%02x:%02x:%02x:%02x:%02x:%02x\t%s\n", argv[2], p[0], p[1], p[2] , p[3], p[4], p[5], cmd.head.if_name); } else { if (errno == ENOENT) { fprintf(stderr, "No route for host %s", argv[2]); if (argc == 5) fprintf(stderr, "on device %s", argv[4]); fprintf(stderr, " found\n"); } else perror("ioctl"); exit(1); } exit(0); } int main(int argc, char *argv[]) { const char rtnet_dev[] = "/dev/rtnet"; if (argc == 1) print_routes(); if ((strcmp(argv[1], "--help") == 0) || (argc < 3)) help(); f = open(rtnet_dev, O_RDWR); if (f < 0) { perror(rtnet_dev); exit(1); } /* add host routes from file? */ if (strcmp(argv[1], "-f") == 0) route_listadd(argv[2]); /* second argument is now always an IP address */ if (!inet_aton(argv[2], &addr)) help(); if (strcmp(argv[1], "solicit") == 0) route_solicit(argc, argv); if (strcmp(argv[1], "add") == 0) route_add(argc, argv); if (strcmp(argv[1], "del") == 0) route_delete(argc, argv); if (strcmp(argv[1], "get") == 0) route_get(argc, argv); help(); return 0; }