static int priv_netinet_ipsec_policy_entrust_setup_af(int asroot, int injail, struct test *test, int af) { entrustbuf = ipsec_set_policy(policy_entrust, sizeof(policy_entrust)-1); if (entrustbuf == NULL) { warn("%s: ipsec_set_policy(NULL)", __func__); return (-1); } switch (af) { case AF_INET: sd = socket(AF_INET, SOCK_DGRAM, 0); if (sd < 0) { warn("%s: socket4", __func__); return (-1); } break; #ifdef INET6 case AF_INET6: sd = socket(AF_INET6, SOCK_DGRAM, 0); if (sd < 0) { warn("%s: socket6", __func__); return (-1); } break; #endif default: warnx("%s: unexpected address family", __func__); return (-1); } return (0); }
char *setpolicy(char *req) { int len; char *buf; if ((len = ipsec_get_policylen(req)) < 0) { printf("ipsec_get_policylen: %s\n", ipsec_strerror()); return NULL; } if ((buf = malloc(len)) == NULL) { perror("malloc"); return NULL; } if ((len = ipsec_set_policy(buf, len, req)) < 0) { printf("ipsec_set_policy: %s\n", ipsec_strerror()); free(buf); return NULL; } return buf; }
static void sock4_open(struct flags *flags #ifdef IPSEC_POLICY_IPSEC , char *policy #endif /* IPSEC_POLICY_IPSEC */ ) { #ifdef IPSEC #ifndef IPSEC_POLICY_IPSEC int optval; #endif #endif if (with_v4dest == 0) return; if ((s4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { syslog(LOG_ERR, "<%s> socket(v4): %s", __func__, strerror(errno)); exit(1); } #if 0 /* XXX: not necessary ?? */ /* * join all routers multicast addresses. */ some_join_function(); #endif #ifdef IPSEC #ifdef IPSEC_POLICY_IPSEC if (flags->policy) { char *buf; buf = ipsec_set_policy(policy, strlen(policy)); if (buf == NULL) errx(1, "%s", ipsec_strerror()); /* XXX should handle in/out bound policy. */ if (setsockopt(s4, IPPROTO_IP, IP_IPSEC_POLICY, buf, ipsec_get_policylen(buf)) < 0) err(1, "setsockopt(IP_IPSEC_POLICY)"); free(buf); } #else /* IPSEC_POLICY_IPSEC */ if (flags->auth) { optval = IPSEC_LEVEL_REQUIRE; if (setsockopt(s4, IPPROTO_IP, IP_AUTH_TRANS_LEVEL, &optval, sizeof(optval)) == -1) { syslog(LOG_ERR, "<%s> IP_AUTH_TRANS_LEVEL: %s", __func__, strerror(errno)); exit(1); } } if (flags->encrypt) { optval = IPSEC_LEVEL_REQUIRE; if (setsockopt(s4, IPPROTO_IP, IP_ESP_TRANS_LEVEL, &optval, sizeof(optval)) == -1) { syslog(LOG_ERR, "<%s> IP_ESP_TRANS_LEVEL: %s", __func__, strerror(errno)); exit(1); } } #endif /* IPSEC_POLICY_IPSEC */ #endif /* IPSEC */ return; }
static void sock6_open(struct flags *flags #ifdef IPSEC_POLICY_IPSEC , char *policy #endif /* IPSEC_POLICY_IPSEC */ ) { struct icmp6_filter filt; int on; #ifdef IPSEC #ifndef IPSEC_POLICY_IPSEC int optval; #endif #endif if (with_v6dest == 0) return; if (with_v6dest && (s6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) { syslog(LOG_ERR, "<%s> socket(v6): %s", __func__, strerror(errno)); exit(1); } /* * join all routers multicast addresses. */ #if 0 /* XXX: not necessary ?? */ join_multi(LL_ALLROUTERS); join_multi(SL_ALLROUTERS); #endif /* set icmpv6 filter */ ICMP6_FILTER_SETBLOCKALL(&filt); ICMP6_FILTER_SETPASS(ICMP6_ROUTER_RENUMBERING, &filt); if (setsockopt(s6, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt)) < 0) { syslog(LOG_ERR, "<%s> IICMP6_FILTER: %s", __func__, strerror(errno)); exit(1); } /* specify to tell receiving interface */ on = 1; if (setsockopt(s6, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) { syslog(LOG_ERR, "<%s> IPV6_RECVPKTINFO: %s", __func__, strerror(errno)); exit(1); } #ifdef IPSEC #ifdef IPSEC_POLICY_IPSEC if (flags->policy) { char *buf; buf = ipsec_set_policy(policy, strlen(policy)); if (buf == NULL) errx(1, "%s", ipsec_strerror()); /* XXX should handle in/out bound policy. */ if (setsockopt(s6, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf, ipsec_get_policylen(buf)) < 0) err(1, "setsockopt(IPV6_IPSEC_POLICY)"); free(buf); } #else /* IPSEC_POLICY_IPSEC */ if (flags->auth) { optval = IPSEC_LEVEL_REQUIRE; if (setsockopt(s6, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL, &optval, sizeof(optval)) == -1) { syslog(LOG_ERR, "<%s> IPV6_AUTH_TRANS_LEVEL: %s", __func__, strerror(errno)); exit(1); } } if (flags->encrypt) { optval = IPSEC_LEVEL_REQUIRE; if (setsockopt(s6, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL, &optval, sizeof(optval)) == -1) { syslog(LOG_ERR, "<%s> IPV6_ESP_TRANS_LEVEL: %s", __func__, strerror(errno)); exit(1); } } #endif /* IPSEC_POLICY_IPSEC */ #endif /* IPSEC */ return; }
/* start l2tpd listner */ static int l2tpd_listener_start(l2tpd_listener *_this) { l2tpd *_l2tpd; int af, lvl, opt, sock, ival; char hbuf[NI_MAXHOST + NI_MAXSERV + 16]; _l2tpd = _this->self; sock = -1; af = _this->bind.sin6.sin6_family; lvl = (af == AF_INET)? IPPROTO_IP : IPPROTO_IPV6; if (_this->tun_name[0] == '\0') strlcpy(_this->tun_name, L2TPD_DEFAULT_LAYER2_LABEL, sizeof(_this->tun_name)); if ((sock = socket(_this->bind.sin6.sin6_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP)) < 0) { l2tpd_log(_l2tpd, LOG_ERR, "socket() failed in %s(): %m", __func__); goto fail; } #if defined(IP_STRICT_RCVIF) && defined(USE_STRICT_RCVIF) ival = 1; if (setsockopt(sock, IPPROTO_IP, IP_STRICT_RCVIF, &ival, sizeof(ival)) != 0) l2tpd_log(_l2tpd, LOG_WARNING, "%s(): setsockopt(IP_STRICT_RCVIF) failed: %m", __func__); #endif ival = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &ival, sizeof(ival)) != 0) { l2tpd_log(_l2tpd, LOG_ERR, "setsockopt(,,SO_REUSEPORT) failed in %s(): %m", __func__); goto fail; } if (bind(sock, (struct sockaddr *)&_this->bind, _this->bind.sin6.sin6_len) != 0) { l2tpd_log(_l2tpd, LOG_ERR, "Binding %s/udp: %m", addrport_tostring((struct sockaddr *)&_this->bind, _this->bind.sin6.sin6_len, hbuf, sizeof(hbuf))); goto fail; } #ifdef USE_LIBSOCKUTIL if (setsockoptfromto(sock) != 0) { l2tpd_log(_l2tpd, LOG_ERR, "setsockoptfromto() failed in %s(): %m", __func__); goto fail; } #else opt = (af == AF_INET)? IP_RECVDSTADDR : IPV6_RECVPKTINFO; ival = 1; if (setsockopt(sock, lvl, opt, &ival, sizeof(ival)) != 0) { l2tpd_log(_l2tpd, LOG_ERR, "setsockopt(,,IP{,V6}_RECVDSTADDR) failed in %s(): %m", __func__); goto fail; } #endif #ifdef USE_SA_COOKIE if (af == AF_INET) { ival = 1; if (setsockopt(sock, IPPROTO_IP, IP_IPSECFLOWINFO, &ival, sizeof(ival)) != 0) { l2tpd_log(_l2tpd, LOG_ERR, "setsockopt(,,IP_IPSECFLOWINFO) failed in %s(): %m", __func__); goto fail; } } #endif #ifdef IP_PIPEX opt = (af == AF_INET)? IP_PIPEX : IPV6_PIPEX; ival = 1; if (setsockopt(sock, lvl, opt, &ival, sizeof(ival)) != 0) l2tpd_log(_l2tpd, LOG_WARNING, "%s(): setsockopt(IP{,V6}_PIPEX) failed: %m", __func__); #endif if (_this->conf->require_ipsec) { #ifdef IP_IPSEC_POLICY caddr_t ipsec_policy_in, ipsec_policy_out; opt = (af == AF_INET)? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; /* * Note: ipsec_set_policy() will assign the buffer for * yacc parser stack, however it never free. * it cause memory leak (-2000byte). */ if ((ipsec_policy_in = ipsec_set_policy(L2TPD_IPSEC_POLICY_IN, strlen(L2TPD_IPSEC_POLICY_IN))) == NULL) { l2tpd_log(_l2tpd, LOG_ERR, "ipsec_set_policy(L2TPD_IPSEC_POLICY_IN) failed " "at %s(): %s: %m", __func__, ipsec_strerror()); } else if (setsockopt(sock, lvl, opt, ipsec_policy_in, ipsec_get_policylen(ipsec_policy_in)) < 0) { l2tpd_log(_l2tpd, LOG_WARNING, "setsockopt(,,IP_IPSEC_POLICY(in)) failed " "in %s(): %m", __func__); } if ((ipsec_policy_out = ipsec_set_policy(L2TPD_IPSEC_POLICY_OUT, strlen(L2TPD_IPSEC_POLICY_OUT))) == NULL) { l2tpd_log(_l2tpd, LOG_ERR, "ipsec_set_policy(L2TPD_IPSEC_POLICY_OUT) failed " "at %s(): %s: %m", __func__, ipsec_strerror()); } if (ipsec_policy_out != NULL && setsockopt(sock, lvl, opt, ipsec_policy_out, ipsec_get_policylen(ipsec_policy_out)) < 0) { l2tpd_log(_l2tpd, LOG_WARNING, "setsockopt(,,IP_IPSEC_POLICY(out)) failed " "in %s(): %m", __func__); } free(ipsec_policy_in); free(ipsec_policy_out); #elif defined(IP_ESP_TRANS_LEVEL) opt = (af == AF_INET) ? IP_ESP_TRANS_LEVEL : IPV6_ESP_TRANS_LEVEL; ival = IPSEC_LEVEL_REQUIRE; if (setsockopt(sock, lvl, opt, &ival, sizeof(ival)) != 0) { l2tpd_log(_l2tpd, LOG_WARNING, "setsockopt(,,IP{,V6}_ESP_TRANS_LEVEL(out)) failed " "in %s(): %m", __func__); } #else #error IP_IPSEC_POLICY or IP_ESP_TRANS_LEVEL must be usable. #endif } _this->sock = sock; event_set(&_this->ev_sock, _this->sock, EV_READ | EV_PERSIST, l2tpd_io_event, _this); event_add(&_this->ev_sock, NULL); l2tpd_log(_l2tpd, LOG_INFO, "Listening %s/udp (L2TP LNS) [%s]", addrport_tostring((struct sockaddr *)&_this->bind, _this->bind.sin6.sin6_len, hbuf, sizeof(hbuf)), _this->tun_name); return 0; fail: if (sock >= 0) close(sock); return 1; }