-int ptm_bfd_echo_sock_init(void)
-{
- int s, ttl, yes = 1;
- struct sockaddr_in sin;
-
- s = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
- if (s == -1) {
- log_error("echo-socket: creation failed: %s", strerror(errno));
- return -1;
- }
-
- memset(&sin, 0, sizeof(sin));
-#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
- /* OmniOS doesn't have this field, but uses this code. */
- sin.sin_len = sizeof(sin);
-#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
- sin.sin_family = AF_INET;
- sin.sin_port = htons(3785);
- if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
- log_error("echo-socket: bind failure: %s", strerror(errno));
- close(s);
- return -1;
- }
-
- if (setsockopt(s, IPPROTO_IP, IP_RECVTTL, &yes, sizeof(yes)) == -1) {
- log_error("echo-socket: setsockopt(IP_RECVTTL): %s",
- strerror(errno));
- close(s);
- return -1;
- }
-
- ttl = BFD_TTL_VAL;
- if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) == -1) {
- log_error("echo-socket: setsockopt(IP_TTL): %s",
- strerror(errno));
- close(s);
- return -1;
- }
-
- return s;
-}
-
-ssize_t bsd_echo_sock_read(int sd, uint8_t *buf, ssize_t *buflen,
- struct sockaddr_storage *ss, socklen_t *sslen,
- uint8_t *ttl, uint32_t *id)
-{
- struct cmsghdr *cmsg;
- struct bfd_echo_pkt *bep;
- ssize_t readlen;
- struct iovec iov;
- struct msghdr msg;
- uint8_t msgctl[255];
- char errbuf[255];
-
- /* Prepare socket read. */
- memset(ss, 0, sizeof(*ss));
- memset(&msg, 0, sizeof(msg));
- iov.iov_base = buf;
- iov.iov_len = *buflen;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = msgctl;
- msg.msg_controllen = sizeof(msgctl);
- msg.msg_name = ss;
- msg.msg_namelen = *sslen;
-
- /* Read the socket and treat errors. */
- readlen = recvmsg(sd, &msg, 0);
- if (readlen == 0) {
- log_error("%s: recvmsg: socket closed", __func__);
- return -1;
- }
- if (readlen == -1) {
- if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
- return -1;
-
- log_error("%s: recvmsg: (%d) %s", __func__, errno,
- strerror(errno));
- return -1;
- }
- /* Short packet, better not risk reading it. */
- if (readlen < (ssize_t)sizeof(*bep)) {
- log_warning("%s: short packet (%ld of %d) from %s", __func__,
- readlen, sizeof(*bep),
- sockaddr_to_string(ss, errbuf, sizeof(errbuf)));
- return -1;
- }
- *buflen = readlen;
-
- /* Read TTL information. */
- *ttl = 0;
- for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&msg, cmsg)) {
- if (cmsg->cmsg_level != IPPROTO_IP)
- continue;
- if (cmsg->cmsg_type != IP_RECVTTL)
- continue;
-
- *ttl = *(uint8_t *)CMSG_DATA(cmsg);
- break;
- }
- if (*ttl == 0) {
- log_debug("%s: failed to read TTL", __func__);
- return -1;
- }
-
- /* Read my discriminator from BFD Echo packet. */
- bep = (struct bfd_echo_pkt *)buf;
- *id = bep->my_discr;
- if (*id == 0) {
- log_debug("%s: invalid packet discriminator from: %s", __func__,
- sockaddr_to_string(ss, errbuf, sizeof(errbuf)));
- return -1;
- }
-
- /* Set the returned sockaddr new length. */
- *sslen = msg.msg_namelen;
-
- return 0;
-}
-
-int ptm_bfd_vxlan_sock_init(void)
-{
- /* TODO: not supported yet. */
- return -1;
-}
-