Esempio n. 1
0
int
udp_attach(PNATState pData, struct socket *so)
{
    struct sockaddr_in *addr;
    struct sockaddr sa_addr;
    socklen_t socklen = sizeof(struct sockaddr);
    int status;
    int opt = 1;

    /* We attaching some olready attched socket ??? */
    Assert(so->so_type == 0);
    if ((so->s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
        goto error;
    /*
     * Here, we bind() the socket.  Although not really needed
     * (sendto() on an unbound socket will bind it), it's done
     * here so that emulation of ytalk etc. don't have to do it
     */
    memset(&sa_addr, 0, sizeof(struct sockaddr));
    addr = (struct sockaddr_in *)&sa_addr;
#ifdef RT_OS_DARWIN
    addr->sin_len = sizeof(struct sockaddr_in);
#endif
    addr->sin_family = AF_INET;
    addr->sin_addr.s_addr = pData->bindIP.s_addr;
    fd_nonblock(so->s);
    if (bind(so->s, &sa_addr, sizeof(struct sockaddr_in)) < 0)
    {
        int lasterrno = errno;
        closesocket(so->s);
        so->s = -1;
#ifdef RT_OS_WINDOWS
        WSASetLastError(lasterrno);
#else
        errno = lasterrno;
#endif
        goto error;
    }
    /* success, insert in queue */
    so->so_expire = curtime + SO_EXPIRE;
    /* enable broadcast for later use */
    setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));
    status = getsockname(so->s, &sa_addr, &socklen);
    Assert(status == 0 && sa_addr.sa_family == AF_INET);
    so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
    so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;

    SOCKET_LOCK_CREATE(so);
    QSOCKET_LOCK(udb);
    insque(pData, so, &udb);
    NSOCK_INC();
    QSOCKET_UNLOCK(udb);
    so->so_type = IPPROTO_UDP;
    return so->s;
error:
    Log2(("NAT: can't create datagramm socket\n"));
    return -1;
}
int
udp_attach(PNATState pData, struct socket *so)
{
    struct sockaddr sa_addr;
    socklen_t socklen = sizeof(struct sockaddr);
    int status;
    int opt = 1;

    AssertReturn(so->so_type == 0, -1);
    so->so_type = IPPROTO_UDP;

    so->s = socket(AF_INET, SOCK_DGRAM, 0);
    if (so->s == -1)
        goto error;
    fd_nonblock(so->s);

    so->so_sottl = 0;
    so->so_sotos = 0;
    so->so_sodf = -1;

    status = sobind(pData, so);
    if (status != 0)
        return status;

    /* success, insert in queue */
    so->so_expire = curtime + SO_EXPIRE;

    /* enable broadcast for later use */
    setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));

    status = getsockname(so->s, &sa_addr, &socklen);
    if (status == 0)
    {
        Assert(sa_addr.sa_family == AF_INET);
        so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
        so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;
    }

    SOCKET_LOCK_CREATE(so);
    QSOCKET_LOCK(udb);
    insque(pData, so, &udb);
    NSOCK_INC();
    QSOCKET_UNLOCK(udb);
    return so->s;
error:
    Log2(("NAT: can't create datagram socket\n"));
    return -1;
}
struct socket *
udp_listen(PNATState pData, u_int32_t bind_addr, u_int port, u_int32_t laddr, u_int lport, int flags)
{
    struct sockaddr_in addr;
    struct socket *so;
    socklen_t addrlen = sizeof(struct sockaddr_in);
    int opt = 1;
    LogFlowFunc(("ENTER: bind_addr:%RTnaipv4, port:%d, laddr:%RTnaipv4, lport:%d, flags:%x\n",
                 bind_addr, RT_N2H_U16(port), laddr, RT_N2H_U16(lport), flags));

    if ((so = socreate()) == NULL)
    {
        LogFlowFunc(("LEAVE: NULL\n"));
        return NULL;
    }

    so->s = socket(AF_INET, SOCK_DGRAM, 0);
    if (so->s == -1)
    {
        LogRel(("NAT: can't create datagram socket\n"));
        RTMemFree(so);
        LogFlowFunc(("LEAVE: NULL\n"));
        return NULL;
    }
    so->so_expire = curtime + SO_EXPIRE;
    so->so_type = IPPROTO_UDP;
    fd_nonblock(so->s);
    so->so_sottl = 0;
    so->so_sotos = 0;
    so->so_sodf = -1;
    SOCKET_LOCK_CREATE(so);
    QSOCKET_LOCK(udb);
    insque(pData, so, &udb);
    NSOCK_INC();
    QSOCKET_UNLOCK(udb);

    memset(&addr, 0, sizeof(addr));
#ifdef RT_OS_DARWIN
    addr.sin_len = sizeof(addr);
#endif
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = bind_addr;
    addr.sin_port = port;

    if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0)
    {
        LogRel(("NAT: udp bind to %RTnaipv4:%d failed, error %d\n",
                addr.sin_addr, RT_N2H_U16(port), errno));
        udp_detach(pData, so);
        LogFlowFunc(("LEAVE: NULL\n"));
        return NULL;
    }
    setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR,(char *)&opt, sizeof(int));
/*  setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE,(char *)&opt, sizeof(int)); */

    getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
    so->so_hladdr = addr.sin_addr;
    so->so_hlport = addr.sin_port;

    /* XXX: wtf are we setting so_faddr/so_fport here? */
    so->so_fport = addr.sin_port;
#if 0
    /* The original check was completely broken, as the commented out
     * if statement was always true (INADDR_ANY=0). */
    /** @todo vvl - alias_addr should be set (if required)
     * later by liabalias module.
     */
    if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
        so->so_faddr = alias_addr;
    else
#endif
        so->so_faddr = addr.sin_addr;

    so->so_lport = lport;
    so->so_laddr.s_addr = laddr;
    if (flags != SS_FACCEPTONCE)
        so->so_expire = 0;

    so->so_state = SS_ISFCONNECTED;

    LogFlowFunc(("LEAVE: %R[natsock]\n", so));
    return so;
}