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 + -
显示快捷键?