/* * Create socket for incoming connections and bind to it an address for * clients to use. Returns -1 on failure. * * If '*family' is AF_UNIX and unix domain sockets are supported: * 'port' is ignored and 'address' is the path to the socket file in the filesystem. * * Otherwise: * address is a string representing the Inet/IPv6 address that the port * is advertised for. To allow connections to all this host's internet * addresses from clients use address == "INADDR_ANY", or for localhost * access only use address == "INADDR_LOOPBACK". * On input, 'family' is a pointer to the address family to use (AF_INET, * AF_INET6) if the address specified is empty. If the spec is not * empty then family is ignored and is set to the actual address family * used. 'family' must be initialized to AF_UNSPEC, in this case. */ static int OpenRequestSocket(int port, const char *address, int *family, int backlog, __pmFdSet *fdset, int *maximum) { int fd = -1; int one, sts; __pmSockAddr *myAddr; int isUnix = 0; /* * Using this flag will eliminate the need for more conditional * compilation below, hopefully making the code easier to read and maintain. */ #if defined(HAVE_STRUCT_SOCKADDR_UN) if (*family == AF_UNIX) isUnix = 1; #endif if (isUnix) { if ((myAddr = __pmSockAddrAlloc()) == NULL) { __pmNoMem("OpenRequestSocket: can't allocate socket address", sizeof(*myAddr), PM_FATAL_ERR); } /* Initialize the address. */ __pmSockAddrSetFamily(myAddr, *family); __pmSockAddrSetPath(myAddr, address); /* Create the socket. */ fd = __pmCreateUnixSocket(); } else { /* * If the address is unspecified, then use the address family we * have been given, otherwise the family will be determined by * __pmStringToSockAddr. */ if (address == NULL || strcmp(address, "INADDR_ANY") == 0) { if ((myAddr = __pmSockAddrAlloc()) == NULL) { __pmNoMem("OpenRequestSocket: can't allocate socket address", sizeof(*myAddr), PM_FATAL_ERR); } __pmSockAddrInit(myAddr, *family, INADDR_ANY, 0); } else if (strcmp(address, "INADDR_LOOPBACK") == 0) { if ((myAddr = __pmSockAddrAlloc()) == NULL) { __pmNoMem("OpenRequestSocket: can't allocate socket address", sizeof(*myAddr), PM_FATAL_ERR); } __pmSockAddrInit(myAddr, *family, INADDR_LOOPBACK, 0); } else { if ((myAddr = __pmStringToSockAddr(address)) == NULL) { __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s) invalid address\n", port, address); goto fail; } *family = __pmSockAddrGetFamily(myAddr); } __pmSockAddrSetPort(myAddr, port); /* Create the socket. */ if (*family == AF_INET) fd = __pmCreateSocket(); else if (*family == AF_INET6) fd = __pmCreateIPv6Socket(); else { __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s) invalid address family: %d\n", port, address, *family); goto fail; } } if (fd < 0) { __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) __pmCreateSocket: %s\n", port, address, AddressFamily(*family), netstrerror()); goto fail; } /* Ignore dead client connections. */ one = 1; #ifndef IS_MINGW if (__pmSetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, (__pmSockLen)sizeof(one)) < 0) { __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) __pmSetSockOpt(SO_REUSEADDR): %s\n", port, address, AddressFamily(*family), netstrerror()); goto fail; } #else if (__pmSetSockOpt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&one, (__pmSockLen)sizeof(one)) < 0) { __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) __pmSetSockOpt(EXCLUSIVEADDRUSE): %s\n", port, address, AddressFamily(*family), netstrerror()); goto fail; } #endif /* and keep alive please - bad networks eat fds */ if (__pmSetSockOpt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&one, (__pmSockLen)sizeof(one)) < 0) { __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) __pmSetSockOpt(SO_KEEPALIVE): %s\n", port, address, AddressFamily(*family), netstrerror()); goto fail; } sts = __pmBind(fd, (void *)myAddr, __pmSockAddrSize()); __pmSockAddrFree(myAddr); myAddr = NULL; if (sts < 0) { sts = neterror(); __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) __pmBind: %s\n", port, address, AddressFamily(*family), netstrerror()); if (sts == EADDRINUSE) __pmNotifyErr(LOG_ERR, "%s may already be running\n", pmProgname); goto fail; } if (isUnix) { /* * For unix domain sockets, grant rw access to the socket for all, * otherwise, on linux platforms, connection will not be possible. * This must be done AFTER binding the address. See Unix(7) for details. */ sts = chmod(address, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (sts != 0) { __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) chmod(%s): %s\n", port, address, AddressFamily(*family), address, strerror(errno)); goto fail; } } sts = __pmListen(fd, backlog); /* Max. pending connection requests */ if (sts < 0) { __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) __pmListen: %s\n", port, address, AddressFamily(*family), netstrerror()); goto fail; } if (fd > *maximum) *maximum = fd; __pmFD_SET(fd, fdset); return fd; fail: if (fd != -1) { __pmCloseSocket(fd); /* We must unlink the socket file. */ if (isUnix) unlink(address); } if (myAddr) __pmSockAddrFree(myAddr); return -1; }
/*! \brief Allows private extensions. If you override this method you must call the parent's method for unknown ops. */ status_t KPPPProtocol::Control(uint32 op, void *data, size_t length) { switch (op) { case PPPC_GET_PROTOCOL_INFO: { if (length < sizeof(ppp_protocol_info_t) || !data) return B_ERROR; ppp_protocol_info *info = (ppp_protocol_info*) data; memset(info, 0, sizeof(ppp_protocol_info_t)); if (Name()) strncpy(info->name, Name(), PPP_HANDLER_NAME_LENGTH_LIMIT); if (Type()) strncpy(info->type, Type(), PPP_HANDLER_NAME_LENGTH_LIMIT); info->activationPhase = ActivationPhase(); info->addressFamily = AddressFamily(); info->flags = Flags(); info->side = Side(); info->level = Level(); info->overhead = Overhead(); info->connectionPhase = fConnectionPhase; info->protocolNumber = ProtocolNumber(); info->isEnabled = IsEnabled(); info->isUpRequested = IsUpRequested(); break; } case PPPC_ENABLE: if (length < sizeof(uint32) || !data) return B_ERROR; SetEnabled(*((uint32*)data)); break; default: return B_BAD_VALUE; } return B_OK; }
socklen_t sockAddrBase::GetSize() const { return AddressFamily() == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in); }