1 #define _BSD_EXTENSION
2 #define _NET_EXTENSION
3 #define _POSIX_SOURCE
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <ctype.h>
9 #include <string.h>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <netdb.h>
14 #include <sys/time.h>
15
16 #define DIALTIMEOUT 30
17
18 /* This is a dummy routine for non Plan9 systems.
19 * No attempt has been made to be clever, it's just
20 * supposed to work in this program.
21 */
22 int dial_debug = 0;
23
24 int
dial(char * dest,char * local,char * dir,int * cfdp)25 dial(char *dest, char *local, char *dir, int *cfdp) {
26 int sockconn, lport;
27 struct hostent *hp; /* Pointer to host info */
28 struct sockaddr_in sin; /* Socket address, Internet style */
29 struct servent *sp = 0;
30 char *tdest, *netname, *hostname, *servname;
31 int sock_type;
32 #ifndef plan9
33 #define USED(x) if(x); else
34 int sockoption, sockoptsize;
35 #endif
36
37 USED(dir);
38 USED(cfdp);
39 if ((tdest = malloc(strlen(dest)+1)) == NULL) {
40 if (dial_debug) fprintf(stderr, "dial: could not allocate memory\n");
41 return(-1);
42 }
43 strcpy(tdest, dest);
44
45 if ((netname = strtok(tdest, "!")) == NULL) {
46 fprintf(stderr, "dial: no network name\n");
47 return(-1);
48 }
49 if (strcmp(netname, "tcp") == 0) {
50 sock_type = SOCK_STREAM;
51 } else if (strcmp(netname, "udp") == 0) {
52 sock_type = SOCK_DGRAM;
53 } else {
54 fprintf(stderr, "dial: network protocol name `%s' is invalid; must be `tcp' or `udp'\n", netname);
55 return(-1);
56 }
57 if ((hostname = strtok(0, "!")) == NULL) {
58 fprintf(stderr, "dial: no host name or number\n");
59 return(-1);
60 }
61 if ((servname = strtok(0, "!")) == NULL) {
62 fprintf(stderr, "dial: no service name or number\n");
63 return(-1);
64 }
65 hp = gethostbyname(hostname);
66 if (hp == (struct hostent *)NULL) {
67 if (dial_debug) fprintf(stderr, "host `%s' unknown by local host\n", hostname);
68 return(-1);
69 }
70 if (!isdigit(servname[0]))
71 sp = getservbyname(servname, netname);
72 sin.sin_addr.s_addr = *(unsigned long*)hp->h_addr;
73 sin.sin_port = htons((sp==0)?atoi(servname):sp->s_port);
74 sin.sin_family = AF_INET;
75 if (local == NULL) {
76 if ((sockconn = socket(AF_INET, sock_type, 0)) < 0) {
77 if (dial_debug) perror("dial:socket():");
78 return(-1);
79 }
80 if (dial_debug) fprintf(stderr, "socket FD=%d\n", sockconn);
81 } else {
82 lport = atoi(local);
83 if ((lport < 512) || (lport >= 1024)) {
84 fprintf(stderr, "dial:invalid local port %d\n", lport);
85 return(-1);
86 }
87 if ((sockconn = rresvport(&lport)) < 0) {
88 if (dial_debug) perror("dial:rresvport():");
89 return(-1);
90 }
91 }
92 if (dial_debug) {
93 fprintf(stderr, "sin size=%d\n", sizeof(sin));
94 }
95 alarm(DIALTIMEOUT);
96 if ((connect(sockconn, (struct sockaddr *) &sin, sizeof(sin)) < 0)) {
97 if (dial_debug) perror("dial:connect():");
98 return(-1);
99 }
100 alarm(0);
101 #ifndef plan9
102 sockoptsize = sizeof(sockoption);
103 if (getsockopt(sockconn, SOL_SOCKET, SO_KEEPALIVE, &sockoption, &sockoptsize) < 0) {
104 if (dial_debug) perror("dial:getsockopt():");
105 return(-1);
106 }
107 if (sockoptsize == sizeof(sockoption) && !sockoption) {
108 if (setsockopt(sockconn, SOL_SOCKET, SO_KEEPALIVE, &sockoption, sockoptsize) < 0) {
109 if (dial_debug) perror("dial:getsockopt():");
110 return(-1);
111 }
112 }
113 #endif
114 return(sockconn);
115 }
116