Ejemplo n.º 1
0
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);
    }
}
Ejemplo n.º 2
0
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;
}