ipsec_io.c
来自「ipsec PNE 3.3 source code, running at mo」· C语言 代码 · 共 1,851 行 · 第 1/5 页
C
1,851 行
** NOMANUAL* * RETURNS: TRUE if network interface is found, FALSE otherwise*/BOOL ipsec_get_attached_network_interface ( TRAFFIC_DIRECTION direction, struct mbuf *p_memory_buffer, struct ip *sptr_ip_header, IPSEC_NETWORK_INTERFACE ** pp_ipsec_network_interface ) { WRSEC_INET4_ADDR v4source; #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) WRSEC_INET6_ADDR v6source; #endif /* #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) */ WRSEC_INET_ADDR *p_source = NULL; WRSEC_INET_FAMILY family; struct ifnet *sptr_ifnet = NULL; IPSEC_NETWORK_INTERFACE *p_network_interface; BOOL found; found = FALSE; sptr_ifnet = p_memory_buffer->m_pkthdr.rcvif; if (sptr_ifnet == NULL) { if (((struct ip *)sptr_ip_header)->ip_v == IP_V4) { if (direction == INBOUND) { v4source.family.type = WRSEC_AF_INET4; WRSEC_INET4_SET_STRUCT_A_WITH_IN_ADDR_B (v4source, sptr_ip_header->ip_dst); } else { v4source.family.type = WRSEC_AF_INET4; WRSEC_INET4_SET_STRUCT_A_WITH_IN_ADDR_B (v4source, sptr_ip_header->ip_src); } p_source = (WRSEC_INET_ADDR *)&v4source; } #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) else if (((struct ip *)sptr_ip_header)->ip_v == IP_V6) { if (direction == INBOUND) { v6source.family.type = WRSEC_AF_INET6; WRSEC_INET6_SET_STRUCT_A_WITH_IN6_ADDR_B (v6source, ((struct ip6_hdr *)sptr_ip_header)->ip6_dst); } else { v6source.family.type = WRSEC_AF_INET6; WRSEC_INET6_SET_STRUCT_A_WITH_IN6_ADDR_B (v6source, ((struct ip6_hdr *)sptr_ip_header)->ip6_src); } p_source = (WRSEC_INET_ADDR *)&v6source; } #endif /* STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) */ else /* unknown IP version field */ { return FALSE; } p_network_interface = ipsec_find_network_interface_based_on_ip_address (p_source); if (p_network_interface != NULL) { *pp_ipsec_network_interface = p_network_interface; found = TRUE; } } else { if (((struct ip *)sptr_ip_header)->ip_v == 4) family = WRSEC_AF_INET4; else if (((struct ip *)sptr_ip_header)->ip_v == 6) family = WRSEC_AF_INET6; else return FALSE; p_network_interface = ipsecFindNetworkInterfaceBasedOnIfnet (sptr_ifnet, family); if (p_network_interface != NULL) { *pp_ipsec_network_interface = p_network_interface; found = TRUE; } } return (found); }/******************************************************************************** ipsecFindNetworkInterfaceBasedOnIfnet * Searches for a network interface with a matching IFNETHANDLE.* * * RETURNS: pointer to IPSEC_NETWORK_INTERFACE on success or NULL on failure** NOMANUAL*/IPSEC_NETWORK_INTERFACE *ipsecFindNetworkInterfaceBasedOnIfnet ( struct ifnet *sptr_ifnet, WRSEC_INET_FAMILY family ) { void *iterator = (void *)NULL; IPSEC_NETWORK_INTERFACE *p_ipsec_network_interface = NULL; IPSEC_NETWORK_INTERFACE *p_target_network_interface = NULL; wrSecListScanLock( ipsec_global_class.ipsec_network_interface_list ); while ((p_ipsec_network_interface = wrSecListScan(ipsec_global_class.ipsec_network_interface_list, &iterator)) != NULL) { if (p_ipsec_network_interface->sptr_ifnet == sptr_ifnet) { if (p_ipsec_network_interface->p_address->type == WRSEC_AF_INET4 && family == WRSEC_AF_INET4) { struct in_ifaddr *sptr_ia; #if STACK_NAME == STACK_NAME_V4_V6 for (sptr_ia = _in_ifaddrhead.tqh_first; sptr_ia != NULL; sptr_ia = sptr_ia->ia_link.tqe_next) #else #ifdef VIRTUAL_STACK for (sptr_ia = _in_ifaddr; sptr_ia != NULL; sptr_ia = sptr_ia->ia_next) #else for (sptr_ia = in_ifaddr; sptr_ia != NULL; sptr_ia = sptr_ia->ia_next) #endif #endif /* STACK_NAME == STACK_NAME_V4_V6 */ { if (sptr_ia->ia_ifp != sptr_ifnet) { continue; } if (sptr_ia->ia_addr.sin_addr.s_addr == ((WRSEC_INET4_ADDR *) ( p_ipsec_network_interface->p_address))->data._ula1[0]) { p_target_network_interface = p_ipsec_network_interface; break; } } }#if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) else if (p_ipsec_network_interface->p_address->type == WRSEC_AF_INET6 && family == WRSEC_AF_INET6) { struct ifaddr *ifa; struct sockaddr_in6 *sockaddr6; struct ifnet *ifp = sptr_ifnet; UCHAR *a, *b; UCHAR len_to_compare; for (ifa = ifp->if_addrlist.tqh_first; ifa; ifa = ifa->ifa_list.tqe_next) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; sockaddr6 = (struct sockaddr_in6 *)ifa->ifa_addr; a = (UCHAR *)&sockaddr6->sin6_addr; b = (UCHAR *)& ((WRSEC_INET6_ADDR *) (p_ipsec_network_interface->p_address))->data; len_to_compare = WRSEC_INET6_ADDR_LENGTH_IN_BYTES; if (*a == 0xfe && *(a + 1) == 0x80 && *b == 0xfe && *(b + 1) == 0x80) { a += 4; b += 4; len_to_compare -= 4; } if (memcmp (a, b, len_to_compare) == 0) { p_target_network_interface = p_ipsec_network_interface; break; } } } #endif /* #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) */ } } wrSecListScanUnlock( ipsec_global_class.ipsec_network_interface_list ); return (p_target_network_interface); }#if defined (__IPSEC_QUEUING__)/******************************************************************************** ipsecEnqueue - queues packets to be processed by ipsec task* * This function creates an IP queue message and sends it to IPSEC task as soon* as it receives a packet from IP. ** NOMANUAL* * RETURNS: QUEUED, NOT_QUEUED if message could not be queued.*/LOCAL int ipsecEnqueue ( TRAFFIC_DIRECTION direction, struct mbuf *p_memory_buffer, SA_BUNDLE *p_sa_bundle, struct ip *p_ip_header, int header_length, int flags ) { IPSEC_QUEUE_MSG ipsec_queue_msg; IPSEC_QUEUE_MSG *p_ipsec_queue_msg = &ipsec_queue_msg; p_ipsec_queue_msg->direction = direction; p_ipsec_queue_msg->p_memory_buffer = p_memory_buffer; p_ipsec_queue_msg->p_sa_bundle = p_sa_bundle; p_ipsec_queue_msg->flags = flags; p_ipsec_queue_msg->header_length = header_length; p_ipsec_queue_msg->p_ip_header = p_ip_header; /* Post the message to the IPsec queue*/ if (msgQSend (ipsec_global_class.ipsecMsgQ, (char *)p_ipsec_queue_msg, sizeof (IPSEC_QUEUE_MSG), WAIT_FOREVER, MSG_PRI_NORMAL) == ERROR) { ipsec_printf (IPSEC_ERROR_PRINTF, "IPSec: Failed msgQSend !\n"); return (NOT_QUEUED); } return (QUEUED); }#endif /*__IPSEC_QUEUING__*//******************************************************************************** ipsecApplyPolicy - Apply ipsec policy on packets* * This routine applies the applicable security policy to a packet.** If an SA bundle does not exist for the packet, the packet is discarded. In * the case where we have a outbound packet with an APPLY policy, an attempt* is made to create an SA bundle.* If an SA bundle exists, the associated security policy is applied to the * packet. This typically means performing IPsec operations on the packet* including encryption/decryption.** NOMANUAL* * RETURNS: OK if the packet is BYPASSed, * ERROR if the packet is DISCARDed or ipsec processing on packet fails,* EMSGSIZE if packet size > mtu;* TUNNELED if the packet was tunneled.* QUEUED if the packet was queued.*/LOCAL int ipsecApplyPolicy ( TRAFFIC_DIRECTION direction, VI_NETWORK_TRAFFIC_INFO *p_traffic_info, SECURITY_POLICY *sptr_policy, SA_BUNDLE *pSABundle, NET_IF *net_interface, struct mbuf ** pp_memory_buffer, struct ip ** pp_ip_header, int header_length, int flags ) { int return_value = OK; WRSEC_INET_FAMILY wrn_inet_family = p_traffic_info->type; SPD_PROCESSING_INDICATOR security_check = sptr_policy ? sptr_policy->processing_indicator:NOT_VALID; IP_VI_MESSAGE *p_ip_message; BOOL tunnel_packet;#if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) if ((wrn_inet_family == WRSEC_PF_INET6) && ipsecIsIcmp6Message (*pp_memory_buffer)) return (OK);#endif /* STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) */ if (direction == INBOUND) { STATUS ret; TRANSPORT_PROTOCOL protocol = TRAFFIC_INFO_PROTOCOL_GET(p_traffic_info);; if (protocol == TRANSPORT_PROTO_ESP || protocol == TRANSPORT_PROTO_AH) { } else if (ipsecIsIcmpPmtuMessage (*pp_memory_buffer, *pp_ip_header) == TRUE) { #ifdef IPSEC_PMTU return_value = ipsecIcmpPmtuMessageProcess (pp_memory_buffer, *pp_ip_header); #endif return (return_value); } else { ret = ipsecInProcessPlainTextPacket(sptr_policy, pp_memory_buffer, pp_ip_header, header_length, p_traffic_info); if (ret != OK) return (ret); } } else return_value = ERROR; /* ** --- If we have an SA bundle */ if ( pSABundle ) { security_check = pSABundle->security_processing_indicator; if (security_check == APPLY) { if (flags & IP_FORWARDING) { struct mbuf *m = *pp_memory_buffer; struct ip *iphdr = *pp_ip_header; struct ifnet *ifp = m->m_pkthdr.rcvif; IPSEC_NETWORK_INTERFACE *p_ipsec_network_interface; UINT path_mtu; if (m->m_pkthdr.len + ipsecSizing (m, ifp) > ifp->if_mtu) { /* This packet possibly will exceed the interface MTU * after applying IPSEC. We need to send a PMTU message * to sender. */ path_mtu = ifp->if_mtu - ipsecSizing (m, ifp); if (wrn_inet_family == WRSEC_PF_INET4) { if (!ipsec_get_attached_network_interface (OUTBOUND, m, iphdr, &p_ipsec_network_interface)) { return (ERROR); } if ((p_ipsec_network_interface->df_bit == SET) || ((p_ipsec_network_interface->df_bit == COPY) && (iphdr->ip_off & IP_DF))) { pSABundle->pmtu_age = ipsecPmtuAgeGet (pSABundle->p_reflected_address); pSABundle->pmtu = path_mtu; } } #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) if (wrn_inet_family == WRSEC_PF_INET6) { if (path_mtu < IPV6_MMTU) { path_mtu = IPV6_MMTU; } pSABundle->pmtu_age = ipsecPmtuAgeGet (pSABundle->p_reflected_address); pSABundle->pmtu = path_mtu; } #endif /* STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) */ } }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?