void connect_function(GtkWidget *widget,gpointer data) { if(!connect_bool && connection_status() == 0) { if (connect_to_client() == 0) { gtk_button_set_label(GTK_BUTTON(widget), "Connect"); gtk_label_set_text(GTK_LABEL(helpLabel), "client offline"); g_timeout_add_seconds(4, reset_help_label, (gpointer) helpLabel); return; } else { sendMessage("100:start"); gtk_button_set_label(GTK_BUTTON(widget), "Disconnect"); connect_bool = 1; } } else { connect_bool = 0; sendMessage("100:stop"); gtk_button_set_label(GTK_BUTTON(buttonDevice1), "Device1"); gtk_button_set_label(GTK_BUTTON(buttonDevice2), "Device2"); gtk_button_set_label(GTK_BUTTON(buttonDevice3), "Device3"); gtk_button_set_label(GTK_BUTTON(buttonDevice4), "Device4"); stop_audio_from_mic(); disconnect(); gtk_button_set_label(GTK_BUTTON(widget), "Connect"); } }
gboolean stop_device(GtkWidget *widget,gpointer data) { if (connection_status()==0) { return FALSE; } char* label_string = gtk_button_get_label(widget); if (!strcmp(label_string,"Device1-On") && device1_on){ device1_on = 0; sendMessage("1:stop"); g_print ("turning off device1\n"); gtk_button_set_label(GTK_BUTTON(widget), "Device1"); } else if (!strcmp(label_string,"Device2-On") && device2_on){ device2_on = 0; sendMessage("2:stop"); g_print ("turning off device2\n"); gtk_button_set_label(GTK_BUTTON(widget), "Device2"); } else if (!strcmp(label_string,"Device3-On") && device3_on) { device3_on = 0; sendMessage("3:stop"); g_print ("turning off device3\n"); gtk_button_set_label(GTK_BUTTON(widget), "Device3"); } else if (!strcmp(label_string,"Device4-On") && device4_on) { device4_on = 0; sendMessage("4:stop"); g_print ("turning off device4\n"); gtk_button_set_label(GTK_BUTTON(widget), "Device4"); } return FALSE; }
gboolean check_network_connectivity(gpointer connectButton){ if (connection_status()){ gtk_button_set_label(GTK_BUTTON(connectButton), "Disconnect"); } else { gtk_button_set_label(GTK_BUTTON(connectButton), "Connect"); } return TRUE; }
void play_function(GtkWidget *widget,gpointer data) { if (connection_status() == 0){ gtk_label_set_text(GTK_LABEL(helpLabel), "please connect"); g_timeout_add_seconds (4, reset_help_label, (gpointer) helpLabel); } else { play_audio_from_mic(); } }
void sig_child_handler() { int wstat; int i; while ((i =wait_nohang(&wstat)) > 0) { if (phccmax) ipsvd_phcc_rem(i); if (cnum) cnum--; if (verbose) { bufnum[fmt_ulong(bufnum, i)] =0; out(INFO); out("end "); out(bufnum); out(" exit "); bufnum[fmt_ulong(bufnum, (unsigned long)wait_exitcode(wstat))] =0; out(bufnum); flush("\n"); } } if (verbose) connection_status(); }
static void sig_child_handler(int sig ATTRIBUTE_UNUSED) { int wstat; int pid; while ((pid = wait_any_nohang(&wstat)) > 0) { if (max_per_host) ipsvd_perhost_remove(pid); if (cnum) cnum--; if (verbose) print_waitstat(pid, wstat); } if (verbose) connection_status(); }
int manage_connect (struct tcp_socket *sk) { int sd = 0; int cnt_status; struct sockaddr_in addr4; struct sockaddr_in6 addr6; struct socks_hdr *hdr; struct msgbuff *msg; u_int8_t errcode; socklen_t addrlen; size_t iplen; size_t bufflen; errno = 0; if ( sk->kind == SOCKET_PASV && sk->state == WAITING_CONNECTION) { if ( sk->family == AF_INET ) { sd = accept_tcp_ipv4(sk->socket, &addr4); iplen = 4; } else if ( sk->family == AF_INET6) { sd = accept_tcp_ipv6(sk->socket, &addr6); iplen = 16; } else { return -1; } if ( sd == -1 ) { if (errno == EINTR) return 0; else errcode = SFAILURE; } else { close(sk->socket); sk->socket = sd; errcode = SUCCESS; } } else if ( sk->kind == SOCKET_PEER && sk->state == CONNECTING ) { if (connection_status(sk->socket, &cnt_status) == -1) { errcode = SFAILURE; } if (cnt_status == 0) { errcode = SUCCESS; if (sk->family == AF_INET) { iplen = 4; addrlen = sizeof(struct sockaddr_in); if ( getsockname(sk->socket, (struct sockaddr *)&addr4, &addrlen) == -1 ) { errcode = SFAILURE; } } else if (sk->family == AF_INET6) { iplen = 16; addrlen = sizeof(struct sockaddr_in); if ( getsockname(sk->socket, (struct sockaddr *)&addr6, &addrlen) == -1 ) { errcode = SFAILURE; } } else return -1; } else { if (cnt_status == EALREADY || cnt_status == EINPROGRESS ) return 0; else { if (cnt_status == ENETUNREACH) errcode = NUNREACHE; else if ( cnt_status == ETIMEDOUT) errcode = HUNREACHE; else errcode = SFAILURE; } } } else { return -1; } bufflen = SZS5HDR + iplen + 2; msg = alloc_msg_buffer(bufflen); if (msg == NULL) return -1; hdr = (struct socks_hdr *) msg->buffer; hdr->ver = 0x05; hdr->kind.rep = errcode; hdr->rsv = 0x00; hdr->atyp = (sk->family == AF_INET) ? IPV4ADDR : IPV6ADDR; if ( errcode == 0x00 ) { memcpy(&((u_int8_t *)(msg->buffer))[SZS5HDR], (sk->family == AF_INET) ? &(addr4.sin_addr.s_addr) : &(addr6.sin6_addr.s6_addr), iplen); memcpy(&((u_int8_t *)(msg->buffer))[SZS5HDR+iplen], (sk->family == AF_INET) ? &(addr4.sin_port) : &(addr6.sin6_port), 2); sk->peer->state = PENDING_SND_REPLY; sk->state = PIPELINE; } else { sk->peer->state = WAITING_CLOSE; sk->state = CLOSE; msg->nrbytes = 4; } enqueue_pending_msg(&(sk->peer->msgq), msg); return 0; }
void button_function(GtkWidget *widget,gpointer data) { char* label_string = gtk_button_get_label(widget); if (connection_status() == 0){ gtk_label_set_text(GTK_LABEL(helpLabel), "please connect"); g_timeout_add_seconds (4, reset_help_label, (gpointer) helpLabel); return; } if (!strcmp(label_string,"Device1") || !strcmp(label_string,"Device1-On")){ int value = gtk_spin_button_get_value_as_int(spinButtonDevice1); if (value==0) { gtk_label_set_text(GTK_LABEL(helpLabel), "set time"); g_timeout_add_seconds (4, reset_help_label, (gpointer) helpLabel); } else if (!device1_on){ sendMessage("1:start"); device1_on = 1; gtk_button_set_label(GTK_BUTTON(widget), "Device1-On"); g_print ("turning on device1 for %d seconds \n",value); g_timeout_add_seconds (value, stop_device, (gpointer) buttonDevice1); } else if (device1_on) { sendMessage("1:stop"); device1_on = 0; gtk_button_set_label(GTK_BUTTON(widget), "Device1"); g_print ("turning off device1\n"); } } else if (!strcmp(label_string,"Device2") || !strcmp(label_string,"Device2-On")){ int value = gtk_spin_button_get_value_as_int(spinButtonDevice2); if (value==0) { gtk_label_set_text(GTK_LABEL(helpLabel), "set time"); g_timeout_add_seconds (4, reset_help_label, (gpointer) helpLabel); } else if (!device2_on){ sendMessage("2:start"); device2_on = 1; g_print ("turning on device2 for %d seconds \n",value); gtk_button_set_label(GTK_BUTTON(widget), "Device2-On"); g_timeout_add_seconds (value, stop_device, (gpointer) buttonDevice2); } else if (device2_on) { sendMessage("2:stop"); device2_on = 0; gtk_button_set_label(GTK_BUTTON(widget), "Device2"); g_print ("turning off device2\n"); } } else if (!strcmp(label_string,"Device3") || !strcmp(label_string,"Device3-On")) { int value = gtk_spin_button_get_value_as_int(spinButtonDevice3); if (value==0) { gtk_label_set_text(GTK_LABEL(helpLabel), "set time"); g_timeout_add_seconds (4, reset_help_label, (gpointer) helpLabel); } else if (!device3_on){ sendMessage("3:start"); device3_on = 1; gtk_button_set_label(GTK_BUTTON(widget), "Device3-On"); g_print ("turning on device3 for %d seconds \n",value); g_timeout_add_seconds (value, stop_device, (gpointer) buttonDevice3); } else if (device3_on) { sendMessage("3:stop"); device3_on = 0; gtk_button_set_label(GTK_BUTTON(widget), "Device3"); g_print ("turning off device3\n"); } } else if (!strcmp(label_string,"Device4") || !strcmp(label_string,"Device4-On")) { int value = gtk_spin_button_get_value_as_int(spinButtonDevice4); if (value==0) { gtk_label_set_text(GTK_LABEL(helpLabel), "set time"); g_timeout_add_seconds (4, reset_help_label, (gpointer) helpLabel); } else if (!device4_on){ sendMessage("4:start"); device4_on = 1; gtk_button_set_label(GTK_BUTTON(widget), "Device4-On"); g_print ("turning on device4 for %d seconds \n",value); g_timeout_add_seconds (value, stop_device, (gpointer) buttonDevice4); } else if (device4_on) { sendMessage("4:stop"); device4_on = 0; gtk_button_set_label(GTK_BUTTON(widget), "Device4"); g_print ("turning off device4\n"); } } }
void edit_interface_rep::set_left_footer () { tree s= concat (); double base_sz= get_env_int (FONT_BASE_SIZE); double sz= get_env_double (FONT_SIZE); /* tree the_style= get_style (); for (int i=0; i<arity (the_style); i++) s << " " << as_string (the_style[i]); */ string mode= get_env_string (MODE); string lan = get_env_string (MODE_LANGUAGE (mode)); if (mode == "prog") s << "program"; else if (as_string (get_init_value (MODE_LANGUAGE (mode))) != lan) s << " " << lan; else s << " " << mode; if ((mode == "text") || (mode == "src")) { s << " " << get_env_string (FONT); append_left_footer (s, FONT_FAMILY); s << " " << as_string ((int) ((base_sz+0.5)*sz)); append_left_footer (s, FONT_SERIES); append_left_footer (s, FONT_SHAPE); } else if (mode == "math") { s << " " << get_env_string (MATH_FONT); append_left_footer (s, MATH_FONT_FAMILY); s << " " << as_string ((int) ((base_sz+0.5)*sz)); append_left_footer (s, MATH_FONT_SERIES); append_left_footer (s, MATH_FONT_SHAPE); } else if (mode == "prog") { string session_name= get_env_string (PROG_SESSION); if (session_name != "default") s << "-" << session_name; s << " " << get_env_string (PROG_FONT); append_left_footer (s, PROG_FONT_FAMILY); s << " " << as_string ((int) ((base_sz+0.5)*sz)); append_left_footer (s, PROG_FONT_SERIES); append_left_footer (s, PROG_FONT_SHAPE); } string r= get_env_string (COLOR); if (r != "black") s << " " << r; if (N(s) > 0 && s[0] == " ") s= s (1, N(s)); if (inside ("session") && (lan != "scheme")) { string lan = get_env_string (PROG_LANGUAGE); string session= get_env_string (PROG_SESSION); switch (connection_status (lan, session)) { case CONNECTION_DEAD: s= s << " [dead]"; break; case CONNECTION_DYING: case WAITING_FOR_OUTPUT: s= s << " [busy]"; break; case WAITING_FOR_INPUT: s= s << " [idle]"; break; } } s= as_tree (call ("footer-hook", object (s))); set_left_footer (s); }
int main(int argc, char **argv) { int opt; char *user =0; char *host; unsigned long port; int pid; int s; int conn; int delim; progname =*argv; phccmax =0; #ifdef SSLSVD while ((opt =getopt(argc, (const char **)argv, "c:C:i:x:u:l:Eb:hpt:vVU:/:Z:K:")) != opteof) { #else while ((opt =getopt(argc, (const char **)argv, "c:C:i:x:u:l:Eb:hpt:vV")) != opteof) { #endif switch(opt) { case 'c': scan_ulong(optarg, &cmax); if (cmax < 1) usage(); break; case 'C': delim =scan_ulong(optarg, &phccmax); if (phccmax < 1) usage(); if (optarg[delim] == ':') { if (ipsvd_fmt_msg(&msg, optarg +delim +1) == -1) die_nomem(); if (! stralloc_0(&msg)) die_nomem(); phccmsg =msg.s; } break; case 'i': if (instructs) usage(); instructs =optarg; break; case 'x': if (instructs) usage(); instructs =optarg; iscdb =1; break; case 'u': user =(char*)optarg; break; case 'l': if (! stralloc_copys(&local_hostname, optarg)) die_nomem(); if (! stralloc_0(&local_hostname)) die_nomem(); break; case 'E': ucspi =0; break; case 'b': scan_ulong(optarg, &backlog); break; case 'h': lookuphost =1; break; case 'p': lookuphost =1; paranoid =1; break; case 't': scan_ulong(optarg, &timeout); break; case 'v': ++verbose; break; #ifdef SSLSVD case 'U': ssluser =(char*)optarg; break; case '/': root =(char*)optarg; break; case 'Z': cert =(char*)optarg; break; case 'K': key =(char*)optarg; break; #endif case 'V': strerr_warn1(VERSION, 0); case '?': usage(); } } argv +=optind; if (! argv || ! *argv) usage(); host =*argv++; if (! argv || ! *argv) usage(); local_port =*argv++; if (! argv || ! *argv) usage(); prog =(const char **)argv; if (phccmax > cmax) phccmax =cmax; if (user) if (! uidgids_get(&ugid, user)) { if (errno) strerr_die4sys(111, FATAL, "unable to get user/group: ", user, ": "); strerr_die3x(100, FATAL, "unknown user/group: ", user); } #ifdef SSLSVD svuser =user; client =0; if ((getuid() == 0) && (! ssluser)) strerr_die2x(100, FATAL, "-U ssluser must be set when running as root"); if (ssluser) if (! uidgids_get(&sslugid, ssluser)) { if (errno) strerr_die4sys(111, FATAL, "unable to get user/group: ", ssluser, ": "); strerr_die3x(100, FATAL, "unknown user/group: ", ssluser); } if (! cert) cert ="./cert.pem"; if (! key) key =cert; if (matrixSslOpen() < 0) fatal("unable to initialize ssl"); if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) { if (client) fatal("unable to read cert, key, or ca file"); fatal("unable to read cert or key file"); } if (matrixSslNewSession(&ssl, keys, 0, SSL_FLAGS_SERVER) < 0) strerr_die2x(111, FATAL, "unable to create ssl session"); #endif dns_random_init(seed); sig_block(sig_child); sig_catch(sig_child, sig_child_handler); sig_catch(sig_term, sig_term_handler); sig_ignore(sig_pipe); if (phccmax) if (ipsvd_phcc_init(cmax) == -1) die_nomem(); if (str_equal(host, "")) host ="0.0.0.0"; if (str_equal(host, "0")) host ="0.0.0.0"; if (! ipsvd_scan_port(local_port, "tcp", &port)) strerr_die3x(100, FATAL, "unknown port number or name: ", local_port); if (! stralloc_copys(&sa, host)) die_nomem(); if ((dns_ip4(&ips, &sa) == -1) || (ips.len < 4)) if (dns_ip4_qualify(&ips, &fqdn, &sa) == -1) fatal2("unable to look up ip address", host); if (ips.len < 4) strerr_die3x(100, FATAL, "unable to look up ip address: ", host); ips.len =4; if (! stralloc_0(&ips)) die_nomem(); local_ip[ipsvd_fmt_ip(local_ip, ips.s)] =0; if (! lookuphost) { if (! stralloc_copys(&remote_hostname, "")) die_nomem(); if (! stralloc_0(&remote_hostname)) die_nomem(); } if ((s =socket_tcp()) == -1) fatal("unable to create socket"); if (socket_bind4_reuse(s, ips.s, port) == -1) fatal("unable to bind socket"); if (listen(s, backlog) == -1) fatal("unable to listen"); ndelay_off(s); #ifdef SSLSVD #else if (user) { /* drop permissions */ if (setgroups(ugid.gids, ugid.gid) == -1) fatal("unable to set groups"); if (setgid(*ugid.gid) == -1) fatal("unable to set gid"); if (prot_uid(ugid.uid) == -1) fatal("unable to set uid"); } #endif close(0); if (verbose) { out(INFO); out("listening on "); outfix(local_ip); out(":"); outfix(local_port); #ifdef SSLSVD #else if (user) { bufnum[fmt_ulong(bufnum, (unsigned long)ugid.uid)] =0; out(", uid "); out(bufnum); bufnum[fmt_ulong(bufnum, (unsigned long)ugid.gid)] =0; out(", gid "); out(bufnum); } #endif flush(", starting.\n"); } for (;;) { while (cnum >= cmax) sig_pause(); socka_size =sizeof(socka); sig_unblock(sig_child); conn =accept(s, (struct sockaddr *)&socka, &socka_size); sig_block(sig_child); if (conn == -1) { if (errno != error_intr) warn("unable to accept connection"); continue; } cnum++; if (verbose) connection_status(); if (phccmax) phcc =ipsvd_phcc_add((char*)&socka.sin_addr); if ((pid =fork()) == -1) { warn2("drop connection", "unable to fork"); close(conn); continue; } if (pid == 0) { /* child */ close(s); #ifdef SSLSVD if (*progname) *progname ='\\'; #endif connection_accept(conn); } if (phccmax) ipsvd_phcc_setpid(pid); close(conn); } _exit(0); }
int tcpudpsvd_main(int argc ATTRIBUTE_UNUSED, char **argv) { char *str_C, *str_t; char *user; struct hcc *hccp; const char *instructs; char *msg_per_host = NULL; unsigned len_per_host = len_per_host; /* gcc */ #ifndef SSLSVD struct bb_uidgid_t ugid; #endif bool tcp; uint16_t local_port; char *preset_local_hostname = NULL; char *remote_hostname = remote_hostname; /* for compiler */ char *remote_addr = remote_addr; /* for compiler */ len_and_sockaddr *lsa; len_and_sockaddr local, remote; socklen_t sa_len; int pid; int sock; int conn; unsigned backlog = 20; INIT_G(); tcp = (applet_name[0] == 't'); /* 3+ args, -i at most once, -p implies -h, -v is counter, -b N, -c N */ opt_complementary = "-3:i--i:ph:vv:b+:c+"; #ifdef SSLSVD getopt32(argv, "+c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:", &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose ); #else /* "+": stop on first non-option */ getopt32(argv, "+c:C:i:x:u:l:Eb:hpt:v", &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, &backlog, &str_t, &verbose ); #endif if (option_mask32 & OPT_C) { /* -C n[:message] */ max_per_host = bb_strtou(str_C, &str_C, 10); if (str_C[0]) { if (str_C[0] != ':') bb_show_usage(); msg_per_host = str_C + 1; len_per_host = strlen(msg_per_host); } } if (max_per_host > cmax) max_per_host = cmax; if (option_mask32 & OPT_u) { if (!get_uidgid(&ugid, user, 1)) bb_error_msg_and_die("unknown user/group: %s", user); } #ifdef SSLSVD if (option_mask32 & OPT_U) ssluser = optarg; if (option_mask32 & OPT_slash) root = optarg; if (option_mask32 & OPT_Z) cert = optarg; if (option_mask32 & OPT_K) key = optarg; #endif argv += optind; if (!argv[0][0] || LONE_CHAR(argv[0], '0')) argv[0] = (char*)"0.0.0.0"; /* Per-IP flood protection is not thought-out for UDP */ if (!tcp) max_per_host = 0; bb_sanitize_stdio(); /* fd# 0,1,2 must be opened */ #ifdef SSLSVD sslser = user; client = 0; if ((getuid() == 0) && !(option_mask32 & OPT_u)) { xfunc_exitcode = 100; bb_error_msg_and_die("-U ssluser must be set when running as root"); } if (option_mask32 & OPT_u) if (!uidgid_get(&sslugid, ssluser, 1)) { if (errno) { bb_perror_msg_and_die("fatal: cannot get user/group: %s", ssluser); } bb_error_msg_and_die("unknown user/group '%s'", ssluser); } if (!cert) cert = "./cert.pem"; if (!key) key = cert; if (matrixSslOpen() < 0) fatal("cannot initialize ssl"); if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) { if (client) fatal("cannot read cert, key, or ca file"); fatal("cannot read cert or key file"); } if (matrixSslNewSession(&ssl, keys, 0, SSL_FLAGS_SERVER) < 0) fatal("cannot create ssl session"); #endif sig_block(SIGCHLD); signal(SIGCHLD, sig_child_handler); bb_signals(BB_FATAL_SIGS, sig_term_handler); signal(SIGPIPE, SIG_IGN); if (max_per_host) ipsvd_perhost_init(cmax); local_port = bb_lookup_port(argv[1], tcp ? "tcp" : "udp", 0); lsa = xhost2sockaddr(argv[0], local_port); argv += 2; sock = xsocket(lsa->u.sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); setsockopt_reuseaddr(sock); sa_len = lsa->len; /* I presume sockaddr len stays the same */ xbind(sock, &lsa->u.sa, sa_len); if (tcp) xlisten(sock, backlog); else /* udp: needed for recv_from_to to work: */ socket_want_pktinfo(sock); /* ndelay_off(sock); - it is the default I think? */ #ifndef SSLSVD if (option_mask32 & OPT_u) { /* drop permissions */ xsetgid(ugid.gid); xsetuid(ugid.uid); } #endif if (verbose) { char *addr = xmalloc_sockaddr2dotted(&lsa->u.sa); bb_error_msg("listening on %s, starting", addr); free(addr); #ifndef SSLSVD if (option_mask32 & OPT_u) printf(", uid %u, gid %u", (unsigned)ugid.uid, (unsigned)ugid.gid); #endif } /* Main accept() loop */ again: hccp = NULL; while (cnum >= cmax) wait_for_any_sig(); /* expecting SIGCHLD */ /* Accept a connection to fd #0 */ again1: close(0); again2: sig_unblock(SIGCHLD); local.len = remote.len = sa_len; if (tcp) { conn = accept(sock, &remote.u.sa, &remote.len); } else { /* In case recv_from_to won't be able to recover local addr. * Also sets port - recv_from_to is unable to do it. */ local = *lsa; conn = recv_from_to(sock, NULL, 0, MSG_PEEK, &remote.u.sa, &local.u.sa, sa_len); } sig_block(SIGCHLD); if (conn < 0) { if (errno != EINTR) bb_perror_msg(tcp ? "accept" : "recv"); goto again2; } xmove_fd(tcp ? conn : sock, 0); if (max_per_host) { /* Drop connection immediately if cur_per_host > max_per_host * (minimizing load under SYN flood) */ remote_addr = xmalloc_sockaddr2dotted_noport(&remote.u.sa); cur_per_host = ipsvd_perhost_add(remote_addr, max_per_host, &hccp); if (cur_per_host > max_per_host) { /* ipsvd_perhost_add detected that max is exceeded * (and did not store ip in connection table) */ free(remote_addr); if (msg_per_host) { /* don't block or test for errors */ send(0, msg_per_host, len_per_host, MSG_DONTWAIT); } goto again1; } /* NB: remote_addr is not leaked, it is stored in conn table */ } if (!tcp) { /* Voodoo magic: making udp sockets each receive its own * packets is not trivial, and I still not sure * I do it 100% right. * 1) we have to do it before fork() * 2) order is important - is it right now? */ /* Open new non-connected UDP socket for further clients... */ sock = xsocket(lsa->u.sa.sa_family, SOCK_DGRAM, 0); setsockopt_reuseaddr(sock); /* Make plain write/send work for old socket by supplying default * destination address. This also restricts incoming packets * to ones coming from this remote IP. */ xconnect(0, &remote.u.sa, sa_len); /* hole? at this point we have no wildcard udp socket... * can this cause clients to get "port unreachable" icmp? * Yup, time window is very small, but it exists (is it?) */ /* ..."open new socket", continued */ xbind(sock, &lsa->u.sa, sa_len); socket_want_pktinfo(sock); /* Doesn't work: * we cannot replace fd #0 - we will lose pending packet * which is already buffered for us! And we cannot use fd #1 * instead - it will "intercept" all following packets, but child * does not expect data coming *from fd #1*! */ #if 0 /* Make it so that local addr is fixed to localp->u.sa * and we don't accidentally accept packets to other local IPs. */ /* NB: we possibly bind to the _very_ same_ address & port as the one * already bound in parent! This seems to work in Linux. * (otherwise we can move socket to fd #0 only if bind succeeds) */ close(0); set_nport(localp, htons(local_port)); xmove_fd(xsocket(localp->u.sa.sa_family, SOCK_DGRAM, 0), 0); setsockopt_reuseaddr(0); /* crucial */ xbind(0, &localp->u.sa, localp->len); #endif } pid = vfork(); if (pid == -1) { bb_perror_msg("vfork"); goto again; } if (pid != 0) { /* Parent */ cnum++; if (verbose) connection_status(); if (hccp) hccp->pid = pid; /* clean up changes done by vforked child */ undo_xsetenv(); goto again; } /* Child: prepare env, log, and exec prog */ /* Closing tcp listening socket */ if (tcp) close(sock); { /* vfork alert! every xmalloc in this block should be freed! */ char *local_hostname = local_hostname; /* for compiler */ char *local_addr = NULL; char *free_me0 = NULL; char *free_me1 = NULL; char *free_me2 = NULL; if (verbose || !(option_mask32 & OPT_E)) { if (!max_per_host) /* remote_addr is not yet known */ free_me0 = remote_addr = xmalloc_sockaddr2dotted(&remote.u.sa); if (option_mask32 & OPT_h) { free_me1 = remote_hostname = xmalloc_sockaddr2host_noport(&remote.u.sa); if (!remote_hostname) { bb_error_msg("cannot look up hostname for %s", remote_addr); remote_hostname = remote_addr; } } /* Find out local IP peer connected to. * Errors ignored (I'm not paranoid enough to imagine kernel * which doesn't know local IP). */ if (tcp) getsockname(0, &local.u.sa, &local.len); /* else: for UDP it is done earlier by parent */ local_addr = xmalloc_sockaddr2dotted(&local.u.sa); if (option_mask32 & OPT_h) { local_hostname = preset_local_hostname; if (!local_hostname) { free_me2 = local_hostname = xmalloc_sockaddr2host_noport(&local.u.sa); if (!local_hostname) bb_error_msg_and_die("cannot look up hostname for %s", local_addr); } /* else: local_hostname is not NULL, but is NOT malloced! */ } } if (verbose) { pid = getpid(); if (max_per_host) { bb_error_msg("concurrency %s %u/%u", remote_addr, cur_per_host, max_per_host); } bb_error_msg((option_mask32 & OPT_h) ? "start %u %s-%s (%s-%s)" : "start %u %s-%s", pid, local_addr, remote_addr, local_hostname, remote_hostname); } if (!(option_mask32 & OPT_E)) { /* setup ucspi env */ const char *proto = tcp ? "TCP" : "UDP"; /* Extract "original" destination addr:port * from Linux firewall. Useful when you redirect * an outbond connection to local handler, and it needs * to know where it originally tried to connect */ if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &local.u.sa, &local.len) == 0) { char *addr = xmalloc_sockaddr2dotted(&local.u.sa); xsetenv_plain("TCPORIGDSTADDR", addr); free(addr); } xsetenv_plain("PROTO", proto); xsetenv_proto(proto, "LOCALADDR", local_addr); xsetenv_proto(proto, "REMOTEADDR", remote_addr); if (option_mask32 & OPT_h) { xsetenv_proto(proto, "LOCALHOST", local_hostname); xsetenv_proto(proto, "REMOTEHOST", remote_hostname); } //compat? xsetenv_proto(proto, "REMOTEINFO", ""); /* additional */ if (cur_per_host > 0) /* can not be true for udp */ xsetenv_plain("TCPCONCURRENCY", utoa(cur_per_host)); } free(local_addr); free(free_me0); free(free_me1); free(free_me2); } xdup2(0, 1); signal(SIGTERM, SIG_DFL); signal(SIGPIPE, SIG_DFL); signal(SIGCHLD, SIG_DFL); sig_unblock(SIGCHLD); #ifdef SSLSVD strcpy(id, utoa(pid)); ssl_io(0, argv); #else BB_EXECVP(argv[0], argv); #endif bb_perror_msg_and_die("exec '%s'", argv[0]); }