/**************************************************************************** * net/socket/socket.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include "usrsock/usrsock.h" #include "socket/socket.h" #ifdef CONFIG_NET /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: psock_socket * * Description: * socket() creates an endpoint for communication and returns a socket * structure. * * Input Parameters: * domain (see sys/socket.h) * type (see sys/socket.h) * protocol (see sys/socket.h) * psock A pointer to a user allocated socket structure to be * initialized. * * Returned Value: * Returns zero (OK) on success. On failure, it returns a negated errno * value to indicate the nature of the error: * * EACCES * Permission to create a socket of the specified type and/or protocol * is denied. * EAFNOSUPPORT * The implementation does not support the specified address family. * EINVAL * Unknown protocol, or protocol family not available. * EMFILE * Process file table overflow. * ENFILE * The system limit on the total number of open files has been reached. * ENOBUFS or ENOMEM * Insufficient memory is available. The socket cannot be created until * sufficient resources are freed. * EPROTONOSUPPORT * The protocol type or the specified protocol is not supported within * this domain. * ****************************************************************************/ int psock_socket(int domain, int type, int protocol, FAR struct socket *psock) { FAR const struct sock_intf_s *sockif = NULL; int ret; if (type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_TYPE_MASK)) { return -EINVAL; } /* Initialize the socket structure */ psock->s_domain = domain; psock->s_proto = protocol; psock->s_conn = NULL; psock->s_type = type & SOCK_TYPE_MASK; #ifdef CONFIG_NET_USRSOCK /* Get the usrsock interface */ sockif = &g_usrsock_sockif; psock->s_sockif = sockif; ret = sockif->si_setup(psock); /* When usrsock daemon returns -ENOSYS or -ENOTSUP, it means to use * kernel's network stack, so fallback to kernel socket. * When -ENETDOWN is returned, it means the usrsock daemon was never * launched or is no longer running, so fallback to kernel socket. */ if (ret == 0 || (ret != -ENOSYS && ret != -ENOTSUP && ret != -ENETDOWN)) { return ret; } #endif /* Get the socket interface */ sockif = net_sockif(domain, psock->s_type, psock->s_proto); if (sockif == NULL) { nerr("ERROR: socket address family unsupported: %d\n", domain); #ifdef CONFIG_NET_USRSOCK /* We tried to fallback to kernel socket, but one is not available, * so use the return code from usrsock. */ return ret; #endif return -EAFNOSUPPORT; } /* The remaining of the socket initialization depends on the address * family. */ DEBUGASSERT(sockif->si_setup != NULL); psock->s_sockif = sockif; ret = sockif->si_setup(psock); if (ret >= 0) { FAR struct socket_conn_s *conn = psock->s_conn; if (type & SOCK_NONBLOCK) { conn->s_flags |= _SF_NONBLOCK; } /* The socket has been successfully initialized */ conn->s_flags |= _SF_INITD; } else { nerr("ERROR: socket si_setup() failed: %d\n", ret); } return ret; } #endif /* CONFIG_NET */