EIBnetServer * startServer (Layer3 * l3, Trace * t, const char *name) { EIBnetServer *c; char *ip; int port; if (!arg.serverip) return 0; char *a = strdup (arg.serverip); char *b; if (!a) die ("out of memory"); for (b = a; *b; b++) if (*b == ':') break; if (*b == ':') { *b = 0; port = atoi (b + 1); } else port = 3671; c = new EIBnetServer (a, port, arg.tunnel, arg.route, arg.discover, l3, t, name == 0 ? "knxd" : name); if (!c->init ()) die ("initilization of the EIBnet/IP server failed"); free (a); return c; }
/** parses and stores an option */ static error_t parse_opt (int key, char *arg, struct argp_state *state) { struct arguments *arguments = (struct arguments *) state->input; switch (key) { case 'T': arguments->tunnel = 1; arguments->has_work++; break; case 'R': arguments->route = 1; arguments->has_work++; break; case 'D': arguments->discover = 1; break; case 'S': { const char *serverip; const char *name = arguments->eibnetname; EIBnetServer *c; int port = 0; char *a = strdup (OPT_ARG(arg, state, "")); char *b; if (!a) die ("out of memory"); b = strchr (a, ':'); if (b) { *b++ = 0; port = atoi (b); } if (port <= 0) port = 3671; serverip = a; if (!*serverip) serverip = "224.0.23.12"; c = new EIBnetServer (serverip, port, arguments->tunnel, arguments->route, arguments->discover, arguments->l3(), arguments->tracer(), (name && *name) ? name : "knxd"); if (!c->init ()) die ("initialization of the EIBnet/IP server failed"); free (a); arguments->tunnel = false; arguments->route = false; arguments->discover = false; arguments->eibnetname = 0; } break; case 'u': { BaseServer *s; const char *name = OPT_ARG(arg,state,"/run/knx"); s = new LocalServer (arguments->l3(), arguments->tracer(), name); if (!s->init ()) die ("initialisation of the knxd unix protocol failed"); arguments->has_work++; } break; case 'i': { BaseServer *s = NULL; int port = atoi(OPT_ARG(arg,state,"6720")); if (port > 0) s = new InetServer (arguments->l3(), arguments->tracer(), port); if (!s || !s->init ()) die ("initialisation of the knxd inet protocol failed"); arguments->has_work++; } break; case 't': if (arg) { char *x; unsigned long level = strtoul(arg, &x, 0); if (*x) die ("Trace level: '%s' is not a number", arg); arguments->tracer(true)->SetTraceLevel (level); } else arguments->tracer(true)->SetTraceLevel (0); break; case 'f': arguments->tracer(true)->SetErrorLevel (arg ? atoi (arg) : 0); break; case 'e': if (arguments->has_l3 ()) { die ("You need to specify '-e' earlier"); } arguments->addr = readaddr (arg); break; case 'p': arguments->pidfile = arg; break; case 'd': arguments->daemon = OPT_ARG(arg,state,"/dev/null"); break; case 'c': if (!CreateGroupCache (arguments->l3(), arguments->tracer(), true)) die ("initialisation of the group cache failed"); break; case 'n': arguments->eibnetname = (char *)arg; if(arguments->eibnetname[0] == '=') arguments->eibnetname++; if(strlen(arguments->eibnetname) >= 30) die("EIBnetServer/IP name must be shorter than 30 bytes"); break; case OPT_FORCE_BROADCAST: arguments->force_broadcast = true; break; case OPT_STOP_NOW: arguments->stop_now = true; break; case OPT_BACK_TUNNEL_NOQUEUE: arguments->l2opts.flags |= FLAG_B_TUNNEL_NOQUEUE; break; case OPT_BACK_TPUARTS_ACKGROUP: arguments->l2opts.flags |= FLAG_B_TPUARTS_ACKGROUP; break; case OPT_BACK_TPUARTS_ACKINDIVIDUAL: arguments->l2opts.flags |= FLAG_B_TPUARTS_ACKINDIVIDUAL; break; case OPT_BACK_TPUARTS_DISCH_RESET: arguments->l2opts.flags |= FLAG_B_TPUARTS_DISCH_RESET; break; case OPT_BACK_EMI_NOQUEUE: arguments->l2opts.flags |= FLAG_B_EMI_NOQUEUE; break; case 'N': arguments->l2opts.flags |= FLAG_B_NO_MONITOR; break; case ARGP_KEY_ARG: case 'b': { arguments->l2opts.t = arguments->tracer (); Layer2 *l2 = Create (arg, &arguments->l2opts, arguments->l3 ()); if (!l2 || !l2->init ()) die ("initialisation of backend '%s' failed", arg); if (arguments->l2opts.flags) die ("You provided options which '%s' does not recognize", arg); memset(&arguments->l2opts, 0, sizeof(arguments->l2opts)); arguments->has_work++; break; } case ARGP_KEY_FINI: if (arguments->l2opts.flags) die ("You need to use backend flags in front of the affected backend"); #ifdef HAVE_SYSTEMD { BaseServer *s = NULL; const int num_fds = sd_listen_fds(0); if( num_fds < 0 ) die("Error getting fds from systemd."); // zero FDs from systemd is not a bug for( int fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START+num_fds; ++fd ) { if( sd_is_socket(fd, AF_UNSPEC, SOCK_STREAM, 1) <= 0 ) die("Error: socket not of expected type."); s = new SystemdServer(arguments->l3(), arguments->tracer(), fd); if (!s->init ()) die ("initialisation of the systemd socket failed"); arguments->has_work++; } } #endif errno = 0; if (arguments->tunnel || arguments->route || arguments->discover || arguments->eibnetname) die ("Option '-S' starts the multicast server.\n" "-T/-R/-D/-n after or without that option are useless."); if (arguments->l2opts.flags) die ("You provided L2 flags after specifying an L2 interface."); if (arguments->has_work == 0) die ("I know about no interface. Nothing to do. Giving up."); if (arguments->has_work == 1) die ("I only have one interface. Nothing to do. Giving up."); arguments->finish_l3(); break; default: return ARGP_ERR_UNKNOWN; } return 0; }