static int module_init(void) { struct sa laddr_udp, laddr_http; struct pl addr; uint32_t port; int err; /* UDP bind address */ if (conf_get(restund_conf(), "status_udp_addr", &addr)) pl_set_str(&addr, "127.0.0.1"); if (conf_get_u32(restund_conf(), "status_udp_port", &port)) port = 33000; err = sa_set(&laddr_udp, &addr, port); if (err) { restund_error("status: bad udp bind address: %r:%u", &addr, port); goto out; } /* HTTP bind address */ if (conf_get(restund_conf(), "status_http_addr", &addr)) pl_set_str(&addr, "127.0.0.1"); if (conf_get_u32(restund_conf(), "status_http_port", &port)) port = 8080; err = sa_set(&laddr_http, &addr, port); if (err) { restund_error("status: bad http bind address: %r:%u", &addr, port); goto out; } err = udp_listen(&stg.us, &laddr_udp, udp_recv, NULL); if (err) { restund_warning("status: udp_listen: %m\n", err); goto out; } err = httpd_alloc(&stg.httpd, &laddr_http, httpd_handler); if (err) { restund_warning("status: httpd: %m\n", err); goto out; } stg.start = time(NULL); restund_debug("status: module loaded (udp=%J http=%J)\n", &laddr_udp, &laddr_http); out: if (err) { stg.us = mem_deref(stg.us); stg.httpd = mem_deref(stg.httpd); } return err; }
static int parse_resolv_conf(char *domain, size_t dsize, struct sa *srvv, uint32_t *n) { FILE *f; struct pl dom = pl_null; uint32_t i = 0; int err = 0; if (!srvv || !n || !*n) return EINVAL; f = fopen("/etc/resolv.conf", "r"); if (!f) return errno; for (;;) { char line[128]; struct pl srv; size_t len; if (1 != fscanf(f, "%127[^\n]\n", line)) break; if ('#' == line[0]) continue; len = str_len(line); /* Set domain if not already set */ if (!pl_isset(&dom)) { if (0 == re_regex(line, len, "domain [^ ]+", &dom)) { (void)pl_strcpy(&dom, domain, dsize); } if (0 == re_regex(line, len, "search [^ ]+", &dom)) { (void)pl_strcpy(&dom, domain, dsize); } } /* Use the first entry */ if (i < *n && 0 == re_regex(line, len, "nameserver [^\n]+", &srv)) { err = sa_set(&srvv[i], &srv, DNS_PORT); if (err) { DEBUG_WARNING("sa_set: %r (%m)\n", &srv, err); } ++i; } } *n = i; (void)fclose(f); return err; }
static int conn_decode(struct sa *sa, const struct pl *pl) { struct pl v; if (re_regex(pl->p, pl->l, "IN IP[46]1 [^ ]+", NULL, &v)) return EBADMSG; (void)sa_set(sa, &v, sa_port(sa)); return 0; }
static void sa_of_string_test(void) { printsln((String)__func__); Array ac, ex; ac = sa_of_string("1, 2, 3"); ex = sa_create(3, ""); sa_set(ex, 0, "1"); sa_set(ex, 1, "2"); sa_set(ex, 2, "3"); sa_check_expect(ac, ex); sa_free(ac); ac = sa_of_string("1 , 2, 3 "); sa_set(ex, 0, "1 "); sa_set(ex, 1, "2"); sa_set(ex, 2, "3 "); sa_check_expect(ac, ex); sa_free(ac); a_free(ex); ac = sa_of_string("1 , 2"); ex = sa_create(2, ""); sa_set(ex, 0, "1 "); sa_set(ex, 1, "2"); sa_check_expect(ac, ex); sa_free(ac); a_free(ex); ac = sa_of_string(""); ex = sa_create(1, ""); sa_check_expect(ac, ex); sa_free(ac); a_free(ex); ac = sa_of_string("123"); ex = sa_create(1, "123"); sa_check_expect(ac, ex); sa_free(ac); a_free(ex); }
static int attr_decode_rtcp(struct sdp_media *m, const struct pl *pl) { struct pl port, addr; int err = 0; if (!m) return 0; if (!re_regex(pl->p, pl->l, "[0-9]+ IN IP[46]1 [^ ]+", &port, NULL, &addr)) { (void)sa_set(&m->raddr_rtcp, &addr, pl_u32(&port)); } else if (!re_regex(pl->p, pl->l, "[0-9]+", &port)) { sa_set_port(&m->raddr_rtcp, pl_u32(&port)); } else err = EBADMSG; return err; }
/** * Decode a pointer-length string into a SIP Via header * * @param via SIP Via header * @param pl Pointer-length string * * @return 0 for success, otherwise errorcode */ int sip_via_decode(struct sip_via *via, const struct pl *pl) { struct pl transp, host, port; int err; if (!via || !pl) return EINVAL; err = re_regex(pl->p, pl->l, "SIP[ \t\r\n]*/[ \t\r\n]*2.0[ \t\r\n]*/[ \t\r\n]*" "[A-Z]+[ \t\r\n]*[^; \t\r\n]+[ \t\r\n]*[^]*", NULL, NULL, NULL, NULL, &transp, NULL, &via->sentby, NULL, &via->params); if (err) return err; if (!pl_strcmp(&transp, "TCP")) via->tp = SIP_TRANSP_TCP; else if (!pl_strcmp(&transp, "TLS")) via->tp = SIP_TRANSP_TLS; else if (!pl_strcmp(&transp, "UDP")) via->tp = SIP_TRANSP_UDP; else via->tp = SIP_TRANSP_NONE; err = decode_hostport(&via->sentby, &host, &port); if (err) return err; sa_init(&via->addr, AF_INET); (void)sa_set(&via->addr, &host, 0); if (pl_isset(&port)) sa_set_port(&via->addr, pl_u32(&port)); via->val = *pl; return msg_param_decode(&via->params, "branch", &via->branch); }
int stun_uri_decode(struct stun_uri *stun_uri, const char *str) { struct uri uri; struct pl pl_uri; uint16_t port; struct pl transp; int err; if (!stun_uri || !str) return EINVAL; pl_set_str(&pl_uri, str); err = uri_decode(&uri, &pl_uri); if (err) { warning("cannot decode URI (%r)\n", &pl_uri); return err; } if (0 == pl_strcasecmp(&uri.scheme, "stun") || 0 == pl_strcasecmp(&uri.scheme, "stuns")) { stun_uri->scheme = STUN_SCHEME_STUN; } else if (0 == pl_strcasecmp(&uri.scheme, "turn") || 0 == pl_strcasecmp(&uri.scheme, "turns")) { stun_uri->scheme = STUN_SCHEME_TURN; } else { warning("unsupported stun scheme (%r)\n", &uri.scheme); return ENOTSUP; } stun_uri->secure = 's' == tolower(uri.scheme.p[uri.scheme.l-1]); if (uri.port) port = uri.port; else if (stun_uri->secure) port = 5349; else port = 3478; err = sa_set(&stun_uri->addr, &uri.host, port); if (err) { warning("invalid stun address (%r)\n", &uri.host); return err; } if (0 == re_regex(str, strlen(str), "?transport=[a-z]+", &transp)) { if (0 == pl_strcasecmp(&transp, "udp")) stun_uri->proto = IPPROTO_UDP; else if (0 == pl_strcasecmp(&transp, "tcp")) stun_uri->proto = IPPROTO_TCP; else { warning("unsupported stun transport (%r)\n", &transp); return ENOTSUP; } } else { stun_uri->proto = IPPROTO_UDP; } return 0; }
static int module_init(void) { uint32_t x, bsize = ALLOC_DEFAULT_BSIZE; struct pl opt; int err = 0; restund_stun_register_handler(&stun); restund_cmd_subscribe(&cmd_turn); restund_cmd_subscribe(&cmd_turnstats); /* turn_external_addr */ if (!conf_get(restund_conf(), "turn_relay_addr", &opt)) err = sa_set(&turnd.rel_addr, &opt, 0); else sa_init(&turnd.rel_addr, AF_UNSPEC); if (err) { restund_error("turn: bad turn_relay_addr: '%r'\n", &opt); goto out; } /* turn_external_addr6 */ if (!conf_get(restund_conf(), "turn_relay_addr6", &opt)) err = sa_set(&turnd.rel_addr6, &opt, 0); else sa_init(&turnd.rel_addr6, AF_UNSPEC); if (err) { restund_error("turn: bad turn_relay_addr6: '%r'\n", &opt); goto out; } if (!sa_isset(&turnd.rel_addr, SA_ADDR) && !sa_isset(&turnd.rel_addr6, SA_ADDR)) { restund_error("turn: no relay address configured\n"); err = EINVAL; goto out; } /* turn_max_lifetime, turn_max_allocations, udp_sockbuf_size */ turnd.lifetime_max = TURN_DEFAULT_LIFETIME; conf_get_u32(restund_conf(), "turn_max_lifetime", &turnd.lifetime_max); conf_get_u32(restund_conf(), "turn_max_allocations", &bsize); conf_get_u32(restund_conf(), "udp_sockbuf_size", &turnd.udp_sockbuf_size); for (x=2; (uint32_t)1<<x<bsize; x++); bsize = 1<<x; err = hash_alloc(&turnd.ht_alloc, bsize); if (err) { restund_error("turnd hash alloc error: %m\n", err); goto out; } restund_debug("turn: lifetime=%u ext=%j ext6=%j bsz=%u\n", turnd.lifetime_max, &turnd.rel_addr, &turnd.rel_addr6, bsize); out: return err; }
int ice_cand_attr_decode(struct ice_cand_attr *cand, const char *val) { struct pl pl_fnd, pl_compid, pl_transp, pl_prio, pl_addr, pl_port; struct pl pl_type, pl_raddr, pl_rport, pl_opt = PL_INIT; size_t len; char type[8]; int err; if (!cand || !val) return EINVAL; memset(cand, 0, sizeof(*cand)); len = str_len(val); err = re_regex(val, len, "[^ ]+ [0-9]+ [a-z]+ [0-9]+ [^ ]+ [0-9]+ typ [a-z]+" "[^]*", &pl_fnd, &pl_compid, &pl_transp, &pl_prio, &pl_addr, &pl_port, &pl_type, &pl_opt); if (err) return err; (void)pl_strcpy(&pl_fnd, cand->foundation, sizeof(cand->foundation)); if (0 == pl_strcasecmp(&pl_transp, "UDP")) cand->proto = IPPROTO_UDP; else if (0 == pl_strcasecmp(&pl_transp, "TCP")) cand->proto = IPPROTO_TCP; else cand->proto = 0; err = sa_set(&cand->addr, &pl_addr, pl_u32(&pl_port)); if (err) return err; cand->compid = pl_u32(&pl_compid); cand->prio = pl_u32(&pl_prio); (void)pl_strcpy(&pl_type, type, sizeof(type)); cand->type = ice_cand_name2type(type); /* optional */ if (0 == re_regex(pl_opt.p, pl_opt.l, "raddr [^ ]+ rport [0-9]+", &pl_raddr, &pl_rport)) { err = sa_set(&cand->rel_addr, &pl_raddr, pl_u32(&pl_rport)); if (err) return err; } if (cand->proto == IPPROTO_TCP) { struct pl tcptype; err = re_regex(pl_opt.p, pl_opt.l, "tcptype [^ ]+", &tcptype); if (err) return err; cand->tcptype = ice_tcptype_resolve(&tcptype); } return 0; }
static int cand_decode(struct icem *icem, const char *val) { struct pl foundation, compid, transp, prio, addr, port, cand_type; struct pl extra = pl_null; struct sa caddr, rel_addr; char type[8]; uint8_t cid; int err; sa_init(&rel_addr, AF_INET); err = re_regex(val, strlen(val), "[^ ]+ [0-9]+ [^ ]+ [0-9]+ [^ ]+ [0-9]+ typ [a-z]+[^]*", &foundation, &compid, &transp, &prio, &addr, &port, &cand_type, &extra); if (err) return err; if (ICE_TRANSP_NONE == transp_resolve(&transp)) { DEBUG_NOTICE("<%s> ignoring candidate with" " unknown transport=%r (%r:%r)\n", icem->name, &transp, &cand_type, &addr); return 0; } if (pl_isset(&extra)) { struct pl name, value; /* Loop through " SP attr SP value" pairs */ while (!re_regex(extra.p, extra.l, " [^ ]+ [^ ]+", &name, &value)) { pl_advance(&extra, value.p + value.l - extra.p); if (0 == pl_strcasecmp(&name, rel_addr_str)) { err = sa_set(&rel_addr, &value, sa_port(&rel_addr)); if (err) break; } else if (0 == pl_strcasecmp(&name, rel_port_str)) { sa_set_port(&rel_addr, pl_u32(&value)); } } } err = sa_set(&caddr, &addr, pl_u32(&port)); if (err) return err; cid = pl_u32(&compid); /* add only if not exist */ if (icem_cand_find(&icem->rcandl, cid, &caddr)) return 0; (void)pl_strcpy(&cand_type, type, sizeof(type)); return icem_rcand_add(icem, ice_cand_name2type(type), cid, pl_u32(&prio), &caddr, &rel_addr, &foundation); }