The Pedigree Project  0.1
net-syscalls.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS // don't need them here
21 
22 #include "modules/system/vfs/File.h"
23 #include "modules/system/vfs/VFS.h"
24 #include "pedigree/kernel/process/Process.h"
25 #include "pedigree/kernel/process/Scheduler.h"
26 #include "pedigree/kernel/processor/Processor.h"
27 #include "pedigree/kernel/processor/types.h"
28 #include "pedigree/kernel/syscallError.h"
29 #include "pedigree/kernel/utilities/Tree.h"
30 
34 
35 #include "pedigree/kernel/Subsystem.h"
36 #include "modules/subsys/posix/FileDescriptor.h"
37 #include "modules/subsys/posix/PosixSubsystem.h"
38 #include "modules/subsys/posix/UnixFilesystem.h"
39 
40 #include "file-syscalls.h"
41 #include "net-syscalls.h"
42 
43 #include <fcntl.h>
44 
45 #ifndef UTILITY_LINUX
46 #include <netdb.h>
47 #include <netinet/tcp.h>
48 #include <sys/socket.h>
49 #endif
50 
51 #include <netinet/in.h>
52 #include <sys/un.h>
53 
54 // Set to 1 to also log the contents of send() and recv() buffers ala strace
55 #define LOG_SEND_RECV_BUFFERS 0
56 
58  LwipSocketSyscalls::m_SyscallObjects;
59 
60 extern UnixFilesystem *g_pUnixFilesystem;
61 
63 // operate if the socket does not yet have valid members (i.e. before a bind).
64 static bool isSaneSocket(FileDescriptor *f, bool is_create = false)
65 {
66  if (!f)
67  {
68  N_NOTICE(" -> isSaneSocket: descriptor is null");
69  SYSCALL_ERROR(BadFileDescriptor);
70  return false;
71  }
72 
73  if (is_create)
74  {
75  return true;
76  }
77 
78  if (!f->networkImpl)
79  {
80  N_NOTICE(" -> isSaneSocket: no network implementation found");
81  SYSCALL_ERROR(BadFileDescriptor);
82  return false;
83  }
84 
85  return true;
86 }
87 
88 static err_t sockaddrToIpaddr(
89  const struct sockaddr *saddr, uint16_t &port, ip_addr_t *result,
90  bool isbind = true)
91 {
92  ByteSet(result, 0, sizeof(*result));
93 
94  if (saddr->sa_family == AF_INET)
95  {
96  const struct sockaddr_in *sin =
97  reinterpret_cast<const struct sockaddr_in *>(saddr);
98  result->u_addr.ip4.addr = sin->sin_addr.s_addr;
99  result->type = IPADDR_TYPE_V4;
100 
101  if (!isbind)
102  {
103  // do some extra sanity checks for client connections
104  if (!sin->sin_addr.s_addr)
105  {
106  // rebind to 127.0.0.1 (localhost)
107  result->u_addr.ip4.addr = HOST_TO_BIG32(INADDR_LOOPBACK);
108  }
109  }
110 
111  port = BIG_TO_HOST16(sin->sin_port);
112 
113  return ERR_OK;
114  }
115  else
116  {
117  ERROR("sockaddrToIpaddr: only AF_INET is supported at the moment.");
118  }
119 
120  return ERR_VAL;
121 }
122 
123 int posix_socket(int domain, int type, int protocol)
124 {
125  N_NOTICE("socket(" << domain << ", " << type << ", " << protocol << ")");
126 
127  size_t fd = getAvailableDescriptor();
128 
129  netconn_type connType = NETCONN_INVALID;
130 
131  File *file = nullptr;
132  struct netconn *conn = nullptr;
133  bool valid = true;
134 
135  NetworkSyscalls *syscalls;
136 
137  if (domain == AF_UNIX)
138  {
139  syscalls = new UnixSocketSyscalls(domain, type, protocol);
140  }
141  else
142  {
144  syscalls = new LwipSocketSyscalls(domain, type, protocol);
145  }
146 
147  if (!syscalls->create())
148  {
149  return -1;
150  }
151 
153  f->networkImpl = syscalls;
154  f->fd = fd;
155  addDescriptor(fd, f);
156  syscalls->associate(f);
157 
158  N_NOTICE(" -> " << Dec << fd << Hex);
159  return static_cast<int>(fd);
160 }
161 
162 int posix_socketpair(int domain, int type, int protocol, int sv[2])
163 {
164  N_NOTICE("socketpair");
165 
167  reinterpret_cast<uintptr_t>(sv), sizeof(int) * 2,
168  PosixSubsystem::SafeWrite))
169  {
170  N_NOTICE("socketpair -> invalid address");
171  SYSCALL_ERROR(BadAddress);
172  return -1;
173  }
174 
175  if (domain != AF_UNIX)
176  {
178  N_NOTICE(" -> bad domain");
179  return -1;
180  }
181 
182  UnixSocketSyscalls *syscallsA =
183  new UnixSocketSyscalls(domain, type, protocol);
184  if (!syscallsA->create())
185  {
186  delete syscallsA;
187  N_NOTICE(" -> failed to create first socket");
188  return -1;
189  }
190 
191  UnixSocketSyscalls *syscallsB =
192  new UnixSocketSyscalls(domain, type, protocol);
193  if (!syscallsB->create())
194  {
195  delete syscallsA;
196  delete syscallsB;
197  N_NOTICE(" -> failed to create second socket");
198  return -1;
199  }
200 
201  if (!syscallsA->pairWith(syscallsB))
202  {
203  delete syscallsA;
204  delete syscallsB;
205  N_NOTICE(" -> failed to pair");
206  return -1;
207  }
208 
209  FileDescriptor *fA = new FileDescriptor;
210  FileDescriptor *fB = new FileDescriptor;
211 
212  size_t fdA = getAvailableDescriptor();
213  size_t fdB = getAvailableDescriptor();
214 
215  fA->networkImpl = syscallsA;
216  fA->fd = fdA;
217  fB->networkImpl = syscallsB;
218  fB->fd = fdB;
219 
220  addDescriptor(fdA, fA);
221  addDescriptor(fdB, fB);
222 
223  syscallsA->associate(fA);
224  syscallsB->associate(fB);
225 
226  sv[0] = static_cast<int>(fdA);
227  sv[1] = static_cast<int>(fdB);
228 
229  N_NOTICE(" -> " << sv[0] << ", " << sv[1]);
230  return 0;
231 }
232 
233 int posix_connect(int sock, const struct sockaddr *address, socklen_t addrlen)
234 {
235  N_NOTICE("connect");
236 
238  reinterpret_cast<uintptr_t>(address), addrlen,
239  PosixSubsystem::SafeRead))
240  {
241  N_NOTICE("connect -> invalid address");
242  SYSCALL_ERROR(InvalidArgument);
243  return -1;
244  }
245 
246  N_NOTICE(
247  "connect(" << sock << ", " << reinterpret_cast<uintptr_t>(address)
248  << ", " << addrlen << ")");
249 
250  FileDescriptor *f = getDescriptor(sock);
251  if (!isSaneSocket(f, true))
252  {
253  return -1;
254  }
255 
256  if (address->sa_family != f->networkImpl->getDomain())
257  {
258  // EAFNOSUPPORT
259  N_NOTICE(" -> incorrect address family passed to connect()");
260  return -1;
261  }
262 
263  return f->networkImpl->connect(address, addrlen);
264 }
265 
266 ssize_t posix_send(int sock, const void *buff, size_t bufflen, int flags)
267 {
268  N_NOTICE("send");
269 
271  reinterpret_cast<uintptr_t>(buff), bufflen,
272  PosixSubsystem::SafeRead))
273  {
274  N_NOTICE("send -> invalid address");
275  SYSCALL_ERROR(InvalidArgument);
276  return -1;
277  }
278 
279  N_NOTICE(
280  "send(" << sock << ", " << buff << ", " << bufflen << ", " << flags
281  << ")");
282 
283 #if LOG_SEND_RECV_BUFFERS
284  if (buff && bufflen)
285  {
286  String debug;
287  debug.assign(reinterpret_cast<const char *>(buff), bufflen, true);
288  N_NOTICE(" -> sending: '" << debug << "'");
289  }
290 #endif
291 
292  FileDescriptor *f = getDescriptor(sock);
293  if (!isSaneSocket(f))
294  {
295  return -1;
296  }
297 
298  return f->networkImpl->sendto(buff, bufflen, flags, nullptr, 0);
299 }
300 
301 ssize_t posix_sendto(
302  int sock, const void *buff, size_t bufflen, int flags,
303  struct sockaddr *address, socklen_t addrlen)
304 {
305  N_NOTICE("sendto");
306 
308  reinterpret_cast<uintptr_t>(buff), bufflen,
309  PosixSubsystem::SafeRead))
310  {
311  N_NOTICE("sendto -> invalid address for transmission buffer");
312  SYSCALL_ERROR(InvalidArgument);
313  return -1;
314  }
315 
316  N_NOTICE(
317  "sendto(" << sock << ", " << buff << ", " << bufflen << ", " << flags
318  << ", " << address << ", " << addrlen << ")");
319 
320 #if LOG_SEND_RECV_BUFFERS
321  if (buff && bufflen)
322  {
323  String debug;
324  debug.assign(reinterpret_cast<const char *>(buff), bufflen, true);
325  N_NOTICE(" -> sending: '" << debug << "'");
326  }
327 #endif
328 
329  FileDescriptor *f = getDescriptor(sock);
330  if (!isSaneSocket(f))
331  {
332  return -1;
333  }
334 
335  return f->networkImpl->sendto(buff, bufflen, flags, address, addrlen);
336 }
337 
338 ssize_t posix_recv(int sock, void *buff, size_t bufflen, int flags)
339 {
340  N_NOTICE("recv");
341 
343  reinterpret_cast<uintptr_t>(buff), bufflen,
344  PosixSubsystem::SafeWrite))
345  {
346  N_NOTICE("recv -> invalid address");
347  SYSCALL_ERROR(InvalidArgument);
348  return -1;
349  }
350 
351  N_NOTICE(
352  "recv(" << sock << ", " << buff << ", " << bufflen << ", " << flags
353  << ")");
354 
355  FileDescriptor *f = getDescriptor(sock);
356  if (!isSaneSocket(f))
357  {
358  return -1;
359  }
360 
361  ssize_t n =
362  f->networkImpl->recvfrom(buff, bufflen, flags, nullptr, nullptr);
363 
364 #if LOG_SEND_RECV_BUFFERS
365  if (buff && n > 0)
366  {
367  String debug;
368  debug.assign(reinterpret_cast<const char *>(buff), n, true);
369  N_NOTICE(" -> received: '" << debug << "'");
370  }
371 #endif
372 
373  N_NOTICE(" -> " << n);
374  return n;
375 }
376 
377 ssize_t posix_recvfrom(
378  int sock, void *buff, size_t bufflen, int flags, struct sockaddr *address,
379  socklen_t *addrlen)
380 {
381  N_NOTICE("recvfrom");
382 
384  reinterpret_cast<uintptr_t>(buff), bufflen,
385  PosixSubsystem::SafeWrite) &&
386  ((!address) || PosixSubsystem::checkAddress(
387  reinterpret_cast<uintptr_t>(addrlen),
388  sizeof(socklen_t), PosixSubsystem::SafeWrite))))
389  {
390  N_NOTICE("recvfrom -> invalid address for receive buffer or addrlen "
391  "parameter");
392  SYSCALL_ERROR(InvalidArgument);
393  return -1;
394  }
395 
396  N_NOTICE(
397  "recvfrom(" << sock << ", " << buff << ", " << bufflen << ", " << flags
398  << ", " << address << ", " << addrlen);
399 
400  FileDescriptor *f = getDescriptor(sock);
401  if (!isSaneSocket(f))
402  {
403  return -1;
404  }
405 
406  ssize_t n =
407  f->networkImpl->recvfrom(buff, bufflen, flags, address, addrlen);
408 
409 #if LOG_SEND_RECV_BUFFERS
410  if (buff && n > 0)
411  {
412  String debug;
413  debug.assign(reinterpret_cast<const char *>(buff), n, true);
414  N_NOTICE(" -> received: '" << debug << "'");
415  }
416 #endif
417 
418  N_NOTICE(" -> " << n);
419  return n;
420 }
421 
422 int posix_bind(int sock, const struct sockaddr *address, socklen_t addrlen)
423 {
424  N_NOTICE("bind");
425 
427  reinterpret_cast<uintptr_t>(address), addrlen,
428  PosixSubsystem::SafeRead))
429  {
430  N_NOTICE("bind -> invalid address");
431  SYSCALL_ERROR(InvalidArgument);
432  return -1;
433  }
434 
435  N_NOTICE("bind(" << sock << ", " << address << ", " << addrlen << ")");
436 
437  FileDescriptor *f = getDescriptor(sock);
438  if (!isSaneSocket(f, true))
439  {
440  return -1;
441  }
442 
443  if (f->networkImpl->getDomain() != address->sa_family)
444  {
445  // EAFNOSUPPORT
446  return -1;
447  }
448 
449  return f->networkImpl->bind(address, addrlen);
450 }
451 
452 int posix_listen(int sock, int backlog)
453 {
454  N_NOTICE("listen(" << sock << ", " << backlog << ")");
455 
456  FileDescriptor *f = getDescriptor(sock);
457  if (!isSaneSocket(f))
458  {
459  return -1;
460  }
461 
462  if (f->networkImpl->getType() != SOCK_STREAM)
463  {
464  SYSCALL_ERROR(InvalidArgument);
465  return -1;
466  }
467 
468  return f->networkImpl->listen(backlog);
469 }
470 
471 int posix_accept(int sock, struct sockaddr *address, socklen_t *addrlen)
472 {
473  N_NOTICE("accept");
474 
476  reinterpret_cast<uintptr_t>(address),
477  sizeof(struct sockaddr_storage), PosixSubsystem::SafeWrite) &&
479  reinterpret_cast<uintptr_t>(addrlen), sizeof(socklen_t),
480  PosixSubsystem::SafeWrite)))
481  {
482  N_NOTICE("accept -> invalid address");
483  SYSCALL_ERROR(InvalidArgument);
484  return -1;
485  }
486 
487  N_NOTICE("accept(" << sock << ", " << address << ", " << addrlen << ")");
488 
489  FileDescriptor *f = getDescriptor(sock);
490  if (!isSaneSocket(f))
491  {
492  return -1;
493  }
494 
495  if (f->networkImpl->getType() != SOCK_STREAM)
496  {
497  SYSCALL_ERROR(OperationNotSupported);
498  return -1;
499  }
500 
501  int r = f->networkImpl->accept(address, addrlen);
502  N_NOTICE(" -> " << Dec << r);
503  return r;
504 }
505 
506 int posix_shutdown(int socket, int how)
507 {
508  N_NOTICE("shutdown(" << socket << ", " << how << ")");
509 
510  FileDescriptor *f = getDescriptor(socket);
511  if (!isSaneSocket(f))
512  {
513  return -1;
514  }
515 
516  return f->networkImpl->shutdown(how);
517 }
518 
519 int posix_getpeername(
520  int socket, struct sockaddr *address, socklen_t *address_len)
521 {
522  N_NOTICE("getpeername");
523 
525  reinterpret_cast<uintptr_t>(address),
526  sizeof(struct sockaddr_storage), PosixSubsystem::SafeWrite) &&
528  reinterpret_cast<uintptr_t>(address_len), sizeof(socklen_t),
529  PosixSubsystem::SafeWrite)))
530  {
531  N_NOTICE("getpeername -> invalid address");
532  SYSCALL_ERROR(InvalidArgument);
533  return -1;
534  }
535 
536  N_NOTICE(
537  "getpeername(" << socket << ", " << address << ", " << address_len
538  << ")");
539 
540  FileDescriptor *f = getDescriptor(socket);
541  if (!isSaneSocket(f))
542  {
543  return -1;
544  }
545 
546  return f->networkImpl->getpeername(address, address_len);
547 }
548 
549 int posix_getsockname(
550  int socket, struct sockaddr *address, socklen_t *address_len)
551 {
552  N_NOTICE("getsockname");
553 
555  reinterpret_cast<uintptr_t>(address),
556  sizeof(struct sockaddr_storage), PosixSubsystem::SafeWrite) &&
558  reinterpret_cast<uintptr_t>(address_len), sizeof(socklen_t),
559  PosixSubsystem::SafeWrite)))
560  {
561  N_NOTICE("getsockname -> invalid address");
562  SYSCALL_ERROR(InvalidArgument);
563  return -1;
564  }
565 
566  N_NOTICE(
567  "getsockname(" << socket << ", " << address << ", " << address_len
568  << ")");
569 
570  FileDescriptor *f = getDescriptor(socket);
571  if (!isSaneSocket(f))
572  {
573  return -1;
574  }
575 
576  return f->networkImpl->getsockname(address, address_len);
577 }
578 
579 int posix_setsockopt(
580  int sock, int level, int optname, const void *optvalue, socklen_t optlen)
581 {
582  N_NOTICE(
583  "setsockopt(" << sock << ", " << level << ", " << optname << ", "
584  << optvalue << ", " << optlen << ")");
585 
587  reinterpret_cast<uintptr_t>(optvalue), optlen,
588  PosixSubsystem::SafeWrite)))
589  {
590  N_NOTICE("setsockopt -> invalid address");
591  SYSCALL_ERROR(InvalidArgument);
592  return -1;
593  }
594 
595  FileDescriptor *f = getDescriptor(sock);
596  if (!isSaneSocket(f))
597  {
598  return -1;
599  }
600 
601  return f->networkImpl->setsockopt(level, optname, optvalue, optlen);
602 }
603 
604 int posix_getsockopt(
605  int sock, int level, int optname, void *optvalue, socklen_t *optlen)
606 {
607  N_NOTICE("getsockopt(" << sock << ", " << level << ", " << optname << ")");
608 
609  // Check optlen first, then use it to check optvalue.
611  reinterpret_cast<uintptr_t>(optlen), sizeof(socklen_t),
612  PosixSubsystem::SafeRead) &&
614  reinterpret_cast<uintptr_t>(optlen), sizeof(socklen_t),
615  PosixSubsystem::SafeWrite)))
616  {
617  N_NOTICE("getsockopt -> invalid address");
618  SYSCALL_ERROR(InvalidArgument);
619  return -1;
620  }
622  reinterpret_cast<uintptr_t>(optvalue), *optlen,
623  PosixSubsystem::SafeWrite)))
624  {
625  N_NOTICE("getsockopt -> invalid address");
626  SYSCALL_ERROR(InvalidArgument);
627  return -1;
628  }
629 
630  FileDescriptor *f = getDescriptor(sock);
631  if (!isSaneSocket(f))
632  {
633  return -1;
634  }
635 
636  return f->networkImpl->getsockopt(level, optname, optvalue, optlen);
637 }
638 
639 int posix_sethostname(const char *name, size_t len)
640 {
641  N_NOTICE("sethostname");
642 
644  reinterpret_cast<uintptr_t>(name), len, PosixSubsystem::SafeRead)))
645  {
646  N_NOTICE(" -> invalid address");
647  SYSCALL_ERROR(InvalidArgument);
648  return -1;
649  }
650 
651  N_NOTICE("sethostname(" << String(name, len) << ")");
652 
654 
655  return 0;
656 }
657 
658 ssize_t posix_sendmsg(int sockfd, const struct msghdr *msg, int flags)
659 {
660  N_NOTICE("sendmsg(" << sockfd << ", " << msg << ", " << flags << ")");
661 
663 
664  FileDescriptor *f = getDescriptor(sockfd);
665  if (!isSaneSocket(f))
666  {
667  return -1;
668  }
669 
670  ssize_t n = f->networkImpl->sendto_msg(msg);
671  N_NOTICE(" -> " << n);
672  return n;
673 }
674 
675 ssize_t posix_recvmsg(int sockfd, struct msghdr *msg, int flags)
676 {
677  N_NOTICE("recvmsg(" << sockfd << ", " << msg << ", " << flags << ")");
678 
680 
681  FileDescriptor *f = getDescriptor(sockfd);
682  if (!isSaneSocket(f))
683  {
684  return -1;
685  }
686 
687  ssize_t n = f->networkImpl->recvfrom_msg(msg);
688  N_NOTICE(" -> " << n);
689  return n;
690 }
691 
692 NetworkSyscalls::NetworkSyscalls(int domain, int type, int protocol)
693  : m_Domain(domain), m_Type(type), m_Protocol(protocol), m_Blocking(true),
694  m_Fd(nullptr)
695 {
696 }
697 
698 NetworkSyscalls::~NetworkSyscalls()
699 {
700 }
701 
703 {
704  return true;
705 }
706 
707 ssize_t NetworkSyscalls::sendto(
708  const void *buffer, size_t bufferlen, int flags,
709  const struct sockaddr *address, socklen_t addrlen)
710 {
711  struct iovec iov;
712  iov.iov_base = const_cast<void *>(buffer);
713  iov.iov_len = bufferlen;
714 
715  struct msghdr msg;
716  msg.msg_name = const_cast<struct sockaddr *>(address);
717  msg.msg_namelen = addrlen;
718  msg.msg_iov = &iov;
719  msg.msg_iovlen = 1;
720  msg.msg_control = nullptr;
721  msg.msg_controllen = 0;
722  msg.msg_flags = flags;
723 
724  return sendto_msg(&msg);
725 }
726 
727 ssize_t NetworkSyscalls::recvfrom(
728  void *buffer, size_t bufferlen, int flags, struct sockaddr *address,
729  socklen_t *addrlen)
730 {
731  struct iovec iov;
732  iov.iov_base = buffer;
733  iov.iov_len = bufferlen;
734 
735  struct msghdr msg;
736  msg.msg_name = address;
737  msg.msg_namelen = addrlen ? *addrlen : 0;
738  msg.msg_iov = &iov;
739  msg.msg_iovlen = 1;
740  msg.msg_control = nullptr;
741  msg.msg_controllen = 0;
742  msg.msg_flags = flags;
743 
744  ssize_t result = recvfrom_msg(&msg);
745  if (result >= 0)
746  {
747  // Copy result address length if needed.
748  if (addrlen)
749  {
750  *addrlen = msg.msg_namelen;
751  }
752  }
753 
754  return result;
755 }
756 
757 int NetworkSyscalls::shutdown(int how)
758 {
759  return 0;
760 }
761 
762 bool NetworkSyscalls::canPoll() const
763 {
764  return false;
765 }
766 
767 bool NetworkSyscalls::poll(
768  bool &read, bool &write, bool &error, Semaphore *waiter)
769 {
770  read = false;
771  write = false;
772  error = false;
773  return false;
774 }
775 
776 void NetworkSyscalls::unPoll(Semaphore *waiter)
777 {
778 }
779 
780 bool NetworkSyscalls::monitor(Thread *pThread, Event *pEvent)
781 {
782  return false;
783 }
784 
785 bool NetworkSyscalls::unmonitor(Event *pEvent)
786 {
787  return false;
788 }
789 
790 void NetworkSyscalls::associate(FileDescriptor *fd)
791 {
792  m_Fd = fd;
793 }
794 
795 bool NetworkSyscalls::isBlocking() const
796 {
797  return m_Blocking;
798 }
799 
800 void NetworkSyscalls::setBlocking(bool blocking)
801 {
802  m_Blocking = blocking;
803 }
804 
805 LwipSocketSyscalls::LwipSocketSyscalls(int domain, int type, int protocol)
806  : NetworkSyscalls(domain, type, protocol), m_Socket(nullptr), m_Metadata()
807 {
808 }
809 
810 LwipSocketSyscalls::~LwipSocketSyscalls()
811 {
812  if (m_Socket)
813  {
814  m_SyscallObjects.remove(m_Socket);
815 
816  netconn_delete(m_Socket);
817  m_Socket = nullptr;
818  }
819 }
820 
822 {
823  netconn_type connType = NETCONN_INVALID;
824 
825  // fix up some defaults that make sense for inet[6] sockets
826  if (!m_Protocol)
827  {
828  N_NOTICE("LwipSocketSyscalls: using default protocol for socket type");
829  if (m_Type == SOCK_DGRAM)
830  {
831  m_Protocol = IPPROTO_UDP;
832  }
833  else if (m_Type == SOCK_STREAM)
834  {
835  m_Protocol = IPPROTO_TCP;
836  }
837  }
838 
839  if (m_Domain == AF_INET)
840  {
841  switch (m_Protocol)
842  {
843  case IPPROTO_TCP:
844  connType = NETCONN_TCP;
845  break;
846  case IPPROTO_UDP:
847  connType = NETCONN_UDP;
848  break;
849  }
850  }
851  else if (m_Domain == AF_INET6)
852  {
853  switch (m_Protocol)
854  {
855  case IPPROTO_TCP:
856  connType = NETCONN_TCP_IPV6;
857  break;
858  case IPPROTO_UDP:
859  connType = NETCONN_UDP_IPV6;
860  break;
861  }
862  }
863  else if (m_Domain == AF_PACKET)
864  {
865  connType = NETCONN_RAW;
866  }
867  else
868  {
869  WARNING("LwipSocketSyscalls: domain " << m_Domain << " is not known!");
870  SYSCALL_ERROR(InvalidArgument);
871  return false;
872  }
873 
874  if (connType == NETCONN_INVALID)
875  {
876  N_NOTICE("LwipSocketSyscalls: invalid socket creation parameters");
877  SYSCALL_ERROR(InvalidArgument);
878  return false;
879  }
880 
881  // Socket already exists? No need to do the rest.
882  if (m_Socket)
883  {
884  return true;
885  }
886 
887  m_Socket = netconn_new_with_callback(connType, netconnCallback);
888  if (!m_Socket)
889  {
891  return false;
892  }
893 
894  m_SyscallObjects.insert(m_Socket, this);
895 
896  return true;
897 }
898 
900  const struct sockaddr *address, socklen_t addrlen)
901 {
903  ip_addr_t ipaddr;
904  ByteSet(&ipaddr, 0, sizeof(ipaddr));
905  err_t err = netconn_bind(m_Socket, &ipaddr, 0); // bind to any address
906  if (err != ERR_OK)
907  {
908  N_NOTICE(" -> lwip error when binding before connect");
909  lwipToSyscallError(err);
910  return -1;
911  }
912 
913  uint16_t port = 0;
914  if ((err = sockaddrToIpaddr(address, port, &ipaddr, false)) != ERR_OK)
915  {
916  N_NOTICE("failed to convert sockaddr");
917  lwipToSyscallError(err);
918  return -1;
919  }
920 
921  // set blocking status if needed
922  bool blocking =
923  !((getFileDescriptor()->flflags & O_NONBLOCK) == O_NONBLOCK);
924  netconn_set_nonblocking(m_Socket, blocking ? 0 : 1);
925 
926  N_NOTICE("using socket " << m_Socket << "!");
927  N_NOTICE(
928  " -> connecting to remote " << ipaddr_ntoa(&ipaddr) << " on port "
929  << Dec << port);
930 
931  err = netconn_connect(m_Socket, &ipaddr, port);
932  if (err != ERR_OK)
933  {
934  N_NOTICE(" -> lwip error");
935  lwipToSyscallError(err);
936  return -1;
937  }
938 
939  // need to allow writing immediately for non-tcp sockets
941  if (NETCONNTYPE_GROUP(m_Socket->type) != NETCONN_TCP)
942  {
943  m_Metadata.send = 1;
944  }
945 
946  N_NOTICE(" -> ok!");
947  return 0;
948 }
949 
950 ssize_t LwipSocketSyscalls::sendto_msg(const struct msghdr *msghdr)
951 {
952  err_t err;
953 
954  if (msghdr->msg_name)
955  {
957  SYSCALL_ERROR(Unimplemented);
958  return -1;
959  }
960 
961  // Can we send without blocking?
962  if (!isBlocking() && !m_Metadata.send)
963  {
964  N_NOTICE(" -> send queue full, would block");
965  SYSCALL_ERROR(NoMoreProcesses);
966  return -1;
967  }
968 
969  size_t bytesWritten = 0;
970  bool ok = true;
971 
972  if (NETCONNTYPE_GROUP(m_Socket->type) == NETCONN_TCP)
973  {
974  for (int i = 0; i < msghdr->msg_iovlen; ++i)
975  {
976  void *buffer = msghdr->msg_iov[i].iov_base;
977  size_t bufferlen = msghdr->msg_iov[i].iov_len;
978 
979  size_t thisBytesWritten = 0;
980  err = netconn_write_partly(
981  m_Socket, buffer, bufferlen, NETCONN_COPY | NETCONN_MORE,
982  &thisBytesWritten);
983  if (err != ERR_OK)
984  {
985  lwipToSyscallError(err);
986  ok = false;
987  break;
988  }
989 
990  bytesWritten += thisBytesWritten;
991  }
992  }
993  else
994  {
995  struct netbuf *buf = netbuf_new();
996  for (int i = 0; i < msghdr->msg_iovlen; ++i)
997  {
998  netbuf_ref(
999  buf, msghdr->msg_iov[i].iov_base, msghdr->msg_iov[i].iov_len);
1000  }
1001 
1003  err = netconn_send(m_Socket, buf);
1004  if (err != ERR_OK)
1005  {
1006  lwipToSyscallError(err);
1007  ok = false;
1008  }
1009  else
1010  {
1011  bytesWritten += netbuf_len(buf);
1012  netbuf_delete(buf);
1013  }
1014  }
1015 
1016  if (!bytesWritten)
1017  {
1018  if (!ok)
1019  {
1020  return -1;
1021  }
1022  }
1023 
1024  return bytesWritten;
1025 }
1026 
1027 ssize_t LwipSocketSyscalls::recvfrom_msg(struct msghdr *msghdr)
1028 {
1029  if (msghdr->msg_name)
1030  {
1032  SYSCALL_ERROR(Unimplemented);
1033  return -1;
1034  }
1035 
1036  // No data to read right now.
1037  if (!isBlocking())
1038  {
1039  if (!(m_Metadata.recv || m_Metadata.pb))
1040  {
1041  // If an app tightly calls recv() and keeps hitting here, it'll
1042  // burn a lot of cycles for no good reason. Instead, reschedule to
1043  // reduce that tight spin.
1045 
1046  N_NOTICE(" -> no more data available, would block");
1047  SYSCALL_ERROR(NoMoreProcesses);
1048  return -1;
1049  }
1050  }
1051 
1052  err_t err;
1053  if (!m_Metadata.pb)
1054  {
1055  struct pbuf *pb = nullptr;
1056  struct netbuf *buf = nullptr;
1057 
1058  // No partial data present from a previous read. Read new data from
1059  // the socket.
1060  if (NETCONNTYPE_GROUP(netconn_type(m_Socket)) == NETCONN_TCP)
1061  {
1062  err = netconn_recv_tcp_pbuf(m_Socket, &pb);
1063  }
1064  else
1065  {
1066  err = netconn_recv(m_Socket, &buf);
1067  }
1068 
1069  if (err != ERR_OK)
1070  {
1071  N_NOTICE(" -> lwIP error");
1072  lwipToSyscallError(err);
1073  return -1;
1074  }
1075 
1076  if (pb == nullptr && buf != nullptr)
1077  {
1078  pb = buf->p;
1079  }
1080 
1081  m_Metadata.offset = 0;
1082  m_Metadata.pb = pb;
1083  m_Metadata.buf = buf;
1084  }
1085 
1086  size_t totalLen = 0;
1087  for (int i = 0; i < msghdr->msg_iovlen; ++i)
1088  {
1089  void *buffer = msghdr->msg_iov[i].iov_base;
1090  size_t bufferlen = msghdr->msg_iov[i].iov_len;
1091 
1092  // now we read some things.
1093  size_t finalPos = m_Metadata.offset + bufferlen;
1094  if (finalPos > m_Metadata.pb->tot_len)
1095  {
1096  bufferlen = m_Metadata.pb->tot_len - m_Metadata.offset;
1097  if (!bufferlen)
1098  {
1099  break; // finished reading!
1100  }
1101  }
1102 
1103  pbuf_copy_partial(m_Metadata.pb, buffer, bufferlen, m_Metadata.offset);
1104  totalLen += bufferlen;
1105  }
1106 
1107  // partial read?
1108  if ((m_Metadata.offset + totalLen) < m_Metadata.pb->tot_len)
1109  {
1110  m_Metadata.offset += totalLen;
1111  }
1112  else
1113  {
1114  if (m_Metadata.buf == nullptr)
1115  {
1116  pbuf_free(m_Metadata.pb);
1117  }
1118  else
1119  {
1120  // will indirectly clean up m_Metadata.pb as it's a member of the
1121  // netbuf
1122  netbuf_free(m_Metadata.buf);
1123  }
1124 
1125  m_Metadata.pb = nullptr;
1126  m_Metadata.buf = nullptr;
1127  m_Metadata.offset = 0;
1128  }
1129 
1130  N_NOTICE(" -> " << totalLen);
1131  return totalLen;
1132 }
1133 
1134 int LwipSocketSyscalls::listen(int backlog)
1135 {
1136  err_t err = netconn_listen_with_backlog(m_Socket, backlog);
1137  if (err != ERR_OK)
1138  {
1139  N_NOTICE(" -> lwIP error");
1140  lwipToSyscallError(err);
1141  return -1;
1142  }
1143 
1144  return 0;
1145 }
1146 
1147 int LwipSocketSyscalls::bind(const struct sockaddr *address, socklen_t addrlen)
1148 {
1149  uint16_t port = 0;
1150  ip_addr_t ipaddr;
1151  sockaddrToIpaddr(address, port, &ipaddr);
1152 
1153  err_t err = netconn_bind(m_Socket, &ipaddr, port);
1154  if (err != ERR_OK)
1155  {
1156  N_NOTICE(" -> lwIP error");
1157  lwipToSyscallError(err);
1158  return -1;
1159  }
1160 
1161  return 0;
1162 }
1163 
1164 int LwipSocketSyscalls::accept(struct sockaddr *address, socklen_t *addrlen)
1165 {
1166  struct netconn *new_conn;
1167  err_t err = netconn_accept(m_Socket, &new_conn);
1168  if (err != ERR_OK)
1169  {
1170  N_NOTICE(" -> lwIP error");
1171  lwipToSyscallError(err);
1172  return -1;
1173  }
1174 
1175  // get the new peer
1176  ip_addr_t peer;
1177  uint16_t port;
1178  err = netconn_peer(new_conn, &peer, &port);
1179  if (err != ERR_OK)
1180  {
1181  netconn_delete(new_conn);
1182  lwipToSyscallError(err);
1183  return -1;
1184  }
1185 
1187  struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(address);
1188  sin->sin_family = AF_INET;
1189  sin->sin_port = HOST_TO_BIG16(port);
1190  sin->sin_addr.s_addr = peer.u_addr.ip4.addr;
1191  *addrlen = sizeof(sockaddr_in);
1192 
1193  LwipSocketSyscalls *obj =
1194  new LwipSocketSyscalls(m_Domain, m_Type, m_Protocol);
1195  obj->m_Socket = new_conn;
1196  obj->create();
1197  m_SyscallObjects.insert(new_conn, obj);
1198 
1199  size_t fd = getAvailableDescriptor();
1200  FileDescriptor *desc = new FileDescriptor;
1201  desc->networkImpl = obj;
1202  desc->fd = fd;
1203 
1204  addDescriptor(fd, desc);
1205  obj->associate(desc);
1206 
1207  return static_cast<int>(fd);
1208 }
1209 
1210 int LwipSocketSyscalls::shutdown(int how)
1211 {
1212  int rx = 0;
1213  int tx = 0;
1214  if (how == SHUT_RDWR)
1215  {
1216  rx = tx = 1;
1217  }
1218  else if (how == SHUT_RD)
1219  {
1220  rx = 1;
1221  }
1222  else
1223  {
1224  tx = 1;
1225  }
1226 
1227  err_t err = netconn_shutdown(m_Socket, rx, tx);
1228  if (err != ERR_OK)
1229  {
1230  lwipToSyscallError(err);
1231  return -1;
1232  }
1233 
1234  return 0;
1235 }
1236 
1238  struct sockaddr *address, socklen_t *address_len)
1239 {
1240  ip_addr_t peer;
1241  uint16_t port;
1242  err_t err = netconn_peer(m_Socket, &peer, &port);
1243  if (err != ERR_OK)
1244  {
1245  N_NOTICE(" -> getpeername failed");
1246  lwipToSyscallError(err);
1247  return -1;
1248  }
1249 
1251  struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(address);
1252  sin->sin_family = AF_INET;
1253  sin->sin_port = HOST_TO_BIG16(port);
1254  sin->sin_addr.s_addr = peer.u_addr.ip4.addr;
1255  *address_len = sizeof(sockaddr_in);
1256 
1257  return 0;
1258 }
1259 
1261  struct sockaddr *address, socklen_t *address_len)
1262 {
1263  ip_addr_t self;
1264  uint16_t port;
1265  err_t err = netconn_addr(m_Socket, &self, &port);
1266  if (err != ERR_OK)
1267  {
1268  lwipToSyscallError(err);
1269  return -1;
1270  }
1271 
1273  struct sockaddr_in *sin = reinterpret_cast<struct sockaddr_in *>(address);
1274  sin->sin_family = AF_INET;
1275  sin->sin_port = HOST_TO_BIG16(port);
1276  sin->sin_addr.s_addr = self.u_addr.ip4.addr;
1277  *address_len = sizeof(sockaddr_in);
1278 
1279  return 0;
1280 }
1281 
1283  int level, int optname, const void *optvalue, socklen_t optlen)
1284 {
1285  if (m_Protocol == IPPROTO_TCP && level == IPPROTO_TCP)
1286  {
1287 #ifdef TCP_NODELAY
1288 #pragma GCC diagnostic push
1289 #pragma GCC diagnostic ignored "-Wold-style-cast"
1290  if (optname == TCP_NODELAY)
1291  {
1292  N_NOTICE(" -> TCP_NODELAY");
1293  const uint32_t *val = reinterpret_cast<const uint32_t *>(optvalue);
1294  N_NOTICE(" --> val=" << *val);
1295 
1296  // TCP_NODELAY controls Nagle's algorithm usage
1297  if (*val)
1298  {
1299  tcp_nagle_disable(m_Socket->pcb.tcp);
1300  }
1301  else
1302  {
1303  tcp_nagle_enable(m_Socket->pcb.tcp);
1304  }
1305 
1306  return 0;
1307  }
1308 #pragma GCC diagnostic pop
1309 #endif
1310  }
1311 
1313  return -1;
1314 }
1315 
1317  int level, int optname, void *optvalue, socklen_t *optlen)
1318 {
1319  // SO_ERROR etc
1321  return -1;
1322 }
1323 
1324 bool LwipSocketSyscalls::canPoll() const
1325 {
1326  return true;
1327 }
1328 
1330  bool &read, bool &write, bool &error, Semaphore *waiter)
1331 {
1332  bool ok = false;
1333 
1334  if (!(read || write || error))
1335  {
1336  // not actually polling for anything
1337  return true;
1338  }
1339 
1340 #ifdef THREADS
1341  m_Metadata.lock.acquire();
1342 #endif
1343 
1344  if (write)
1345  {
1346  write = m_Metadata.send != 0;
1347  ok = ok || write;
1348  }
1349 
1350  if (read)
1351  {
1352  read = m_Metadata.recv || m_Metadata.pb;
1353  ok = ok || read;
1354  }
1355 
1356  if (error)
1357  {
1358  error = m_Metadata.error;
1359  ok = ok || error;
1360  }
1361 
1362  if (waiter && !ok)
1363  {
1364  // Need to wait for socket data.
1366  m_Metadata.semaphores.pushBack(waiter);
1367  }
1368 
1369 #ifdef THREADS
1370  m_Metadata.lock.release();
1371 #endif
1372 
1373  return ok;
1374 }
1375 
1376 void LwipSocketSyscalls::unPoll(Semaphore *waiter)
1377 {
1378 #ifdef THREADS
1379  m_Metadata.lock.acquire();
1380  for (auto it = m_Metadata.semaphores.begin();
1381  it != m_Metadata.semaphores.end();)
1382  {
1383  if ((*it) == waiter)
1384  {
1385  it = m_Metadata.semaphores.erase(it);
1386  }
1387  else
1388  {
1389  ++it;
1390  }
1391  }
1392  m_Metadata.lock.release();
1393 #endif
1394 }
1395 
1397  struct netconn *conn, enum netconn_evt evt, u16_t len)
1398 {
1399  LwipSocketSyscalls *obj = m_SyscallObjects.lookup(conn);
1400  if (!obj)
1401  {
1402  return;
1403  }
1404 
1405 #ifdef THREADS
1406  obj->m_Metadata.lock.acquire();
1407 #endif
1408 
1409  switch (evt)
1410  {
1411  case NETCONN_EVT_RCVPLUS:
1412  N_NOTICE("RCV+");
1413  ++(obj->m_Metadata.recv);
1414  break;
1415  case NETCONN_EVT_RCVMINUS:
1416  N_NOTICE("RCV-");
1417  if (obj->m_Metadata.recv)
1418  {
1419  --(obj->m_Metadata.recv);
1420  }
1421  break;
1422  case NETCONN_EVT_SENDPLUS:
1423  N_NOTICE("SND+");
1424  obj->m_Metadata.send = 1;
1425  break;
1426  case NETCONN_EVT_SENDMINUS:
1427  N_NOTICE("SND-");
1428  obj->m_Metadata.send = 0;
1429  break;
1430  case NETCONN_EVT_ERROR:
1431  N_NOTICE("ERR");
1432  obj->m_Metadata.error =
1433  true;
1434  break;
1435  default:
1436  N_NOTICE("Unknown netconn callback error.");
1437  }
1438 
1440 #ifdef THREADS
1441  for (auto &it : obj->m_Metadata.semaphores)
1442  {
1443  it->release();
1444  }
1445 
1446  obj->m_Metadata.lock.release();
1447 #endif
1448 }
1449 
1450 void LwipSocketSyscalls::lwipToSyscallError(err_t err)
1451 {
1452  if (err != ERR_OK)
1453  {
1454  N_NOTICE(" -> lwip strerror gives '" << lwip_strerr(err) << "'");
1455  }
1456  // Based on lwIP's err_to_errno_table.
1457  switch (err)
1458  {
1459  case ERR_OK:
1460  break;
1461  case ERR_MEM:
1462  SYSCALL_ERROR(OutOfMemory);
1463  break;
1464  case ERR_BUF:
1465  SYSCALL_ERROR(NoMoreBuffers);
1466  break;
1467  case ERR_TIMEOUT:
1468  SYSCALL_ERROR(TimedOut);
1469  break;
1470  case ERR_RTE:
1471  SYSCALL_ERROR(HostUnreachable);
1472  break;
1473  case ERR_INPROGRESS:
1474  SYSCALL_ERROR(InProgress);
1475  break;
1476  case ERR_VAL:
1477  SYSCALL_ERROR(InvalidArgument);
1478  break;
1479  case ERR_WOULDBLOCK:
1480  SYSCALL_ERROR(NoMoreProcesses);
1481  break;
1482  case ERR_USE:
1483  // address in use
1484  SYSCALL_ERROR(InvalidArgument);
1485  break;
1486  case ERR_ALREADY:
1487  SYSCALL_ERROR(Already);
1488  break;
1489  case ERR_ISCONN:
1490  SYSCALL_ERROR(IsConnected);
1491  break;
1492  case ERR_CONN:
1493  SYSCALL_ERROR(NotConnected);
1494  break;
1495  case ERR_IF:
1496  // no error
1497  break;
1498  case ERR_ABRT:
1499  SYSCALL_ERROR(ConnectionAborted);
1500  break;
1501  case ERR_RST:
1502  SYSCALL_ERROR(ConnectionReset);
1503  break;
1504  case ERR_CLSD:
1505  SYSCALL_ERROR(NotConnected);
1506  break;
1507  case ERR_ARG:
1508  SYSCALL_ERROR(IoError);
1509  break;
1510  }
1511 }
1512 
1513 LwipSocketSyscalls::LwipMetadata::LwipMetadata()
1514  : recv(0), send(0), error(false), lock(false), semaphores(), offset(0),
1515  pb(nullptr), buf(nullptr)
1516 {
1517 }
1518 
1519 UnixSocketSyscalls::UnixSocketSyscalls(int domain, int type, int protocol)
1520  : NetworkSyscalls(domain, type, protocol), m_Socket(nullptr),
1521  m_Remote(nullptr), m_LocalPath(), m_RemotePath()
1522 {
1523 }
1524 
1526 {
1528  N_NOTICE("UnixSocketSyscalls::~UnixSocketSyscalls");
1529  m_Socket->unbind();
1530  delete m_Socket;
1531 }
1532 
1534 {
1535  if (m_Socket)
1536  {
1537  return true;
1538  }
1539 
1540  // Create an unnamed unix socket by default.
1541  m_Socket = new UnixSocket(
1542  String(), g_pUnixFilesystem, nullptr, nullptr, getSocketType());
1543 
1544  return true;
1545 }
1546 
1548  const struct sockaddr *address, socklen_t addrlen)
1549 {
1550  // Find the remote socket
1551  const struct sockaddr_un *un =
1552  reinterpret_cast<const struct sockaddr_un *>(address);
1553  String pathname;
1554  normalisePath(pathname, un->sun_path);
1555 
1556  N_NOTICE(" -> unix connect: '" << pathname << "'");
1557 
1558  File *file = VFS::instance().find(pathname);
1559  if (!file)
1560  {
1561  SYSCALL_ERROR(DoesNotExist);
1562  N_NOTICE(" -> unix socket '" << pathname << "' doesn't exist");
1563  return -1;
1564  }
1565 
1566  if (!file->isSocket())
1567  {
1569  SYSCALL_ERROR(DoesNotExist);
1570  N_NOTICE(" -> target '" << pathname << "' is not a unix socket");
1571  return -1;
1572  }
1573 
1574  m_Remote = static_cast<UnixSocket *>(file);
1575 
1576  if (getType() == SOCK_STREAM)
1577  {
1578  N_NOTICE(" -> stream");
1579 
1580  // Create the remote for accept() on the server side.
1581  UnixSocket *remote = new UnixSocket(
1582  String(), g_pUnixFilesystem, nullptr, nullptr,
1583  UnixSocket::Streaming);
1584  m_Remote->addSocket(remote);
1585 
1586  bool blocking =
1587  !((getFileDescriptor()->flflags & O_NONBLOCK) == O_NONBLOCK);
1588 
1589  // Bind our local socket to the remote side
1590  N_NOTICE(" -> stream is binding blocking=" << blocking);
1591  m_Socket->bind(remote, blocking);
1592  N_NOTICE(" -> stream bound!");
1593  }
1594  else
1595  {
1596  N_NOTICE(" -> dgram");
1597  }
1598 
1599  m_RemotePath = pathname;
1600 
1601  N_NOTICE(" -> remote is now " << m_RemotePath);
1602 
1603  return 0;
1604 }
1605 
1606 ssize_t UnixSocketSyscalls::sendto_msg(const struct msghdr *msghdr)
1607 {
1608  N_NOTICE("UnixSocketSyscalls::sendto_msg");
1609 
1610  UnixSocket *remote = getRemote();
1611  if (getType() == SOCK_STREAM && !remote)
1612  {
1616  N_NOTICE(" -> not connected");
1617  SYSCALL_ERROR(NotConnected);
1618  return -1;
1619  }
1620 
1621  if (!m_Remote)
1622  {
1623  if (getType() == SOCK_STREAM)
1624  {
1625  // sendto() can't be used for streaming sockets
1627  N_NOTICE(
1628  " -> sendto on streaming socket with no remote is invalid");
1629  return -1;
1630  }
1631  else if (!msghdr->msg_name)
1632  {
1634  N_NOTICE(" -> sendto on unconnected socket with no address");
1635  return -1;
1636  }
1637 
1638  // Find the remote socket
1639  const struct sockaddr_un *un =
1640  reinterpret_cast<const struct sockaddr_un *>(msghdr->msg_name);
1641  String pathname;
1642  normalisePath(pathname, un->sun_path);
1643 
1644  N_NOTICE(" -> unix connect: '" << pathname << "'");
1645 
1646  File *file = VFS::instance().find(pathname);
1647  if (!file)
1648  {
1649  SYSCALL_ERROR(DoesNotExist);
1650  N_NOTICE(" -> unix socket '" << pathname << "' doesn't exist");
1651  return -1;
1652  }
1653 
1654  if (!file->isSocket())
1655  {
1657  SYSCALL_ERROR(DoesNotExist);
1658  N_NOTICE(" -> target '" << pathname << "' is not a unix socket");
1659  return -1;
1660  }
1661 
1662  remote = static_cast<UnixSocket *>(file);
1663  }
1664 
1665  N_NOTICE(" -> transmitting!");
1666 
1667  uint64_t numWritten = 0;
1668  for (int i = 0; i < msghdr->msg_iovlen; ++i)
1669  {
1670  void *buffer = msghdr->msg_iov[i].iov_base;
1671  size_t bufferlen = msghdr->msg_iov[i].iov_len;
1672 
1673  uint64_t thisWrite = remote->write(
1674  reinterpret_cast<uintptr_t>(static_cast<const char *>(m_LocalPath)),
1675  bufferlen, reinterpret_cast<uintptr_t>(buffer), isBlocking());
1676 
1677  if (!thisWrite)
1678  {
1679  // eof or some other similar condition
1680  break;
1681  }
1682 
1683  numWritten += thisWrite;
1684  }
1685  if (!numWritten)
1686  {
1687  if (!isBlocking())
1688  {
1689  // NOT an EOF yet!
1691  SYSCALL_ERROR(NoMoreProcesses);
1692  N_NOTICE(" -> -1 (EAGAIN)");
1693  return -1;
1694  }
1695  }
1696  N_NOTICE(" -> " << numWritten);
1697  return numWritten;
1698 }
1699 
1700 ssize_t UnixSocketSyscalls::recvfrom_msg(struct msghdr *msghdr)
1701 {
1702  String remote;
1703  uint64_t numRead = 0;
1704  for (int i = 0; i < msghdr->msg_iovlen; ++i)
1705  {
1706  void *buffer = msghdr->msg_iov[i].iov_base;
1707  size_t bufferlen = msghdr->msg_iov[i].iov_len;
1708 
1709  uint64_t thisRead = m_Socket->recvfrom(
1710  bufferlen, reinterpret_cast<uintptr_t>(buffer), isBlocking(),
1711  remote);
1712  if (!thisRead)
1713  {
1714  // eof or some other similar condition
1715  break;
1716  }
1717 
1718  numRead += thisRead;
1719  }
1720 
1721  if (numRead && msghdr->msg_name)
1722  {
1723  struct sockaddr_un *un =
1724  reinterpret_cast<struct sockaddr_un *>(msghdr->msg_name);
1725  un->sun_family = AF_UNIX;
1726  StringCopy(un->sun_path, remote);
1727  msghdr->msg_namelen = sizeof(sa_family_t) + remote.length();
1728  }
1729 
1731  msghdr->msg_flags = 0;
1732  if (!numRead)
1733  {
1734  if (!isBlocking())
1735  {
1736  // NOT an EOF yet!
1738  SYSCALL_ERROR(NoMoreProcesses);
1739  N_NOTICE(" -> -1 (EAGAIN)");
1740  return -1;
1741  }
1742  }
1743  N_NOTICE(" -> " << numRead);
1744  return numRead;
1745 }
1746 
1748 {
1749  if (m_Socket->getType() != UnixSocket::Streaming)
1750  {
1751  // EOPNOTSUPP
1752  return -1;
1753  }
1754 
1756 
1757  m_Socket->markListening();
1758  return 0;
1759 }
1760 
1761 int UnixSocketSyscalls::bind(const struct sockaddr *address, socklen_t addrlen)
1762 {
1764 
1765  // Valid state. But no socket, so do the magic here.
1766  const struct sockaddr_un *un =
1767  reinterpret_cast<const struct sockaddr_un *>(address);
1768 
1769  if (SUN_LEN(un) == sizeof(sa_family_t))
1770  {
1772  return 0;
1773  }
1774 
1775  String adjusted_pathname;
1776  normalisePath(adjusted_pathname, un->sun_path);
1777 
1778  N_NOTICE(" -> unix bind: '" << adjusted_pathname << "'");
1779 
1780  File *cwd = VFS::instance().find(String("."));
1781  if (adjusted_pathname.endswith('/'))
1782  {
1783  // uh, that's a directory
1784  SYSCALL_ERROR(IsADirectory);
1785  return -1;
1786  }
1787 
1788  File *parentDirectory = cwd;
1789 
1790  const char *pDirname =
1791  DirectoryName(static_cast<const char *>(adjusted_pathname));
1792  const char *pBasename =
1793  BaseName(static_cast<const char *>(adjusted_pathname));
1794 
1795  String basename(pBasename);
1796  delete[] pBasename;
1797 
1798  if (pDirname)
1799  {
1800  // Reorder rfind result to be from beginning of string.
1801  String dirname(pDirname);
1802  delete[] pDirname;
1803 
1804  N_NOTICE(" -> dirname=" << dirname);
1805 
1806  parentDirectory = VFS::instance().find(dirname);
1807  if (!parentDirectory)
1808  {
1809  N_NOTICE(" -> parent directory '" << dirname << "' doesn't exist");
1810  SYSCALL_ERROR(DoesNotExist);
1811  return -1;
1812  }
1813  }
1814 
1815  if (!parentDirectory->isDirectory())
1816  {
1817  SYSCALL_ERROR(NotADirectory);
1818  return -1;
1819  }
1820 
1821  Directory *pDir = Directory::fromFile(parentDirectory);
1822 
1824  UnixSocket *socket = new UnixSocket(
1825  basename, parentDirectory->getFilesystem(), parentDirectory, nullptr,
1826  getSocketType());
1827  if (!pDir->addEphemeralFile(socket))
1828  {
1830  delete socket;
1831  return false;
1832  }
1833 
1834  N_NOTICE(" -> basename=" << basename);
1835 
1836  // bind() then connect().
1837  if (!m_LocalPath.length())
1838  {
1839  // just an unnamed socket, safe to delete.
1840  delete m_Socket;
1841  }
1842 
1843  m_Socket = socket;
1844  m_LocalPath = adjusted_pathname;
1845 
1846  return 0;
1847 }
1848 
1849 int UnixSocketSyscalls::accept(struct sockaddr *address, socklen_t *addrlen)
1850 {
1851  N_NOTICE("unix accept");
1852  UnixSocket *remote = m_Socket->getSocket(isBlocking());
1853  if (!remote)
1854  {
1855  N_NOTICE("accept() failed");
1856  SYSCALL_ERROR(NoMoreProcesses);
1857  return -1;
1858  }
1859 
1860  if (remote)
1861  {
1862  N_NOTICE("accept() got a socket");
1863 
1864  struct sockaddr_un *sun =
1865  reinterpret_cast<struct sockaddr_un *>(address);
1866 
1867  if (remote->getName().length())
1868  {
1869  // Named.
1870  String name = remote->getFullPath();
1871 
1872  StringCopy(sun->sun_path, name);
1873  *addrlen = sizeof(sa_family_t) + name.length();
1874  }
1875  else
1876  {
1877  *addrlen = sizeof(sa_family_t);
1878  }
1879 
1880  sun->sun_family = AF_UNIX;
1881 
1882  UnixSocketSyscalls *obj =
1883  new UnixSocketSyscalls(m_Domain, m_Type, m_Protocol);
1884  obj->m_Socket = remote;
1885  obj->m_Remote = remote->getOther();
1886  obj->m_LocalPath = String();
1887  obj->m_RemotePath = m_Socket->getFullPath();
1888  obj->create();
1889 
1890  size_t fd = getAvailableDescriptor();
1891  FileDescriptor *desc = new FileDescriptor;
1892  desc->networkImpl = obj;
1893  desc->fd = fd;
1894 
1895  addDescriptor(fd, desc);
1896  obj->associate(desc);
1897 
1898  return static_cast<int>(fd);
1899  }
1900 
1901  return -1;
1902 }
1903 
1905 {
1907  N_NOTICE("UnixSocketSyscalls::shutdown");
1908  return 0;
1909 }
1910 
1911 int UnixSocketSyscalls::getpeername(
1912  struct sockaddr *address, socklen_t *address_len)
1913 {
1914  N_NOTICE("UNIX getpeername");
1915  struct sockaddr_un *sun = reinterpret_cast<struct sockaddr_un *>(address);
1916  sun->sun_family = AF_UNIX;
1917  StringCopy(sun->sun_path, m_RemotePath);
1918  *address_len = sizeof(sa_family_t) + m_RemotePath.length();
1919 
1920  N_NOTICE(" -> " << m_RemotePath);
1921  return 0;
1922 }
1923 
1924 int UnixSocketSyscalls::getsockname(
1925  struct sockaddr *address, socklen_t *address_len)
1926 {
1927  N_NOTICE("UNIX getsockname");
1928  struct sockaddr_un *sun = reinterpret_cast<struct sockaddr_un *>(address);
1929  sun->sun_family = AF_UNIX;
1930  StringCopy(sun->sun_path, m_LocalPath);
1931  *address_len = sizeof(sa_family_t) + m_LocalPath.length();
1932 
1933  N_NOTICE(" -> " << m_LocalPath);
1934  return 0;
1935 }
1936 
1937 int UnixSocketSyscalls::setsockopt(
1938  int level, int optname, const void *optvalue, socklen_t optlen)
1939 {
1940  // nothing to do here
1941  return -1;
1942 }
1943 
1944 int UnixSocketSyscalls::getsockopt(
1945  int level, int optname, void *optvalue, socklen_t *optlen)
1946 {
1947  if (level == SOL_SOCKET)
1948  {
1949  if (optname == SO_PEERCRED)
1950  {
1951  N_NOTICE(" -> SO_PEERCRED");
1952 
1953  // get credentials of other side of this socket
1954  struct ucred *targetCreds =
1955  reinterpret_cast<struct ucred *>(optvalue);
1956  struct ucred sourceCreds = m_Socket->getPeerCredentials();
1957 
1958  N_NOTICE(" --> pid=" << Dec << sourceCreds.pid);
1959  N_NOTICE(" --> uid=" << Dec << sourceCreds.uid);
1960  N_NOTICE(" --> gid=" << Dec << sourceCreds.gid);
1961 
1962  *targetCreds = sourceCreds;
1963  *optlen = sizeof(sourceCreds);
1964 
1965  return 0;
1966  }
1967  }
1968  // nothing to do here
1969  return -1;
1970 }
1971 
1972 bool UnixSocketSyscalls::canPoll() const
1973 {
1974  return getRemote() || m_Socket;
1975 }
1976 
1977 bool UnixSocketSyscalls::poll(
1978  bool &read, bool &write, bool &error, Semaphore *waiter)
1979 {
1980  UnixSocket *remote = getRemote();
1981  UnixSocket *local = m_Socket;
1982 
1983  if (read && !local)
1984  {
1985  ERROR(
1986  "UnixSocketSyscalls::poll - no local socket to poll for reading!");
1987  }
1988  if (write && !remote)
1989  {
1990  ERROR(
1991  "UnixSocketSyscalls::poll - no remote socket to poll for writing!");
1992  }
1993 
1994  bool ok = false;
1995  if (read && local)
1996  {
1997  read = local->select(false, 0);
1998  ok = ok || read;
1999 
2000  if (waiter && !read)
2001  {
2002  local->addWaiter(waiter);
2003  }
2004  }
2005 
2006  if (write && remote)
2007  {
2008  write = remote->select(true, 0);
2009  ok = ok || write;
2010 
2011  if (waiter && !write)
2012  {
2013  remote->addWaiter(waiter);
2014  }
2015  }
2016 
2017  error = false;
2018  return ok;
2019 }
2020 
2021 void UnixSocketSyscalls::unPoll(Semaphore *waiter)
2022 {
2023  UnixSocket *remote = getRemote();
2024  UnixSocket *local = m_Socket;
2025 
2026  // these don't error out if the Semaphore isn't present so this is easy
2027  if (remote)
2028  {
2029  remote->removeWaiter(waiter);
2030  }
2031  if (local)
2032  {
2033  local->removeWaiter(waiter);
2034  }
2035 }
2036 
2037 bool UnixSocketSyscalls::monitor(Thread *pThread, Event *pEvent)
2038 {
2039  UnixSocket *remote = getRemote();
2040  UnixSocket *local = m_Socket;
2041 
2042  if (remote != local)
2043  {
2044  remote->addWaiter(pThread, pEvent);
2045  }
2046 
2047  local->addWaiter(pThread, pEvent);
2048 
2049  return true;
2050 }
2051 
2052 bool UnixSocketSyscalls::unmonitor(Event *pEvent)
2053 {
2054  UnixSocket *remote = getRemote();
2055  UnixSocket *local = m_Socket;
2056 
2057  if (remote != local)
2058  {
2059  remote->removeWaiter(pEvent);
2060  }
2061 
2062  local->removeWaiter(pEvent);
2063 
2064  return true;
2065 }
2066 
2068 {
2069  if (!m_Socket->bind(other->m_Socket))
2070  {
2071  return false;
2072  }
2073 
2074  // make sure both sides can use the socket
2075  other->m_Socket->acknowledgeBind();
2076 
2077  m_Remote = other->m_Socket;
2078  other->m_Remote = m_Socket;
2079  return true;
2080 }
2081 
2082 UnixSocket *UnixSocketSyscalls::getRemote() const
2083 {
2084  UnixSocket *remote = m_Remote;
2085  if (getType() == SOCK_STREAM)
2086  {
2087  if (!m_Socket->getOther())
2088  {
2089  return nullptr;
2090  }
2091 
2092  remote = m_Socket;
2093  }
2094 
2095  return remote;
2096 }
2097 
2098 UnixSocket::SocketType UnixSocketSyscalls::getSocketType() const
2099 {
2100  if (getType() == SOCK_STREAM)
2101  {
2102  return UnixSocket::Streaming;
2103  }
2104 
2105  return UnixSocket::Datagram;
2106 }
virtual bool create()
virtual int getsockname(struct sockaddr *address, socklen_t *address_len)
virtual int bind(const struct sockaddr *address, socklen_t addrlen)
u16_t tot_len
Definition: pbuf.h:175
File * find(const String &path, File *pStartNode=0)
Definition: VFS.cc:243
Definition: err.h:109
bool pairWith(UnixSocketSyscalls *other)
virtual bool poll(bool &read, bool &write, bool &error, Semaphore *waiter)
Definition: err.h:86
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
Definition: Semaphore.h:62
SharedPointer< class NetworkSyscalls > networkImpl
Network syscall implementation for this descriptor (if it&#39;s a socket).
virtual int accept(struct sockaddr *address, socklen_t *addrlen)
static Directory * fromFile(File *pF)
Definition: Directory.h:50
size_t fd
Descriptor number.
virtual bool create()
Implementation-specific final socket creation logic.
virtual ssize_t recvfrom_msg(struct msghdr *msghdr)
Definition: String.h:49
static VFS & instance()
Definition: VFS.cc:56
Definition: err.h:84
virtual ssize_t recvfrom_msg(struct msghdr *msghdr)
virtual int listen(int backlog)
virtual ssize_t sendto_msg(const struct msghdr *msghdr)
Definition: err.h:113
static bool checkAddress(uintptr_t addr, size_t extent, size_t flags)
#define WARNING(text)
Definition: Log.h:78
virtual ~UnixSocketSyscalls()
Definition: err.h:115
virtual ssize_t sendto_msg(const struct msghdr *msghdr)
Definition: pbuf.h:161
void release(size_t n=1)
Definition: Semaphore.cc:239
virtual int shutdown(int how)
virtual int setsockopt(int level, int optname, const void *optvalue, socklen_t optlen)
virtual String getFullPath(bool bWithLabel=true)
Definition: File.cc:718
Definition: Log.h:136
#define INADDR_LOOPBACK
Definition: inet.h:92
Definition: err.h:106
static Scheduler & instance()
Definition: Scheduler.h:48
s8_t err_t
Definition: err.h:76
Definition: err.h:104
virtual bool isSocket() const
Definition: File.cc:451
virtual int getsockopt(int level, int optname, void *optvalue, socklen_t *optlen)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:1034
virtual int getpeername(struct sockaddr *address, socklen_t *address_len)
static void netconnCallback(struct netconn *conn, enum netconn_evt evt, uint16_t len)
virtual bool create()
Implementation-specific final socket creation logic.
String getName() const
Definition: File.cc:411
virtual int connect(const struct sockaddr *address, socklen_t addrlen)
virtual int connect(const struct sockaddr *address, socklen_t addrlen)
Definition: Thread.h:54
Definition: Event.h:48
Definition: err.h:111
Definition: err.h:94
bool addEphemeralFile(File *pFile)
Add an ephemeral file to the directory.
Definition: Directory.cc:159
#define ERROR(text)
Definition: Log.h:82
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:734
virtual Type getType()
Definition: Network.cc:56
Definition: err.h:82
virtual bool isDirectory()
Definition: File.cc:436
Definition: err.h:98
void yield()
Definition: Scheduler.cc:135
Definition: Log.h:138
Definition: err.h:90
Definition: File.h:66
bool endswith(const char c) const
Definition: String.cc:710
virtual bool send(size_t nBytes, uintptr_t buffer)
Definition: Ne2k.cc:150
virtual uint64_t write(uint64_t location, uint64_t size, uintptr_t buffer, bool bCanBlock=true) final
Definition: File.cc:183
virtual int select(bool bWriting=false, int timeout=0)