]> git.ipfire.org Git - thirdparty/strongswan.git/blob - linux/net/ipsec/ipsec_proc.c
5d2bba5544bea507d3989a55271321ae03326066
[thirdparty/strongswan.git] / linux / net / ipsec / ipsec_proc.c
1 /*
2 * @(#) /proc file system interface code.
3 *
4 * Copyright (C) 1996, 1997 John Ioannidis.
5 * Copyright (C) 1998, 1999, 2000, 2001 Richard Guy Briggs <rgb@freeswan.org>
6 * 2001 Michael Richardson <mcr@freeswan.org>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 *
18 * Split out from ipsec_init.c version 1.70.
19 */
20
21 char ipsec_proc_c_version[] = "RCSID $Id: ipsec_proc.c,v 1.8 2004/04/28 08:06:22 as Exp $";
22
23 #include <linux/config.h>
24 #include <linux/version.h>
25 #define __NO_VERSION__
26 #include <linux/module.h>
27 #include <linux/kernel.h> /* printk() */
28
29 #include "freeswan/ipsec_param.h"
30
31 #ifdef MALLOC_SLAB
32 # include <linux/slab.h> /* kmalloc() */
33 #else /* MALLOC_SLAB */
34 # include <linux/malloc.h> /* kmalloc() */
35 #endif /* MALLOC_SLAB */
36 #include <linux/errno.h> /* error codes */
37 #include <linux/types.h> /* size_t */
38 #include <linux/interrupt.h> /* mark_bh */
39
40 #include <linux/netdevice.h> /* struct device, and other headers */
41 #include <linux/etherdevice.h> /* eth_type_trans */
42 #include <linux/ip.h> /* struct iphdr */
43 #include <linux/in.h> /* struct sockaddr_in */
44 #include <linux/skbuff.h>
45 #include <freeswan.h>
46 #ifdef SPINLOCK
47 #ifdef SPINLOCK_23
48 #include <linux/spinlock.h> /* *lock* */
49 #else /* SPINLOCK_23 */
50 #include <asm/spinlock.h> /* *lock* */
51 #endif /* SPINLOCK_23 */
52 #endif /* SPINLOCK */
53 #ifdef NET_21
54 #include <asm/uaccess.h>
55 #include <linux/in6.h>
56 #endif /* NET_21 */
57 #include <asm/checksum.h>
58 #include <net/ip.h>
59 #ifdef CONFIG_PROC_FS
60 #include <linux/proc_fs.h>
61 #endif /* CONFIG_PROC_FS */
62 #ifdef NETLINK_SOCK
63 #include <linux/netlink.h>
64 #else
65 #include <net/netlink.h>
66 #endif
67
68 #include "freeswan/radij.h"
69
70 #include "freeswan/ipsec_life.h"
71 #include "freeswan/ipsec_stats.h"
72 #include "freeswan/ipsec_sa.h"
73
74 #include "freeswan/ipsec_encap.h"
75 #include "freeswan/ipsec_radij.h"
76 #include "freeswan/ipsec_xform.h"
77 #include "freeswan/ipsec_tunnel.h"
78 #include "freeswan/ipsec_xmit.h"
79
80 #include "freeswan/ipsec_rcv.h"
81 #include "freeswan/ipsec_ah.h"
82 #include "freeswan/ipsec_esp.h"
83
84 #ifdef CONFIG_IPSEC_IPCOMP
85 #include "freeswan/ipcomp.h"
86 #endif /* CONFIG_IPSEC_IPCOMP */
87
88 #include "freeswan/ipsec_proto.h"
89
90 #include <pfkeyv2.h>
91 #include <pfkey.h>
92
93 #ifdef CONFIG_PROC_FS
94
95 #ifdef IPSEC_PROC_SUBDIRS
96 static struct proc_dir_entry *proc_net_ipsec_dir = NULL;
97 static struct proc_dir_entry *proc_eroute_dir = NULL;
98 static struct proc_dir_entry *proc_spi_dir = NULL;
99 static struct proc_dir_entry *proc_spigrp_dir = NULL;
100 static struct proc_dir_entry *proc_birth_dir = NULL;
101 static struct proc_dir_entry *proc_stats_dir = NULL;
102 #endif
103
104 struct ipsec_birth_reply ipsec_ipv4_birth_packet;
105 struct ipsec_birth_reply ipsec_ipv6_birth_packet;
106
107 extern int ipsec_xform_get_info(char *buffer, char **start,
108 off_t offset, int length IPSEC_PROC_LAST_ARG);
109
110
111 /* ipsec_snprintf: like snprintf except
112 * - size is signed and a negative value is treated as if it were 0
113 * - the returned result is never negative --
114 * an error generates a "?" or null output (depending on space).
115 * (Our callers are too lazy to check for an error return.)
116 *
117 * @param buf String buffer
118 * @param size Size of the string
119 * @param fmt printf string
120 * @param ... Variables to be displayed in fmt
121 * @return int Return code
122 */
123 int ipsec_snprintf(char *buf, ssize_t size, const char *fmt, ...)
124 {
125 va_list args;
126 int i;
127 size_t possize = size < 0? 0 : size;
128 va_start(args, fmt);
129 i = vsnprintf(buf,possize,fmt,args);
130 va_end(args);
131 if (i < 0) {
132 /* create empty output in place of error */
133 i = 0;
134 if (size > 0) {
135 *buf = '\0';
136 }
137 }
138 return i;
139 }
140
141
142 IPSEC_PROCFS_DEBUG_NO_STATIC
143 int
144 ipsec_eroute_get_info(char *buffer,
145 char **start,
146 off_t offset,
147 int length IPSEC_PROC_LAST_ARG)
148 {
149 struct wsbuf w = {buffer, length, offset, 0, 0};
150
151 #ifdef CONFIG_IPSEC_DEBUG
152 if (debug_radij & DB_RJ_DUMPTREES)
153 rj_dumptrees(); /* XXXXXXXXX */
154 #endif /* CONFIG_IPSEC_DEBUG */
155
156 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
157 "klips_debug:ipsec_eroute_get_info: "
158 "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
159 buffer,
160 *start,
161 (int)offset,
162 length);
163
164 spin_lock_bh(&eroute_lock);
165
166 rj_walktree(rnh, ipsec_rj_walker_procprint, &w);
167 /* rj_walktree(mask_rjhead, ipsec_rj_walker_procprint, &w); */
168
169 spin_unlock_bh(&eroute_lock);
170
171 *start = buffer + (offset - w.begin); /* Start of wanted data */
172 return w.len - (offset - w.begin);
173 }
174
175 IPSEC_PROCFS_DEBUG_NO_STATIC
176 int
177 ipsec_spi_get_info(char *buffer,
178 char **start,
179 off_t offset,
180 int length IPSEC_PROC_LAST_ARG)
181 {
182 /* Limit of useful snprintf output */
183 const int max_content = length > 0? length-1 : 0;
184
185 int len = 0;
186 off_t begin = 0;
187 int i;
188 struct ipsec_sa *sa_p;
189 char sa[SATOA_BUF];
190 char buf_s[SUBNETTOA_BUF];
191 char buf_d[SUBNETTOA_BUF];
192 size_t sa_len;
193
194 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
195 "klips_debug:ipsec_spi_get_info: "
196 "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
197 buffer,
198 *start,
199 (int)offset,
200 length);
201
202 spin_lock_bh(&tdb_lock);
203
204
205
206 for (i = 0; i < SADB_HASHMOD; i++) {
207 for (sa_p = ipsec_sadb_hash[i];
208 sa_p;
209 sa_p = sa_p->ips_hnext) {
210 atomic_inc(&sa_p->ips_refcount);
211 sa_len = satoa(sa_p->ips_said, 0, sa, SATOA_BUF);
212 len += ipsec_snprintf(buffer+len, length-len, "%s ",
213 sa_len ? sa : " (error)");
214
215 len += ipsec_snprintf(buffer+len, length-len, "%s%s%s",
216 IPS_XFORM_NAME(sa_p));
217
218 len += ipsec_snprintf(buffer+len, length-len, ": dir=%s",
219 (sa_p->ips_flags & EMT_INBOUND) ?
220 "in " : "out");
221
222 if(sa_p->ips_addr_s) {
223 addrtoa(((struct sockaddr_in*)(sa_p->ips_addr_s))->sin_addr,
224 0, buf_s, sizeof(buf_s));
225 len += ipsec_snprintf(buffer+len, length-len, " src=%s",
226 buf_s);
227 }
228
229 if((sa_p->ips_said.proto == IPPROTO_IPIP)
230 && (sa_p->ips_flags & SADB_X_SAFLAGS_INFLOW)) {
231 subnettoa(sa_p->ips_flow_s.u.v4.sin_addr,
232 sa_p->ips_mask_s.u.v4.sin_addr,
233 0,
234 buf_s,
235 sizeof(buf_s));
236
237 subnettoa(sa_p->ips_flow_d.u.v4.sin_addr,
238 sa_p->ips_mask_d.u.v4.sin_addr,
239 0,
240 buf_d,
241 sizeof(buf_d));
242
243 len += ipsec_snprintf(buffer+len, length-len, " policy=%s->%s",
244 buf_s, buf_d);
245 }
246
247 if(sa_p->ips_iv_bits) {
248 int j;
249 len += ipsec_snprintf(buffer+len, length-len, " iv_bits=%dbits iv=0x",
250 sa_p->ips_iv_bits);
251
252 for(j = 0; j < sa_p->ips_iv_bits / 8; j++) {
253 len += ipsec_snprintf(buffer+len, length-len, "%02x",
254 (__u32)((__u8*)(sa_p->ips_iv))[j]);
255 }
256 }
257
258 if(sa_p->ips_encalg || sa_p->ips_authalg) {
259 if(sa_p->ips_replaywin) {
260 len += ipsec_snprintf(buffer+len, length-len, " ooowin=%d",
261 sa_p->ips_replaywin);
262 }
263 if(sa_p->ips_errs.ips_replaywin_errs) {
264 len += ipsec_snprintf(buffer+len, length-len, " ooo_errs=%d",
265 sa_p->ips_errs.ips_replaywin_errs);
266 }
267 if(sa_p->ips_replaywin_lastseq) {
268 len += ipsec_snprintf(buffer+len, length-len, " seq=%d",
269 sa_p->ips_replaywin_lastseq);
270 }
271 if(sa_p->ips_replaywin_bitmap) {
272 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
273 len += ipsec_snprintf(buffer+len, length-len, " bit=0x%Lx",
274 sa_p->ips_replaywin_bitmap);
275 #else
276 len += ipsec_snprintf(buffer+len, length-len, " bit=0x%x%08x",
277 (__u32)(sa_p->ips_replaywin_bitmap >> 32),
278 (__u32)sa_p->ips_replaywin_bitmap);
279 #endif
280 }
281 if(sa_p->ips_replaywin_maxdiff) {
282 len += ipsec_snprintf(buffer+len, length-len, " max_seq_diff=%d",
283 sa_p->ips_replaywin_maxdiff);
284 }
285 }
286 if(sa_p->ips_flags & ~EMT_INBOUND) {
287 len += ipsec_snprintf(buffer+len, length-len, " flags=0x%x",
288 sa_p->ips_flags & ~EMT_INBOUND);
289 len += ipsec_snprintf(buffer+len, length-len, "<");
290 /* flag printing goes here */
291 len += ipsec_snprintf(buffer+len, length-len, ">");
292 }
293 if(sa_p->ips_auth_bits) {
294 len += ipsec_snprintf(buffer+len, length-len, " alen=%d",
295 sa_p->ips_auth_bits);
296 }
297 if(sa_p->ips_key_bits_a) {
298 len += ipsec_snprintf(buffer+len, length-len, " aklen=%d",
299 sa_p->ips_key_bits_a);
300 }
301 if(sa_p->ips_errs.ips_auth_errs) {
302 len += ipsec_snprintf(buffer+len, length-len, " auth_errs=%d",
303 sa_p->ips_errs.ips_auth_errs);
304 }
305 if(sa_p->ips_key_bits_e) {
306 len += ipsec_snprintf(buffer+len, length-len, " eklen=%d",
307 sa_p->ips_key_bits_e);
308 }
309 if(sa_p->ips_errs.ips_encsize_errs) {
310 len += ipsec_snprintf(buffer+len, length-len, " encr_size_errs=%d",
311 sa_p->ips_errs.ips_encsize_errs);
312 }
313 if(sa_p->ips_errs.ips_encpad_errs) {
314 len += ipsec_snprintf(buffer+len, length-len, " encr_pad_errs=%d",
315 sa_p->ips_errs.ips_encpad_errs);
316 }
317
318 len += ipsec_snprintf(buffer+len, length-len, " life(c,s,h)=");
319
320 len += ipsec_lifetime_format(buffer + len,
321 length - len,
322 "alloc",
323 ipsec_life_countbased,
324 &sa_p->ips_life.ipl_allocations);
325
326 len += ipsec_lifetime_format(buffer + len,
327 length - len,
328 "bytes",
329 ipsec_life_countbased,
330 &sa_p->ips_life.ipl_bytes);
331
332 len += ipsec_lifetime_format(buffer + len,
333 length - len,
334 "addtime",
335 ipsec_life_timebased,
336 &sa_p->ips_life.ipl_addtime);
337
338 len += ipsec_lifetime_format(buffer + len,
339 length - len,
340 "usetime",
341 ipsec_life_timebased,
342 &sa_p->ips_life.ipl_usetime);
343
344 len += ipsec_lifetime_format(buffer + len,
345 length - len,
346 "packets",
347 ipsec_life_countbased,
348 &sa_p->ips_life.ipl_packets);
349
350 if(sa_p->ips_life.ipl_usetime.ipl_last) { /* XXX-MCR should be last? */
351 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
352 len += ipsec_snprintf(buffer+len, length-len, " idle=%Ld",
353 jiffies / HZ - sa_p->ips_life.ipl_usetime.ipl_last);
354 #else
355 len += ipsec_snprintf(buffer+len, length-len, " idle=%lu",
356 jiffies / HZ - (unsigned long)sa_p->ips_life.ipl_usetime.ipl_last);
357 #endif
358 }
359
360 #ifdef CONFIG_IPSEC_IPCOMP
361 if(sa_p->ips_said.proto == IPPROTO_COMP &&
362 (sa_p->ips_comp_ratio_dbytes ||
363 sa_p->ips_comp_ratio_cbytes)) {
364 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
365 len += ipsec_snprintf(buffer+len, length-len, " ratio=%Ld:%Ld",
366 sa_p->ips_comp_ratio_dbytes,
367 sa_p->ips_comp_ratio_cbytes);
368 #else
369 len += ipsec_snprintf(buffer+len, length-len, " ratio=%lu:%lu",
370 (unsigned long)sa_p->ips_comp_ratio_dbytes,
371 (unsigned long)sa_p->ips_comp_ratio_cbytes);
372 #endif
373 }
374 #endif /* CONFIG_IPSEC_IPCOMP */
375
376 #ifdef CONFIG_IPSEC_NAT_TRAVERSAL
377 if(sa_p->ips_natt_type != 0) {
378 char *natttype_name;
379
380 switch(sa_p->ips_natt_type)
381 {
382 case ESPINUDP_WITH_NON_IKE:
383 natttype_name="nonike";
384 break;
385 case ESPINUDP_WITH_NON_ESP:
386 natttype_name="nonesp";
387 break;
388 default:
389 natttype_name="unknown";
390 break;
391 }
392
393 len += ipsec_snprintf(buffer+len, length-len, " natencap=%s",
394 natttype_name);
395
396 len += ipsec_snprintf(buffer+len, length-len, " natsport=%d",
397 sa_p->ips_natt_sport);
398
399 len += ipsec_snprintf(buffer+len, length-len, " natdport=%d",
400 sa_p->ips_natt_dport);
401 }
402 #endif /* CONFIG_IPSEC_NAT_TRAVERSAL */
403
404 len += ipsec_snprintf(buffer+len, length-len, " refcount=%d",
405 atomic_read(&sa_p->ips_refcount));
406
407 len += ipsec_snprintf(buffer+len, length-len, " ref=%d",
408 sa_p->ips_ref);
409 #ifdef CONFIG_IPSEC_DEBUG
410 if(debug_xform) {
411 len += ipsec_snprintf(buffer+len, length-len, " reftable=%lu refentry=%lu",
412 (unsigned long)IPsecSAref2table(sa_p->ips_ref),
413 (unsigned long)IPsecSAref2entry(sa_p->ips_ref));
414 }
415 #endif /* CONFIG_IPSEC_DEBUG */
416
417 len += ipsec_snprintf(buffer+len, length-len, "\n");
418
419 atomic_dec(&sa_p->ips_refcount);
420
421 if (len >= max_content) {
422 /* we've done all that can fit -- stop loops */
423 len = max_content; /* truncate crap */
424 goto done_spi_i;
425 } else {
426 const off_t pos = begin + len;
427
428 if (pos <= offset) {
429 /* all is before first interesting character:
430 * discard, but note where we are.
431 */
432 len = 0;
433 begin = pos;
434 }
435 }
436 }
437 }
438
439 done_spi_i:
440 spin_unlock_bh(&tdb_lock);
441
442 *start = buffer + (offset - begin); /* Start of wanted data */
443 return len - (offset - begin);
444 }
445
446 IPSEC_PROCFS_DEBUG_NO_STATIC
447 int
448 ipsec_spigrp_get_info(char *buffer,
449 char **start,
450 off_t offset,
451 int length IPSEC_PROC_LAST_ARG)
452 {
453 /* limit of useful snprintf output */
454 const int max_content = length > 0? length-1 : 0;
455
456 int len = 0;
457 off_t begin = 0;
458 int i;
459 struct ipsec_sa *sa_p, *sa_p2;
460 char sa[SATOA_BUF];
461 size_t sa_len;
462
463 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
464 "klips_debug:ipsec_spigrp_get_info: "
465 "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
466 buffer,
467 *start,
468 (int)offset,
469 length);
470
471 spin_lock_bh(&tdb_lock);
472
473 for (i = 0; i < SADB_HASHMOD; i++) {
474 for (sa_p = ipsec_sadb_hash[i];
475 sa_p != NULL;
476 sa_p = sa_p->ips_hnext)
477 {
478 atomic_inc(&sa_p->ips_refcount);
479 if(sa_p->ips_inext == NULL) {
480 sa_p2 = sa_p;
481 while(sa_p2 != NULL) {
482 atomic_inc(&sa_p2->ips_refcount);
483 sa_len = satoa(sa_p2->ips_said,
484 0, sa, SATOA_BUF);
485
486 len += ipsec_snprintf(buffer+len, length-len, "%s ",
487 sa_len ? sa : " (error)");
488 atomic_dec(&sa_p2->ips_refcount);
489 sa_p2 = sa_p2->ips_onext;
490 }
491 len += ipsec_snprintf(buffer+len, length-len, "\n");
492 }
493
494 atomic_dec(&sa_p->ips_refcount);
495
496 if (len >= max_content) {
497 /* we've done all that can fit -- stop loops */
498 len = max_content; /* truncate crap */
499 goto done_spigrp_i;
500 } else {
501 const off_t pos = begin + len;
502
503 if (pos <= offset) {
504 /* all is before first interesting character:
505 * discard, but note where we are.
506 */
507 len = 0;
508 begin = pos;
509 }
510 }
511 }
512 }
513
514 done_spigrp_i:
515 spin_unlock_bh(&tdb_lock);
516
517 *start = buffer + (offset - begin); /* Start of wanted data */
518 return len - (offset - begin);
519 }
520
521 IPSEC_PROCFS_DEBUG_NO_STATIC
522 int
523 ipsec_tncfg_get_info(char *buffer,
524 char **start,
525 off_t offset,
526 int length IPSEC_PROC_LAST_ARG)
527 {
528 /* limit of useful snprintf output */
529 const int max_content = length > 0? length-1 : 0;
530
531 int len = 0;
532 off_t begin = 0;
533 int i;
534 char name[9];
535 struct device *dev, *privdev;
536 struct ipsecpriv *priv;
537
538 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
539 "klips_debug:ipsec_tncfg_get_info: "
540 "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
541 buffer,
542 *start,
543 (int)offset,
544 length);
545
546 for(i = 0; i < IPSEC_NUM_IF; i++) {
547 ipsec_snprintf(name, (ssize_t) sizeof(name), IPSEC_DEV_FORMAT, i);
548 dev = __ipsec_dev_get(name);
549 if(dev) {
550 priv = (struct ipsecpriv *)(dev->priv);
551 len += ipsec_snprintf(buffer+len, length-len, "%s",
552 dev->name);
553 if(priv) {
554 privdev = (struct device *)(priv->dev);
555 len += ipsec_snprintf(buffer+len, length-len, " -> %s",
556 privdev ? privdev->name : "NULL");
557 len += ipsec_snprintf(buffer+len, length-len, " mtu=%d(%d) -> %d",
558 dev->mtu,
559 priv->mtu,
560 privdev ? privdev->mtu : 0);
561 } else {
562 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
563 "klips_debug:ipsec_tncfg_get_info: device '%s' has no private data space!\n",
564 dev->name);
565 }
566 len += ipsec_snprintf(buffer+len, length-len, "\n");
567
568 if (len >= max_content) {
569 /* we've done all that can fit -- stop loop */
570 len = max_content; /* truncate crap */
571 break;
572 } else {
573 const off_t pos = begin + len;
574 if (pos <= offset) {
575 len = 0;
576 begin = pos;
577 }
578 }
579 }
580 }
581 *start = buffer + (offset - begin); /* Start of wanted data */
582 len -= (offset - begin); /* Start slop */
583 if (len > length)
584 len = length;
585 return len;
586 }
587
588 IPSEC_PROCFS_DEBUG_NO_STATIC
589 int
590 ipsec_version_get_info(char *buffer,
591 char **start,
592 off_t offset,
593 int length IPSEC_PROC_LAST_ARG)
594 {
595 int len = 0;
596 off_t begin = 0;
597
598 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
599 "klips_debug:ipsec_version_get_info: "
600 "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
601 buffer,
602 *start,
603 (int)offset,
604 length);
605
606 len += ipsec_snprintf(buffer+len, length-len, "strongSwan version: %s\n",
607 ipsec_version_code());
608 #if 0
609 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
610 "klips_debug:ipsec_version_get_info: "
611 "ipsec_init version: %s\n",
612 ipsec_init_c_version);
613 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
614 "klips_debug:ipsec_version_get_info: "
615 "ipsec_tunnel version: %s\n",
616 ipsec_tunnel_c_version);
617 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
618 "klips_debug:ipsec_version_get_info: "
619 "ipsec_netlink version: %s\n",
620 ipsec_netlink_c_version);
621 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
622 "klips_debug:ipsec_version_get_info: "
623 "radij_c_version: %s\n",
624 radij_c_version);
625 #endif
626
627 *start = buffer + (offset - begin); /* Start of wanted data */
628 len -= (offset - begin); /* Start slop */
629 if (len > length)
630 len = length;
631 return len;
632 }
633
634 IPSEC_PROCFS_DEBUG_NO_STATIC
635 int
636 ipsec_birth_info(char *page,
637 char **start,
638 off_t offset,
639 int count,
640 int *eof,
641 void *data)
642 {
643 struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data;
644 int len;
645
646 if(offset >= ibr->packet_template_len) {
647 if(eof) {
648 *eof=1;
649 }
650 return 0;
651 }
652
653 len = ibr->packet_template_len;
654 len -= offset;
655 if (len > count)
656 len = count;
657
658 memcpy(page + offset, ibr->packet_template+offset, len);
659
660 return len;
661 }
662
663 IPSEC_PROCFS_DEBUG_NO_STATIC
664 int
665 ipsec_birth_set(struct file *file, const char *buffer,
666 unsigned long count, void *data)
667 {
668 struct ipsec_birth_reply *ibr = (struct ipsec_birth_reply *)data;
669 int len;
670
671 MOD_INC_USE_COUNT;
672 if(count > IPSEC_BIRTH_TEMPLATE_MAXLEN) {
673 len = IPSEC_BIRTH_TEMPLATE_MAXLEN;
674 } else {
675 len = count;
676 }
677
678 if(copy_from_user(ibr->packet_template, buffer, len)) {
679 MOD_DEC_USE_COUNT;
680 return -EFAULT;
681 }
682 ibr->packet_template_len = len;
683
684 MOD_DEC_USE_COUNT;
685
686 return len;
687 }
688
689
690 #ifdef CONFIG_IPSEC_DEBUG
691 IPSEC_PROCFS_DEBUG_NO_STATIC
692 int
693 ipsec_klipsdebug_get_info(char *buffer,
694 char **start,
695 off_t offset,
696 int length IPSEC_PROC_LAST_ARG)
697 {
698 int len = 0;
699 off_t begin = 0;
700
701 KLIPS_PRINT(debug_tunnel & DB_TN_PROCFS,
702 "klips_debug:ipsec_klipsdebug_get_info: "
703 "buffer=0p%p, *start=0p%p, offset=%d, length=%d\n",
704 buffer,
705 *start,
706 (int)offset,
707 length);
708
709 len += ipsec_snprintf(buffer+len, length-len, "debug_tunnel=%08x.\n", debug_tunnel);
710 len += ipsec_snprintf(buffer+len, length-len, "debug_xform=%08x.\n", debug_xform);
711 len += ipsec_snprintf(buffer+len, length-len, "debug_eroute=%08x.\n", debug_eroute);
712 len += ipsec_snprintf(buffer+len, length-len, "debug_spi=%08x.\n", debug_spi);
713 len += ipsec_snprintf(buffer+len, length-len, "debug_radij=%08x.\n", debug_radij);
714 len += ipsec_snprintf(buffer+len, length-len, "debug_esp=%08x.\n", debug_esp);
715 len += ipsec_snprintf(buffer+len, length-len, "debug_ah=%08x.\n", debug_ah);
716 len += ipsec_snprintf(buffer+len, length-len, "debug_rcv=%08x.\n", debug_rcv);
717 len += ipsec_snprintf(buffer+len, length-len, "debug_pfkey=%08x.\n", debug_pfkey);
718
719 *start = buffer + (offset - begin); /* Start of wanted data */
720 len -= (offset - begin); /* Start slop */
721 if (len > length)
722 len = length;
723 return len;
724 }
725 #endif /* CONFIG_IPSEC_DEBUG */
726
727 IPSEC_PROCFS_DEBUG_NO_STATIC
728 int
729 ipsec_stats_get_int_info(char *buffer,
730 char **start,
731 off_t offset,
732 int length,
733 int *eof,
734 void *data)
735 {
736 /* Limit of useful snprintf output */
737 const int max_content = length > 0? length-1 : 0;
738
739 int len = 0;
740 int *thing;
741
742 thing = (int *)data;
743
744 len = ipsec_snprintf(buffer+len, length-len, "%08x\n", *thing);
745
746 if (len >= max_content)
747 len = max_content; /* truncate crap */
748
749 *start = buffer + offset; /* Start of wanted data */
750 return len > offset? len - offset : 0;
751 }
752
753 #ifndef PROC_FS_2325
754 struct proc_dir_entry ipsec_eroute =
755 {
756 0,
757 12, "ipsec_eroute",
758 S_IFREG | S_IRUGO, 1, 0, 0, 0,
759 &proc_net_inode_operations,
760 ipsec_eroute_get_info,
761 NULL, NULL, NULL, NULL, NULL
762 };
763
764 struct proc_dir_entry ipsec_spi =
765 {
766 0,
767 9, "ipsec_spi",
768 S_IFREG | S_IRUGO, 1, 0, 0, 0,
769 &proc_net_inode_operations,
770 ipsec_spi_get_info,
771 NULL, NULL, NULL, NULL, NULL
772 };
773
774 struct proc_dir_entry ipsec_spigrp =
775 {
776 0,
777 12, "ipsec_spigrp",
778 S_IFREG | S_IRUGO, 1, 0, 0, 0,
779 &proc_net_inode_operations,
780 ipsec_spigrp_get_info,
781 NULL, NULL, NULL, NULL, NULL
782 };
783
784 struct proc_dir_entry ipsec_tncfg =
785 {
786 0,
787 11, "ipsec_tncfg",
788 S_IFREG | S_IRUGO, 1, 0, 0, 0,
789 &proc_net_inode_operations,
790 ipsec_tncfg_get_info,
791 NULL, NULL, NULL, NULL, NULL
792 };
793
794 struct proc_dir_entry ipsec_version =
795 {
796 0,
797 13, "ipsec_version",
798 S_IFREG | S_IRUGO, 1, 0, 0, 0,
799 &proc_net_inode_operations,
800 ipsec_version_get_info,
801 NULL, NULL, NULL, NULL, NULL
802 };
803
804 #ifdef CONFIG_IPSEC_DEBUG
805 struct proc_dir_entry ipsec_klipsdebug =
806 {
807 0,
808 16, "ipsec_klipsdebug",
809 S_IFREG | S_IRUGO, 1, 0, 0, 0,
810 &proc_net_inode_operations,
811 ipsec_klipsdebug_get_info,
812 NULL, NULL, NULL, NULL, NULL
813 };
814 #endif /* CONFIG_IPSEC_DEBUG */
815 #endif /* !PROC_FS_2325 */
816 #endif /* CONFIG_PROC_FS */
817
818 #if defined(PROC_FS_2325)
819 struct ipsec_proc_list {
820 char *name;
821 struct proc_dir_entry **parent;
822 struct proc_dir_entry **dir;
823 read_proc_t *readthing;
824 write_proc_t *writething;
825 void *data;
826 };
827 static struct ipsec_proc_list proc_items[]={
828 #ifdef CONFIG_IPSEC_DEBUG
829 {"klipsdebug", &proc_net_ipsec_dir, NULL, ipsec_klipsdebug_get_info, NULL, NULL},
830 #endif
831 {"eroute", &proc_net_ipsec_dir, &proc_eroute_dir, NULL, NULL, NULL},
832 {"all", &proc_eroute_dir, NULL, ipsec_eroute_get_info, NULL, NULL},
833 {"spi", &proc_net_ipsec_dir, &proc_spi_dir, NULL, NULL, NULL},
834 {"all", &proc_spi_dir, NULL, ipsec_spi_get_info, NULL, NULL},
835 {"spigrp", &proc_net_ipsec_dir, &proc_spigrp_dir, NULL, NULL, NULL},
836 {"all", &proc_spigrp_dir, NULL, ipsec_spigrp_get_info, NULL, NULL},
837 {"birth", &proc_net_ipsec_dir, &proc_birth_dir, NULL, NULL, NULL},
838 {"ipv4", &proc_birth_dir, NULL, ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv4_birth_packet},
839 {"ipv6", &proc_birth_dir, NULL, ipsec_birth_info, ipsec_birth_set, (void *)&ipsec_ipv6_birth_packet},
840 {"xforms", &proc_net_ipsec_dir, NULL, ipsec_xform_get_info, NULL, NULL},
841 {"tncfg", &proc_net_ipsec_dir, NULL, ipsec_tncfg_get_info, NULL, NULL},
842 {"stats", &proc_net_ipsec_dir, &proc_stats_dir, NULL, NULL, NULL},
843 {"trap_count", &proc_stats_dir, NULL, ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_count},
844 {"trap_sendcount", &proc_stats_dir, NULL, ipsec_stats_get_int_info, NULL, &ipsec_xmit_trap_sendcount},
845 {"version", &proc_net_ipsec_dir, NULL, ipsec_version_get_info, NULL, NULL},
846 {NULL, NULL, NULL, NULL, NULL, NULL}
847 };
848 #endif
849
850 int
851 ipsec_proc_init()
852 {
853 int error = 0;
854 #ifdef IPSEC_PROC_SUBDIRS
855 struct proc_dir_entry *item;
856 #endif
857
858 /*
859 * just complain because pluto won't run without /proc!
860 */
861 #ifndef CONFIG_PROC_FS
862 #error You must have PROC_FS built in to use KLIPS
863 #endif
864
865 /* for 2.0 kernels */
866 #if !defined(PROC_FS_2325) && !defined(PROC_FS_21)
867 error |= proc_register_dynamic(&proc_net, &ipsec_eroute);
868 error |= proc_register_dynamic(&proc_net, &ipsec_spi);
869 error |= proc_register_dynamic(&proc_net, &ipsec_spigrp);
870 error |= proc_register_dynamic(&proc_net, &ipsec_tncfg);
871 error |= proc_register_dynamic(&proc_net, &ipsec_version);
872 #ifdef CONFIG_IPSEC_DEBUG
873 error |= proc_register_dynamic(&proc_net, &ipsec_klipsdebug);
874 #endif /* CONFIG_IPSEC_DEBUG */
875 #endif
876
877 /* for 2.2 kernels */
878 #if !defined(PROC_FS_2325) && defined(PROC_FS_21)
879 error |= proc_register(proc_net, &ipsec_eroute);
880 error |= proc_register(proc_net, &ipsec_spi);
881 error |= proc_register(proc_net, &ipsec_spigrp);
882 error |= proc_register(proc_net, &ipsec_tncfg);
883 error |= proc_register(proc_net, &ipsec_version);
884 #ifdef CONFIG_IPSEC_DEBUG
885 error |= proc_register(proc_net, &ipsec_klipsdebug);
886 #endif /* CONFIG_IPSEC_DEBUG */
887 #endif
888
889 /* for 2.4 kernels */
890 #if defined(PROC_FS_2325)
891 /* create /proc/net/ipsec */
892
893 /* zero these out before we initialize /proc/net/ipsec/birth/stuff */
894 memset(&ipsec_ipv4_birth_packet, 0, sizeof(struct ipsec_birth_reply));
895 memset(&ipsec_ipv6_birth_packet, 0, sizeof(struct ipsec_birth_reply));
896
897 proc_net_ipsec_dir = proc_mkdir("ipsec", proc_net);
898 if(proc_net_ipsec_dir == NULL) {
899 /* no point in continuing */
900 return 1;
901 }
902
903 {
904 struct ipsec_proc_list *it;
905
906 it=proc_items;
907 while(it->name!=NULL) {
908 if(it->dir) {
909 /* make a dir instead */
910 item = proc_mkdir(it->name, *it->parent);
911 *it->dir = item;
912 } else {
913 item = create_proc_entry(it->name, 0400, *it->parent);
914 }
915 if(item) {
916 item->read_proc = it->readthing;
917 item->write_proc = it->writething;
918 item->data = it->data;
919 #ifdef MODULE
920 item->owner = THIS_MODULE;
921 #endif
922 } else {
923 error |= 1;
924 }
925 it++;
926 }
927 }
928
929 /* now create some symlinks to provide compatibility */
930 proc_symlink("ipsec_eroute", proc_net, "ipsec/eroute/all");
931 proc_symlink("ipsec_spi", proc_net, "ipsec/spi/all");
932 proc_symlink("ipsec_spigrp", proc_net, "ipsec/spigrp/all");
933 proc_symlink("ipsec_tncfg", proc_net, "ipsec/tncfg");
934 proc_symlink("ipsec_version",proc_net, "ipsec/version");
935 proc_symlink("ipsec_klipsdebug",proc_net,"ipsec/klipsdebug");
936
937 #endif /* !PROC_FS_2325 */
938
939 return error;
940 }
941
942 void
943 ipsec_proc_cleanup()
944 {
945
946 /* for 2.0 and 2.2 kernels */
947 #if !defined(PROC_FS_2325)
948
949 #ifdef CONFIG_IPSEC_DEBUG
950 if (proc_net_unregister(ipsec_klipsdebug.low_ino) != 0)
951 printk("klips_debug:ipsec_cleanup: "
952 "cannot unregister /proc/net/ipsec_klipsdebug\n");
953 #endif /* CONFIG_IPSEC_DEBUG */
954
955 if (proc_net_unregister(ipsec_version.low_ino) != 0)
956 printk("klips_debug:ipsec_cleanup: "
957 "cannot unregister /proc/net/ipsec_version\n");
958 if (proc_net_unregister(ipsec_eroute.low_ino) != 0)
959 printk("klips_debug:ipsec_cleanup: "
960 "cannot unregister /proc/net/ipsec_eroute\n");
961 if (proc_net_unregister(ipsec_spi.low_ino) != 0)
962 printk("klips_debug:ipsec_cleanup: "
963 "cannot unregister /proc/net/ipsec_spi\n");
964 if (proc_net_unregister(ipsec_spigrp.low_ino) != 0)
965 printk("klips_debug:ipsec_cleanup: "
966 "cannot unregister /proc/net/ipsec_spigrp\n");
967 if (proc_net_unregister(ipsec_tncfg.low_ino) != 0)
968 printk("klips_debug:ipsec_cleanup: "
969 "cannot unregister /proc/net/ipsec_tncfg\n");
970 #endif
971
972 /* for 2.4 kernels */
973 #if defined(PROC_FS_2325)
974 {
975 struct ipsec_proc_list *it;
976
977 /* find end of list */
978 it=proc_items;
979 while(it->name!=NULL) {
980 it++;
981 }
982 it--;
983
984 do {
985 remove_proc_entry(it->name, *it->parent);
986 it--;
987 } while(it > proc_items);
988 }
989
990
991 #ifdef CONFIG_IPSEC_DEBUG
992 remove_proc_entry("ipsec_klipsdebug", proc_net);
993 #endif /* CONFIG_IPSEC_DEBUG */
994 remove_proc_entry("ipsec_eroute", proc_net);
995 remove_proc_entry("ipsec_spi", proc_net);
996 remove_proc_entry("ipsec_spigrp", proc_net);
997 remove_proc_entry("ipsec_tncfg", proc_net);
998 remove_proc_entry("ipsec_version", proc_net);
999 remove_proc_entry("ipsec", proc_net);
1000 #endif /* 2.4 kernel */
1001 }
1002
1003