diff -urNp openswan-2.6.32-cvs-patched/programs/pluto/ikev2_child.c openswan-2.6.32-current/programs/pluto/ikev2_child.c --- openswan-2.6.32-cvs-patched/programs/pluto/ikev2_child.c 2011-03-02 10:22:54.215538106 -0500 +++ openswan-2.6.32-current/programs/pluto/ikev2_child.c 2011-03-17 10:56:41.470114998 -0400 @@ -97,6 +97,23 @@ struct traffic_selector ikev2_subnettots break; } + /* IKEv2 code always sent 0-65535 as port regardless of + * what local policy is. if local policy states a specific + * protocol and port, then send that protocol + * value and port to other end */ + + ts.ipprotoid = e->protocol; + + /*if port is %any or 0*/ + if(e->port == 0 || e->has_port_wildcard) { + ts.startport = 0; + ts.endport = 65535; + } + else { + ts.startport = e->port; + ts.endport = e->port; + } + return ts; } @@ -128,9 +145,16 @@ stf_status ikev2_emit_ts(struct msg_dige its1.isat1_sellen = 40; break; } - its1.isat1_ipprotoid = 0; /* all protocols */ - its1.isat1_startport = 0; /* all ports */ - its1.isat1_endport = 65535; + + + /* IKEv2 code always sent 0-65535 as port regardless of + * what local policy is. if local policy states a specific + * protocol and port, then send that protocol + * value and port to other end */ + + its1.isat1_ipprotoid = ts->ipprotoid; /* protocol as per local policy*/ + its1.isat1_startport = htons(ts->startport); /* ports as per local policy*/ + its1.isat1_endport = htons(ts->endport); if(!out_struct(&its1, &ikev2_ts1_desc, &ts_pbs, &ts_pbs2)) return STF_INTERNAL_ERROR; @@ -268,8 +292,9 @@ ikev2_parse_ts(struct payload_digest *co } array[i].ipprotoid = ts1.isat1_ipprotoid; - array[i].startport = ts1.isat1_startport; - array[i].endport = ts1.isat1_startport; + /*should be converted to host byte order for local processing*/ + array[i].startport = ntohs(ts1.isat1_startport); + array[i].endport = ntohs(ts1.isat1_endport); } } @@ -354,6 +379,19 @@ static int ikev2_evaluate_connection_fit int fitbits2 = maskbits2 + ts_range2; int fitbits = (fitbits1 << 8) + fitbits2; + /* + * comparing for ports + * for finding better local polcy + */ + + if( ei->port && (tsi[tsi_ni].startport == ei->port && tsi[tsi_ni].endport == ei->port)) { + fitbits = fitbits << 1; + } + + if( er->port && (tsr[tsr_ni].startport == er->port && tsr[tsr_ni].endport == er->port)) { + fitbits = fitbits << 1; + } + DBG(DBG_CONTROLMORE, { DBG_log(" has ts_range1=%u maskbits1=%u ts_range2=%u maskbits2=%u fitbits=%d <> %d" @@ -390,27 +428,6 @@ stf_status ikev2_child_sa_respond(struct unsigned int tsi_n, tsr_n; st1 = duplicate_state(st); - insert_state(st1); - md->st = st1; - md->pst= st; - - /* start of SA out */ - { - struct isakmp_sa r_sa = sa_pd->payload.sa; - notification_t rn; - pb_stream r_sa_pbs; - - r_sa.isasa_np = ISAKMP_NEXT_v2TSi; - if (!out_struct(&r_sa, &ikev2_sa_desc, outpbs, &r_sa_pbs)) - return STF_INTERNAL_ERROR; - - /* SA body in and out */ - rn = ikev2_parse_child_sa_body(&sa_pd->pbs, &sa_pd->payload.v2sa, - &r_sa_pbs, st1, FALSE); - - if (rn != NOTHING_WRONG) - return STF_FAIL + rn; - } /* * now look at provided TSx, and see if these fit the connection @@ -449,7 +466,7 @@ stf_status ikev2_child_sa_respond(struct { hp = find_host_pair(&sra->this.host_addr , sra->this.host_port - , NULL + , &sra->that.host_addr , sra->that.host_port); #ifdef DEBUG @@ -499,12 +516,40 @@ stf_status ikev2_child_sa_respond(struct * the state structure as the tsi/tsr * */ + + /*better connection*/ + c=b; + /* Paul: should we STF_FAIL here instead of checking for NULL */ if (bsr != NULL) { st1->st_ts_this = ikev2_subnettots(&bsr->this); st1->st_ts_that = ikev2_subnettots(&bsr->that); } } + + st1->st_connection = c; + insert_state(st1); + md->st = st1; + md->pst= st; + + /* start of SA out */ + { + struct isakmp_sa r_sa = sa_pd->payload.sa; + notification_t rn; + pb_stream r_sa_pbs; + + r_sa.isasa_np = ISAKMP_NEXT_v2TSi; + if (!out_struct(&r_sa, &ikev2_sa_desc, outpbs, &r_sa_pbs)) + return STF_INTERNAL_ERROR; + + /* SA body in and out */ + rn = ikev2_parse_child_sa_body(&sa_pd->pbs, &sa_pd->payload.v2sa, + &r_sa_pbs, st1, FALSE); + + if (rn != NOTHING_WRONG) + return STF_FAIL + rn; + } + ret = ikev2_calc_emit_ts(md, outpbs, role , c, c->policy); if(ret != STF_OK) return ret; diff -urNp openswan-2.6.32-cvs-patched/programs/pluto/kernel_netlink.c openswan-2.6.32-current/programs/pluto/kernel_netlink.c --- openswan-2.6.32-cvs-patched/programs/pluto/kernel_netlink.c 2011-03-02 10:47:39.480778457 -0500 +++ openswan-2.6.32-current/programs/pluto/kernel_netlink.c 2011-03-17 10:56:49.851084412 -0400 @@ -591,6 +591,32 @@ netlink_raw_eroute(const ip_address *thi req.u.p.sel.sport = portof(&this_client->addr); req.u.p.sel.dport = portof(&that_client->addr); + + /* As per RFC 4301/5996, icmp type is put in the most significant 8 bits + * and icmp code is in the least significant 8 bits of port field. + * Although Openswan does not have any configuration options for + * icmp type/code values, it is possible to specify icmp type and code + * using protoport option. For example, icmp echo request (type 8/code 0) + * needs to be encoded as 0x0800 in the port field and can be specified + * as left/rightprotoport=icmp/2048. Now with NETKEY, icmp type and code + * need to be passed as source and destination ports, respectively. + * therefore, this code extracts upper 8 bits and lower 8 bits and puts + * into source and destination ports before passing to NETKEY. */ + + + if( 1 == transport_proto /*icmp*/ || 58 == transport_proto /*ipv6-icmp*/) { + + u_int16_t icmp_type; + u_int16_t icmp_code; + + icmp_type = ntohs(req.u.p.sel.sport) >> 8; + icmp_code = ntohs(req.u.p.sel.sport) & 0xFF; + + req.u.p.sel.sport = htons(icmp_type); + req.u.p.sel.dport = htons(icmp_code); + + } + req.u.p.sel.sport_mask = (req.u.p.sel.sport) ? ~0:0; req.u.p.sel.dport_mask = (req.u.p.sel.dport) ? ~0:0; ip2xfrm(&this_client->addr, &req.u.p.sel.saddr);