vfs: check userland buffers before reading them.
[haiku.git] / src / tests / kits / net / sock / servopen.c
blob7b61d7ea4fb66c30956830bbd05ab5be0d83d330
1 /* -*- c-basic-offset: 8; -*-
3 * Copyright (c) 1993 W. Richard Stevens. All rights reserved.
4 * Permission to use or modify this software and its documentation only for
5 * educational purposes and without fee is hereby granted, provided that
6 * the above copyright notice appear in all copies. The author makes no
7 * representations about the suitability of this software for any purpose.
8 * It is provided "as is" without express or implied warranty.
9 */
12 #include <stdio.h>
13 #include <netdb.h>
14 #include <sys/types.h>
15 #include <netinet/in.h>
16 #include <arpa/inet.h>
17 #include "sock.h"
19 int
20 servopen(char *host, char *port)
22 int fd, newfd, i, on, pid;
23 char *protocol;
24 struct in_addr inaddr;
25 struct servent *sp;
27 protocol = udp ? "udp" : "tcp";
29 /* Initialize the socket address structure */
30 bzero(&servaddr, sizeof(servaddr));
31 servaddr.sin_family = AF_INET;
33 /* Caller normally wildcards the local Internet address, meaning
34 a connection will be accepted on any connected interface.
35 We only allow an IP address for the "host", not a name. */
36 if (host == NULL)
37 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */
38 else {
39 if (inet_aton(host, &inaddr) == 0)
40 err_quit("invalid host name for server: %s", host);
41 servaddr.sin_addr = inaddr;
44 /* See if "port" is a service name or number */
45 if ( (i = atoi(port)) == 0) {
46 if ( (sp = getservbyname(port, protocol)) == NULL)
47 err_ret("getservbyname() error for: %s/%s", port, protocol);
49 servaddr.sin_port = sp->s_port;
50 } else
51 servaddr.sin_port = htons(i);
53 if ( (fd = socket(AF_INET, udp ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0)
54 err_sys("socket() error");
56 if (reuseaddr) {
57 on = 1;
58 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
59 err_sys("setsockopt of SO_REUSEADDR error");
62 #ifdef SO_REUSEPORT
63 if (reuseport) {
64 on = 1;
65 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0)
66 err_sys("setsockopt of SO_REUSEPORT error");
68 #endif
70 /* Bind our well-known port so the client can connect to us. */
71 if (bind(fd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
72 err_sys("can't bind local address");
74 join_mcast(fd, &servaddr);
76 if (udp) {
77 buffers(fd);
79 if (foreignip[0] != 0) { /* connect to foreignip/port# */
80 bzero(&cliaddr, sizeof(cliaddr));
81 if (inet_aton(foreignip, &cliaddr.sin_addr) == 0)
82 err_quit("invalid IP address: %s", foreignip);
83 cliaddr.sin_family = AF_INET;
84 cliaddr.sin_port = htons(foreignport);
85 /* connect() for datagram socket doesn't appear to allow
86 wildcarding of either IP address or port number */
88 if (connect(fd, (struct sockaddr *) &cliaddr, sizeof(cliaddr))
89 < 0)
90 err_sys("connect() error");
94 sockopts(fd, 1);
96 return(fd); /* nothing else to do */
99 buffers(fd); /* may set receive buffer size; must do here to get
100 correct window advertised on SYN */
101 sockopts(fd, 0); /* only set some socket options for fd */
103 listen(fd, listenq);
105 if (pauselisten)
106 sleep_us(pauselisten*1000); /* lets connection queue build up */
108 if (dofork)
109 TELL_WAIT(); /* initialize synchronization primitives */
111 for ( ; ; ) {
112 i = sizeof(cliaddr);
113 if ( (newfd = accept(fd, (struct sockaddr *) &cliaddr, &i)) < 0)
114 err_sys("accept() error");
116 if (dofork) {
117 if ( (pid = fork()) < 0)
118 err_sys("fork error");
120 if (pid > 0) {
121 close(newfd); /* parent closes connected socket */
122 WAIT_CHILD(); /* wait for child to output to terminal */
123 continue; /* and back to for(;;) for another accept() */
124 } else {
125 close(fd); /* child closes listening socket */
129 /* child (or iterative server) continues here */
130 if (verbose) {
131 /* Call getsockname() to find local address bound to socket:
132 local internet address is now determined (if multihomed). */
133 i = sizeof(servaddr);
134 if (getsockname(newfd, (struct sockaddr *) &servaddr, &i) < 0)
135 err_sys("getsockname() error");
137 /* Can't do one fprintf() since inet_ntoa() stores
138 the result in a static location. */
139 fprintf(stderr, "connection on %s.%d ",
140 INET_NTOA(servaddr.sin_addr), ntohs(servaddr.sin_port));
141 fprintf(stderr, "from %s.%d\n",
142 INET_NTOA(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
145 buffers(newfd); /* setsockopt() again, in case it didn't propagate
146 from listening socket to connected socket */
147 sockopts(newfd, 1); /* can set all socket options for this socket */
149 if (dofork)
150 TELL_PARENT(getppid()); /* tell parent we're done with terminal */
152 return(newfd);