📄 klips.c
字号:
= ((struct sockaddr_in *)(incoming ? src : dst))->sin_addr; /* * Klips does not know about expirations, thus we need to do them inside * isakmpd. */ if (sa->seconds) if (sa_setup_expirations (sa)) goto cleanup; LOG_DBG ((LOG_SYSDEP, 10, "klips_set_spi: proto %d dst %s SPI 0x%x", emsg->em_proto, inet_ntoa (emsg->em_dst), htonl (emsg->em_spi))); if (klips_write (emsg)) goto cleanup; free (emsg); /* If we are tunneling we have to setup an IP in IP tunnel too. */ if (iproto->encap_mode == IPSEC_ENCAP_TUNNEL) { len = EMT_SETSPI_FLEN + EMT_IPE4_ULEN; emsg = calloc (1, len); if (!emsg) goto cleanup; emsg->em_proto = IPPROTO_IPIP; emsg->em_msglen = len; emsg->em_type = EMT_SETSPI; /* * XXX Code in Pluto suggests this is not possible, but that we have * to have a unique SPI for the IP4 SA. */ memcpy (&emsg->em_spi, proto->spi[incoming], sizeof emsg->em_spi); emsg->em_flags = 0; emsg->em_alg = XF_IP4; ip4x = (struct ipe4_xdata *)emsg->em_dat; ip4x->i4_dst = emsg->em_dst = ((struct sockaddr_in *)(incoming ? src : dst))->sin_addr; ip4x->i4_src = ((struct sockaddr_in *)(incoming ? dst : src))->sin_addr; LOG_DBG ((LOG_SYSDEP, 10, "klips_set_spi: proto %d dst %s SPI 0x%x", emsg->em_proto, inet_ntoa (emsg->em_dst), htonl (emsg->em_spi))); if (klips_write (emsg)) goto cleanup; free (emsg); /* * Grouping the IP-in-IP SA with the IPsec one means we must be careful * in klips_group_spis so that we'll remove duplicate IP-in-IP SAs * and get everything grouped in the right order. * * XXX Could we not share code with klips_group_spis here? */ emsg = calloc (1, EMT_GRPSPIS_FLEN + 2 * EMT_GRPSPIS_COMPLEN); if (!emsg) goto cleanup; emsg->em_msglen = EMT_GRPSPIS_FLEN + 2 * EMT_GRPSPIS_COMPLEN; emsg->em_type = EMT_GRPSPIS; memcpy (&emsg->em_rel[0].emr_spi, proto->spi[incoming], sizeof emsg->em_rel[0].emr_spi); memcpy (&emsg->em_rel[1].emr_spi, proto->spi[incoming], sizeof emsg->em_rel[1].emr_spi); emsg->em_rel[0].emr_dst = emsg->em_rel[1].emr_dst = ((struct sockaddr_in *)(incoming ? src : dst))->sin_addr; emsg->em_rel[0].emr_proto = IPPROTO_IPIP; /* XXX What if IPCOMP etc. comes along? */ emsg->em_rel[1].emr_proto = proto->proto == IPSEC_PROTO_IPSEC_ESP ? IPPROTO_ESP : IPPROTO_AH; if (klips_write (emsg)) goto cleanup; free (emsg); } LOG_DBG ((LOG_SYSDEP, 50, "klips_set_spi: done")); return 0; cleanup: /* XXX Cleanup the potential SAs we have setup. */ if (emsg) free (emsg); return -1;}/* * Delete the IPsec SA represented by the INCOMING direction in protocol PROTO * of the IKE security association SA. */intklips_delete_spi (struct sa *sa, struct proto *proto, int incoming){ struct encap_msghdr *emsg = 0; struct sockaddr *dst; struct ipsec_proto *iproto = proto->data; emsg = calloc (1, EMT_SETSPI_FLEN); if (!emsg) return -1; emsg->em_msglen = EMT_SETSPI_FLEN; emsg->em_type = EMT_DELSPI; memcpy (&emsg->em_spi, proto->spi[incoming], sizeof emsg->em_spi); if (incoming) sa->transport->vtbl->get_src (sa->transport, &dst); else sa->transport->vtbl->get_dst (sa->transport, &dst); emsg->em_dst = ((struct sockaddr_in *)dst)->sin_addr; /* XXX What if IPCOMP etc. comes along? */ emsg->em_proto = (iproto->encap_mode == IPSEC_ENCAP_TUNNEL ? IPPROTO_IPIP : proto->proto == IPSEC_PROTO_IPSEC_ESP ? IPPROTO_ESP : IPPROTO_AH); if (klips_write (emsg)) goto cleanup; free (emsg); LOG_DBG ((LOG_SYSDEP, 50, "klips_delete_spi: done")); return 0; cleanup: if (emsg) free (emsg); return -1;}intklips_hex_decode (char *src, u_char *dst, int dstsize){ char *p, *pe; u_char *q, *qe, ch, cl; pe = src + strlen (src); qe = dst + dstsize; for (p = src, q = dst; p < pe && q < qe && isxdigit ((int)*p); p += 2) { ch = tolower (p[0]); cl = tolower (p[1]); if ((ch >= '0') && (ch <= '9')) ch -= '0'; else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10; else return -1; if ((cl >= '0') && (cl <= '9')) cl -= '0'; else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10; else return -1; *q++ = (ch << 4) | cl; } return (int)(q - dst);}/* Consult kernel routing table for next-hop lookup. From dugsong@monkey.org */u_longklips_route_get (u_long dst){ FILE *f; char buf[BUFSIZ]; char ifbuf[16], netbuf[128], gatebuf[128], maskbuf[128]; int i, iflags, refcnt, use, metric, mss, win, irtt; u_long ret, gate, net, mask; if ((f = fopen (PROC_ROUTE_FILE, "r")) == NULL) return dst; ret = dst; while (fgets (buf, sizeof buf, f) != NULL) { i = sscanf (buf, PROC_ROUTE_FMT, ifbuf, netbuf, gatebuf, &iflags, &refcnt, &use, &metric, maskbuf, &mss, &win, &irtt); if (i < 10 || !(iflags & RTF_UP)) continue; klips_hex_decode (netbuf, (u_char *)&net, sizeof net); klips_hex_decode (gatebuf, (u_char *)&gate, sizeof gate); klips_hex_decode (maskbuf, (u_char *)&mask, sizeof mask); net = htonl (net); gate = htonl (gate); mask = htonl (mask); if ((dst & mask) == net) { if (gate != INADDR_ANY) ret = gate; break; } } fclose (f); return ret;}/* Enable a flow given a SA. */intklips_enable_sa (struct sa *sa, struct sa *isakmp_sa){ struct ipsec_sa *isa = sa->data; struct sockaddr *dst; struct proto *proto = TAILQ_FIRST (&sa->protos); struct ipsec_proto *iproto = proto->data; struct encap_msghdr emsg; int s = -1; struct rtentry rt; sa->transport->vtbl->get_dst (sa->transport, &dst); /* XXX Is this needed? */ memset (&emsg, '\0', sizeof emsg); emsg.em_msglen = sizeof emsg; emsg.em_type = EMT_RPLACEROUTE; memcpy (&emsg.em_erspi, proto->spi[0], sizeof emsg.em_erspi); emsg.em_erdst = ((struct sockaddr_in *)dst)->sin_addr; LOG_DBG ((LOG_SYSDEP, 50, "klips_enable_sa: src %x %x dst %x %x", ntohl (isa->src_net), ntohl (isa->src_mask), ntohl (isa->dst_net), ntohl (isa->dst_mask))); /* XXX Magic constant from Pluto (26 = AF_ISDN in BSD). */ emsg.em_eaddr.sen_family = emsg.em_emask.sen_family = 26; emsg.em_eaddr.sen_type = SENT_IP4; /* XXX Magic constant from Pluto. */ emsg.em_emask.sen_type = 255; emsg.em_eaddr.sen_len = emsg.em_emask.sen_len = sizeof (struct sockaddr_encap); emsg.em_eaddr.sen_ip_src.s_addr = isa->src_net; emsg.em_emask.sen_ip_src.s_addr = isa->src_mask; emsg.em_eaddr.sen_ip_dst.s_addr = isa->dst_net; emsg.em_emask.sen_ip_dst.s_addr = isa->dst_mask; /* XXX What if IPCOMP etc. comes along? */ emsg.em_erproto = (iproto->encap_mode == IPSEC_ENCAP_TUNNEL ? IPPROTO_IPIP : proto->proto == IPSEC_PROTO_IPSEC_ESP ? IPPROTO_ESP : IPPROTO_AH); if (klips_write (&emsg)) { emsg.em_type = EMT_SETEROUTE; if (klips_write (&emsg)) goto cleanup; } s = socket (PF_INET, SOCK_DGRAM, AF_UNSPEC); if (s == -1) { log_error ("klips_enable_sa: " "socket(PF_INET, SOCK_DGRAM, AF_UNSPEC) failed"); goto cleanup; } memset (&rt, '\0', sizeof rt); rt.rt_dst.sa_family = AF_INET; ((struct sockaddr_in *)&rt.rt_dst)->sin_addr.s_addr = isa->dst_net; rt.rt_genmask.sa_family = AF_INET; ((struct sockaddr_in *)&rt.rt_genmask)->sin_addr.s_addr = isa->dst_mask; rt.rt_gateway.sa_family = AF_INET; ((struct sockaddr_in *)&rt.rt_gateway)->sin_addr.s_addr = klips_route_get (emsg.em_erdst.s_addr); rt.rt_flags = RTF_UP | RTF_GATEWAY; /* XXX What if we have multiple interfaces? */ rt.rt_dev = "ipsec0"; if (ioctl (s, SIOCDELRT, &rt) == -1 && errno != ESRCH) { log_error ("klips_enable_sa: ioctl (%d, SIOCDELRT, %p) failed", s, &rt); goto cleanup; } if (ioctl (s, SIOCADDRT, &rt) == -1) { log_error ("klips_enable_sa: ioctl (%d, SIOCADDRT, %p) failed", s, &rt); goto cleanup; } close (s); return 0; cleanup: if (s != -1) close (s); return -1;}static voidklips_stayalive (struct exchange *exchange, void *vconn, int fail){ char *conn = vconn; struct sa *sa; /* XXX What if it is phase 1? */ sa = sa_lookup_by_name (conn, 2); if (sa) sa->flags |= SA_FLAG_STAYALIVE;}/* Establish the connection in VCONN and set the stayalive flag for it. */voidklips_connection_check (char *conn){ if (!sa_lookup_by_name (conn, 2)) { LOG_DBG ((LOG_SYSDEP, 70, "klips_connection_check: SA for %s missing", conn)); exchange_establish (conn, klips_stayalive, conn); } else LOG_DBG ((LOG_SYSDEP, 70, "klips_connection_check: SA for %s exists", conn));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -