void wccpConnectionOpen(void) { u_short port = WCCP_PORT; struct sockaddr_in router, local; int local_len, router_len; debug(80, 5) ("wccpConnectionOpen: Called\n"); if (Config.Wccp.router.s_addr == any_addr.s_addr) { debug(1, 1) ("WCCP Disabled.\n"); return; } theInWccpConnection = comm_open(SOCK_DGRAM, 0, Config.Wccp.incoming, port, COMM_NONBLOCKING, "WCCP Socket"); if (theInWccpConnection < 0) fatal("Cannot open WCCP Port"); commSetSelect(theInWccpConnection, COMM_SELECT_READ, wccpHandleUdp, NULL, 0); debug(1, 1) ("Accepting WCCP messages on port %d, FD %d.\n", (int) port, theInWccpConnection); if (Config.Wccp.outgoing.s_addr != no_addr.s_addr) { theOutWccpConnection = comm_open(SOCK_DGRAM, 0, Config.Wccp.outgoing, port, COMM_NONBLOCKING, "WCCP Socket"); if (theOutWccpConnection < 0) fatal("Cannot open Outgoing WCCP Port"); commSetSelect(theOutWccpConnection, COMM_SELECT_READ, wccpHandleUdp, NULL, 0); debug(1, 1) ("Outgoing WCCP messages on port %d, FD %d.\n", (int) port, theOutWccpConnection); fd_note(theOutWccpConnection, "Outgoing WCCP socket"); fd_note(theInWccpConnection, "Incoming WCCP socket"); } else { theOutWccpConnection = theInWccpConnection; } router_len = sizeof(router); memset(&router, '\0', router_len); router.sin_family = AF_INET; router.sin_port = htons(port); router.sin_addr = Config.Wccp.router; if (connect(theOutWccpConnection, (struct sockaddr *) &router, router_len)) fatal("Unable to connect WCCP out socket"); local_len = sizeof(local); memset(&local, '\0', local_len); if (getsockname(theOutWccpConnection, (struct sockaddr *) &local, &local_len)) fatal("Unable to getsockname on WCCP out socket"); local_ip.s_addr = local.sin_addr.s_addr; }
void idnsInit(void) { static int init = 0; if (DnsSocket < 0) { DnsSocket = comm_open(SOCK_DGRAM, 0, Config.Addrs.udp_outgoing, 0, COMM_NONBLOCKING, "DNS Socket"); if (DnsSocket < 0) fatal("Could not create a DNS socket"); debug(78, 1) ("DNS Socket created on FD %d\n", DnsSocket); } assert(0 == nns); idnsParseNameservers(); if (0 == nns) idnsParseResolvConf(); if (0 == nns) fatal("Could not find any nameservers.\n" " Please check your /etc/resolv.conf file\n" " or use the 'dns_nameservers' option in squid.conf."); if (!init) { memDataInit(MEM_IDNS_QUERY, "idns_query", sizeof(idns_query), 0); cachemgrRegister("idns", "Internal DNS Statistics", idnsStats, 0, 1); memset(RcodeMatrix, '\0', sizeof(RcodeMatrix)); init++; } }
static int init_finish(adns_state ads) { struct in_addr ia; int r; if (!ads->nservers) { #if 0 if (ads->diagfile && ads->iflags & adns_if_debug) fprintf(ads->diagfile,"adns: no nameservers, using localhost\n"); #endif ia.s_addr= htonl(INADDR_LOOPBACK); addserver(ads,ia); } ads->udpsocket = comm_open(AF_INET, SOCK_DGRAM, 0, "UDP Resolver socket"); if (ads->udpsocket<0) { ilog(L_CRIT, "Failed to open socket"); r= errno; goto x_free; } r= adns__setnonblock(ads,ads->udpsocket); if (r) { ilog(L_CRIT, "Failed to make socket non-blocking"); r= errno; goto x_closeudp; } return 0; x_closeudp: fd_close(ads->udpsocket); x_free: MyFree(ads); ilog(L_CRIT, "Returning from init_finish: r = %d", r); return r; }
/* * peerProbeConnect will be called on dead peers by neighborUp */ static int peerProbeConnect(peer * p) { int fd; time_t ctimeout = p->connect_timeout > 0 ? p->connect_timeout : Config.Timeout.peer_connect; int ret = squid_curtime - p->stats.last_connect_failure > ctimeout * 10; if (p->test_fd != -1) return ret; /* probe already running */ if (squid_curtime - p->stats.last_connect_probe == 0) return ret; /* don't probe to often */ fd = comm_open(SOCK_STREAM, IPPROTO_TCP, getOutgoingAddr(NULL), 0, COMM_NONBLOCKING, p->name); if (fd < 0) return ret; commSetTimeout(fd, ctimeout, peerProbeConnectTimeout, p); p->test_fd = fd; p->stats.last_connect_probe = squid_curtime; commConnectStart(p->test_fd, p->host, p->http_port, peerProbeConnectDone, p, NULL); return ret; }
/* * comm_accept() - accept an incoming connection * * This is a simple wrapper for accept() which enforces FD limits like * comm_open() does. */ int comm_accept(int fd, struct sockaddr *pn, socklen_t *addrlen) { int newfd; if(number_fd >= MASTER_MAX) { errno = ENFILE; return -1; } /* * Next, do the accept(). if we get an error, we should drop the * reserved fd limit, but we can deal with that when comm_open() * also does it. XXX -- adrian */ newfd = accept(fd, (struct sockaddr *) pn, addrlen); comm_fd_hack(&newfd); if(newfd < 0) return -1; /* Set the socket non-blocking, and other wonderful bits */ if(!comm_set_nb(newfd)) { libcharybdis_log("comm_accept: Couldn't set FD %d non blocking!", newfd); close(newfd); return -1; } /* Next, tag the FD as an incoming connection */ comm_open(newfd, FD_SOCKET, "Incoming connection"); /* .. and return */ return newfd; }
static void idnsRetryTcp(idns_query * q) { struct in_addr addr; int ns = (q->nsends - 1) % nns; idnsTcpCleanup(q); if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) addr = Config.Addrs.udp_outgoing; else addr = Config.Addrs.udp_incoming; q->tcp_socket = comm_open(SOCK_STREAM, IPPROTO_TCP, addr, 0, COMM_NONBLOCKING, "DNS TCP Socket"); q->queue_t = q->sent_t = current_time; dlinkAdd(q, &q->lru, &lru_list); commConnectStart(q->tcp_socket, inet_ntoa(nameservers[ns].S.sin_addr), ntohs(nameservers[ns].S.sin_port), idnsSendTcpQuery, q ); }
void idnsInit(void) { static int init = 0; CBDATA_INIT_TYPE(idns_query); if (DnsSocket < 0) { int port; struct in_addr addr; if (Config.Addrs.udp_outgoing.s_addr != no_addr.s_addr) addr = Config.Addrs.udp_outgoing; else addr = Config.Addrs.udp_incoming; DnsSocket = comm_open(SOCK_DGRAM, IPPROTO_UDP, addr, 0, COMM_NONBLOCKING, "DNS Socket"); if (DnsSocket < 0) fatal("Could not create a DNS socket"); /* Ouch... we can't call functions using debug from a debug * statement. Doing so messes up the internal _db_level */ port = comm_local_port(DnsSocket); debug(78, 1) ("DNS Socket created at %s, port %d, FD %d\n", inet_ntoa(addr), port, DnsSocket); } assert(0 == nns); idnsParseNameservers(); #ifndef _SQUID_MSWIN_ if (0 == nns) idnsParseResolvConf(); #endif #ifdef _SQUID_WIN32_ if (0 == nns) idnsParseWIN32Registry(); #endif if (0 == nns) { debug(78, 1) ("Warning: Could not find any nameservers. Trying to use localhost\n"); #ifdef _SQUID_WIN32_ debug(78, 1) ("Please check your TCP-IP settings or /etc/resolv.conf file\n"); #else debug(78, 1) ("Please check your /etc/resolv.conf file\n"); #endif debug(78, 1) ("or use the 'dns_nameservers' option in squid.conf.\n"); idnsAddNameserver("127.0.0.1"); } if (!init) { memDataInit(MEM_IDNS_QUERY, "idns_query", sizeof(idns_query), 0); cachemgrRegister("idns", "Internal DNS Statistics", idnsStats, 0, 1); memset(RcodeMatrix, '\0', sizeof(RcodeMatrix)); idns_lookup_hash = hash_create((HASHCMP *) strcmp, 103, hash_string); init++; } }
/* * comm_socket() - open a socket * * This is a highly highly cut down version of squid's comm_open() which * for the most part emulates socket(), *EXCEPT* it fails if we're about * to run out of file descriptors. */ int comm_socket(int family, int sock_type, int proto, const char *note) { int fd; /* First, make sure we aren't going to run out of file descriptors */ if(number_fd >= MASTER_MAX) { errno = ENFILE; return -1; } /* * Next, we try to open the socket. We *should* drop the reserved FD * limit if/when we get an error, but we can deal with that later. * XXX !!! -- adrian */ fd = socket(family, sock_type, proto); comm_fd_hack(&fd); if(fd < 0) return -1; /* errno will be passed through, yay.. */ #if defined(IPV6) && defined(IPV6_V6ONLY) /* * Make sure we can take both IPv4 and IPv6 connections * on an AF_INET6 socket */ if(family == AF_INET6) { int off = 1; if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) == -1) { libcharybdis_log("comm_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s", fd, strerror(errno)); close(fd); return -1; } } #endif /* Set the socket non-blocking, and other wonderful bits */ if(!comm_set_nb(fd)) { libcharybdis_log("comm_open: Couldn't set FD %d non blocking: %s", fd, strerror(errno)); close(fd); return -1; } /* Next, update things in our fd tracking */ comm_open(fd, FD_SOCKET, note); return fd; }
/** * @brief Opens the communication dialogue with a pilot. * * @param pilot Pilot to communicate with. * @return 0 on success. */ int comm_openPilot( unsigned int pilot ) { const char *msg; unsigned int wid; /* Get the pilot. */ comm_pilot = pilot_get( pilot ); if (comm_pilot == NULL) return -1; /* Must not be disabled. */ if (pilot_isFlag(comm_pilot, PILOT_DISABLED)) { player_message("%s does not respond.", comm_pilot->name); return 0; } /* Check to see if pilot wants to communicate. */ msg = comm_getString( "comm_no" ); if (msg != NULL) { player_message( msg ); return 0; } /* Set up for the comm_get* functions. */ ai_setPilot( comm_pilot ); /* Create the generic comm window. */ wid = comm_open( ship_loadCommGFX( comm_pilot->ship ), comm_pilot->faction, pilot_isHostile(comm_pilot) ? -1 : pilot_isFriendly(comm_pilot) ? 1 : 0, pilot_isFlag(comm_pilot, PILOT_BRIBED), comm_pilot->name ); /* Add special buttons. */ window_addButton( wid, -20, 20 + BUTTON_HEIGHT + 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnGreet", "Greet", NULL ); if (!pilot_isFlag(comm_pilot, PILOT_BRIBED) && /* Not already bribed. */ ((faction_getPlayer( comm_pilot->faction ) < 0) || /* Hostile. */ pilot_isHostile(comm_pilot))) window_addButton( wid, -20, 20 + 2*BUTTON_HEIGHT + 40, BUTTON_WIDTH, BUTTON_HEIGHT, "btnBribe", "Bribe", comm_bribePilot ); else window_addButton( wid, -20, 20 + 2*BUTTON_HEIGHT + 40, BUTTON_WIDTH, BUTTON_HEIGHT, "btnRequest", "Refuel", comm_requestFuel ); /* Run hooks if needed. */ pilot_runHook( comm_pilot, PILOT_HOOK_HAIL ); return 0; }
void serverConnectionsOpen(int port) { theHttpConnection = comm_open(SOCK_STREAM, 0, port, COMM_NONBLOCKING); if (theHttpConnection < 0) { fprintf(stderr, "SDKtest_server: unable to open socket connection to listen for requests on port %d\n", port); exit(0); } BIGGEST_FD = theHttpConnection; comm_listen(theHttpConnection); fd_table[theHttpConnection].state = READABLE; fd_table[theHttpConnection].outbufsize = 0; }
/* * start a TCP connection to the peer host on port 113 */ void identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data) { IdentStateData *state; int fd; char key1[IDENT_KEY_SZ]; char key2[IDENT_KEY_SZ]; char key[IDENT_KEY_SZ]; snprintf(key1, IDENT_KEY_SZ, "%s:%d", inet_ntoa(me->sin_addr), ntohs(me->sin_port)); snprintf(key2, IDENT_KEY_SZ, "%s:%d", inet_ntoa(my_peer->sin_addr), ntohs(my_peer->sin_port)); snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2); if ((state = hash_lookup(ident_hash, key)) != NULL) { identClientAdd(state, callback, data); return; } fd = comm_open(SOCK_STREAM, IPPROTO_TCP, me->sin_addr, 0, COMM_NONBLOCKING, "ident"); if (fd == COMM_ERROR) { /* Failed to get a local socket */ callback(NULL, data); return; } CBDATA_INIT_TYPE(IdentStateData); state = cbdataAlloc(IdentStateData); state->hash.key = xstrdup(key); state->fd = fd; state->me = *me; state->my_peer = *my_peer; identClientAdd(state, callback, data); hash_join(ident_hash, &state->hash); comm_add_close_handler(fd, identClose, state); commSetTimeout(fd, Config.Timeout.ident, identTimeout, state); commConnectStart(fd, inet_ntoa(state->my_peer.sin_addr), IDENT_PORT, identConnectDone, state); }
void connect_server() { struct Client *client = make_client(NULL); struct Server *server = make_server(client); struct Module *protomod; char modes[MODEBUFLEN+1] = ""; int i, j = 0; protomod = find_module(Connect.protocol, NO); if(protomod == NULL) { ilog(L_CRIT, "Unable to connect to uplink, protocol module %s not found.", Connect.protocol); services_die("Connect error", NO); } ServerModeList = (struct ModeList *)modsym(protomod->handle, "ModeList"); for(i = 0; ServerModeList[i].letter != '\0'; i++) { modes[j++] = ServerModeList[i].letter; if(j > MODEBUFLEN) break; } modes[j] = '\0'; ilog(L_DEBUG, "Loaded server mode list %p %s %d", ServerModeList, modes, j); strlcpy(server->pass, Connect.password, sizeof(server->pass)); strlcpy(client->name, Connect.name, sizeof(client->name)); strlcpy(client->host, Connect.host, sizeof(client->host)); SetConnecting(client); client->from = client; dlinkAdd(client, &client->node, &global_client_list); if(comm_open(&server->fd, AF_INET, SOCK_STREAM, 0, NULL) < 0) { ilog(L_CRIT, "connect_server: Could not open socket"); exit(1); } comm_connect_tcp(&server->fd, Connect.host, Connect.port, NULL, 0, serv_connect_callback, client, AF_INET, CONNECTTIMEOUT); eventAdd("Server connection check", try_reconnect, NULL, 60); }
/** * @brief Opens a communication dialogue with a planet. * * @param planet Planet to communicate with. * @return 0 on success. */ int comm_openPlanet( Planet *planet ) { unsigned int wid; /* Must not be disabled. */ if (!planet_hasService(planet, PLANET_SERVICE_BASIC)) { player_message("%s does not respond.", planet->name); return 0; } comm_planet = planet; /* Create the generic comm window. */ wid = comm_open( gl_dupTexture( comm_planet->gfx_space ), comm_planet->faction, 0, 0, comm_planet->name ); /* Add special buttons. */ if (areEnemies(player->faction, planet->faction) && !planet->bribed) window_addButton( wid, -20, 20 + BUTTON_HEIGHT + 20, BUTTON_WIDTH, BUTTON_HEIGHT, "btnBribe", "Bribe", comm_bribePlanet ); return 0; }
static int inetport(struct Listener* listener) { struct irc_sockaddr lsin; int fd; int opt = 1; /* * At first, open a new socket */ fd = comm_open(DEF_FAM, SOCK_STREAM, 0, "Listener socket"); #ifdef IPV6 if (!IN6_ARE_ADDR_EQUAL((struct in6_addr *)&listener->addr, &in6addr_any)) { #else if (INADDR_ANY != listener->addr.sins.sin.s_addr) { #endif inetntop(DEF_FAM, &IN_ADDR(listener->addr), listener->vhost, HOSTLEN); listener->name = listener->vhost; } if (fd == -1) { report_error(L_ALL, "opening listener socket %s:%s", get_listener_name(listener), errno); return 0; } else if ((HARD_FDLIMIT - 10) < fd) { report_error(L_ALL, "no more connections left for listener %s:%s", get_listener_name(listener), errno); fd_close(fd); return 0; } /* * XXX - we don't want to do all this crap for a listener * set_sock_opts(listener); */ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(opt))) { report_error(L_ALL, "setting SO_REUSEADDR for listener %s:%s", get_listener_name(listener), errno); fd_close(fd); return 0; } /* * Bind a port to listen for new connections if port is non-null, * else assume it is already open and try get something from it. */ memset(&lsin, 0, sizeof(struct irc_sockaddr)); S_FAM(lsin) = DEF_FAM; copy_s_addr(S_ADDR(lsin), IN_ADDR(listener->addr)); S_PORT(lsin) = htons(listener->port); if (bind(fd, (struct sockaddr*) &SOCKADDR(lsin), sizeof(struct irc_sockaddr))) { report_error(L_ALL, "binding listener socket %s:%s", get_listener_name(listener), errno); fd_close(fd); return 0; } if (listen(fd, HYBRID_SOMAXCONN)) { report_error(L_ALL, "listen failed for %s:%s", get_listener_name(listener), errno); fd_close(fd); return 0; } /* * XXX - this should always work, performance will suck if it doesn't */ if (!set_non_blocking(fd)) report_error(L_ALL, NONB_ERROR_MSG, get_listener_name(listener), errno); listener->fd = fd; /* Listen completion events are READ events .. */ accept_connection(fd, listener); return 1; } static struct Listener* find_listener(int port, struct irc_inaddr *addr) { struct Listener* listener = NULL; struct Listener* last_closed = NULL; for (listener = ListenerPollList; listener; listener = listener->next) { if ( (port == listener->port) && (!memcmp(&PIN_ADDR(addr), &IN_ADDR(listener->addr), sizeof(struct irc_inaddr)))) { /* Try to return an open listener, otherwise reuse a closed one */ if (listener->fd == -1) last_closed = listener; else return listener; } } return last_closed; } /* * add_listener- create a new listener * port - the port number to listen on * vhost_ip - if non-null must contain a valid IP address string in * the format "255.255.255.255" */ void add_listener(int port, const char* vhost_ip) { struct Listener* listener; struct irc_inaddr vaddr; /* * if no port in conf line, don't bother */ if (port == 0) return; #ifdef IPV6 copy_s_addr(IN_ADDR(vaddr), &in6addr_any); #else copy_s_addr(IN_ADDR(vaddr), INADDR_ANY); #endif if (vhost_ip) { if(inetpton(DEF_FAM, vhost_ip, &IN_ADDR(vaddr)) <= 0) return; } if ((listener = find_listener(port, &vaddr))) { if (listener->fd > -1) return; } else { listener = make_listener(port, &vaddr); listener->next = ListenerPollList; ListenerPollList = listener; } listener->fd = -1; if (inetport(listener)) listener->active = 1; else close_listener(listener); } /* * close_listener - close a single listener */ void close_listener(struct Listener* listener) { assert(listener != NULL); if(listener == NULL) return; if (listener->fd >= 0) { fd_close(listener->fd); listener->fd = -1; } listener->active = 0; if (listener->ref_count) return; free_listener(listener); }
pid_t ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, void **hIpc) { unsigned long thread; struct ipc_params params; int opt; int optlen = sizeof(opt); DWORD ecode = 0; pid_t pid; struct sockaddr_in CS; struct sockaddr_in PS; int crfd = -1; int prfd = -1; int cwfd = -1; int pwfd = -1; socklen_t len; int x; requirePathnameExists(name, prog); if (rfd) *rfd = -1; if (wfd) *wfd = -1; if (hIpc) *hIpc = NULL; if (WIN32_OS_version != _WIN_OS_WINNT) { getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen); opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT); setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, sizeof(opt)); } if (type == IPC_TCP_SOCKET) { crfd = cwfd = comm_open(SOCK_STREAM, IPPROTO_TCP, local_addr, 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_STREAM, IPPROTO_TCP, /* protocol */ local_addr, 0, /* port */ 0, /* blocking */ name); } else if (type == IPC_UDP_SOCKET) { crfd = cwfd = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, name); } else if (type == IPC_FIFO) { debug(54, 0) ("ipcCreate: %s: use IPC_TCP_SOCKET instead of IP_FIFO on Windows\n", prog); assert(0); } else { assert(IPC_NONE); } debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd); debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd); debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd); debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd); if (WIN32_OS_version != _WIN_OS_WINNT) { getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen); opt = opt | SO_SYNCHRONOUS_NONALERT; setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen); } if (crfd < 0) { debug(54, 0) ("ipcCreate: Failed to create child FD.\n"); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (pwfd < 0) { debug(54, 0) ("ipcCreate: Failed to create server FD.\n"); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { len = sizeof(PS); memset(&PS, '\0', len); if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) { debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port)); len = sizeof(CS); memset(&CS, '\0', len); if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) { debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port)); } if (type == IPC_TCP_SOCKET) { if (listen(crfd, 1) < 0) { debug(54, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd); } /* flush or else we get dup data if unbuffered_logs is set */ logsFlush(); params.type = type; params.crfd = crfd; params.cwfd = cwfd; params.PS = PS; params.prog = prog; params.args = (char **) args; thread = _beginthreadex(NULL, 0, ipc_thread_1, ¶ms, 0, NULL); if (thread == 0) { debug(54, 1) ("ipcCreate: _beginthread: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) { CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } memset(hello_buf, '\0', HELLO_BUF_SZ); x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0); if (x < 0) { debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(54, 0) ("--> read: %s\n", xstrerror()); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } else if (strcmp(hello_buf, hello_string)) { debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(54, 0) ("--> read returned %d\n", x); debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } x = send(pwfd, ok_string, strlen(ok_string), 0); if (x < 0) { debug(54, 0) ("ipcCreate: PARENT: OK write test failed\n"); debug(54, 0) ("--> read: %s\n", xstrerror()); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } memset(hello_buf, '\0', HELLO_BUF_SZ); x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0); if (x < 0) { debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n"); debug(54, 0) ("--> read: %s\n", xstrerror()); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } else if (!strcmp(hello_buf, err_string)) { debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n"); debug(54, 0) ("--> read returned %d\n", x); debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } hello_buf[x] = '\0'; pid = atol(hello_buf); commSetTimeout(prfd, -1, NULL, NULL); commSetNonBlocking(prfd); commSetNonBlocking(pwfd); commSetCloseOnExec(prfd); commSetCloseOnExec(pwfd); if (rfd) *rfd = prfd; if (wfd) *wfd = pwfd; fd_table[prfd].flags.ipc = 1; fd_table[pwfd].flags.ipc = 1; fd_table[crfd].flags.ipc = 1; fd_table[cwfd].flags.ipc = 1; if (Config.sleep_after_fork) { /* XXX emulation of usleep() */ DWORD sl; sl = Config.sleep_after_fork / 1000; if (sl == 0) sl = 1; Sleep(sl); } if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) { if (hIpc) *hIpc = (HANDLE) thread; return pid; } else { CloseHandle((HANDLE) thread); return ipcCloseAllFD(prfd, pwfd, -1, -1); } }
static unsigned int __stdcall ipc_thread_1(void *in_params) { int t1, t2, t3, retval = -1; int p2c[2] = {-1, -1}; int c2p[2] = {-1, -1}; HANDLE hProcess = NULL, thread = NULL; pid_t pid = -1; struct thread_params thread_params; int x, tmp_s, fd = -1; char *str; #if HAVE_PUTENV char *env_str = NULL; #endif STARTUPINFO si; PROCESS_INFORMATION pi; long F; int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1; char *prog = NULL, *buf1 = NULL; struct sockaddr_in CS_ipc, PS_ipc; struct ipc_params *params = (struct ipc_params *) in_params; int type = params->type; int crfd = params->crfd; int cwfd = params->cwfd; char **args = params->args; struct sockaddr_in PS = params->PS; buf1 = xcalloc(1, 8192); strcpy(buf1, params->prog); prog = strtok(buf1, w_space); if ((str = strrchr(prog, '/'))) prog = ++str; if ((str = strrchr(prog, '\\'))) prog = ++str; prog = xstrdup(prog); if (type == IPC_TCP_SOCKET) { debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd); if ((fd = accept(crfd, NULL, NULL)) < 0) { debug(54, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror()); goto cleanup; } debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd); comm_close(crfd); snprintf(buf1, 8191, "%s CHILD socket", prog); fd_open(fd, FD_SOCKET, buf1); fd_table[fd].flags.ipc = 1; cwfd = crfd = fd; } else if (type == IPC_UDP_SOCKET) { if (comm_connect_addr(crfd, &PS) == COMM_ERROR) goto cleanup; } x = send(cwfd, hello_string, strlen(hello_string) + 1, 0); if (x < 0) { debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror()); debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n"); goto cleanup; } #if HAVE_PUTENV env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1); snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions); putenv(env_str); #endif memset(buf1, '\0', sizeof(buf1)); x = recv(crfd, buf1, 8191, 0); if (x < 0) { debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n"); debug(54, 0) ("--> read: %s\n", xstrerror()); goto cleanup; } else if (strcmp(buf1, ok_string)) { debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n"); debug(54, 0) ("--> read returned %d\n", x); debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); goto cleanup; } /* assign file descriptors to child process */ if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) { debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror()); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) { debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror()); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } if (type == IPC_UDP_SOCKET) { snprintf(buf1, 8192, "%s(%ld) <-> ipc CHILD socket", prog, -1L); crfd_ipc = cwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1); if (crfd_ipc < 0) { debug(54, 0) ("ipcCreate: CHILD: Failed to create child FD for %s.\n", prog); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } snprintf(buf1, 8192, "%s(%ld) <-> ipc PARENT socket", prog, -1L); prfd_ipc = pwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1); if (pwfd_ipc < 0) { debug(54, 0) ("ipcCreate: CHILD: Failed to create server FD for %s.\n", prog); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } tmp_s = sizeof(PS_ipc); memset(&PS_ipc, '\0', tmp_s); if (getsockname(pwfd_ipc, (struct sockaddr *) &PS_ipc, &tmp_s) < 0) { debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", pwfd_ipc, inet_ntoa(PS_ipc.sin_addr), ntohs(PS_ipc.sin_port)); tmp_s = sizeof(CS_ipc); memset(&CS_ipc, '\0', tmp_s); if (getsockname(crfd_ipc, (struct sockaddr *) &CS_ipc, &tmp_s) < 0) { debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", crfd_ipc, inet_ntoa(CS_ipc.sin_addr), ntohs(CS_ipc.sin_port)); if (comm_connect_addr(pwfd_ipc, &CS_ipc) == COMM_ERROR) { ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } fd = crfd; if (comm_connect_addr(crfd_ipc, &PS_ipc) == COMM_ERROR) { ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } } /* IPC_UDP_SOCKET */ t1 = dup(0); t2 = dup(1); t3 = dup(2); dup2(c2p[0], 0); dup2(p2c[1], 1); dup2(fileno(debug_log), 2); close(c2p[0]); close(p2c[1]); commUnsetNonBlocking(fd); memset(&si, 0, sizeof(STARTUPINFO)); si.cb = sizeof(STARTUPINFO); si.hStdInput = (HANDLE) _get_osfhandle(0); si.hStdOutput = (HANDLE) _get_osfhandle(1); si.hStdError = (HANDLE) _get_osfhandle(2); si.dwFlags = STARTF_USESTDHANDLES; /* Make sure all other valid handles are not inerithable */ for (x = 3; x < Squid_MaxFD; x++) { if ((F = _get_osfhandle(x)) == -1) continue; SetHandleInformation((HANDLE) F, HANDLE_FLAG_INHERIT, 0); } *buf1 = '\0'; strcpy(buf1 + 4096, params->prog); str = strtok(buf1 + 4096, w_space); do { strcat(buf1, str); strcat(buf1, " "); } while ((str = strtok(NULL, w_space))); x = 1; while (args[x]) { strcat(buf1, args[x++]); strcat(buf1, " "); } if (CreateProcess(buf1 + 4096, buf1, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { pid = pi.dwProcessId; hProcess = pi.hProcess; } else { pid = -1; WIN32_maperror(GetLastError()); x = errno; } dup2(t1, 0); dup2(t2, 1); dup2(t3, 2); close(t1); close(t2); close(t3); if (pid == -1) { errno = x; debug(54, 0) ("ipcCreate: CHILD: %s: %s\n", params->prog, xstrerror()); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } if (type == IPC_UDP_SOCKET) { WSAPROTOCOL_INFO wpi; memset(&wpi, 0, sizeof(wpi)); if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc, pid, &wpi)) { debug(54, 0) ("ipcCreate: CHILD: WSADuplicateSocket: %s\n", xstrerror()); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } x = write(c2p[1], (const char *) &wpi, sizeof(wpi)); if (x < sizeof(wpi)) { debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1], xstrerror()); debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", prog); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } x = read(p2c[0], buf1, 8192); if (x < 0) { debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0], xstrerror()); debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", prog); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } else if (strncmp(buf1, ok_string, strlen(ok_string))) { debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", prog); debug(54, 0) ("--> read returned %d\n", x); buf1[x] = '\0'; debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1)); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } x = write(c2p[1], (const char *) &PS_ipc, sizeof(PS_ipc)); if (x < sizeof(PS_ipc)) { debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1], xstrerror()); debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", prog); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } x = read(p2c[0], buf1, 8192); if (x < 0) { debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0], xstrerror()); debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", prog); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } else if (strncmp(buf1, ok_string, strlen(ok_string))) { debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", prog); debug(54, 0) ("--> read returned %d\n", x); buf1[x] = '\0'; debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1)); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } x = send(pwfd_ipc, ok_string, strlen(ok_string), 0); x = recv(prfd_ipc, buf1 + 200, 8191 - 200, 0); assert((size_t) x == strlen(ok_string) && !strncmp(ok_string, buf1 + 200, strlen(ok_string))); } /* IPC_UDP_SOCKET */ snprintf(buf1, 8191, "%s(%ld) CHILD socket", prog, (long int) pid); fd_note(fd, buf1); if (prfd_ipc != -1) { snprintf(buf1, 8191, "%s(%ld) <-> ipc CHILD socket", prog, (long int) pid); fd_note(crfd_ipc, buf1); snprintf(buf1, 8191, "%s(%ld) <-> ipc PARENT socket", prog, (long int) pid); fd_note(prfd_ipc, buf1); } /* else { IPC_TCP_SOCKET */ /* commSetNoLinger(fd); */ /* } */ thread_params.prog = prog; thread_params.send_fd = cwfd; thread_params.pid = pid; if ((thread_params.type = type) == IPC_TCP_SOCKET) thread_params.rfd = p2c[0]; else thread_params.rfd = prfd_ipc; thread = (HANDLE) _beginthreadex(NULL, 0, ipc_thread_2, &thread_params, 0, NULL); if (!thread) { debug(54, 0) ("ipcCreate: CHILD: _beginthreadex: %s\n", xstrerror()); ipcSend(cwfd, err_string, strlen(err_string)); goto cleanup; } snprintf(buf1, 8191, "%ld\n", (long int) pid); if (-1 == ipcSend(cwfd, buf1, strlen(buf1))) goto cleanup; debug(54, 2) ("ipc(%s,%ld): started successfully\n", prog, (long int) pid); /* cycle */ for (;;) { x = recv(crfd, buf1, 8192, 0); if (x <= 0) { debug(54, 3) ("ipc(%s,%d): %d bytes received from parent. Exiting...\n", prog, pid, x); break; } buf1[x] = '\0'; if (type == IPC_UDP_SOCKET && !strcmp(buf1, shutdown_string)) { debug(54, 3) ("ipc(%s,%d): request for shutdown received from parent. Exiting...\n", prog, pid); TerminateProcess(hProcess, 0); break; } debug(54, 5) ("ipc(%s,%d): received from parent: %s\n", prog, pid, rfc1738_escape_unescaped(buf1)); if (type == IPC_TCP_SOCKET) x = write(c2p[1], buf1, x); else x = send(pwfd_ipc, buf1, x, 0); if (x <= 0) { debug(54, 3) ("ipc(%s,%d): %d bytes written to %s. Exiting...\n", prog, pid, x, prog); break; } } retval = 0; cleanup: if (c2p[1] != -1) close(c2p[1]); if (fd_table[crfd].flags.open) ipcCloseAllFD(-1, -1, crfd, cwfd); if (prfd_ipc != -1) { send(crfd_ipc, shutdown_string, strlen(shutdown_string), 0); shutdown(crfd_ipc, SD_BOTH); shutdown(prfd_ipc, SD_BOTH); } ipcCloseAllFD(prfd_ipc, pwfd_ipc, crfd_ipc, cwfd_ipc); if (hProcess && WAIT_OBJECT_0 != WaitForSingleObject(hProcess, type == IPC_UDP_SOCKET ? 12000 : 5000)) { getCurrentTime(); debug(54, 0) ("ipc(%s,%d): WARNING: %s didn't exit in %d seconds.\n", prog, pid, prog, type == IPC_UDP_SOCKET ? 12 : 5); } if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) { getCurrentTime(); debug(54, 0) ("ipc(%s,%d): WARNING: ipc_thread_2 didn't exit in 3 seconds.\n", prog, pid); } getCurrentTime(); if (!retval) debug(54, 2) ("ipc(%s,%d): normal exit\n", prog, pid); if (buf1) xfree(buf1); if (prog) xfree(prog); if (env_str) xfree(env_str); if (thread) CloseHandle(thread); if (hProcess) CloseHandle(hProcess); if (p2c[0] != -1) close(p2c[0]); return retval; }
void sslStart(int fd, const char *url, request_t * request, size_t * size_ptr) { /* Create state structure. */ SslStateData *sslState = NULL; int sock; ErrorState *err = NULL; debug(26, 3) ("sslStart: '%s %s'\n", RequestMethodStr[request->method], url); Counter.server.all.requests++; Counter.server.other.requests++; /* Create socket. */ sock = comm_open(SOCK_STREAM, 0, Config.Addrs.tcp_outgoing, 0, COMM_NONBLOCKING, url); if (sock == COMM_ERROR) { debug(26, 4) ("sslStart: Failed because we're out of sockets.\n"); err = errorCon(ERR_SOCKET_FAILURE, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; err->request = requestLink(request); errorSend(fd, err); return; } sslState = xcalloc(1, sizeof(SslStateData)); cbdataAdd(sslState, cbdataXfree, 0); #if DELAY_POOLS sslState->delay_id = delayClient(request); delayRegisterDelayIdPtr(&sslState->delay_id); #endif sslState->url = xstrdup(url); sslState->request = requestLink(request); sslState->size_ptr = size_ptr; sslState->client.fd = fd; sslState->server.fd = sock; sslState->server.buf = xmalloc(SQUID_TCP_SO_RCVBUF); sslState->client.buf = xmalloc(SQUID_TCP_SO_RCVBUF); comm_add_close_handler(sslState->server.fd, sslServerClosed, sslState); comm_add_close_handler(sslState->client.fd, sslClientClosed, sslState); commSetTimeout(sslState->client.fd, Config.Timeout.lifetime, sslTimeout, sslState); commSetTimeout(sslState->server.fd, Config.Timeout.connect, sslTimeout, sslState); peerSelect(request, NULL, sslPeerSelectComplete, sslState); /* * Disable the client read handler until peer selection is complete * Take control away from client_side.c. */ commSetSelect(sslState->client.fd, COMM_SELECT_READ, NULL, NULL, 0); }
void icpConnectionsOpen(void) { u_short port; struct in_addr addr; struct sockaddr_in xaddr; int x; socklen_t len; wordlist *s; if (Config2.Accel.on && !Config.onoff.accel_with_proxy) return; if ((port = Config.Port.icp) <= 0) return; enter_suid(); theInIcpConnection = comm_open(SOCK_DGRAM, 0, Config.Addrs.udp_incoming, port, COMM_NONBLOCKING, "ICP Socket"); leave_suid(); if (theInIcpConnection < 0) fatal("Cannot open ICP Port"); commSetSelect(theInIcpConnection, COMM_SELECT_READ, icpHandleUdp, NULL, 0); for (s = Config.mcast_group_list; s; s = s->next) ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL); debug(12, 1) ("Accepting ICP messages at %s, port %d, FD %d.\n", inet_ntoa(Config.Addrs.udp_incoming), (int) port, theInIcpConnection); if ((addr = Config.Addrs.udp_outgoing).s_addr != no_addr.s_addr) { enter_suid(); theOutIcpConnection = comm_open(SOCK_DGRAM, 0, addr, port, COMM_NONBLOCKING, "ICP Port"); leave_suid(); if (theOutIcpConnection < 0) fatal("Cannot open Outgoing ICP Port"); commSetSelect(theOutIcpConnection, COMM_SELECT_READ, icpHandleUdp, NULL, 0); debug(12, 1) ("Outgoing ICP messages on port %d, FD %d.\n", (int) port, theOutIcpConnection); fd_note(theOutIcpConnection, "Outgoing ICP socket"); fd_note(theInIcpConnection, "Incoming ICP socket"); } else { theOutIcpConnection = theInIcpConnection; } memset(&theOutICPAddr, '\0', sizeof(struct in_addr)); len = sizeof(struct sockaddr_in); memset(&xaddr, '\0', len); x = getsockname(theOutIcpConnection, (struct sockaddr *) &xaddr, &len); if (x < 0) debug(50, 1) ("theOutIcpConnection FD %d: getsockname: %s\n", theOutIcpConnection, xstrerror()); else theOutICPAddr = xaddr.sin_addr; }
int ipcCreate(int type, const char *prog, char *const args[], const char *name, int *rfd, int *wfd) { pid_t pid; struct sockaddr_in CS; struct sockaddr_in PS; int crfd = -1; int prfd = -1; int cwfd = -1; int pwfd = -1; int fd; int t1, t2, t3; socklen_t len; int tmp_s; #if HAVE_PUTENV char *env_str; #endif int x; #if HAVE_POLL && defined(_SQUID_OSF_) assert(type != IPC_FIFO); #endif if (rfd) *rfd = -1; if (wfd) *wfd = -1; if (type == IPC_TCP_SOCKET) { crfd = cwfd = comm_open(SOCK_STREAM, 0, local_addr, 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_STREAM, 0, /* protocol */ local_addr, 0, /* port */ 0, /* blocking */ name); } else if (type == IPC_UDP_SOCKET) { crfd = cwfd = comm_open(SOCK_DGRAM, 0, local_addr, 0, COMM_NOCLOEXEC, name); prfd = pwfd = comm_open(SOCK_DGRAM, 0, local_addr, 0, 0, name); } else if (type == IPC_FIFO) { int p2c[2]; int c2p[2]; if (pipe(p2c) < 0) { debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror()); return -1; } if (pipe(c2p) < 0) { debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror()); return -1; } fd_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read"); fd_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write"); fd_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read"); fd_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write"); } else { assert(IPC_NONE); } debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd); debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd); debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd); debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd); if (crfd < 0) { debug(54, 0) ("ipcCreate: Failed to create child FD.\n"); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (pwfd < 0) { debug(54, 0) ("ipcCreate: Failed to create server FD.\n"); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { len = sizeof(PS); memset(&PS, '\0', len); if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) { debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port)); len = sizeof(CS); memset(&CS, '\0', len); if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) { debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port)); } if (type == IPC_TCP_SOCKET) { if (listen(crfd, 1) < 0) { debug(50, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd); } /* flush or else we get dup data if unbuffered_logs is set */ logsFlush(); if ((pid = fork()) < 0) { debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (pid > 0) { /* parent */ /* close shared socket with child */ comm_close(crfd); if (cwfd != crfd) comm_close(cwfd); cwfd = crfd = -1; if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } memset(hello_buf, '\0', HELLO_BUF_SZ); if (type == IPC_UDP_SOCKET) x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0); else x = read(prfd, hello_buf, HELLO_BUF_SZ - 1); if (x < 0) { debug(50, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(50, 0) ("--> read: %s\n", xstrerror()); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } else if (strcmp(hello_buf, hello_string)) { debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(54, 0) ("--> read returned %d\n", x); debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } commSetTimeout(prfd, -1, NULL, NULL); commSetNonBlocking(prfd); commSetNonBlocking(pwfd); if (rfd) *rfd = prfd; if (wfd) *wfd = pwfd; fd_table[prfd].flags.ipc = 1; fd_table[pwfd].flags.ipc = 1; return pwfd; } /* child */ no_suid(); /* give up extra priviliges */ /* close shared socket with parent */ close(prfd); if (pwfd != prfd) close(pwfd); pwfd = prfd = -1; if (type == IPC_TCP_SOCKET) { debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd); if ((fd = accept(crfd, NULL, NULL)) < 0) { debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror()); _exit(1); } debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd); close(crfd); cwfd = crfd = fd; } else if (type == IPC_UDP_SOCKET) { if (comm_connect_addr(crfd, &PS) == COMM_ERROR) return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } if (type == IPC_UDP_SOCKET) { x = send(cwfd, hello_string, strlen(hello_string), 0); if (x < 0) { debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror()); debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n"); _exit(1); } } else { if (write(cwfd, hello_string, strlen(hello_string)) < 0) { debug(50, 0) ("write FD %d: %s\n", cwfd, xstrerror()); debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n"); _exit(1); } } #if HAVE_PUTENV env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1); snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions); putenv(env_str); #endif /* * This double-dup stuff avoids problems when one of * crfd, cwfd, or debug_log are in the rage 0-2. */ do { x = open(_PATH_DEVNULL, 0, 0444); if (x > -1) commSetCloseOnExec(x); } while (x < 3); t1 = dup(crfd); t2 = dup(cwfd); t3 = dup(fileno(debug_log)); assert(t1 > 2 && t2 > 2 && t3 > 2); close(crfd); close(cwfd); close(fileno(debug_log)); dup2(t1, 0); dup2(t2, 1); dup2(t3, 2); close(t1); close(t2); close(t3); #if HAVE_SETSID setsid(); #endif execvp(prog, args); debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror()); _exit(1); return 0; }
/* * This code expects the path to be syslog:<priority> */ int logfile_mod_udp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag) { l_udp_t *ll; struct sockaddr_in addr; char *strAddr; lf->f_close = logfile_mod_udp_close; lf->f_linewrite = logfile_mod_udp_writeline; lf->f_linestart = logfile_mod_udp_linestart; lf->f_lineend = logfile_mod_udp_lineend; lf->f_flush = logfile_mod_udp_flush; lf->f_rotate = logfile_mod_udp_rotate; ll = xcalloc(1, sizeof(*ll)); lf->data = ll; if (strncmp(path, "//", 2) == 0) { path += 2; } strAddr = xstrdup(path); if (!parse_sockaddr(strAddr, &addr)) { if (lf->flags.fatal) { fatalf("Invalid UDP logging address '%s'\n", lf->path); } else { debug(50, 1) ("Invalid UDP logging address '%s'\n", lf->path); safe_free(strAddr); return FALSE; } } safe_free(strAddr); ll->fd = comm_open(SOCK_DGRAM, IPPROTO_UDP, no_addr, 0, COMM_NONBLOCKING, "UDP log socket"); if (ll->fd < 0) { if (lf->flags.fatal) { fatalf("Unable to open UDP socket for logging\n"); } else { debug(50, 1) ("Unable to open UDP socket for logging\n"); return FALSE; } } if (comm_connect_addr(ll->fd, &addr)) { if (lf->flags.fatal) { fatalf("Unable to connect to %s for UDP log: %s\n", lf->path, xstrerror()); } else { debug(50, 1) ("Unable to connect to %s for UDP log: %s\n", lf->path, xstrerror()); return FALSE; } } if (ll->fd == -1) { if (ENOENT == errno && fatal_flag) { fatalf("Cannot open '%s' because\n" "\tthe parent directory does not exist.\n" "\tPlease create the directory.\n", path); } else if (EACCES == errno && fatal_flag) { fatalf("Cannot open '%s' for writing.\n" "\tThe parent directory must be writeable by the\n" "\tuser '%s', which is the cache_effective_user\n" "\tset in squid.conf.", path, Config.effectiveUser); } else { debug(50, 1) ("logfileOpen (stdio): %s: %s\n", path, xstrerror()); return 0; } } /* Force buffer size to something roughly fitting inside an MTU */ /* * XXX note the receive side needs to receive the whole packet at once; * applications like netcat have a small default receive buffer and will * truncate! */ bufsz = 1400; if (bufsz > 0) { ll->buf = (char *) xmalloc(bufsz); ll->bufsz = bufsz; } return 1; }