/* * Get a UDP socket, bind it, figure out the port, * and advertise the port as program "prog". * * XXX - it would be nice if you could advertise ascii strings. */ int udp_server(u_long prog, int rdwr) { int sock; struct sockaddr_in s; if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); exit(1); } sock_optimize(sock, rdwr); bzero((void*)&s, sizeof(s)); s.sin_family = AF_INET; #ifdef NO_PORTMAPPER s.sin_port = htons(prog); #endif if (bind(sock, (struct sockaddr*)&s, sizeof(s)) < 0) { perror("bind"); exit(2); } #ifdef PORTMAP (void)pmap_unset(prog, (u_long)1); if (!pmap_set(prog, (u_long)1, (u_long)IPPROTO_UDP, (unsigned short)sockport(sock))) { perror("pmap_set"); exit(5); } #endif return (sock); }
/* * Accept a connection and return it */ int tcp_accept(int sock, int rdwr) { struct sockaddr_in s; int newsock; socklen_t namelen; namelen = sizeof(s); bzero((void*)&s, namelen); retry: if ((newsock = accept(sock, (struct sockaddr*)&s, &namelen)) < 0) { if (errno == EINTR) goto retry; perror("accept"); exit(6); } #ifdef LIBTCP_VERBOSE fprintf(stderr, "Server newsock port %d\n", sockport(newsock)); #endif sock_optimize(newsock, rdwr); return (newsock); }
// NOTE: this function can create multiple listen sockets, but will only return the last one! listen_socket * new_listen_socket(uint16_t listen_port, uint8_t protocol) { struct addrinfo hints; struct addrinfo *result, *rp; int s; char service[7]; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; hints.ai_protocol = 0; hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; snprintf(service, 7, "%d", listen_port); if ((s = getaddrinfo(NULL, service, &hints, &result)) != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); exit(1); } listen_socket *listensock; for (rp = result; rp != NULL; rp = rp->ai_next) { listensock = malloc(sizeof(listen_socket)); listensock->type = SOCKTYPE_LISTEN; memcpy(&listensock->addr, rp->ai_addr, rp->ai_addrlen); listensock->fd = socket(rp->ai_family, SOCK_STREAM, IPPROTO_TCP); int yes = 1; if (setsockopt(listensock->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } if (rp->ai_family == AF_INET6) { if (setsockopt(listensock->fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } } if (bind(listensock->fd, rp->ai_addr, rp->ai_addrlen) == -1) { perror("bind"); exit(1); } if (listen(listensock->fd, SOMAXCONN) == -1) { perror("listen"); exit(1); } sock2a(rp->ai_addr, buf, BUFFER_SIZE); fprintf(stderr, "Listening on %s\n", buf); listensock->port = sockport(rp->ai_addr); listensock->protocol = protocol; readsockets = array_push(readsockets, listensock); errorsockets = array_push(errorsockets, listensock); } freeaddrinfo(result); return listensock; }