Watt-32 tcp/ip  2.2 dev-rel.10
bind.c
Go to the documentation of this file.
1 
5 /* BSD sockets functionality for Watt-32 TCP/IP
6  *
7  * Copyright (c) 1997-2002 Gisle Vanem <gvanem@yahoo.no>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  * must display the following acknowledgement:
19  * This product includes software developed by Gisle Vanem
20  * Bergen, Norway.
21  *
22  * THIS SOFTWARE IS PROVIDED BY ME (Gisle Vanem) AND CONTRIBUTORS ``AS IS''
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL I OR CONTRIBUTORS BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Version
34  *
35  * 0.5 : Dec 18, 1997 : G. Vanem - created
36  * 0.6 : Aug 06, 2002 : G. Vanem - added AF_INET6 support
37  */
38 
39 #include "socket.h"
40 
41 #if defined(USE_BSD_API)
42 
63 int W32_CALL bind (int s, const struct sockaddr *myaddr, int namelen)
64 {
66  struct sockaddr_in *addr = (struct sockaddr_in*) myaddr;
67  struct sockaddr_in6 *addr6 = (struct sockaddr_in6*) myaddr;
68  BOOL bind_any, is_bcast, is_mcast, our_addr;
69  WORD local_port;
70  BOOL is_ip6;
71  int sa_len;
72 
73  SOCK_PROLOGUE (socket, "\nbind:%d", s);
74 
75  is_ip6 = (socket->so_family == AF_INET6);
76  sa_len = is_ip6 ? sizeof(*addr6) : sizeof(*addr);
77 
78  if (_sock_chk_sockaddr(socket, myaddr, namelen) < 0)
79  return (-1);
80 
81  if (socket->so_type == SOCK_STREAM)
82  {
83  if (is_ip6)
84  is_mcast = IN6_IS_ADDR_MULTICAST (&addr6->sin6_addr);
85  else is_mcast = IN_MULTICAST (ntohl(addr->sin_addr.s_addr));
86  if (is_mcast)
87  {
88  SOCK_DEBUGF ((", EINVAL (mcast)"));
89  SOCK_ERRNO (EINVAL);
90  return (-1);
91  }
92  }
93 
94  /* binding to any address/port on local machine?
95  */
96 #if defined(USE_IPV6)
97  if (is_ip6)
98  {
99  our_addr = _ip6_is_local_addr (&addr6->sin6_addr);
100  bind_any = IN6_ARE_ADDR_EQUAL (&addr6->sin6_addr, &in6addr_any);
101  is_bcast = IN6_IS_ADDR_MC_GLOBAL (&addr6->sin6_addr); /* ?? */
102  }
103  else
104 #endif
105  {
106  our_addr = _ip4_is_local_addr (ntohl(addr->sin_addr.s_addr));
107  bind_any = (addr->sin_addr.s_addr == INADDR_ANY);
108  is_bcast = ((~addr->sin_addr.s_addr & ~sin_mask) == 0);
109  }
110 
111  if (socket->so_type == SOCK_STREAM &&
112  !bind_any && !our_addr && !is_bcast)
113  {
114  SOCK_DEBUGF ((", EADDRNOTAVAIL"));
115  SOCK_ERRNO (EADDRNOTAVAIL);
116  return (-1);
117  }
118 
119  if (socket->local_addr)
120  {
121  struct in6_addr *ip6 = &((struct sockaddr_in6*) socket->local_addr)->sin6_addr;
122  u_short port = socket->local_addr->sin_port;
123  u_long ip4 = socket->local_addr->sin_addr.s_addr;
124  BOOL equal = (!is_ip6 && ip4 == addr->sin_addr.s_addr) ||
125  (is_ip6 && IN6_ARE_ADDR_EQUAL(ip6,&addr6->sin6_addr));
126 
127  if ((addr->sin_port != IPPORT_ANY && addr->sin_port == port) ||
128  (!bind_any && equal))
129  {
130  SOCK_DEBUGF ((", EADDRINUSE, local port %d, bind_any %d",
131  ntohs(port), bind_any));
132  SOCK_ERRNO (EADDRINUSE);
133  return (-1);
134  }
135 
139  }
140  else
141  {
142  socket->local_addr = (struct sockaddr_in*) SOCK_CALLOC (sa_len);
143  if (!socket->local_addr)
144  {
145  SOCK_DEBUGF ((", ENOMEM"));
146  SOCK_ERRNO (ENOMEM);
147  return (-1);
148  }
149  }
150 
151 #if defined(USE_IPV6)
152  if (is_ip6 && addr6->sin6_port == IPPORT_ANY)
153  {
154  local_port = find_free_port (0, TRUE);
155  addr6->sin6_port = htons (local_port);
156  }
157  else
158 #endif
159  if (!is_ip6 && addr->sin_port == IPPORT_ANY)
160  {
161  local_port = find_free_port (0, TRUE);
162  addr->sin_port = htons (local_port);
163  }
164  else /* check if requested port is vacant */
165  {
166  local_port = ntohs (addr->sin_port);
167  if (grab_localport(local_port) < 0)
168  {
169  SOCK_DEBUGF ((", EADDRNOTAVAIL, local port %d", local_port));
170  SOCK_ERRNO (EADDRNOTAVAIL);
171  return (-1);
172  }
173  }
174 
175 #if defined(USE_IPV6)
176  if (is_ip6)
177  {
178  struct sockaddr_in6 *la = (struct sockaddr_in6*)socket->local_addr;
179 
180  la->sin6_family = AF_INET6;
181  la->sin6_port = addr6->sin6_port;
182  memcpy (&la->sin6_addr, &addr6->sin6_addr, sizeof(la->sin6_addr));
183 
184  SOCK_DEBUGF ((", %s, (%d)",
185  bind_any ? "INADDR_ANY" : _inet6_ntoa(&addr6->sin6_addr),
186  ntohs(addr->sin_port)));
187  }
188  else
189 #endif
190  {
191  socket->local_addr->sin_port = addr->sin_port;
192  socket->local_addr->sin_addr = addr->sin_addr;
193  socket->local_addr->sin_family = AF_INET;
194 
195  SOCK_DEBUGF ((", %s, (%d)",
196  bind_any ? "INADDR_ANY" : inet_ntoa(addr->sin_addr),
197  ntohs(addr->sin_port)));
198  }
199 
200  /* Since SOCK_DGRAM sockets are connectionless, the application need
201  * not use connect() or accept(). Hence we need to use _UDP_listen().
202  */
203  if (socket->so_type == SOCK_DGRAM)
204  {
205  if (bind_any)
206  socket->so_state |= SS_PRIV; /* privileged for broadcast reception */
207 
208 #if defined(USE_IPV6)
209  if (is_ip6)
210  {
211  if (_UDP6_listen (socket, &addr6->sin6_addr, addr6->sin6_port) < 0)
212  return (-1);
213  }
214  else
215 #endif
216  if (_UDP_listen (socket, addr->sin_addr, addr->sin_port) < 0)
217  return (-1);
218  }
219  return (0);
220 }
221 
222 
223 /*
224  * A small test djgpp program
225  */
226 #if defined(TEST_PROG)
227 
228 #define MY_PORT_ID 6060
229 #undef close
230 
231 #if !defined(__CYGWIN__)
232 #include <conio.h>
233 #endif
234 
235 #ifndef STDIN_FILENO
236 #define STDIN_FILENO 0
237 #endif
238 
239 #include "pcdbug.h"
240 
241 int main (int argc, char **argv)
242 {
243  struct sockaddr_in addr;
244  int sock, quit;
245 
246  dbug_init();
247 
248  sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
249  if (sock < 0)
250  {
251  perror ("socket");
252  return (-1);
253  }
254 
255  memset (&addr, 0, sizeof(addr));
256  addr.sin_family = AF_INET;
257 
258  if (argc >= 2 && !strcmp(argv[1],"-frag")) /* test Tx of large datagrams */
259  {
260  #define CHUNK_SIZE 500
261  char data [3*CHUNK_SIZE];
262  int i;
263 
264  for (i = 0; i < sizeof(data); i++)
265  data[i] = i;
266 
267  addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
268  addr.sin_port = IPPORT_ANY;
269 
270  if (sendto (sock, &data, sizeof(data), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0)
271  perror ("sendto");
272 
273  close (sock);
274  return (-1);
275  }
276 
277  /* INADDR_ANY will take all the address of the system
278  */
279  addr.sin_addr.s_addr = htonl (INADDR_ANY);
280  addr.sin_port = htons (MY_PORT_ID);
281 
282  if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)
283  {
284  perror ("bind");
285  close (sock);
286  return (-1);
287  }
288 
289 #if 0
290  if (listen (sock, 5) < 0)
291  {
292  perror ("listen");
293  close (sock);
294  return (-1);
295  }
296 #endif
297 
298  quit = 0;
299 
300  while (!quit)
301  {
302  struct timeval tv;
303  struct sockaddr from;
304  fd_set fd_read, fd_write, fd_exc;
305  int num, from_len = sizeof(from);
306 
307  FD_ZERO (&fd_read);
308  FD_ZERO (&fd_write);
309  FD_ZERO (&fd_exc);
310  FD_SET (STDIN_FILENO, &fd_read);
311  FD_SET (sock, &fd_read);
312  FD_SET (sock, &fd_write);
313  FD_SET (sock, &fd_exc);
314  tv.tv_usec = 0;
315  tv.tv_sec = 1;
316 
317  num = select (sock+1, &fd_read, &fd_write, &fd_exc, &tv);
318 
319  if (FD_ISSET(sock, &fd_read)) fputc ('r', stderr);
320  if (FD_ISSET(sock, &fd_write)) fputc ('w', stderr);
321  if (FD_ISSET(sock, &fd_exc)) fputc ('x', stderr);
322 
323  if (FD_ISSET(STDIN_FILENO, &fd_read))
324  {
325  int ch = getch();
326  quit = (ch == 27);
327  fputc (ch, stderr);
328  }
329 
330  if (FD_ISSET(sock, &fd_read) &&
331  accept (sock, &from, &from_len) < 0)
332  {
333  perror ("accept");
334  break;
335  }
336  if (num < 0)
337  {
338  perror ("select");
339  break;
340  }
341  fputc ('.', stderr);
342  usleep (300000); /* 300ms */
343  }
344 
345  close (sock);
346  return (0);
347 }
348 #endif /* TEST_PROG */
349 
350 #endif /* USE_BSD_API */
351 
Definition: wtypes.h:197
int _sock_chk_sockaddr(Socket *socket, const struct sockaddr *sa, int len)
Check `sockaddr*' passed to bind/connect.
Definition: socket.c:839
Definition: socket.h:137
Definition: if.h:84
Socket * _socklist_find(int s)
Returns a pointer to the Socket structure associated with socket 's'.
Definition: socket.c:1534
DWORD sin_mask
our net-mask, 255.255.255.0
Definition: pctcp.c:71
Definition: in.h:153
Definition: wtime.h:38
int W32_CALL socket(int family, int type, int protocol)
socket().
Definition: socket.c:1794
int _UDP6_listen(Socket *socket, const void *host, WORD port)
Definition: socket.c:2222
int W32_CALL bind(int s, const struct sockaddr *myaddr, int namelen)
bind() - bind name to socket.
Definition: bind.c:63
int W32_CALL accept(int s, struct sockaddr *addr, int *addrlen)
Definition: accept.c:59
const char * _inet6_ntoa(const void *ip)
Convert an IPv6-address 'ip' into a string.
Definition: netaddr.c:401
int main(int argc, char **argv)
Definition: echo.c:223