Example #1
0
static void ss_forward_pkt(redudp_client *client, struct sockaddr * destaddr, void *data, size_t pktlen)
{
    ss_client *ssclient = (void*)(client + 1);
    ss_instance * ss = (ss_instance *)(client->instance+1);
    struct sockaddr_in * relayaddr = &client->instance->config.relayaddr;
    struct msghdr msg;
    struct iovec io[1];
    ssize_t outgoing;
    int rc;
    ss_header_ipv4 header;
    size_t len = 0;
    size_t fwdlen = 0;
    void * buff = client->instance->shared_buff;

    /* build and send header */
    // TODO: Better implementation and IPv6 Support
    header.addr_type = ss_addrtype_ipv4;
    header.addr = ((struct sockaddr_in *)destaddr)->sin_addr.s_addr;
    header.port = ((struct sockaddr_in *)destaddr)->sin_port;

    if (enc_ctx_init(&ss->info, &ss->e_ctx, 1)) {
        redudp_log_error(client, LOG_ERR, "Shadowsocks UDP failed to initialize encryption context.");
        return;
    }
    rc = ss_encrypt(&ss->e_ctx, (char *)&header, sizeof(header), buff, &len);
    if (rc)
    {
        if (len + pktlen < MAX_UDP_PACKET_SIZE)
            rc = ss_encrypt(&ss->e_ctx, (char *)data, pktlen, buff+len, &fwdlen);
        else
            rc = 0;
    }
    enc_ctx_free(&ss->e_ctx);
    if (!rc)
    {
        redudp_log_error(client, LOG_DEBUG, "Can't encrypt packet, dropping it");
        return;
    }
    fwdlen += len;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = relayaddr;
    msg.msg_namelen = sizeof(*relayaddr);
    msg.msg_iov = io;
    msg.msg_iovlen = SIZEOF_ARRAY(io);

    io[0].iov_base = buff;
    io[0].iov_len = fwdlen;

    outgoing = sendmsg(event_get_fd(&ssclient->udprelay), &msg, 0);
    if (outgoing == -1) {
        redudp_log_errno(client, LOG_DEBUG, "sendmsg: Can't forward packet, dropping it");
        return;
    }
    else if (outgoing != fwdlen) {
        redudp_log_error(client, LOG_DEBUG, "sendmsg: I was sending %zd bytes, but only %zd were sent.", fwdlen, outgoing);
        return;
    }
}
Example #2
0
static void ss_pkt_from_server(int fd, short what, void *_arg)
{
    redudp_client *client = _arg;
    ss_client *ssclient = (void*)(client + 1);
    ss_instance * ss = (ss_instance *)(client->instance+1);
    ss_header_ipv4  * header;
    ssize_t pktlen;
    size_t  fwdlen;
    struct sockaddr_in udprelayaddr;
    int rc;
    void * buff = client->instance->shared_buff;
    void * buff2 = ss->buff;

    assert(fd == event_get_fd(&ssclient->udprelay));

    pktlen = red_recv_udp_pkt(fd, buff, MAX_UDP_PACKET_SIZE, &udprelayaddr, NULL);
    if (pktlen == -1)
        return;

    if (enc_ctx_init(&ss->info, &ss->d_ctx, 0)) {
        redudp_log_error(client, LOG_ERR, "Shadowsocks UDP failed to initialize decryption context.");
        return;
    }
    rc = ss_decrypt(&ss->d_ctx, buff, pktlen, buff2, &fwdlen);
    enc_ctx_free(&ss->d_ctx);
    if (!rc) {
        redudp_log_error(client, LOG_DEBUG, "Can't decrypt packet, dropping it");
        return;
    }
    header = (ss_header_ipv4 *)buff2;
    // We do not verify src address, but at least, we need to ensure address type is correct.
    if (header->addr_type != ss_addrtype_ipv4) {
        redudp_log_error(client, LOG_DEBUG, "Got address type #%u instead of expected #%u (IPv4).",
                        header->addr_type, ss_addrtype_ipv4);
        return;
    }

    struct sockaddr_in pktaddr = {
        .sin_family = AF_INET,
        .sin_addr   = { header->addr },
        .sin_port   = header->port,
    };

    if (fwdlen < sizeof(*header)) {
        redudp_log_error(client, LOG_DEBUG, "Packet too short.");
        return;
    }
    fwdlen -= sizeof(*header);
    redudp_fwd_pkt_to_sender(client, buff2 + sizeof(*header), fwdlen, &pktaddr);
}
Example #3
0
static void ss_client_fini(redsocks_client *client)
{
    ss_client *sclient = (void*)(client + 1);
    enc_ctx_free(&sclient->e_ctx);
    enc_ctx_free(&sclient->d_ctx);
}