void nextconfig (const char *file) { #ifndef IPV6 struct servent *sp; #endif struct servtab *sep, **sepp; struct passwd *pwd; FILE *fconfig; SIGSTATUS sigstatus; size_t line = 0; fconfig = setconfig (file); if (!fconfig) { syslog (LOG_ERR, "%s: %m", file); return; } while ((sep = getconfigent (fconfig, file, &line))) { if ((pwd = getpwnam (sep->se_user)) == NULL) { syslog (LOG_ERR, "%s/%s: No such user '%s', service ignored", sep->se_service, sep->se_proto, sep->se_user); continue; } if (ISMUX (sep)) { sep->se_fd = -1; sep->se_checked = 1; enter (sep); } else expand_enter (sep); freeconfig (sep); } endconfig (fconfig); /* * Purge anything not looked at above. */ signal_block (&sigstatus); sepp = &servtab; while ((sep = *sepp)) { if (sep->se_checked) { sepp = &sep->se_next; continue; } *sepp = sep->se_next; if (sep->se_fd >= 0) close_sep (sep); if (debug) print_service ("FREE", sep); freeconfig (sep); free (sep); } signal_unblock (&sigstatus); }
/** * \fn int exittimeout() * \brief send timeout and exit propely */ int exittimeout () { clearData (); sendTxt ("451 timeout\r\n"); free_commands (); freeconfig (); exit (0); return 451; }
/** * \fn quit(char *c) * \brief send goodbye message and close the quit the process */ int quit (char *c) { clearData (); sendTxt ("221 Service closing transmission channel\r\n"); free_commands (); freeconfig (); freeAllPlugin (); exit (0); return 221; }
/** * \fn void exitTalkEarlier() * \brief exit when the client don't wait the 220 greeting message */ void exitTalkEarlier () { sendTxt ("451 you must wait 220 code\r\n"); if (config->exitTalkEarlier) { clearData (); sendTxt ("451 you must wait 220 code\r\n"); free_commands (); freeconfig (); exit (0); } }
int main(const int argc, const char *const argv[]) { printf("running with pid %d\n", getpid()); const treeplugin tp = { .rc = formconfig(argc, argv, 64, 0), .extra = NULL, .treeroutine = treeroutine, .makeargument = makeargument, .dropargument = dropargument }; treespawn(&tp); sleep(tp.rc->size); freeconfig((runconfig *)tp.rc); return 0; }
struct servtab * getconfigent (FILE *fconfig, const char *file, size_t *line) { static struct servtab serv; struct servtab *sep = &serv; int argc = 0; size_t i; char **argv = NULL; char *node, *service; static char TCPMUX_TOKEN[] = "tcpmux/"; #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) if (serv_node) return next_node_sep (sep); memset ((caddr_t) sep, 0, sizeof *sep); while (1) { argcv_free (argc, argv); freeconfig (sep); memset ((caddr_t) sep, 0, sizeof *sep); do { ssize_t n = getline (&linebuf, &linebufsize, fconfig); if (n < 0) return 0; else if (n == 0) continue; if (linebuf[n-1] == '\n') linebuf[n-1] = 0; ++ *line; } while (*linebuf == '#' || *linebuf == 0); if (argcv_get (linebuf, "", &argc, &argv)) continue; if (argc < INETD_FIELDS_MIN) { if (argc == 1 && argv[0][strlen (argv[0]) - 1] == ':') { argv[0][strlen (argv[0]) - 1] = 0; free (global_serv_node); if (strcmp (argv[0], "*")) global_serv_node = newstr (argv[0]); } else syslog (LOG_ERR, "%s:%lu: not enough fields", file, (unsigned long) *line); continue; } sep->se_file = file; sep->se_line = *line; node = argv[INETD_SERVICE]; service = strchr (node, ':'); if (!service) { if (global_serv_node) { node = global_serv_node; serv_node = newstr (node); serv_node_offset = 0; } else node = NULL; service = argv[INETD_SERVICE]; } else { *service++ = 0; if (strcmp (node, "*") == 0) node = NULL; else { serv_node = newstr (node); serv_node_offset = 0; } } if (strncmp (service, TCPMUX_TOKEN, MUX_LEN) == 0) { char *c = service + MUX_LEN; if (*c == '+') { sep->se_type = MUXPLUS_TYPE; c++; } else sep->se_type = MUX_TYPE; sep->se_service = newstr (c); } else { sep->se_service = newstr (service); sep->se_type = NORM_TYPE; } if (strcmp (argv[INETD_SOCKET], "stream") == 0) sep->se_socktype = SOCK_STREAM; else if (strcmp (argv[INETD_SOCKET], "dgram") == 0) sep->se_socktype = SOCK_DGRAM; else if (strcmp (argv[INETD_SOCKET], "rdm") == 0) sep->se_socktype = SOCK_RDM; else if (strcmp (argv[INETD_SOCKET], "seqpacket") == 0) sep->se_socktype = SOCK_SEQPACKET; else if (strcmp (argv[INETD_SOCKET], "raw") == 0) sep->se_socktype = SOCK_RAW; else { syslog (LOG_WARNING, "%s:%lu: bad socket type", file, (unsigned long) *line); sep->se_socktype = -1; } sep->se_proto = newstr (argv[INETD_PROTOCOL]); #ifdef IPV6 /* We default to IPv6, in setup() we'll fall back to IPv4 if it doesn't work. */ sep->se_family = AF_INET6; sep->se_v4mapped = 1; if ((strncmp (sep->se_proto, "tcp", 3) == 0) || (strncmp (sep->se_proto, "udp", 3) == 0)) { if (sep->se_proto[3] == '6') { sep->se_family = AF_INET6; sep->se_v4mapped = 0; } else if (sep->se_proto[3] == '4') { sep->se_family = AF_INET; } } #else if ((strncmp (sep->se_proto, "tcp6", 4) == 0) || (strncmp (sep->se_proto, "udp6", 4) == 0)) { syslog (LOG_ERR, "%s:%lu: %s: IPv6 support isn't enabled", file, (unsigned long) *line, sep->se_proto); continue; } sep->se_family = AF_INET; #endif { char *p, *q; p = strchr(argv[INETD_WAIT], '.'); if (p) *p++ = 0; if (strcmp (argv[INETD_WAIT], "wait") == 0) sep->se_wait = 1; else if (strcmp (argv[INETD_WAIT], "nowait") == 0) sep->se_wait = 0; else { syslog (LOG_WARNING, "%s:%lu: bad wait type", file, (unsigned long) *line); } if (p) { sep->se_max = strtoul(p, &q, 10); if (*q) syslog (LOG_WARNING, "%s:%lu: invalid number (%s)", file, (unsigned long) *line, p); } } if (ISMUX (sep)) { /* * Silently enforce "nowait" for TCPMUX services since * they don't have an assigned port to listen on. */ sep->se_wait = 0; if (strncmp (sep->se_proto, "tcp", 3)) { syslog (LOG_ERR, "%s:%lu: bad protocol for tcpmux service %s", file, (unsigned long) *line, sep->se_service); continue; } if (sep->se_socktype != SOCK_STREAM) { syslog (LOG_ERR, "%s:%lu: bad socket type for tcpmux service %s", file, (unsigned long) *line, sep->se_service); continue; } } sep->se_user = newstr (argv[INETD_USER]); sep->se_server = newstr (argv[INETD_SERVER_PATH]); if (strcmp (sep->se_server, "internal") == 0) { sep->se_bi = bi_lookup (sep); if (!sep->se_bi) { syslog (LOG_ERR, "%s:%lu: internal service %s unknown", file, (unsigned long) *line, sep->se_service); continue; } sep->se_wait = sep->se_bi->bi_wait; } else sep->se_bi = NULL; sep->se_argc = argc - INETD_FIELDS_MIN + 1; sep->se_argv = calloc (sep->se_argc + 1, sizeof sep->se_argv[0]); if (!sep->se_argv) { syslog (LOG_ERR, "%s:%lu: Out of memory.", file, (unsigned long) *line); exit (-1); } for (i = 0; i < sep->se_argc; i++) { sep->se_argv[i] = argv[INETD_SERVER_ARGS + i]; argv[INETD_SERVER_ARGS + i] = 0; } sep->se_argv[i] = NULL; break; } argcv_free (argc, argv); return next_node_sep (sep); }
void fix_tcpmux () { struct servtab *sep; int need_tcpmux = 0; int has_tcpmux = 0; for (sep = servtab; sep; sep = sep->se_next) { if (sep->se_checked) { if (ISMUX (sep)) { if (has_tcpmux) return; need_tcpmux = 1; } if (strcmp (sep->se_service, "tcpmux") == 0) { if (need_tcpmux) return; has_tcpmux = 1; } } } if (need_tcpmux && !has_tcpmux) { struct servtab serv; memset (&serv, 0, sizeof (serv)); serv.se_service = newstr ("tcpmux"); serv.se_socktype = SOCK_STREAM; serv.se_proto = newstr ("tcp"); serv.se_checked = 1; serv.se_user = newstr ("root"); serv.se_bi = bi_lookup (&serv); if (!serv.se_bi) { /* Should not happen */ freeconfig (&serv); if (debug) fprintf (stderr, "INETERNAL ERROR: could not found tcpmux built-in"); syslog (LOG_ERR, "INETERNAL ERROR: could not found tcpmux built-in"); return; } serv.se_wait = serv.se_bi->bi_wait; serv.se_server = newstr ("internal"); serv.se_fd = -1; serv.se_type = NORM_TYPE; #ifdef IPV6 serv.se_family = AF_INET6; serv.se_v4mapped = 1; #else serv.se_family = AF_INET; #endif if (debug) fprintf (stderr, "inserting default tcpmux entry\n"); syslog (LOG_INFO, "inserting default tcpmux entry"); enter (&serv); } }