const char* get_ifname_descriptor(const char* ifname, int ap_mode, int *ifindex, int *wan_no) { struct ifname_desc_t *ifd; for (ifd = (struct ifname_desc_t *)&ifname_descs[0]; ifd->ifname; ifd++) { if (ap_mode && ifd->is_router_mode) continue; if (!ap_mode && ifd->is_ap_mode) continue; if (strcmp(ifname, ifd->ifname) == 0) { if (wan_no) *wan_no = (int)ifd->wan_no; if (ifd->is_dynamic) *ifindex = get_interface_index(ifname); else *ifindex = 0; return ifd->ifdesc; } } return NULL; }
static int set_routes(const char *name, const char *routes) { int index = get_interface_index(name); if (index < 0) { return index; } rtentry rt4; memset(&rt4, 0, sizeof(rt4)); rt4.rt_dev = (char *)name; rt4.rt_flags = RTF_UP; rt4.rt_dst.sa_family = AF_INET; rt4.rt_genmask.sa_family = AF_INET; in6_rtmsg rt6; memset(&rt6, 0, sizeof(rt6)); rt6.rtmsg_ifindex = index; rt6.rtmsg_flags = RTF_UP; char address[65]; int prefix; int chars; int count = 0; while (sscanf(routes, " %64[^/]/%d %n", address, &prefix, &chars) == 2) { routes += chars; if (strchr(address, ':')) { // Add an IPv6 route. if (inet_pton(AF_INET6, address, &rt6.rtmsg_dst) != 1 || prefix < 0 || prefix > 128) { count = BAD_ARGUMENT; break; } rt6.rtmsg_dst_len = prefix ? prefix : 1; if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) { count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; break; } if (!prefix) { // Split the route instead of replacing the default route. rt6.rtmsg_dst.s6_addr[0] ^= 0x80; if (ioctl(inet6, SIOCADDRT, &rt6) && errno != EEXIST) { count = SYSTEM_ERROR; break; } } } else { // Add an IPv4 route. if (inet_pton(AF_INET, address, as_in_addr(&rt4.rt_dst)) != 1 || prefix < 0 || prefix > 32) { count = BAD_ARGUMENT; break; } in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0x80000000; *as_in_addr(&rt4.rt_genmask) = htonl(mask); if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) { count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; break; } if (!prefix) { // Split the route instead of replacing the default route. *as_in_addr(&rt4.rt_dst) ^= htonl(0x80000000); if (ioctl(inet4, SIOCADDRT, &rt4) && errno != EEXIST) { count = SYSTEM_ERROR; break; } } } ALOGD("Route added on %s: %s/%d", name, address, prefix); ++count; } if (count == BAD_ARGUMENT) { ALOGE("Invalid route: %s/%d", address, prefix); } else if (count == SYSTEM_ERROR) { ALOGE("Cannot add route: %s/%d: %s", address, prefix, strerror(errno)); } else if (*routes) { ALOGE("Invalid route: %s", routes); count = BAD_ARGUMENT; } return count; }
static int set_addresses(const char *name, const char *addresses) { int index = get_interface_index(name); if (index < 0) { return index; } ifreq ifr4; memset(&ifr4, 0, sizeof(ifr4)); strncpy(ifr4.ifr_name, name, IFNAMSIZ); ifr4.ifr_addr.sa_family = AF_INET; ifr4.ifr_netmask.sa_family = AF_INET; in6_ifreq ifr6; memset(&ifr6, 0, sizeof(ifr6)); ifr6.ifr6_ifindex = index; char address[65]; int prefix; int chars; int count = 0; while (sscanf(addresses, " %64[^/]/%d %n", address, &prefix, &chars) == 2) { addresses += chars; if (strchr(address, ':')) { // Add an IPv6 address. if (inet_pton(AF_INET6, address, &ifr6.ifr6_addr) != 1 || prefix < 0 || prefix > 128) { count = BAD_ARGUMENT; break; } ifr6.ifr6_prefixlen = prefix; if (ioctl(inet6, SIOCSIFADDR, &ifr6)) { count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; break; } } else { // Add an IPv4 address. if (inet_pton(AF_INET, address, as_in_addr(&ifr4.ifr_addr)) != 1 || prefix < 0 || prefix > 32) { count = BAD_ARGUMENT; break; } if (count) { sprintf(ifr4.ifr_name, "%s:%d", name, count); } if (ioctl(inet4, SIOCSIFADDR, &ifr4)) { count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; break; } in_addr_t mask = prefix ? (~0 << (32 - prefix)) : 0; *as_in_addr(&ifr4.ifr_netmask) = htonl(mask); if (ioctl(inet4, SIOCSIFNETMASK, &ifr4)) { count = (errno == EINVAL) ? BAD_ARGUMENT : SYSTEM_ERROR; break; } } ALOGD("Address added on %s: %s/%d", name, address, prefix); ++count; } if (count == BAD_ARGUMENT) { ALOGE("Invalid address: %s/%d", address, prefix); } else if (count == SYSTEM_ERROR) { ALOGE("Cannot add address: %s/%d: %s", address, prefix, strerror(errno)); } else if (*addresses) { ALOGE("Invalid address: %s", addresses); count = BAD_ARGUMENT; } return count; }
int main(int argc, char** argv) { unsigned long my_ip, my_netmask, my_prefix, network_len, cur_ip; int my_index; struct sockaddr sa; int sock; u_char hwaddr[MAC_ADDR_LEN]; char *ifname, *ifsend, *cindex; char ch; if (argc < 2) { print_usage(usage); } while ((ch = getopt(argc, argv, "d")) != -1) { switch(ch) { case 'd': opt_d = 1; break; case '?': default: goto args; } } args: argc -= optind; argv += optind; if (opt_d && !argc) { print_usage(usage); } // Sockets sock = NEWSOCKET(); ioctl_sock = NEWSOCKET(); // Recv timeout struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 1; setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval)); if ((sock < 0) || (ioctl_sock < 0)) { perror("Unable to create socket"); exit(1); } if (!(ifname = strdup(*argv)) || !(ifsend = strdup(*argv))) die("Cannot duplicate interface name\n"); /* * For an alias interface we use its data but we send * the actual packet on corresponding real interface */ if ((cindex = strchr(ifsend, ':'))) *cindex = '\0'; if (opt_d) { printf("Interface: %s\n", ifname); } sa.sa_family = AF_INET; strcpy(sa.sa_data, ifsend); get_hw_addr(hwaddr, ifname); my_ip = get_ip_addr(ifname); my_netmask = get_ip_mask(ifname); my_index = get_interface_index(ifname); my_prefix = my_ip & my_netmask; network_len = my_netmask ^ 0xffffffff; if (opt_d) { printf("Prefix: %lu\n", my_prefix); printf("Network length: %lu\n", network_len); } for (cur_ip = my_prefix + 1; cur_ip <= my_prefix + network_len; cur_ip++) { if (cur_ip == my_ip) continue; // Skip gratuitous ARP send_arp(sock, my_index, cur_ip, my_ip, hwaddr); detect_sonos(sock); } exit(0); }