📄 pf_key.c
字号:
/* * @(#) pfkey socket manipulator/observer * * Copyright (C) 2001 Richard Guy Briggs <rgb@freeswan.org> * and Michael Richardson <mcr@freeswan.org> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * RCSID $Id: pf_key.c,v 1.18 2004/04/04 01:50:56 ken Exp $ * *//* * This program opens a pfkey socket or a file * and prints all messages that it sees. * * This can be used to diagnose problems. * */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <getopt.h>#include <errno.h>#include <setjmp.h>#include <signal.h>#include <sys/socket.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdint.h>#include <openswan.h>#include <pfkeyv2.h>#include <pfkey.h>char *progname;uint32_t pfkey_seq = 0;int pfkey_sock;static voidUsage(char *progname){ fprintf(stderr, "%s: Usage: %s [--help]\n" "\tby default listens for AH, ESP, IPIP and IPCOMP\n" "\t--daemon <file> fork before printing, stuffing the PID in the file\n" "\t--dumpfile <file> decode file of pfkey messages\n" "\t--encodefile <file> encode file of pfkey messages\n" "\t--esp listen for ESP messages\n" "\t--ah listen for AH messages\n" "\t--esp listen for ESP messages\n" "\t--ipip listen for IPIP messages\n" "\t--ipcomp listen for IPCOMP messages\n", progname, progname); exit(1);}voidpfkey_register(uint8_t satype) { /* for registering SA types that can be negotiated */ int error = 0; struct sadb_ext *extensions[SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg; pfkey_extensions_init(extensions); if((error = pfkey_msg_hdr_build(&extensions[0], SADB_REGISTER, satype, 0, ++pfkey_seq, getpid()))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } if((error = pfkey_msg_build(&pfkey_msg, extensions, EXT_BITS_IN))) { fprintf(stderr, "%s: Trouble building pfkey message, error=%d.\n", progname, error); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); exit(1); } if(write(pfkey_sock, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) { /* cleanup code here */ fprintf(stderr, "%s: Trouble writing to channel PF_KEY.\n", progname); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); exit(1); } pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg);}int dienow;void controlC(int foo){ fflush(stdout); printf("%s: Exiting on signal 15\n", progname); fflush(stderr); exit(0);}intmain(int argc, char *argv[]){ int opt; ssize_t readlen; unsigned char pfkey_buf[256]; struct sadb_msg *msg; int fork_after_register; char *pidfilename; char *infilename; char *outfilename; static int ah_register; static int esp_register; static int ipip_register; static int ipcomp_register; static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"daemon", required_argument, 0, 'f'}, {"dumpfile", required_argument, 0, 'd'}, {"encodefile", required_argument, 0, 'e'}, {"ah", no_argument, &ah_register, 1}, {"esp", no_argument, &esp_register, 1}, {"ipip", no_argument, &ipip_register, 1}, {"ipcomp", no_argument, &ipcomp_register, 1}, }; ah_register = 0; esp_register = 0; ipip_register = 0; ipcomp_register=0; dienow = 0; fork_after_register=0; pidfilename = NULL; infilename = NULL; outfilename = NULL; progname = argv[0]; if(strrchr(progname, '/')) { progname=strrchr(progname, '/')+1; } while((opt = getopt_long(argc, argv, "hd:e:f:", long_options, NULL)) != EOF) { switch(opt) { case 'f': pidfilename=optarg; fork_after_register=1; break; case 'd': infilename = optarg; break; case 'e': outfilename = optarg; break; case 'h': Usage(progname); break; case '0': /* it was a long option with a flag */ break; } } if(infilename == NULL && outfilename == NULL) { if((pfkey_sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0) { fprintf(stderr, "%s: failed to open PF_KEY family socket: %s\n", progname, strerror(errno)); exit(1); } if(ah_register == 0 && esp_register== 0 && ipip_register==0 && ipcomp_register==0) { ah_register=1; esp_register=1; ipip_register=1; ipcomp_register=1; } if(ah_register) { pfkey_register(SADB_SATYPE_AH); } if(esp_register) { pfkey_register(SADB_SATYPE_ESP); } if(ipip_register) { pfkey_register(SADB_X_SATYPE_IPIP); } if(ipcomp_register) { pfkey_register(SADB_X_SATYPE_COMP); } if(fork_after_register) { /* * to aid in regression testing, we offer to register * everything first, and then we fork. As part of this * we write the PID of the new process to a file * provided. */ int pid; FILE *pidfile; fflush(stdout); fflush(stderr); pid=fork(); if(pid!=0) { /* in parent! */ exit(0); } if((pidfile=fopen(pidfilename, "w"))==NULL) { perror(pidfilename); } else { fprintf(pidfile, "%d", getpid()); fclose(pidfile); } } } else if(infilename != NULL) { pfkey_sock = open(infilename, O_RDONLY); if(pfkey_sock < 0) { fprintf(stderr, "%s: failed to open %s: %s\n", progname, infilename, strerror(errno)); exit(1); } } else if(outfilename != NULL) { /* call encoder */ exit(1); } signal(SIGINT, controlC); signal(SIGTERM, controlC); while((readlen = read(pfkey_sock, pfkey_buf, sizeof(pfkey_buf))) > 0) { msg = (struct sadb_msg *)pfkey_buf; /* first, see if we got enough for an sadb_msg */ if((size_t)readlen < sizeof(struct sadb_msg)) { printf("%s: runt packet of size: %d (<%lu)\n", progname, (int)readlen, (unsigned long)sizeof(struct sadb_msg)); continue; } /* okay, we got enough for a message, print it out */ printf("\npfkey v%d msg. type=%d(%s) seq=%d len=%d pid=%d errno=%d satype=%d(%s)\n", msg->sadb_msg_version, msg->sadb_msg_type, pfkey_v2_sadb_type_string(msg->sadb_msg_type), msg->sadb_msg_seq, msg->sadb_msg_len, msg->sadb_msg_pid, msg->sadb_msg_errno, msg->sadb_msg_satype, satype2name(msg->sadb_msg_satype)); if((size_t)readlen != msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { printf("%s: packet size read from socket=%d doesn't equal sadb_msg_len %d * %u; message not decoded\n", progname, (int) readlen, msg->sadb_msg_len, (int) IPSEC_PFKEYv2_ALIGN); continue; } pfkey_print(msg, stdout); } printf("%s: exited normally\n", progname); exit(0);} /* * $Log: pf_key.c,v $ * Revision 1.18 2004/04/04 01:50:56 ken * Use openswan includes * * Revision 1.17 2003/11/07 01:36:55 ken * Cast to (int) for readlen * * Revision 1.16 2003/10/31 02:33:00 mcr * new printing routines for pf_key. * * Revision 1.15.2.1 2003/10/29 01:38:21 mcr * use new pfkey printer. * * Revision 1.15 2003/09/10 00:01:30 mcr * fixes for gcc 3.3 from Matthias Bethke <Matthias.Bethke@gmx.net> * * Revision 1.14 2002/10/09 03:12:05 dhr * * [kenb+dhr] 64-bit fixes * * Revision 1.13 2002/09/20 05:02:15 rgb * Cleaned up pfkey_lib_debug usage. * * Revision 1.12 2002/09/13 23:02:23 rgb * Type fiddling to tame ia64 compiler. * Added text labels to elucidate numeric values presented. * * Revision 1.11 2002/08/26 03:05:25 mcr * duh, pf_key much catch SIGTERM as well as SIGINT... * * Revision 1.10 2002/08/13 19:01:27 mcr * patches from kenb to permit compilation of FreeSWAN on ia64. * des library patched to use proper DES_LONG type for ia64. * * Revision 1.9 2002/07/16 02:53:42 mcr * added --daemon <pidfile> to "ipsec pf_key" command. * this is used in *-trap-* tests to avoid race conditions between * registration of PF_KEY listeners and arrival of first test packet. * * Revision 1.8 2002/06/17 04:32:55 mcr * exit nicely from pf_key when SIGINT (^C) is sent. * This is needed so that the stdout will flush properly. * * Revision 1.7 2002/04/24 07:55:32 mcr * #include patches and Makefiles for post-reorg compilation. * * Revision 1.6 2002/04/24 07:35:39 mcr * Moved from ./klips/utils/pf_key.c,v * * Revision 1.5 2002/03/08 21:44:04 rgb * Update for all GNU-compliant --version strings. * * Revision 1.4 2001/11/27 05:19:06 mcr * added extra newline between packets. * set pfkey_lib_debug to enum rather than just to "1". * * Revision 1.3 2001/11/27 03:35:29 rgb * Added stdlib *again*. * * Revision 1.2 2001/11/23 07:23:14 mcr * pulled up klips2 Makefile and pf_key code. * * Revision 1.1.2.5 2001/10/23 18:49:12 mcr * renamed man page to section 8. * added --ah, --esp, --ipcomp and --ipip to control which * protocols are printed. * incomplete messages which include at least an sadb header are printed. * * Revision 1.1.2.4 2001/10/22 21:50:51 rgb * Added pfkey register for AH, ESP, IPIP and COMP. * * Revision 1.1.2.3 2001/10/21 21:51:06 rgb * Bug fixes to get working. * * Revision 1.1.2.2 2001/10/20 22:45:31 rgb * Added check for exact length and a call to message parser to get some * idea of the contents of each extension. * * Revision 1.1.2.1 2001/10/17 23:25:37 mcr * added "pk_key" program to dump raw kernel pf messages. * (program is still skeletal) * * * Local variables: * c-file-style: "linux" * End: * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -