void pcap_network_interface::send_raw_icmp(struct in6_addr *dest, struct in6_addr *src, const unsigned char *icmp_body, const unsigned int icmp_len) { uint8_t all_hosts_addr[] = {0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; unsigned char packet[icmp_len+sizeof(ip6_hdr)+16]; if (dest == NULL) { dest = (struct in6_addr *)all_hosts_addr; /* XXX WRONG WRONG WRONG */ } /* layer 2 */ memset(packet, 0, sizeof(packet)); packet[0] =0x02; packet[1]=0x34; packet[2]=0x56; packet[3] =0x78; packet[4]=0x9a; packet[5]=0xbc; memcpy(packet+6, this->if_hwaddr, 6); packet[12]=0x86; packet[13]=0xdd; /* layer 3 */ unsigned char *layer3 = &packet[14]; struct ip6_hdr *v6 = (struct ip6_hdr *)layer3; v6->ip6_src = link_local(); if(src) { memcpy(&v6->ip6_src, src, 16); } v6->ip6_vfc = 6 << 4; memcpy(&v6->ip6_dst, dest, 16); v6->ip6_nxt = IPPROTO_ICMPV6; v6->ip6_hlim= 64; v6->ip6_plen= htons(icmp_len); /* layer 4+ */ unsigned char *payload = (unsigned char *)(v6+1); memcpy(payload, icmp_body, icmp_len); struct icmp6_hdr *icmp6h = (struct icmp6_hdr *)payload; /* compute checksum */ icmp6h->icmp6_cksum = 0; unsigned short icmp6sum = csum_ipv6_magic(&v6->ip6_src, &v6->ip6_dst, icmp_len, IPPROTO_ICMPV6, 0); #if 0 unsigned int chksum_len = icmp_len+sizeof(struct ip6_hdr); printf("iface output of %u bytes (%u)\n", chksum_len, icmp_len); hexdump(layer3, 0, chksum_len); #endif icmp6sum = csum_partial(payload, icmp_len, icmp6sum); icmp6sum = (~icmp6sum & 0xffff); icmp6h->icmp6_cksum = icmp6sum; struct pcap_pkthdr h; memset(&h, 0, sizeof(h)); h.caplen = 14+40+icmp_len; h.len = h.caplen; gettimeofday(&h.ts, NULL); if(this->pcap_out) { pcap_dump((u_char *)this->pcap_out, &h, packet); } }
json_t* make_address_file() { json_t *ipAddrTable_json = json_object(); json_t *ipAddrEntry_array = json_array(); struct rtnl_handle rth = { .fd = -1 }; if (rtnl_open(&rth, 0) < 0) { exit(1); } int preferred_family = AF_PACKET; if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETADDR) < 0) { perror("Cannot send dump request"); exit(1); } struct nlmsg_list *ainfo = NULL; if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } struct nlmsg_list *a, *n; for (a = ainfo; a; a = n) { n = a->next; struct nlmsghdr *nlhdr = &(a->h); struct ifaddrmsg *ifamsg = NLMSG_DATA(nlhdr); // Process Data of Netlink Message as ifaddrmsg if (ifamsg->ifa_family != AF_INET && ifamsg->ifa_family != AF_INET6) { printf("error family: %d\n", ifamsg->ifa_family); continue; } json_t *address_json = json_object(); json_object_set_new(address_json, "ipAdEntIfIndex", json_integer(ifamsg->ifa_index)); json_object_set_new(address_json, "ipAdEntNetMask", json_integer(ifamsg->ifa_prefixlen)); // Analyze rtattr Message int len = nlhdr->nlmsg_len - NLMSG_LENGTH(sizeof(*ifamsg));; struct rtattr *tb[IFA_MAX+1]; parse_rtattr(tb, IFA_MAX, IFA_RTA(ifamsg), len); char abuf[256]; if (tb[IFA_ADDRESS]) { json_object_set_new(address_json, "ipAdEntAddr", json_string(rt_addr_n2a(ifamsg->ifa_family, RTA_PAYLOAD(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_ADDRESS]), abuf, sizeof(abuf)))); } if (tb[IFA_BROADCAST]) { json_object_set_new(address_json, "ipAdEntBcastAddr", json_string(rt_addr_n2a(ifamsg->ifa_family, RTA_PAYLOAD(tb[IFA_BROADCAST]), RTA_DATA(tb[IFA_BROADCAST]), abuf, sizeof(abuf)))); } json_array_append(ipAddrEntry_array, address_json); } json_object_set_new(ipAddrTable_json, "ipAddrEntry", ipAddrEntry_array); free(a); rtnl_close(&rth); return ipAddrTable_json; } int link_local(char *address) { if (strncmp(address, "fe80:", 5) == 0) { return 1; } return 0; } int delete_address(int interface, char *address) { if (link_local(address)) { fprintf(stderr, "Can't delete ipv6 link local address.\n"); return 0; } struct rtnl_handle rth = { .fd = -1 }; if (rtnl_open(&rth, 0) < 0) { exit(1); } struct iplink_req req; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST; req.ifa.ifa_index = interface; req.ifa.ifa_flags = 0; req.ifa.ifa_scope = 0; req.n.nlmsg_type = RTM_DELADDR; inet_prefix lcl; get_prefix(&lcl, address, req.ifa.ifa_family); addattr_l(&req.n, sizeof(req), IFA_LOCAL, &lcl.data, lcl.bytelen); req.ifa.ifa_prefixlen = lcl.bitlen; req.ifa.ifa_family = lcl.family; ll_init_map(&rth); if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) { exit(2); } fprintf(stderr, "delete address %s\n", address); return 0; } int delete_all_address() { struct rtnl_handle rth = { .fd = -1 }; if (rtnl_open(&rth, 0) < 0) { exit(1); } if (rtnl_wilddump_request(&rth, AF_PACKET, RTM_GETADDR) < 0) { perror("Cannot send dump request\n"); exit(1); } struct nlmsg_list *ainfo = NULL; if (rtnl_dump_filter(&rth, store_nlmsg, &ainfo, NULL, NULL) < 0) { fprintf(stderr, "Dump terminated\n"); exit(1); } struct nlmsg_list *a, *n; for (a = ainfo; a; a = n) { n = a->next; struct nlmsghdr *nlhdr = &(a->h); struct ifaddrmsg *ifamsg = NLMSG_DATA(nlhdr); // Process Data of Netlink Message as ifaddrmsg if (ifamsg->ifa_family != AF_INET && ifamsg->ifa_family != AF_INET6) { fprintf(stderr, "error family: %d\n", ifamsg->ifa_family); continue; } // Analyze rtattr Message int len = nlhdr->nlmsg_len - NLMSG_LENGTH(sizeof(*ifamsg));; struct rtattr *tb[IFA_MAX+1]; parse_rtattr(tb, IFA_MAX, IFA_RTA(ifamsg), len); char buf[64] = ""; char abuf[256]; if (tb[IFA_ADDRESS]) { sprintf(buf, "%s", rt_addr_n2a(ifamsg->ifa_family, RTA_PAYLOAD(tb[IFA_ADDRESS]), RTA_DATA(tb[IFA_ADDRESS]), abuf, sizeof(abuf))); } delete_address(ifamsg->ifa_index, buf); } fprintf(stderr, "delete all addresses.(except link local addresses)\n\n"); free(a); rtnl_close(&rth); return 0; } void modify_address(json_t *ipAddrEntry_json) { int i; for (i = 0; i < (int)json_array_size(ipAddrEntry_json); i++) { json_t *address_json = json_array_get(ipAddrEntry_json, i); struct rtnl_handle rth = { .fd = -1 }; if (rtnl_open(&rth, 0) < 0) { exit(1); } struct iplink_req req; memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; req.ifa.ifa_index = (int)json_number_value(json_object_get(address_json, "ipAdEntIfIndex")); req.ifa.ifa_prefixlen = (int)json_number_value(json_object_get(address_json, "ipAdEntNetMask")); req.ifa.ifa_flags = 0; req.ifa.ifa_family = 0; req.ifa.ifa_scope = 0; req.n.nlmsg_type = RTM_NEWADDR; inet_prefix addr; int link_local_flag = 0; char *address_name = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; const char *key; json_t *value; json_object_foreach(address_json, key, value) { if (strcmp(key, "ipAdEntAddr") == 0) { // if link_local -> skip if (link_local((char *)json_string_value(value))) { link_local_flag = 1; break; } address_name = (char *)json_string_value(value); get_prefix(&addr, address_name, req.ifa.ifa_family); addattr_l(&req.n, sizeof(req), IFA_LOCAL, &addr.data, addr.bytelen); addattr_l(&req.n, sizeof(req), IFA_ADDRESS, &addr.data, addr.bytelen); req.ifa.ifa_family = addr.family; } if (strcmp(key, "ipAdEntBcastAddr") == 0) { get_addr(&addr, (char *)json_string_value(value), req.ifa.ifa_family); if (req.ifa.ifa_family == AF_UNSPEC) req.ifa.ifa_family = addr.family; addattr_l(&req.n, sizeof(req), IFA_BROADCAST, &addr.data, addr.bytelen); } } if (link_local_flag) { fprintf(stderr, "Don't assign link local address.\n"); continue; } if (req.ifa.ifa_family == 0) { printf("No address data\n"); exit(5); } ll_init_map(&rth); if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) { exit(2); } fprintf(stderr, "arrange address %s/%d\n", address_name, req.ifa.ifa_prefixlen); } fprintf(stderr, "Success arranging all addresses!\n\n"); } int read_address_file(json_t* addresses_json) { // 全部のアドレス情報を削除する必要あり delete_all_address(); json_t *ipAddrEntry_json = json_object_get(addresses_json, "ipAddrEntry"); modify_address(ipAddrEntry_json); return 0; }