static RouteEntry * route_sv2c(SV *h, RouteEntry *ref) { if (ref && h && SvROK(h)) { HV *hv = (HV *)SvRV(h); memset(ref, 0, sizeof(RouteEntry)); if (hv_exists(hv, "route_dst", 9)) { SV **r = hv_fetch(hv, "route_dst", 9, 0); if (SvOK(*r)) { struct addr a; if (addr_aton(SvPV(*r, PL_na), &a) == 0) { memcpy(&(ref->route_dst), &a, sizeof(struct addr)); } } } if (hv_exists(hv, "route_gw", 8)) { SV **r = hv_fetch(hv, "route_gw", 8, 0); if (SvOK(*r)) { struct addr a; if (addr_aton(SvPV(*r, PL_na), &a) == 0) { memcpy(&(ref->route_gw), &a, sizeof(struct addr)); } } } } else { ref = NULL; } return ref; }
int arp_loop(arp_t *a, arp_handler callback, void *arg) { FILE *fp; struct arp_entry entry; char buf[BUFSIZ], ipbuf[100], macbuf[100], maskbuf[100], devbuf[100]; int i, type, flags, ret; if ((fp = fopen(PROC_ARP_FILE, "r")) == NULL) return (-1); ret = 0; while (fgets(buf, sizeof(buf), fp) != NULL) { i = sscanf(buf, "%s 0x%x 0x%x %100s %100s %100s\n", ipbuf, &type, &flags, macbuf, maskbuf, devbuf); if (i < 4 || (flags & ATF_COM) == 0) continue; if (addr_aton(ipbuf, &entry.arp_pa) == 0 && addr_aton(macbuf, &entry.arp_ha) == 0) { if ((ret = callback(&entry, arg)) != 0) break; } } if (ferror(fp)) { fclose(fp); return (-1); } fclose(fp); return (ret); }
int main(int argc, char **argv) { ip_t *sock; intf_t *intf; struct addr dst; struct ip_hdr *ip; struct udp_hdr *udp; struct intf_entry entry; int len = IP_HDR_LEN + UDP_HDR_LEN; char buf[len]; if (argc < 2 || addr_aton(argv[1], &dst)) { printf("error: please specify a target ip address\n"); return 1; } memset(buf, 0, sizeof(buf)); ip = (struct ip_hdr *) buf; ip->ip_v = 4; ip->ip_hl = 5; ip->ip_tos = 0; ip->ip_off = 0; ip->ip_sum = 0; ip->ip_ttl = IP_TTL_MAX; ip->ip_p = IP_PROTO_UDP; ip->ip_id = htons(0xdead); ip->ip_len = htons(len); udp = (struct udp_hdr *) (buf + IP_HDR_LEN); udp->uh_sum = 0; udp->uh_sport = htons(0); udp->uh_dport = htons(5353); udp->uh_ulen = htons(UDP_HDR_LEN); intf = intf_open(); intf_get_dst(intf, &entry, &dst); intf_close(intf); ip->ip_src = entry.intf_addr.addr_ip; ip->ip_dst = dst.addr_ip; ip_checksum(buf, len); sock = ip_open(); if (!sock) { printf("error: root privileges needed for raw socket\n"); return 1; } ip_send(sock, buf, len); ip_close(sock); return 0; }
int load_address(FILE *fp, char *ip, char *hw, char *pt, struct addr *ad, struct addr *ha, int swit) { if ( fgets(ip, 32, fp) == NULL ) return(-1); rmnl(ip); if ( addr_aton(ip, ad) == -1 ) return(-2); if ( fgets(hw, 32, fp) == NULL ) return(-3); rmnl(hw); if ( addr_aton(hw, ha) == -1 ) { return(-4); } if(swit == 1){ if ( fgets(pt, 32, fp) == NULL ) return(-5); rmnl(pt); } return(0); }
void * ip6_opt_open(int argc, char *argv[]) { struct ip6_opt_data *opt; int i, j; if (argc < 4) return (NULL); if ((opt = calloc(1, sizeof(*opt))) == NULL) return (NULL); if (strcasecmp(argv[1], "route") == 0) { opt->type = OPT6_TYPE_ROUTE; if ((opt->u.route.segments = atoi(argv[2])) < 1 || opt->u.route.segments > MAX_ADDRS) { warnx("<segments> must be >= 1"); return (ip6_opt_close(opt)); } i = 0; j = 3; if (opt->u.route.segments + 3 != argc) { return (ip6_opt_close(opt)); } for (; j < argc; i++, j++) { if (addr_aton(argv[j], &opt->u.route.addr[i]) < 0 || opt->u.route.addr[i].addr_type != ADDR_TYPE_IP6) { return (ip6_opt_close(opt)); } } } else if (strcasecmp(argv[1], "raw") == 0) { opt->type = OPT6_TYPE_RAW; if (raw_ip6_opt_parse(argc - 2, &argv[2], &opt->u.raw.proto, &opt->u.raw.len, &opt->u.raw.data8[2], sizeof(opt->u.raw.data8) - 2) != 0) return (ip6_opt_close(opt)); opt->u.raw.len += 2; opt->u.raw.data8[0] = 0; opt->u.raw.data8[1] = opt->u.raw.len / 8; } else { return (ip6_opt_close(opt)); } return (opt); }
int parse_host_range(const char *range, uint32_t *start, uint32_t *end) { struct addr addr, bcast; uint32_t val, mask; u_int u[4]; char *p, *s; int ret = -1; if ((p = strdup(range)) == NULL) return (ret); if (addr_aton(p, &addr) == 0 && addr.addr_type == ADDR_TYPE_IP) { if (addr.addr_bits != IP_ADDR_BITS) { *start = htonl(ntohl(addr.addr_ip) + 1); addr_bcast(&addr, &bcast); *end = htonl(ntohl(bcast.addr_ip) - 1); } else *start = *end = addr.addr_ip; ret = 0; } else if ((s = strchr(p, '-')) != NULL) { *s = '\0'; if (ip_aton(p, start) == 0) { if (ip_aton(s + 1, end) == 0) { ret = 0; } else if ((val = atoi(s + 1)) > 0 && val <= 0xff) { *end = (*start & IP_CLASSC_NET) | htonl(val); ret = 0; } } } else if ((s = strchr(p, '/')) != NULL) { *s = '\0'; memset(u, 0, sizeof(u)); if (sscanf(p, "%d.%d.%d.%d", &u[0], &u[1], &u[2], &u[3]) > 0 && addr_btom(atoi(s + 1), &mask, IP_ADDR_LEN) == 0) { val = ((u[0]<<24) | (u[1]<<16) | (u[2]<<8) | u[3]) & ntohl(mask); *start = htonl(val + 1); *end = htonl((val | ~(ntohl(mask))) - 1); ret = 0; } } free(p); return (ret); }
void * ip_opt_open(int argc, char *argv[]) { struct ip_opt *opt; struct addr addr; int i, j; if (argc < 4) return (NULL); if ((opt = calloc(1, sizeof(*opt))) == NULL) return (NULL); if (strcasecmp(argv[1], "lsrr") == 0) { opt->opt_type = IP_OPT_LSRR; } else if (strcasecmp(argv[1], "ssrr") == 0) { opt->opt_type = IP_OPT_SSRR; } else return (ip_opt_close(opt)); if ((i = atoi(argv[2])) < 4 || i > 0xff) { warnx("<ptr> must be >= 4, and should be a multiple of 4"); return (ip_opt_close(opt)); } opt->opt_data.rr.ptr = i; for (i = 3, j = 0; i < argc && j < 9; i++, j++) { if (addr_aton(argv[i], &addr) < 0) { return (ip_opt_close(opt)); } opt->opt_data.rr.iplist[j] = addr.addr_ip; } opt->opt_len = IP_OPT_LEN + 1 + (IP_ADDR_LEN * j); return (opt); }
int route_loop(route_t *r, route_handler callback, void *arg) { FILE *fp; struct route_entry entry; char buf[BUFSIZ]; int ret = 0; if ((fp = fopen(PROC_ROUTE_FILE, "r")) != NULL) { char ifbuf[16]; int i, iflags, refcnt, use, metric, mss, win, irtt; uint32_t mask; while (fgets(buf, sizeof(buf), fp) != NULL) { i = sscanf(buf, "%16s %X %X %X %d %d %d %X %d %d %d\n", ifbuf, &entry.route_dst.addr_ip, &entry.route_gw.addr_ip, &iflags, &refcnt, &use, &metric, &mask, &mss, &win, &irtt); if (i < 10 || !(iflags & RTF_UP)) continue; if (entry.route_gw.addr_ip == IP_ADDR_ANY) continue; entry.route_dst.addr_type = entry.route_gw.addr_type = ADDR_TYPE_IP; if (addr_mtob(&mask, IP_ADDR_LEN, &entry.route_dst.addr_bits) < 0) continue; entry.route_gw.addr_bits = IP_ADDR_BITS; if ((ret = callback(&entry, arg)) != 0) break; } fclose(fp); } if (ret == 0 && (fp = fopen(PROC_IPV6_ROUTE_FILE, "r")) != NULL) { char s[33], d[8][5], n[8][5]; u_int slen, dlen; while (fgets(buf, sizeof(buf), fp) != NULL) { sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %02x " "%32s %02x %04s%04s%04s%04s%04s%04s%04s%04s ", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], &dlen, s, &slen, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]); snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], dlen); addr_aton(buf, &entry.route_dst); snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d", n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], IP6_ADDR_BITS); addr_aton(buf, &entry.route_gw); if ((ret = callback(&entry, arg)) != 0) break; } fclose(fp); } return (ret); }
int intf_main(int argc, char *argv[]) { struct intf_entry *entry; struct addr *ap, addr; char *cmd, buf[1024]; if (argc < 2) usage(); cmd = argv[1]; entry = (struct intf_entry *)buf; memset(entry, 0, sizeof(*entry)); entry->intf_len = sizeof(buf); if ((intf = intf_open()) == NULL) err(1, "intf_open"); if (strcmp(cmd, "show") == 0) { if (intf_loop(intf, print_intf, NULL) < 0) err(1, "intf_loop"); } else if (strcmp(cmd, "get") == 0) { if (argc < 3) usage(); strlcpy(entry->intf_name, argv[2], sizeof(entry->intf_name)); if (intf_get(intf, entry) < 0) err(1, "intf_get"); print_intf(entry, NULL); } else if (strcmp(cmd, "src") == 0) { if (argc < 3 || addr_aton(argv[2], &addr) < 0) usage(); if (intf_get_src(intf, entry, &addr) < 0) err(1, "intf_get_src"); print_intf(entry, NULL); } else if (strcmp(cmd, "dst") == 0) { if (argc < 3 || addr_aton(argv[2], &addr) < 0) usage(); if (intf_get_dst(intf, entry, &addr) < 0) err(1, "intf_get_dst"); print_intf(entry, NULL); } else if (strcmp(cmd, "set") == 0) { if (argc < 4) usage(); strlcpy(entry->intf_name, argv[2], sizeof(entry->intf_name)); for (argv += 3, argc -= 3; argc > 1; argv += 2, argc -= 2) { if (strcmp(argv[0], "alias") == 0) { ap = &entry->intf_alias_addrs [entry->intf_alias_num++]; } else if (strcmp(argv[0], "dst") == 0) { ap = &entry->intf_dst_addr; } else if (strcmp(argv[0], "inet") == 0) { ap = &entry->intf_addr; } else if (strcmp(argv[0], "link") == 0) { ap = &entry->intf_link_addr; } else break; if (addr_pton(argv[1], ap) < 0) err(1, "invalid address: %s", argv[1]); } for ( ; argc > 0; argv++, argc--) { if (strcmp(argv[0], "up") == 0) entry->intf_flags |= INTF_FLAG_UP; else if (strcmp(argv[0], "down") == 0) entry->intf_flags &= ~INTF_FLAG_UP; else if (strcmp(argv[0], "arp") == 0) entry->intf_flags &= ~INTF_FLAG_NOARP; else if (strcmp(argv[0], "noarp") == 0) entry->intf_flags |= INTF_FLAG_NOARP; else usage(); } if (intf_set(intf, entry) < 0) err(1, "intf_set"); } else usage(); intf_close(intf); exit(0); }
int main(int argc, char **argv) { int *register_module_ids = [ GGPKT_MOD_0_INTERNAL_ID, -1 ]; struct event_base *evb; struct gg_client *cli; struct ggpkt *pkt; char *notice_msg; int notice_len; int loglevel; struct addr ip; int port; int res; int op; _test_connected = 0; _test_receive_response = 0; notice_msg = NULL; notice_len = 0; loglevel = 0; while ((op = getopt(argc, argv, "hN:t:v")) != -1) { switch (op) { case 'h': usage(); /* NOTREACHED */ case 'v': loglevel++; break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc < 2 || argc > 3) usage(); addr_aton(argv[0], &ip); port = atoi(argv[1]); if (argc == 3) { notice_msg = strdup(argv[2]); notice_len = strlen(notice_msg); } evb = event_base_new(); cli = gg_client_connect(evb, &ip, port, register_modules, handle_conn, handle_pkt); if (!cli) { printf("Error: could not connect ! (gg_client_connect failed)\n"); return 2; } pkt = ggpkt_mod_0_internal_ping() if (!pkt) { printf("Error: could not create PING packet !\n"); return 10; } res = gg_client_send(cli, pkt); if (res < 0) { printf("Error: could not send PING !\n"); return 11; } if (notice_msg) { pkt = ggpkt_mod_0_internal_notice(notice_len, notice_msg); if (!pkt) { printf("Error: could not create NOTICE packet !\n"); return 10; } res = gg_client_send(cli, pkt); if (res < 0) { printf("Error: could not send NOTICE !\n"); return 11; } } event_base_dispatch(evb); gg_client_disconnect(cli); if (_test_connected == 0) { printf("Error: could not connect ! (test_connected == 0)\n"); return 1; } if (_test_receive_response == 0) { printf("Error: did not receive response !"); return 15; } return 0; }
int main(int argc, char **argv) { struct event *ev_sigint, *ev_sigterm, *ev_sigchld, *ev_sighup; struct glougloud *ggd; int op; ggd = xcalloc(1, sizeof(struct glougloud)); addr_aton("127.0.0.1", &ggd->probes.serv_ip); addr_aton("127.0.0.1", &ggd->viz.serv_ip); ggd->probes.serv_port = GLOUGLOU_PROBE_DEFAULT_PORT; ggd->viz.serv_port = GLOUGLOU_VIZ_DEFAULT_PORT; ggd->daemonize = 1; ggd->logfile = GLOUGLOUD_LOGFILE; ggd->loglevel = LOG_WARN; ggd->redis.socket_chrooted = "/socket/redis.sock"; ggd->redis.socket = "/var/lib/glougloud/chroot/socket/redis.sock"; while ((op = getopt(argc, argv, "Dhl:L:p:P:v")) != -1) { switch (op) { case 'D': ggd->logfile = NULL; ggd->daemonize = 0; break; case 'h': usage(); /* NOTREACHED */ case 'l': if (addr_aton(optarg, &ggd->probes.serv_ip) < 0) err(1, "invalid probes server ip"); break; case 'L': if (addr_aton(optarg, &ggd->viz.serv_ip) < 0) err(1, "invalid vizualisation server ip"); break; case 'p': ggd->probes.serv_port = atoi(optarg); break; case 'P': ggd->viz.serv_port = atoi(optarg); break; case 'v': ggd->loglevel++; break; default: usage(); /* NOTREACHED */ } } if (geteuid() != 0) errx(1, "must be root"); log_init(ggd->logfile, ggd->loglevel); log_warn("glougloud startup"); if (redis_init(ggd) < 0) log_fatal("init redis failed"); if (probes_init(ggd) < 0) log_fatal("init probes failed"); if (viz_init(ggd) < 0) log_fatal("init viz failed"); ev_base = event_base_new(); ev_sigint = evsignal_new(ev_base, SIGINT, sig_handler, NULL); ev_sigterm = evsignal_new(ev_base, SIGTERM, sig_handler, NULL); ev_sigchld = evsignal_new(ev_base, SIGCHLD, sig_handler, NULL); ev_sighup = evsignal_new(ev_base, SIGHUP, sig_handler, NULL); evsignal_add(ev_sigint, NULL); evsignal_add(ev_sigterm, NULL); evsignal_add(ev_sigchld, NULL); evsignal_add(ev_sighup, NULL); signal(SIGPIPE, SIG_IGN); if (ggd->daemonize) { ggd->pid = fork(); log_info("daemonized, pid %d", ggd->pid); if (ggd->pid > 0) return 0; } event_base_dispatch(ev_base); viz_shutdown(); probes_shutdown(); redis_shutdown(); return 0; }
int main(int argc, char *argv[]) { struct intf_entry ifent; intf_t *intf; int i, tests; char *cmd; if (argc < 3) usage(); for (tests = 0, i = 1; i < argc - 1; i++) { cmd = argv[i]; if (strcmp(cmd, "all") == 0) tests = ~0; else if (strcmp(cmd, "ping") == 0) tests |= TEST_PING; else if (strcmp(cmd, "ip-opt") == 0) tests |= TEST_IP_OPT; else if (strcmp(cmd, "ip-tracert") == 0) tests |= TEST_IP_TRACERT; else if (strcmp(cmd, "frag") == 0) tests |= TEST_FRAG; else if (strcmp(cmd, "frag-new") == 0) tests |= TEST_FRAG_NEW; else if (strcmp(cmd, "frag-old") == 0) tests |= TEST_FRAG_OLD; else if (strcmp(cmd, "frag-timeout") == 0) tests |= TEST_FRAG_TIMEOUT; else usage(); } if (addr_aton(argv[i], &ctx.dst) < 0) err(1, "invalid host %s", argv[i]); if ((intf = intf_open()) == NULL) err(1, "couldn't open interface handle"); ifent.intf_len = sizeof(ifent); if (intf_get_dst(intf, &ifent, &ctx.dst) < 0) err(1, "couldn't find interface for %s", addr_ntoa(&ctx.dst)); memcpy(&ctx.src, &ifent.intf_addr, sizeof(ctx.src)); ctx.src.addr_bits = IP_ADDR_BITS; intf_close(intf); if ((ctx.ip = ip_open()) == NULL) err(1, "couldn't open raw IP interface"); if ((ctx.pcap = pcap_open(ifent.intf_name)) == NULL) err(1, "couldn't open %s for sniffing", ifent.intf_name); if ((ctx.dloff = pcap_dloff(ctx.pcap)) < 0) err(1, "couldn't determine link layer offset"); ctx.rnd = rand_open(); pkt_init(16); TAILQ_INIT(&ctx.pktq); ping = pkt_new(); ip_pack_hdr(ping->pkt_ip, 0, IP_HDR_LEN + 8 + 24, 666, 0, IP_TTL_DEFAULT, IP_PROTO_ICMP, ctx.src.addr_ip, ctx.dst.addr_ip); icmp_pack_hdr_echo(ping->pkt_icmp, ICMP_ECHO, ICMP_CODE_NONE, 666, 1, "AAAAAAAABBBBBBBBCCCCCCCC", 24); ping->pkt_end = ping->pkt_eth_data + IP_HDR_LEN + 8 + 24; pkt_decorate(ping); if ((tests & TEST_PING) != 0) test_ping(); if ((tests & TEST_IP_OPT) != 0) test_ip_opt(); if ((tests & TEST_IP_TRACERT) != 0) test_ip_tracert(); if ((tests & TEST_FRAG) != 0) test_frag(NULL, 0); if ((tests & TEST_FRAG_NEW) != 0) test_frag("new", 0); if ((tests & TEST_FRAG_OLD) != 0) test_frag("old", 0); if ((tests & TEST_FRAG_TIMEOUT) != 0) test_frag(NULL, 1); rand_close(ctx.rnd); pcap_close(ctx.pcap); ip_close(ctx.ip); exit(0); }
static int _intf_get_aliases(intf_t *intf, struct intf_entry *entry) { struct ifreq *ifr, *lifr; struct ifreq tmpifr; struct addr *ap, *lap; char *p; if (intf->ifc.ifc_len < (int)sizeof(*ifr)) { errno = EINVAL; return (-1); } entry->intf_alias_num = 0; ap = entry->intf_alias_addrs; lifr = (struct ifreq *)intf->ifc.ifc_buf + (intf->ifc.ifc_len / sizeof(*lifr)); lap = (struct addr *)((u_char *)entry + entry->intf_len); /* Get addresses for this interface. */ for (ifr = intf->ifc.ifc_req; ifr < lifr && (ap + 1) < lap; ifr = NEXTIFR(ifr)) { /* XXX - Linux, Solaris ifaliases */ if ((p = strchr(ifr->ifr_name, ':')) != NULL) *p = '\0'; if (strcmp(ifr->ifr_name, entry->intf_name) != 0) { if (p) *p = ':'; continue; } /* Fix the name back up */ if (p) *p = ':'; if (addr_ston(&ifr->ifr_addr, ap) < 0) continue; /* XXX */ if (ap->addr_type == ADDR_TYPE_ETH) { memcpy(&entry->intf_link_addr, ap, sizeof(*ap)); continue; } else if (ap->addr_type == ADDR_TYPE_IP) { if (ap->addr_ip == entry->intf_addr.addr_ip || ap->addr_ip == entry->intf_dst_addr.addr_ip) continue; strlcpy(tmpifr.ifr_name, ifr->ifr_name, sizeof(tmpifr.ifr_name)); if (ioctl(intf->fd, SIOCGIFNETMASK, &tmpifr) == 0) addr_stob(&tmpifr.ifr_addr, &ap->addr_bits); } #ifdef SIOCGIFNETMASK_IN6 else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) { struct in6_ifreq ifr6; /* XXX - sizeof(ifr) < sizeof(ifr6) */ memcpy(&ifr6, ifr, sizeof(ifr6)); if (ioctl(intf->fd6, SIOCGIFNETMASK_IN6, &ifr6) == 0) { addr_stob((struct sockaddr *)&ifr6.ifr_addr, &ap->addr_bits); } else perror("SIOCGIFNETMASK_IN6"); } #else #ifdef SIOCGIFNETMASK6 else if (ap->addr_type == ADDR_TYPE_IP6 && intf->fd6 != -1) { struct in6_ifreq ifr6; /* XXX - sizeof(ifr) < sizeof(ifr6) */ memcpy(&ifr6, ifr, sizeof(ifr6)); if (ioctl(intf->fd6, SIOCGIFNETMASK6, &ifr6) == 0) { /* For some reason this is 0 after the ioctl. */ ifr6.ifr_Addr.sin6_family = AF_INET6; addr_stob((struct sockaddr *)&ifr6.ifr_Addr, &ap->addr_bits); } else perror("SIOCGIFNETMASK6"); } #endif #endif ap++, entry->intf_alias_num++; } #ifdef HAVE_LINUX_PROCFS #define PROC_INET6_FILE "/proc/net/if_inet6" { FILE *f; char buf[256], s[8][5], name[INTF_NAME_LEN]; u_int idx, bits, scope, flags; if ((f = fopen(PROC_INET6_FILE, "r")) != NULL) { while (ap < lap && fgets(buf, sizeof(buf), f) != NULL) { sscanf(buf, "%04s%04s%04s%04s%04s%04s%04s%04s %x %02x %02x %02x %32s\n", s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], &idx, &bits, &scope, &flags, name); if (strcmp(name, entry->intf_name) == 0) { snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s/%d", s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7], bits); addr_aton(buf, ap); ap++, entry->intf_alias_num++; } } fclose(f); } } #endif entry->intf_len = (u_char *)ap - (u_char *)entry; return (0); }
static void fragroute_init(const char *dst, const char *outfile) { struct arp_entry arpent; struct intf_entry ifent; struct route_entry rtent; #ifdef WIN32 WSADATA wsdata; if (WSAStartup(MAKEWORD(2, 2), &wsdata) != 0) err(1, "couldn't initialize Winsock"); SetConsoleCtrlHandler(fragroute_signal, TRUE); #else signal(SIGINT, fragroute_signal); signal(SIGTERM, fragroute_signal); #endif if (addr_aton(dst, &ctx.dst) < 0) err(1, "destination address invalid"); if (ctx.dst.addr_bits != IP_ADDR_BITS) errx(1, "only /32 destinations supported at this time"); pkt_init(128); event_init(); // event_sigcb = fragroute_close; if ((ctx.arp = arp_open()) == NULL || (ctx.intf = intf_open()) == NULL || (ctx.route = route_open()) == NULL) err(1, "couldn't open kernel networking interfaces"); /* Find outgoing interface, addresses, and MTU. */ ifent.intf_len = sizeof(ifent); if (intf_get_dst(ctx.intf, &ifent, &ctx.dst) < 0) err(1, "couldn't determine outgoing interface"); memcpy(&ctx.src, &ifent.intf_addr, sizeof(ctx.src)); ctx.src.addr_bits = IP_ADDR_BITS; memcpy(&ctx.smac, &ifent.intf_link_addr, sizeof(ctx.smac)); ctx.mtu = ifent.intf_mtu; /* Open outgoing interface for sending. */ if ((ctx.eth = eth_open(ifent.intf_name)) == NULL) err(1, "couldn't open %s for sending", ifent.intf_name); /* Find destination MAC address. */ memcpy(&arpent.arp_pa, &ctx.dst, sizeof(arpent.arp_pa)); if (arp_get(ctx.arp, &arpent) < 0) { memcpy(&rtent.route_dst, &ctx.dst, sizeof(rtent.route_dst)); if (route_get(ctx.route, &rtent) < 0) err(1, "no route to %s", addr_ntoa(&rtent.route_dst)); memcpy(&arpent.arp_pa, &rtent.route_gw, sizeof(arpent.arp_pa)); if (arp_get(ctx.arp, &arpent) < 0) err(1, "no ARP entry for %s", addr_ntoa(&arpent.arp_pa)); } memcpy(&ctx.dmac, &arpent.arp_ha, sizeof(ctx.dmac)); /* Setup our tunnel. */ if ((ctx.tun = tun_open(&ctx.src, &ctx.dst, ctx.mtu)) == NULL) err(1, "couldn't initialize tunnel interface"); ctx.dfile = NULL; if (outfile && ((ctx.dfile = pcap_dump_open(ctx.tun->pcap, outfile)) == NULL)) err(1, "couldn't open pcap dump file"); tun_register(ctx.tun, fragroute_process, &ctx); }
static int socket_connect() { int sockfd, n; const int on = 1; struct sockaddr_in addr; struct linger l = { .l_onoff = 1, .l_linger = 0, }; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) err(1, "socket"); setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1) err(1, "linger"); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(dst); addr.sin_port = htons(dport); n = connect(sockfd, (const struct sockaddr*)&addr, sizeof(addr)); if (n == -1) err(1, "connect"); return sockfd; } static void recv_cb(u_char *usr, const struct pcap_pkthdr *h, const u_char *bytes) { static struct send_pkt pkt = { .data = "", .data_len = 0, .seq = 10, .flags = TH_ACK, .ack = 0, }; pcap_t *handle = (pcap_t*)usr; const struct eth_hdr *eth_hdr; const struct ip_hdr *ip_hdr; const struct tcp_hdr *tcp_hdr; const unsigned char *payload; int n; int ip_hdr_len; int tcp_hdr_len; static int c = 0; static unsigned int len = 0; static char buf[2048] = {0}; (void)h; if (!bytes) return; eth_hdr = (const struct eth_hdr*)bytes; ip_hdr = (const struct ip_hdr*)(eth_hdr + 1); ip_hdr_len = ip_hdr->ip_hl * 4; tcp_hdr = (const struct tcp_hdr *)((char *)ip_hdr + ip_hdr_len); tcp_hdr_len = tcp_hdr->th_off * 4; payload = (const unsigned char *)((char *)tcp_hdr + tcp_hdr_len); n = ntohs(ip_hdr->ip_len) - ip_hdr_len - tcp_hdr_len; if (n == 0) /* recv an ack */ return; memcpy(buf + len, payload, n); len += n; /* send an ack */ pkt.ack = ntohl(tcp_hdr->th_seq) + n; raw_send(&pkt, 1); /* XXX wait until 8 or 10 * some system may ignore the packets out of sequence * or not send 2222 */ if (len < strlen(FAVOR_OLD) - 2) return; if (strncmp(buf, FAVOR_OLD, len) == 0) { printf("old\n"); fflush(stdout); } else if (strncmp(buf, FAVOR_NEW, len) == 0) { printf("new\n"); fflush(stdout); } else if (strncmp(buf, FAVOR_BEFORE, len) == 0) { printf("before\n"); fflush(stdout); } else if (strncmp(buf, FAVOR_AFTER, len) == 0) { printf("after\n"); fflush(stdout); } else if (len >= 10) { printf("Unknown %s\n", buf); fflush(stdout); } else { printf("\nrecved %s. try to read again\nrecv:", buf); fflush(stdout); } if (++c > 10) { warnx("tried too many times. exit..."); } pcap_breakloop(handle); } /* prepare addr for libdnet */ static void prepare(int sockfd) { struct sockaddr addr; unsigned int len = sizeof(struct sockaddr); struct sockaddr_in *addr_in; if (-1 == getsockname(sockfd, &addr, &len)) err(1, "getsockname"); addr_in = (struct sockaddr_in *)&addr; src = inet_ntoa(addr_in->sin_addr); sport = ntohs(addr_in->sin_port); printf("local addr: %s:%d\n", src, sport); /* for libdnet */ addr_aton(src, &s_addr); addr_aton(dst, &d_addr); return; } static void *pcap_thread(void *arg) { char errbuf[2048]; const char *dev = NULL; pcap_t *handle; struct bpf_program fp; char rule[2048]; bpf_u_int32 mask; bpf_u_int32 net; struct pcap_pkthdr header; const unsigned char *data = NULL; const struct eth_hdr *eth_hdr; const struct ip_hdr *ip_hdr; const struct tcp_hdr *tcp_hdr; int n; (void)arg; if (local) dev = "lo"; else dev = "eth0"; n = snprintf(rule, sizeof(rule), "src port %d", dport); rule[n] = 0; arg = NULL; if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) err(1, "pcap_lookupnet"); handle = pcap_open_live(dev, BUFSIZ, 0, 0, errbuf); if (!handle) { err(1, "pcap_open_live:%s", errbuf); } if (pcap_compile(handle, &fp, rule, 0, net) == -1) err(1, "pcap_compile %s:%s", rule, errbuf); if (pcap_setfilter(handle, &fp) == -1) err(1, "pcap_setfilter:%s", pcap_geterr(handle)); printf("initializing..."); fflush(stdout); sleep(1); sockfd = socket_connect(); prepare(sockfd); while (!data) data = pcap_next(handle, &header); eth_hdr = (const struct eth_hdr*)data; ip_hdr = (const struct ip_hdr *)(eth_hdr+1); tcp_hdr = (const struct tcp_hdr *)(ip_hdr+1); tcp_seq = ntohl(tcp_hdr->th_ack); dst_seq = ntohl(tcp_hdr->th_seq) + 1; tell_main(); printf("recv:"); fflush(stdout); wait_main(); pcap_loop(handle, 0, recv_cb, (u_char*)handle); pcap_freecode(&fp); pcap_close(handle); close(sockfd); pthread_exit(NULL); } static void usage() { warnx("[s src_port][d dst_port] ip"); }
static IntfEntry * intf_sv2c(SV *h, IntfEntry *ref) { if (ref && h && SvROK(h)) { HV *hv = (HV *)SvRV(h); memset(ref, 0, sizeof(IntfEntry)); if (hv_exists(hv, "intf_len", 8)) { SV **len = hv_fetch((HV *)SvRV(h), "intf_len", 8, 0); ref->intf_len = (SvOK(*len) ? SvIV(*len) : 0); } if (hv_exists(hv, "intf_name", 9)) { SV **name = hv_fetch((HV *)SvRV(h), "intf_name", 9, 0); if (SvOK(*name)) { memcpy(&(ref->intf_name), SvPV(*name, PL_na), sizeof(ref->intf_name)); } } if (hv_exists(hv, "intf_type", 9)) { SV **type = hv_fetch((HV *)SvRV(h), "intf_type", 9, 0); ref->intf_type = (SvOK(*type) ? SvIV(*type) : 0); } if (hv_exists(hv, "intf_flags", 10)) { SV **flags = hv_fetch((HV *)SvRV(h), "intf_flags", 10, 0); ref->intf_flags = (SvOK(*flags) ? SvIV(*flags) : 0); } if (hv_exists(hv, "intf_mtu", 8)) { SV **mtu = hv_fetch((HV *)SvRV(h), "intf_mtu", 8, 0); ref->intf_mtu = (SvOK(*mtu) ? SvIV(*mtu) : 0); } if (hv_exists(hv, "intf_addr", 9)) { SV **addr = hv_fetch((HV *)SvRV(h), "intf_addr", 9, 0); if (SvOK(*addr)) { struct addr a; if (addr_aton(SvPV(*addr, PL_na), &a) == 0) { memcpy(&(ref->intf_addr), &a, sizeof(struct addr)); } } } if (hv_exists(hv, "intf_dst_addr", 13)) { SV **dstAddr = hv_fetch((HV *)SvRV(h), "intf_dst_addr", 13, 0); if (SvOK(*dstAddr)) { struct addr a; if (addr_aton(SvPV(*dstAddr, PL_na), &a) == 0) { memcpy(&(ref->intf_dst_addr), &a, sizeof(struct addr)); } } } if (hv_exists(hv, "intf_link_addr", 14)) { SV **lnkAddr = hv_fetch((HV *)SvRV(h), "intf_link_addr", 14, 0); if (SvOK(*lnkAddr)) { struct addr a; if (addr_aton(SvPV(*lnkAddr, PL_na), &a) == 0) { memcpy(&(ref->intf_link_addr), &a, sizeof(struct addr)); } } } } else { ref = NULL; } // XXX: put aliases also return ref; }
static FwRule * fw_sv2c(SV *h, FwRule *ref) { if (ref && h && SvROK(h)) { HV *hv = (HV *)SvRV(h); memset(ref, 0, sizeof(FwRule)); if (hv_exists(hv, "fw_device", 9)) { SV **r = hv_fetch(hv, "fw_device", 9, 0); if (SvOK(*r)) { memcpy(&(ref->fw_device), SvPV(*r, PL_na), sizeof(ref->fw_device)); } } if (hv_exists(hv, "fw_op", 5)) { SV **r = hv_fetch(hv, "fw_op", 5, 0); ref->fw_op = (SvOK(*r) ? SvIV(*r) : 0); } if (hv_exists(hv, "fw_dir", 6)) { SV **r = hv_fetch(hv, "fw_dir", 6, 0); ref->fw_dir = (SvOK(*r) ? SvIV(*r) : 0); } if (hv_exists(hv, "fw_proto", 8)) { SV **r = hv_fetch(hv, "fw_proto", 8, 0); ref->fw_proto = (SvOK(*r) ? SvIV(*r) : 0); } if (hv_exists(hv, "fw_src", 6)) { SV **r = hv_fetch(hv, "fw_src", 6, 0); if (SvOK(*r)) { struct addr a; if (addr_aton(SvPV(*r, PL_na), &a) == 0) { memcpy(&(ref->fw_src), &a, sizeof(struct addr)); } } } if (hv_exists(hv, "fw_dst", 6)) { SV **r = hv_fetch(hv, "fw_dst", 6, 0); if (SvOK(*r)) { struct addr a; if (addr_aton(SvPV(*r, PL_na), &a) == 0) { memcpy(&(ref->fw_dst), &a, sizeof(struct addr)); } } } if (hv_exists(hv, "fw_sport", 8)) { SV **r = hv_fetch(hv, "fw_sport", 8, 0); if (SvOK(*r)) { AV *a = (AV *)SvRV(*r); SV *p1 = av_shift(a); SV *p2 = av_shift(a); ref->fw_sport[0] = (SvOK(p1) ? SvIV(p1) : 0); ref->fw_sport[1] = (SvOK(p2) ? SvIV(p2) : 0); } } if (hv_exists(hv, "fw_dport", 8)) { SV **r = hv_fetch(hv, "fw_dport", 8, 0); if (SvOK(*r)) { AV *a = (AV *)SvRV(*r); SV *p1 = av_shift(a); SV *p2 = av_shift(a); ref->fw_dport[0] = (SvOK(p1) ? SvIV(p1) : 0); ref->fw_dport[1] = (SvOK(p2) ? SvIV(p2) : 0); } } } else { ref = NULL; } return ref; }
int ip_main(int argc, char *argv[]) { struct ip_hdr *ip; struct addr addr; u_char *p, buf[IP_LEN_MAX]; /* XXX */ char *name, *value; int c, len; srand(time(NULL)); ip = (struct ip_hdr *)buf; ip->ip_hl = 5; ip->ip_v = 4; ip->ip_tos = 0; ip->ip_id = rand() & 0xffff; ip->ip_off = 0; ip->ip_ttl = IP_TTL_MAX; ip->ip_p = rand() & 0xff; ip->ip_sum = 0; ip->ip_src = rand(); ip->ip_dst = rand(); for (c = 1; c + 1 < argc; c += 2) { name = argv[c]; value = argv[c + 1]; if (strcmp(name, "tos") == 0) ip->ip_tos = atoi(value); else if (strcmp(name, "id") == 0) ip->ip_id = ntohs(atoi(value)); else if (strcmp(name, "off") == 0) { if (off_aton(value, &ip->ip_off) < 0) ip_usage(); } else if (strcmp(name, "ttl") == 0) ip->ip_ttl = atoi(value); else if (strcmp(name, "proto") == 0) { if (proto_aton(value, &ip->ip_p) < 0) ip_usage(); } else if (strcmp(name, "src") == 0) { if (addr_aton(value, &addr) < 0) ip_usage(); ip->ip_src = addr.addr_ip; } else if (strcmp(name, "dst") == 0) { if (addr_aton(value, &addr) < 0) ip_usage(); ip->ip_dst = addr.addr_ip; } else ip_usage(); } argc -= c; argv += c; if (argc != 0) ip_usage(); if (isatty(STDIN_FILENO)) errx(1, "can't read IP payload from tty"); p = buf + IP_HDR_LEN; len = sizeof(buf) - (p - buf); while ((c = read(STDIN_FILENO, p, len)) > 0) { p += c; len -= c; } len = p - buf; ip->ip_len = htons(len); ip_checksum(buf, len); if (write(STDOUT_FILENO, buf, len) != len) err(1, "write"); return (0); }