00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00056 #include "ipsec/debug.h"
00057
00058 #include "ipsec/ipsec.h"
00059 #include "ipsec/util.h"
00060 #include "ipsec/sa.h"
00061 #include "ipsec/ah.h"
00062 #include "ipsec/esp.h"
00063
00064
00065
00081 int ipsec_input(unsigned char *packet, int packet_size,
00082 int *payload_offset, int *payload_size,
00083 db_set_netif *databases)
00084 {
00085 int ret_val = IPSEC_STATUS_NOT_INITIALIZED;
00086 int dummy = packet_size;
00087 sad_entry *sa ;
00088 spd_entry *spd ;
00089 ipsec_ip_header *ip ;
00090 ipsec_ip_header *inner_ip ;
00091 __u32 spi ;
00092
00093 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER,
00094 "ipsec_input",
00095 ("*packet=%p, packet_size=%d, len=%u, *payload_offset=%d, *payload_size=%d databases=%p",
00096 (void *)packet, packet_size, (int)*payload_offset, (int)*payload_size, (void *)databases)
00097 );
00098
00099 IPSEC_DUMP_BUFFER(" INBOUND ESP or AH:", packet, 0, packet_size);
00100
00101 ip = (ipsec_ip_header*)packet ;
00102 spi = ipsec_sad_get_spi(ip) ;
00103 sa = ipsec_sad_lookup(ip->dest, ip->protocol, spi, &databases->inbound_sad) ;
00104
00105 if(sa == NULL)
00106 {
00107 IPSEC_LOG_AUD("ipsec_input", IPSEC_AUDIT_FAILURE, ("no matching SA found")) ;
00108 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_input", ("return = %d", IPSEC_STATUS_FAILURE) );
00109 return IPSEC_STATUS_FAILURE;
00110 }
00111
00112 if(sa->mode != IPSEC_TUNNEL)
00113 {
00114 IPSEC_LOG_ERR("ipsec_input", IPSEC_STATUS_FAILURE, ("unsupported transmission mode (only IPSEC_TUNNEL is supported)") );
00115 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_input", ("return = %d", IPSEC_STATUS_FAILURE) );
00116 return IPSEC_STATUS_FAILURE;
00117 }
00118
00119 if(sa->protocol == IPSEC_PROTO_AH)
00120 {
00121 ret_val = ipsec_ah_check((ipsec_ip_header *)packet, payload_offset, payload_size, sa);
00122 if(ret_val != IPSEC_STATUS_SUCCESS)
00123 {
00124 IPSEC_LOG_ERR("ipsec_input", ret_val, ("ah_packet_check() failed") );
00125 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_input", ("ret_val=%d", ret_val) );
00126 return ret_val;
00127 }
00128
00129 } else if (sa->protocol == IPSEC_PROTO_ESP)
00130 {
00131 ret_val = ipsec_esp_decapsulate((ipsec_ip_header *)packet, payload_offset, payload_size, sa);
00132 if(ret_val != IPSEC_STATUS_SUCCESS)
00133 {
00134 IPSEC_LOG_ERR("ipsec_input", ret_val, ("ipsec_esp_decapsulate() failed") );
00135 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_input", ("ret_val=%d", ret_val) );
00136 return ret_val;
00137 }
00138
00139 } else
00140 {
00141 IPSEC_LOG_ERR("ipsec_input", IPSEC_STATUS_FAILURE, ("invalid protocol from SA") );
00142 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_input", ("ret_val=%d", IPSEC_STATUS_FAILURE) );
00143 return IPSEC_STATUS_FAILURE;
00144 }
00145
00146 inner_ip = (ipsec_ip_header *)(((unsigned char *)ip) + *payload_offset) ;
00147
00148 spd = ipsec_spd_lookup(inner_ip, &databases->inbound_spd) ;
00149 if(spd == NULL)
00150 {
00151 IPSEC_LOG_AUD("ipsec_input", IPSEC_AUDIT_FAILURE, ("no matching SPD found")) ;
00152 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_input", ("ret_val=%d", IPSEC_STATUS_FAILURE) );
00153 return IPSEC_STATUS_FAILURE;
00154 }
00155
00156 if(spd->policy == POLICY_APPLY)
00157 {
00158 if(spd->sa != sa)
00159 {
00160 IPSEC_LOG_AUD("ipsec_input", IPSEC_AUDIT_SPI_MISMATCH, ("SPI mismatch") );
00161 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_input", ("return = %d", IPSEC_AUDIT_SPI_MISMATCH) );
00162 return IPSEC_STATUS_FAILURE;
00163 }
00164 }
00165 else
00166 {
00167 IPSEC_LOG_AUD("ipsec_input", IPSEC_AUDIT_POLICY_MISMATCH, ("matching SPD does not permit IPsec processing") );
00168 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_input", ("return = %d", IPSEC_STATUS_FAILURE) );
00169 return IPSEC_STATUS_FAILURE;
00170 }
00171
00172 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_input", ("return = %d", IPSEC_STATUS_SUCCESS) );
00173 return IPSEC_STATUS_SUCCESS;
00174 }
00175
00176
00193 int ipsec_output(unsigned char *packet, int packet_size, int *payload_offset, int *payload_size,
00194 __u32 src, __u32 dst, spd_entry *spd)
00195 {
00196 int ret_val = IPSEC_STATUS_NOT_INITIALIZED;
00197 ipsec_ip_header *ip ;
00198
00199 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER,
00200 "ipsec_output",
00201 ("*packet=%p, packet_size=%d, len=%u, *payload_offset=%d, *payload_size=%d src=%lx dst=%lx *spd=%p",
00202 (void *)packet, packet_size, *payload_offset, *payload_size, (__u32) src, (__u32) dst, (void *)spd)
00203 );
00204
00205 ip = (ipsec_ip_header*)packet;
00206
00207 if((ip == NULL) || (ipsec_ntohs(ip->len) > packet_size))
00208 {
00209 IPSEC_LOG_DBG("ipsec_output", IPSEC_STATUS_NOT_IMPLEMENTED, ("bad packet ip=%p, ip->len=%d (must not be >%d bytes)", (void *)ip, ipsec_ntohs(ip->len), packet_size) );
00210
00211 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_output", ("return = %d", IPSEC_STATUS_BAD_PACKET) );
00212 return IPSEC_STATUS_BAD_PACKET;
00213 }
00214
00215 if((spd == NULL) || (spd->sa == NULL))
00216 {
00218 IPSEC_LOG_DBG("ipsec_output", IPSEC_STATUS_NOT_IMPLEMENTED, ("unable to generate dynamically an SA (IKE not implemented)") );
00219
00220 IPSEC_LOG_AUD("ipsec_output", IPSEC_STATUS_NO_SA_FOUND, ("no SA or SPD defined")) ;
00221 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_output", ("return = %d", IPSEC_STATUS_NO_SA_FOUND) );
00222 return IPSEC_STATUS_NO_SA_FOUND;
00223 }
00224
00225 switch(spd->sa->protocol) {
00226 case IPSEC_PROTO_AH:
00227 IPSEC_LOG_MSG("ipsec_output", ("have to encapsulate an AH packet")) ;
00228 ret_val = ipsec_ah_encapsulate((ipsec_ip_header *)packet, payload_offset, payload_size, spd->sa, src, dst);
00229
00230 if(ret_val != IPSEC_STATUS_SUCCESS)
00231 {
00232 IPSEC_LOG_ERR("ipsec_output", ret_val, ("ipsec_ah_encapsulate() failed"));
00233 }
00234 break;
00235
00236 case IPSEC_PROTO_ESP:
00237 IPSEC_LOG_MSG("ipsec_output", ("have to encapsulate an ESP packet")) ;
00238 ret_val = ipsec_esp_encapsulate((ipsec_ip_header *)packet, payload_offset, payload_size, spd->sa, src, dst);
00239
00240 if(ret_val != IPSEC_STATUS_SUCCESS)
00241 {
00242 IPSEC_LOG_ERR("ipsec_output", ret_val, ("ipsec_esp_encapsulate() failed"));
00243 }
00244 break;
00245
00246 default:
00247 ret_val = IPSEC_STATUS_BAD_PROTOCOL;
00248 IPSEC_LOG_ERR("ipsec_output", ret_val, ("unsupported protocol '%d' in spd->sa->protocol", spd->sa->protocol));
00249 }
00250
00251 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_output", ("ret_val=%d", ret_val) );
00252 return ret_val;
00253 }
00254
00255