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; }