Exemple #1
0
int red_recv_udp_pkt(int fd, char *buf, size_t buflen, struct sockaddr_in *inaddr, struct sockaddr_in *toaddr)
{
    socklen_t addrlen = sizeof(*inaddr);
    ssize_t pktlen;
    struct msghdr msg;
    struct iovec io;
    char control[1024];

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = inaddr;
    msg.msg_namelen = sizeof(*inaddr);
    msg.msg_iov = &io;
    msg.msg_iovlen = 1;
    msg.msg_control = control;
    msg.msg_controllen = sizeof(control);
    io.iov_base = buf;
    io.iov_len = buflen;

    pktlen = recvmsg(fd, &msg, 0);
    if (pktlen == -1) {
        log_errno(LOG_WARNING, "recvfrom");
        return -1;
    }

    if (toaddr) {
        memset(toaddr, 0, sizeof(*toaddr));
        for (struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
            if (
                cmsg->cmsg_level == SOL_IP &&
                cmsg->cmsg_type == IP_ORIGDSTADDR &&
                cmsg->cmsg_len >= CMSG_LEN(sizeof(*toaddr))
            ) {
                struct sockaddr_in* cmsgaddr = (struct sockaddr_in*)CMSG_DATA(cmsg);
                memcpy(toaddr, cmsgaddr, sizeof(*toaddr));
            }
            else {
                log_error(LOG_WARNING, "unexepcted cmsg (level,type) = (%d,%d)",
                    cmsg->cmsg_level, cmsg->cmsg_type);
            }
        }
        if (toaddr->sin_family != AF_INET) {
            log_error(LOG_WARNING, "(SOL_IP, IP_ORIGDSTADDR) not found");
            return -1;
        }
    }

    if (addrlen != sizeof(*inaddr)) {
        log_error(LOG_WARNING, "unexpected address length %u instead of %zu", addrlen, sizeof(*inaddr));
        return -1;
    }

    if (pktlen >= buflen) {
        char buf[RED_INET_ADDRSTRLEN];
        log_error(LOG_WARNING, "wow! Truncated udp packet of size %zd from %s! impossible! dropping it...",
                  pktlen, red_inet_ntop(inaddr, buf, sizeof(buf)));
        return -1;
    }

    return pktlen;
}
Exemple #2
0
static int ss_instance_init(struct redudp_instance_t *instance)
{
    ss_instance * ss = (ss_instance *)(instance+1);
    const redudp_config *config = &instance->config;
    char buf1[RED_INET_ADDRSTRLEN];

    int valid_cred =  ss_is_valid_cred(config->login, config->password);
    if (!valid_cred 
    || (ss->method = enc_init(&ss->info, config->password, config->login), ss->method == -1))
    {
        log_error(LOG_ERR, "Invalided encrytion method or password.");
        return -1;
    }
    else
    {
        log_error(LOG_INFO, "%s @ %s: encryption method: %s",
            instance->relay_ss->name,
            red_inet_ntop(&instance->config.bindaddr, buf1, sizeof(buf1)),
            config->login);
    }
    // An additional buffer is allocated for each instance for encryption/decrption.
    ss->buff = malloc(MAX_UDP_PACKET_SIZE);
    if (!ss->buff) {
        log_error(LOG_ERR, "Out of memory.");
        return -1;
    }
    return 0;
}