/* * Copyright (c) 1995, 1996 Gunther Schadow. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "pg_config.h" #include "socket.h" #include #include #include #include #include #include static result split_address(char *addr, char **host, char **serv) { if((*serv = strtok(addr,"%")) == NULL) goto syntax_error; *host = strtok(NULL,"%"); #ifdef MUST_NAME_HOST if(*host == NULL) goto syntax_error; #endif if(strtok(NULL,"%") != NULL) goto syntax_error; return SUCCESS; syntax_error: syslog(LOG_ERR, "inet address must be '%%'"); return FAIL; } int connect_inet(const char *address) { struct sockaddr_in saddr; struct servent *servp; struct hostent *hostp; int sfd; char *addr = strdup(address); char *host, *serv; DBG(syslog(LOG_DEBUG, "opening inet domain socket '%s'", addr)); if(split_address(addr, &host, &serv) == FAIL) goto fail; DBG(syslog(LOG_DEBUG, "host: `%s', service: `%s'", host, serv)); servp = getservbyname(serv, "tcp"); if (servp == NULL) { syslog(LOG_ERR, "service %s/tcp not found", serv); goto fail; } hostp = gethostbyname(host); if (hostp == NULL) { syslog(LOG_ERR, "host %s not found", host); goto fail; } memset(&saddr, 0, sizeof(saddr)); memcpy(&saddr.sin_addr, hostp->h_addr, hostp->h_length); saddr.sin_family = hostp->h_addrtype; saddr.sin_port = servp->s_port; sfd = socket(AF_INET, SOCK_STREAM, 0); if(sfd < 0) { syslog(LOG_ERR, "socket: %m"); goto fail; } if( connect(sfd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0 ) { syslog(LOG_ERR, "connect: %m"); goto fail; } free(addr); return sfd; fail: close(sfd); free(addr); return FAIL; } result shutdown_inet(int sfd) { if( close(sfd) != SUCCESS ) { syslog(LOG_ERR, "close: %m"); return FAIL; } return SUCCESS; } int bind_inet(const char *address) { int sfd; struct sockaddr_in saddr; struct servent *servp; char *addr = strdup(address); char *host, *serv; DBG(syslog(LOG_DEBUG, "opening inet domain socket '%s'", addr)); if(split_address(addr, &host, &serv) == FAIL) goto fail; DBG(syslog(LOG_DEBUG, "host: `%s', service: `%s'", host, serv)); servp = getservbyname(serv, "tcp"); if (servp == NULL) { syslog(LOG_ERR, "service %s/tcp not found", serv); goto fail; } memset(&saddr, 0, sizeof(struct sockaddr_in)); saddr.sin_port = servp->s_port; sfd = socket(AF_INET, SOCK_STREAM, 0); if(sfd < 0) { syslog(LOG_ERR, "socket: %m"); goto fail; } if (bind(sfd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)) < 0) { syslog(LOG_ERR, "bind: %m"); goto fail; } return sfd; fail: return FAIL; } int accept_inet(int sfd) { int cfd; struct sockaddr_in saddr; int len = sizeof(struct sockaddr_in); cfd = accept(sfd, (struct sockaddr *)&saddr, &len); if(cfd == FAIL) { syslog(LOG_ERR, "accept: %m"); goto fail; } return cfd; fail: return FAIL; } result peername_inet(int s, peername_t peer) { struct sockaddr_in sin; int len = sizeof(sin); struct hostent *host_p; if(getpeername(s, (struct sockaddr *)&sin, &len) == FAIL) { syslog(LOG_ERR, "getpeername: %m"); return FAIL; } if((host_p = gethostbyaddr((char *)(&sin.sin_addr), sizeof(struct in_addr), sin.sin_family)) == NULL) { syslog(LOG_ERR, "getpeername: %m"); return FAIL; } strncpy(peer, host_p->h_name, PEERNAME_SIZE); return SUCCESS; }