/* * Copyright (c) 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: sockconn.c,v 1.1 2005/08/24 20:56:17 ca Exp $") #include "sm/assert.h" #include "sm/error.h" #include "sm/memops.h" #include "sm/fcntl.h" #include "sm/net.h" #include "sm/sockcnf.h" #include "sm/socket.h" /* ** SOCK_CONNECT -- Create a socket and connect it to a server. ** ** Parameters: ** sock -- address to bind to. ** pfd -- (pointer to) file descriptor (output) ** ** Returns: ** usual error code */ sm_ret_T sock_connect(sockspec_P sock, int *pfd) { sm_ret_T ret; int sockfd; sockaddr_len_T sock_size; sm_sockaddr_T sm_sockaddr; SM_ASSERT(sock != NULL); SM_ASSERT(pfd != NULL); sm_memset(&sm_sockaddr, 0, sizeof(sm_sockaddr)); sockfd = INVALID_SOCKET; switch (sock->sckspc_type) { case SOCK_TYPE_INET: sm_sockaddr.sin.sin_family = AF_INET; sm_sockaddr.sin.sin_addr.s_addr = sock->sock_inet.inetsckspc_addr; sm_sockaddr.sin.sin_port = sock->sock_inet.inetsckspc_port; sock_size = sizeof(sm_sockaddr.sin); break; case SOCK_TYPE_UNIX: { size_t len; sm_sockaddr.sunix.sun_family = AF_UNIX; len = strlcpy(sm_sockaddr.sunix.sun_path, sock->sock_unix.unixsckspc_path, sizeof(sm_sockaddr.sunix.sun_path)); if (len <= 0 || len >= sizeof(sm_sockaddr.sunix.sun_path)) return sm_error_perm(SM_EM_NET, SM_E_2BIG); #if HAVE_SOCK_UN_SUN_LEN sm_sockaddr.sunix.sun_len = strlen(sock->sock_unix.unixsckspc_path); #endif sock_size = sizeof(sm_sockaddr.sunix); break; } default: return sm_error_perm(SM_EM_NET, EINVAL); } sockfd = socket(sm_sockaddr.sa.sa_family, SOCK_STREAM, 0); if (sockfd == INVALID_SOCKET) return sm_error_perm(SM_EM_NET, errno); if ((connect(sockfd, (struct sockaddr *) &(sm_sockaddr.sa), sock_size)) == -1) { ret = sm_error_perm(SM_EM_NET, errno); goto error; } *pfd = sockfd; return SM_SUCCESS; error: if (sockfd != INVALID_SOCKET) closesocket(sockfd); return ret; }