/* * Copyright © 2005,2008 Red Hat, Inc. All rights reserved. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions of the * GNU General Public License v.2. This program is distributed in the hope * that it will be useful, but WITHOUT ANY WARRANTY expressed or implied, * including the implied warranties 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., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat * trademarks that are incorporated in the source code or documentation are not * subject to the GNU General Public License and may only be used or replicated * with the express permission of Red Hat, Inc. * * Red Hat Author(s): Nathan Straz * Dean Jansa */ #include #include #include #include #include #include #include #include #include #include #include "qarsh_packet.h" /* Some generic socket related functions to make things easier */ int getsockport(int sd) { struct sockaddr_in addr; socklen_t addrlen; addrlen = sizeof addr; if (getsockname(sd, (struct sockaddr *)&addr, &addrlen) == 0) { return ntohs(addr.sin_port); } else { return -1; } } int bind_any(int minport) { int sd; struct sockaddr_in addr; sd = socket(AF_INET, SOCK_STREAM, 0); if (sd == -1) return -1; addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); do { addr.sin_port = htons(minport++); } while (bind(sd, (struct sockaddr *)&addr, sizeof addr) != 0); if (listen(sd, 0) == -1) { syslog(LOG_WARNING, "listen error %d, %s", errno, strerror(errno)); } return sd; } int connect_to_host(char *hostname, int port) { struct hostent *h; struct sockaddr_in haddr; int sd; if ((h = gethostbyname(hostname)) == NULL) { return -1; } haddr.sin_family = h->h_addrtype; haddr.sin_port = htons(port); memcpy(&haddr.sin_addr, h->h_addr, h->h_length); sd = socket(PF_INET, SOCK_STREAM, 0); if (sd == -1) return -1; if (connect(sd, (struct sockaddr *)&haddr, sizeof haddr) == -1) { return -1; } return sd; } int connect_to_peer(struct sockaddr_in *peer, int port) { struct sockaddr_in in_peer; int sd; int fdflags; in_peer.sin_family = AF_INET; in_peer.sin_port = htons(port); in_peer.sin_addr = peer->sin_addr; sd = socket(PF_INET, SOCK_STREAM, 0); if (sd == -1) return -1; /* Set close-on-exec for these sds */ if ((fdflags = fcntl(sd, F_GETFD, 0)) < 0) { return -1; } fdflags |= FD_CLOEXEC; if (fcntl(sd, F_SETFD, fdflags) < 0) { return -1; } if (connect(sd, (struct sockaddr *)&in_peer, sizeof in_peer) == -1) { return -1; } return sd; } struct qa_packet * recv_packet(int fd) { char *packetbuf; int packetsize; struct qa_packet *qp = NULL; packetbuf = malloc(QARSH_MAX_PACKET_SIZE); memset(packetbuf, 0, QARSH_MAX_PACKET_SIZE); packetsize = read(fd, packetbuf, QARSH_MAX_PACKET_SIZE); if (packetsize > 0) { qp = parse_packets(packetbuf, packetsize); } free(packetbuf); return qp; } int send_packet(int fd, struct qa_packet *qp) { char *packetbuf; int packetsize; ssize_t ret; packetbuf = qptostr(qp, &packetbuf, &packetsize); ret = write(fd, packetbuf, packetsize); free(packetbuf); return ret; }