📄 ipsec_icmp_pmtu.c
字号:
bcopy ((const char *)pmtu_message->data, (char *)p_transport, (int)pmtu_message->datalength); icmp_len += pmtu_message->datalength; } m->m_len = icmp_len; m->m_data = (char *)icmp4; icmp4->icmp_type = ICMP_UNREACH; icmp4->icmp_code = ICMP_UNREACH_NEEDFRAG; icmp4->icmp_void = 0; icmp4->icmp_nextmtu = htons (pmtu_message->pmtu); icmp4->icmp_cksum = 0; icmp4->icmp_cksum = in_cksum (m, icmp_len); m->m_data -= MINIMUM_IP_V4_HEADER_LENGTH; m->m_len = icmp_len + MINIMUM_IP_V4_HEADER_LENGTH; m->m_pkthdr.len = m->m_len; m->m_pkthdr.rcvif = (struct ifnet *)p_network_interface->sptr_ifnet; m->m_flags |= M_PKTHDR; s = splnet (); sptr_ifnet = ipsec_get_ifnet_handle (pmtu_message->destination_address); splx (s); if (sptr_ifnet != NULL) { /* pmtu message destined to us,bypass it to upper layers */ ip4->ip_len = icmp_len; #if STACK_NAME == STACK_NAME_V4_V6 icmp_input (m, MINIMUM_IP_V4_HEADER_LENGTH, IPPROTO_ICMP); #else icmp_input (m, MINIMUM_IP_V4_HEADER_LENGTH); #endif /* STACK_NAME == STACK_NAME_V4_V6 */ m_freem (m_source); return (ERROR); } ip4->ip_len = icmp_len + MINIMUM_IP_V4_HEADER_LENGTH; bzero ((char *)&ro, sizeof (struct route)); (void)ip_output (m, NULL, &ro, 0, NULL); m_freem (m_source); } #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) else if (pmtu_message->family == WRSEC_AF_INET6) { struct ip6_hdr *ip6hdr; struct icmp6_hdr *icmp6; struct ifnet *outif; int ip6hdr_len; outif = NULL; /* The pmtu payload should contain the full original ip header plus * 8 bytes of upper layer protocol ( UDP/TCP) */ if (pmtu_message->datalength < (sizeof (struct ip6_hdr) + MIN_TRANSPORT_HDR_LEN)) { /* Store the PMTU Message */ WRN_M_FREEM (m_source); wrSecTrace( TRACE_ALL, L1, "PACKET DROPPED!! 'function::%s'\n", __FUNCTION__); return (ERROR); } mblk_size = ICMP6_MINLEN + pmtu_message->datalength + (MINIMUM_IP_V6_HEADER_LENGTH); MGET1 (m, mblk_size, M_WAIT, m_source->m_type); if (m == NULL) { /* Store the PMTU Message */ WRN_M_FREEM (m_source); wrSecTrace( TRACE_ALL, L1, "PACKET DROPPED!! 'function::%s'\n", __FUNCTION__); return (ERROR); } ip6hdr = mtod (m, struct ip6_hdr *); ip6hdr_len = MINIMUM_IP_V6_HEADER_LENGTH; ip6hdr->ip6_flow = 0x00; ip6hdr->ip6_vfc = IPV6_VERSION; ip6hdr->ip6_hlim = IPV6_DEFHLIM; ip6hdr->ip6_nxt = IPPROTO_ICMPV6; WRSEC_INET6_SET_IN6_ADDR_A_WITH_STRUCT_B(ip6hdr->ip6_dst, (*(WRSEC_INET6_ADDR *)pmtu_message->destination_address)) p_network_interface = ipsecFindNetworkInterfaceBasedOnIfnet (m_source->m_pkthdr.rcvif, WRSEC_AF_INET6); if (p_network_interface == NULL) { return (ERROR); } WRSEC_INET6_SET_IN6_ADDR_A_WITH_STRUCT_B ( ip6hdr->ip6_src, (* ((WRSEC_INET6_ADDR *)p_network_interface->p_address))); icmp_len = ICMP6_MINLEN; if (pmtu_message->data != NULL) { UCHAR *p_transport = (UCHAR *)ip6hdr + MINIMUM_IP_V6_HEADER_LENGTH + ICMP6_MINLEN; bcopy ((const char *)pmtu_message->data, (char *)p_transport, (int)pmtu_message->datalength); icmp_len += pmtu_message->datalength; } icmp6 = (struct icmp6_hdr *) ((UCHAR *)ip6hdr + MINIMUM_IP_V6_HEADER_LENGTH); icmp6->icmp6_type = ICMP6_PACKET_TOO_BIG; icmp6->icmp6_code = 0; icmp6->icmp6_mtu = 0; icmp6->icmp6_mtu = htonl (pmtu_message->pmtu); ip6hdr->ip6_plen = icmp_len; m->m_len = icmp_len + ip6hdr_len; m->m_pkthdr.len = m->m_len; icmp6->icmp6_cksum = 0; icmp6->icmp6_cksum = in6_cksum (m, IPPROTO_ICMPV6, ip6hdr_len, ip6hdr->ip6_plen); m->m_pkthdr.rcvif = (struct ifnet *)p_network_interface->sptr_ifnet; m->m_flags |= M_PKTHDR; s = splnet (); sptr_ifnet = ipsec_get_ifnet_handle (pmtu_message->destination_address); splx (s); if (sptr_ifnet != NULL) { /* pmtu message destined to us,bypass it to upper layers */ icmp6_input (&m, &ip6hdr_len, IPPROTO_ICMPV6); m_freem (m_source); return (ERROR); } ip6_output (m, NULL, NULL, 0, NULL, &outif); m_freem (m_source); } #endif /* STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) */ return (ERROR); }/****************************************************************************** * ipsecPmtuMessageCreate - creates the pmtu message information. * * NOMANUAL * * RETURNS : N/A */LOCAL void ipsecPmtuMessageCreate ( IPSEC_PMTU_MESSAGE *pmtu_message, /* pmtu message */ WRSEC_INET_ADDR_FAMILY type /* family type */ ) { pmtu_message->family = type; pmtu_message->transport = FALSE; pmtu_message->data = NULL; pmtu_message->datalength = 0; pmtu_message->pmtu = 0; pmtu_message->ip_nxt_protocol = 0; pmtu_message->destination_address = wrSecInetAddrCreate(type); }/****************************************************************************** * ipsecPmtuSaInfoCreate - creates the SA information. * * NOMANUAL * * RETURNS : N/A */LOCAL void ipsecPmtuSaInfoCreate ( SA_BUNDLE_INFO *sa_info, /* sa information */ WRSEC_INET_ADDR_FAMILY type /* family type */ ) { sa_info->p_sa_bundle = NULL; sa_info->spi = 0; sa_info->protocol = 0; sa_info->tunnel_endpoint = wrSecInetAddrCreate(type); }/****************************************************************************** * ipsecPmtuMessageDelete - destroys the pmtu message information. * * * NOMANUAL * * RETURNS : N/A */LOCAL void ipsecPmtuMessageDelete ( IPSEC_PMTU_MESSAGE *pmtu_message /* pmtu info */ ) { if (pmtu_message->destination_address != NULL) { wrSecFree (pmtu_message->destination_address); pmtu_message->destination_address = NULL; } if (pmtu_message->data != NULL) { wrSecFree (pmtu_message->data); pmtu_message->data = NULL; } }/****************************************************************************** * ipsecSAInfoDestroy - destroys the SA information. * * NOMANUAL * * RETURNS : N/A */LOCAL void ipsecSAInfoDestroy ( SA_BUNDLE_INFO *sa_info /* sa info */ ) { if (sa_info->tunnel_endpoint != NULL) { wrSecFree (sa_info->tunnel_endpoint); sa_info->tunnel_endpoint = NULL; } }/****************************************************************************** * ipsecPmtuSaBundleFind - finds an outbound sa with the with sa info * provided. * * NOMANUAL * RETURNS : pointer to the SA bundle or NULL. */LOCAL SA_BUNDLE *ipsecPmtuSaBundleFind ( SA_BUNDLE_INFO *sa_info /* info to retrieve sa bundle */ ) { SA_BUNDLE *p_sa_bundle; WRSEC_HASH_TABLE hashtable; p_sa_bundle = NULL; if (sa_info->protocol == TRANSPORT_PROTO_AH) { hashtable = sadb.p_ob_ah_sa_bundles; } else if (sa_info->protocol == TRANSPORT_PROTO_ESP) { hashtable = sadb.p_ob_esp_sa_bundles; } else { return NULL; /* This should not happen */ } p_sa_bundle = sadb_get_sa_from_ob_spi_container (sa_info->spi, hashtable, sa_info->tunnel_endpoint); return (p_sa_bundle); }/****************************************************************************** * ipsecPmtuSendPmtuMessage - sends a pmtu message back to the peer. * * This function sends a pmtu message back to the originator of the packet. * * NOMANUAL * RETUNRS : N/A. */void ipsecPmtuSendPmtuMessage ( struct mbuf *m, /* pmtu packet to be sent */ SA_BUNDLE *p_SAbundle /* bundle contianing PMTU info */ ) { struct ip *ip; IPSEC_PMTU_MESSAGE ipsec_pmtu_message; IPSEC_PMTU_MESSAGE *pmtu_message = &ipsec_pmtu_message; ip = mtod (m, struct ip *); if (((struct ip *)ip)->ip_v == IP_V4) { /* initialize pmtu_mesage */ ipsecPmtuMessageCreate (pmtu_message, WRSEC_AF_INET4); WRSEC_INET4_SET_STRUCT_A_WITH_IN_ADDR_B((*(WRSEC_INET4_ADDR *)pmtu_message->destination_address), ip->ip_src) if (ip->ip_len > IPSEC_PMTU_MESSAGE_LENGTH) { pmtu_message->datalength = IPSEC_PMTU_MESSAGE_LENGTH; } else { pmtu_message->datalength = ip->ip_len; } ip->ip_len = htons(ip->ip_len); /* FIXME: VXWORKS_6_X compile error */ pmtu_message->pmtu = p_SAbundle->pmtu; if (ipsecPmtuDataCopy (pmtu_message, (UCHAR *)ip, pmtu_message->datalength) == ERROR) { ipsec_printf (IPSEC_ERROR_PRINTF, "IPSEC:PMTU:Tunnel:Unable to allocate memory\n"); return; } ipsecPmtuForwardPmtuMessage (m, pmtu_message); ipsecPmtuMessageDelete (pmtu_message); } #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) else if (((struct ip *)ip)->ip_v == IP_V6) { int ip6_hdrlen; struct ip6_hdr *ip6 = mtod (m, struct ip6_hdr *); ipsecPmtuMessageCreate (pmtu_message, WRSEC_AF_INET6); ip6_hdrlen = ipsecIpv6HdrLenGet (m, NULL); WRSEC_INET6_SET_STRUCT_A_WITH_IN6_ADDR_B((*(WRSEC_INET6_ADDR *)pmtu_message->destination_address), ip6->ip6_src) if ((ntohs (ip6->ip6_plen) + ip6_hdrlen) > IPSEC_PMTU_MESSAGE_LENGTH) { pmtu_message->datalength = IPSEC_PMTU_MESSAGE_LENGTH; } else { pmtu_message->datalength = ntohs (ip6->ip6_plen) + ip6_hdrlen; } pmtu_message->pmtu = p_SAbundle->pmtu; if (ipsecPmtuDataCopy (pmtu_message, (UCHAR *)ip6, pmtu_message->datalength) == ERROR) { ipsec_printf (IPSEC_ERROR_PRINTF, "IPSEC:PMTU:Tunnel:Unable to allocate memory\n"); return; } ipsecPmtuForwardPmtuMessage (m, pmtu_message); ipsecPmtuMessageDelete (pmtu_message); } #endif /* STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) */ }/****************************************************************************** * ipsecPmtuIsPacketBiggerThanPmtu - checks if the packet length is * bigger * than the PMTU stored in * the SA. * * This funciton checks if the packet length is bigger than the PMTU stored * in the SA. * * NOMANUAL * RETUNRS : ERROR if the packet is bigger than the pmtu stored in the SA * else OK. */STATUS ipsecPmtuIsPacketBiggerThanPmtu ( struct mbuf *m, /* packet whose length is to be chacked */ SA_BUNDLE *pSABundle /* SA contining PMTU info */ ) { STATUS status; struct ip *ip; UINT packetLength; status = OK; packetLength = 0; ip = mtod (m, struct ip *); if (((struct ip *)ip)->ip_v == IP_V4) { packetLength = ip->ip_len; } #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) else if (((struct ip *)ip)->ip_v == IP_V6) { struct ip6_hdr *ip6 = mtod (m, struct ip6_hdr *); packetLength = (ntohs (ip6->ip6_plen) + sizeof (struct ip6_hdr)); } #endif /* STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) */ if (packetLength >= pSABundle->pmtu) { status = ERROR; } return (status); }/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -