vfs: check userland buffers before reading them.
[haiku.git] / src / tests / kits / net / sock / cliopen.c
blobace24602bc1def49e92d68a8866f8e9843fa0c95
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 */
11 #include "sock.h"
13 int cliopen(char *host, char *port)
15 int fd, i, on;
16 char *protocol;
17 struct in_addr inaddr;
18 struct servent *sp;
19 struct hostent *hp;
21 protocol = udp ? "udp" : "tcp";
23 /* initialize socket address structure */
24 bzero(&servaddr, sizeof(servaddr));
25 servaddr.sin_family = AF_INET;
27 /* see if "port" is a service name or number */
28 if ( (i = atoi(port)) == 0) {
29 if ( (sp = getservbyname(port, protocol)) == NULL)
30 err_quit("getservbyname() error for: %s/%s", port, protocol);
32 servaddr.sin_port = sp->s_port;
33 } else
34 servaddr.sin_port = htons(i);
37 * First try to convert the host name as a dotted-decimal number.
38 * Only if that fails do we call gethostbyname().
41 if (inet_aton(host, &inaddr) == 1)
42 servaddr.sin_addr = inaddr; /* it's dotted-decimal */
43 else if ( (hp = gethostbyname(host)) != NULL)
44 bcopy(hp->h_addr, &servaddr.sin_addr, hp->h_length);
45 else
46 err_quit("invalid hostname: %s", host);
48 if ( (fd = socket(AF_INET, udp ? SOCK_DGRAM : SOCK_STREAM, 0)) < 0)
49 err_sys("socket() error");
51 if (reuseaddr) {
52 on = 1;
53 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
54 err_sys("setsockopt of SO_REUSEADDR error");
57 #ifdef SO_REUSEPORT
58 if (reuseport) {
59 on = 1;
60 if (setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof (on)) < 0)
61 err_sys("setsockopt of SO_REUSEPORT error");
63 #endif
66 * User can specify port number for client to bind. Only real use
67 * is to see a TCP connection initiated by both ends at the same time.
68 * Also, if UDP is being used, we specifically call bind() to assign
69 * an ephemeral port to the socket.
70 * Also, for experimentation, client can also set local IP address
71 * (and port) using -l option. Allow localip[] to be set but bindport
72 * to be 0.
75 if (bindport != 0 || localip[0] != 0 || udp) {
76 bzero(&cliaddr, sizeof(cliaddr));
77 cliaddr.sin_family = AF_INET;
78 cliaddr.sin_port = htons(bindport); /* can be 0 */
79 if (localip[0] != 0) {
80 if (inet_aton(localip, &cliaddr.sin_addr) == 0)
81 err_quit("invalid IP address: %s", localip);
82 } else
83 cliaddr.sin_addr.s_addr = htonl(INADDR_ANY); /* wildcard */
85 if (bind(fd, (struct sockaddr *) &cliaddr, sizeof(cliaddr)) < 0)
86 err_sys("bind() error");
89 /* Need to allocate buffers before connect(), since they can affect
90 * TCP options (window scale, etc.).
93 buffers(fd);
94 sockopts(fd, 0); /* may also want to set SO_DEBUG */
97 * Connect to the server. Required for TCP, optional for UDP.
100 if (udp == 0 || connectudp) {
101 for ( ; ; ) {
102 if (connect(fd, (struct sockaddr *) &servaddr, sizeof(servaddr))
103 == 0)
104 break; /* all OK */
105 if (errno == EINTR) /* can happen with SIGIO */
106 continue;
107 if (errno == EISCONN) /* can happen with SIGIO */
108 break;
109 err_sys("connect() error");
113 if (verbose) {
114 /* Call getsockname() to find local address bound to socket:
115 TCP ephemeral port was assigned by connect() or bind();
116 UDP ephemeral port was assigned by bind(). */
117 i = sizeof(cliaddr);
118 if (getsockname(fd, (struct sockaddr *) &cliaddr, &i) < 0)
119 err_sys("getsockname() error");
121 /* Can't do one fprintf() since inet_ntoa() stores
122 the result in a static location. */
123 fprintf(stderr, "connected on %s.%d ",
124 INET_NTOA(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
125 fprintf(stderr, "to %s.%d\n",
126 INET_NTOA(servaddr.sin_addr), ntohs(servaddr.sin_port));
129 sockopts(fd, 1); /* some options get set after connect() */
131 return(fd);