-------------------------------------------------
- the new oss writer (supported on *BSD and Linux)
+ - support for netmask subsets (Gerrit Renker)
- the new prebuffer filter
- improved signal handling
- variable fec output buffer size
- --log_color actually works
- new ls option: -d (print dates as seconds after the epoch)
+ - update to gengetopt 2.22.2
-----------------------------------------
0.3.4 (2009-05-07) "elliptic inheritance"
* \param addr The address to delete.
* \param netmask The netmask of the entry to be removed from the list.
*/
-static void acl_del_entry(struct list_head *acl, char *addr, int netmask)
+static void acl_del_entry(struct list_head *acl, char *addr, unsigned netmask)
{
struct access_info *ai, *tmp;
+ struct in_addr to_delete;
+
+ inet_pton(AF_INET, addr, &to_delete);
list_for_each_entry_safe(ai, tmp, acl, node) {
- if (!strcmp(addr, inet_ntoa(ai->addr)) &&
- ai->netmask == netmask) {
+
+ if (v4_addr_match(to_delete.s_addr, ai->addr.s_addr,
+ PARA_MIN(netmask, ai->netmask))) {
PARA_NOTICE_LOG("removing %s/%i from access list\n",
addr, ai->netmask);
list_del(&ai->node);
*/
void acl_init(struct list_head *acl, char * const *acl_info, int num)
{
- int i;
+ char addr[16];
+ int mask, i;
INIT_LIST_HEAD(acl);
- for (i = 0; i < num; i++) {
- char *arg = para_strdup(acl_info[i]);
- char *p = strchr(arg, '/');
- int netmask;
-
- if (!p)
- goto err;
- *p = '\0';
- if (!is_valid_ipv4_address(arg))
- goto err;
- netmask = atoi(++p);
- if (netmask < 0 || netmask > 32)
- goto err;
- acl_add_entry(acl, arg, netmask);
- goto success;
-err:
- PARA_CRIT_LOG("syntax error: %s\n", acl_info[i]);
-success:
- free(arg);
- continue;
- }
+ for (i = 0; i < num; i++)
+ if (parse_cidr(acl_info[i], addr, sizeof(addr), &mask) == NULL)
+ PARA_CRIT_LOG("ACL syntax error: %s, ignoring\n",
+ acl_info[i]);
+ else
+ acl_add_entry(acl, addr, mask);
}
/**
return ret;
}
-int com_stat(int fd, __a_unused int argc, __a_unused char **argv)
+int com_stat(int fd, int argc, char **argv)
{
int i, ret;
char *buf = NULL;
- long unsigned mask = ~0LU;
+ uint64_t mask = 0;
+ const uint64_t one = 1;
if (argc > 1) {
- mask = 0;
for (i = 1; i < argc; i++) {
ret = stat_item_valid(argv[i]);
if (ret < 0)
return ret;
- mask |= (1 << ret);
+ mask |= (one << ret);
}
- }
- PARA_INFO_LOG("mask: 0x%lx\n", mask);
- if (mask & (1 << SI_PLAY_TIME)) {
+ } else
+ mask--; /* set all bits */
+ PARA_INFO_LOG("mask: 0x%llx\n", (long long unsigned)mask);
+ if (mask & (one << SI_PLAY_TIME)) {
int slot_num = get_play_time_slot_num();
char *ts = get_time_string(slot_num);
if (ts) {
free(ts);
}
}
- if (mask & (1 << SI_AUDIOD_UPTIME)) {
+ if (mask & (one << SI_AUDIOD_UPTIME)) {
char *tmp, *us = uptime_str();
tmp = make_message("%s: %s\n",
status_item_list[SI_AUDIOD_UPTIME], us);
goto out;
free(tmp);
}
- if (mask & (1 << SI_AUDIOD_STATUS)) {
+ if (mask & (one << SI_AUDIOD_STATUS)) {
char *s = audiod_status_string();
ret = client_write(fd, s);
if (ret < 0)
goto out;
free(s);
}
- if (mask & (1 << SI_DECODER_FLAGS)) {
+ if (mask & (one << SI_DECODER_FLAGS)) {
char *df = decoder_flags();
ret = client_write(fd, df);
if (ret < 0)
}
FOR_EACH_STATUS_ITEM(i) {
char *tmp, *v;
- if (!((1 << i) & mask))
+ if (!((one << i) & mask))
continue;
v = stat_item_values[i];
tmp = make_message("%s%s%s", buf? buf: "",
break;
case SENDER_DENY:
case SENDER_ALLOW:
- if (argc != 4 && argc != 5)
+ if (argc != 4 || parse_cidr(argv[3], scd->host,
+ sizeof(scd->host), &scd->netmask) == NULL)
return -E_COMMAND_SYNTAX;
- if (!is_valid_ipv4_address(argv[3]))
- return -E_COMMAND_SYNTAX;
- scd->netmask = 32;
- if (argc == 5) {
- scd->netmask = atoi(argv[4]);
- if (scd->netmask < 0 || scd->netmask > 32)
- return -E_COMMAND_SYNTAX;
- }
- strncpy(scd->host, argv[3], sizeof(scd->host));
break;
case SENDER_ADD:
case SENDER_DELETE:
{
int i;
struct grab_client_args_info *c = gc->conf;
- char **mv = grab_client_cmdline_parser_mode_values;
+ const char **mv = grab_client_cmdline_parser_mode_values;
PARA_INFO_LOG("filter_num: %d\n", c->filter_num_arg);
for (i = 0; mv[i]; i++)
#include "string.h"
#include "fd.h"
+/**
+ * Parse and validate IPv4 address/netmask string.
+ *
+ * \param cidr Address in CIDR notation
+ * \param addr Copy of the IPv4 address part of \a cidr
+ * \param addrlen Size of \a addr in bytes
+ * \param netmask Value of the netmask part in \a cidr or the
+ * default of 32 if not specified.
+ *
+ * \return Pointer to \a addr if succesful, NULL on error.
+ * \sa RFC 4632
+ */
+char *parse_cidr(const char *cidr,
+ char *addr, ssize_t addrlen,
+ int32_t *netmask)
+{
+ const char *o = cidr;
+ char *c = addr, *end = c + (addrlen - 1);
+
+ *netmask = 0x20;
+
+ if (cidr == NULL || addrlen < 1)
+ goto failed;
+
+ for (o = cidr; (*c = *o == '/'? '\0' : *o); c++, o++)
+ if (c == end)
+ goto failed;
+
+ if (*o == '/')
+ if (para_atoi32(++o, netmask) < 0 ||
+ *netmask < 0 || *netmask > 0x20)
+ goto failed;
+
+ if (is_valid_ipv4_address(addr))
+ return addr;
+failed:
+ *addr = '\0';
+ return NULL;
+}
+
+
/**
* Match string as a candidate IPv4 address.
*
/**
* Functions to parse and validate (parts of) URLs.
*/
+extern char *parse_cidr(const char *cidr,
+ char *addr, ssize_t addrlen, int32_t *netmask);
extern char *parse_url(const char *url,
char *host, ssize_t hostlen, int32_t *port);
/**
int stat_item_valid(const char *item);
int stat_line_valid(const char *);
void stat_client_write(const char *msg, int itemnum);
-int stat_client_add(int fd, long unsigned mask);
+int stat_client_add(int fd, uint64_t mask);
__printf_2_3 void para_log(int, const char*, ...);
{
return make_message(
"usage: {on|off}\n"
- "usage: {allow|deny} IP mask\n"
- "example: allow 127.0.0.1 32\n"
+ "usage: {allow|deny} IP[/netmask]\n"
+ " where mask defaults to 32\n"
+ "example: allow 192.168.0.1/24\n"
);
}
/** The stat client's file descriptor. */
int fd;
/** Bitmask of those status items the client is interested in. */
- long unsigned item_mask;
+ uint64_t item_mask;
/** Its entry in the list of stat clients. */
struct list_head node;
};
* \return Positive value on success, or -E_TOO_MANY_CLIENTS if
* the number of connected clients exceeds #MAX_STAT_CLIENTS.
*/
-int stat_client_add(int fd, long unsigned mask)
+int stat_client_add(int fd, uint64_t mask)
{
struct stat_client *new_client;
{
struct stat_client *sc, *tmp;
size_t len = strlen(msg);
+ const uint64_t one = 1;
if (!initialized || !len)
return;
list_for_each_entry_safe(sc, tmp, &client_list, node) {
int fd = sc->fd, ret;
- if (!((1 << itemnum) & sc->item_mask))
+ if (!((one << itemnum) & sc->item_mask))
continue;
if (write_ok(fd) > 0) {
ret = write(fd, msg, len);