Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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)->ihl = sizeof(*iph);
178         XFRM_MODE_SKB_CB(skb)->id = 0;
179         XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF);
180         XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph);
181         XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit;
182         XFRM_MODE_SKB_CB(skb)->optlen = 0;
183         memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl,
184                sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
185 
186         return 0;
187 }
188 
189 static struct xfrm_state_afinfo xfrm6_state_afinfo = {
190         .family                 = AF_INET6,
191         .proto                  = IPPROTO_IPV6,
192         .eth_proto              = htons(ETH_P_IPV6),
193         .owner                  = THIS_MODULE,
194         .init_tempsel           = __xfrm6_init_tempsel,
195         .tmpl_sort              = __xfrm6_tmpl_sort,
196         .state_sort             = __xfrm6_state_sort,
197         .output                 = xfrm6_output,
198         .extract_input          = xfrm6_extract_input,
199         .extract_output         = xfrm6_extract_output,
200         .transport_finish       = xfrm6_transport_finish,
201 };
202 
203 int __init xfrm6_state_init(void)
204 {
205         return xfrm_state_register_afinfo(&xfrm6_state_afinfo);
206 }
207 
208 void xfrm6_state_fini(void)
209 {
210         xfrm_state_unregister_afinfo(&xfrm6_state_afinfo);
211 }
212 
213 
  This page was automatically generated by the LXR engine.