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 <net/ipv6.h> 18 #include <net/addrconf.h> 19 20 static struct xfrm_state_afinfo xfrm6_state_afinfo; 21 22 static void 23 __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, 24 struct xfrm_tmpl *tmpl, 25 xfrm_address_t *daddr, xfrm_address_t *saddr) 26 { 27 /* Initialize temporary selector matching only 28 * to current session. */ 29 ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst); 30 ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src); 31 x->sel.dport = xfrm_flowi_dport(fl); 32 x->sel.dport_mask = htons(0xffff); 33 x->sel.sport = xfrm_flowi_sport(fl); 34 x->sel.sport_mask = htons(0xffff); 35 x->sel.prefixlen_d = 128; 36 x->sel.prefixlen_s = 128; 37 x->sel.proto = fl->proto; 38 x->sel.ifindex = fl->oif; 39 x->id = tmpl->id; 40 if (ipv6_addr_any((struct in6_addr*)&x->id.daddr)) 41 memcpy(&x->id.daddr, daddr, sizeof(x->sel.daddr)); 42 memcpy(&x->props.saddr, &tmpl->saddr, sizeof(x->props.saddr)); 43 if (ipv6_addr_any((struct in6_addr*)&x->props.saddr)) 44 memcpy(&x->props.saddr, saddr, sizeof(x->props.saddr)); 45 x->props.mode = tmpl->mode; 46 x->props.reqid = tmpl->reqid; 47 x->props.family = AF_INET6; 48 } 49 50 static int 51 __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) 52 { 53 int i; 54 int j = 0; 55 56 /* Rule 1: select IPsec transport except AH */ 57 for (i = 0; i < n; i++) { 58 if (src[i]->props.mode == XFRM_MODE_TRANSPORT && 59 src[i]->id.proto != IPPROTO_AH) { 60 dst[j++] = src[i]; 61 src[i] = NULL; 62 } 63 } 64 if (j == n) 65 goto end; 66 67 /* Rule 2: select MIPv6 RO or inbound trigger */ 68 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 69 for (i = 0; i < n; i++) { 70 if (src[i] && 71 (src[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION || 72 src[i]->props.mode == XFRM_MODE_IN_TRIGGER)) { 73 dst[j++] = src[i]; 74 src[i] = NULL; 75 } 76 } 77 if (j == n) 78 goto end; 79 #endif 80 81 /* Rule 3: select IPsec transport AH */ 82 for (i = 0; i < n; i++) { 83 if (src[i] && 84 src[i]->props.mode == XFRM_MODE_TRANSPORT && 85 src[i]->id.proto == IPPROTO_AH) { 86 dst[j++] = src[i]; 87 src[i] = NULL; 88 } 89 } 90 if (j == n) 91 goto end; 92 93 /* Rule 4: select IPsec tunnel */ 94 for (i = 0; i < n; i++) { 95 if (src[i] && 96 src[i]->props.mode == XFRM_MODE_TUNNEL) { 97 dst[j++] = src[i]; 98 src[i] = NULL; 99 } 100 } 101 if (likely(j == n)) 102 goto end; 103 104 /* Final rule */ 105 for (i = 0; i < n; i++) { 106 if (src[i]) { 107 dst[j++] = src[i]; 108 src[i] = NULL; 109 } 110 } 111 112 end: 113 return 0; 114 } 115 116 static int 117 __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) 118 { 119 int i; 120 int j = 0; 121 122 /* Rule 1: select IPsec transport */ 123 for (i = 0; i < n; i++) { 124 if (src[i]->mode == XFRM_MODE_TRANSPORT) { 125 dst[j++] = src[i]; 126 src[i] = NULL; 127 } 128 } 129 if (j == n) 130 goto end; 131 132 /* Rule 2: select MIPv6 RO or inbound trigger */ 133 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) 134 for (i = 0; i < n; i++) { 135 if (src[i] && 136 (src[i]->mode == XFRM_MODE_ROUTEOPTIMIZATION || 137 src[i]->mode == XFRM_MODE_IN_TRIGGER)) { 138 dst[j++] = src[i]; 139 src[i] = NULL; 140 } 141 } 142 if (j == n) 143 goto end; 144 #endif 145 146 /* Rule 3: select IPsec tunnel */ 147 for (i = 0; i < n; i++) { 148 if (src[i] && 149 src[i]->mode == XFRM_MODE_TUNNEL) { 150 dst[j++] = src[i]; 151 src[i] = NULL; 152 } 153 } 154 if (likely(j == n)) 155 goto end; 156 157 /* Final rule */ 158 for (i = 0; i < n; i++) { 159 if (src[i]) { 160 dst[j++] = src[i]; 161 src[i] = NULL; 162 } 163 } 164 165 end: 166 return 0; 167 } 168 169 static struct xfrm_state_afinfo xfrm6_state_afinfo = { 170 .family = AF_INET6, 171 .init_tempsel = __xfrm6_init_tempsel, 172 .tmpl_sort = __xfrm6_tmpl_sort, 173 .state_sort = __xfrm6_state_sort, 174 .output = xfrm6_output, 175 }; 176 177 void __init xfrm6_state_init(void) 178 { 179 xfrm_state_register_afinfo(&xfrm6_state_afinfo); 180 } 181 182 void xfrm6_state_fini(void) 183 { 184 xfrm_state_unregister_afinfo(&xfrm6_state_afinfo); 185 } 186 187