unsigned int mroute_extract_addr_ipv4 (struct mroute_addr *src, struct mroute_addr *dest, const struct buffer *buf) { unsigned int ret = 0; if (BLEN (buf) >= 1) { switch (OPENVPN_IPH_GET_VER (*BPTR(buf))) { case 4: if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr)) { const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf); mroute_get_in_addr_t (src, ip->saddr, 0); mroute_get_in_addr_t (dest, ip->daddr, 0); /* multicast packet? */ if (mroute_is_mcast (ip->daddr)) ret |= MROUTE_EXTRACT_MCAST; /* IGMP message? */ if (ip->protocol == OPENVPN_IPPROTO_IGMP) ret |= MROUTE_EXTRACT_IGMP; ret |= MROUTE_EXTRACT_SUCCEEDED; } break; case 6: if (BLEN (buf) >= (int) sizeof (struct openvpn_ipv6hdr)) { const struct openvpn_ipv6hdr *ipv6 = (const struct openvpn_ipv6hdr *) BPTR (buf); #if 0 /* very basic debug */ struct gc_arena gc = gc_new (); msg( M_INFO, "IPv6 packet! src=%s, dst=%s", print_in6_addr( ipv6->saddr, 0, &gc ), print_in6_addr( ipv6->daddr, 0, &gc )); gc_free (&gc); #endif mroute_get_in6_addr (src, ipv6->saddr, 0); mroute_get_in6_addr (dest, ipv6->daddr, 0); if (mroute_is_mcast_ipv6 (ipv6->daddr)) ret |= MROUTE_EXTRACT_MCAST; ret |= MROUTE_EXTRACT_SUCCEEDED; } break; default: msg (M_WARN, "IP packet with unknown IP version=%d seen", OPENVPN_IPH_GET_VER (*BPTR(buf))); } } return ret; }
/* * If raw tunnel packet is IPv4, return true and increment * buffer offset to start of IP header. */ bool is_ipv4 (int tunnel_type, struct buffer *buf) { int offset; const struct openvpn_iphdr *ih; verify_align_4 (buf); if (tunnel_type == DEV_TYPE_TUN) { if (BLEN (buf) < (int) sizeof (struct openvpn_iphdr)) return false; offset = 0; } else if (tunnel_type == DEV_TYPE_TAP) { const struct openvpn_ethhdr *eh; if (BLEN (buf) < (int)(sizeof (struct openvpn_ethhdr) + sizeof (struct openvpn_iphdr))) return false; eh = (const struct openvpn_ethhdr *) BPTR (buf); if (ntohs (eh->proto) != OPENVPN_ETH_P_IPV4) return false; offset = sizeof (struct openvpn_ethhdr); } else return false; ih = (const struct openvpn_iphdr *) (BPTR (buf) + offset); if (OPENVPN_IPH_GET_VER (ih->version_len) == 4) return buf_advance (buf, offset); else return false; }
/* * If raw tunnel packet is IPv<X>, return true and increment * buffer offset to start of IP header. */ static bool is_ipv_X( int tunnel_type, struct buffer *buf, int ip_ver ) { int offset; const struct openvpn_iphdr *ih; verify_align_4(buf); if (tunnel_type == DEV_TYPE_TUN) { //tun类型,不包含以太头 if (BLEN(buf) < (int) sizeof(struct openvpn_iphdr)) { return false; } offset = 0; } else if (tunnel_type == DEV_TYPE_TAP) { //tap类型,包含以太头 const struct openvpn_ethhdr *eh; if (BLEN(buf) < (int)(sizeof(struct openvpn_ethhdr) + sizeof(struct openvpn_iphdr))) { return false; } eh = (const struct openvpn_ethhdr *) BPTR(buf); if (ntohs(eh->proto) != (ip_ver == 6 ? OPENVPN_ETH_P_IPV6 : OPENVPN_ETH_P_IPV4)) { //非指定协议,返回false return false; } offset = sizeof(struct openvpn_ethhdr); } else { return false; } //指向ip头部 ih = (const struct openvpn_iphdr *) (BPTR(buf) + offset); /* IP version is stored in the same bits for IPv4 or IPv6 header */ if (OPENVPN_IPH_GET_VER(ih->version_len) == ip_ver) { //为对应ip协议,使buf指向对应的ip头部 return buf_advance(buf, offset); } else { //非对应的ip协议,返回false return false; } }
unsigned int mroute_extract_addr_ipv4 (struct mroute_addr *src, struct mroute_addr *dest, const struct buffer *buf) { unsigned int ret = 0; static bool ipv6warned = false; if (BLEN (buf) >= 1) { switch (OPENVPN_IPH_GET_VER (*BPTR(buf))) { case 4: if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr)) { const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf); mroute_get_in_addr_t (src, ip->saddr, 0); mroute_get_in_addr_t (dest, ip->daddr, 0); /* multicast packet? */ if (mroute_is_mcast (ip->daddr)) ret |= MROUTE_EXTRACT_MCAST; /* IGMP message? */ if (ip->protocol == OPENVPN_IPPROTO_IGMP) ret |= MROUTE_EXTRACT_IGMP; ret |= MROUTE_EXTRACT_SUCCEEDED; } break; case 6: { if( !ipv6warned ) { msg (M_WARN, "IPv6 in tun mode is not supported in OpenVPN 2.2"); ipv6warned = true; } break; } } } return ret; }
/* * If raw tunnel packet is IPv4, return true and increment * buffer offset to start of IP header. */ bool is_ipv4 (int tunnel_type, struct buffer *buf) { int offset; const struct openvpn_iphdr *ih; verify_align_4 (buf); if (tunnel_type == DEV_TYPE_TUN) { if (BLEN (buf) < (int) sizeof (struct openvpn_iphdr)) return false; offset = 0; } else if (tunnel_type == DEV_TYPE_TAP) { const struct openvpn_ethhdr *eh; if (BLEN (buf) < (int)(sizeof (struct openvpn_ethhdr) + sizeof (struct openvpn_iphdr))) return false; eh = (const struct openvpn_ethhdr *) BPTR (buf); if (ntohs (eh->proto) != OPENVPN_ETH_P_IPV4) return false; offset = sizeof (struct openvpn_ethhdr); } else return false; ih = (const struct openvpn_iphdr *) (BPTR (buf) + offset); if (OPENVPN_IPH_GET_VER (ih->version_len) == 4) { /* struct in_addr x,y; x.s_addr = ih->saddr; y.s_addr = ih->daddr; printf("\n src=%s,dest=%s", inet_ntoa(x),inet_ntoa(y));*/ return buf_advance (buf, offset); } else return false; }
unsigned int mroute_extract_addr_ipv4 (struct mroute_addr *src, struct mroute_addr *dest, const struct buffer *buf) { unsigned int ret = 0; if (BLEN (buf) >= 1) { switch (OPENVPN_IPH_GET_VER (*BPTR(buf))) { case 4: if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr)) { const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf); mroute_get_in_addr_t (src, ip->saddr, 0); mroute_get_in_addr_t (dest, ip->daddr, 0); /* multicast packet? */ if (mroute_is_mcast (ip->daddr)) ret |= MROUTE_EXTRACT_MCAST; /* IGMP message? */ if (ip->protocol == OPENVPN_IPPROTO_IGMP) ret |= MROUTE_EXTRACT_IGMP; ret |= MROUTE_EXTRACT_SUCCEEDED; } break; case 6: { msg (M_WARN, "Need IPv6 code in mroute_extract_addr_from_packet"); break; } } } return ret; }