int do_tests(unsigned char *ifname, Boolean do_set_tests, Boolean use_ipv6) { unsigned char default_ifname[16] = DEFAULT_IFNAME; SshUInt32 ifnum, flags; SshNetconfigError error; unsigned char addr_buf[64], mask_buf[64]; SshNetconfigLinkStruct link; SshNetconfigInterfaceAddrStruct address; SshNetconfigRouteStruct route; Boolean use_any_interface; unsigned char print_buf[512]; if (ifname == NULL) { use_any_interface = TRUE; ifname = default_ifname; } else { use_any_interface = FALSE; } ifnum = SSH_INVALID_IFNUM; /* Resolve ifname. */ printf("Resolving interface \"%s\": ", ifname); error = ssh_netconfig_resolve_ifname(ifname, &ifnum); if (error != SSH_NETCONFIG_ERROR_OK) printf("ssh_netconfig_resolve_ifname: error %d\n", error); else printf("ifnum %ld\n", ifnum); if (ifnum == SSH_INVALID_IFNUM) { if (use_any_interface) { /* Pick another interface. */ for (ifnum = 10; ifnum >= 1; ifnum--) { printf("Resolving ifnum %d: ", (int) ifnum); if (ssh_netconfig_resolve_ifnum(ifnum, default_ifname, sizeof(default_ifname)) == SSH_NETCONFIG_ERROR_OK) { ifname = default_ifname; printf("\"%s\"\n", ifname); goto interface_found; } printf("not found\n"); } printf("no usable interfaces found\n"); } return -1; } interface_found: /* Get link state. */ printf("Fetching link state: "); error = ssh_netconfig_get_link(ifnum, &link); if (error != SSH_NETCONFIG_ERROR_OK) { printf("ssh_netconfig_get_link: error %d\n", error); return -1; } if (ssh_snprintf(print_buf, sizeof(print_buf), "%@", ssh_netconfig_link_render, &link) <= sizeof(print_buf)) printf("%s\n", print_buf); /* Set link state up. */ if (do_set_tests) { /* Bring link up, even if it is already up, because this is a test program. */ printf("Bringing interface up: "); error = ssh_netconfig_set_link_flags(ifnum, SSH_NETCONFIG_LINK_UP, SSH_NETCONFIG_LINK_UP); if (error != SSH_NETCONFIG_ERROR_OK) { printf("ssh_netconfig_set_link_flags: error %d\n", error); return -1; } printf("ok\n"); } /* Dump addresses. */ printf("Fetching addresses:\n"); if (dump_addresses(ifnum)) return -1; if (do_set_tests) { /* Add new IP address. */ memset(&address, 0, sizeof(address)); if (!use_ipv6) { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV4_ADDR); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV4_MASK); } else { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV6_ADDR); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV6_MASK); } printf("Adding address %s/%s ", addr_buf, mask_buf); if (!ssh_ipaddr_parse_with_mask(&address.address, addr_buf, mask_buf)) { printf("ssh_ipaddr_parse: error\n"); return -1; } if (!use_ipv6) { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV4_BCAST); printf("brd %s: ", addr_buf); if (!ssh_ipaddr_parse(&address.broadcast, addr_buf)) { printf("ssh_ipaddr_parse: error\n"); return -1; } address.flags = SSH_NETCONFIG_ADDR_BROADCAST; } error = ssh_netconfig_add_address(ifnum, &address); if (error != SSH_NETCONFIG_ERROR_OK) { printf("ssh_netconfig_add_address: error %d\n", error); return -1; } printf("ok\n"); /* Dump addresses. */ printf("Fetching addresses:\n"); if (dump_addresses(ifnum)) return -1; } /* Dump routes. */ printf("Fetching routing table:\n"); if (dump_routes(NULL)) return -1; if (do_set_tests) { /* Add new route. */ memset(&route, 0, sizeof(route)); if (!use_ipv6) { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV4_NET); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV4_NETMASK); } else { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV6_NET); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV6_NETMASK); } ssh_ipaddr_parse_with_mask(&route.prefix, addr_buf, mask_buf); printf("Adding route %s/%s", addr_buf, mask_buf); if (!use_ipv6) ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV4_GW); else ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV6_GW); ssh_ipaddr_parse(&route.gateway, addr_buf); route.ifnum = ifnum; route.metric = 8; printf(" via %s dev %ld metric %ld: ", addr_buf, route.ifnum, route.metric); error = ssh_netconfig_add_route(&route); if (error != SSH_NETCONFIG_ERROR_OK) { printf("ssh_netconfig_add_route: error %d\n", error); return -1; } printf("ok\n"); /* Dump routes. */ printf("Fetching routing table:\n"); if (dump_routes(NULL)) return -1; } /* Get routes matching prefix. */ if (!use_ipv6) { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV4_NET); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV4_NETMASK); } else { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV6_NET); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV6_NETMASK); } printf("Getting routes matching %s/%s:\n", addr_buf, mask_buf); ssh_ipaddr_parse_with_mask(&route.prefix, addr_buf, mask_buf); if (dump_routes(&route.prefix)) return -1; if (do_set_tests) { /* Delete newly added route. */ memset(&route, 0, sizeof(route)); if (!use_ipv6) { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV4_NET); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV4_NETMASK); } else { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV6_NET); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV6_NETMASK); } ssh_ipaddr_parse_with_mask(&route.prefix, addr_buf, mask_buf); printf("Deleting route %s/%s", addr_buf, mask_buf); if (!use_ipv6) ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV4_GW); else ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV6_GW); ssh_ipaddr_parse(&route.gateway, addr_buf); route.ifnum = ifnum; route.metric = 8; printf(" via %s dev %ld metric %ld: ", addr_buf, route.ifnum, route.metric); error = ssh_netconfig_del_route(&route); if (error != SSH_NETCONFIG_ERROR_OK) { printf("ssh_netconfig_del_route: error %d\n", error); return -1; } printf("ok\n"); /* Dump routes. */ printf("Fetching routing table:\n"); if (dump_routes(NULL)) return -1; /* Delete newly added address. */ memset(&address, 0, sizeof(address)); if (!use_ipv6) { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV4_ADDR); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV4_MASK); } else { ssh_snprintf(addr_buf, sizeof(addr_buf), DEFAULT_IPV6_ADDR); ssh_snprintf(mask_buf, sizeof(mask_buf), DEFAULT_IPV6_MASK); } printf("Deleting address %s/%s: ", addr_buf, mask_buf); if (!ssh_ipaddr_parse_with_mask(&address.address, addr_buf, mask_buf)) { printf("ssh_ipaddr_parse: error\n"); return -1; } address.flags = 0; error = ssh_netconfig_del_address(ifnum, &address); if (error != SSH_NETCONFIG_ERROR_OK) { printf("ssh_netconfig_del_address: error %d\n", error); return -1; } printf("ok\n"); /* Dump addresses. */ printf("Fetching addresses:\n"); if (dump_addresses(ifnum)) return -1; /* Restore link state. */ if ((flags & SSH_NETCONFIG_LINK_UP) == 0) { printf("Bringing interface down: "); error = ssh_netconfig_set_link_flags(ifnum, 0, SSH_NETCONFIG_LINK_UP); if (error != SSH_NETCONFIG_ERROR_OK) { printf("ssh_netconfig_set_link_flags: error %d\n", error); return -1; } printf("ok\n"); } } return 0; }
int main(int argc, char **argv) { struct packet { unsigned long word1; unsigned long word2; unsigned long word3; unsigned long src_addr; unsigned long dst_addr; unsigned char rest[8172]; }; int addrlen; int fd; int i; int n; struct packet packet; struct route *rp; struct sockaddr_in addr; if (argc >= 2) { load_routes(); dump_routes(); exit(0); } if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) halt("socket"); memset((char *) &addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(PORT); if (bind(fd, (struct sockaddr *) &addr, sizeof(addr))) halt("bind"); for (n = 0; n < 60; n++) { if (n != fd) close(n); } if (fork()) exit(0); setsid(); if (fork()) exit(0); load_routes(); for (;;) { addrlen = sizeof(addr); n = recvfrom(fd, (char *) &packet, sizeof(struct packet), 0, (struct sockaddr *) &addr, &addrlen); if (n < 20) continue; i = (int) (packet.src_addr & 0xff); for (rp = Routes[i]; rp && rp->a_addr != packet.src_addr; rp = rp->next) ; if (!rp) { rp = (struct route *) malloc(sizeof(struct route)); if (rp) { rp->a_addr = packet.src_addr; rp->i_addr = 0; rp->i_port = 0; rp->next = Routes[i]; Routes[i] = rp; } } if (rp && (rp->i_addr != addr.sin_addr.s_addr || rp->i_port != addr.sin_port)) { rp->i_addr = addr.sin_addr.s_addr; rp->i_port = addr.sin_port; save_routes(); } i = (int) (packet.dst_addr & 0xff); for (rp = Routes[i]; rp && rp->a_addr != packet.dst_addr; rp = rp->next) ; if (!rp) rp = find_subnet_route(packet.dst_addr); if (rp) { addr.sin_addr.s_addr = rp->i_addr; addr.sin_port = rp->i_port; sendto(fd, (char *) &packet, n, 0, (struct sockaddr *) &addr, sizeof(addr)); } } }