static int geo_parse_cidr(geo_t *g, char *cidr, char *value) { struct in_addr in; int i; uint32_t addr; uint32_t mask; uint32_t ip_addr; uint32_t old; if (strcmp(cidr, "default") == 0) { if (inet_aton(value, &in) == 0) { return -1; } ip_addr = ntohl(in.s_addr); addr = 0; mask = 0; } else if (strcmp(cidr, "delete") == 0) { if (parse_cidr(value, &addr, &mask) != 0) { return -1; } if (radix32tree_delete(g->u.tree, addr, mask) != 0) { return -1; } return 0; } if (parse_cidr(cidr, &addr, &mask) != 0) { return -1; } if (inet_aton(value, &in) == 0) { return -1; } ip_addr = ntohl(in.s_addr); /* Retry 3 times */ for (i = 3; i; --i) { if (radix32tree_insert(g->u.tree, addr, mask, ip_addr) == 0) { return 0; } old = radix32tree_find(g->u.tree, addr & mask); /* TODO log */ if (radix32tree_delete(g->u.tree, addr, mask) != 0) { return -1; } } return -1; }
int main(int argc, char *argv[]) { struct netent *netent; ipaddr_t gateway, destination, netmask, defaultmask=0; u8_t high_byte; nwio_route_t route; int ip_fd, itab; int r; int metric; char *check; char *ip_device; char *netmask_str, *metric_str, *destination_str, *gateway_str; int c; char *d_arg, *g_arg, *m_arg, *n_arg, *I_arg; int i_flag, o_flag, D_flag, v_flag; int cidr; prog_name= strrchr(argv[0], '/'); if (prog_name == NULL) prog_name= argv[0]; else prog_name++; if (strcmp(prog_name, "add_route") == 0) action= ADD; else if (strcmp(prog_name, "del_route") == 0) action= DEL; else { fprintf(stderr, "Don't know what to do when named '%s'\n", prog_name); exit(1); } i_flag= 0; o_flag= 0; D_flag= 0; v_flag= 0; g_arg= NULL; d_arg= NULL; m_arg= NULL; n_arg= NULL; I_arg= NULL; while ((c= getopt(argc, argv, "iovDg:d:m:n:I:?")) != -1) { switch(c) { case 'i': if (i_flag) usage(); i_flag= 1; break; case 'o': if (o_flag) usage(); o_flag= 1; break; case 'v': if (v_flag) usage(); v_flag= 1; break; case 'D': if (D_flag) usage(); D_flag= 1; break; case 'g': if (g_arg) usage(); g_arg= optarg; break; case 'd': if (d_arg) usage(); d_arg= optarg; break; case 'm': if (m_arg) usage(); m_arg= optarg; break; case 'n': if (n_arg) usage(); n_arg= optarg; break; case 'I': if (I_arg) usage(); I_arg= optarg; break; case '?': usage(); default: fprintf(stderr, "%s: getopt failed\n", prog_name); exit(1); } } if (optind != argc) usage(); if (i_flag && o_flag) usage(); itab= i_flag; if (i_flag) { if (g_arg == NULL || d_arg == NULL || m_arg == NULL) usage(); } else { if (g_arg == NULL || (d_arg == NULL && n_arg != NULL)) { usage(); } } gateway_str= g_arg; destination_str= d_arg; metric_str= m_arg; netmask_str= n_arg; ip_device= I_arg; if (!name_to_ip(gateway_str, &gateway)) { fprintf(stderr, "%s: unknown host '%s'\n", prog_name, gateway_str); exit(1); } destination= 0; netmask= 0; cidr= 0; if (destination_str) { if (parse_cidr(destination_str, &destination, &netmask)) cidr= 1; else if (inet_aton(destination_str, &destination)) ; else if ((netent= getnetbyname(destination_str)) != NULL) destination= netent->n_net; else if (!name_to_ip(destination_str, &destination)) { fprintf(stderr, "%s: unknown network/host '%s'\n", prog_name, destination_str); exit(1); } high_byte= *(u8_t *)&destination; if (!(high_byte & 0x80)) /* class A or 0 */ { if (destination) defaultmask= HTONL(0xff000000); } else if (!(high_byte & 0x40)) /* class B */ { defaultmask= HTONL(0xffff0000); } else if (!(high_byte & 0x20)) /* class C */ { defaultmask= HTONL(0xffffff00); } else /* class D is multicast ... */ { fprintf(stderr, "%s: Warning: Martian address '%s'\n", prog_name, inet_ntoa(destination)); defaultmask= HTONL(0xffffffff); } if (destination & ~defaultmask) { /* host route */ defaultmask= HTONL(0xffffffff); } if (!cidr) netmask= defaultmask; } if (netmask_str) { if (cidr) usage(); if (inet_aton(netmask_str, &netmask) == 0) { fprintf(stderr, "%s: illegal netmask'%s'\n", prog_name, netmask_str); exit(1); } } if (metric_str) { metric= strtol(metric_str, &check, 0); if (check[0] != '\0' || metric < 1) { fprintf(stderr, "%s: illegal metric %s\n", prog_name, metric_str); } } else metric= 1; if (!ip_device) ip_device= getenv("IP_DEVICE"); if (!ip_device) ip_device= IP_DEVICE; ip_fd= open(ip_device, O_RDWR); if (ip_fd == -1) { fprintf(stderr, "%s: unable to open('%s'): %s\n", prog_name, ip_device, strerror(errno)); exit(1); } if (v_flag) { printf("%s %s route to %s ", action == ADD ? "adding" : "deleting", itab ? "input" : "output", inet_ntoa(destination)); printf("with netmask %s ", inet_ntoa(netmask)); printf("using gateway %s", inet_ntoa(gateway)); if (itab && action == ADD) printf(" at distance %d", metric); printf("\n"); } route.nwr_ent_no= 0; route.nwr_dest= destination; route.nwr_netmask= netmask; route.nwr_gateway= gateway; route.nwr_dist= action == ADD ? metric : 0; route.nwr_flags= (action == DEL && D_flag) ? 0 : NWRF_STATIC; route.nwr_pref= 0; route.nwr_mtu= 0; if (action == ADD) r= ioctl(ip_fd, itab ? NWIOSIPIROUTE : NWIOSIPOROUTE, &route); else r= ioctl(ip_fd, itab ? NWIODIPIROUTE : NWIODIPOROUTE, &route); if (r == -1) { fprintf(stderr, "%s: NWIO%cIP%cROUTE: %s\n", prog_name, action == ADD ? 'S' : 'D', itab ? 'I' : 'O', strerror(errno)); exit(1); } return(0); }
/** * returns the include_exclude_mode on success placing the CIDR or LIST in mybuf * but on failure, returns xXError */ int parse_xX_str(tcpr_xX_t *xX, char *str, tcpr_bpf_t *bpf) { int out = 0; dbgx(1, "Parsing string: %s", str); dbgx(1, "Switching on: %c", str[0]); switch (str[0]) { case 'B': /* both ip's */ str = str + 2; out = xXBoth; if (!parse_cidr(&(xX->cidr), str, ",")) return xXError; break; case 'D': /* dst ip */ str = str + 2; out = xXDest; if (!parse_cidr(&(xX->cidr), str, ",")) return xXError; break; case 'E': /* either ip */ str = str + 2; out = xXEither; if (!parse_cidr(&(xX->cidr), str, ",")) return xXError; break; case 'F': /* bpf filter */ str = str + 2; out = xXBPF; bpf->filter = safe_strdup(str); /* * note: it's temping to compile the BPF here, but we don't * yet know what the link type is for the file, so we have * to compile the BPF once we open the pcap file */ break; case 'P': /* packet id */ str = str + 2; out = xXPacket; if (!parse_list(&(xX->list), str)) return xXError; break; case 'S': /* source ip */ str = str + 2; out = xXSource; if (!parse_cidr(&(xX->cidr), str, ",")) return xXError; break; default: errx(-1, "Invalid -%c option: %c", xX->mode, *str); break; } if (xX->mode == 'X') { /* run in exclude mode */ out += xXExclude; if (bpf->filter != NULL) err(-1, "Using a BPF filter with -X doesn't work.\n" "Try using -xF:\"not <filter>\" instead"); } xX->mode = out; return xX->mode; }