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
00069 #include "lwip/mem.h"
00070
00071 #include "netif/ipsecdev.h"
00072
00073 #include "ipsec/debug.h"
00074 #include "ipsec/ipsec.h"
00075 #include "ipsec/util.h"
00076 #include "ipsec/sa.h"
00077
00078
00079 #define IPSECDEV_NAME0 'i'
00080 #define IPSECDEV_NAME1 's'
00082 extern sad_entry inbound_sad_config[];
00083 extern spd_entry inbound_spd_config[];
00084 extern sad_entry outbound_sad_config[];
00085 extern spd_entry outbound_spd_config[];
00087 extern db_set_netif db_sets[];
00088 db_set_netif *databases;
00089 struct netif mapped_netif;
00090 __u32 tunnel_src_addr;
00091 __u32 tunnel_dst_addr;
00100 void ipsecdev_service(struct netif *netif)
00101 {
00102 struct netif *i ;
00103 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER, "ipsecdev_service", ("netif=%p", (void *)netif) );
00104 i = netif ;
00105 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_service", ("void") );
00106 return ;
00107 }
00108
00109
00123 err_t ipsecdev_input(struct pbuf *p, struct netif *inp)
00124 {
00125 int retcode;
00126 int payload_offset = 0;
00127 int payload_size = 0;
00128 spd_entry *spd ;
00129
00130 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER,
00131 "ipsecdev_input",
00132 ("p=%p, inp=%p",
00133 (void *)p, (void *)inp)
00134 );
00135
00136 IPSEC_DUMP_BUFFER("ipsecdev_input", p->payload, 0, p->len) ;
00137
00138 if(p == NULL || p->payload == NULL)
00139 {
00140 IPSEC_LOG_DBG("ipsecdev_input", IPSEC_STATUS_DATA_SIZE_ERROR, ("Packet has no payload. Can't pass it to higher level protocol stacks."));
00141 pbuf_free(p) ;
00142 }
00143 else
00144 {
00145
00146
00147 if((p->tot_len > IPSEC_MTU) || (ipsec_ntohs(((ipsec_ip_header *)((unsigned char *)p->payload))->len) > IPSEC_MTU))
00148 {
00149 IPSEC_LOG_DBG("ipsecdev_input", IPSEC_STATUS_DATA_SIZE_ERROR, ("Packet to long (%d > %d (IPSEC_MTU))", p->tot_len, IPSEC_MTU) );
00150
00151 pbuf_free(p) ;
00152 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_input", ("return = %d", ERR_OK) );
00153 return ERR_OK;
00154 }
00155
00156 if(p->next != NULL)
00157 {
00158 IPSEC_LOG_DBG("ipsecdev_input", IPSEC_STATUS_DATA_SIZE_ERROR, ("can not handle chained pbuf - (packet must be < %d bytes )", PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - IPSEC_HLEN) );
00159
00160 pbuf_free(p) ;
00161 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_input", ("return = %d", ERR_OK) );
00162 return ERR_OK;
00163 }
00164
00165
00166 if( ((ipsec_ip_header*)(p->payload))->protocol == IPSEC_PROTO_ESP || ((ipsec_ip_header*)(p->payload))->protocol == IPSEC_PROTO_AH)
00167 {
00168
00169 retcode = ipsec_input(p->payload, p->len, (int *)&payload_offset, (int *)&payload_size, databases);
00170
00171 if(retcode == IPSEC_STATUS_SUCCESS)
00172 {
00174
00175 p->payload = (unsigned char *)(p->payload) + payload_offset;
00176 p->len = payload_size;
00177 p->tot_len = payload_size;
00178
00179 IPSEC_LOG_MSG("ipsecdev_input", ("fwd decapsulated IPsec packet to ip_input()") );
00180 retcode = ip_input(p, inp);
00181 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_input", ("retcode = %d", retcode) );
00182 return retcode;
00183
00184 }
00185 else
00186 {
00187 IPSEC_LOG_ERR("ipsecdev_input", retcode, ("error on ipsec_input() processing (retcode = %d)", retcode));
00188 pbuf_free(p) ;
00189 }
00190 }
00191 else
00192 {
00193
00194 spd = ipsec_spd_lookup(p->payload, &databases->inbound_spd) ;
00195 if(spd == NULL)
00196 {
00197 IPSEC_LOG_ERR("ipsecdev_input", IPSEC_STATUS_NO_POLICY_FOUND, ("no matching SPD policy found")) ;
00198 pbuf_free(p) ;
00199 }
00200 else
00201 {
00202 switch(spd->policy)
00203 {
00204 case POLICY_APPLY:
00205 IPSEC_LOG_AUD("ipsecdev_input", IPSEC_AUDIT_APPLY, ("POLICY_APPLY: got non-IPsec packet which should be one")) ;
00206 pbuf_free(p) ;
00207 break;
00208 case POLICY_DISCARD:
00209 IPSEC_LOG_AUD("ipsecdev_input", IPSEC_AUDIT_DISCARD, ("POLICY_DISCARD: dropping packet")) ;
00210 pbuf_free(p) ;
00211 break;
00212 case POLICY_BYPASS:
00213 IPSEC_LOG_AUD("ipsecdev_input", IPSEC_AUDIT_BYPASS, ("POLICY_BYPASS: forwarding packet to ip_input")) ;
00214 ip_input(p, inp);
00215 break;
00216 default:
00217 pbuf_free(p) ;
00218 IPSEC_LOG_ERR("ipsecdev_input", IPSEC_STATUS_FAILURE, ("IPSEC_STATUS_FAILURE: dropping packet")) ;
00219 IPSEC_LOG_AUD("ipsecdev_input", IPSEC_AUDIT_FAILURE, ("unknown Security Policy: dropping packet")) ;
00220 }
00221 }
00222 }
00223 }
00224
00225
00226 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_input", ("retcode = %d", ERR_OK) );
00227 return ERR_OK;
00228 }
00229
00230
00243 err_t ipsecdev_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr)
00244 {
00245 struct pbuf *p_cpy = NULL;
00246 int payload_size ;
00247 int payload_offset ;
00248 spd_entry *spd ;
00249 ipsec_status status ;
00250 struct ip_addr dest_addr;
00251 int retcode;
00252
00253 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER,
00254 "ipsecdev_output",
00255 ("netif=%p, p=%p, ipaddr=%p", (void *)netif, (void *)p, (void *)ipaddr )
00256 );
00257
00258
00259
00260 if((p->tot_len > IPSEC_MTU) || (ipsec_ntohs(((ipsec_ip_header *)((unsigned char *)p->payload))->len) > IPSEC_MTU))
00261 {
00262 IPSEC_LOG_DBG("ipsecdev_output", IPSEC_STATUS_DATA_SIZE_ERROR, ("Packet to long (> IPSEC_MTU) on interface '%c%c'", netif->name[0], netif->name[1]));
00263 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_output", ("return = %d", ERR_CONN) );
00264 return ERR_CONN;
00265 }
00266
00267 if(p->next != NULL)
00268 {
00269 IPSEC_LOG_DBG("ipsecdev_output", IPSEC_STATUS_DATA_SIZE_ERROR, ("can not handle chained pbuf - use pbuf size of %d bytes", IPSEC_MTU));
00270 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_output", ("return = %d", ERR_CONN) );
00271 return ERR_CONN;
00272 }
00273
00274 if(p->ref != 1)
00275 {
00276 IPSEC_LOG_DBG("ipsecdev_output", IPSEC_STATUS_DATA_SIZE_ERROR, ("can not handle pbuf->ref != 1 - p->ref == %d", p->ref));
00277 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_output", ("return = %d", ERR_CONN) );
00278 return ERR_CONN;
00279 }
00280
00281
00283 memcpy(&dest_addr, ipaddr, sizeof(struct ip_addr));
00284
00287
00288 spd = ipsec_spd_lookup((ipsec_ip_header*)p->payload, &databases->outbound_spd) ;
00289 if(spd == NULL)
00290 {
00291 IPSEC_LOG_ERR("ipsecdev_output", IPSEC_STATUS_NO_POLICY_FOUND, ("no matching SPD policy found")) ;
00292
00293 pbuf_free(p);
00294 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_output", ("retcode = %d", ERR_CONN) );
00295 return ERR_CONN ;
00296 }
00297
00298 switch(spd->policy)
00299 {
00300 case POLICY_APPLY:
00301 IPSEC_LOG_AUD("ipsecdev_output", IPSEC_AUDIT_APPLY, ("POLICY_APPLY: processing IPsec packet")) ;
00302
00308 p_cpy = p;
00309 if(spd->sa->protocol == IPSEC_PROTO_ESP)
00310 {
00311
00312 p_cpy = pbuf_alloc(PBUF_RAW, p->len + 50, PBUF_POOL);
00313
00314 if(p_cpy != NULL) {
00315 memcpy(p_cpy->payload, p->payload, p->len);
00316 p_cpy->next = NULL;
00317 p_cpy->len = p->len + 50;
00318 p_cpy->tot_len = p->tot_len + 50;
00319 p_cpy->ref = p->ref;
00320 IPSEC_LOG_MSG("ipsecdev_output", ("lwIP ESP TCP workaround: successfully allocated new pbuf (tot_len = %d)", p_cpy->tot_len) );
00321 }
00322 else {
00323 IPSEC_LOG_ERR("ipsecdev_output", IPSEC_AUDIT_FAILURE, ("can't alloc new pbuf for lwIP ESP TCP workaround!") ) ;
00324 }
00325 }
00326
00327 status = ipsec_output(p_cpy->payload, p_cpy->len, &payload_offset, &payload_size, tunnel_src_addr, tunnel_dst_addr, spd) ;
00328
00329 if(status == IPSEC_STATUS_SUCCESS)
00330 {
00331
00332 p_cpy->payload = (unsigned char *)(p_cpy->payload) + payload_offset;
00333 p_cpy->len = payload_size;
00334 p_cpy->tot_len = payload_size;
00335
00336 IPSEC_LOG_MSG("ipsec_output", ("fwd IPsec packet to HW mapped device") );
00337 retcode = mapped_netif.output(&mapped_netif, p_cpy, (void *)&tunnel_dst_addr);
00338 if(spd->sa->protocol == IPSEC_PROTO_ESP) pbuf_free(p_cpy);
00339 }
00340 else {
00341 IPSEC_LOG_ERR("ipsec_output", status, ("error on ipsec_output() processing"));
00342 if(spd->sa->protocol == IPSEC_PROTO_ESP) pbuf_free(p_cpy);
00343 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_output", ("retcode = %d", ERR_CONN) );
00344 }
00345
00346 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_output", ("retcode = %d", ERR_OK) );
00347 return ERR_OK;
00348 break;
00349 case POLICY_DISCARD:
00350 IPSEC_LOG_AUD("ipsecdev_output", IPSEC_AUDIT_DISCARD, ("POLICY_DISCARD: dropping packet")) ;
00351 break;
00352 case POLICY_BYPASS:
00353 IPSEC_LOG_AUD("ipsecdev_output", IPSEC_AUDIT_BYPASS, ("POLICY_BYPASS: forwarding packet to ip_output")) ;
00354 retcode = mapped_netif.output(&mapped_netif, p, &dest_addr);
00355 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_output", ("retcode = %d", retcode) );
00356 return retcode;
00357 break;
00358 default:
00359 IPSEC_LOG_ERR("ipsecdev_input", IPSEC_STATUS_FAILURE, ("POLICY_DIRCARD: dropping packet")) ;
00360 IPSEC_LOG_AUD("ipsecdev_input", IPSEC_AUDIT_FAILURE, ("unknown Security Policy: dropping packet")) ;
00361 }
00362
00363 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_output", ("return = %d", ERR_CONN) );
00364 return ERR_CONN;
00365 }
00366
00367
00378 err_t ipsecdev_netlink_output(struct netif *netif, struct pbuf *p)
00379 {
00380 int retcode;
00381 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER,
00382 "ipsecdev_netlink_output",
00383 ("netif=%p, p=%d", (void *)netif, (void *)p )
00384 );
00385 IPSEC_LOG_MSG("ipsecdev_netlink_output", ("fwd from interface '%c%c' to real HW linkoutput", netif->name[0], netif->name[1]) );
00386
00387 retcode = mapped_netif.linkoutput(&mapped_netif, p);
00388 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_netlink_output", ("retcode = %d", retcode) );
00389 return retcode;
00390 }
00391
00392
00402 err_t ipsecdev_init(struct netif *netif)
00403 {
00404 struct ipsecdev_stats *ipsecdev_stats;
00405
00406 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER,
00407 "ipsecdev_init",
00408 ("netif=%p", (void *)netif )
00409 );
00410
00411
00412 ipsecdev_stats = mem_malloc(sizeof(struct ipsecdev_stats));
00413 if (ipsecdev_stats == NULL)
00414 {
00415 IPSEC_LOG_DBG("ipsecdev_init", IPSEC_STATUS_DATA_SIZE_ERROR, ("out of memory for ipsecdev_stats"));
00416 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_init", ("retcode = %d", ERR_MEM) );
00417 return ERR_MEM;
00418 }
00419
00420
00421 netif->name[0] = IPSECDEV_NAME0;
00422 netif->name[1] = IPSECDEV_NAME1;
00423
00424
00425 netif->output = (void *)ipsecdev_output;
00426 netif->linkoutput = (void *)ipsecdev_netlink_output;
00427
00429
00430 memset(db_sets, 0, IPSEC_NR_NETIFS*sizeof(db_set_netif)) ;
00431
00432
00434
00435 memcpy(&mapped_netif, netif_list, sizeof(struct netif)) ;
00436 netif_list->output = (void *)ipsecdev_output;
00437
00438
00439 databases = ipsec_spd_load_dbs(inbound_spd_config, outbound_spd_config, inbound_sad_config, outbound_sad_config) ;
00440 if (databases == NULL)
00441 {
00442 IPSEC_LOG_ERR("ipsecdev_init", -1, ("not able to load SPD and SA configuration for ipsec device")) ;
00443 }
00444
00445 ipsecdev_stats->sentbytes = 0;
00446 netif->state = ipsecdev_stats;
00447 netif->mtu = 1500;
00448 netif->flags = NETIF_FLAG_LINK_UP | NETIF_FLAG_BROADCAST;
00449 netif->hwaddr_len = 6;
00450
00452 #ifdef PHYCORE167HSE
00453 netif->hwaddr_len = 6;
00454 netif->hwaddr[0] = 0xA4;
00455 netif->hwaddr[1] = 0xB4;
00456 netif->hwaddr[2] = 0xC4;
00457 netif->hwaddr[3] = 0xD4;
00458 netif->hwaddr[4] = 0xE4;
00459 netif->hwaddr[5] = 0xF4;
00460 #else
00461 netif->hwaddr_len = 6;
00462 netif->hwaddr[0] = 0xA3;
00463 netif->hwaddr[1] = 0xB3;
00464 netif->hwaddr[2] = 0xC3;
00465 netif->hwaddr[3] = 0xD3;
00466 netif->hwaddr[4] = 0xE3;
00467 netif->hwaddr[5] = 0xF3;
00468 #endif
00469
00470 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsecdev_init", ("retcode = %d", IPSEC_STATUS_SUCCESS) );
00471 return IPSEC_STATUS_SUCCESS;
00472 }
00473
00481 void ipsec_set_tunnel(char *src, char *dst)
00482 {
00483 tunnel_src_addr = ipsec_inet_addr(src) ;
00484 tunnel_dst_addr = ipsec_inet_addr(dst) ;
00485 return ;
00486 }