1 /* 2 * xfrm6_state.c: based on xfrm4_state.c 3 * 4 * Authors: 5 * Mitsuru KANDA @USAGI 6 * Kazunori MIYAZAWA @USAGI 7 * Kunihiro Ishiguro <kunihiro@ipinfusion.com> 8 * IPv6 support 9 * YOSHIFUJI Hideaki @USAGI 10 * Split up af-specific portion 11 * 12 */ 13 14 #include <net/xfrm.h> 15 #include <linux/pfkeyv2.h> 16 #include <linux/ipsec.h> 17 #include <linux/netfilter_ipv6.h> 18 #include <net/dsfield.h> 19 #include <net/ipv6.h> 20 #include <net/addrconf.h> 21 22 static struct xfrm_state_afinfo xfrm6_state_afinfo; 23 24 static void 25 __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, 26 struct xfrm_tmpl *tmpl, 27 xfrm_address_t *daddr, xfrm_address_t *saddr) 28 { 29 /* Initialize temporary selector matching only 30 * to current session. */ 31 ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst); 32 ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src); 33 x->sel.dport = xfrm_flowi_dport(fl); 34 x->sel.dport_mask = htons(0xffff); 35 x->sel.sport = xfrm_flowi_sport(fl); 36 x->sel.sport_mask = htons(0xffff); 37 x->sel.prefixlen_d = 128; 38 x->sel.prefixlen_s = 128; 39 x->sel.proto = fl->proto; 40 x->sel.ifindex = fl->oif; 41 x->id = tmpl->id; 42 if (ipv6_addr_any((struct in6_addr*)&x->id.daddr)) 43 memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr)); 44 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); 45 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) 46 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); 47 x->props.mode = tmpl->mode; 48 x->props.reqid = tmpl->reqid; 49 x->props.family = AF_INET6; 50 } 51 52 static int 53 __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) 54 { 55 int i; 56 int j = 0; 57 58 /* Rule 1: select IPsec transport except AH */ 59 for (i = 0; i < n; i++) { 60 if (src[i]->props.mode == XFRM_MODE_TRANSPORT && 61 src[i]->id.proto != IPPROTO_AH) { 62 dst[j++] = src[i]; 63 src[i] = NULL; 64 } 65 } 66 if (j == n) 67 goto end; 68 69 /* Rule 2: select MIPv6 RO or inbound trigger */ 70 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 71 for (i = 0; i < n; i++) { 72 if (src[i] && 73 (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || 74 src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) { 75 dst[j++] = src[i]; 76 src[i] = NULL; 77 } 78 } 79 if (j == n) 80 goto end; 81 #endif 82 83 /* Rule 3: select IPsec transport AH */ 84 for (i = 0; i < n; i++) { 85 if (src[i] && 86 src[i]->props.mode == XFRM_MODE_TRANSPORT && 87 src[i]->id.proto == IPPROTO_AH) { 88 dst[j++] = src[i]; 89 src[i] = NULL; 90 } 91 } 92 if (j == n) 93 goto end; 94 95 /* Rule 4: select IPsec tunnel */ 96 for (i = 0; i < n; i++) { 97 if (src[i] && 98 (src[i]->props.mode == XFRM_MODE_TUNNEL || 99 src[i]->props.mode == XFRM_MODE_BEET)) { 100 dst[j++] = src[i]; 101 src[i] = NULL; 102 } 103 } 104 if (likely(j == n)) 105 goto end; 106 107 /* Final rule */ 108 for (i = 0; i < n; i++) { 109 if (src[i]) { 110 dst[j++] = src[i]; 111 src[i] = NULL; 112 } 113 } 114 115 end: 116 return 0; 117 } 118 119 static int 120 __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) 121 { 122 int i; 123 int j = 0; 124 125 /* Rule 1: select IPsec transport */ 126 for (i = 0; i < n; i++) { 127 if (src[i]->mode == XFRM_MODE_TRANSPORT) { 128 dst[j++] = src[i]; 129 src[i] = NULL; 130 } 131 } 132 if (j == n) 133 goto end; 134 135 /* Rule 2: select MIPv6 RO or inbound trigger */ 136 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 137 for (i = 0; i < n; i++) { 138 if (src[i] && 139 (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || 140 src[i]->mode == XFRM_MODE_IN_TRIGGER)) { 141 dst[j++] = src[i]; 142 src[i] = NULL; 143 } 144 } 145 if (j == n) 146 goto end; 147 #endif 148 149 /* Rule 3: select IPsec tunnel */ 150 for (i = 0; i < n; i++) { 151 if (src[i] && 152 (src[i]->mode == XFRM_MODE_TUNNEL || 153 src[i]->mode == XFRM_MODE_BEET)) { 154 dst[j++] = src[i]; 155 src[i] = NULL; 156 } 157 } 158 if (likely(j == n)) 159 goto end; 160 161 /* Final rule */ 162 for (i = 0; i < n; i++) { 163 if (src[i]) { 164 dst[j++] = src[i]; 165 src[i] = NULL; 166 } 167 } 168 169 end: 170 return 0; 171 } 172 173 int xfrm6_extract_header(struct sk_buff *skb) 174 { 175 struct ipv6hdr *iph = ipv6_hdr(skb); 176 177 XFRM_MODE_SKB_CB(skb)->id = 0; 178 XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF); 179 XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph); 180 XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit; 181 memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl, 182 sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl)); 183 184 return 0; 185 } 186 187 static struct xfrm_state_afinfo xfrm6_state_afinfo = { 188 .family = AF_INET6, 189 .proto = IPPROTO_IPV6, 190 .eth_proto = htons(ETH_P_IPV6), 191 .owner = THIS_MODULE, 192 .init_tempsel = __xfrm6_init_tempsel, 193 .tmpl_sort = __xfrm6_tmpl_sort, 194 .state_sort = __xfrm6_state_sort, 195 .output = xfrm6_output, 196 .extract_input = xfrm6_extract_input, 197 .extract_output = xfrm6_extract_output, 198 .transport_finish = xfrm6_transport_finish, 199 }; 200 201 int __init xfrm6_state_init(void) 202 { 203 return xfrm_state_register_afinfo(&xfrm6_state_afinfo); 204 } 205 206 void xfrm6_state_fini(void) 207 { 208 xfrm_state_unregister_afinfo(&xfrm6_state_afinfo); 209 } 210 211