📄 kernel.c
字号:
if (ugh != NULL) break; /* his client */ context = "destination subnet field malformed: "; ugh = ttosubnet(ff[2].ptr, ff[2].len, AF_INET, &eri.his); if (ugh != NULL) break; /* SAID */ context = "SA ID field malformed: "; ugh = read_proto(ff[4].ptr, &ff[4].len, &eri.transport_proto); if (ugh != NULL) break; ugh = ttosa(ff[4].ptr, ff[4].len, &eri.said); } while (FALSE); if (ugh != NULL) { openswan_log("INTERNAL ERROR: %s line %d %s%s" , procname, lino, context, ugh); continue; /* ignore rest of line */ } /* Now we have decoded eroute, let's consider it. * For shunt eroutes: * * %hold: if not known, add to orphaned_holds list for initiation * because ACQUIRE might have been lost. * * %pass, %drop, %reject: determine if idle; if so, blast it away. * Can occur bare (if DNS provided insufficient information) * or with a connection (failure context). * Could even be installed by ipsec manual. * * %trap: always welcome. * * For other eroutes: find state and record count change */ if (eri.said.proto == SA_INT) { /* shunt eroute */ switch (ntohl(eri.said.spi)) { case SPI_HOLD: if (bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto) == NULL && shunt_owner(&eri.ours, &eri.his) == NULL) { int ourport = ntohs(portof(&eri.ours.addr)); int hisport = ntohs(portof(&eri.his.addr)); char ourst[SUBNETTOT_BUF]; char hist[SUBNETTOT_BUF]; char sat[SATOT_BUF]; subnettot(&eri.ours, 0, ourst, sizeof(ourst)); subnettot(&eri.his, 0, hist, sizeof(hist)); satot(&eri.said, 0, sat, sizeof(sat)); DBG(DBG_CONTROL, DBG_log("add orphaned shunt %s:%d -> %s:%d => %s:%d" , ourst, ourport, hist, hisport, sat, eri.transport_proto) ) eri.next = orphaned_holds; orphaned_holds = clone_thing(eri, "orphaned %hold"); } break; case SPI_PASS: case SPI_DROP: case SPI_REJECT: /* nothing sensible to do if we don't have counts */ if (ff != field) { struct bare_shunt **bs_pp = bare_shunt_ptr(&eri.ours, &eri.his, eri.transport_proto); if (bs_pp != NULL) { struct bare_shunt *bs = *bs_pp; if (eri.count != bs->count) { bs->count = eri.count; bs->last_activity = nw; } else if (nw - bs->last_activity > SHUNT_PATIENCE) { eri.next = expired; expired = clone_thing(eri, "expired %pass"); } } } break; case SPI_TRAP: break; default: bad_case(ntohl(eri.said.spi)); } } else { /* regular (non-shunt) eroute */ state_eroute_usage(&eri.ours, &eri.his, eri.count, nw); } } /* for each line */ fclose(f); /* Now that we've finished processing the /proc file, * it is safe to delete the expired %pass shunts. */ while (expired != NULL) { struct eroute_info *p = expired; ip_address src, dst; networkof(&p->ours, &src); networkof(&p->his, &dst); (void) replace_bare_shunt(&src, &dst , BOTTOM_PRIO /* not used because we are deleting. This value is a filler */ , SPI_PASS /* not used because we are deleting. This value is a filler */ , FALSE, p->transport_proto, "delete expired bare shunts"); expired = p->next; pfree(p); }}static booldel_spi(ipsec_spi_t spi, int proto, const ip_address *src, const ip_address *dest){ char text_said[SATOT_BUF]; struct kernel_sa sa; set_text_said(text_said, dest, spi, proto); DBG(DBG_KLIPS, DBG_log("delete %s", text_said)); memset(&sa, 0, sizeof(sa)); sa.spi = spi; sa.proto = proto; sa.src = src; sa.dst = dest; sa.text_said = text_said; return kernel_ops->del_sa(&sa);}/* * Setup a pair of SAs. * */static boolsetup_half_ipsec_sa(struct state *st, bool inbound){ /* Build an inbound or outbound SA */ struct connection *c = st->st_connection; ip_subnet src, dst; ip_subnet src_client, dst_client; ipsec_spi_t inner_spi; unsigned int proto, satype; bool replace; /* SPIs, saved for spigrouping or undoing, if necessary */ struct kernel_sa said[EM_MAXRELSPIS], *said_next = said; char text_said[SATOT_BUF]; int encapsulation; replace = inbound && (kernel_ops->get_spi != NULL); src.maskbits = 0; dst.maskbits = 0; if (inbound) { src.addr = c->spd.that.host_addr; dst.addr = c->spd.this.host_addr; src_client = c->spd.that.client; dst_client = c->spd.this.client; } else { src.addr = c->spd.this.host_addr, dst.addr = c->spd.that.host_addr; src_client = c->spd.this.client; dst_client = c->spd.that.client; } encapsulation = ENCAPSULATION_MODE_TRANSPORT; if (st->st_ah.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL || st->st_esp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL || st->st_ipcomp.attrs.encapsulation == ENCAPSULATION_MODE_TUNNEL) { encapsulation = ENCAPSULATION_MODE_TUNNEL; } memset(said, 0, sizeof(said)); /* If we are tunnelling, set up IP in IP pseudo SA */ if (kernel_ops->inbound_eroute) { inner_spi = 256; proto = SA_IPIP; satype = SADB_SATYPE_UNSPEC; } else if (encapsulation == ENCAPSULATION_MODE_TUNNEL) { /* XXX hack alert -- we SHOULD NOT HAVE TO HAVE A DIFFERENT SPI * XXX FOR IP-in-IP ENCAPSULATION! */ ipsec_spi_t ipip_spi; /* Allocate an SPI for the tunnel. * Since our peer will never see this, * and it comes from its own number space, * it is purely a local implementation wart. */ { static ipsec_spi_t last_tunnel_spi = IPSEC_DOI_SPI_OUR_MIN; ipip_spi = htonl(++last_tunnel_spi); if (inbound) st->st_tunnel_in_spi = ipip_spi; else st->st_tunnel_out_spi = ipip_spi; } set_text_said(text_said , &c->spd.that.host_addr, ipip_spi, SA_IPIP); said_next->src = &src.addr; said_next->dst = &dst.addr; said_next->src_client = &src_client; said_next->dst_client = &dst_client; said_next->spi = ipip_spi; said_next->satype = SADB_X_SATYPE_IPIP; said_next->text_said = text_said; if (!kernel_ops->add_sa(said_next, replace)) goto fail; said_next++; inner_spi = ipip_spi; proto = SA_IPIP; satype = SADB_X_SATYPE_IPIP; } /* set up IPCOMP SA, if any */ if (st->st_ipcomp.present) { ipsec_spi_t ipcomp_spi = inbound? st->st_ipcomp.our_spi : st->st_ipcomp.attrs.spi; unsigned compalg; switch (st->st_ipcomp.attrs.transid) { case IPCOMP_DEFLATE: compalg = SADB_X_CALG_DEFLATE; break; default: loglog(RC_LOG_SERIOUS, "IPCOMP transform %s not implemented" , enum_name(&ipcomp_transformid_names, st->st_ipcomp.attrs.transid)); goto fail; } set_text_said(text_said, &dst.addr, ipcomp_spi, SA_COMP); said_next->src = &src.addr; said_next->dst = &dst.addr; said_next->src_client = &src_client; said_next->dst_client = &dst_client; said_next->spi = ipcomp_spi; said_next->satype = SADB_X_SATYPE_COMP; said_next->encalg = compalg; said_next->encapsulation = encapsulation; said_next->reqid = c->spd.reqid + 2; said_next->text_said = text_said; if (!kernel_ops->add_sa(said_next, replace)) goto fail; said_next++; encapsulation = ENCAPSULATION_MODE_TRANSPORT; } /* set up ESP SA, if any */ if (st->st_esp.present) { ipsec_spi_t esp_spi = inbound? st->st_esp.our_spi : st->st_esp.attrs.spi; u_char *esp_dst_keymat = inbound? st->st_esp.our_keymat : st->st_esp.peer_keymat; const struct esp_info *ei; u_int16_t key_len; static const struct esp_info esp_info[] = { { ESP_NULL, AUTH_ALGORITHM_HMAC_MD5, 0, HMAC_MD5_KEY_LEN, SADB_EALG_NULL, SADB_AALG_MD5HMAC }, { ESP_NULL, AUTH_ALGORITHM_HMAC_SHA1, 0, HMAC_SHA1_KEY_LEN, SADB_EALG_NULL, SADB_AALG_SHA1HMAC }, { ESP_DES, AUTH_ALGORITHM_NONE, DES_CBC_BLOCK_SIZE, 0, SADB_EALG_DESCBC, SADB_AALG_NONE }, { ESP_DES, AUTH_ALGORITHM_HMAC_MD5, DES_CBC_BLOCK_SIZE, HMAC_MD5_KEY_LEN, SADB_EALG_DESCBC, SADB_AALG_MD5HMAC }, { ESP_DES, AUTH_ALGORITHM_HMAC_SHA1, DES_CBC_BLOCK_SIZE, HMAC_SHA1_KEY_LEN, SADB_EALG_DESCBC, SADB_AALG_SHA1HMAC }, { ESP_3DES, AUTH_ALGORITHM_NONE, DES_CBC_BLOCK_SIZE * 3, 0, SADB_EALG_3DESCBC, SADB_AALG_NONE }, { ESP_3DES, AUTH_ALGORITHM_HMAC_MD5, DES_CBC_BLOCK_SIZE * 3, HMAC_MD5_KEY_LEN, SADB_EALG_3DESCBC, SADB_AALG_MD5HMAC }, { ESP_3DES, AUTH_ALGORITHM_HMAC_SHA1, DES_CBC_BLOCK_SIZE * 3, HMAC_SHA1_KEY_LEN, SADB_EALG_3DESCBC, SADB_AALG_SHA1HMAC }, { ESP_AES, AUTH_ALGORITHM_NONE, AES_CBC_BLOCK_SIZE, 0, SADB_X_EALG_AESCBC, SADB_AALG_NONE }, { ESP_AES, AUTH_ALGORITHM_HMAC_MD5, AES_CBC_BLOCK_SIZE, HMAC_MD5_KEY_LEN, SADB_X_EALG_AESCBC, SADB_AALG_MD5HMAC }, { ESP_AES, AUTH_ALGORITHM_HMAC_SHA1, AES_CBC_BLOCK_SIZE, HMAC_SHA1_KEY_LEN, SADB_X_EALG_AESCBC, SADB_AALG_SHA1HMAC }, }; //static const int esp_max = elemsof(esp_info); //int esp_count;#ifdef NAT_TRAVERSAL u_int8_t natt_type = 0; u_int16_t natt_sport = 0, natt_dport = 0; ip_address natt_oa; if (st->nat_traversal & NAT_T_DETECTED) { natt_type = (st->nat_traversal & NAT_T_WITH_PORT_FLOATING) ? ESPINUDP_WITH_NON_ESP : ESPINUDP_WITH_NON_IKE; natt_sport = inbound? c->spd.that.host_port : c->spd.this.host_port; natt_dport = inbound? c->spd.this.host_port : c->spd.that.host_port; natt_oa = st->nat_oa; }#endif for (ei = esp_info; ; ei++) { /* if it is the last key entry, then ask algo */ if (ei == &esp_info[elemsof(esp_info)]) { /* Check for additional kernel alg */#ifdef KERNEL_ALG if ((ei=kernel_alg_esp_info(st->st_esp.attrs.transid, st->st_esp.attrs.auth))!=NULL) { break; }#endif /* note: enum_show may use a static buffer, so two * calls in one printf would be a mistake. * enum_name does the same job, without a static buffer, * assuming the name will be found. */ loglog(RC_LOG_SERIOUS, "ESP transform %s / auth %s not implemented yet" , enum_name(&esp_transformid_names, st->st_esp.attrs.transid) , enum_name(&auth_alg_names, st->st_esp.attrs.auth)); goto fail; } if (st->st_esp.attrs.transid == ei->transid && st->st_esp.attrs.auth == ei->auth) break; } if (st->st_esp.attrs.transid != ei->transid && st->st_esp.attrs.auth != ei->auth) { loglog(RC_LOG_SERIOUS, "failed to find key info for %s/%s" , enum_name(&esp_transformid_names, st->st_esp.attrs.transid) , enum_name(&auth_alg_names, st->st_esp.attrs.auth)); goto fail; } key_len = st->st_esp.attrs.key_len/8; if (key_len) { /* XXX: must change to check valid _range_ key_len */ if (key_len > ei->enckeylen) { loglog(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -