]>
Commit | Line | Data |
---|---|---|
fc8c9395 | 1 | diff -bru gawk-3.1.5.orig/io.c gawk-3.1.5/io.c |
2 | --- gawk-3.1.5.orig/io.c 2006-07-07 16:13:08.000000000 +0200 | |
3 | +++ gawk-3.1.5/io.c 2006-07-10 13:18:13.000000000 +0200 | |
4 | @@ -71,7 +71,6 @@ | |
5 | extern int MRL; | |
6 | ||
7 | #ifdef HAVE_SOCKETS | |
8 | -enum inet_prot { INET_NONE, INET_TCP, INET_UDP, INET_RAW }; | |
9 | ||
10 | #ifndef SHUT_RD | |
11 | #define SHUT_RD 0 | |
12 | @@ -1133,24 +1132,60 @@ | |
13 | /* socketopen --- open a socket and set it into connected state */ | |
14 | ||
15 | static int | |
16 | -socketopen(enum inet_prot type, int localport, int remoteport, const char *remotehostname) | |
17 | +socketopen(int type, const char *localpname, const char *remotepname, | |
18 | + const char *remotehostname) | |
19 | { | |
20 | - struct hostent *hp = gethostbyname(remotehostname); | |
21 | - struct sockaddr_in local_addr, remote_addr; | |
22 | + struct addrinfo *lres, *lres0; | |
23 | + struct addrinfo lhints; | |
24 | + struct addrinfo *rres, *rres0; | |
25 | + struct addrinfo rhints; | |
26 | + | |
27 | + int lerror; | |
28 | + int rerror; | |
29 | + | |
30 | int socket_fd; | |
31 | int any_remote_host = strcmp(remotehostname, "0"); | |
32 | ||
33 | + memset (&lhints, '\0', sizeof (lhints)); | |
34 | + lhints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; | |
35 | + lhints.ai_socktype = type; | |
36 | + | |
37 | + lerror = getaddrinfo (NULL, localpname, &lhints, &lres); | |
38 | + if (lerror) { | |
39 | + if (strcmp(localpname, "0")) | |
40 | + fatal(_("local port invalid in `/inet'")); | |
41 | + lres0 = NULL; | |
42 | + lres = &lhints; | |
43 | + } else | |
44 | + lres0 = lres; | |
45 | + | |
46 | + while (lres) { | |
47 | + memset (&rhints, '\0', sizeof (rhints)); | |
48 | + rhints.ai_flags = lhints.ai_flags; | |
49 | + rhints.ai_socktype = lhints.ai_socktype; | |
50 | + rhints.ai_family = lhints.ai_family; | |
51 | + rhints.ai_protocol = lhints.ai_protocol; | |
52 | + | |
53 | + rerror = getaddrinfo (remotehostname, remotepname, &rhints, &rres); | |
54 | + if (rerror) { | |
55 | + if (lres0) | |
56 | + freeaddrinfo(lres0); | |
57 | + fatal(_("remote host and port information invalid")); | |
58 | + } | |
59 | + rres0 = rres; | |
60 | socket_fd = INVALID_HANDLE; | |
61 | - switch (type) { | |
62 | - case INET_TCP: | |
63 | - if (localport != 0 || remoteport != 0) { | |
64 | + while (rres) { | |
65 | + socket_fd = socket (rres->ai_family, | |
66 | + rres->ai_socktype, rres->ai_protocol); | |
67 | + if (socket_fd < 0 || socket_fd == INVALID_HANDLE) | |
68 | + goto nextrres; | |
69 | + | |
70 | + if (type == SOCK_STREAM) { | |
71 | int on = 1; | |
72 | #ifdef SO_LINGER | |
73 | struct linger linger; | |
74 | - | |
75 | memset(& linger, '\0', sizeof(linger)); | |
76 | #endif | |
77 | - socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
78 | setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, | |
79 | (char *) & on, sizeof(on)); | |
80 | #ifdef SO_LINGER | |
81 | @@ -1160,57 +1195,27 @@ | |
82 | (char *) & linger, sizeof(linger)); | |
83 | #endif | |
84 | } | |
85 | - break; | |
86 | - case INET_UDP: | |
87 | - if (localport != 0 || remoteport != 0) | |
88 | - socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); | |
89 | - break; | |
90 | - case INET_RAW: | |
91 | -#ifdef SOCK_RAW | |
92 | - if (localport == 0 && remoteport == 0) | |
93 | - socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); | |
94 | -#endif | |
95 | - break; | |
96 | - case INET_NONE: | |
97 | - /* fall through */ | |
98 | - default: | |
99 | - cant_happen(); | |
100 | - break; | |
101 | - } | |
102 | + if (bind(socket_fd, lres->ai_addr, lres->ai_addrlen) != 0) | |
103 | + goto nextrres; | |
104 | ||
105 | - if (socket_fd < 0 || socket_fd == INVALID_HANDLE | |
106 | - || (hp == NULL && any_remote_host != 0)) | |
107 | - return INVALID_HANDLE; | |
108 | - | |
109 | - local_addr.sin_family = remote_addr.sin_family = AF_INET; | |
110 | - local_addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
111 | - remote_addr.sin_addr.s_addr = htonl(INADDR_ANY); | |
112 | - local_addr.sin_port = htons(localport); | |
113 | - remote_addr.sin_port = htons(remoteport); | |
114 | - if (bind(socket_fd, (struct sockaddr *) &local_addr, sizeof(local_addr)) == 0) { | |
115 | if (any_remote_host != 0) { /* not ANY => create a client */ | |
116 | - if (type == INET_TCP || type == INET_UDP) { | |
117 | - memcpy(&remote_addr.sin_addr, hp->h_addr, | |
118 | - sizeof(remote_addr.sin_addr)); | |
119 | - if (connect(socket_fd, | |
120 | - (struct sockaddr *) &remote_addr, | |
121 | - sizeof(remote_addr)) != 0) { | |
122 | - close(socket_fd); | |
123 | - if (localport == 0) | |
124 | - socket_fd = INVALID_HANDLE; | |
125 | - else | |
126 | - socket_fd = socketopen(type, localport, 0, "0"); | |
127 | - } | |
128 | + if (type != SOCK_RAW) { | |
129 | + if (connect(socket_fd, rres->ai_addr, | |
130 | + rres->ai_addrlen) == 0) | |
131 | + break; | |
132 | } else { | |
133 | /* /inet/raw client not ready yet */ | |
134 | fatal(_("/inet/raw client not ready yet, sorry")); | |
135 | if (geteuid() != 0) | |
136 | + /* FIXME: is this second fatal ever reached? */ | |
137 | fatal(_("only root may use `/inet/raw'.")); | |
138 | } | |
139 | } else { /* remote host is ANY => create a server */ | |
140 | - if (type == INET_TCP) { | |
141 | + if (type == SOCK_STREAM) { | |
142 | int clientsocket_fd = INVALID_HANDLE; | |
143 | - socklen_t namelen = sizeof(remote_addr); | |
144 | + | |
145 | + struct sockaddr_storage remote_addr; | |
146 | + socklen_t namelen = sizeof (remote_addr); | |
147 | ||
148 | if (listen(socket_fd, 1) >= 0 | |
149 | && (clientsocket_fd = accept(socket_fd, | |
150 | @@ -1218,25 +1223,22 @@ | |
151 | &namelen)) >= 0) { | |
152 | close(socket_fd); | |
153 | socket_fd = clientsocket_fd; | |
154 | - } else { | |
155 | - close(socket_fd); | |
156 | - socket_fd = INVALID_HANDLE; | |
157 | + break; | |
158 | } | |
159 | - } else if (type == INET_UDP) { | |
160 | + } else if (type == SOCK_DGRAM) { | |
161 | #ifdef MSG_PEEK | |
162 | char buf[10]; | |
163 | + struct sockaddr_storage remote_addr; | |
164 | socklen_t readle; | |
165 | ||
166 | if (recvfrom(socket_fd, buf, 1, MSG_PEEK, | |
167 | (struct sockaddr *) & remote_addr, | |
168 | - & readle) < 1 | |
169 | - || readle != sizeof(remote_addr) | |
170 | - || connect(socket_fd, | |
171 | + & readle) >= 0 | |
172 | + && readle | |
173 | + && connect(socket_fd, | |
174 | (struct sockaddr *)& remote_addr, | |
175 | - readle) != 0) { | |
176 | - close(socket_fd); | |
177 | - socket_fd = INVALID_HANDLE; | |
178 | - } | |
179 | + readle) == 0) | |
180 | + break; | |
181 | #endif | |
182 | } else { | |
183 | /* /inet/raw server not ready yet */ | |
184 | @@ -1245,10 +1247,20 @@ | |
185 | fatal(_("only root may use `/inet/raw'.")); | |
186 | } | |
187 | } | |
188 | - } else { | |
189 | + | |
190 | +nextrres: | |
191 | + if (socket_fd != INVALID_HANDLE) | |
192 | close(socket_fd); | |
193 | socket_fd = INVALID_HANDLE; | |
194 | + rres = rres->ai_next; | |
195 | + } | |
196 | + freeaddrinfo(rres0); | |
197 | + if (socket_fd != INVALID_HANDLE) | |
198 | + break; | |
199 | + lres = lres->ai_next; | |
200 | } | |
201 | + if (lres0) | |
202 | + freeaddrinfo(lres0); | |
203 | ||
204 | return socket_fd; | |
205 | } | |
206 | @@ -1313,30 +1325,24 @@ | |
207 | } else if (STREQN(name, "/inet/", 6)) { | |
208 | #ifdef HAVE_SOCKETS | |
209 | /* /inet/protocol/localport/hostname/remoteport */ | |
210 | - enum inet_prot protocol = INET_NONE; | |
211 | - int localport, remoteport; | |
212 | + int protocol; | |
213 | char *hostname; | |
214 | char *hostnameslastcharp; | |
215 | char *localpname; | |
216 | - char proto[4]; | |
217 | - struct servent *service; | |
218 | + char *localpnamelastcharp; | |
219 | ||
220 | cp = (char *) name + 6; | |
221 | /* which protocol? */ | |
222 | if (STREQN(cp, "tcp/", 4)) | |
223 | - protocol = INET_TCP; | |
224 | + protocol = SOCK_STREAM; | |
225 | else if (STREQN(cp, "udp/", 4)) | |
226 | - protocol = INET_UDP; | |
227 | + protocol = SOCK_DGRAM; | |
228 | else if (STREQN(cp, "raw/", 4)) | |
229 | - protocol = INET_RAW; | |
230 | + protocol = SOCK_RAW; | |
231 | else | |
232 | fatal(_("no (known) protocol supplied in special filename `%s'"), | |
233 | name); | |
234 | ||
235 | - proto[0] = cp[0]; | |
236 | - proto[1] = cp[1]; | |
237 | - proto[2] = cp[2]; | |
238 | - proto[3] = '\0'; | |
239 | cp += 4; | |
240 | ||
241 | /* which localport? */ | |
242 | @@ -1354,25 +1360,17 @@ | |
243 | * By using atoi() the use of decimal numbers is enforced. | |
244 | */ | |
245 | *cp = '\0'; | |
246 | - | |
247 | - localport = atoi(localpname); | |
248 | - if (strcmp(localpname, "0") != 0 | |
249 | - && (localport <= 0 || localport > 65535)) { | |
250 | - service = getservbyname(localpname, proto); | |
251 | - if (service == NULL) | |
252 | - fatal(_("local port invalid in `%s'"), name); | |
253 | - else | |
254 | - localport = ntohs(service->s_port); | |
255 | - } | |
256 | - *cp = '/'; | |
257 | + localpnamelastcharp = cp; | |
258 | ||
259 | /* which hostname? */ | |
260 | cp++; | |
261 | hostname = cp; | |
262 | while (*cp != '/' && *cp != '\0') | |
263 | cp++; | |
264 | - if (*cp != '/' || cp == hostname) | |
265 | + if (*cp != '/' || cp == hostname) { | |
266 | + *localpnamelastcharp = '/'; | |
267 | fatal(_("must supply a remote hostname to `/inet'")); | |
268 | + } | |
269 | *cp = '\0'; | |
270 | hostnameslastcharp = cp; | |
271 | ||
272 | @@ -1386,22 +1384,15 @@ | |
273 | * Here too, require a port, let them explicitly put 0 if | |
274 | * they don't care. | |
275 | */ | |
276 | - if (*cp == '\0') | |
277 | + if (*cp == '\0') { | |
278 | + *localpnamelastcharp = '/'; | |
279 | + *hostnameslastcharp = '/'; | |
280 | fatal(_("must supply a remote port to `/inet'")); | |
281 | - remoteport = atoi(cp); | |
282 | - if (strcmp(cp, "0") != 0 | |
283 | - && (remoteport <= 0 || remoteport > 65535)) { | |
284 | - service = getservbyname(cp, proto); | |
285 | - if (service == NULL) | |
286 | - fatal(_("remote port invalid in `%s'"), name); | |
287 | - else | |
288 | - remoteport = ntohs(service->s_port); | |
289 | } | |
290 | ||
291 | - /* Open Sesame! */ | |
292 | - openfd = socketopen(protocol, localport, remoteport, hostname); | |
293 | + openfd = socketopen(protocol, localpname, cp, hostname); | |
294 | + *localpnamelastcharp = '/'; | |
295 | *hostnameslastcharp = '/'; | |
296 | - | |
297 | #else /* ! HAVE_SOCKETS */ | |
298 | fatal(_("TCP/IP communications are not supported")); | |
299 | #endif /* HAVE_SOCKETS */ |