void my_server(char *ip, int port, char *ip2, int port2) { int error; t_serv_info *serv; t_dest_info *dest; struct protoent *pe; serv = malloc(sizeof(serv)); dest = malloc(sizeof(dest)); pe = getprotobyname("TCP"); serv->sock = xsocket(PF_INET, SOCK_STREAM, pe->p_proto); serv->sin.sin_addr.s_addr = INADDR_ANY; serv->sin.sin_family = AF_INET; serv->sin.sin_port = htons(port); serv->ip = ip; serv->port = port; error = xbind(serv->sock, (const struct sockaddr *)&serv->sin, sizeof(serv->sin)); error = xlisten(serv->sock, 42); serv->client_len = sizeof(serv->sin_client); dest->ip = ip2; dest->port = port2; main_loop(error, serv, dest); close(serv->sock); }
int main (int argc, char **argv) { int i, j; char *ubuf = 0; int afd, sfd, tmp; thread_t cli_thread = {}; BUG_ON ( (afd = xlisten ("tcp+ipc+inproc://127.0.0.1:18897") ) < 0); thread_start (&cli_thread, xclient_thread, 0); usleep (100000); BUG_ON (xselect (XPOLLIN, 1, &afd, 1, &tmp) <= 0); for (j = 0; j < 3; j++) { BUG_ON ( (sfd = xaccept (afd) ) < 0); for (i = 0; i < cnt; i++) { while (xselect (XPOLLIN, 1, &sfd, 1, &tmp) <= 0) usleep (10000); BUG_ON (tmp != sfd); BUG_ON (0 != xrecv (sfd, &ubuf) ); BUG_ON (0 != xsend (sfd, ubuf) ); } xclose (sfd); } thread_stop (&cli_thread); xclose (afd); return 0; }
int serveur(t_serv *e) { int fd; fd = xsocket(); xbind(fd, e); xlisten(fd); e->fd_type[fd] = FD_SERVEUR; e->fct_read[fd] = serveur_read; }
int fakeidentd_main(int argc, char **argv) { enum { OPT_foreground = 0x1, OPT_inetd = 0x2, OPT_inetdwait = 0x4, OPT_fiw = 0x7, OPT_bindaddr = 0x8, }; const char *bind_address = NULL; unsigned opt; int fd; opt = getopt32(argv, "fiwb:", &bind_address); strcpy(bogouser, "nobody"); if (argv[optind]) strncpy(bogouser, argv[optind], sizeof(bogouser)); /* Daemonize if no -f and no -i and no -w */ if (!(opt & OPT_fiw)); bb_daemonize_or_rexec(0, argv); /* Where to log in inetd modes? "Classic" inetd * probably has its stderr /dev/null'ed (we need log to syslog?), * but daemontools-like utilities usually expect that children * log to stderr. I like daemontools more. Go their way. * (Or maybe we need yet another option "log to syslog") */ if (!(opt & OPT_fiw) /* || (opt & OPT_syslog) */) { openlog(applet_name, 0, LOG_DAEMON); logmode = LOGMODE_SYSLOG; } if (opt & OPT_inetd) { inetd_mode(); return 0; } /* Ignore closed connections when writing */ signal(SIGPIPE, SIG_IGN); fd = 0; if (!(opt & OPT_inetdwait)) { fd = create_and_bind_stream_or_die(bind_address, bb_lookup_port("identd", "tcp", 113)); xlisten(fd, 5); } isrv_run(fd, new_peer, do_rd, /*do_wr:*/ NULL, do_timeout, TIMEOUT, (opt & OPT_inetdwait) ? TIMEOUT : 0); return 0; }
int main(int argc, char **argv) { t_server *s; int port; char path[4096]; getcwd(path, 4096); if (argc >= 2) port = atoi(argv[1]); else port = 4242; s = xmalloc(sizeof(*s)); init_socket(s); bind_socket(s, port); xlisten(s->listener, 10); FD_SET(s->listener, &(s->master)); s->fdmax = s->listener; s->home = path; loop_server(s, argv); return (0); }
void start_server(t_desc *serv) { t_env e; int i; int x; serv->s = init_serveur(serv); xlisten(serv->s, 42); i = 0; x = i; e.fd_max = serv->s; e.team = NULL; e.t = 0; e.graph_cs = -1; serv->tv = NULL; while (serv->team[x] != NULL) add_elem_in_team(serv, &e.team, x++); init_struct_player(serv->players); /* init_struct_player(serv->players, FD_GHOST, MAX_GHOST, MAX_FD + 1); */ while (1) manage_serveur(serv, &e); }
/* Initializes the dump socket, usually in /var/run directory * (the path depends on compile-time configuration). */ static void dumpsocket_init(void) { unlink(SOCKET_FILE); /* not caring about the result */ int socketfd = xsocket(AF_UNIX, SOCK_STREAM, 0); close_on_exec_on(socketfd); struct sockaddr_un local; memset(&local, 0, sizeof(local)); local.sun_family = AF_UNIX; strcpy(local.sun_path, SOCKET_FILE); xbind(socketfd, (struct sockaddr*)&local, sizeof(local)); xlisten(socketfd, MAX_CLIENT_COUNT); if (chmod(SOCKET_FILE, SOCKET_PERMISSION) != 0) perror_msg_and_die("chmod '%s'", SOCKET_FILE); channel_socket = abrt_gio_channel_unix_new(socketfd); g_io_channel_set_buffered(channel_socket, FALSE); channel_id_socket = add_watch_or_die(channel_socket, G_IO_IN | G_IO_PRI | G_IO_HUP, server_socket_cb); }
int init_serveur(int port) { struct protoent *pe; t_servinfo servinfo; int error; pe = getprotobyname("TCP"); servinfo.sock = xsocket(AF_INET, SOCK_STREAM, pe->p_proto); printf("\tMy IRC \nServer IP: %d:%d\nLocal IP: %d:%d\nSocket %d open.\n", system(IP), port, system(IPL), port, servinfo.sock); servinfo.sin.sin_addr.s_addr = INADDR_ANY; servinfo.sin.sin_family = AF_INET; servinfo.sin.sin_port = htons(port); error = xbind(servinfo.sock, (const struct sockaddr *)&servinfo.sin, sizeof(servinfo.sin)); error = xlisten(servinfo.sock, 42); servinfo.client_len = sizeof(servinfo.sin_client); error = 0; main_loop(error, &servinfo); close(servinfo.sock); return (0); }
int fakeidentd_main(int argc, char **argv) { int fd; pid_t pid; /* FD_ZERO(&G.readfds); - in bss, already zeroed */ FD_SET(0, &G.readfds); /* handle -b <ip> parameter */ getopt32(argc, argv, "b:", &bind_ip_address); /* handle optional REPLY STRING */ if (optind < argc) G.identuser = argv[optind]; else G.identuser = "******"; writepid(); signal(SIGTERM, handlexitsigs); signal(SIGINT, handlexitsigs); signal(SIGQUIT, handlexitsigs); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); /* ignore closed connections when writing */ fd = create_and_bind_stream_or_die(bind_ip_address, bb_lookup_port("identd", "tcp", 113)); xlisten(fd, 5); pid = fork(); if (pid < 0) bb_perror_msg_and_die("fork"); if (pid != 0) /* parent */ exit(0); /* child */ setsid(); movefd(fd, 0); while (fd) close(fd--); openlog(applet_name, 0, LOG_DAEMON); logmode = LOGMODE_SYSLOG; /* main loop where we process all events and never exit */ while (1) { fd_set rfds = G.readfds; struct timeval tv = { 15, 0 }; int i; int tim = time(NULL); select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); for (i = G.conncnt - 1; i >= 0; i--) { int s = i + FCS; if (FD_ISSET(s, &rfds)) { char *buf = conns[i].buf; unsigned len = conns[i].len; unsigned l; l = read(s, buf + len, sizeof(conns[0].buf) - len); if (l > 0) { if (checkInput(buf, len, l)) { reply(s, buf); goto deleteconn; } else if (len + l >= sizeof(conns[0].buf)) { replyError(s, "X-INVALID-REQUEST"); goto deleteconn; } else { conns[i].len += l; } } else { goto deleteconn; } conns[i].lasttime = tim; continue; deleteconn: deleteConn(s); } else { /* implement as time_after() in linux kernel sources ... */ if (conns[i].lasttime + MAXIDLETIME <= tim) { replyError(s, "X-TIMEOUT"); deleteConn(s); } } } if (FD_ISSET(0, &rfds)) { int s = accept(0, NULL, 0); if (s < 0) { if (errno != EINTR) bb_perror_msg("accept"); } else { if (G.conncnt == MAXCONNS) i = closeOldest(); else i = G.conncnt++; movefd(s, i + FCS); /* move if not already there */ FD_SET(i + FCS, &G.readfds); conns[i].len = 0; conns[i].lasttime = time(NULL); } } } /* end of while (1) */ return 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]); }
void start_daemon(int client) { // Launch the daemon, create new session, set proper context if (getuid() != UID_ROOT || getgid() != UID_ROOT) { fprintf(stderr, "Starting daemon requires root: %s\n", strerror(errno)); PLOGE("start daemon"); } switch (fork()) { case -1: PLOGE("fork"); case 0: break; default: return; } // First close the client, it's useless for us close(client); xsetsid(); setcon("u:r:su:s0"); umask(022); int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC); xdup2(fd, STDIN_FILENO); xdup2(fd, STDOUT_FILENO); xdup2(fd, STDERR_FILENO); close(fd); // Patch selinux with medium patch before we do anything load_policydb(SELINUX_POLICY); sepol_med_rules(); dump_policydb(SELINUX_LOAD); // Continue the larger patch in another thread, we will join later pthread_create(&sepol_patch, NULL, large_sepol_patch, NULL); struct sockaddr_un sun; fd = setup_socket(&sun); xbind(fd, (struct sockaddr*) &sun, sizeof(sun)); xlisten(fd, 10); // Change process name strcpy(argv0, "magisk_daemon"); // The root daemon should not do anything if an error occurs // It should stay intact under any circumstances err_handler = do_nothing; LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n"); // Unlock all blocks for rw unlock_blocks(); // Setup links under /sbin xmount(NULL, "/", NULL, MS_REMOUNT, NULL); create_links(NULL, "/sbin"); xchmod("/sbin", 0755); xmkdir("/magisk", 0755); xchmod("/magisk", 0755); xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL); // Loop forever to listen for requests while(1) { int *client = xmalloc(sizeof(int)); *client = xaccept4(fd, NULL, NULL, SOCK_CLOEXEC); pthread_t thread; xpthread_create(&thread, NULL, request_handler, client); // Detach the thread, we will never join it pthread_detach(thread); } }