📄 agentadv.c
字号:
if (dev != NULL && setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, dev, IFNAMSIZ)) { DEBUG(DEBUG_FLAG, "open_agent_icmp_socket - " "setsockopt(SOL_SOCKET, SO_BINDTODEVICE): %s\n", strerror(errno)); close(s); return -1; } /* let the kernel filter out uninteresting ICMP messages */ ifilter.data = filter; if (setsockopt(s, SOL_RAW, ICMP_FILTER, &ifilter, sizeof(ifilter)) < 0) { DEBUG(DEBUG_FLAG, "setsockopt: ICMP_FILTER failed: %s\n", strerror(errno)); /* do not send error code - the filtering is done in this * daemon instead */ } /* join multicast groups 224.0.0.1 and 224.0.0.2 */ memset(&imr, 0, sizeof(imr)); if (dev != NULL) { if (dyn_ip_get_ifaddr(dev, &imr.imr_interface) != 0) { DEBUG(DEBUG_FLAG, "open_agent_icmp_socket - " "could not get ifaddr for %s; trying to " "continue without joining multicast groups\n", dev); return s; } } inet_aton("224.0.0.1", &imr.imr_multiaddr); if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreq)) < 0) { DEBUG(DEBUG_FLAG, "setsockopt: IP_ADD_MEMBERSHIP failed: %s\n", strerror(errno)); /* try to live without multicast */ } inet_aton("224.0.0.2", &imr.imr_multiaddr); if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &imr, sizeof(struct ip_mreq)) < 0) { DEBUG(DEBUG_FLAG, "setsockopt: IP_ADD_MEMBERSHIP failed: %s\n", strerror(errno)); /* try to live without multicast */ }#endif#ifdef DYN_TARGET_WINDOWS int i; s = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); if (s < 0) { DEBUG(DEBUG_FLAG, "socket(SOCK_RAW) failed: %s\n", strerror(errno)); return -1; } i = 1; if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof(i)) < 0) { DEBUG(DEBUG_FLAG, "socket(SOCK_RAW) failed: %s\n", strerror(errno)); }#endif return s;}#ifdef DYN_TARGET_LINUX/** * send_agent_advertisement: * @s: packet socket (PF_PACKET, SOCK_DGRAM) * @dest: unicast destination address (HW) or %NULL for broadcast message * @destaddr: unicast destination address (IP) or %NULL for broadcast message * @ifindex: interface index * * Make the agent advertisement message and send it. * If @dest is %NULL, use defined broadcast or multicast destination and * set the TTL to one. * * Returns: * 0) no errors, * -3) send failed */int send_agent_advertisement(int s, struct sockaddr *dest, struct in_addr *destaddr, int ifindex){ static __u16 next_agent_adv_seq = 0; /* counter used in determining the advertisement sequence number in _host_ byte order */ unsigned char buf[MAX_ADV_MSG]; struct iphdr *ip; struct router_adv *radv; struct agent_adv_ext *ext; struct agent_adv_dynamics *own_ext; int len, i, err; struct sockaddr_ll bc_addr; struct in_addr *addr, ownaddr, dstaddr; char dev[IFNAMSIZ]; DEBUG(DEBUG_FLAG, "sending agent advertisement\n"); if (dest == NULL) { dest = (struct sockaddr *) &bc_addr; memset((char *) &bc_addr, 0, sizeof(bc_addr)); bc_addr.sll_family = AF_PACKET; bc_addr.sll_protocol = htons(ETH_P_IP); bc_addr.sll_ifindex = ifindex; bc_addr.sll_hatype = htons(ARPHRD_ETHER); bc_addr.sll_halen = ETH_ALEN; /* FIX: add support for other L2 * devices */ memset(bc_addr.sll_addr, 0xff, sizeof(bc_addr.sll_addr)); } if (destaddr == NULL) { inet_aton(AGENT_ADV_DEST_IP, &dstaddr); destaddr = &dstaddr; } memset(buf, 0, sizeof(buf)); DEBUG(DEBUG_FLAG, " * IP header, len=%i\n", sizeof(struct iphdr)); ip = (struct iphdr *) buf; ip->ihl = 5; ip->version = 4; ip->ttl = dest == NULL ? 1 : 255; ip->protocol = IPPROTO_ICMP; ip->daddr = destaddr->s_addr; if (dyn_ip_get_ifname(ifindex, dev) < 0 || dyn_ip_get_ifaddr(dev, &ownaddr) < 0) DEBUG(DEBUG_FLAG, "Could not get own address for agentadv\n"); ip->saddr = ip->saddr = ownaddr.s_addr; len = sizeof(struct iphdr); /* ICMP Router Advertisement message - see RFC 1256 and * RFC 2002, chapter 2 */ DEBUG(DEBUG_FLAG, " * header, len=%i\n", sizeof(struct router_adv)); radv = (struct router_adv *) (ip + 1); radv->type = ICMP_ROUTERADVERT; radv->code = 16; /* no common traffic routing; could also be 0 * if the mobility agent handles also common * traffic */ radv->checksum = 0; /* set to zero for checksum calculation */ radv->num_addr = 0; /* Our implementation does not advertise general * routers */ radv->entry_size = 2; /* maximum time that this agent advertisement is consider valid */ radv->lifetime = data.adv_lifetime; len += sizeof(struct router_adv); ext = (struct agent_adv_ext *) (buf + len); ext->type = 16; addr = (struct in_addr *) (ext + 1); addr->s_addr = data.agent_own_addr; addr++; /* FIX: remove own address and use only HFA address (?) */ if (data.highest_fa_addr == 0 || data.agent_own_addr == data.highest_fa_addr) { ext->length = 10; } else { ext->length = 14; /* Change "priority". Add highest FA address as the first entry */ addr->s_addr = data.agent_own_addr; addr--; addr->s_addr = data.highest_fa_addr; } /* Sequence Number - see RFC 2002, section 2.3.2 */ ext->seq = htons(next_agent_adv_seq); if (next_agent_adv_seq < 0xffff) next_agent_adv_seq++; else next_agent_adv_seq = 256; /* maximum lifetime for tunnels */ ext->reg_lifetime = data.max_lifetime; ext->opts = data.agent_adv_opt; DEBUG(DEBUG_FLAG, " * agentadv ext, len=%i\n", radv->num_addr * sizeof(struct router_adv_router) + 2 + ext->length); len += radv->num_addr * sizeof(struct router_adv_router) + 2 + ext->length; DEBUG(DEBUG_FLAG, " * Dynamics ext, len=%i\n", sizeof(struct agent_adv_dynamics)); own_ext = (struct agent_adv_dynamics *) (buf + len); own_ext->type = VENDOR_EXT_TYPE2; own_ext->length = sizeof(struct agent_adv_dynamics) - 2; own_ext->reserved = 0; own_ext->vendor_id = htonl(VENDOR_ID_DYNAMICS); own_ext->sub_type = htons(VENDOR_EXT_DYNAMICS_AGENTADV); own_ext->version = VENDOR_EXT_VERSION; own_ext->opts = data.own_agent_adv_opt; own_ext->reserved2 = 0;#ifdef INCLUDE_IPAY DEBUG(DEBUG_FLAG, "ADV: timePrice=%i, bytePrice=%i\n", ntohl(data.timePrice), ntohl(data.bytePrice)); if (own_ext->length >= sizeof(struct agent_adv_dynamics) - 2) { own_ext->timePrice = data.timePrice; own_ext->bytePrice = data.bytePrice; } else { DEBUG(DEBUG_FLAG, " * no price in adv\n"); own_ext->timePrice = 0; own_ext->bytePrice = 0; }#endif len += sizeof(struct agent_adv_dynamics); if (data.hfa_pubkey_hash != NULL) { struct msg_key *hashext = (struct msg_key *) (buf + len); init_key_extension(hashext, VENDOR_EXT_DYNAMICS_PUBKEY_HASH, htonl(PUBKEY_ALG_SPI_RSA), data.hfa_pubkey_hash_len); MOVE_UNALIGNED(MSG_KEY_DATA(hashext), data.hfa_pubkey_hash, data.hfa_pubkey_hash_len); len += GET_KEY_EXT_LEN(hashext); DEBUG(DEBUG_FLAG, " * pubkey hash, len=%i\n", GET_KEY_EXT_LEN(hashext)); } if (data.fa_nai_extension != NULL) { if (len + GET_NAI_EXT_LEN(data.fa_nai_extension) > MAX_ADV_MSG) { DEBUG(DEBUG_FLAG, "send_agent_advertisement - " "too small buffer for FA NAI extension\n"); return -3; } MOVE_UNALIGNED(buf + len, data.fa_nai_extension, GET_NAI_EXT_LEN(data.fa_nai_extension)); len += GET_NAI_EXT_LEN(data.fa_nai_extension); DEBUG(DEBUG_FLAG, " * FA NAI, len=%i\n", GET_NAI_EXT_LEN(data.fa_nai_extension)); } if (data.challenge != NULL) { int j; unsigned char *c; if (len + GET_CHALLENGE_EXT_LEN(data.challenge) > MAX_ADV_MSG) { DEBUG(DEBUG_FLAG, "send_agent_advertisement - " "too small buffer for challenge extension\n"); return -3; } MOVE_UNALIGNED(buf + len, data.challenge, GET_CHALLENGE_EXT_LEN(data.challenge)); len += GET_CHALLENGE_EXT_LEN(data.challenge); DEBUG(DEBUG_FLAG, " * Challenge, len=%i: ", GET_CHALLENGE_EXT_LEN(data.challenge)); c = MSG_CHALLENGE_EXT_DATA(data.challenge); for (j = 0; j < GET_CHALLENGE_LEN(data.challenge); j++) DEBUG(DEBUG_FLAG, "%02X", *c++); DEBUG(DEBUG_FLAG, "\n"); } DEBUG(DEBUG_FLAG, " * total len: %i\n", len); radv->checksum = ip_checksum((unsigned char *) radv, len - sizeof(struct iphdr)); ip->tot_len = htons(len); ip->check = 0; ip->check = ip_checksum(buf, sizeof(*ip)); i = sendto(s, buf, len, 0, dest, sizeof(struct sockaddr_ll)); err = errno; if (i < 0) { DEBUG(DEBUG_FLAG, "send_agent_advertisement - sendto: %s\n", strerror(err)); return -3; } if (i != len) { DEBUG(DEBUG_FLAG, "agent adv: wrote %d/%d\n", i, len); return -3; }#ifdef PACKET_DUMP DEBUG_HEXDUMP(DEBUG_FLAG, "Send agentadv", buf, i);#endif return 0;}#endif /* DYN_TARGET_LINUX *//** * send_agent_solicitation: * @s: * * Make the agent solicitation message and send it * An Agent Solicitation message is identical to an ICMP Router Solicitation * [RFC1256] with the further restriction that the IP TTL field is set to 1. * [RFC2002] * * Returns: * 0) no errors, * -1) setsockopt IP_TTL failed, * -2) setsockopt SO_BROADCAST failed, * -3) send failed */int send_agent_solicitation(int s){ struct agent_sol sol; int len; int i, err;#ifdef DYN_TARGET_LINUX unsigned char ttl;#endif struct sockaddr_in bc_addr; DEBUG(DEBUG_FLAG, "sending agent solicitation\n"); memset((char *) &bc_addr, 0, sizeof(bc_addr)); bc_addr.sin_family = AF_INET; inet_aton(AGENT_SOL_DEST_IP, &bc_addr.sin_addr); /* FIX: agent solicitation sending does not yet work with Windows */#ifdef DYN_TARGET_LINUX ttl = 1; if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, 1) < 0) { DEBUG(DEBUG_FLAG, "setsockopt: IP_TTL failed: %s\n", strerror(errno)); return -1; }#endif i = 1; if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof(i)) < 0) { DEBUG(DEBUG_FLAG, "setsockopt: SO_BROADCAST failed: %s\n", strerror(errno)); return -2; } /* ICMP Agent solicitation - see RFC 1256 and RFC 2002 */ sol.type = 10; sol.code = 0; sol.checksum = htons(0); /* set to zero for checksum calculation */ sol.reserved = htonl(0); len = sizeof(sol); sol.checksum = ip_checksum((unsigned char *) &sol, len); i = sendto(s, &sol, len, 0, (struct sockaddr *) &bc_addr, sizeof(struct sockaddr)); err = errno; if (i < 0) { DEBUG(DEBUG_FLAG, "send_agent_solicitation - sendto: %s\n", strerror(err)); return -3; } if (i != len) { DEBUG(DEBUG_FLAG, "agent sol: wrote %d/%d\n", len, i); return -3; } return 0;}#ifdef DYN_TARGET_LINUX/** * check_icmp_sol: * @s: * @data:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -