/** * parseBSR - Parse the candidate BSR configured information. * @s: String token * * Syntax: * cand_bootstrap_router [address | ifname] [priority <0-255>] */ int parseBSR(char *s) { char *w; uint32_t local = INADDR_ANY_N; uint32_t priority = PIM_DEFAULT_BSR_PRIORITY; cand_bsr_flag = FALSE; while (!EQUAL((w = next_word(&s)), "")) { if (EQUAL(w, "priority")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing Cand-BSR priority, defaulting to %u", PIM_DEFAULT_BSR_PRIORITY); priority = PIM_DEFAULT_BSR_PRIORITY; continue; } if (sscanf(w, "%u", &priority) != 1) { WARN("Invalid Cand-BSR priority %s, defaulting to %u", PIM_DEFAULT_BSR_PRIORITY); priority = PIM_DEFAULT_BSR_PRIORITY; continue; } if (priority > PIM_MAX_CAND_BSR_PRIORITY) { WARN("Too high Cand-BSR priority %u, defaulting to %d", priority, PIM_MAX_CAND_BSR_PRIORITY); priority = PIM_MAX_CAND_BSR_PRIORITY; } my_bsr_priority = (u_int8)priority; continue; } /* Cand-BSR interface or address */ local = ifname2addr(w); if (!local) local = inet_parse(w, 4); if (!inet_valid_host(local)) { local = max_local_address(); WARN("Invalid Cand-BSR address '%s', defaulting to %s", w, inet_fmt(local, s1, sizeof(s1))); continue; } if (local_address(local) == NO_VIF) { local = max_local_address(); WARN("Cand-BSR address '%s' is not local, defaulting to %s", w, inet_fmt(local, s1, sizeof(s1))); } } if (local == INADDR_ANY_N) { /* If address not provided, use the max. local */ local = max_local_address(); } my_bsr_address = local; my_bsr_priority = priority; MASKLEN_TO_MASK(RP_DEFAULT_IPV4_HASHMASKLEN, my_bsr_hash_mask); cand_bsr_flag = TRUE; logit(LOG_INFO, 0, "Local Cand-BSR address %s, priority %u", inet_fmt(local, s1, sizeof(s1)), priority); return TRUE; }
int inet_listen(const char *str, char *ostr, int olen, int socktype, int port_offset, Error **errp) { char *optstr; int sock = -1; InetSocketAddress *addr; addr = inet_parse(str, errp); if (addr != NULL) { sock = inet_listen_saddr(addr, port_offset, true, errp); if (sock != -1 && ostr) { optstr = strchr(str, ','); if (addr->ipv6) { snprintf(ostr, olen, "[%s]:%s%s", addr->host, addr->port, optstr ? optstr : ""); } else { snprintf(ostr, olen, "%s:%s%s", addr->host, addr->port, optstr ? optstr : ""); } } qapi_free_InetSocketAddress(addr); } return sock; }
int inet_listen(const char *str, char *ostr, int olen, int socktype, int port_offset, Error **errp) { QemuOpts *opts; char *optstr; int sock = -1; InetSocketAddress *addr; addr = inet_parse(str, errp); if (addr != NULL) { opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); inet_addr_to_opts(opts, addr); qapi_free_InetSocketAddress(addr); sock = inet_listen_opts(opts, port_offset, errp); if (sock != -1 && ostr) { optstr = strchr(str, ','); if (qemu_opt_get_bool(opts, "ipv6", 0)) { snprintf(ostr, olen, "[%s]:%s%s", qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), optstr ? optstr : ""); } else { snprintf(ostr, olen, "%s:%s%s", qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), optstr ? optstr : ""); } } qemu_opts_del(opts); } return sock; }
int inet_listen(const char *str, char *ostr, int olen, int socktype, int port_offset) { QemuOpts *opts; char *optstr; int sock = -1; opts = qemu_opts_create(&dummy_opts, NULL, 0); if (inet_parse(opts, str) == 0) { sock = inet_listen_opts(opts, port_offset); if (sock != -1 && ostr) { optstr = strchr(str, ','); if (qemu_opt_get_bool(opts, "ipv6", 0)) { snprintf(ostr, olen, "[%s]:%s%s", qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), optstr ? optstr : ""); } else { snprintf(ostr, olen, "%s:%s%s", qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), optstr ? optstr : ""); } } } qemu_opts_del(opts); return sock; }
int inet_listen(const char *addr, int backlog, int block_mode) { struct sockaddr_in sin; int sock; int t = 1; char *buf; char *host; char *port; /* * Translate address information to internal form. */ buf = inet_parse(addr, &host, &port); memset((char *) &sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = find_inet_port(port, "tcp"); sin.sin_addr.s_addr = (*host ? find_inet_addr(host) : INADDR_ANY); myfree(buf); /* * Create a listener socket. */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) msg_fatal("socket: %m"); if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0) msg_fatal("setsockopt: %m"); if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) msg_fatal("bind %s port %d: %m", sin.sin_addr.s_addr == INADDR_ANY ? "INADDR_ANY" : inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); non_blocking(sock, block_mode); if (listen(sock, backlog) < 0) msg_fatal("listen: %m"); return (sock); }
/* * function name: parseBSR * input: char *s * output: int * operation: parse the candidate BSR configured information. * General form: * 'cand_bootstrap_router <local-addr> [priority <number>]'. */ int parseBSR(char *s) { char *w; u_int32 local = INADDR_ANY_N; u_int32 priority = PIM_DEFAULT_BSR_PRIORITY; cand_bsr_flag = FALSE; while (!EQUAL((w = next_word(&s)), "")) { if (EQUAL(w, "priority")) { if (EQUAL((w = next_word(&s)), "")) { logit(LOG_WARNING, 0, "Missing priority; set to default %u (0 is lowest)\n", PIM_DEFAULT_BSR_PRIORITY); priority = PIM_DEFAULT_BSR_PRIORITY; continue; } if (sscanf(w, "%u", &priority) != 1) { logit(LOG_WARNING, 0, "invalid priority %s; set to default %u (0 is lowest)", PIM_DEFAULT_BSR_PRIORITY); priority = PIM_DEFAULT_BSR_PRIORITY; continue; } if (priority > (my_bsr_priority = ~0)) priority = my_bsr_priority; my_bsr_priority = (u_int8)priority; continue; } /* BSR address */ local = inet_parse(w, 4); if (!inet_valid_host(local)) { local = max_local_address(); logit(LOG_WARNING, 0, "Invalid BSR address provided '%s' in %s. Will use the largest enabled local address.", w, configfilename); continue; } if (local_address(local) == NO_VIF) { local = max_local_address(); logit(LOG_WARNING, 0, "Cand-BSR address is not local '%s' in %s. Will use the largest enabled local address.", w, configfilename); } } /* while not empty */ if (local == INADDR_ANY_N) /* If address not provided, use the max. local */ local = max_local_address(); my_bsr_address = local; my_bsr_priority = priority; MASKLEN_TO_MASK(RP_DEFAULT_IPV4_HASHMASKLEN, my_bsr_hash_mask); cand_bsr_flag = TRUE; logit(LOG_INFO, 0, "Local Cand-BSR address is %s", inet_fmt(local, s1, sizeof(s1))); logit(LOG_INFO, 0, "Local Cand-BSR priority is %u", priority); return TRUE; }
int inet_connect(const char *addr, int block_mode, int timeout) { char *buf; char *host; char *port; struct sockaddr_in sin; int sock; /* * Translate address information to internal form. No host defaults to * the local host. */ buf = inet_parse(addr, &host, &port); if (*host == 0) host = "localhost"; memset((char *) &sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = find_inet_addr(host); sin.sin_port = find_inet_port(port, "tcp"); myfree(buf); /* * Create a client socket. */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) msg_fatal("socket: %m"); /* * Timed connect. */ if (timeout > 0) { non_blocking(sock, NON_BLOCKING); if (timed_connect(sock, (struct sockaddr *) & sin, sizeof(sin), timeout) < 0) { close(sock); return (-1); } if (block_mode != NON_BLOCKING) non_blocking(sock, block_mode); return (sock); } /* * Maybe block until connected. */ else { non_blocking(sock, block_mode); if (sane_connect(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0 && errno != EINPROGRESS) { close(sock); return (-1); } return (sock); } }
int inet_connect(const char *str, int socktype) { QemuOpts *opts; int sock = -1; opts = qemu_opts_create(&dummy_opts, NULL, 0); if (inet_parse(opts, str) == 0) sock = inet_connect_opts(opts); qemu_opts_del(opts); return sock; }
/** * Create a blocking socket and connect it to an address. * * @str: address string * @errp: set in case of an error * * Returns -1 in case of error, file descriptor on success **/ int inet_connect(const char *str, Error **errp) { int sock = -1; InetSocketAddress *addr = g_new(InetSocketAddress, 1); if (!inet_parse(addr, str, errp)) { sock = inet_connect_saddr(addr, errp); } qapi_free_InetSocketAddress(addr); return sock; }
/** * Create a blocking socket and connect it to an address. * * @str: address string * @errp: set in case of an error * * Returns -1 in case of error, file descriptor on success **/ int inet_connect(const char *str, Error **errp) { int sock = -1; InetSocketAddress *addr; addr = inet_parse(str, errp); if (addr != NULL) { sock = inet_connect_saddr(addr, errp, NULL, NULL); qapi_free_InetSocketAddress(addr); } return sock; }
/* * function name: parse_group_prefix * input: char *s * output: int * operation: parse group_prefix configured information. * General form: 'group_prefix <group-addr> [masklen <masklen>]'. */ int parse_group_prefix(char *s) { char *w; u_int32 group_addr; u_int32 masklen; w = next_word(&s); if (EQUAL(w, "")) { logit(LOG_WARNING, 0, "Configuration error for 'group_prefix' in %s: no group_addr. Ignoring...", configfilename); return FALSE; } group_addr = inet_parse(w, 4); if (!IN_MULTICAST(ntohl(group_addr))) { logit(LOG_WARNING, 0, "Config error for 'group_prefix' in %s: %s is not a mcast addr. Ignoring...", configfilename, inet_fmt(group_addr, s1, sizeof(s1))); return FALSE; } /* Was if (!(~(*cand_rp_adv_message.prefix_cnt_ptr))) which Arm GCC 4.4.2 dislikes: * --> "config.c:693: warning: promoted ~unsigned is always non-zero" * The prefix_cnt_ptr is a u_int8 so it seems this check was to prevent overruns. * I've changed the check to see if we've already read 255 entries, if so the cnt * is maximized and we need to tell the user. --Joachim Nilsson 2010-01-16 */ if (*cand_rp_adv_message.prefix_cnt_ptr == 255) { logit(LOG_WARNING, 0, "Too many group_prefix configured. Truncating..."); return FALSE; } if (EQUAL((w = next_word(&s)), "masklen")) { w = next_word(&s); if (sscanf(w, "%u", &masklen) == 1) { if (masklen > (sizeof(group_addr)*8)) masklen = (sizeof(group_addr)*8); else if (masklen < 4) masklen = 4; } else masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; } else masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; PUT_EGADDR(group_addr, (u_int8)masklen, 0, cand_rp_adv_message.insert_data_ptr); (*cand_rp_adv_message.prefix_cnt_ptr)++; logit(LOG_INFO, 0, "Adding prefix %s/%d", inet_fmt(group_addr, s1, sizeof(s1)), masklen); return TRUE; }
/** * Create a blocking socket and connect it to an address. * * @str: address string * @errp: set in case of an error * * Returns -1 in case of error, file descriptor on success **/ int inet_connect(const char *str, Error **errp) { QemuOpts *opts; int sock = -1; opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); if (inet_parse(opts, str) == 0) { sock = inet_connect_opts(opts, errp, NULL, NULL); } else { error_set(errp, QERR_SOCKET_CREATE_FAILED); } qemu_opts_del(opts); return sock; }
static SocketAddress *tcp_build_address(const char *host_port, Error **errp) { InetSocketAddress *iaddr = inet_parse(host_port, errp); SocketAddress *saddr; if (!iaddr) { return NULL; } saddr = g_new0(SocketAddress, 1); saddr->type = SOCKET_ADDRESS_KIND_INET; saddr->u.inet.data = iaddr; return saddr; }
/** * Create a blocking socket and connect it to an address. * * @str: address string * @errp: set in case of an error * * Returns -1 in case of error, file descriptor on success **/ int inet_connect(const char *str, Error **errp) { QemuOpts *opts; int sock = -1; InetSocketAddress *addr; addr = inet_parse(str, errp); if (addr != NULL) { opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); inet_addr_to_opts(opts, addr); qapi_free_InetSocketAddress(addr); sock = inet_connect_opts(opts, errp, NULL, NULL); qemu_opts_del(opts); } return sock; }
/** * Create a non-blocking socket and connect it to an address. * Calls the callback function with fd in case of success or -1 in case of * error. * * @str: address string * @callback: callback function that is called when connect completes, * cannot be NULL. * @opaque: opaque for callback function * @errp: set in case of an error * * Returns: -1 on immediate error, file descriptor on success. **/ int inet_nonblocking_connect(const char *str, NonBlockingConnectHandler *callback, void *opaque, Error **errp) { int sock = -1; InetSocketAddress *addr; g_assert(callback != NULL); addr = inet_parse(str, errp); if (addr != NULL) { sock = inet_connect_saddr(addr, errp, callback, opaque); qapi_free_InetSocketAddress(addr); } return sock; }
/** * parse_group_prefix - Parse group_prefix configured information. * @s: String token * Syntax: * group_prefix <group-addr>[/<masklen>] * <group-addr> [masklen <masklen>] * * Returns: * %TRUE if the parsing was successful, o.w. %FALSE */ int parse_group_prefix(char *s) { char *w; uint32_t group_addr; uint32_t masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; w = next_word(&s); if (EQUAL(w, "")) { WARN("Missing group_prefix address"); return FALSE; } parse_prefix_len (w, &masklen); group_addr = inet_parse(w, 4); if (!IN_MULTICAST(ntohl(group_addr))) { WARN("Group address '%s' is not a valid multicast address", inet_fmt(group_addr, s1, sizeof(s1))); return FALSE; } /* Was if (!(~(*cand_rp_adv_message.prefix_cnt_ptr))) which Arm GCC 4.4.2 dislikes: * --> "config.c:693: warning: promoted ~unsigned is always non-zero" * The prefix_cnt_ptr is a u_int8 so it seems this check was to prevent overruns. * I've changed the check to see if we've already read 255 entries, if so the cnt * is maximized and we need to tell the user. --Joachim Nilsson 2010-01-16 */ if (*cand_rp_adv_message.prefix_cnt_ptr == 255) { WARN("Too many multicast groups configured!"); return FALSE; } if (EQUAL((w = next_word(&s)), "masklen")) { w = next_word(&s); if (!sscanf(w, "%u", &masklen)) masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; } validate_prefix_len(&masklen); PUT_EGADDR(group_addr, (u_int8)masklen, 0, cand_rp_adv_message.insert_data_ptr); (*cand_rp_adv_message.prefix_cnt_ptr)++; logit(LOG_INFO, 0, "Adding Cand-RP group prefix %s/%d", inet_fmt(group_addr, s1, sizeof(s1)), masklen); return TRUE; }
/** * Create a non-blocking socket and connect it to an address. * Calls the callback function with fd in case of success or -1 in case of * error. * * @str: address string * @callback: callback function that is called when connect completes, * cannot be NULL. * @opaque: opaque for callback function * @errp: set in case of an error * * Returns: -1 on immediate error, file descriptor on success. **/ int inet_nonblocking_connect(const char *str, NonBlockingConnectHandler *callback, void *opaque, Error **errp) { QemuOpts *opts; int sock = -1; g_assert(callback != NULL); opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); if (inet_parse(opts, str) == 0) { sock = inet_connect_opts(opts, errp, callback, opaque); } else { error_set(errp, QERR_SOCKET_CREATE_FAILED); } qemu_opts_del(opts); return sock; }
SocketAddress *socket_parse(const char *str, Error **errp) { SocketAddress *addr; addr = g_new0(SocketAddress, 1); if (strstart(str, "unix:", NULL)) { if (str[5] == '\0') { error_setg(errp, "invalid Unix socket address"); goto fail; } else { addr->type = SOCKET_ADDRESS_KIND_UNIX; addr->u.q_unix.data = g_new(UnixSocketAddress, 1); addr->u.q_unix.data->path = g_strdup(str + 5); } } else if (strstart(str, "fd:", NULL)) { if (str[3] == '\0') { error_setg(errp, "invalid file descriptor address"); goto fail; } else { addr->type = SOCKET_ADDRESS_KIND_FD; addr->u.fd.data = g_new(String, 1); addr->u.fd.data->str = g_strdup(str + 3); } } else if (strstart(str, "vsock:", NULL)) { addr->type = SOCKET_ADDRESS_KIND_VSOCK; addr->u.vsock.data = vsock_parse(str + strlen("vsock:"), errp); if (addr->u.vsock.data == NULL) { goto fail; } } else { addr->type = SOCKET_ADDRESS_KIND_INET; addr->u.inet.data = inet_parse(str, errp); if (addr->u.inet.data == NULL) { goto fail; } } return addr; fail: qapi_free_SocketAddress(addr); return NULL; }
/** * Create a non-blocking socket and connect it to an address. * Calls the callback function with fd in case of success or -1 in case of * error. * * @str: address string * @callback: callback function that is called when connect completes, * cannot be NULL. * @opaque: opaque for callback function * @errp: set in case of an error * * Returns: -1 on immediate error, file descriptor on success. **/ int inet_nonblocking_connect(const char *str, NonBlockingConnectHandler *callback, void *opaque, Error **errp) { QemuOpts *opts; int sock = -1; InetSocketAddress *addr; g_assert(callback != NULL); addr = inet_parse(str, errp); if (addr != NULL) { opts = qemu_opts_create(&socket_optslist, NULL, 0, &error_abort); inet_addr_to_opts(opts, addr); qapi_free_InetSocketAddress(addr); sock = inet_connect_opts(opts, errp, callback, opaque); qemu_opts_del(opts); } return sock; }
SocketAddress *socket_parse(const char *str, Error **errp) { SocketAddress *addr; addr = g_new0(SocketAddress, 1); if (strstart(str, "unix:", NULL)) { if (str[5] == '\0') { error_setg(errp, "invalid Unix socket address"); goto fail; } else { addr->type = SOCKET_ADDRESS_TYPE_UNIX; addr->u.q_unix.path = g_strdup(str + 5); } } else if (strstart(str, "fd:", NULL)) { if (str[3] == '\0') { error_setg(errp, "invalid file descriptor address"); goto fail; } else { addr->type = SOCKET_ADDRESS_TYPE_FD; addr->u.fd.str = g_strdup(str + 3); } } else if (strstart(str, "vsock:", NULL)) { addr->type = SOCKET_ADDRESS_TYPE_VSOCK; if (vsock_parse(&addr->u.vsock, str + strlen("vsock:"), errp)) { goto fail; } } else { addr->type = SOCKET_ADDRESS_TYPE_INET; if (inet_parse(&addr->u.inet, str, errp)) { goto fail; } } return addr; fail: qapi_free_SocketAddress(addr); return NULL; }
SocketAddress *socket_parse(const char *str, Error **errp) { SocketAddress *addr = NULL; addr = g_new(SocketAddress, 1); if (strstart(str, "unix:", NULL)) { if (str[5] == '\0') { error_setg(errp, "invalid Unix socket address\n"); goto fail; } else { addr->kind = SOCKET_ADDRESS_KIND_UNIX; addr->q_unix = g_new(UnixSocketAddress, 1); addr->q_unix->path = g_strdup(str + 5); } } else if (strstart(str, "fd:", NULL)) { if (str[3] == '\0') { error_setg(errp, "invalid file descriptor address\n"); goto fail; } else { addr->kind = SOCKET_ADDRESS_KIND_FD; addr->fd = g_new(String, 1); addr->fd->str = g_strdup(str + 3); } } else { addr->kind = SOCKET_ADDRESS_KIND_INET; addr->inet = g_new(InetSocketAddress, 1); addr->inet = inet_parse(str, errp); if (addr->inet == NULL) { goto fail; } } return addr; fail: qapi_free_SocketAddress(addr); return NULL; }
static void nbd_parse_filename(const char *filename, QDict *options, Error **errp) { char *file; char *export_name; const char *host_spec; const char *unixpath; if (qdict_haskey(options, "host") || qdict_haskey(options, "port") || qdict_haskey(options, "path")) { error_setg(errp, "host/port/path and a file name may not be specified " "at the same time"); return; } if (strstr(filename, "://")) { int ret = nbd_parse_uri(filename, options); if (ret < 0) { error_setg(errp, "No valid URL specified"); } return; } file = g_strdup(filename); export_name = strstr(file, EN_OPTSTR); if (export_name) { if (export_name[strlen(EN_OPTSTR)] == 0) { goto out; } export_name[0] = 0; /* truncate 'file' */ export_name += strlen(EN_OPTSTR); qdict_put(options, "export", qstring_from_str(export_name)); } /* extract the host_spec - fail if it's not nbd:... */ if (!strstart(file, "nbd:", &host_spec)) { error_setg(errp, "File name string for NBD must start with 'nbd:'"); goto out; } if (!*host_spec) { goto out; } /* are we a UNIX or TCP socket? */ if (strstart(host_spec, "unix:", &unixpath)) { qdict_put(options, "path", qstring_from_str(unixpath)); } else { InetSocketAddress *addr = NULL; addr = inet_parse(host_spec, errp); if (!addr) { goto out; } qdict_put(options, "host", qstring_from_str(addr->host)); qdict_put(options, "port", qstring_from_str(addr->port)); qapi_free_InetSocketAddress(addr); } out: g_free(file); }
/* * function name: parse_candidateRP * input: char *s * output: int (TRUE if the parsing was successful, o.w. FALSE) * operation: parses the candidate RP information. * The general form is: * 'cand_rp <local-addr> [priority <number>] [time <number>]'. */ int parse_candidateRP(char *s) { u_int time = PIM_DEFAULT_CAND_RP_ADV_PERIOD; u_int priority = PIM_DEFAULT_CAND_RP_PRIORITY; char *w; u_int32 local = INADDR_ANY_N; cand_rp_flag = FALSE; my_cand_rp_adv_period = PIM_DEFAULT_CAND_RP_ADV_PERIOD; while (!EQUAL((w = next_word(&s)), "")) { if (EQUAL(w, "priority")) { if (EQUAL((w = next_word(&s)), "")) { logit(LOG_WARNING, 0, "Missing priority; set to default %u (0 is highest)", PIM_DEFAULT_CAND_RP_PRIORITY); priority = PIM_DEFAULT_CAND_RP_PRIORITY; continue; } if (sscanf(w, "%u", &priority) != 1) { logit(LOG_WARNING, 0, "invalid priority %s; set to default %u (0 is highest)", PIM_DEFAULT_CAND_RP_PRIORITY); priority = PIM_DEFAULT_CAND_RP_PRIORITY; } continue; } if (EQUAL(w, "time")) { if (EQUAL((w = next_word(&s)), "")) { logit(LOG_WARNING, 0, "Missing cand_rp_adv_period value; set to default %u", PIM_DEFAULT_CAND_RP_ADV_PERIOD); time = PIM_DEFAULT_CAND_RP_ADV_PERIOD; continue; } if (sscanf(w, "%u", &time) != 1) { logit(LOG_WARNING, 0, "Invalid cand_rp_adv_period value; set to default %u", PIM_DEFAULT_CAND_RP_ADV_PERIOD); time = PIM_DEFAULT_CAND_RP_ADV_PERIOD; continue; } if (time > (my_cand_rp_adv_period = ~0)) time = my_cand_rp_adv_period; /* TODO: XXX: cannot be shorter than 10 seconds (not in the spec)*/ if (time < 10) time = 10; #if 0 if (time > PIM_DEFAULT_CAND_RP_ADV_PERIOD) time = PIM_DEFAULT_CAND_RP_ADV_PERIOD; #endif /* 0 */ my_cand_rp_adv_period = time; continue; } /* Cand-RP address */ local = inet_parse(w, 4); if (!inet_valid_host(local)) { local = max_local_address(); logit(LOG_WARNING, 0, "Invalid Cand-RP address provided '%s' in %s. Will use the largest enabled local address.", w, configfilename); } else if (local_address(local) == NO_VIF) { local = max_local_address(); logit(LOG_WARNING, 0, "Cand-RP address is not local '%s' in %s. Will use the largest enabled local address.", w, configfilename); } } /* while not empty */ if (local == INADDR_ANY_N) { /* If address not provided, use the max. local */ local = max_local_address(); } my_cand_rp_address = local; my_cand_rp_priority = priority; my_cand_rp_adv_period = time; cand_rp_flag = TRUE; logit(LOG_INFO, 0, "Local Cand-RP address is %s", inet_fmt(local, s1, sizeof(s1))); logit(LOG_INFO, 0, "Local Cand-RP priority is %u", priority); logit(LOG_INFO, 0, "Local Cand-RP advertisement period is %u sec.", time); return TRUE; }
/** * parse_rp_address - Parse rp_address config option. * @s: String token. * * This is an extension to the original pimd to add pimd.conf support for static * Rendez-Vous Point addresses. * * The function has been extended by [email protected], of Lintrack, to allow specifying * multicast group addresses as well. * * Format: * rp_address <rp-address> * * Returns: * When parsing @s is successful this function returns %TRUE, otherwise %FALSE. */ int parse_rp_address(char *s) { char *w; u_int32 local = 0xffffff; u_int32 group_addr; u_int32 masklen; struct rp_hold * rph; w = next_word(&s); if (EQUAL(w, "")) { logit(LOG_WARNING, 0, "'rp_address' in %s: no <rp-addr> - ignoring", configfilename); return FALSE; } local = inet_parse(w, 4); if (local == 0xffffff) { logit(LOG_WARNING, 0, "'rp_address' in %s: invalid <rp-addr> provided: '%s'", configfilename, w); return FALSE; } w = next_word(&s); if (!EQUAL(w, "")) { group_addr = inet_parse(w, 4); if (!IN_MULTICAST(ntohl(group_addr))) { logit(LOG_WARNING, 0, "'rp_address' in %s: %s is not a multicast addr", configfilename, inet_fmt(group_addr, s1, sizeof(s1))); return FALSE; } if (EQUAL((w = next_word(&s)), "masklen")) { w = next_word(&s); if (sscanf(w, "%u", &masklen) == 1) { if (masklen > (sizeof(group_addr) * 8)) masklen = (sizeof(group_addr) * 8); else if (masklen < 4) masklen = 4; } else masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; } else masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; } else { group_addr = htonl(224 << 24); masklen = 4; } /* save */ rph = malloc(sizeof(*rph)); rph->address = local; rph->group = group_addr; VAL_TO_MASK(rph->mask, masklen); /* attach at the beginning */ rph->next = g_rp_hold; g_rp_hold = rph; logit(LOG_INFO, 0, "Added static RP: %s, group %s/%d", inet_fmt(local, s1, sizeof(s1)), inet_fmt(group_addr, s2, sizeof(s2)), masklen); return TRUE; }
/** * parse_phyint - Parse physical interface configuration, if any. * @s: String token * * Syntax: * phyint <local-addr | ifname> [disable|enable] * [threshold <t>] [preference <p>] [metric <m>] * [altnet <net-addr>/<masklen>] * [altnet <net-addr> masklen <masklen>] * [scoped <net-addr>/<masklen>] * [scoped <net-addr> masklen <masklen>] * * Returns: * %TRUE if the parsing was successful, o.w. %FALSE */ static int parse_phyint(char *s) { char *w, c; uint32_t local, altnet_addr, scoped_addr; vifi_t vifi; struct uvif *v; u_int n, altnet_masklen = 0, scoped_masklen = 0; struct phaddr *ph; struct vif_acl *v_acl; if (EQUAL((w = next_word(&s)), "")) { WARN("Missing phyint address"); return FALSE; } local = ifname2addr(w); if (!local) { local = inet_parse(w, 4); if (!inet_valid_host(local)) { WARN("Invalid phyint address '%s'", w); return FALSE; } } for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v) { if (vifi == numvifs) { WARN("phyint %s is not a valid interface", inet_fmt(local, s1, sizeof(s1))); return FALSE; } if (local != v->uv_lcl_addr) continue; while (!EQUAL((w = next_word(&s)), "")) { if (EQUAL(w, "disable")) { v->uv_flags |= VIFF_DISABLED; continue; } if (EQUAL(w, "enable")) { v->uv_flags &= ~VIFF_DISABLED; continue; } if (EQUAL(w, "altnet")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing ALTNET for phyint %s", inet_fmt(local, s1, sizeof(s1))); continue; } parse_prefix_len (w, &altnet_masklen); altnet_addr = ifname2addr(w); if (!altnet_addr) { altnet_addr = inet_parse(w, 4); if (!inet_valid_host(altnet_addr)) { WARN("Invalid altnet address '%s'", w); return FALSE; } } if (EQUAL((w = next_word(&s)), "masklen")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing ALTNET masklen for phyint %s", inet_fmt(local, s1, sizeof (s1))); continue; } if (!sscanf(w, "%u", &altnet_masklen)) { WARN("Invalid altnet masklen '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1))); continue; } } ph = (struct phaddr *)calloc(1, sizeof(struct phaddr)); if (!ph) return FALSE; if (altnet_masklen) { VAL_TO_MASK(ph->pa_subnetmask, altnet_masklen); } else { ph->pa_subnetmask = v->uv_subnetmask; } ph->pa_subnet = altnet_addr & ph->pa_subnetmask; ph->pa_subnetbcast = ph->pa_subnet | ~ph->pa_subnetmask; if (altnet_addr & ~ph->pa_subnetmask) WARN("Extra subnet %s/%d has host bits set", inet_fmt(altnet_addr, s1, sizeof(s1)), altnet_masklen); ph->pa_next = v->uv_addrs; v->uv_addrs = ph; logit(LOG_DEBUG, 0, "ALTNET: %s/%d", inet_fmt(altnet_addr, s1, sizeof(s1)), altnet_masklen); } /* altnet */ /* scoped mcast groups/masklen */ if (EQUAL(w, "scoped")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing SCOPED for phyint %s", inet_fmt(local, s1, sizeof(s1))); continue; } parse_prefix_len (w, &scoped_masklen); scoped_addr = ifname2addr(w); if (!scoped_addr) { scoped_addr = inet_parse(w, 4); if (!IN_MULTICAST(ntohl(scoped_addr))) { WARN("Invalid scoped address '%s'", w); return FALSE; } } if (EQUAL((w = next_word(&s)), "masklen")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing SCOPED masklen for phyint %s", inet_fmt(local, s1, sizeof(s1))); continue; } if (sscanf(w, "%u", &scoped_masklen) != 1) { WARN("Invalid scoped masklen '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1))); continue; } } v_acl = (struct vif_acl *)calloc(1, sizeof(struct vif_acl)); if (!v_acl) return FALSE; VAL_TO_MASK(v_acl->acl_mask, scoped_masklen); v_acl->acl_addr = scoped_addr & v_acl->acl_mask; if (scoped_addr & ~v_acl->acl_mask) WARN("Boundary spec %s/%d has host bits set", inet_fmt(scoped_addr, s1, sizeof(s1)),scoped_masklen); v_acl->acl_next = v->uv_acl; v->uv_acl = v_acl; logit(LOG_DEBUG, 0, "SCOPED %s/%x", inet_fmt(v_acl->acl_addr, s1, sizeof(s1)), v_acl->acl_mask); } /* scoped */ if (EQUAL(w, "threshold")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing threshold for phyint %s", inet_fmt(local, s1, sizeof(s1))); continue; } if (sscanf(w, "%u%c", &n, &c) != 1 || n < 1 || n > 255 ) { WARN("Invalid threshold '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1))); continue; } v->uv_threshold = n; continue; } /* threshold */ if (EQUAL(w, "preference")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing preference for phyint %s", inet_fmt(local, s1, sizeof(s1))); continue; } if (sscanf(w, "%u%c", &n, &c) != 1 || n < 1 || n > 255 ) { WARN("Invalid preference '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1))); continue; } IF_DEBUG(DEBUG_ASSERT) { logit(LOG_DEBUG, 0, "Config setting default local preference on %s to %d", inet_fmt(local, s1, sizeof(s1)), n); } v->uv_local_pref = n; continue; } if (EQUAL(w, "metric")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing metric for phyint %s", inet_fmt(local, s1, sizeof(s1))); continue; } if (sscanf(w, "%u%c", &n, &c) != 1 || n < 1 || n > 1024 ) { WARN("Invalid metric '%s' for phyint %s", w, inet_fmt(local, s1, sizeof(s1))); continue; } IF_DEBUG(DEBUG_ASSERT) { logit(LOG_DEBUG, 0, "Setting default local metric on %s to %d", inet_fmt(local, s1, sizeof(s1)), n); } v->uv_local_metric = n; continue; } } /* if not empty */ break; } return TRUE; }
int inet_connect_opts(QemuOpts *opts, Error **errp) { struct addrinfo ai,*res,*e; const char *addr; const char *port; char uaddr[INET6_ADDRSTRLEN+1]; char uport[33]; int sock,rc; bool block; memset(&ai,0, sizeof(ai)); ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; ai.ai_family = PF_UNSPEC; ai.ai_socktype = SOCK_STREAM; addr = qemu_opt_get(opts, "host"); port = qemu_opt_get(opts, "port"); block = qemu_opt_get_bool(opts, "block", 0); if (addr == NULL || port == NULL) { fprintf(stderr, "inet_connect: host and/or port not specified\n"); error_set(errp, QERR_SOCKET_CREATE_FAILED); return -1; } if (qemu_opt_get_bool(opts, "ipv4", 0)) ai.ai_family = PF_INET; if (qemu_opt_get_bool(opts, "ipv6", 0)) ai.ai_family = PF_INET6; /* lookup */ if (0 != (rc = getaddrinfo(addr, port, &ai, &res))) { fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, gai_strerror(rc)); error_set(errp, QERR_SOCKET_CREATE_FAILED); return -1; } for (e = res; e != NULL; e = e->ai_next) { if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen, uaddr,INET6_ADDRSTRLEN,uport,32, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { fprintf(stderr,"%s: getnameinfo: oops\n", __FUNCTION__); continue; } sock = qemu_socket(e->ai_family, e->ai_socktype, e->ai_protocol); if (sock < 0) { fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, inet_strfamily(e->ai_family), strerror(errno)); continue; } setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); if (!block) { socket_set_nonblock(sock); } /* connect to peer */ do { rc = 0; if (connect(sock, e->ai_addr, e->ai_addrlen) < 0) { rc = -socket_error(); } } while (rc == -EINTR); #ifdef _WIN32 if (!block && (rc == -EINPROGRESS || rc == -EWOULDBLOCK || rc == -WSAEALREADY)) { #else if (!block && (rc == -EINPROGRESS)) { #endif error_set(errp, QERR_SOCKET_CONNECT_IN_PROGRESS); } else if (rc < 0) { if (NULL == e->ai_next) fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, inet_strfamily(e->ai_family), e->ai_canonname, uaddr, uport, strerror(errno)); closesocket(sock); sock = -1; continue; } freeaddrinfo(res); return sock; } error_set(errp, QERR_SOCKET_CONNECT_FAILED); freeaddrinfo(res); return -1; } int inet_dgram_opts(QemuOpts *opts) { struct addrinfo ai, *peer = NULL, *local = NULL; const char *addr; const char *port; char uaddr[INET6_ADDRSTRLEN+1]; char uport[33]; int sock = -1, rc; /* lookup peer addr */ memset(&ai,0, sizeof(ai)); ai.ai_flags = AI_CANONNAME | AI_ADDRCONFIG; ai.ai_family = PF_UNSPEC; ai.ai_socktype = SOCK_DGRAM; addr = qemu_opt_get(opts, "host"); port = qemu_opt_get(opts, "port"); if (addr == NULL || strlen(addr) == 0) { addr = "localhost"; } if (port == NULL || strlen(port) == 0) { fprintf(stderr, "inet_dgram: port not specified\n"); return -1; } if (qemu_opt_get_bool(opts, "ipv4", 0)) ai.ai_family = PF_INET; if (qemu_opt_get_bool(opts, "ipv6", 0)) ai.ai_family = PF_INET6; if (0 != (rc = getaddrinfo(addr, port, &ai, &peer))) { fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, gai_strerror(rc)); return -1; } /* lookup local addr */ memset(&ai,0, sizeof(ai)); ai.ai_flags = AI_PASSIVE; ai.ai_family = peer->ai_family; ai.ai_socktype = SOCK_DGRAM; addr = qemu_opt_get(opts, "localaddr"); port = qemu_opt_get(opts, "localport"); if (addr == NULL || strlen(addr) == 0) { addr = NULL; } if (!port || strlen(port) == 0) port = "0"; if (0 != (rc = getaddrinfo(addr, port, &ai, &local))) { fprintf(stderr,"getaddrinfo(%s,%s): %s\n", addr, port, gai_strerror(rc)); return -1; } /* create socket */ sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol); if (sock < 0) { fprintf(stderr,"%s: socket(%s): %s\n", __FUNCTION__, inet_strfamily(peer->ai_family), strerror(errno)); goto err; } setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(void*)&on,sizeof(on)); /* bind socket */ if (getnameinfo((struct sockaddr*)local->ai_addr,local->ai_addrlen, uaddr,INET6_ADDRSTRLEN,uport,32, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); goto err; } if (bind(sock, local->ai_addr, local->ai_addrlen) < 0) { fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__, inet_strfamily(local->ai_family), uaddr, inet_getport(local)); goto err; } /* connect to peer */ if (getnameinfo((struct sockaddr*)peer->ai_addr, peer->ai_addrlen, uaddr, INET6_ADDRSTRLEN, uport, 32, NI_NUMERICHOST | NI_NUMERICSERV) != 0) { fprintf(stderr, "%s: getnameinfo: oops\n", __FUNCTION__); goto err; } if (connect(sock,peer->ai_addr,peer->ai_addrlen) < 0) { fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__, inet_strfamily(peer->ai_family), peer->ai_canonname, uaddr, uport, strerror(errno)); goto err; } freeaddrinfo(local); freeaddrinfo(peer); return sock; err: if (-1 != sock) closesocket(sock); if (local) freeaddrinfo(local); if (peer) freeaddrinfo(peer); return -1; } /* compatibility wrapper */ static int inet_parse(QemuOpts *opts, const char *str) { const char *optstr, *h; char addr[64]; char port[33]; int pos; /* parse address */ if (str[0] == ':') { /* no host given */ addr[0] = '\0'; if (1 != sscanf(str,":%32[^,]%n",port,&pos)) { fprintf(stderr, "%s: portonly parse error (%s)\n", __FUNCTION__, str); return -1; } } else if (str[0] == '[') { /* IPv6 addr */ if (2 != sscanf(str,"[%64[^]]]:%32[^,]%n",addr,port,&pos)) { fprintf(stderr, "%s: ipv6 parse error (%s)\n", __FUNCTION__, str); return -1; } qemu_opt_set(opts, "ipv6", "on"); } else if (qemu_isdigit(str[0])) { /* IPv4 addr */ if (2 != sscanf(str,"%64[0-9.]:%32[^,]%n",addr,port,&pos)) { fprintf(stderr, "%s: ipv4 parse error (%s)\n", __FUNCTION__, str); return -1; } qemu_opt_set(opts, "ipv4", "on"); } else { /* hostname */ if (2 != sscanf(str,"%64[^:]:%32[^,]%n",addr,port,&pos)) { fprintf(stderr, "%s: hostname parse error (%s)\n", __FUNCTION__, str); return -1; } } qemu_opt_set(opts, "host", addr); qemu_opt_set(opts, "port", port); /* parse options */ optstr = str + pos; h = strstr(optstr, ",to="); if (h) qemu_opt_set(opts, "to", h+4); if (strstr(optstr, ",ipv4")) qemu_opt_set(opts, "ipv4", "on"); if (strstr(optstr, ",ipv6")) qemu_opt_set(opts, "ipv6", "on"); return 0; } int inet_listen(const char *str, char *ostr, int olen, int socktype, int port_offset, Error **errp) { QemuOpts *opts; char *optstr; int sock = -1; opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL); if (inet_parse(opts, str) == 0) { sock = inet_listen_opts(opts, port_offset, errp); if (sock != -1 && ostr) { optstr = strchr(str, ','); if (qemu_opt_get_bool(opts, "ipv6", 0)) { snprintf(ostr, olen, "[%s]:%s%s", qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), optstr ? optstr : ""); } else { snprintf(ostr, olen, "%s:%s%s", qemu_opt_get(opts, "host"), qemu_opt_get(opts, "port"), optstr ? optstr : ""); } } } else { error_set(errp, QERR_SOCKET_CREATE_FAILED); } qemu_opts_del(opts); return sock; }
/** * parse_rp_address - Parse rp_address config option. * @s: String token. * * This is an extension to the original pimd to add pimd.conf support for static * Rendez-Vous Point addresses. * * The function has been extended by [email protected], of Lintrack, to allow specifying * multicast group addresses as well. * * Syntax: * rp_address <ADDRESS> [<GROUP>[</LENGTH> masklen <LENGTH>] * * Returns: * When parsing @s is successful this function returns %TRUE, otherwise %FALSE. */ int parse_rp_address(char *s) { char *w; uint32_t local = 0xffffff; uint32_t group_addr = htonl(INADDR_UNSPEC_GROUP); uint32_t masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; u_int dummy; struct rp_hold *rph; /* next is RP addr */ w = next_word(&s); if (EQUAL(w, "")) { logit(LOG_WARNING, 0, "Missing rp_address argument"); return FALSE; } local = inet_parse(w, 4); if (local == 0xffffff) { WARN("Invalid rp_address %s", w); return FALSE; } /* next is group addr if exist */ w = next_word(&s); if (!EQUAL(w, "")) { parse_prefix_len (w, &masklen); group_addr = inet_parse(w, 4); if (!IN_MULTICAST(ntohl(group_addr))) { WARN("%s is not a valid multicast address", inet_fmt(group_addr, s1, sizeof(s1))); return FALSE; } /* next is prefix or priority if exist */ while (!EQUAL((w = next_word(&s)), "")) { if (EQUAL(w, "masklen")) { w = next_word(&s); if (!sscanf(w, "%u", &masklen)) { WARN("Invalid masklen %s. Defaulting to %d)", w, PIM_GROUP_PREFIX_DEFAULT_MASKLEN); masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; } } /* Unused, but keeping for backwards compatibility for people who * may still have this option in their pimd.conf * The priority of a static RP is hardcoded to always be 1, see Juniper's * configuration or similar sources for reference. */ if (EQUAL(w, "priority")) { w = next_word(&s); sscanf(w, "%u", &dummy); WARN("The priority of static RP's is, as of pimd 2.2.0, always 1."); } } } else { group_addr = htonl(INADDR_UNSPEC_GROUP); masklen = PIM_GROUP_PREFIX_MIN_MASKLEN; } validate_prefix_len(&masklen); rph = calloc(1, sizeof(*rph)); if (!rph) { logit(LOG_WARNING, 0, "Out of memory when parsing rp-address %s", inet_fmt(local, s1, sizeof(s1))); return FALSE; } rph->address = local; rph->group = group_addr; VAL_TO_MASK(rph->mask, masklen); /* attach at the beginning */ rph->next = g_rp_hold; g_rp_hold = rph; logit(LOG_INFO, 0, "Local static RP: %s, group %s/%d", inet_fmt(local, s1, sizeof(s1)), inet_fmt(group_addr, s2, sizeof(s2)), masklen); return TRUE; }
/** * parse_candidateRP - Parse candidate Rendez-Vous Point information. * @s: String token * * Syntax: * cand_rp [address | ifname] [priority <0-255>] [time <10-16383>] * * Returns: * %TRUE if the parsing was successful, o.w. %FALSE */ int parse_candidateRP(char *s) { u_int time = PIM_DEFAULT_CAND_RP_ADV_PERIOD; u_int priority = PIM_DEFAULT_CAND_RP_PRIORITY; char *w; uint32_t local = INADDR_ANY_N; cand_rp_flag = FALSE; my_cand_rp_adv_period = PIM_DEFAULT_CAND_RP_ADV_PERIOD; while (!EQUAL((w = next_word(&s)), "")) { if (EQUAL(w, "priority")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing priority, defaulting to %u", w, PIM_DEFAULT_CAND_RP_PRIORITY); priority = PIM_DEFAULT_CAND_RP_PRIORITY; continue; } if (sscanf(w, "%u", &priority) != 1) { WARN("Invalid priority %s, defaulting to %u", w, PIM_DEFAULT_CAND_RP_PRIORITY); priority = PIM_DEFAULT_CAND_RP_PRIORITY; } if (priority > PIM_MAX_CAND_RP_PRIORITY) { WARN("Too high Cand-RP priority %u, defaulting to %d", priority, PIM_MAX_CAND_RP_PRIORITY); priority = PIM_MAX_CAND_RP_PRIORITY; } continue; } if (EQUAL(w, "time")) { if (EQUAL((w = next_word(&s)), "")) { WARN("Missing Cand-RP announce interval, defaulting to %u", PIM_DEFAULT_CAND_RP_ADV_PERIOD); time = PIM_DEFAULT_CAND_RP_ADV_PERIOD; continue; } if (sscanf(w, "%u", &time) != 1) { WARN("Invalid Cand-RP announce interval, defaulting to %u", PIM_DEFAULT_CAND_RP_ADV_PERIOD); time = PIM_DEFAULT_CAND_RP_ADV_PERIOD; continue; } if (time < PIM_MIN_CAND_RP_ADV_PERIOD) time = PIM_MIN_CAND_RP_ADV_PERIOD; if (time > PIM_MAX_CAND_RP_ADV_PERIOD) time = PIM_MAX_CAND_RP_ADV_PERIOD; my_cand_rp_adv_period = time; continue; } /* Cand-RP interface or address */ local = ifname2addr(w); if (!local) local = inet_parse(w, 4); if (!inet_valid_host(local)) { local = max_local_address(); WARN("Invalid Cand-RP address '%s', defaulting to %s", w, inet_fmt(local, s1, sizeof(s1))); } else if (local_address(local) == NO_VIF) { local = max_local_address(); WARN("Cand-RP address '%s' is not local, defaulting to %s", w, inet_fmt(local, s1, sizeof(s1))); } } if (local == INADDR_ANY_N) { /* If address not provided, use the max. local */ local = max_local_address(); } my_cand_rp_address = local; my_cand_rp_priority = priority; my_cand_rp_adv_period = time; cand_rp_flag = TRUE; logit(LOG_INFO, 0, "Local Cand-RP address %s, priority %u, interval %u sec", inet_fmt(local, s1, sizeof(s1)), priority, time); return TRUE; }
/** * parse_rp_address - Parse rp_address config option. * @s: String token. * * This is an extension to the original pimd to add pimd.conf support for static * Rendez-Vous Point addresses. * * The function has been extended by [email protected], of Lintrack, to allow specifying * multicast group addresses as well. * * Syntax: * rp_address <rp-address> [<group-addr>[/masklen>] [priority <number>]] * [<group-addr> [masklen <masklen>] [priority <number>]] * * Returns: * When parsing @s is successful this function returns %TRUE, otherwise %FALSE. */ int parse_rp_address(char *s) { char *w; uint32_t local = 0xffffff; uint32_t group_addr = htonl(INADDR_UNSPEC_GROUP); uint32_t masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; u_int priority = PIM_DEFAULT_CAND_RP_PRIORITY; struct rp_hold *rph; /* next is RP addr */ w = next_word(&s); if (EQUAL(w, "")) { logit(LOG_WARNING, 0, "Missing rp_address argument"); return FALSE; } local = inet_parse(w, 4); if (local == 0xffffff) { WARN("Invalid rp_address %s", w); return FALSE; } /* next is group addr if exist */ w = next_word(&s); if (!EQUAL(w, "")) { parse_prefix_len (w, &masklen); group_addr = inet_parse(w, 4); if (!IN_MULTICAST(ntohl(group_addr))) { WARN("%s is not a valid multicast address", inet_fmt(group_addr, s1, sizeof(s1))); return FALSE; } /* next is prefix or priority if exist */ while (!EQUAL((w = next_word(&s)), "")) { if (EQUAL(w, "masklen")) { w = next_word(&s); if (!sscanf(w, "%u", &masklen)) { WARN("Invalid masklen %s. Defaulting to %d)", w, PIM_GROUP_PREFIX_DEFAULT_MASKLEN); masklen = PIM_GROUP_PREFIX_DEFAULT_MASKLEN; } } if (EQUAL(w, "priority")) { w = next_word(&s); if (sscanf(w, "%u", &priority) == 1) { if (priority > PIM_MAX_CAND_RP_PRIORITY) { WARN("Too large priority %s. Defaulting to %d", w, PIM_MAX_CAND_RP_PRIORITY); priority = PIM_MAX_CAND_RP_PRIORITY; } } else { WARN("Invalid priority %s. Defaulting to %d", w, PIM_DEFAULT_CAND_RP_PRIORITY); priority = PIM_DEFAULT_CAND_RP_PRIORITY; } } } } else { group_addr = htonl(INADDR_UNSPEC_GROUP); masklen = PIM_GROUP_PREFIX_MIN_MASKLEN; priority = 1; } validate_prefix_len (&masklen); rph = calloc(1, sizeof(*rph)); if (!rph) { logit(LOG_WARNING, 0, "Ran out of memory in parse_rp_address()"); return FALSE; } rph->address = local; rph->group = group_addr; VAL_TO_MASK(rph->mask, masklen); rph->priority = priority; /* attach at the beginning */ rph->next = g_rp_hold; g_rp_hold = rph; logit(LOG_INFO, 0, "Added static RP: %s, group %s/%d, priority %d", inet_fmt(local, s1, sizeof(s1)), inet_fmt(group_addr, s2, sizeof(s2)), masklen, priority); return TRUE; }