void ikev2_print_ts(struct traffic_selector *ts){ char lbx[ADDRTOT_BUF]; char hbx[ADDRTOT_BUF]; DBG_log("printing contents struct traffic_selector"); DBG_log(" ts_type: %s", enum_name(&ikev2_ts_type_names, ts->ts_type)); DBG_log(" ipprotoid: %d", ts->ipprotoid); DBG_log(" startport: %d", ts->startport); DBG_log(" endport: %d", ts->endport); addrtot(&ts->low, 0, lbx, sizeof(lbx)); addrtot(&ts->high, 0, hbx, sizeof(hbx)); DBG_log(" ip low: %s", lbx); DBG_log(" ip high: %s", hbx); }
int main(int argc, char *argv[]) { ip_address high; ip_address low; char bh[100],bl[100]; const char *oops; int n; int af; int i; if (argc == 2 && strcmp(argv[1], "-r") == 0) { regress(); fprintf(stderr, "regress() returned?!?\n"); exit(1); } if (argc < 3) { fprintf(stderr, "Usage: %s [-6] high low\n", argv[0]); fprintf(stderr, " or: %s -r\n", argv[0]); exit(2); } af = AF_INET; i = 1; if (strcmp(argv[i], "-6") == 0) { af = AF_INET6; i++; } oops = ttoaddr(argv[i], 0, af, &high); if (oops != NULL) { fprintf(stderr, "%s: high conversion failed: %s\n", argv[0], oops); exit(1); } oops = ttoaddr(argv[i+1], 0, af, &low); if (oops != NULL) { fprintf(stderr, "%s: low conversion failed: %s\n", argv[0], oops); exit(1); } n = ikev2_calc_iprangediff(high, low); addrtot(&high, 0, bh, sizeof(bh)); addrtot(&low, 0, bl, sizeof(bl)); printf("iprange between %s and %s => %d\n", bh, bl, n); exit(0); }
static void dump_policyreply(struct ipsec_policy_cmd_query *q) { char src[ADDRTOT_BUF], dst[ADDRTOT_BUF]; /* now print it! */ addrtot(&q->query_local, 0, src, sizeof(src)); addrtot(&q->query_remote, 0, dst, sizeof(dst)); printf("Results of query on %s -> %s with seq %d\n", src, dst, q->head.ipm_msg_seq); printf("Received reply of %d bytes.\n", q->head.ipm_msg_len); printf("Strength: %d\n", q->strength); printf("Bandwidth: %d\n", q->bandwidth); printf("authdetail: %d\n", q->auth_detail); printf("esp_detail: %d\n", q->esp_detail); printf("comp_detail: %d\n",q->comp_detail); printf("credentials: %d\n", q->credential_count); if(q->credential_count > 0) { int c; for(c=0; c<q->credential_count; c++) { switch(q->credentials[c].ii_format) { case CERT_DNS_SIGNED_KEY: printf("\tDNSSEC identity: %s (SIG %s)\n", q->credentials[c].ii_credential.ipsec_dns_signed.fqdn, q->credentials[c].ii_credential.ipsec_dns_signed.dns_sig); break; case CERT_RAW_RSA: printf("\tlocal identity: %s\n", q->credentials[c].ii_credential.ipsec_raw_key.id_name); case CERT_NONE: printf("\tDNS identity: %s\n", q->credentials[c].ii_credential.ipsec_dns_signed.fqdn); break; default: printf("\tUnknown identity type %d", q->credentials[c].ii_format); break; } } } }
const char *ip_str(const ip_address *src) { static char buf[ADDRTOT_BUF]; addrtot(src, 0, buf, sizeof(buf)); return buf; }
/***************************************************************************************** 函数名称: dpd_timeout 功能描述: dpd超时处理,删除连接 输入参数: st 输出参数: 无 返 回 值: 无 ------------------------------------------------------------------------------------------- 最近一次修改记录 : 修改作者: 王之云 修改目的: 超时处理 修改日期: 2012年3月20日 ********************************************************************************************/ void dpd_timeout(struct state *st) { int action; struct ike_conn *c = st->st_connection; action = st->st_connection->dpd_action; so_serial_t newest = c->newest_isakmp_sa ; char buf_remoteip[20] = {0}; st->st_dpd_timeout_flag = 1; addrtot(&st->st_remoteaddr, 0, buf_remoteip, sizeof(buf_remoteip)); passert(IS_ISAKMP_SA_ESTABLISHED(st->st_state)); passert(action == DPD_ACTION_HOLD || action == DPD_ACTION_CLEAR || action == DPD_ACTION_RESTART || action == DPD_ACTION_RESTART_BY_PEER); if (newest != st->st_serialno && newest != SOS_NOBODY) { IPSEC_log(IPSEC_LOGLEVEL_WARNING, "Connection < %s > < %s > old state DPD TIMEOUT, " "We will delete state depend on it.!", st->st_connection->name, buf_remoteip); ipsec_release_state_by_parent(st); delete_state(st); return; } { IPSEC_log(IPSEC_LOGLEVEL_WARNING, "Connection < %s > < %s > DPD TIMEOUT, we will %s connection!", st->st_connection->name, buf_remoteip, action == DPD_ACTION_CLEAR ? "clear":"restart"); } switch(action) { case DPD_ACTION_CLEAR: release_connection(&c); break; case DPD_ACTION_RESTART: release_connection(&c); if(NULL != c) { start_initiate_connnection(c); } break; case DPD_ACTION_HOLD: case DPD_ACTION_RESTART_BY_PEER: /*未用到此两种情况*/ break; default : break; } }
bool dag_network::matchesIfPrefix(const ip_address v6) { char b1[ADDRTOT_BUF], b2[SUBNETTOT_BUF]; addrtot(&v6, 0, b1, sizeof(b1)); for(int i=0; i<mIfFilter_max && i<DAG_IFWILDCARD_MAX; i++) { bool matched = addrinsubnet(&v6, &mIfFilter[i]); subnettot(&mIfFilter[i], 0, b2, sizeof(b2)); debug->debug(RPL_DEBUG_NETLINK, "matching addr:%s against %s: result: %s\n", b1, b2, matched ? "matched" : "failed"); if(matched) return true; } return false; }
/* format a string for the log, with suitable prefixes. * A format starting with ~ indicates that this is a reprocessing * of the message, so prefixing and quoting is suppressed. */ static void fmt_log(char *buf, size_t buf_len, const char *fmt, va_list ap) { bool reproc = *fmt == '~'; size_t ps; struct connection *c = cur_state != NULL ? cur_state->st_connection : cur_connection; buf[0] = '\0'; if (reproc) fmt++; /* ~ at start of format suppresses this prefix */ else if (c != NULL) { /* start with name of connection */ char *const be = buf + buf_len; char *bp = buf; snprintf(bp, be - bp, "(%s)", c->name); bp += strlen(bp); /* if it fits, put in any connection instance information */ if (be - bp > CONN_INST_BUF) { fmt_conn_instance(c, bp); bp += strlen(bp); } if (cur_state != NULL) { /* state number */ snprintf(bp, be - bp, " #%lu", cur_state->st_serialno); bp += strlen(bp); } snprintf(bp, be - bp, ": "); } else if (cur_from != NULL) { /* peer's IP address */ /* Note: must not use ip_str() because our caller might! */ char ab[ADDRTOT_BUF]; (void) addrtot(cur_from, 0, ab, sizeof(ab)); snprintf(buf, buf_len, "packet from %s:%u: " , ab, (unsigned)cur_from_port); } ps = strlen(buf); vsnprintf(buf + ps, buf_len - ps, fmt, ap); if (!reproc) (void)sanitize(buf, buf_len); }
int main(int argc, char *argv[]) { ip_subnet s; char buf[100]; char buf2[100]; const char *oops; size_t n; int af; char *p; if (argc < 2) { fprintf(stderr, "Usage: %s [-6] addr/mask\n", argv[0]); fprintf(stderr, " or: %s -r\n", argv[0]); exit(2); } if (strcmp(argv[1], "-r") == 0) { regress(); fprintf(stderr, "regress() returned?!?\n"); exit(1); } af = AF_INET; p = argv[1]; if (strcmp(argv[1], "-6") == 0) { af = AF_INET6; p = argv[2]; } else if (strchr(argv[1], ':') != NULL) af = AF_INET6; oops = ttosubnet(p, 0, af, &s); if (oops != NULL) { fprintf(stderr, "%s: conversion failed: %s\n", argv[0], oops); exit(1); } n = subnettot(&s, 0, buf, sizeof(buf)); if (n > sizeof(buf)) { fprintf(stderr, "%s: reverse conversion of ", argv[0]); (void) addrtot(&s.addr, 0, buf2, sizeof(buf2)); fprintf(stderr, "%s/", buf2); fprintf(stderr, "%d", s.maskbits); fprintf(stderr, " failed: need %ld bytes, have only %ld\n", (long)n, (long)sizeof(buf)); exit(1); } printf("%s\n", buf); exit(0); }
void receive_ike_echo_reply(struct msg_digest *md) { char b1[ADDRTOT_BUF]; addrtot(&md->sender, 0, b1, sizeof(b1)); openswan_log("received ike-echo-reply-%d packet from %s/%d\n", md->hdr.isa_xchg, b1, md->sender_port); #if 0 op->isa_np = NOTHING_WRONG; op->isa_version = (1 << ISA_MAJ_SHIFT) | 0; op->isa_xchg = ISAKMP_XCHG_ECHOREPLY; op->isa_flags =0; op->isa_msgid =rand(); op->isa_length=0; #endif }
/***************************************************************************************** 函数名称: dpd_init 功能描述: 初始化dpd事件 输入参数: st 输出参数: 无 返 回 值: stf_status ------------------------------------------------------------------------------------------- 最近一次修改记录 : 修改作者: 王之云 修改目的: 防止客户端多次初始化DPD 修改日期: 2012年3月20日 ********************************************************************************************/ stf_status dpd_init(struct state *st) { char buf_remoteip[20] = {0}; EV_ADD ev_arg; passert(NULL != st); /*标示该状态是否已经初始化过*/ if(NULL == st->st_dpd_event) { addrtot(&st->st_remoteaddr, 0, buf_remoteip, sizeof(buf_remoteip)); if (st->hidden_variables.st_dpd) { ev_arg.u.st = st; event_schedule(EVENT_DPD, st->st_connection->dpd_delay, &ev_arg); } else { IPSEC_log(IPSEC_LOGLEVEL_INFO, "connection<%s> <%s> peer don't config dpd\n", st->st_connection->name, buf_remoteip); } } return STF_OK; }
/* open the per-peer log */ static void open_peerlog(struct connection *c) { syslog(LOG_INFO, "opening log file for conn %s", c->name); if (c->log_file_name == NULL) { char peername[ADDRTOT_BUF], dname[ADDRTOT_BUF]; int peernamelen, lf_len; addrtot(&c->spd.that.host_addr, 'Q', peername, sizeof(peername)); peernamelen = strlen(peername); /* copy IP address, turning : and . into / */ { char c, *p, *q; p = peername; q = dname; do { c = *p++; if (c == '.' || c == ':') c = '/'; *q++ = c; } while (c != '\0'); } lf_len = peernamelen * 2 + strlen(base_perpeer_logdir) + sizeof("//.log") + 1; c->log_file_name = alloc_bytes(lf_len, "per-peer log file name"); fprintf(stderr, "base dir |%s| dname |%s| peername |%s|" , base_perpeer_logdir, dname, peername); snprintf(c->log_file_name, lf_len, "%s/%s/%s.log" , base_perpeer_logdir, dname, peername); syslog(LOG_DEBUG, "conn %s logfile is %s", c->name, c->log_file_name); } /* now open the file, creating directories if necessary */ { /* create the directory */ char *dname; int bpl_len = strlen(base_perpeer_logdir); char *slashloc; dname = clone_str(c->log_file_name, "temp copy of file name"); dname = dirname(dname); if (access(dname, W_OK) != 0) { if (errno != ENOENT) { if (c->log_file_err) { syslog(LOG_CRIT, "can not write to %s: %s" , dname, strerror(errno)); c->log_file_err = TRUE; pfree(dname); return; } } /* directory does not exist, walk path creating dirs */ /* start at base_perpeer_logdir */ slashloc = dname + bpl_len; slashloc++; /* since, by construction there is a slash right there */ while (*slashloc != '\0') { char saveslash; /* look for next slash */ while (*slashloc != '\0' && *slashloc != '/') slashloc++; saveslash = *slashloc; *slashloc = '\0'; if (mkdir(dname, 0750) != 0 && errno != EEXIST) { syslog(LOG_CRIT, "can not create dir %s: %s" , dname, strerror(errno)); c->log_file_err = TRUE; pfree(dname); return; } syslog(LOG_DEBUG, "created new directory %s", dname); *slashloc = saveslash; slashloc++; } } pfree(dname); } c->log_file = fopen(c->log_file_name, "a"); if (c->log_file == NULL) { if (c->log_file_err) { syslog(LOG_CRIT, "logging system can not open %s: %s" , c->log_file_name, strerror(errno)); c->log_file_err = TRUE; } return; } /* look for a connection to close! */ while (perpeer_count >= MAX_PEERLOG_COUNT) { /* can not be NULL because perpeer_count > 0 */ passert(perpeer_list.cqh_last != (void *)&perpeer_list); perpeer_logclose(perpeer_list.cqh_last); } /* insert this into the list */ CIRCLEQ_INSERT_HEAD(&perpeer_list, c, log_link); passert(c->log_file != NULL); perpeer_count++; }
int main(int argc, char **argv) { int i, nspis; char *endptr; int said_opt = 0; const char* error_s = NULL; char ipaddr_txt[ADDRTOT_BUF]; int debug = 0; int j; struct said_af said_af_array[4]; int error = 0; struct sadb_ext *extensions[SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg; #if 0 ip_address pfkey_address_s_ska; #endif program_name = argv[0]; for(i = 0; i < 4; i++) { memset(&said_af_array[i], 0, sizeof(struct said_af)); } if(argc > 1 && strcmp(argv[1], "--debug") == 0) { debug = 1; if(debug) { fprintf(stdout, "\"--debug\" option requested.\n"); } argv += 1; argc -= 1; pfkey_lib_debug = 1; } if(debug) { fprintf(stdout, "argc=%d (%d incl. --debug option).\n", argc, argc + 1); } if(argc > 1 && strcmp(argv[1], "--label") == 0) { if(argc > 2) { program_name = malloc(strlen(argv[0]) + 10 /* update this when changing the sprintf() */ + strlen(argv[2])); sprintf(program_name, "%s --label %s", argv[0], argv[2]); if(debug) { fprintf(stdout, "using \"%s\" as a label.\n", program_name); } argv += 2; argc -= 2; } else { fprintf(stderr, "%s: --label option requires an argument.\n", program_name); exit(1); } } if(debug) { fprintf(stdout, "...After check for --label option.\n"); } if(argc == 1) { system("cat /proc/net/ipsec_spigrp"); exit(0); } if(debug) { fprintf(stdout, "...After check for no option to print /proc/net/ipsec_spigrp.\n"); } if(strcmp(argv[1], "--help") == 0) { if(debug) { fprintf(stdout, "\"--help\" option requested.\n"); } usage(program_name); exit(1); } if(debug) { fprintf(stdout, "...After check for --help option.\n"); } if(strcmp(argv[1], "--version") == 0) { if(debug) { fprintf(stdout, "\"--version\" option requested.\n"); } fprintf(stdout, "%s %s\n", me, ipsec_version_code()); fprintf(stdout, "See `ipsec --copyright' for copyright information.\n"); exit(1); } if(debug) { fprintf(stdout, "...After check for --version option.\n"); } if(strcmp(argv[1], "--said") == 0) { if(debug) { fprintf(stdout, "processing %d args with --said flag.\n", argc); } said_opt = 1; } if(debug) { fprintf(stdout, "...After check for --said option.\n"); } if(said_opt) { if (argc < 3 /*|| argc > 5*/) { fprintf(stderr, "expecting 3 or more args with --said, got %d.\n", argc); usage(program_name); exit(1); } nspis = argc - 2; } else { if ((argc < 5) || (argc > 17) || ((argc % 4) != 1)) { fprintf(stderr, "expecting 5 or more args without --said, got %d.\n", argc); usage(program_name); exit(1); } nspis = argc / 4; } if(debug) { fprintf(stdout, "processing %d nspis.\n", nspis); } for(i = 0; i < nspis; i++) { if(debug) { fprintf(stdout, "processing spi #%d.\n", i); } if(said_opt) { error_s = ttosa((const char *)argv[i+2], 0, (ip_said*)&(said_af_array[i].said)); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n", program_name, error_s, argv[i+2]); exit (1); } said_af_array[i].af = addrtypeof(&(said_af_array[i].said.dst)); if(debug) { addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stdout, "said[%d].dst=%s.\n", i, ipaddr_txt); } } else { if(!strcmp(argv[i*4+4], "ah")) { said_af_array[i].said.proto = SA_AH; } if(!strcmp(argv[i*4+4], "esp")) { said_af_array[i].said.proto = SA_ESP; } if(!strcmp(argv[i*4+4], "tun")) { said_af_array[i].said.proto = SA_IPIP; } if(!strcmp(argv[i*4+4], "comp")) { said_af_array[i].said.proto = SA_COMP; } if(said_af_array[i].said.proto == 0) { fprintf(stderr, "%s: Badly formed proto: %s\n", program_name, argv[i*4+4]); exit(1); } said_af_array[i].said.spi = htonl(strtoul(argv[i*4+3], &endptr, 0)); if(!(endptr == argv[i*4+3] + strlen(argv[i*4+3]))) { fprintf(stderr, "%s: Badly formed spi: %s\n", program_name, argv[i*4+3]); exit(1); } if(!strcmp(argv[i*4+1], "inet")) { said_af_array[i].af = AF_INET; } if(!strcmp(argv[i*4+1], "inet6")) { said_af_array[i].af = AF_INET6; } if((said_af_array[i].af != AF_INET) && (said_af_array[i].af != AF_INET6)) { fprintf(stderr, "%s: Address family %s not supported\n", program_name, argv[i*4+1]); exit(1); } error_s = ttoaddr(argv[i*4+2], 0, said_af_array[i].af, &(said_af_array[i].said.dst)); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting %dth address argument:%s\n", program_name, error_s, i, argv[i*4+2]); exit (1); } } if(debug) { fprintf(stdout, "SA %d contains: ", i+1); fprintf(stdout, "\n"); fprintf(stdout, "proto = %d\n", said_af_array[i].said.proto); fprintf(stdout, "spi = %08x\n", said_af_array[i].said.spi); addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stdout, "edst = %s\n", ipaddr_txt); } } if(debug) { fprintf(stdout, "Opening pfkey socket.\n"); } if((pfkey_sock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2) ) < 0) { fprintf(stderr, "%s: Trouble opening PF_KEY family socket with error: ", program_name); switch(errno) { case ENOENT: fprintf(stderr, "device does not exist. See FreeS/WAN installation procedure.\n"); break; case EACCES: fprintf(stderr, "access denied. "); if(getuid() == 0) { fprintf(stderr, "Check permissions. Should be 600.\n"); } else { fprintf(stderr, "You must be root to open this file.\n"); } break; case EUNATCH: fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n"); break; case ENODEV: fprintf(stderr, "KLIPS not loaded or enabled.\n"); break; case EBUSY: fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. Please report as much detail as possible to development team.\n"); break; case EINVAL: fprintf(stderr, "Invalid argument, KLIPS not loaded or check kernel log messages for specifics.\n"); break; case ENOBUFS: fprintf(stderr, "No kernel memory to allocate SA.\n"); break; case ESOCKTNOSUPPORT: fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n"); break; case EEXIST: fprintf(stderr, "SA already in use. Delete old one first.\n"); break; case ENXIO: fprintf(stderr, "SA does not exist. Cannot delete.\n"); break; case EAFNOSUPPORT: fprintf(stderr, "KLIPS not loaded or enabled.\n"); break; default: fprintf(stderr, "Unknown file open error %d. Please report as much detail as possible to development team.\n", errno); } exit(1); } for(i = 0; i < (((nspis - 1) < 2) ? 1 : (nspis - 1)); i++) { if(debug) { fprintf(stdout, "processing %dth pfkey message.\n", i); } pfkey_extensions_init(extensions); for(j = 0; j < ((nspis == 1) ? 1 : 2); j++) { if(debug) { fprintf(stdout, "processing %dth said of %dth pfkey message.\n", j, i); } /* Build an SADB_X_GRPSA message to send down. */ /* It needs <base, SA, SA2, address(D,D2) > minimum. */ if(!j) { if((error = pfkey_msg_hdr_build(&extensions[0], SADB_X_GRPSA, proto2satype(said_af_array[i].said.proto), 0, ++pfkey_seq, getpid()))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", program_name, error); pfkey_extensions_free(extensions); exit(1); } } else { if(debug) { fprintf(stdout, "setting x_satype proto=%d satype=%d\n", said_af_array[i+j].said.proto, proto2satype(said_af_array[i+j].said.proto) ); } if((error = pfkey_x_satype_build(&extensions[SADB_X_EXT_SATYPE2], proto2satype(said_af_array[i+j].said.proto) ))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", program_name, error); pfkey_extensions_free(extensions); exit(1); } } if((error = pfkey_sa_build(&extensions[!j ? SADB_EXT_SA : SADB_X_EXT_SA2], !j ? SADB_EXT_SA : SADB_X_EXT_SA2, said_af_array[i+j].said.spi, /* in network order */ 0, 0, 0, 0, 0))) { fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n", program_name, error); pfkey_extensions_free(extensions); exit(1); } #if 0 if(!j) { anyaddr(said_af_array[i].af, &pfkey_address_s_ska); /* Is the address family correct ?? */ if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, 0, sockaddrof(&pfkey_address_s_ska)))) { addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n", program_name, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } } #endif if((error = pfkey_address_build(&extensions[!j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2], !j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2, 0, 0, sockaddrof(&said_af_array[i+j].said.dst)))) { addrtot(&said_af_array[i+j].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n", program_name, ipaddr_txt, 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", program_name, error); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); exit(1); } if((error = write(pfkey_sock, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) != pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN) { fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n", program_name, error, errno); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); switch(errno) { case EACCES: fprintf(stderr, "access denied. "); if(getuid() == 0) { fprintf(stderr, "Check permissions. Should be 600.\n"); } else { fprintf(stderr, "You must be root to open this file.\n"); } break; case EUNATCH: fprintf(stderr, "Netlink not enabled OR KLIPS not loaded.\n"); break; case EBUSY: fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. Please report as much detail as possible to development team.\n"); break; case EINVAL: fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n"); break; case ENODEV: fprintf(stderr, "KLIPS not loaded or enabled.\n"); fprintf(stderr, "No device?!?\n"); break; case ENOBUFS: fprintf(stderr, "No kernel memory to allocate SA.\n"); break; case ESOCKTNOSUPPORT: fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n"); break; case EEXIST: fprintf(stderr, "SA already in use. Delete old one first.\n"); break; case ENOENT: fprintf(stderr, "device does not exist. See FreeS/WAN installation procedure.\n"); break; case ENXIO: fprintf(stderr, "SA does not exist. Cannot delete.\n"); break; default: fprintf(stderr, "Unknown socket write error %d. Please report as much detail as possible to development team.\n", errno); } exit(1); } if(pfkey_msg) { pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); } } (void) close(pfkey_sock); /* close the socket */ exit(0); }
const char *ipstr(const ip_address *src, ipstr_buf *b) { addrtot(src, 0, b->private_buf, sizeof(b->private_buf)); return b->private_buf; }
void confwrite_side(FILE *out, struct starter_conn *conn, struct starter_end *end, char *side) { char databuf[2048]; /* good for a 12288 bit rsa key */ int keyingtype; if(conn->manualkey) { keyingtype=kv_manual; } else { keyingtype=kv_auto; } switch(end->addrtype) { case KH_NOTSET: /* nothing! */ break; case KH_DEFAULTROUTE: fprintf(out, "\t%s=%%defaultroute\n",side); break; case KH_ANY: fprintf(out, "\t%s=%%any\n",side); break; case KH_IFACE: if(end->strings_set[KSCF_IP]) { fprintf(out, "\t%s=%s\n",side, end->strings[KSCF_IP]); } break; case KH_OPPO: fprintf(out, "\t%s=%%opportunistic\n",side); break; case KH_OPPOGROUP: fprintf(out, "\t%s=%%opportunisticgroup\n",side); break; case KH_GROUP: fprintf(out, "\t%s=%%group\n",side); break; case KH_IPHOSTNAME: if(end->strings_set[KSCF_IP]) { fprintf(out, "\t%s=%s\n",side, end->strings[KSCF_IP]); } break; case KH_IPADDR: addrtot(&end->addr, 0, databuf, ADDRTOT_BUF); fprintf(out, "\t%s=%s\n", side, databuf); break; } if(end->strings_set[KSCF_ID] && end->id) { fprintf(out, "\t%sid=\"%s\"\n", side, end->id); } switch(end->nexttype) { case KH_NOTSET: /* nothing! */ break; case KH_DEFAULTROUTE: fprintf(out, "\t%snexthop=%%defaultroute\n",side); break; case KH_IPADDR: addrtot(&end->nexthop, 0, databuf, ADDRTOT_BUF); fprintf(out, "\t%snexthop=%s\n", side, databuf); break; default: break; } if(end->has_client) { if(isvalidsubnet(&end->subnet) && (!subnetishost(&end->subnet) || !addrinsubnet(&end->addr, &end->subnet))) { subnettot(&end->subnet, 0, databuf, SUBNETTOT_BUF); fprintf(out, "\t%ssubnet=%s\n", side, databuf); } } if(end->rsakey1) { fprintf(out, "\t%srsakey=%s\n", side, end->rsakey1); } if(end->rsakey2) { fprintf(out, "\t%srsakey2=%s\n", side, end->rsakey2); } if(end->port || end->protocol) { char b2[32]; strcpy(b2, "%any"); strcpy(databuf, "%any"); if(end->port) { sprintf(b2, "%u", end->port); } if(end->protocol) { sprintf(databuf, "%u", end->protocol); } fprintf(out, "\t%sprotoport=%s/%s\n", side, databuf, b2); } if(end->cert) { fprintf(out, "\t%scert=%s\n", side, end->cert); } if(!isanyaddr(&end->sourceip)) { addrtot(&end->sourceip, 0, databuf, ADDRTOT_BUF); fprintf(out, "\t%ssourceip=%s\n", side, databuf); } confwrite_int(out, side, kv_conn|kv_leftright, keyingtype, end->options, end->options_set, end->strings); confwrite_str(out, side, kv_conn|kv_leftright, keyingtype, end->strings, end->strings_set); }
/* open the per-peer log * * NOTE: this routine must not call our own logging facilities to report * an error since those routines are not re-entrant and such a call * would be recursive. */ static void open_peerlog(struct connection *c) { /* syslog(LOG_INFO, "opening log file for conn %s", c->name); */ if (c->log_file_name == NULL) { char peername[ADDRTOT_BUF], dname[ADDRTOT_BUF]; int peernamelen, lf_len; addrtot(&c->spd.that.host_addr, 'Q', peername, sizeof(peername)); peernamelen = strlen(peername); /* copy IP address, turning : and . into / */ { char ch, *p, *q; p = peername; q = dname; do { ch = *p++; if (ch == '.' || ch == ':') ch = '/'; *q++ = ch; } while (ch != '\0'); } lf_len = peernamelen * 2 + strlen(base_perpeer_logdir) + sizeof("//.log") + 1; c->log_file_name = alloc_bytes(lf_len, "per-peer log file name"); #if 0 fprintf(stderr, "base dir |%s| dname |%s| peername |%s|", base_perpeer_logdir, dname, peername); #endif snprintf(c->log_file_name, lf_len, "%s/%s/%s.log", base_perpeer_logdir, dname, peername); /* syslog(LOG_DEBUG, "conn %s logfile is %s", c->name, c->log_file_name); */ } /* now open the file, creating directories if necessary */ c->log_file_err = !ensure_writeable_parent_directory(c->log_file_name); if (c->log_file_err) return; c->log_file = fopen(c->log_file_name, "w"); if (c->log_file == NULL) { if (c->log_file_err) { syslog(LOG_CRIT, "logging system can not open %s: %s", c->log_file_name, strerror(errno)); c->log_file_err = TRUE; } return; } /* look for a connection to close! */ while (perpeer_count >= MAX_PEERLOG_COUNT) { /* can not be NULL because perpeer_count > 0 */ passert(perpeer_list.cqh_last != (void *)&perpeer_list); perpeer_logclose(perpeer_list.cqh_last); } /* insert this into the list */ CIRCLEQ_INSERT_HEAD(&perpeer_list, c, log_link); passert(c->log_file != NULL); perpeer_count++; }
/* * receive and decode packet. * */ static void receive_ping(int afamily, int s, int reply, int natt) { ip_address sender; struct isakmp_hdr ih; char rbuf[256]; char buf[64]; int n, rport; unsigned int sendlen; const char *xchg_name; int xchg; u_int32_t tmp_ic[2], tmp_rc[2]; rport = 500; xchg = 0; sendlen=sizeof(sender); n = recvfrom(s, rbuf, sizeof(rbuf) , 0, (struct sockaddr *)&sender, (socklen_t *)&sendlen); memcpy(&ih, rbuf, sizeof(ih)); if(natt) { /* need to skip 4 bytes! */ if(rbuf[0]!=0x0 || rbuf[1]!=0x0 || rbuf[2]!=0x0 || rbuf[3]!=0x0) { printf("kernel failed to steal ESP packet (SPI=0x%02x%02x%02x%02x) of length %d\n" , rbuf[0], rbuf[1], rbuf[2], rbuf[3] , n); return; } /* otherwise, skip 4 bytes */ memcpy(&ih, rbuf+4, sizeof(ih)); } addrtot(&sender, 0, buf, sizeof(buf)); switch(afamily) { case AF_INET: rport = sender.u.v4.sin_port; break; case AF_INET6: rport = sender.u.v6.sin6_port; break; } if((unsigned int)n < sizeof(ih)) { fprintf(stderr, "read short packet (%d) from %s/%d\n", n, buf, rport); return; } /* translate from network byte order */ ntoh_ping(&ih); if(ih.isa_xchg == ISAKMP_XCHG_ECHOREQUEST || ih.isa_xchg == ISAKMP_XCHG_ECHOREQUEST_PRIVATE || (exchange_number!=0 && ih.isa_xchg == exchange_number)) { xchg_name="echo-request"; xchg=ISAKMP_XCHG_ECHOREQUEST; } else if(ih.isa_xchg == ISAKMP_XCHG_ECHOREPLY || ih.isa_xchg == ISAKMP_XCHG_ECHOREPLY_PRIVATE || (exchange_number!=0 && ih.isa_xchg == exchange_number+1)) { xchg_name="echo-reply"; } else { xchg_name=""; } printf("received %d(%s) packet from %s/%d of len: %d\n", ih.isa_xchg, xchg_name, buf, ntohs(rport), n); /* questionable: printing each cookie as if it were two uint32 values in host order */ memcpy(&tmp_ic, ih.isa_icookie, 2 * sizeof(u_int32_t)); memcpy(&tmp_rc, ih.isa_rcookie, 2 * sizeof(u_int32_t)); printf("\trcookie=%08x_%08x icookie=%08x_%08x msgid=%08x\n", tmp_ic[0], tmp_ic[1], tmp_rc[0], tmp_rc[1], ih.isa_msgid); printf("\tnp=%03d version=%d.%d xchg=%s(%d)\n", ih.isa_np, ih.isa_version >> ISA_MAJ_SHIFT, ih.isa_version & ISA_MIN_MASK, xchg_name, ih.isa_xchg); if(reply && xchg==ISAKMP_XCHG_ECHOREQUEST) { reply_packet(afamily, s, &sender, sendlen, &ih); } }
int main(int argc, char *argv[]) { int opt = 0; int all = 0; int search = 0; int typeexport = 0; int checkconfig = 0; int listroute=0, liststart=0; struct starter_config *cfg = NULL; err_t err = NULL; char *confdir = NULL; char *configfile = NULL; char *varprefix = ""; int exit_status = 0; struct starter_conn *conn = NULL; char *defaultroute = NULL; char *defaultnexthop = NULL; char *ctlbase = NULL; bool resolvip = FALSE; #if 0 /* efence settings */ extern int EF_PROTECT_BELOW; extern int EF_PROTECT_FREE; EF_PROTECT_BELOW=1; EF_PROTECT_FREE=1; #endif progname = argv[0]; rootdir[0]='\0'; tool_init_log(); while((opt = getopt_long(argc, argv, "", longopts, 0)) != EOF) { switch(opt) { case 'h': /* usage: */ usage(); break; case 'a': all=1; break; case 'D': verbose++; break; case 'W': warningsarefatal++; break; case 'S': search++; break; case 'T': typeexport++; break; case 'K': checkconfig++; break; case 'C': configfile = clone_str(optarg, "config file name"); break; case 'c': ctlbase = clone_str(optarg, "control base"); break; case 'A': all=1; break; case 'r': listroute=1; break; case 's': liststart=1; break; case 'P': varprefix=optarg; break; case 'R': printf("setting rootdir=%s\n", optarg); strncat(rootdir, optarg, sizeof(rootdir)-1); break; case 'd': defaultroute=optarg; break; case 'n': defaultnexthop=optarg; break; default: usage(); } } /* if nothing to add, then complain */ if(optind == argc && !all && !listroute && !liststart && !search && !typeexport && !checkconfig) { usage(); } if(verbose > 3) { extern int yydebug; yydebug=1; } /* find config file */ confdir = getenv(IPSEC_CONFDIR_VAR); if(confdir == NULL) { confdir = IPSEC_CONFDIR; } if(!configfile) { configfile = alloc_bytes(strlen(confdir)+sizeof("/ipsec.conf")+2,"conf file"); /* calculate default value for configfile */ configfile[0]='\0'; strcpy(configfile, confdir); if(configfile[strlen(configfile)-1]!='/') { strcat(configfile, "/"); } strcat(configfile, "ipsec.conf"); } if(verbose) { printf("opening file: %s\n", configfile); } starter_use_log (verbose, 1, verbose ? 0 : 1); err = NULL; /* reset to no error */ resolvip=TRUE; /* default to looking up names */ if(typeexport || checkconfig || listroute || liststart || search) { /* but not if we have no use for them... might cause delays too! */ resolvip=FALSE; } cfg = confread_load(configfile, &err, resolvip, ctlbase,typeexport); if(cfg == NULL) { fprintf(stderr, "can not load config '%s': %s\n", configfile, err); exit(3); } else if(checkconfig) { confread_free(cfg); exit(0); } if(defaultroute) { err_t e; char b[ADDRTOT_BUF]; e = ttoaddr(defaultroute, strlen(defaultroute), AF_INET, &cfg->dr); if(e) { printf("ignoring invalid defaultroute: %s\n", e); defaultroute = NULL; /* exit(4); */ } else if(verbose) { addrtot(&cfg->dr, 0, b, sizeof(b)); printf("default route is: %s\n", b); } } if(defaultnexthop) { err_t e; char b[ADDRTOT_BUF]; e = ttoaddr(defaultnexthop, strlen(defaultnexthop), AF_INET, &cfg->dnh); if(e) { printf("ignoring invalid defaultnexthop: %s\n", e); defaultnexthop = NULL; /* exit(4); */ } else if(verbose) { addrtot(&cfg->dnh, 0, b, sizeof(b)); printf("default nexthop is: %s\n", b); } } if(all) { if(verbose) { printf("loading all conns:"); } /* load all conns marked as auto=add or better */ for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_ADD || conn->desired_state == STARTUP_START || conn->desired_state == STARTUP_ROUTE) { if(verbose) printf(" %s", conn->name); starter_whack_add_conn(cfg, conn); } } if(verbose) printf("\n"); } else if(listroute) { if(verbose) { printf("listing all conns marked as auto=start\n"); } /* list all conns marked as auto=route or start or better */ for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START || conn->desired_state == STARTUP_ROUTE) { printf("%s ", conn->name); } } printf("\n"); } else if(liststart) { /* list all conns marked as auto=start */ for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if (conn->desired_state == STARTUP_START) { printf("%s ", conn->name); } } printf("\n"); } else if(search) { char *sep=""; if((argc-optind) < 2 ) { printf("%s_confreadstatus=failed\n", varprefix); confread_free(cfg); exit(3); } printf("%s_confreadstatus=\n", varprefix); printf("%s_confreadnames=\"",varprefix); /* find conn names that have value set */ for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { /* we recognize a limited set of values */ if(strcasecmp(argv[optind],"auto")==0 && strcasecmp(argv[optind+1],"manual")==0) { if(conn->manualkey) { printf("%s%s", sep, conn->name); sep=" "; } } } printf("\"\n"); confread_free(cfg); exit(0); } else if(typeexport) { struct keyword_def *kd; printf("export %sconfreadstatus=''\n", varprefix); for(kd=ipsec_conf_keywords_v2; kd->keyname != NULL; kd++) { if((kd->validity & kv_config)==0) continue; switch(kd->type) { case kt_string: case kt_filename: case kt_dirname: case kt_loose_enum: if(cfg->setup.strings[kd->field]) { printf("export %s%s='%s'\n", varprefix, kd->keyname, cfg->setup.strings[kd->field]); } break; case kt_bool: printf("export %s%s='%s'\n", varprefix, kd->keyname, cfg->setup.options[kd->field] ? "yes" : "no"); break; case kt_list: printf("export %s%s='", varprefix, kd->keyname); confwrite_list(stdout, "", cfg->setup.options[kd->field], kd); printf("'\n"); break; case kt_obsolete: printf("# obsolete option '%s%s' ignored\n", varprefix, kd->keyname); break; default: if(cfg->setup.options[kd->field] || cfg->setup.options_set[kd->field]) { printf("export %s%s='%d'\n", varprefix, kd->keyname, cfg->setup.options[kd->field]); } break; } } confread_free(cfg); exit(0); } else { /* load named conns, regardless of their state */ int connum; if(verbose) { printf("loading named conns:"); } for(connum = optind; connum<argc; connum++) { char *connname = argv[connum]; if(verbose) { printf(" %s", connname); } for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { /* yes, let's make it case-insensitive */ if(strcasecmp(conn->name, connname)==0) { if(conn->state == STATE_ADDED) { printf("\nconn %s already added\n", conn->name); } else if(conn->state == STATE_FAILED) { printf("\nconn %s did not load properly\n", conn->name); } else { exit_status = starter_whack_add_conn(cfg, conn); conn->state = STATE_ADDED; } break; } } if(conn == NULL) { /* only if we don't find it, do we now look for aliases */ for(conn = cfg->conns.tqh_first; conn != NULL; conn = conn->link.tqe_next) { if(conn->strings_set[KSF_CONNALIAS] && osw_alias_cmp(connname , conn->strings[KSF_CONNALIAS])) { if(conn->state == STATE_ADDED) { printf("\nalias: %s conn %s already added\n", connname, conn->name); } else if(conn->state == STATE_FAILED) { printf("\nalias: %s conn %s did not load properly\n", connname, conn->name); } else { exit_status = starter_whack_add_conn(cfg, conn); conn->state = STATE_ADDED; } break; } } } if(conn == NULL) { exit_status++; if(!verbose) { printf("conn '%s': not found (tried aliases)\n", connname); } else { printf("(notfound)"); } } } if(verbose) printf("\n"); } confread_free(cfg); exit(exit_status); }
/** * Validate that yes in fact we are one side of the tunnel * * The function checks that IP addresses are valid, nexthops are * present (if needed) as well as policies, and sets the leftID * from the left= if it isn't set. * * @param conn_st a connection definition * @param end a connection end * @param left boolean (are we 'left'? 1 = yes, 0 = no) * @param perr pointer to char containing error value * @return bool TRUE if failed */ static bool validate_end(struct starter_conn *conn_st , struct starter_end *end , bool left , bool resolvip UNUSED , err_t *perr) { err_t er = NULL; char *err_str = NULL; const char *leftright=(left ? "left" : "right"); int family = conn_st->options[KBF_CONNADDRFAMILY]; bool err = FALSE; #define ERR_FOUND(args...) do { err += error_append(&err_str, ##args); } while(0) if(!end->options_set[KNCF_IP]) { conn_st->state = STATE_INCOMPLETE; } end->addrtype=end->options[KNCF_IP]; end->addr_family = family; /* validate the KSCF_IP/KNCF_IP */ switch(end->addrtype) { case KH_ANY: anyaddr(family, &(end->addr)); break; case KH_IFACE: /* generally, this doesn't show up at this stage */ break; case KH_IPADDR: /* right=/left= */ assert(end->strings[KSCF_IP] != NULL); if (end->strings[KSCF_IP][0]=='%') { if (end->iface) pfree(end->iface); end->iface = clone_str(end->strings[KSCF_IP] + 1, "KH_IPADDR end->iface"); if (starter_iface_find(end->iface, family, &(end->addr), &(end->nexthop)) == -1) { conn_st->state = STATE_INVALID; } /* not numeric, so set the type to the iface type */ end->addrtype = KH_IFACE; break; } er = ttoaddr_num(end->strings[KNCF_IP], 0, family, &(end->addr)); if(er) { /* not numeric, so set the type to the string type */ end->addrtype = KH_IPHOSTNAME; } if(end->id == NULL) { char idbuf[ADDRTOT_BUF]; addrtot(&end->addr, 0, idbuf, sizeof(idbuf)); end->id= clone_str(idbuf, "end id"); } break; case KH_OPPO: conn_st->policy |= POLICY_OPPO; break; case KH_OPPOGROUP: conn_st->policy |= POLICY_OPPO|POLICY_GROUP; break; case KH_GROUP: conn_st->policy |= POLICY_GROUP; break; case KH_IPHOSTNAME: /* XXX */ break; case KH_DEFAULTROUTE: break; case KH_NOTSET: break; } /* validate the KSCF_SUBNET */ if(end->strings_set[KSCF_SUBNET]) { char *value = end->strings[KSCF_SUBNET]; if ( ((strlen(value)>=6) && (strncmp(value,"vhost:",6)==0)) || ((strlen(value)>=5) && (strncmp(value,"vnet:",5)==0)) ) { er = NULL; end->virt = clone_str(value, "end->virt"); } else { end->has_client = TRUE; er = ttosubnet(value, 0, 0, &(end->subnet)); } if (er) ERR_FOUND("bad subnet %ssubnet=%s [%s] family=%s", leftright, value, er, family2str(family)); } /* set nexthop address to something consistent, by default */ anyaddr(family, &end->nexthop); anyaddr(addrtypeof(&end->addr), &end->nexthop); /* validate the KSCF_NEXTHOP */ if(end->strings_set[KSCF_NEXTHOP]) { char *value = end->strings[KSCF_NEXTHOP]; if(strcasecmp(value, "%defaultroute")==0) { end->nexttype=KH_DEFAULTROUTE; } else { if (tnatoaddr(value, strlen(value), AF_INET, &(end->nexthop)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->nexthop)) != NULL) { er = ttoaddr(value, 0, family, &(end->nexthop)); if (er) ERR_FOUND("bad addr %snexthop=%s [%s]", leftright, value, er); } end->nexttype = KH_IPADDR; } } else { if (end->addrtype == KH_DEFAULTROUTE) { end->nexttype = KH_DEFAULTROUTE; } anyaddr(family, &end->nexthop); } /* validate the KSCF_ID */ if(end->strings_set[KSCF_ID]) { char *value = end->strings[KSCF_ID]; pfreeany(end->id); end->id = clone_str(value, "end->id"); } if(end->options_set[KSCF_RSAKEY1]) { end->rsakey1_type = end->options[KSCF_RSAKEY1]; end->rsakey2_type = end->options[KSCF_RSAKEY2]; switch(end->rsakey1_type) { case PUBKEY_DNS: case PUBKEY_DNSONDEMAND: end->key_from_DNS_on_demand = TRUE; break; default: end->key_from_DNS_on_demand = FALSE; /* validate the KSCF_RSAKEY1/RSAKEY2 */ if(end->strings[KSCF_RSAKEY1] != NULL) { char *value = end->strings[KSCF_RSAKEY1]; pfreeany(end->rsakey1); end->rsakey1 = (unsigned char *)clone_str(value,"end->rsakey1"); } if(end->strings[KSCF_RSAKEY2] != NULL) { char *value = end->strings[KSCF_RSAKEY2]; pfreeany(end->rsakey2); end->rsakey2 = (unsigned char *)clone_str(value,"end->rsakey2"); } } } /* validate the KSCF_SOURCEIP, if any, and if set, * set the subnet to same value, if not set. */ if(end->strings_set[KSCF_SOURCEIP]) { char *value = end->strings[KSCF_SOURCEIP]; if (tnatoaddr(value, strlen(value), AF_INET, &(end->sourceip)) != NULL && tnatoaddr(value, strlen(value), AF_INET6, &(end->sourceip)) != NULL) { er = ttoaddr(value, 0, 0, &(end->sourceip)); if (er) ERR_FOUND("bad addr %ssourceip=%s [%s]", leftright, value, er); } else { er = tnatoaddr(value, 0, 0, &(end->sourceip)); if (er) ERR_FOUND("bad numerical addr %ssourceip=%s [%s]", leftright, value, er); } if(!end->has_client) { starter_log(LOG_LEVEL_INFO, "defaulting %ssubnet to %s\n", leftright, value); er = addrtosubnet(&end->sourceip, &end->subnet); if (er) ERR_FOUND("attempt to default %ssubnet from %s failed: %s", leftright, value, er); end->has_client = TRUE; end->has_client_wildcard = FALSE; } } /* copy certificate path name */ if(end->strings_set[KSCF_CERT]) { end->cert = clone_str(end->strings[KSCF_CERT], "KSCF_CERT"); } if(end->strings_set[KSCF_CA]) { end->ca = clone_str(end->strings[KSCF_CA], "KSCF_CA"); } if(end->strings_set[KSCF_UPDOWN]) { end->updown = clone_str(end->strings[KSCF_UPDOWN], "KSCF_UPDOWN"); } if(end->strings_set[KSCF_PROTOPORT]) { err_t ugh; char *value = end->strings[KSCF_PROTOPORT]; ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &end->has_port_wildcard); if (ugh) ERR_FOUND("bad %sprotoport=%s [%s]", leftright, value, ugh); } if (end->options_set[KNCF_XAUTHSERVER] || end->options_set[KNCF_XAUTHCLIENT]) { conn_st->policy |= POLICY_XAUTH; } /* KSCF_SUBNETWITHIN --- not sure what to do with it. KSCF_ESPENCKEY --- todo (manual keying) KSCF_ESPAUTHKEY --- todo (manual keying) KSCF_SOURCEIP = 16, KSCF_MAX = 19 */ if(err) *perr = err_str; return err; # undef ERR_FOUND }
int main(int argc, char **argv) { char *foo; const char *errstr; int s; int listen_only; int lport,dport; int afamily; int pfamily; int c; int numSenders, numReceived; int natt; int waitTime; int verbose; ip_address laddr, raddr; char *afam = ""; progname = argv[0]; afamily=AF_INET; pfamily=PF_INET; lport=500; dport=500; waitTime=3*1000; verbose=0; natt=0; listen_only=0; bzero(&laddr, sizeof(laddr)); while((c = getopt_long(argc, argv, "hVvsp:b:46E:w:", long_opts, 0))!=EOF) { switch (c) { case 'h': /* --help */ help(); return 0; /* GNU coding standards say to stop here */ case 'V': /* --version */ fprintf(stderr, "Openswan %s\n", ipsec_version_code()); return 0; /* GNU coding standards say to stop here */ case 'v': /* --label <string> */ verbose++; continue; case 'T': natt++; break; case 'E': exchange_number=strtol(optarg, &foo, 0); if(optarg==foo || exchange_number < 1 || exchange_number>255) { fprintf(stderr, "Invalid exchange number '%s' (should be 1<=x<255)\n", optarg); exit(1); } continue; case 's': listen_only++; continue; case 'p': lport=strtol(optarg, &foo, 0); if(optarg==foo || lport <0 || lport>65535) { fprintf(stderr, "Invalid port number '%s' (should be 0<=x<65536)\n", optarg); exit(1); } fprintf(stderr, "setting source port to %u\n", lport); continue; case 'w': /* convert msec to sec */ waitTime=strtol(optarg, &foo, 0)*500; if(optarg==foo || waitTime < 0) { fprintf(stderr, "Invalid waittime number '%s' (should be 0<=x)\n", optarg); exit(1); } continue; case 'b': errstr = ttoaddr(optarg, strlen(optarg), afamily, &laddr); if(errstr!=NULL) { fprintf(stderr, "Invalid local address '%s': %s\n", optarg, errstr); exit(1); } continue; case '4': afamily=AF_INET; pfamily=PF_INET; afam = "IPv4"; continue; case '6': afamily=AF_INET6; pfamily=PF_INET6; afam = "IPv6"; continue; default: help(); } } s=safe_socket(pfamily, SOCK_DGRAM, IPPROTO_UDP); if(s < 0) { perror("socket"); exit(3); } switch(afamily) { case AF_INET: laddr.u.v4.sin_family= AF_INET; laddr.u.v4.sin_port = htons(lport); if(bind(s, (struct sockaddr *)&laddr.u.v4, sizeof(laddr.u.v4)) < 0) { fprintf(stderr, "warning, unable to bind v4 socket port %u: %s" , lport, strerror(errno)); } break; case AF_INET6: laddr.u.v6.sin6_family= AF_INET6; laddr.u.v6.sin6_port = htons(lport); if(bind(s, (struct sockaddr *)&laddr.u.v6, sizeof(laddr.u.v6)) < 0) { fprintf(stderr, "warning, unable to bind v6 socket to port %u: %s" , lport, strerror(errno)); } break; } if(natt) { int r; /* only support RFC method */ int type = ESPINUDP_WITH_NON_ESP; r = setsockopt(s, SOL_UDP, UDP_ESPINUDP, &type, sizeof(type)); if ((r<0) && (errno == ENOPROTOOPT)) { fprintf(stderr, "NAT-Traversal: ESPINUDP(%d) not supported by kernel for family %s" , type, afam); } } numSenders = 0; if(!listen_only) { while(optind < argc) { char *port; char *host; char namebuf[128]; host = argv[optind]; port = strchr(host, '/'); dport=500; if(port) { *port='\0'; port++; dport= strtol(port, &foo, 0); if(port==foo || dport < 0 || dport > 65535) { fprintf(stderr, "Invalid port number '%s' " "(should be 0<=x<65536)\n", port); exit(1); } } errstr = ttoaddr(host, strlen(host), afamily, &raddr); if(errstr!=NULL) { fprintf(stderr, "Invalid remote address '%s': %s\n", host, errstr); exit(1); } addrtot(&raddr, 0, namebuf, sizeof(namebuf)); printf("Sending packet to %s/%d\n", namebuf, dport); send_ping(afamily, s, &raddr, dport); numSenders++; optind++; } } numReceived=0; /* really should catch ^C and print stats on exit */ while(numSenders > 0 || listen_only) { struct pollfd ready; int n; ready.fd = s; ready.events = POLLIN; n = poll(&ready, 1, waitTime); if(n < 0) { if(errno != EINTR) { perror("poll"); exit(1); } } if(n == 0 && !listen_only) { break; } if(n == 1) { numReceived++; receive_ping(afamily, s, listen_only, natt); } } printf("%d packets sent, %d packets received. %d%% packet loss\n", numSenders, numReceived, numSenders > 0 ? 100-numReceived*100/numSenders : 0); exit(numSenders - numReceived); }
static void klips_process_raw_ifaces(struct raw_iface *rifaces) { struct raw_iface *ifp; /* Find all virtual/real interface pairs. * For each real interface... */ for (ifp = rifaces; ifp != NULL; ifp = ifp->next) { struct raw_iface *v = NULL; /* matching ipsecX interface */ struct raw_iface fake_v; bool after = FALSE; /* has vfp passed ifp on the list? */ bool bad = FALSE; struct raw_iface *vfp; ip_address lip; if (pluto_listen) { err_t e; e = ttoaddr(pluto_listen, 0, 0, &lip); if (e) { DBG_log("invalid listen= option ignored: %s\n", e); pluto_listen = NULL; } } /* ignore if virtual (ipsec*) interface */ if (strncmp(ifp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX) - 1) == 0) continue; /* ignore if virtual (mast*) interface */ if (strncmp(ifp->name, MASTDEVPREFIX, sizeof(MASTDEVPREFIX) - 1) == 0) continue; for (vfp = rifaces; vfp != NULL; vfp = vfp->next) { if (vfp == ifp) { after = TRUE; } else if (sameaddr(&ifp->addr, &vfp->addr)) { /* Different entries with matching IP addresses. * Many interesting cases. */ if (strncmp(vfp->name, IPSECDEVPREFIX, sizeof(IPSECDEVPREFIX) - 1) == 0) { if (v != NULL) { loglog(RC_LOG_SERIOUS, "ipsec interfaces %s and %s share same address %s", v->name, vfp->name, ip_str(&ifp->addr)); bad = TRUE; } else { v = vfp; /* current winner */ } } else { /* ugh: a second real interface with the same IP address * "after" allows us to avoid double reporting. */ #if defined(linux) && defined(NETKEY_SUPPORT) if (kern_interface == USE_NETKEY) { if (after) { bad = TRUE; break; } continue; } #endif if (after) { loglog(RC_LOG_SERIOUS, "IP interfaces %s and %s share address %s!", ifp->name, vfp->name, ip_str(&ifp->addr)); } bad = TRUE; } } } if (bad) continue; #if defined(linux) && defined(NETKEY_SUPPORT) if (kern_interface == USE_NETKEY) { v = ifp; goto add_entry; } #endif /* what if we didn't find a virtual interface? */ if (v == NULL) { if (kern_interface == NO_KERNEL) { /* kludge for testing: invent a virtual device */ static const char fvp[] = "virtual"; fake_v = *ifp; passert(sizeof(fake_v.name) > sizeof(fvp)); strcpy(fake_v.name, fvp); addrtot(&ifp->addr, 0, fake_v.name + sizeof(fvp) - 1, sizeof(fake_v.name) - (sizeof(fvp) - 1)); v = &fake_v; } else { DBG(DBG_CONTROL, DBG_log( "IP interface %s %s has no matching ipsec* interface -- ignored", ifp->name, ip_str(&ifp->addr))); continue; } } /* ignore if --listen is specified and we do not match */ if (pluto_listen != NULL) { if (!sameaddr(&lip, &ifp->addr)) { libreswan_log("skipping interface %s with %s", ifp->name, ip_str(&ifp->addr)); continue; } } /* We've got all we need; see if this is a new thing: * search old interfaces list. */ #if defined(linux) && defined(NETKEY_SUPPORT) add_entry: #endif { struct iface_port **p = &interfaces; for (;; ) { struct iface_port *q = *p; struct iface_dev *id = NULL; /* search is over if at end of list */ if (q == NULL) { /* matches nothing -- create a new entry */ int fd = create_socket(ifp, v->name, pluto_port); if (fd < 0) break; DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: checking for nat_traversal_support_non_ike for IPv4")); if (nat_traversal_support_non_ike && addrtypeof(&ifp->addr) == AF_INET) { DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: found, calling nat_traversal_espinudp_socket")); nat_traversal_espinudp_socket( fd, "IPv4", ESPINUDP_WITH_NON_IKE); } else { DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: support not found, nat_traversal_support_non_ike = %s", nat_traversal_support_non_ike ? "TRUE" : "FALSE")); } q = alloc_thing(struct iface_port, "struct iface_port"); id = alloc_thing(struct iface_dev, "struct iface_dev"); LIST_INSERT_HEAD(&interface_dev, id, id_entry); q->ip_dev = id; id->id_rname = clone_str(ifp->name, "real device name"); id->id_vname = clone_str(v->name, "virtual device name klips"); id->id_count++; q->ip_addr = ifp->addr; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->port = pluto_port; q->ike_float = FALSE; interfaces = q; libreswan_log( "adding interface %s/%s %s:%d", q->ip_dev->id_vname, q->ip_dev->id_rname, ip_str(&q->ip_addr), q->port); /* * right now, we do not support NAT-T on IPv6, because * the kernel did not support it, and gave an error * it one tried to turn it on. */ if (nat_traversal_support_port_floating && addrtypeof(&ifp->addr) == AF_INET) { DBG(DBG_NATT, DBG_log( "NAT-T KLIPS: found floating port, calling nat_traversal_espinudp_socket")); fd = create_socket(ifp, v->name, pluto_natt_float_port); if (fd < 0) break; nat_traversal_espinudp_socket( fd, "IPv4", ESPINUDP_WITH_NON_ESP); q = alloc_thing( struct iface_port, "struct iface_port"); q->ip_dev = id; id->id_count++; q->ip_addr = ifp->addr; setportof(htons( pluto_natt_float_port), &q->ip_addr); q->port = pluto_natt_float_port; q->fd = fd; q->next = interfaces; q->change = IFN_ADD; q->ike_float = TRUE; interfaces = q; libreswan_log( "adding interface %s/%s %s:%d", q->ip_dev->id_vname, q->ip_dev->id_rname, ip_str(&q-> ip_addr), q->port); } break; } /* search over if matching old entry found */ if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, v->name) && sameaddr(&q->ip_addr, &ifp->addr)) { /* matches -- rejuvinate old entry */ q->change = IFN_KEEP; /* look for other interfaces to keep (due to NAT-T) */ for (q = q->next; q; q = q->next) { if (streq(q->ip_dev->id_rname, ifp->name) && streq(q->ip_dev->id_vname, v->name) && sameaddr(&q->ip_addr, &ifp->addr)) q->change = IFN_KEEP; } break; } /* try again */ p = &q->next; } /* for (;;) */ }
/* * discover the default route via /proc/net/route */ void get_defaultroute(defaultroute_t *defaultroute) { FILE *fd; char line[BUF_LEN]; bool first = TRUE; init_defaultroute(defaultroute); fd = fopen("/proc/net/route", "r"); if (!fd) { plog("could not open 'proc/net/route'"); return; } while (fgets(line, sizeof(line), fd) != 0) { char iface[11]; char destination[9]; char gateway[11]; char flags[5]; char mask[9]; int refcnt; int use; int metric; int items; /* proc/net/route returns IP addresses in host order */ strcpy(gateway, "0h"); /* skip the header line */ if (first) { first = FALSE; continue; } /* parsing a single line of proc/net/route */ items = sscanf(line, "%10s\t%8s\t%8s\t%5s\t%d\t%d\t%d\t%8s\t" , iface, destination, gateway+2, flags, &refcnt, &use, &metric, mask); if (items < 8) { plog("parsing error while scanning /proc/net/route"); continue; } /* check for defaultroute (destination 0.0.0.0 and mask 0.0.0.0) */ if (streq(destination, "00000000") && streq(mask, "00000000")) { if (defaultroute->defined) { plog("multiple default routes - cannot cope with %%defaultroute!!!"); defaultroute->defined = FALSE; fclose(fd); return; } ttoaddr(gateway, strlen(gateway), AF_INET, &defaultroute->nexthop); strncpy(defaultroute->iface, iface, IFNAMSIZ); defaultroute->defined = TRUE; } } fclose(fd); if (!defaultroute->defined) { plog("no default route - cannot cope with %%defaultroute!!!"); } else { char addr_buf[20], nexthop_buf[20]; struct ifreq physreq; int sock = socket(AF_INET, SOCK_DGRAM, 0); /* determine IP address of iface */ if (sock < 0) { plog("could not open SOCK_DGRAM socket"); defaultroute->defined = FALSE; return; } memset ((void*)&physreq, 0, sizeof(physreq)); strncpy(physreq.ifr_name, defaultroute->iface, IFNAMSIZ); ioctl(sock, SIOCGIFADDR, &physreq); close(sock); defaultroute->addr.u.v4 = *((struct sockaddr_in *)&physreq.ifr_addr); addrtot(&defaultroute->addr, 0, addr_buf, sizeof(addr_buf)); addrtot(&defaultroute->nexthop, 0, nexthop_buf, sizeof(nexthop_buf)); DBG(DBG_CONTROL, DBG_log("Default route found: iface=%s, addr=%s, nexthop=%s" , defaultroute->iface, addr_buf, nexthop_buf) ) /* for backwards-compatibility with the awk shell scripts * store the defaultroute in /var/run/ipsec.info */ fd = fopen(INFO_FILE, "w"); if (fd) { fprintf(fd, "defaultroutephys=%s\n", defaultroute->iface ); fprintf(fd, "defaultroutevirt=ipsec0\n"); fprintf(fd, "defaultrouteaddr=%s\n", addr_buf); fprintf(fd, "defaultroutenexthop=%s\n", nexthop_buf); fclose(fd); } } return; }
/** Lookup information about the hostpair, and set things like bandwidth * relative crypto strength, compression and credentials. * * @param IPsec Policy Query * @return void */ static void info_lookuphostpair(struct ipsec_policy_cmd_query *ipcq) { struct connection *c; struct state *p1st, *p2st; /* default result: no crypto */ ipcq->strength = IPSEC_PRIVACY_NONE; ipcq->bandwidth = IPSEC_QOS_WIRESPEED; ipcq->credential_count = 0; #ifdef DEBUG { char sstr[ADDRTOT_BUF], dstr[ADDRTOT_BUF]; addrtot(&ipcq->query_local, 0, sstr, sizeof(sstr)); addrtot(&ipcq->query_remote, 0, dstr, sizeof(dstr)); DBG_log("info request for %s -> %s", sstr, dstr); } #endif /* okay, look up what connection handles this ip pair */ c = find_connection_for_clients(NULL, &ipcq->query_local, &ipcq->query_remote, ipcq->proto); if (c == NULL) { /* try reversing it */ c = find_connection_for_clients(NULL, &ipcq->query_remote, &ipcq->query_local, ipcq->proto); if (c != NULL) { ip_address tmp; /* If it is reversed, swap it */ tmp = ipcq->query_local; ipcq->query_local = ipcq->query_remote; ipcq->query_remote = tmp; } } if (c == NULL) { #ifdef DEBUG DBG_log("no connection found"); #endif return; /* no crypto */ } if (c->newest_ipsec_sa == SOS_NOBODY) { ip_subnet us, them; DBG_log("connection %s found, no ipsec state, looking again", c->name); addrtosubnet(&ipcq->query_local, &us); addrtosubnet(&ipcq->query_remote, &them); c = find_client_connection(c, &us, &them, 0, 0, 0, 0); if (c == NULL) return; /* no crypto */ } DBG_log("connection %s[%ld] with state %u" , c->name, c->instance_serial , (unsigned int)c->newest_ipsec_sa); if (c->newest_ipsec_sa == SOS_NOBODY) return; /* no crypto */ /* we found a connection, try to lookup the state */ p2st = state_with_serialno(c->newest_ipsec_sa); p1st = find_phase1_state(c, ISAKMP_SA_ESTABLISHED_STATES); if (p1st == NULL || p2st == NULL) { DBG_log("connection %s[%ld] has missing states %s %s" , c->name, c->instance_serial , (p1st ? "phase1" : "") , (p2st ? "phase1" : "")); return; /* no crypto */ } /* if we have AH present, then record minimal info */ if (p2st->st_ah.present) { ipcq->strength = IPSEC_PRIVACY_INTEGRAL; ipcq->auth_detail = p2st->st_esp.attrs.transattrs.integ_hash; } if (p2st->st_esp.present) { /* * XXX-mcr Please do not shout at me about relative strengths * here. I'm not a cryptographer. I just diddle bits. */ switch (p2st->st_esp.attrs.transattrs.encrypt) { case ESP_NULL: /* actually, do not change it if we set it from AH */ break; case ESP_DES: case ESP_DES_IV64: case ESP_DES_IV32: case ESP_RC4: ipcq->strength = IPSEC_PRIVACY_ROT13; break; case ESP_RC5: case ESP_IDEA: case ESP_CAST: case ESP_BLOWFISH: case ESP_3DES: ipcq->strength = IPSEC_PRIVACY_PRIVATE; ipcq->bandwidth = IPSEC_QOS_VOIP; break; case ESP_3IDEA: ipcq->strength = IPSEC_PRIVACY_STRONG; ipcq->bandwidth = IPSEC_QOS_INTERACTIVE; break; case ESP_AES: ipcq->strength = IPSEC_PRIVACY_STRONG; ipcq->bandwidth = IPSEC_QOS_FTP; break; } ipcq->esp_detail = p2st->st_esp.attrs.transattrs.encrypt; } if (p2st->st_ipcomp.present) ipcq->comp_detail = p2st->st_esp.attrs.transattrs.encrypt; /* now! the credentails that were used */ /* for the moment we only have 1 credential, the DNS name, * because the DNS servers do not return the chain of SIGs yet */ if(!c->spd.this.key_from_DNS_on_demand) { /* the key didn't come from the DNS in some way, * so it must have been loaded locally. */ ipcq->credential_count = 1; ipcq->credentials[0].ii_type = c->spd.this.id.kind; ipcq->credentials[0].ii_format = CERT_RAW_RSA; } #if 0 switch (c->spd.id.kind) { case ID_IPV4_ADDR: } if (c->gw_info == NULL) { plog("rcv_info: connection %s had NULL gw_info.", c->name); return } #endif ipcq->credential_count = 1; /* pull credentials out of gw_info */ switch (p1st->st_peer_pubkey->dns_auth_level) { case DAL_UNSIGNED: case DAL_NOTSEC: /* these seem to be the same for this purpose */ ipcq->credentials[0].ii_type = p1st->st_peer_pubkey->id.kind; ipcq->credentials[0].ii_type = CERT_NONE; idtoa(&p1st->st_peer_pubkey->id , ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn , sizeof(ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn)); break; case DAL_SIGNED: ipcq->credentials[0].ii_type = p1st->st_peer_pubkey->id.kind; ipcq->credentials[0].ii_format = CERT_DNS_SIGNED_KEY; idtoa(&p1st->st_peer_pubkey->id , ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn , sizeof(ipcq->credentials[0].ii_credential.ipsec_dns_signed.fqdn)); if (p1st->st_peer_pubkey->dns_sig != NULL) { strncat(ipcq->credentials[0].ii_credential.ipsec_dns_signed.dns_sig , p1st->st_peer_pubkey->dns_sig , sizeof(ipcq->credentials[0].ii_credential.ipsec_dns_signed.dns_sig) - strlen(ipcq->credentials[0].ii_credential.ipsec_dns_signed.dns_sig -1)); } break; case DAL_LOCAL: ipcq->credentials[0].ii_type = p1st->st_peer_pubkey->id.kind; ipcq->credentials[0].ii_format = CERT_RAW_RSA; idtoa(&p1st->st_peer_pubkey->id , ipcq->credentials[0].ii_credential.ipsec_raw_key.id_name , sizeof(ipcq->credentials[0].ii_credential.ipsec_raw_key.id_name)); break; } }
int main(int argc, char **argv) { int i, nspis; char *endptr; int said_opt = 0; const char* error_s = NULL; char ipaddr_txt[ADDRTOT_BUF]; int j; struct said_af said_af_array[4]; int error = 0; struct stat sts; struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg; #if 0 ip_address pfkey_address_s_ska; #endif progname = argv[0]; for(i = 0; i < 4; i++) { memset(&said_af_array[i], 0, sizeof(struct said_af)); } if(argc > 1 && strcmp(argv[1], "--debug") == 0) { debug = 1; if(debug) { fprintf(stdout, "\"--debug\" option requested.\n"); } argv += 1; argc -= 1; pfkey_lib_debug = PF_KEY_DEBUG_PARSE_MAX; } if(debug) { fprintf(stdout, "argc=%d (%d incl. --debug option).\n", argc, argc + 1); } if(argc > 1 && strcmp(argv[1], "--label") == 0) { if(argc > 2) { progname = malloc(strlen(argv[0]) + 10 /* update this when changing the sprintf() */ + strlen(argv[2])); sprintf(progname, "%s --label %s", argv[0], argv[2]); if(debug) { fprintf(stdout, "using \"%s\" as a label.\n", progname); } argv += 2; argc -= 2; } else { fprintf(stderr, "%s: --label option requires an argument.\n", progname); exit(1); } } if(debug) { fprintf(stdout, "...After check for --label option.\n"); } if ( ((stat ("/proc/net/pfkey", &sts)) == 0) ) { fprintf(stderr, "%s: NETKEY does not use the ipsec spigrp command. Use 'ip xfrm' instead.\n",progname); exit(1); } if(argc == 1) { int ret = 1; if ((stat ("/proc/net/ipsec_spigrp", &sts)) != 0) { fprintf(stderr, "%s: No spigrp - no IPsec support in kernel (are the modules loaded?)\n", progname); } else { ret = system("cat /proc/net/ipsec_spigrp"); ret = ret != -1 && WIFEXITED(ret) ? WEXITSTATUS(ret) : 1; } exit(ret); } if(debug) { fprintf(stdout, "...After check for no option to print /proc/net/ipsec_spigrp.\n"); } if(strcmp(argv[1], "--help") == 0) { if(debug) { fprintf(stdout, "\"--help\" option requested.\n"); } usage(progname); exit(1); } if(debug) { fprintf(stdout, "...After check for --help option.\n"); } if(strcmp(argv[1], "--version") == 0) { if(debug) { fprintf(stdout, "\"--version\" option requested.\n"); } fprintf(stderr, "%s, %s\n", progname, ipsec_version_code()); exit(1); } if(debug) { fprintf(stdout, "...After check for --version option.\n"); } if(strcmp(argv[1], "--said") == 0) { if(debug) { fprintf(stdout, "processing %d args with --said flag.\n", argc); } said_opt = 1; } if(debug) { fprintf(stdout, "...After check for --said option.\n"); } if(said_opt) { if (argc < 3 /*|| argc > 5*/) { fprintf(stderr, "expecting 3 or more args with --said, got %d.\n", argc); usage(progname); exit(1); } nspis = argc - 2; } else { if ((argc < 5) || (argc > 17) || ((argc % 4) != 1)) { fprintf(stderr, "expecting 5 or more args without --said, got %d.\n", argc); usage(progname); exit(1); } nspis = argc / 4; } if(debug) { fprintf(stdout, "processing %d nspis.\n", nspis); } for(i = 0; i < nspis; i++) { if(debug) { fprintf(stdout, "processing spi #%d.\n", i); } if(said_opt) { error_s = ttosa((const char *)argv[i+2], 0, (ip_said*)&(said_af_array[i].said)); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n", progname, error_s, argv[i+2]); exit (1); } said_af_array[i].af = addrtypeof(&(said_af_array[i].said.dst)); if(debug) { addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stdout, "said[%d].dst=%s.\n", i, ipaddr_txt); } } else { if(!strcmp(argv[i*4+4], "ah")) { said_af_array[i].said.proto = SA_AH; } if(!strcmp(argv[i*4+4], "esp")) { said_af_array[i].said.proto = SA_ESP; } if(!strcmp(argv[i*4+4], "tun")) { said_af_array[i].said.proto = SA_IPIP; } if(!strcmp(argv[i*4+4], "comp")) { said_af_array[i].said.proto = SA_COMP; } if(said_af_array[i].said.proto == 0) { fprintf(stderr, "%s: Badly formed proto: %s\n", progname, argv[i*4+4]); exit(1); } said_af_array[i].said.spi = htonl(strtoul(argv[i*4+3], &endptr, 0)); if(!(endptr == argv[i*4+3] + strlen(argv[i*4+3]))) { fprintf(stderr, "%s: Badly formed spi: %s\n", progname, argv[i*4+3]); exit(1); } if(!strcmp(argv[i*4+1], "inet")) { said_af_array[i].af = AF_INET; } if(!strcmp(argv[i*4+1], "inet6")) { said_af_array[i].af = AF_INET6; } if((said_af_array[i].af != AF_INET) && (said_af_array[i].af != AF_INET6)) { fprintf(stderr, "%s: Address family %s not supported\n", progname, argv[i*4+1]); exit(1); } error_s = ttoaddr(argv[i*4+2], 0, said_af_array[i].af, &(said_af_array[i].said.dst)); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting %dth address argument:%s\n", progname, error_s, i, argv[i*4+2]); exit (1); } } if(debug) { fprintf(stdout, "SA %d contains: ", i+1); fprintf(stdout, "\n"); fprintf(stdout, "proto = %d\n", said_af_array[i].said.proto); fprintf(stdout, "spi = %08x\n", said_af_array[i].said.spi); addrtot(&said_af_array[i].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stdout, "edst = %s\n", ipaddr_txt); } } if(debug) { fprintf(stdout, "Opening pfkey socket.\n"); } pfkey_sock = pfkey_open_sock_with_error(); if(pfkey_sock < 0) { exit(1); } for(i = 0; i < (((nspis - 1) < 2) ? 1 : (nspis - 1)); i++) { if(debug) { fprintf(stdout, "processing %dth pfkey message.\n", i); } pfkey_extensions_init(extensions); for(j = 0; j < ((nspis == 1) ? 1 : 2); j++) { if(debug) { fprintf(stdout, "processing %dth said of %dth pfkey message.\n", j, i); } /* Build an SADB_X_GRPSA message to send down. */ /* It needs <base, SA, SA2, address(D,D2) > minimum. */ if(!j) { if((error = pfkey_msg_hdr_build(&extensions[0], K_SADB_X_GRPSA, proto2satype(said_af_array[i].said.proto), 0, ++pfkey_seq, getpid()))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } } else { if(debug) { fprintf(stdout, "setting x_satype proto=%d satype=%d\n", said_af_array[i+j].said.proto, proto2satype(said_af_array[i+j].said.proto) ); } if((error = pfkey_x_satype_build(&extensions[K_SADB_X_EXT_SATYPE2], proto2satype(said_af_array[i+j].said.proto) ))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } } if((error = pfkey_sa_build(&extensions[!j ? K_SADB_EXT_SA : K_SADB_X_EXT_SA2], !j ? K_SADB_EXT_SA : K_SADB_X_EXT_SA2, said_af_array[i+j].said.spi, /* in network order */ 0, 0, 0, 0, 0))) { fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } #if 0 if(!j) { anyaddr(said_af_array[i].af, &pfkey_address_s_ska); /* Is the address family correct ?? */ if((error = pfkey_address_build(&extensions[K_SADB_EXT_ADDRESS_SRC], K_SADB_EXT_ADDRESS_SRC, 0, 0, sockaddrof(&pfkey_address_s_ska)))) { addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } } #endif if((error = pfkey_address_build(&extensions[!j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2], !j ? SADB_EXT_ADDRESS_DST : SADB_X_EXT_ADDRESS_DST2, 0, 0, sockaddrof(&said_af_array[i+j].said.dst)))) { addrtot(&said_af_array[i+j].said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n", progname, ipaddr_txt, 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((error = write(pfkey_sock, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) { fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n", progname, error, errno); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); pfkey_write_error(error, errno); } if(pfkey_msg) { pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); } } (void) close(pfkey_sock); /* close the socket */ exit(0); }
int idtoa(const struct id *id, char *dst, size_t dstlen) { int n; id = resolve_myid(id); switch (id->kind) { case ID_MYID: n = snprintf(dst, dstlen, "%s", "%myid"); break; case ID_FROMCERT: n = snprintf(dst, dstlen, "%s", "%fromcert"); break; case ID_NONE: n = snprintf(dst, dstlen, "%s", "(none)"); break; case ID_IPV4_ADDR: case ID_IPV6_ADDR: if(isanyaddr(&id->ip_addr)) { dst[0]='\0'; strncat(dst, "%any", dstlen); n = strlen(dst); } else { n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1; } break; case ID_FQDN: n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr); break; case ID_USER_FQDN: n = snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr); break; case ID_DER_ASN1_DN: n = dntoa(dst, dstlen, id->name); break; case ID_KEY_ID: passert(dstlen > 4); dst[0]='@'; dst[1]='#'; dstlen-=2; dst+=2; n = keyidtoa(dst, dstlen, id->name); n+= 2; break; default: n = snprintf(dst, dstlen, "unknown id kind %d", id->kind); break; } /* "Sanitize" string so that log isn't endangered: * replace unprintable characters with '?'. */ if (n > 0) { for ( ; *dst != '\0'; dst++) if (!isprint(*dst)) *dst = '?'; } return n; }
/***************************************************************************************** 函数名称: dpd_inI_outR 功能描述: 处理R_U_THERE报文,判断R_U_THERE报文长度是否正确以及 通过序列号判断自己想要的报文 输入参数: p1st,n,pbs 输出参数: stf_status 返 回 值: 无 ------------------------------------------------------------------------------------------- 最近一次修改记录 : 修改作者: 王之云 修改目的: dpd_outI处理 修改日期: 2012年3月20日 ********************************************************************************************/ stf_status dpd_inI_outR(struct state *p1st, struct isakmp_notification *const n, pb_stream *pbs) { time_t tm = now(); u_int32_t seqno; char buf_remoteip[20] = {0}; EV_ADD ev_arg; addrtot(&p1st->st_remoteaddr, 0, buf_remoteip, sizeof(buf_remoteip)); if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state)) { return STF_IGNORE; } if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2) { IPSEC_log(IPSEC_LOGLEVEL_ERROR, "<%s> < %s > DPD Error: R_U_THERE has invalid SPI length (%d)", p1st->st_connection->name, buf_remoteip, n->isan_spisize); return STF_FAIL + PAYLOAD_MALFORMED; } if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0) { IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "DPD Warning: R_U_THERE has invalid icookie (broken Cisco?)"); } pbs->cur += COOKIE_SIZE; if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0) { IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "DPD Warning: R_U_THERE has invalid rcookie (broken Cisco?)"); } pbs->cur += COOKIE_SIZE; if (pbs_left(pbs) != sizeof(seqno)) { IPSEC_log(IPSEC_LOGLEVEL_ERROR, "<%s> < %s > DPD Error: R_U_THERE has invalid data length (%d)", p1st->st_connection->name, buf_remoteip, (int) pbs_left(pbs)); return STF_FAIL + PAYLOAD_MALFORMED; } seqno = ntohl(*(u_int32_t *)pbs->cur); if (p1st->st_dpd_peerseqno && seqno <= p1st->st_dpd_peerseqno) { IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "DPD Info: received old or duplicate R_U_THERE"); return STF_IGNORE; } DBG(DBG_DPD, DBG_log("received R_U_THERE seq:%u time:%lu (state=#%lu name=\"%s\")" , seqno , (unsigned long)tm , p1st->st_serialno, p1st->st_connection->name)); p1st->st_dpd_peerseqno = seqno; if (send_isakmp_notification(p1st, R_U_THERE_ACK , pbs->cur, pbs_left(pbs)) != STF_IGNORE) { IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "DPD Info: could not send R_U_THERE_ACK"); return STF_IGNORE; } p1st->st_last_dpd = tm; if(p1st->st_dpd_timeout_event != NULL) { ev_arg.u.st = p1st; disable_event(EVENT_DPD_TIMEOUT, &ev_arg); } return STF_IGNORE; }
static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token, kw_list_t *kw, char *conn_name, starter_config_t *cfg) { err_t ugh = NULL; bool assigned = FALSE; bool has_port_wildcard; /* set if port is %any */ char *name = kw->entry->name; char *value = kw->value; if (!assign_arg(token, KW_END_FIRST, kw, (char *)end, &assigned)) goto err; /* post processing of some keywords that were assigned automatically */ switch (token) { case KW_SUBNET: if ((strlen(value) >= 6 && strncmp(value,"vhost:",6) == 0) || (strlen(value) >= 5 && strncmp(value,"vnet:",5) == 0)) { /* used by pluto only */ end->has_virt = TRUE; } else { ip_subnet net; char *pos; int len = 0; end->has_client = TRUE; conn->tunnel_addr_family = ip_version(value); pos = strchr(value, ','); if (pos) { len = pos - value; } ugh = ttosubnet(value, len, ip_version(value), &net); if (ugh != NULL) { plog("# bad subnet: %s=%s [%s]", name, value, ugh); goto err; } } break; case KW_SOURCEIP: if (end->has_natip) { plog("# natip and sourceip cannot be defined at the same time"); goto err; } if (value[0] == '%') { if (streq(value, "%modeconfig") || streq(value, "%modecfg") || streq(value, "%config") || streq(value, "%cfg")) { /* request ip via config payload */ free(end->sourceip); end->sourceip = NULL; end->sourceip_mask = 1; } else { /* %poolname, strip %, serve ip requests */ free(end->sourceip); end->sourceip = clone_str(value+1); end->sourceip_mask = 0; } end->modecfg = TRUE; } else { char *pos; ip_address addr; ip_subnet net; conn->tunnel_addr_family = ip_version(value); pos = strchr(value, '/'); if (pos) { /* CIDR notation, address pool */ ugh = ttosubnet(value, 0, conn->tunnel_addr_family, &net); if (ugh != NULL) { plog("# bad subnet: %s=%s [%s]", name, value, ugh); goto err; } *pos = '\0'; free(end->sourceip); end->sourceip = clone_str(value); end->sourceip_mask = atoi(pos + 1); } else { /* fixed srcip */ ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); goto err; } end->sourceip_mask = (conn->tunnel_addr_family == AF_INET) ? 32 : 128; } } conn->policy |= POLICY_TUNNEL; break; case KW_SENDCERT: if (end->sendcert == CERT_YES_SEND) { end->sendcert = CERT_ALWAYS_SEND; } else if (end->sendcert == CERT_NO_SEND) { end->sendcert = CERT_NEVER_SEND; } break; default: break; } if (assigned) return; /* individual processing of keywords that were not assigned automatically */ switch (token) { case KW_HOST: if (streq(value, "%defaultroute")) { if (cfg->defaultroute.defined) { end->addr = cfg->defaultroute.addr; end->nexthop = cfg->defaultroute.nexthop; } else if (!cfg->defaultroute.supported) { plog("%%defaultroute not supported, fallback to %%any"); } else { plog("# default route not known: %s=%s", name, value); goto err; } } else if (streq(value, "%any") || streq(value, "%any4")) { anyaddr(conn->addr_family, &end->addr); } else if (streq(value, "%any6")) { conn->addr_family = AF_INET6; anyaddr(conn->addr_family, &end->addr); } else if (streq(value, "%group")) { ip_address any; conn->policy |= POLICY_GROUP | POLICY_TUNNEL; anyaddr(conn->addr_family, &end->addr); anyaddr(conn->tunnel_addr_family, &any); end->has_client = TRUE; } else { /* check for allow_any prefix */ if (value[0] == '%') { end->allow_any = TRUE; value++; } conn->addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->addr_family, &end->addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); if (streq(ugh, "does not look numeric and name lookup failed")) { end->dns_failed = TRUE; anyaddr(conn->addr_family, &end->addr); } else { goto err; } } } break; case KW_NEXTHOP: if (streq(value, "%defaultroute")) { if (cfg->defaultroute.defined) { end->nexthop = cfg->defaultroute.nexthop; } else { plog("# default route not known: %s=%s", name, value); goto err; } } else if (streq(value, "%direct")) { ugh = anyaddr(conn->addr_family, &end->nexthop); } else { conn->addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->addr_family, &end->nexthop); } if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); goto err; } break; case KW_SUBNETWITHIN: { ip_subnet net; end->has_client = TRUE; end->has_client_wildcard = TRUE; conn->tunnel_addr_family = ip_version(value); ugh = ttosubnet(value, 0, ip_version(value), &net); if (ugh != NULL) { plog("# bad subnet: %s=%s [%s]", name, value, ugh); goto err; } end->subnet = clone_str(value); break; } case KW_PROTOPORT: ugh = ttoprotoport(value, 0, &end->protocol, &end->port, &has_port_wildcard); end->has_port_wildcard = has_port_wildcard; break; case KW_NATIP: if (end->sourceip) { plog("# natip and sourceip cannot be defined at the same time"); goto err; } if (streq(value, "%defaultroute")) { char buf[64]; if (cfg->defaultroute.defined) { addrtot(&cfg->defaultroute.addr, 0, buf, sizeof(buf)); end->sourceip = clone_str(buf); } else { plog("# default route not known: %s=%s", name, value); goto err; } } else { ip_address addr; conn->tunnel_addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->tunnel_addr_family, &addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); goto err; } end->sourceip = clone_str(value); } end->has_natip = TRUE; conn->policy |= POLICY_TUNNEL; break; default: break; } return; err: plog(" bad argument value in conn '%s'", conn_name); cfg->err++; }
/***************************************************************************************** 函数名称: dpd_inR 功能描述: 处理R_U_THERE_ACK 报文,判断报文长度是否正确以及通过序列号判断 报文是否是自己想要的 输入参数: p1st,n,pbs 输出参数: 无 返 回 值: stf_status ------------------------------------------------------------------------------------------- 最近一次修改记录 : 修改作者: 王之云 修改目的: ACk处理 修改日期: 2012年3月20日 ********************************************************************************************/ stf_status dpd_inR(struct state *p1st, struct isakmp_notification *const n, pb_stream *pbs) { EV_ADD ev_arg; if(!p1st->hidden_variables.st_is_dp_dev) { time_t tm = now(); u_int32_t seqno; char buf_remoteip[20] = {0}; addrtot(&p1st->st_remoteaddr, 0, buf_remoteip, sizeof(buf_remoteip)); if (!IS_ISAKMP_SA_ESTABLISHED(p1st->st_state)) { IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "recevied R_U_THERE_ACK for unestablished ISKAMP SA"); return STF_FAIL; } if (n->isan_spisize != COOKIE_SIZE * 2 || pbs_left(pbs) < COOKIE_SIZE * 2) { IPSEC_log(IPSEC_LOGLEVEL_ERROR, "<%s> < %s > R_U_THERE_ACK has invalid SPI length (%d)", p1st->st_connection->name, buf_remoteip, n->isan_spisize); return STF_FAIL + PAYLOAD_MALFORMED; } if (memcmp(pbs->cur, p1st->st_icookie, COOKIE_SIZE) != 0) { IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "R_U_THERE_ACK has invalid icookie"); } pbs->cur += COOKIE_SIZE; if (memcmp(pbs->cur, p1st->st_rcookie, COOKIE_SIZE) != 0) { IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "R_U_THERE_ACK has invalid rcookie (tolerated)"); } pbs->cur += COOKIE_SIZE; if (pbs_left(pbs) != sizeof(seqno)) { IPSEC_log(IPSEC_LOGLEVEL_ERROR, "<%s> < %s > R_U_THERE_ACK has invalid data length (%d)", p1st->st_connection->name, buf_remoteip, (int) pbs_left(pbs)); return STF_FAIL + PAYLOAD_MALFORMED; } seqno = ntohl(*(u_int32_t *)pbs->cur); DBG(DBG_DPD, DBG_log("R_U_THERE_ACK, seqno received: %u expected: %u (state=#%lu)", seqno, p1st->st_dpd_expectseqno, p1st->st_serialno)); if (seqno != p1st->st_dpd_expectseqno) { IPSEC_log(IPSEC_LOGLEVEL_PRIVATE, "R_U_THERE_ACK has unexpected sequence number (expected: %u got: %u", seqno, p1st->st_dpd_expectseqno); return STF_IGNORE; } else { p1st->st_last_dpd = tm; } } if(p1st->st_dpd_timeout_event != NULL) { ev_arg.u.st = p1st; disable_event(EVENT_DPD_TIMEOUT, &ev_arg); } return STF_IGNORE; }
int main(int argc, char **argv) { /* int fd; */ char *endptr; /* int ret; */ int c; const char* error_s; int error = 0; char ipaddr_txt[ADDRTOT_BUF]; struct sadb_ext *extensions[K_SADB_EXT_MAX + 1]; struct sadb_msg *pfkey_msg; ip_address pfkey_address_s_ska; /*struct sockaddr_in pfkey_address_d_ska;*/ ip_address pfkey_address_sflow_ska; ip_address pfkey_address_dflow_ska; ip_address pfkey_address_smask_ska; ip_address pfkey_address_dmask_ska; int transport_proto = 0; int src_port = 0; int dst_port = 0; ip_said said; ip_subnet s_subnet, d_subnet; int eroute_af = 0; int said_af = 0; int sa_flags=0; int argcount = argc; progname = argv[0]; memset(&pfkey_address_s_ska, 0, sizeof(ip_address)); memset(&pfkey_address_sflow_ska, 0, sizeof(ip_address)); memset(&pfkey_address_dflow_ska, 0, sizeof(ip_address)); memset(&pfkey_address_smask_ska, 0, sizeof(ip_address)); memset(&pfkey_address_dmask_ska, 0, sizeof(ip_address)); memset(&said, 0, sizeof(ip_said)); memset(&s_subnet, 0, sizeof(ip_subnet)); memset(&d_subnet, 0, sizeof(ip_subnet)); eroute_af_opt = said_af_opt = edst_opt = spi_opt = proto_opt = said_opt = dst_opt = src_opt = NULL; while((c = getopt_long(argc, argv, ""/*"acdD:e:i:hprs:S:f:vl:+:g"*/, longopts, 0)) != EOF) { switch(c) { case 'g': debug = 1; pfkey_lib_debug = PF_KEY_DEBUG_PARSE_MAX; argcount--; break; case 'a': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_SETEROUTE; break; case 'A': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_INEROUTE; break; case 'r': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_REPLACEROUTE; break; case 'E': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--replacein', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_INREPLACEROUTE; break; case 'c': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_CLREROUTE; break; case 'd': if(action_type) { fprintf(stderr, "%s: Only one of '--add', '--addin', '--replace', '--clear', or '--del' options permitted.\n", progname); exit(1); } action_type = EMT_DELEROUTE; break; case 'e': if(said_opt) { fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit (1); } if(edst_opt) { fprintf(stderr, "%s: Error, EDST parameter redefined:%s, already defined as:%s\n", progname, optarg, edst_opt); exit (1); } error_s = ttoaddr(optarg, 0, said_af, &said.dst); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --edst argument:%s\n", progname, error_s, optarg); exit (1); } edst_opt = optarg; break; case 'h': case '?': usage(progname); exit(1); case 's': if(said_opt) { fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit (1); } if(spi_opt) { fprintf(stderr, "%s: Error, SPI parameter redefined:%s, already defined as:%s\n", progname, optarg, spi_opt); exit (1); } said.spi = htonl(strtoul(optarg, &endptr, 0)); if(!(endptr == optarg + strlen(optarg))) { fprintf(stderr, "%s: Invalid character in SPI parameter: %s\n", progname, optarg); exit (1); } if(ntohl(said.spi) < 0x100) { fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than 0x100.\n", progname, optarg, ntohl(said.spi)); exit(1); } spi_opt = optarg; break; case 'p': if(said_opt) { fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit (1); } if(proto_opt) { fprintf(stderr, "%s: Error, PROTO parameter redefined:%s, already defined as:%s\n", progname, optarg, proto_opt); exit (1); } #if 0 if(said.proto) { fprintf(stderr, "%s: Warning, PROTO parameter redefined:%s\n", progname, optarg); exit (1); } #endif if(!strcmp(optarg, "ah")) said.proto = SA_AH; if(!strcmp(optarg, "esp")) said.proto = SA_ESP; if(!strcmp(optarg, "tun")) said.proto = SA_IPIP; if(!strcmp(optarg, "comp")) said.proto = SA_COMP; if(said.proto == 0) { fprintf(stderr, "%s: Invalid PROTO parameter: %s\n", progname, optarg); exit (1); } proto_opt = optarg; break; case 'I': if(said_opt) { fprintf(stderr, "%s: Error, SAID parameter redefined:%s, already defined in SA:%s\n", progname, optarg, said_opt); exit (1); } if(proto_opt) { fprintf(stderr, "%s: Error, PROTO parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, proto_opt); exit (1); } if(edst_opt) { fprintf(stderr, "%s: Error, EDST parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, edst_opt); exit (1); } if(spi_opt) { fprintf(stderr, "%s: Error, SPI parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, spi_opt); exit (1); } if(said_af_opt) { fprintf(stderr, "%s: Error, address family parameter redefined in SA:%s, already defined as:%s\n", progname, optarg, said_af_opt); exit (1); } error_s = ttosa(optarg, 0, &said); if(error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --sa argument:%s\n", progname, error_s, optarg); exit (1); } else if(ntohl(said.spi) < 0x100){ fprintf(stderr, "%s: Illegal reserved spi: %s => 0x%x Must be larger than or equal to 0x100.\n", progname, optarg, said.spi); exit(1); } said_af = addrtypeof(&said.dst); said_opt = optarg; break; case 'v': fprintf(stdout, "%s %s\n", me, ipsec_version_code()); fprintf(stdout, "See `ipsec --copyright' for copyright information.\n"); exit(1); case 'D': if(dst_opt) { fprintf(stderr, "%s: Error, --dst parameter redefined:%s, already defined as:%s\n", progname, optarg, dst_opt); exit (1); } error_s = ttosubnet(optarg, 0, eroute_af, &d_subnet); if (error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --dst argument: %s\n", progname, error_s, optarg); exit (1); } dst_opt = optarg; break; case 'S': if(src_opt) { fprintf(stderr, "%s: Error, --src parameter redefined:%s, already defined as:%s\n", progname, optarg, src_opt); exit (1); } error_s = ttosubnet(optarg, 0, eroute_af, &s_subnet); if (error_s != NULL) { fprintf(stderr, "%s: Error, %s converting --src argument: %s\n", progname, error_s, optarg); exit (1); } src_opt = optarg; break; case 'P': if (transport_proto_opt) { fprintf(stderr, "%s: Error, --transport-proto" " parameter redefined:%s, " "already defined as:%s\n", progname, optarg, transport_proto_opt); exit(1); } transport_proto_opt = optarg; break; case 'Q': if (src_port_opt) { fprintf(stderr, "%s: Error, --src-port" " parameter redefined:%s, " "already defined as:%s\n", progname, optarg, src_port_opt); exit(1); } src_port_opt = optarg; break; case 'R': if (dst_port_opt) { fprintf(stderr, "%s: Error, --dst-port" " parameter redefined:%s, " "already defined as:%s\n", progname, optarg, dst_port_opt); exit(1); } dst_port_opt = optarg; break; case 'l': progname = malloc(strlen(argv[0]) + 10 /* update this when changing the sprintf() */ + strlen(optarg)); sprintf(progname, "%s --label %s", argv[0], optarg); argcount -= 2; break; case 'i': /* specifies the address family of the SAID, stored in said_af */ if(said_af_opt) { fprintf(stderr, "%s: Error, address family of SAID redefined:%s, already defined as:%s\n", progname, optarg, said_af_opt); exit (1); } if(!strcmp(optarg, "inet")) said_af = AF_INET; if(!strcmp(optarg, "inet6")) said_af = AF_INET6; if(said_af == 0) { fprintf(stderr, "%s: Invalid address family parameter for SAID: %s\n", progname, optarg); exit (1); } said_af_opt = optarg; break; case 'f': /* specifies the address family of the eroute, stored in eroute_af */ if(eroute_af_opt) { fprintf(stderr, "%s: Error, address family of eroute redefined:%s, already defined as:%s\n", progname, optarg, eroute_af_opt); exit (1); } if(!strcmp(optarg, "inet")) eroute_af = AF_INET; if(!strcmp(optarg, "inet6")) eroute_af = AF_INET6; if(eroute_af == 0) { fprintf(stderr, "%s: Invalid address family parameter for eroute: %s\n", progname, optarg); exit (1); } eroute_af_opt = optarg; break; case '+': /* optionsfrom */ optionsfrom(optarg, &argc, &argv, optind, stderr); /* no return on error */ break; default: break; } } if(debug) { fprintf(stdout, "%s: DEBUG: argc=%d\n", progname, argc); } if(argcount == 1) { struct stat sts; if ( ((stat ("/proc/net/pfkey", &sts)) == 0) ) { fprintf(stderr, "%s: NETKEY does not support eroute table.\n",progname); exit(1); } else { int ret = 1; if ((stat ("/proc/net/ipsec_eroute", &sts)) != 0) { fprintf(stderr, "%s: No eroute table - no IPsec support in kernel (are the modules loaded?)\n", progname); } else { ret = system("cat /proc/net/ipsec_eroute"); ret = ret != -1 && WIFEXITED(ret) ? WEXITSTATUS(ret) : 1; } exit(ret); } } /* Sanity checks */ if(debug) { fprintf(stdout, "%s: DEBUG: action_type=%d\n", progname, action_type); } if (transport_proto_opt != 0) { struct protoent * proto = getprotobyname(transport_proto_opt); if (proto != 0) { transport_proto = proto->p_proto; } else { transport_proto = strtoul(transport_proto_opt, &endptr, 0); if ((*endptr != '\0') || (transport_proto == 0 && endptr == transport_proto_opt)) { fprintf(stderr, "%s: Invalid character in --transport-proto parameter: %s\n", progname, transport_proto_opt); exit (1); } if (transport_proto > 255) { fprintf(stderr, "%s: --transport-proto parameter: %s must be in the range 0 to 255 inclusive\n", progname, transport_proto_opt); exit (1); } } } if (src_port_opt != 0 || dst_port_opt != 0) { switch (transport_proto) { case IPPROTO_UDP: case IPPROTO_TCP: break; default: fprintf(stderr, "%s: --transport-proto with either UDP or TCP must be specified if --src-port or --dst-port is used\n", progname); exit(1); } } if (src_port_opt) { struct servent * ent = getservbyname(src_port_opt, 0); if (ent != 0) { src_port = ent->s_port; } else { src_port = strtoul(src_port_opt, &endptr, 0); if ((*endptr != '\0') || (src_port == 0 && endptr == src_port_opt)) { fprintf(stderr, "%s: Invalid character in --src-port parameter: %s\n", progname, src_port_opt); exit (1); } if (src_port > 65535) { fprintf(stderr, "%s: --src-port parameter: %s must be in the range 0 to 65535 inclusive\n", progname, src_port_opt); } src_port = htons(src_port); } } if (dst_port_opt) { struct servent * ent = getservbyname(dst_port_opt, 0); if (ent != 0) { dst_port = ent->s_port; } else { dst_port = strtoul(dst_port_opt, &endptr, 0); if ((*endptr != '\0') || (dst_port == 0 && endptr == dst_port_opt)) { fprintf(stderr, "%s: Invalid character in --dst-port parameter: %s\n", progname, dst_port_opt); exit (1); } if (dst_port > 65535) { fprintf(stderr, "%s: --dst-port parameter: %s must be in the range 0 to 65535 inclusive\n", progname, dst_port_opt); } dst_port = htons(dst_port); } } switch(action_type) { case EMT_SETEROUTE: case EMT_REPLACEROUTE: case EMT_INEROUTE: case EMT_INREPLACEROUTE: if(!(said_af_opt && edst_opt && spi_opt && proto_opt) && !(said_opt)) { fprintf(stderr, "%s: add and addin options must have SA specified.\n", progname); exit(1); } case EMT_DELEROUTE: if(!src_opt) { fprintf(stderr, "%s: Error -- %s option '--src' is required.\n", progname, (action_type == EMT_SETEROUTE) ? "add" : "del"); exit(1); } if(!dst_opt) { fprintf(stderr, "%s: Error -- %s option '--dst' is required.\n", progname, (action_type == EMT_SETEROUTE) ? "add" : "del"); exit(1); } case EMT_CLREROUTE: break; default: fprintf(stderr, "%s: exactly one of '--add', '--addin', '--replace', '--del' or '--clear' options must be specified.\n" "Try %s --help' for usage information.\n", progname, progname); exit(1); } pfkey_sock = pfkey_open_sock_with_error(); if(pfkey_sock == -1) { exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: PFKEYv2 socket successfully openned=%d.\n", progname, pfkey_sock); } /* Build an SADB_X_ADDFLOW or SADB_X_DELFLOW message to send down. */ /* It needs <base, SA, address(SD), flow(SD), mask(SD)> minimum. */ pfkey_extensions_init(extensions); if((error = pfkey_msg_hdr_build(&extensions[0], (action_type == EMT_SETEROUTE || action_type == EMT_REPLACEROUTE || action_type == EMT_INREPLACEROUTE || action_type == EMT_INEROUTE) ? SADB_X_ADDFLOW : SADB_X_DELFLOW, proto2satype(said.proto), 0, ++pfkey_seq, getpid()))) { fprintf(stderr, "%s: Trouble building message header, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_msg_hdr_build successfull.\n", progname); } switch(action_type) { case EMT_CLREROUTE: sa_flags = SADB_X_SAFLAGS_CLEARFLOW; goto sa_build; case EMT_REPLACEROUTE: sa_flags = SADB_X_SAFLAGS_REPLACEFLOW; goto sa_build; case EMT_INREPLACEROUTE: sa_flags = SADB_X_SAFLAGS_REPLACEFLOW | SADB_X_SAFLAGS_INFLOW; goto sa_build; case EMT_INEROUTE: sa_flags = SADB_X_SAFLAGS_INFLOW; goto sa_build; case EMT_SETEROUTE: sa_build: if((error = pfkey_sa_build(&extensions[SADB_EXT_SA], SADB_EXT_SA, said.spi, /* in network order */ 0, 0, 0, 0, sa_flags))) { fprintf(stderr, "%s: Trouble building sa extension, error=%d.\n", progname, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_sa_build successful.\n", progname); } default: break; } switch(action_type) { case EMT_SETEROUTE: case EMT_REPLACEROUTE: case EMT_INEROUTE: case EMT_INREPLACEROUTE: anyaddr(said_af, &pfkey_address_s_ska); if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_SRC], SADB_EXT_ADDRESS_SRC, 0, 0, sockaddrof(&pfkey_address_s_ska)))) { addrtot(&pfkey_address_s_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_s extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src.\n", progname); } if((error = pfkey_address_build(&extensions[SADB_EXT_ADDRESS_DST], SADB_EXT_ADDRESS_DST, 0, 0, sockaddrof(&said.dst)))) { addrtot(&said.dst, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_d extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst.\n", progname); } default: break; } switch(action_type) { case EMT_SETEROUTE: case EMT_REPLACEROUTE: case EMT_INEROUTE: case EMT_INREPLACEROUTE: case EMT_DELEROUTE: networkof(&s_subnet, &pfkey_address_sflow_ska); /* src flow */ add_port(eroute_af, &pfkey_address_sflow_ska, src_port); if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_FLOW], SADB_X_EXT_ADDRESS_SRC_FLOW, 0, 0, sockaddrof(&pfkey_address_sflow_ska)))) { addrtot(&pfkey_address_sflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_sflow extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src flow.\n", progname); } networkof(&d_subnet, &pfkey_address_dflow_ska); /* dst flow */ add_port(eroute_af, &pfkey_address_dflow_ska, dst_port); if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_FLOW], SADB_X_EXT_ADDRESS_DST_FLOW, 0, 0, sockaddrof(&pfkey_address_dflow_ska)))) { addrtot(&pfkey_address_dflow_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_dflow extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst flow.\n", progname); } maskof(&s_subnet, &pfkey_address_smask_ska); /* src mask */ add_port(eroute_af, &pfkey_address_smask_ska, src_port ? ~0:0); if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_SRC_MASK], SADB_X_EXT_ADDRESS_SRC_MASK, 0, 0, sockaddrof(&pfkey_address_smask_ska)))) { addrtot(&pfkey_address_smask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_smask extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for src mask.\n", progname); } maskof(&d_subnet, &pfkey_address_dmask_ska); /* dst mask */ add_port(eroute_af, &pfkey_address_dmask_ska, dst_port ? ~0:0); if((error = pfkey_address_build(&extensions[SADB_X_EXT_ADDRESS_DST_MASK], SADB_X_EXT_ADDRESS_DST_MASK, 0, 0, sockaddrof(&pfkey_address_dmask_ska)))) { addrtot(&pfkey_address_dmask_ska, 0, ipaddr_txt, sizeof(ipaddr_txt)); fprintf(stderr, "%s: Trouble building address_dmask extension (%s), error=%d.\n", progname, ipaddr_txt, error); pfkey_extensions_free(extensions); exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey_address_build successful for dst mask.\n", progname); } } if (transport_proto != 0) { if ((error = pfkey_x_protocol_build(&extensions[SADB_X_EXT_PROTOCOL], transport_proto))) { fprintf(stderr, "%s: Trouble building transport" " protocol extension, error=%d.\n", progname, error); 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(debug) { fprintf(stdout, "%s: DEBUG: pfkey_msg_build successful.\n", progname); } if((error = write(pfkey_sock, pfkey_msg, pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) != (ssize_t)(pfkey_msg->sadb_msg_len * IPSEC_PFKEYv2_ALIGN)) { fprintf(stderr, "%s: pfkey write failed, returning %d with errno=%d.\n", progname, error, errno); pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); switch(errno) { case EINVAL: fprintf(stderr, "Invalid argument, check kernel log messages for specifics.\n"); break; case ENXIO: if((action_type == EMT_SETEROUTE) || (action_type == EMT_REPLACEROUTE)) { fprintf(stderr, "Invalid mask.\n"); break; } if(action_type == EMT_DELEROUTE) { fprintf(stderr, "Mask not found.\n"); break; } case EFAULT: if((action_type == EMT_SETEROUTE) || (action_type == EMT_REPLACEROUTE)) { fprintf(stderr, "Invalid address.\n"); break; } if(action_type == EMT_DELEROUTE) { fprintf(stderr, "Address not found.\n"); break; } case EACCES: fprintf(stderr, "access denied. "); if(getuid() == 0) { fprintf(stderr, "Check permissions. Should be 600.\n"); } else { fprintf(stderr, "You must be root to open this file.\n"); } break; case EUNATCH: fprintf(stderr, "KLIPS not loaded.\n"); break; case EBUSY: fprintf(stderr, "KLIPS is busy. Most likely a serious internal error occured in a previous command. Please report as much detail as possible to development team.\n"); break; case ENODEV: fprintf(stderr, "KLIPS not loaded or enabled.\n"); fprintf(stderr, "No device?!?\n"); break; case ENOBUFS: fprintf(stderr, "No kernel memory to allocate SA.\n"); break; case ESOCKTNOSUPPORT: fprintf(stderr, "Algorithm support not available in the kernel. Please compile in support.\n"); break; case EEXIST: fprintf(stderr, "eroute already in use. Delete old one first.\n"); break; case ENOENT: if(action_type == EMT_INEROUTE || action_type == EMT_INREPLACEROUTE) { fprintf(stderr, "non-existant IPIP SA.\n"); break; } fprintf(stderr, "eroute doesn't exist. Can't delete.\n"); break; case ENOSPC: fprintf(stderr, "no room in kernel SAref table. Cannot process request.\n"); break; case ESPIPE: fprintf(stderr, "kernel SAref table internal error. Cannot process request.\n"); break; default: fprintf(stderr, "Unknown socket write error %d. Please report as much detail as possible to development team.\n", errno); } /* fprintf(stderr, "%s: socket write returned errno %d\n", progname, errno);*/ exit(1); } if(debug) { fprintf(stdout, "%s: DEBUG: pfkey write successful.\n", progname); } if(pfkey_msg) { pfkey_extensions_free(extensions); pfkey_msg_free(&pfkey_msg); } (void) close(pfkey_sock); /* close the socket */ if(debug) { fprintf(stdout, "%s: DEBUG: write ok\n", progname); } exit(0); }
static void cannot_oppo(struct connection *c , struct find_oppo_bundle *b , err_t ughmsg) { char pcb[ADDRTOT_BUF]; char ocb[ADDRTOT_BUF]; addrtot(&b->peer_client, 0, pcb, sizeof(pcb)); addrtot(&b->our_client, 0, ocb, sizeof(ocb)); DBG(DBG_OPPO, openswan_log("Can not opportunistically initiate for %s to %s: %s" , ocb, pcb, ughmsg)); whack_log(RC_OPPOFAILURE , "Can not opportunistically initiate for %s to %s: %s" , ocb, pcb, ughmsg); if (c != NULL && c->policy_next != NULL) { /* there is some policy that comes afterwards */ struct spd_route *shunt_spd; struct connection *nc = c->policy_next; struct state *st; passert(c->kind == CK_TEMPLATE); passert(nc->kind == CK_PERMANENT); DBG(DBG_OPPO, DBG_log("OE failed for %s to %s, but %s overrides shunt" , ocb, pcb, nc->name)); /* * okay, here we need add to the "next" policy, which is ought * to be an instance. * We will add another entry to the spd_route list for the specific * situation that we have. */ shunt_spd = clone_thing(nc->spd, "shunt eroute policy"); shunt_spd->next = nc->spd.next; nc->spd.next = shunt_spd; happy(addrtosubnet(&b->peer_client, &shunt_spd->that.client)); if (sameaddr(&b->peer_client, &shunt_spd->that.host_addr)) shunt_spd->that.has_client = FALSE; /* * override the tunnel destination with the one from the secondaried * policy */ shunt_spd->that.host_addr = nc->spd.that.host_addr; /* now, lookup the state, and poke it up. */ st = state_with_serialno(nc->newest_ipsec_sa); /* XXX what to do if the IPSEC SA has died? */ passert(st != NULL); /* link the new connection instance to the state's list of * connections */ DBG(DBG_OPPO, DBG_log("installing state: %ld for %s to %s" , nc->newest_ipsec_sa , ocb, pcb)); #ifdef DEBUG if (DBGP(DBG_OPPO | DBG_CONTROLMORE)) { char state_buf[LOG_WIDTH]; char state_buf2[LOG_WIDTH]; const time_t n = now(); fmt_state(st, n, state_buf, sizeof(state_buf) , state_buf2, sizeof(state_buf2)); DBG_log("cannot_oppo, failure SA1: %s", state_buf); DBG_log("cannot_oppo, failure SA2: %s", state_buf2); } #endif /* DEBUG */ if (!route_and_eroute(c, shunt_spd, st)) { whack_log(RC_OPPOFAILURE , "failed to instantiate shunt policy %s for %s to %s" , c->name , ocb, pcb); } return; } /* * NETKEY default for level param in tmpl is required, so no traffic will * transmitted until an SA is fully up */ if (b->held && kern_interface != USE_NETKEY) { int failure_shunt = b->failure_shunt; /* Replace HOLD with b->failure_shunt. * If no failure_shunt specified, use SPI_PASS -- THIS MAY CHANGE. */ if (failure_shunt == 0) { DBG(DBG_OPPO, DBG_log("no explicit failure shunt for %s to %s; removing spurious hold shunt" , ocb, pcb)); } (void) replace_bare_shunt(&b->our_client, &b->peer_client , b->policy_prio , failure_shunt , failure_shunt != 0 , b->transport_proto , ughmsg); } }