Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • autinerd/experimental-openwrt-24.10
  • experimental
  • feature/addMikrotikwAP
  • master
  • nrb/airmax-test
  • nrb/ar9344-reset-sequence
  • nrb/ex400-remove-wps
  • nrb/gluon-master-cpe510
  • nrb/test-radv-filter
  • nrbffs/fastd-remove-delay
  • nrbffs/netgear-ex6120
  • v2018.2.2-ffs
  • v2018.2.3-ffs
  • v2019.1-ffs
  • v2019.1.1-ffs
  • v2019.1.2-ffs
  • v2020.1-ffs
  • v2020.1.1-ffs
  • v2020.1.3-ffs
  • v2020.2-ffs
  • v2020.2.1-ffs
  • v2020.2.2-ffs
  • v2020.2.3-ffs
  • v2021.1-ffs
  • v2021.1.1-ffs
  • v2021.1.2-ffs
  • v2022.1.1-ffs
  • v2022.1.3-ffs
  • v2022.1.4-ffs
  • v2023.1-ffs
  • v2023.2-ffs
  • v2023.2.2-ffs
  • v2023.2.3-ffs
  • v2023.2.4-ffs
  • v2023.2.5-ffs
  • experimental-2022-09-24
  • experimental-2022-09-24-base
  • experimental-2023-03-11
  • experimental-2023-03-11-base
  • experimental-2023-03-12
  • experimental-2023-03-12-base
  • experimental-2023-03-16
  • experimental-2023-03-16-base
  • experimental-2023-03-20
  • experimental-2023-03-20-base
  • experimental-2023-03-23
  • experimental-2023-03-23-base
  • experimental-2023-03-25
  • experimental-2023-03-25-base
  • experimental-2023-03-26
  • experimental-2023-03-26-base
  • experimental-2023-03-30
  • experimental-2023-03-30-base
  • experimental-2023-03-31
  • experimental-2023-03-31-base
  • experimental-2023-04-01
  • experimental-2023-04-01-base
  • experimental-2023-04-08
  • experimental-2023-04-08-base
  • experimental-2023-04-10
  • experimental-2023-04-10-base
  • experimental-2023-04-13
  • experimental-2023-04-13-base
  • experimental-2023-04-15
  • experimental-2023-04-15-base
  • experimental-2023-04-16
  • experimental-2023-04-16-base
  • experimental-2023-04-18
  • experimental-2023-04-18-base
  • experimental-2023-04-20
  • experimental-2023-04-20-base
  • experimental-2023-04-26
  • experimental-2023-04-26-base
  • experimental-2023-04-28
  • experimental-2023-04-28-base
  • experimental-2023-04-30
  • experimental-2023-04-30-base
  • experimental-2023-05-02
  • experimental-2023-05-02-base
  • experimental-2023-05-03
  • experimental-2023-05-03-base
  • experimental-2023-05-12
  • experimental-2023-05-12-base
  • experimental-2023-05-21
  • experimental-2023-05-21-base
  • experimental-2023-05-25
  • experimental-2023-05-25-base
  • experimental-2023-07-02
  • experimental-2023-07-02-base
  • experimental-2023-07-04
  • experimental-2023-07-04-base
  • experimental-2023-07-12
  • experimental-2023-07-12-base
  • experimental-2023-07-16
  • experimental-2023-07-16-base
  • experimental-2023-08-04
  • experimental-2023-08-04-base
  • experimental-2023-08-10
  • experimental-2023-08-10-base
  • experimental-2023-09-08
  • experimental-2023-09-08-base
  • experimental-2023-09-09
  • experimental-2023-09-09-base
  • experimental-2023-09-10
  • experimental-2023-09-10-base
  • experimental-2023-09-11
  • experimental-2023-09-11-base
  • experimental-2023-09-12
  • experimental-2023-09-12-base
  • experimental-2023-09-13
  • experimental-2023-09-13-base
  • experimental-2023-09-15
  • experimental-2023-09-15-base
  • experimental-2023-09-16
  • experimental-2023-09-16-base
  • experimental-2023-09-18
  • experimental-2023-09-18-base
  • experimental-2023-09-20
  • experimental-2023-09-20-base
  • experimental-2023-09-27
  • experimental-2023-09-27-base
  • experimental-2023-09-28
  • experimental-2023-09-28-base
  • experimental-2023-09-29
  • experimental-2023-09-29-base
  • experimental-2023-10-02
  • experimental-2023-10-02-base
  • experimental-2023-10-13
  • experimental-2023-10-13-base
  • experimental-2023-10-14
  • experimental-2023-10-14-base
  • experimental-2023-10-16
  • experimental-2023-10-16-base
  • experimental-2023-10-23
  • experimental-2023-10-23-base
137 results

Target

Select target project
  • firmware/gluon
  • 0x4A6F/gluon
  • patrick/gluon
3 results
Select Git revision
  • 0x4A6F-master
  • 0x4A6F-rpi4
  • 2014.3.x
  • 2014.4.x
  • babel
  • hoodselector
  • master
  • radv-filterd
  • v2015.1.x
  • v2016.1.x
  • v2016.2.4-batmanbug
  • v2016.2.x
  • v2018.2.2-ffs
  • v2018.2.x
  • v2014.1
  • v2014.2
  • v2014.3
  • v2014.3.1
  • v2014.4
  • v2015.1
  • v2015.1.1
  • v2015.1.2
  • v2016.1
  • v2016.1.1
  • v2016.1.2
  • v2016.1.3
  • v2016.1.4
  • v2016.1.5
  • v2016.1.6
  • v2016.2
  • v2016.2.1
  • v2016.2.2
  • v2016.2.3
  • v2016.2.4
  • v2016.2.5
  • v2016.2.6
  • v2016.2.7
  • v2017.1
  • v2017.1.1
  • v2017.1.2
  • v2017.1.3
  • v2017.1.4
  • v2017.1.5
  • v2017.1.6
  • v2017.1.7
  • v2017.1.8
  • v2018.1
  • v2018.1.1
  • v2018.1.2
  • v2018.1.3
  • v2018.1.4
  • v2018.2
  • v2018.2-ffs0.1
  • v2018.2.1
  • v2018.2.1-ffs0.1
  • v2018.2.2-ffs0.1
56 results
Show changes
Showing
with 2119 additions and 794 deletions
/*
* LuCI Template - Lua library header
*
* Copyright (C) 2009 Jo-Philipp Wich <jow@openwrt.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _TEMPLATE_LUALIB_H_
#define _TEMPLATE_LUALIB_H_
#include "template_parser.h"
#include "template_utils.h"
#include "template_lmo.h"
#define TEMPLATE_LUALIB_META "gluon.web.template.parser"
LUALIB_API int luaopen_gluon_web_template_parser(lua_State *L);
#endif
/*
* LuCI Template - Parser implementation
* gluon-web Template - Parser implementation
*
* Copyright (C) 2009-2012 Jo-Philipp Wich <jow@openwrt.org>
* Copyright (C) 2018 Matthias Schiffer <mschiffer@universe-factory.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -20,110 +21,129 @@
#include "template_utils.h"
#include "template_lmo.h"
#include <lualib.h>
#include <lauxlib.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef enum {
T_TYPE_INIT,
T_TYPE_TEXT,
T_TYPE_COMMENT,
T_TYPE_EXPR,
T_TYPE_EXPR_RAW,
T_TYPE_INCLUDE,
T_TYPE_I18N,
T_TYPE_I18N_RAW,
T_TYPE_CODE,
T_TYPE_EOF,
} t_type_t;
struct template_chunk {
const char *s;
const char *e;
t_type_t type;
int line;
};
/* leading and trailing code for different types */
static const char *const gen_code[9][2] = {
{NULL, NULL},
{"write(\"", "\")"},
{NULL, NULL},
{"write(tostring(", " or \"\"))"},
{"include(\"", "\")"},
{"write(\"", "\")"},
{"write(\"", "\")"},
{NULL, " "},
{}
/* parser state */
struct template_parser {
size_t size;
char *data;
char *off;
char *lua_chunk;
int line;
int in_expr;
bool strip_before;
bool strip_after;
struct template_chunk prv_chunk;
struct template_chunk cur_chunk;
const char *file;
};
/* Simple strstr() like function that takes len arguments for both haystack and needle. */
static char *strfind(char *haystack, int hslen, const char *needle, int ndlen)
{
int match = 0;
int i, j;
for( i = 0; i < hslen; i++ )
{
if( haystack[i] == needle[0] )
{
match = ((ndlen == 1) || ((i + ndlen) <= hslen));
/* leading and trailing code for different types */
static const char *const gen_code[][2] = {
[T_TYPE_INIT] = {NULL, NULL},
[T_TYPE_TEXT] = {"write('", "')"},
[T_TYPE_COMMENT] = {NULL, NULL},
[T_TYPE_EXPR] = {"write(pcdata(tostring(", " or '')))"},
[T_TYPE_EXPR_RAW] = {"write(tostring(", " or ''))"},
[T_TYPE_INCLUDE] = {"include('", "')"},
[T_TYPE_I18N] = {"write(pcdata(translate('", "')))"},
[T_TYPE_I18N_RAW] = {"write(translate('", "'))"},
[T_TYPE_CODE] = {NULL, " "},
[T_TYPE_EOF] = {NULL, NULL},
};
for( j = 1; (j < ndlen) && ((i + j) < hslen); j++ )
{
if( haystack[i+j] != needle[j] )
static struct template_parser * template_init(struct template_parser *parser)
{
match = 0;
break;
}
}
if( match )
return &haystack[i];
}
}
parser->off = parser->data;
parser->cur_chunk.type = T_TYPE_INIT;
parser->cur_chunk.s = parser->data;
parser->cur_chunk.e = parser->data;
return NULL;
return parser;
}
struct template_parser * template_open(const char *file)
{
int fd = -1;
struct stat s;
struct template_parser *parser;
if (!(parser = malloc(sizeof(*parser))))
if (!(parser = calloc(1, sizeof(*parser))))
goto err;
memset(parser, 0, sizeof(*parser));
parser->fd = -1;
parser->file = file;
if (stat(file, &s))
fd = open(file, O_RDONLY|O_CLOEXEC);
if (fd < 0)
goto err;
if ((parser->fd = open(file, O_RDONLY)) < 0)
if (fstat(fd, &s))
goto err;
parser->size = s.st_size;
parser->data = mmap(NULL, parser->size, PROT_READ, MAP_PRIVATE,
parser->fd, 0);
fd, 0);
if (parser->data != MAP_FAILED)
{
parser->off = parser->data;
parser->cur_chunk.type = T_TYPE_INIT;
parser->cur_chunk.s = parser->data;
parser->cur_chunk.e = parser->data;
close(fd);
fd = -1;
return parser;
}
if (parser->data == MAP_FAILED)
goto err;
return template_init(parser);
err:
if (fd >= 0)
close(fd);
template_close(parser);
return NULL;
}
struct template_parser * template_string(const char *str, uint32_t len)
struct template_parser * template_string(const char *str, size_t len)
{
struct template_parser *parser;
if (!str) {
errno = EINVAL;
return NULL;
}
if (!(parser = malloc(sizeof(*parser))))
if (!(parser = calloc(1, sizeof(*parser))))
goto err;
memset(parser, 0, sizeof(*parser));
parser->fd = -1;
parser->size = len;
parser->data = (char *)str;
parser->off = parser->data;
parser->cur_chunk.type = T_TYPE_INIT;
parser->cur_chunk.s = parser->data;
parser->cur_chunk.e = parser->data;
return parser;
return template_init(parser);
err:
template_close(parser);
......@@ -135,16 +155,12 @@ void template_close(struct template_parser *parser)
if (!parser)
return;
if (parser->gc != NULL)
free(parser->gc);
free(parser->lua_chunk);
/* if file is not set, we were parsing a string */
if (parser->file) {
if ((parser->data != NULL) && (parser->data != MAP_FAILED))
munmap(parser->data, parser->size);
if (parser->fd >= 0)
close(parser->fd);
}
free(parser);
......@@ -154,18 +170,14 @@ static void template_text(struct template_parser *parser, const char *e)
{
const char *s = parser->off;
if (s < (parser->data + parser->size))
{
if (parser->strip_after)
{
while ((s <= e) && isspace(*s))
if (s < (parser->data + parser->size)) {
if (parser->strip_after) {
while ((s < e) && isspace(s[0]))
s++;
}
parser->cur_chunk.type = T_TYPE_TEXT;
}
else
{
} else {
parser->cur_chunk.type = T_TYPE_EOF;
}
......@@ -178,23 +190,20 @@ static void template_code(struct template_parser *parser, const char *e)
{
const char *s = parser->off;
parser->strip_before = 0;
parser->strip_after = 0;
parser->strip_before = false;
parser->strip_after = false;
if (*s == '-')
{
parser->strip_before = 1;
for (s++; (s <= e) && (*s == ' ' || *s == '\t'); s++);
if (s < e && s[0] == '-') {
parser->strip_before = true;
s++;
}
if (*(e-1) == '-')
{
parser->strip_after = 1;
for (e--; (e >= s) && (*e == ' ' || *e == '\t'); e--);
if (s < e && e[-1] == '-') {
parser->strip_after = true;
e--;
}
switch (*s)
{
switch (*s) {
/* comment */
case '#':
s++;
......@@ -220,15 +229,20 @@ static void template_code(struct template_parser *parser, const char *e)
break;
/* expr */
case '=':
case '|':
s++;
parser->cur_chunk.type = T_TYPE_EXPR;
break;
/* expr raw */
case '=':
s++;
parser->cur_chunk.type = T_TYPE_EXPR_RAW;
break;
/* code */
default:
parser->cur_chunk.type = T_TYPE_CODE;
break;
}
parser->cur_chunk.line = parser->line;
......@@ -236,133 +250,118 @@ static void template_code(struct template_parser *parser, const char *e)
parser->cur_chunk.e = e;
}
static const char *
template_format_chunk(struct template_parser *parser, size_t *sz)
static void luastr_escape(struct template_buffer *out, const char *s, const char *e)
{
const char *s, *p;
const char *head, *tail;
struct template_chunk *c = &parser->prv_chunk;
struct template_buffer *buf;
for (const char *ptr = s; ptr < e; ptr++) {
switch (*ptr) {
case '\\':
buf_append(out, "\\\\", 2);
break;
*sz = 0;
s = parser->gc = NULL;
case '\'':
buf_append(out, "\\\'", 2);
break;
if (parser->strip_before && c->type == T_TYPE_TEXT)
case '\n':
buf_append(out, "\\n", 2);
break;
default:
buf_putchar(out, *ptr);
}
}
}
static struct template_buffer * template_format_chunk(struct template_parser *parser)
{
while ((c->e > c->s) && isspace(*(c->e - 1)))
const char *p;
const char *head, *tail;
struct template_chunk *c = &parser->prv_chunk;
if (parser->strip_before && c->type == T_TYPE_TEXT) {
while ((c->e > c->s) && isspace(c->e[-1]))
c->e--;
}
/* empty chunk */
if (c->s == c->e)
{
if (c->type == T_TYPE_EOF)
{
*sz = 0;
s = NULL;
}
else
{
*sz = 1;
s = " ";
}
}
return NULL;
/* format chunk */
else if ((buf = buf_init(c->e - c->s)) != NULL)
{
struct template_buffer *buf = buf_init(c->e - c->s);
if (!buf)
return NULL;
if (c->e > c->s) {
if ((head = gen_code[c->type][0]) != NULL)
buf_append(buf, head, strlen(head));
switch (c->type)
{
switch (c->type) {
case T_TYPE_TEXT:
luastr_escape(buf, c->s, c->e - c->s, 0);
case T_TYPE_INCLUDE:
case T_TYPE_I18N:
case T_TYPE_I18N_RAW:
luastr_escape(buf, c->s, c->e);
break;
case T_TYPE_EXPR:
case T_TYPE_EXPR_RAW:
buf_append(buf, c->s, c->e - c->s);
for (p = c->s; p < c->e; p++)
parser->line += (*p == '\n');
break;
case T_TYPE_INCLUDE:
luastr_escape(buf, c->s, c->e - c->s, 0);
break;
case T_TYPE_I18N:
luastr_translate(buf, c->s, c->e - c->s, 1);
break;
case T_TYPE_I18N_RAW:
luastr_translate(buf, c->s, c->e - c->s, 0);
break;
case T_TYPE_CODE:
buf_append(buf, c->s, c->e - c->s);
for (p = c->s; p < c->e; p++)
parser->line += (*p == '\n');
break;
case T_TYPE_INIT:
case T_TYPE_COMMENT:
case T_TYPE_EOF:
break;
}
if ((tail = gen_code[c->type][1]) != NULL)
buf_append(buf, tail, strlen(tail));
*sz = buf_length(buf);
s = parser->gc = buf_destroy(buf);
if (!*sz)
{
*sz = 1;
s = " ";
}
}
return s;
return buf;
}
const char *template_reader(lua_State *L, void *ud, size_t *sz)
const char * template_reader(lua_State *L __attribute__((unused)), void *ud, size_t *sz)
{
struct template_parser *parser = ud;
/* free previous chunk */
free(parser->lua_chunk);
parser->lua_chunk = NULL;
while (true) {
int rem = parser->size - (parser->off - parser->data);
char *tag;
parser->prv_chunk = parser->cur_chunk;
/* free previous string */
if (parser->gc)
{
free(parser->gc);
parser->gc = NULL;
}
/* before tag */
if (!parser->in_expr)
{
if ((tag = strfind(parser->off, rem, "<%", 2)) != NULL)
{
if (!parser->in_expr) {
if ((tag = memmem(parser->off, rem, "<%", 2)) != NULL) {
template_text(parser, tag);
parser->off = tag + 2;
parser->in_expr = 1;
}
else
{
} else {
template_text(parser, parser->data + parser->size);
parser->off = parser->data + parser->size;
}
}
/* inside tag */
else
{
if ((tag = strfind(parser->off, rem, "%>", 2)) != NULL)
{
else {
if ((tag = memmem(parser->off, rem, "%>", 2)) != NULL) {
template_code(parser, tag);
parser->off = tag + 2;
parser->in_expr = 0;
}
else
{
} else {
/* unexpected EOF */
template_code(parser, parser->data + parser->size);
......@@ -371,7 +370,16 @@ const char *template_reader(lua_State *L, void *ud, size_t *sz)
}
}
return template_format_chunk(parser, sz);
struct template_buffer *buf = template_format_chunk(parser);
if (!buf)
return NULL;
*sz = buf_length(buf);
if (*sz) {
parser->lua_chunk = buf_destroy(buf);
return parser->lua_chunk;
}
}
}
int template_error(lua_State *L, struct template_parser *parser)
......@@ -383,33 +391,30 @@ int template_error(lua_State *L, struct template_parser *parser)
int line = 0;
int chunkline = 0;
if ((ptr = strfind((char *)err, strlen(err), "]:", 2)) != NULL)
{
if ((ptr = memmem(err, strlen(err), "]:", 2)) != NULL) {
chunkline = atoi(ptr + 2) - parser->prv_chunk.line;
while (*ptr)
{
if (*ptr++ == ' ')
{
while (*ptr) {
if (*ptr++ == ' ') {
err = ptr;
break;
}
}
}
if (strfind((char *)err, strlen(err), "'char(27)'", 10) != NULL)
{
if (memmem(err, strlen(err), "'char(27)'", 10) != NULL) {
off = parser->data + parser->size;
err = "'%>' expected before end of file";
chunkline = 0;
}
for (ptr = parser->data; ptr < off; ptr++)
for (ptr = parser->data; ptr < off; ptr++) {
if (*ptr == '\n')
line++;
}
snprintf(msg, sizeof(msg), "Syntax error in %s:%d: %s",
parser->file ? parser->file : "[string]", line + chunkline, err ? err : "(unknown error)");
parser->file ?: "[string]", line + chunkline, err ?: "(unknown error)");
lua_pushnil(L);
lua_pushinteger(L, line + chunkline);
......
/*
* LuCI Template - Parser header
* gluon-web Template - Parser header
*
* Copyright (C) 2009 Jo-Philipp Wich <jow@openwrt.org>
* Copyright (C) 2018 Matthias Schiffer <mschiffer@universe-factory.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -19,59 +20,14 @@
#ifndef _TEMPLATE_PARSER_H_
#define _TEMPLATE_PARSER_H_
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
/* code types */
#define T_TYPE_INIT 0
#define T_TYPE_TEXT 1
#define T_TYPE_COMMENT 2
#define T_TYPE_EXPR 3
#define T_TYPE_INCLUDE 4
#define T_TYPE_I18N 5
#define T_TYPE_I18N_RAW 6
#define T_TYPE_CODE 7
#define T_TYPE_EOF 8
struct template_chunk {
const char *s;
const char *e;
int type;
int line;
};
struct template_parser;
/* parser state */
struct template_parser {
int fd;
uint32_t size;
char *data;
char *off;
char *gc;
int line;
int in_expr;
int strip_before;
int strip_after;
struct template_chunk prv_chunk;
struct template_chunk cur_chunk;
const char *file;
};
struct template_parser * template_open(const char *file);
struct template_parser * template_string(const char *str, uint32_t len);
struct template_parser * template_string(const char *str, size_t len);
void template_close(struct template_parser *parser);
const char *template_reader(lua_State *L, void *ud, size_t *sz);
......
/*
* LuCI Template - Utility functions
* gluon-web Template - Utility functions
*
* Copyright (C) 2010 Jo-Philipp Wich <jow@openwrt.org>
* Copyright (C) 2018 Matthias Schiffer <mschiffer@universe-factory.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -19,29 +20,22 @@
#include "template_utils.h"
#include "template_lmo.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* initialize a buffer object */
struct template_buffer * buf_init(int size)
struct template_buffer * buf_init(size_t size)
{
struct template_buffer *buf;
if (size <= 0)
size = 1024;
struct template_buffer *buf = malloc(sizeof(*buf));
buf = (struct template_buffer *)malloc(sizeof(struct template_buffer));
if (buf != NULL)
{
buf->fill = 0;
if (buf != NULL) {
buf->size = size;
buf->data = malloc(buf->size);
if (buf->data != NULL)
{
buf->dptr = buf->data;
buf->data[0] = 0;
if (buf->data != NULL || size == 0)
return buf;
}
free(buf);
}
......@@ -50,57 +44,48 @@ struct template_buffer * buf_init(int size)
}
/* grow buffer */
static int buf_grow(struct template_buffer *buf, int size)
static bool buf_grow(struct template_buffer *buf, size_t len)
{
unsigned int off = (buf->dptr - buf->data);
char *data;
size_t off = buf->dptr - buf->data, left = buf->size - off;
if (len <= left)
return true;
if (size <= 0)
size = 1024;
size_t diff = len - left;
if (diff < 1024)
diff = 1024;
data = realloc(buf->data, buf->size + size);
char *data = realloc(buf->data, buf->size + diff);
if (data == NULL)
return false;
if (data != NULL)
{
buf->data = data;
buf->dptr = data + off;
buf->size += size;
buf->size += diff;
return buf->size;
}
return 0;
return true;
}
/* put one char into buffer object */
static int buf_putchar(struct template_buffer *buf, char c)
bool buf_putchar(struct template_buffer *buf, char c)
{
if( ((buf->fill + 1) >= buf->size) && !buf_grow(buf, 0) )
return 0;
if (!buf_grow(buf, 1))
return false;
*(buf->dptr++) = c;
*(buf->dptr) = 0;
buf->fill++;
return 1;
return true;
}
/* append data to buffer */
int buf_append(struct template_buffer *buf, const char *s, int len)
{
if ((buf->fill + len + 1) >= buf->size)
bool buf_append(struct template_buffer *buf, const char *s, size_t len)
{
if (!buf_grow(buf, len + 1))
return 0;
}
if (!buf_grow(buf, len))
return false;
memcpy(buf->dptr, s, len);
buf->fill += len;
buf->dptr += len;
*(buf->dptr) = 0;
return len;
return true;
}
/* destroy buffer object and return pointer to data */
......@@ -114,7 +99,7 @@ char * buf_destroy(struct template_buffer *buf)
/* calculate the number of expected continuation chars */
static inline int mb_num_chars(unsigned char c)
static inline size_t mb_num_chars(unsigned char c)
{
if ((c & 0xE0) == 0xC0)
return 2;
......@@ -131,14 +116,14 @@ static inline int mb_num_chars(unsigned char c)
}
/* test whether the given byte is a valid continuation char */
static inline int mb_is_cont(unsigned char c)
static inline bool mb_is_cont(unsigned char c)
{
return ((c >= 0x80) && (c <= 0xBF));
}
/* test whether the byte sequence at the given pointer with the given
* length is the shortest possible representation of the code point */
static inline int mb_is_shortest(unsigned char *s, int n)
static inline bool mb_is_shortest(const unsigned char *s, size_t n)
{
switch (n)
{
......@@ -178,19 +163,19 @@ static inline int mb_is_shortest(unsigned char *s, int n)
((*(s+5) >> 6) == 0x02));
}
return 1;
return true;
}
/* test whether the byte sequence at the given pointer with the given
* length is an UTF-16 surrogate */
static inline int mb_is_surrogate(unsigned char *s, int n)
static inline bool mb_is_surrogate(const unsigned char *s, size_t n)
{
return ((n == 3) && (*s == 0xED) && (*(s+1) >= 0xA0) && (*(s+1) <= 0xBF));
}
/* test whether the byte sequence at the given pointer with the given
* length is an illegal UTF-8 code point */
static inline int mb_is_illegal(unsigned char *s, int n)
static inline bool mb_is_illegal(const unsigned char *s, size_t n)
{
return ((n == 3) && (*s == 0xEF) && (*(s+1) == 0xBF) &&
(*(s+2) >= 0xBE) && (*(s+2) <= 0xBF));
......@@ -199,14 +184,13 @@ static inline int mb_is_illegal(unsigned char *s, int n)
/* scan given source string, validate UTF-8 sequence and store result
* in given buffer object */
static int validate_utf8(unsigned char **s, int l, struct template_buffer *buf)
static size_t validate_utf8(const unsigned char **s, size_t l, struct template_buffer *buf)
{
unsigned char *ptr = *s;
unsigned int o = 0, v, n;
const unsigned char *ptr = *s;
size_t o = 0, v, n;
/* ascii byte without null */
if ((*(ptr+0) >= 0x01) && (*(ptr+0) <= 0x7F))
{
if ((*(ptr+0) >= 0x01) && (*(ptr+0) <= 0x7F)) {
if (!buf_putchar(buf, *ptr++))
return 0;
......@@ -214,8 +198,7 @@ static int validate_utf8(unsigned char **s, int l, struct template_buffer *buf)
}
/* multi byte sequence */
else if ((n = mb_num_chars(*ptr)) > 1)
{
else if ((n = mb_num_chars(*ptr)) > 1) {
/* count valid chars */
for (v = 1; (v <= n) && ((o+v) < l) && mb_is_cont(*(ptr+v)); v++);
......@@ -237,7 +220,7 @@ static int validate_utf8(unsigned char **s, int l, struct template_buffer *buf)
!mb_is_surrogate(ptr, n) && !mb_is_illegal(ptr, n))
{
/* copy sequence */
if (!buf_append(buf, (char *)ptr, n))
if (!buf_append(buf, (const char *)ptr, n))
return 0;
}
......@@ -252,14 +235,13 @@ static int validate_utf8(unsigned char **s, int l, struct template_buffer *buf)
break;
}
/* advance beyound the last found valid continuation char */
/* advance beyond the last found valid continuation char */
o = v;
ptr += v;
}
/* invalid byte (0x00) */
else
{
else {
if (!buf_putchar(buf, '?')) /* or 0xEF, 0xBF, 0xBD */
return 0;
......@@ -274,35 +256,32 @@ static int validate_utf8(unsigned char **s, int l, struct template_buffer *buf)
/* Sanitize given string and strip all invalid XML bytes
* Validate UTF-8 sequences
* Escape XML control chars */
char * pcdata(const char *s, unsigned int l)
bool pcdata(const char *s, size_t l, char **out, size_t *outl)
{
struct template_buffer *buf = buf_init(l);
unsigned char *ptr = (unsigned char *)s;
unsigned int o, v;
const unsigned char *ptr = (const unsigned char *)s;
size_t o, v;
char esq[8];
int esl;
if (!buf)
return NULL;
return false;
for (o = 0; o < l; o++)
{
for (o = 0; o < l; o++) {
/* Invalid XML bytes */
if (((*ptr >= 0x00) && (*ptr <= 0x08)) ||
if ((*ptr <= 0x08) ||
((*ptr >= 0x0B) && (*ptr <= 0x0C)) ||
((*ptr >= 0x0E) && (*ptr <= 0x1F)) ||
(*ptr == 0x7F))
{
(*ptr == 0x7F)) {
ptr++;
}
/* Escapes */
else if ((*ptr == 0x26) ||
(*ptr == 0x27) ||
(*ptr == 0x22) ||
(*ptr == 0x3C) ||
(*ptr == 0x3E))
{
else if ((*ptr == '\'') ||
(*ptr == '"') ||
(*ptr == '&') ||
(*ptr == '<') ||
(*ptr == '>')) {
esl = snprintf(esq, sizeof(esq), "&#%i;", *ptr);
if (!buf_append(buf, esq, esl))
......@@ -312,14 +291,12 @@ char * pcdata(const char *s, unsigned int l)
}
/* ascii char */
else if (*ptr <= 0x7F)
{
else if (*ptr <= 0x7F) {
buf_putchar(buf, (char)*ptr++);
}
/* multi byte sequence */
else
{
else {
if (!(v = validate_utf8(&ptr, l - o, buf)))
break;
......@@ -327,58 +304,7 @@ char * pcdata(const char *s, unsigned int l)
}
}
return buf_destroy(buf);
}
void luastr_escape(struct template_buffer *out, const char *s, unsigned int l, int escape_xml)
{
int esl;
char esq[8];
char *ptr;
for (ptr = (char *)s; ptr < (s + l); ptr++)
{
switch (*ptr)
{
case '\\':
buf_append(out, "\\\\", 2);
break;
case '"':
if (escape_xml)
buf_append(out, "&#34;", 5);
else
buf_append(out, "\\\"", 2);
break;
case '\n':
buf_append(out, "\\n", 2);
break;
case '\'':
case '&':
case '<':
case '>':
if (escape_xml)
{
esl = snprintf(esq, sizeof(esq), "&#%i;", *ptr);
buf_append(out, esq, esl);
break;
}
default:
buf_putchar(out, *ptr);
}
}
}
void luastr_translate(struct template_buffer *out, const char *s, unsigned int l, int escape_xml)
{
char *tr;
int trlen;
if (!lmo_translate(s, l, &tr, &trlen))
luastr_escape(out, tr, trlen, escape_xml);
else
luastr_escape(out, s, l, escape_xml);
*outl = buf_length(buf);
*out = buf_destroy(buf);
return true;
}
/*
* LuCI Template - Utility header
* gluon-web Template - Utility header
*
* Copyright (C) 2010-2012 Jo-Philipp Wich <jow@openwrt.org>
* Copyright (C) 2018 Matthias Schiffer <mschiffer@universe-factory.net>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -19,33 +20,28 @@
#ifndef _TEMPLATE_UTILS_H_
#define _TEMPLATE_UTILS_H_
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stddef.h>
/* buffer object */
struct template_buffer {
char *data;
char *dptr;
unsigned int size;
unsigned int fill;
size_t size;
};
struct template_buffer * buf_init(int size);
int buf_append(struct template_buffer *buf, const char *s, int len);
struct template_buffer * buf_init(size_t size);
bool buf_putchar(struct template_buffer *buf, char c);
bool buf_append(struct template_buffer *buf, const char *s, size_t len);
char * buf_destroy(struct template_buffer *buf);
/* read buffer length */
static inline int buf_length(struct template_buffer *buf)
static inline size_t buf_length(const struct template_buffer *buf)
{
return buf->fill;
return buf->dptr - buf->data;
}
char * pcdata(const char *s, unsigned int l);
void luastr_escape(struct template_buffer *out, const char *s, unsigned int l, int escape_xml);
void luastr_translate(struct template_buffer *out, const char *s, unsigned int l, int escape_xml);
bool pcdata(const char *s, size_t l, char **out, size_t *outl);
#endif
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-wireless-encryption-wpa3
include ../gluon.mk
define Package/gluon-wireless-encryption-wpa3
DEPENDS:=+hostapd-mbedtls
TITLE:=Package for supporting WPA3 encrypted wireless networks
endef
define Package/gluon-wireless-encryption-wpa3/install
$(INSTALL_DIR) $(1)/lib/gluon/features
touch $(1)/lib/gluon/features/wpa2
touch $(1)/lib/gluon/features/wpa3
endef
$(eval $(call BuildPackageGluon,gluon-wireless-encryption-wpa3))
# Dependencies for LuaSrcDiet
PKG_BUILD_DEPENDS += luci-base/host
GLUON_MK := $(abspath $(lastword $(MAKEFILE_LIST)))
PKG_FILE_DEPENDS += $(GLUON_MK)
PKG_VERSION ?= 1
PKG_BUILD_DEPENDS += luasrcdiet/host
ifneq ($(wildcard ./luasrc/.),)
PKG_CONFIG_DEPENDS += CONFIG_GLUON_MINIFY
endif
ifneq ($(wildcard ./src/respondd.c),)
PKG_BUILD_DEPENDS += respondd
endif
include $(INCLUDE_DIR)/package.mk
# Annoyingly, make's shell function replaces all newlines with spaces, so we have to do some escaping work. Yuck.
define GluonCheckSite
[ -z "$$IPKG_INSTROOT" ] || sed -e 's/-@/\n/g' -e 's/+@/@/g' <<'END__GLUON__CHECK__SITE' | "${TOPDIR}/staging_dir/hostpkg/bin/lua" -e 'dofile()'
local f = assert(io.open(os.getenv('IPKG_INSTROOT') .. '/lib/gluon/site.json'))
local site_json = f:read('*a')
f:close()
shell-escape = $(shell $(1) | sed -ne '1h; 1!H; $$ {g; s/@/@1/g; s/\n/@2/g; p}')
shell-unescape = $(subst @1,@,$(subst @2,$(newline),$(1)))
shell-verbatim = $(call shell-unescape,$(call shell-escape,$(1)))
site = require('cjson').decode(site_json)
$(shell cat '$(TOPDIR)/../scripts/check_site_lib.lua' '$(1)' | sed -ne '1h; 1!H; $$ {g; s/@/+@/g; s/\n/-@/g; p}')
define GluonCheckSite
[ -z "$$STAGING_DIR_HOSTPKG" ] || PATH="$$STAGING_DIR_HOSTPKG/bin:$$PATH"
lua "$$IPKG_INSTROOT/lib/gluon/check-site.lua" <<'END__GLUON__CHECK__SITE'
$(call shell-verbatim,cat '$(1)')
END__GLUON__CHECK__SITE
endef
......@@ -22,22 +36,27 @@ GLUON_LANG_fr := French
GLUON_I18N_CONFIG := $(foreach lang,$(GLUON_SUPPORTED_LANGS),CONFIG_GLUON_WEB_LANG_$(lang))
GLUON_ENABLED_LANGS := en $(foreach lang,$(GLUON_SUPPORTED_LANGS),$(if $(CONFIG_GLUON_WEB_LANG_$(lang)),$(lang)))
ifneq ($(wildcard ./i18n/.),)
PKG_BUILD_DEPENDS += gluon-web/host
PKG_CONFIG_DEPENDS += $(GLUON_I18N_CONFIG)
endif
define GluonBuildI18N
mkdir -p $$(PKG_BUILD_DIR)/i18n
for lang in $$(GLUON_ENABLED_LANGS); do \
if [ -e $(2)/$$$$lang.po ]; then \
rm -f $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo; \
po2lmo $(2)/$$$$lang.po $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo; \
if [ -e $(1)/$$$$lang.po ]; then \
rm -f $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo; \
gluon-po2lmo $(1)/$$$$lang.po $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo; \
fi; \
done
endef
define GluonInstallI18N
$$(INSTALL_DIR) $(2)/lib/gluon/web/i18n
$$(INSTALL_DIR) $(1)/lib/gluon/web/i18n
for lang in $$(GLUON_ENABLED_LANGS); do \
if [ -e $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo ]; then \
$$(INSTALL_DATA) $$(PKG_BUILD_DIR)/i18n/$(1).$$$$lang.lmo $(2)/lib/gluon/web/i18n/$(1).$$$$lang.lmo; \
if [ -e $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo ]; then \
$$(INSTALL_DATA) $$(PKG_BUILD_DIR)/i18n/$$$$lang.lmo $(1)/lib/gluon/web/i18n/$(PKG_NAME).$$$$lang.lmo; \
fi; \
done
endef
......@@ -45,10 +64,66 @@ endef
define GluonSrcDiet
rm -rf $(2)
$(CP) $(1) $(2)
$(FIND) $(2) -type f | while read src; do \
if LuaSrcDiet --noopt-binequiv -o "$$$$src.o" "$$$$src"; then \
chmod $$$$(stat -c%a "$$$$src") "$$$$src.o"; \
mv "$$$$src.o" "$$$$src"; \
fi; \
ifdef CONFIG_GLUON_MINIFY
# Use cp + rm instead of mv to preserve destination permissions
set -e; $(FIND) $(2) -type f | while read src; do \
echo "Minifying $$$$src..."; \
luasrcdiet --noopt-binequiv -o "$$$$src.tmp" "$$$$src"; \
cp "$$$$src.tmp" "$$$$src"; \
rm "$$$$src.tmp"; \
done
endif
endef
define Gluon/Build/Compile
$(if $(wildcard ./src/Makefile ./src/CMakeLists.txt),
$(Build/Compile/Default)
)
$(if $(wildcard ./luasrc/.),
$(call GluonSrcDiet,luasrc,$(PKG_BUILD_DIR)/luadest/)
)
$(if $(wildcard ./i18n/.),
$(call GluonBuildI18N,i18n)
)
endef
define Gluon/Build/Install
$(if $(findstring $(PKG_INSTALL),1),
$(CP) $(PKG_INSTALL_DIR)/. $(1)/
)
$(if $(wildcard ./files/.),
$(CP) ./files/. $(1)/
)
$(if $(wildcard ./luasrc/.),
$(CP) $(PKG_BUILD_DIR)/luadest/. $(1)/
)
$(if $(wildcard ./src/respondd.c),
$(INSTALL_DIR) $(1)/usr/lib/respondd
$(CP) $(PKG_BUILD_DIR)/respondd.so $(1)/usr/lib/respondd/$(PKG_NAME).so
)
$(if $(wildcard ./i18n/.),
$(GluonInstallI18N)
)
endef
Build/Compile=$(call Gluon/Build/Compile)
define BuildPackageGluon
define Package/$(1) :=
SECTION:=gluon
CATEGORY:=Gluon
$$(Package/$(1))
endef
Package/$(1)/install ?= $$(Gluon/Build/Install)
ifneq ($(wildcard check_site.lua),)
define Package/$(1)/postinst
#!/bin/sh
$$(call GluonCheckSite,check_site.lua)
endef
endif
$$(eval $$(call BuildPackage,$(1)))
endef
# SPDX-License-Identifier: MIT
#
# batman-adv helpers functions library
#
# Copyright (c) 2017, Sven Eckelmann <sven@narfation.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
include $(TOPDIR)/rules.mk
PKG_NAME:=libbatadv
PKG_VERSION:=1
PKG_LICENSE:=MIT
PKG_INSTALL:=1
include $(INCLUDE_DIR)/package.mk
define Package/libbatadv
SECTION:=libs
CATEGORY:=Libraries
TITLE:=batman-adv helpers functions
DEPENDS:=+libnl-tiny
endef
TARGET_CFLAGS += -flto -ffunction-sections -fdata-sections
TARGET_LDFLAGS += -fuse-linker-plugin -Wl,--gc-sections
MAKE_VARS += \
LIBNL_NAME="libnl-tiny" \
LIBNL_GENL_NAME="libnl-tiny"
MAKE_ARGS += \
PREFIX=/usr
MAKE_INSTALL_FLAGS += \
PREFIX=/usr
define Package/libbatadv/install
$(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_INSTALL_DIR)/usr/lib/libbatadv.so $(1)/usr/lib/
endef
define Build/InstallDev
$(INSTALL_DIR) $(1)
$(CP) $(PKG_INSTALL_DIR)/* $(1)/
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig/
$(CP) ./files/libbatadv.pc $(1)/usr/lib/pkgconfig/
endef
$(eval $(call BuildPackage,libbatadv))
# SPDX-License-Identifier: MIT
#
# batman-adv helpers functions library
#
# Copyright (c) 2017, Sven Eckelmann <sven@narfation.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
prefix=/usr
exec_prefix=/usr
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: libbatadv
Version: 1
Description: batman-adv helpers functions
Requires.private: libnl-tiny
Libs: -lbatadv
Libs.private:
Cflags:
#!/usr/bin/make -f
# SPDX-License-Identifier: MIT
#
# batman-adv helpers functions library
#
# Copyright (c) 2017, Sven Eckelmann <sven@narfation.org>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# libbatadv build
BINARY_NAME = libbatadv.so
OBJ += batadv-genl.o
# headers to install
HEADER += batadv-genl.h
HEADER += batman_adv.h
# libbatadv flags and options
CFLAGS += -pedantic -Wall -W -MD -MP
CFLAGS += -fPIC -fvisibility=hidden
CPPFLAGS += -D_GNU_SOURCE
LDLIBS +=
LDFLAGS += -shared -Wl,-export-dynamic
# disable verbose output
ifneq ($(findstring $(MAKEFLAGS),s),s)
ifndef V
Q_CC = @echo ' ' CC $@;
Q_LD = @echo ' ' LD $@;
export Q_CC
export Q_LD
endif
endif
ifeq ($(origin PKG_CONFIG), undefined)
PKG_CONFIG = pkg-config
ifeq ($(shell which $(PKG_CONFIG) 2>/dev/null),)
$(error $(PKG_CONFIG) not found)
endif
endif
ifeq ($(origin LIBNL_CFLAGS) $(origin LIBNL_LDLIBS), undefined undefined)
LIBNL_NAME ?= libnl-3.0
ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_NAME) 2>/dev/null),)
$(error No $(LIBNL_NAME) development libraries found!)
endif
LIBNL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_NAME))
LIBNL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBNL_NAME))
endif
CFLAGS += $(LIBNL_CFLAGS)
LDLIBS += $(LIBNL_LDLIBS)
ifeq ($(origin LIBNL_GENL_CFLAGS) $(origin LIBNL_GENL_LDLIBS), undefined undefined)
LIBNL_GENL_NAME ?= libnl-genl-3.0
ifeq ($(shell $(PKG_CONFIG) --modversion $(LIBNL_GENL_NAME) 2>/dev/null),)
$(error No $(LIBNL_GENL_NAME) development libraries found!)
endif
LIBNL_GENL_CFLAGS += $(shell $(PKG_CONFIG) --cflags $(LIBNL_GENL_NAME))
LIBNL_GENL_LDLIBS += $(shell $(PKG_CONFIG) --libs $(LIBNL_GENL_NAME))
endif
CFLAGS += $(LIBNL_GENL_CFLAGS)
LDLIBS += $(LIBNL_GENL_LDLIBS)
# standard build tools
CC ?= gcc
RM ?= rm -f
INSTALL ?= install
MKDIR ?= mkdir -p
COMPILE.c = $(Q_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
LINK.o = $(Q_LD)$(CC) $(CFLAGS) $(LDFLAGS) $(TARGET_ARCH)
# standard install paths
PREFIX = /usr/local
INCLUDEDIR = $(PREFIX)/include
LIBDIR = $(PREFIX)/lib
# default target
all: $(BINARY_NAME)
# standard build rules
.SUFFIXES: .o .c
.c.o:
$(COMPILE.c) -o $@ $<
$(BINARY_NAME): $(OBJ)
$(LINK.o) $^ $(LDLIBS) -o $@
clean:
$(RM) $(BINARY_NAME) $(OBJ) $(DEP)
install: $(BINARY_NAME)
$(MKDIR) $(DESTDIR)$(LIBDIR)
$(MKDIR) $(DESTDIR)$(INCLUDEDIR)
$(INSTALL) -m 0755 $(BINARY_NAME) $(DESTDIR)$(LIBDIR)
$(INSTALL) -m 0644 $(HEADER) $(DESTDIR)$(INCLUDEDIR)
# load dependencies
DEP = $(OBJ:.o=.d)
-include $(DEP)
.PHONY: all clean install
.DELETE_ON_ERROR:
.DEFAULT_GOAL := all
// SPDX-License-Identifier: MIT
/* batman-adv helpers functions library
*
* Copyright (c) 2017, Sven Eckelmann <sven@narfation.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "batadv-genl.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <net/ethernet.h>
#include "batman_adv.h"
__attribute__ ((visibility ("default")))
struct nla_policy batadv_genl_policy[NUM_BATADV_ATTR] = {
[BATADV_ATTR_VERSION] = {
.type = NLA_STRING,
},
[BATADV_ATTR_ALGO_NAME] = {
.type = NLA_STRING,
},
[BATADV_ATTR_MESH_IFINDEX] = {
.type = NLA_U32,
},
[BATADV_ATTR_MESH_IFNAME] = {
.type = NLA_STRING,
.maxlen = IFNAMSIZ,
},
[BATADV_ATTR_MESH_ADDRESS] = {
.type = NLA_UNSPEC,
.minlen = ETH_ALEN,
.maxlen = ETH_ALEN,
},
[BATADV_ATTR_HARD_IFINDEX] = {
.type = NLA_U32,
},
[BATADV_ATTR_HARD_IFNAME] = {
.type = NLA_STRING,
.maxlen = IFNAMSIZ,
},
[BATADV_ATTR_HARD_ADDRESS] = {
.type = NLA_UNSPEC,
.minlen = ETH_ALEN,
.maxlen = ETH_ALEN,
},
[BATADV_ATTR_ORIG_ADDRESS] = {
.type = NLA_UNSPEC,
.minlen = ETH_ALEN,
.maxlen = ETH_ALEN,
},
[BATADV_ATTR_TPMETER_RESULT] = {
.type = NLA_U8,
},
[BATADV_ATTR_TPMETER_TEST_TIME] = {
.type = NLA_U32,
},
[BATADV_ATTR_TPMETER_BYTES] = {
.type = NLA_U64,
},
[BATADV_ATTR_TPMETER_COOKIE] = {
.type = NLA_U32,
},
[BATADV_ATTR_PAD] = {
.type = NLA_UNSPEC,
},
[BATADV_ATTR_ACTIVE] = {
.type = NLA_FLAG,
},
[BATADV_ATTR_TT_ADDRESS] = {
.type = NLA_UNSPEC,
.minlen = ETH_ALEN,
.maxlen = ETH_ALEN,
},
[BATADV_ATTR_TT_TTVN] = {
.type = NLA_U8,
},
[BATADV_ATTR_TT_LAST_TTVN] = {
.type = NLA_U8,
},
[BATADV_ATTR_TT_CRC32] = {
.type = NLA_U32,
},
[BATADV_ATTR_TT_VID] = {
.type = NLA_U16,
},
[BATADV_ATTR_TT_FLAGS] = {
.type = NLA_U32,
},
[BATADV_ATTR_FLAG_BEST] = {
.type = NLA_FLAG,
},
[BATADV_ATTR_LAST_SEEN_MSECS] = {
.type = NLA_U32,
},
[BATADV_ATTR_NEIGH_ADDRESS] = {
.type = NLA_UNSPEC,
.minlen = ETH_ALEN,
.maxlen = ETH_ALEN,
},
[BATADV_ATTR_TQ] = {
.type = NLA_U8,
},
[BATADV_ATTR_THROUGHPUT] = {
.type = NLA_U32,
},
[BATADV_ATTR_BANDWIDTH_UP] = {
.type = NLA_U32,
},
[BATADV_ATTR_BANDWIDTH_DOWN] = {
.type = NLA_U32,
},
[BATADV_ATTR_ROUTER] = {
.type = NLA_UNSPEC,
.minlen = ETH_ALEN,
.maxlen = ETH_ALEN,
},
[BATADV_ATTR_BLA_OWN] = {
.type = NLA_FLAG,
},
[BATADV_ATTR_BLA_ADDRESS] = {
.type = NLA_UNSPEC,
.minlen = ETH_ALEN,
.maxlen = ETH_ALEN,
},
[BATADV_ATTR_BLA_VID] = {
.type = NLA_U16,
},
[BATADV_ATTR_BLA_BACKBONE] = {
.type = NLA_UNSPEC,
.minlen = ETH_ALEN,
.maxlen = ETH_ALEN,
},
[BATADV_ATTR_BLA_CRC] = {
.type = NLA_U16,
},
[BATADV_ATTR_DAT_CACHE_IP4ADDRESS] = {
.type = NLA_U32,
},
[BATADV_ATTR_DAT_CACHE_HWADDRESS] = {
.type = NLA_UNSPEC,
.minlen = ETH_ALEN,
.maxlen = ETH_ALEN,
},
[BATADV_ATTR_DAT_CACHE_VID] = {
.type = NLA_U16,
},
[BATADV_ATTR_MCAST_FLAGS] = {
.type = NLA_U32,
},
[BATADV_ATTR_MCAST_FLAGS_PRIV] = {
.type = NLA_U32,
},
[BATADV_ATTR_VLANID] = {
.type = NLA_U16,
},
[BATADV_ATTR_AGGREGATED_OGMS_ENABLED] = {
.type = NLA_U8,
},
[BATADV_ATTR_AP_ISOLATION_ENABLED] = {
.type = NLA_U8,
},
[BATADV_ATTR_ISOLATION_MARK] = {
.type = NLA_U32,
},
[BATADV_ATTR_ISOLATION_MASK] = {
.type = NLA_U32,
},
[BATADV_ATTR_BONDING_ENABLED] = {
.type = NLA_U8,
},
[BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED] = {
.type = NLA_U8,
},
[BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED] = {
.type = NLA_U8,
},
[BATADV_ATTR_FRAGMENTATION_ENABLED] = {
.type = NLA_U8,
},
[BATADV_ATTR_GW_BANDWIDTH_DOWN] = {
.type = NLA_U32,
},
[BATADV_ATTR_GW_BANDWIDTH_UP] = {
.type = NLA_U32,
},
[BATADV_ATTR_GW_MODE] = {
.type = NLA_U8,
},
[BATADV_ATTR_GW_SEL_CLASS] = {
.type = NLA_U32,
},
[BATADV_ATTR_HOP_PENALTY] = {
.type = NLA_U8,
},
[BATADV_ATTR_LOG_LEVEL] = {
.type = NLA_U32,
},
[BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED] = {
.type = NLA_U8,
},
[BATADV_ATTR_NETWORK_CODING_ENABLED] = {
.type = NLA_U8,
},
[BATADV_ATTR_ORIG_INTERVAL] = {
.type = NLA_U32,
},
[BATADV_ATTR_ELP_INTERVAL] = {
.type = NLA_U32,
},
[BATADV_ATTR_THROUGHPUT_OVERRIDE] = {
.type = NLA_U32,
},
[BATADV_ATTR_MULTICAST_FANOUT] = {
.type = NLA_U32,
},
};
/**
* nlquery_error_cb() - Store error value in &batadv_nlquery_opts->error and
* stop processing
* @nla: netlink address of the peer
* @nlerr: netlink error message being processed
* @arg: &struct batadv_nlquery_opts given to batadv_genl_query()
*
* Return: Always NL_STOP
*/
static int nlquery_error_cb(struct sockaddr_nl *nla __attribute__((unused)),
struct nlmsgerr *nlerr, void *arg)
{
struct batadv_nlquery_opts *query_opts = arg;
query_opts->err = nlerr->error;
return NL_STOP;
}
/**
* nlquery_stop_cb() - Store error value in &batadv_nlquery_opts->error and
* stop processing
* @msg: netlink message being processed
* @arg: &struct batadv_nlquery_opts given to batadv_genl_query()
*
* Return: Always NL_STOP
*/
static int nlquery_stop_cb(struct nl_msg *msg, void *arg)
{
struct nlmsghdr *nlh = nlmsg_hdr(msg);
struct batadv_nlquery_opts *query_opts = arg;
int *error = nlmsg_data(nlh);
if (*error)
query_opts->err = *error;
return NL_STOP;
}
/**
* batadv_genl_query() - Start a common batman-adv generic netlink query
* @mesh_iface: name of the batman-adv mesh interface
* @nl_cmd: &enum batadv_nl_commands which should be sent to kernel
* @callback: receive callback for valid messages
* @flags: additional netlink message header flags
* @query_opts: pointer to &struct batadv_nlquery_opts which is used to save
* the current processing state. This is given as arg to @callback
*
* Return: 0 on success or negative error value otherwise
*/
__attribute__ ((visibility ("default")))
int batadv_genl_query(const char *mesh_iface, enum batadv_nl_commands nl_cmd,
nl_recvmsg_msg_cb_t callback, int flags,
struct batadv_nlquery_opts *query_opts)
{
struct nl_sock *sock;
struct nl_msg *msg;
struct nl_cb *cb;
int ifindex;
int family;
int ret;
query_opts->err = 0;
sock = nl_socket_alloc();
if (!sock)
return -ENOMEM;
ret = genl_connect(sock);
if (ret < 0) {
query_opts->err = ret;
goto err_free_sock;
}
family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
if (family < 0) {
query_opts->err = -EOPNOTSUPP;
goto err_free_sock;
}
ifindex = if_nametoindex(mesh_iface);
if (!ifindex) {
query_opts->err = -ENODEV;
goto err_free_sock;
}
cb = nl_cb_alloc(NL_CB_DEFAULT);
if (!cb) {
query_opts->err = -ENOMEM;
goto err_free_sock;
}
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback, query_opts);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nlquery_stop_cb, query_opts);
nl_cb_err(cb, NL_CB_CUSTOM, nlquery_error_cb, query_opts);
msg = nlmsg_alloc();
if (!msg) {
query_opts->err = -ENOMEM;
goto err_free_cb;
}
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, flags,
nl_cmd, 1);
nla_put_u32(msg, BATADV_ATTR_MESH_IFINDEX, ifindex);
nl_send_auto_complete(sock, msg);
nlmsg_free(msg);
nl_recvmsgs(sock, cb);
err_free_cb:
nl_cb_put(cb);
err_free_sock:
nl_socket_free(sock);
return query_opts->err;
}
/* SPDX-License-Identifier: MIT */
/* batman-adv helpers functions library
*
* Copyright (c) 2017, Sven Eckelmann <sven@narfation.org>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef _BATADV_GENL_H_
#define _BATADV_GENL_H_
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>
#include <stddef.h>
#include <stdbool.h>
#include "batman_adv.h"
/**
* struct batadv_nlquery_opts - internal state for batadv_genl_query()
*
* This structure should be used as member of a struct which tracks the state
* for the callback. The macro batadv_container_of can be used to convert the
* arg pointer from batadv_nlquery_opts to the member which contains this
* struct.
*/
struct batadv_nlquery_opts {
/** @err: current error */
int err;
};
/**
* BATADV_ARRAY_SIZE() - Get number of items in static array
* @x: array with known length
*
* Return: number of items in array
*/
#ifndef BATADV_ARRAY_SIZE
#define BATADV_ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
#endif
/**
* batadv_container_of() - Calculate address of object that contains address ptr
* @ptr: pointer to member variable
* @type: type of the structure containing ptr
* @member: name of the member variable in struct @type
*
* Return: @type pointer of object containing ptr
*/
#ifndef batadv_container_of
#define batadv_container_of(ptr, type, member) __extension__ ({ \
const __typeof__(((type *)0)->member) *__pmember = (ptr); \
(type *)((char *)__pmember - offsetof(type, member)); })
#endif
/**
* batadv_genl_missing_attrs() - Check whether @attrs is missing mandatory
* attribute
* @attrs: attributes which was parsed by nla_parse()
* @mandatory: list of required attributes
* @num: number of required attributes in @mandatory
*
* Return: Return true when a attribute is missing, false otherwise
*/
static inline bool batadv_genl_missing_attrs(struct nlattr *attrs[],
const enum batadv_nl_attrs mandatory[], size_t num) {
size_t i;
for (i = 0; i < num; i++) {
if (!attrs[mandatory[i]])
return true;
}
return false;
}
extern struct nla_policy batadv_genl_policy[];
int batadv_genl_query(const char *mesh_iface, enum batadv_nl_commands nl_cmd,
nl_recvmsg_msg_cb_t callback, int flags,
struct batadv_nlquery_opts *query_opts);
#endif /* _BATADV_GENL_H_ */
/* SPDX-License-Identifier: MIT */
/* Copyright (C) B.A.T.M.A.N. contributors:
*
* Matthias Schiffer
*/
#ifndef _UAPI_LINUX_BATMAN_ADV_H_
#define _UAPI_LINUX_BATMAN_ADV_H_
#define BATADV_NL_NAME "batadv"
#define BATADV_NL_MCAST_GROUP_CONFIG "config"
#define BATADV_NL_MCAST_GROUP_TPMETER "tpmeter"
/**
* enum batadv_tt_client_flags - TT client specific flags
*
* Bits from 0 to 7 are called _remote flags_ because they are sent on the wire.
* Bits from 8 to 15 are called _local flags_ because they are used for local
* computations only.
*
* Bits from 4 to 7 - a subset of remote flags - are ensured to be in sync with
* the other nodes in the network. To achieve this goal these flags are included
* in the TT CRC computation.
*/
enum batadv_tt_client_flags {
/**
* @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table
*/
BATADV_TT_CLIENT_DEL = (1 << 0),
/**
* @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and
* the new update telling its new real location has not been
* received/sent yet
*/
BATADV_TT_CLIENT_ROAM = (1 << 1),
/**
* @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi
* interface. This information is used by the "AP Isolation" feature
*/
BATADV_TT_CLIENT_WIFI = (1 << 4),
/**
* @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This
* information is used by the Extended Isolation feature
*/
BATADV_TT_CLIENT_ISOLA = (1 << 5),
/**
* @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from
* the table
*/
BATADV_TT_CLIENT_NOPURGE = (1 << 8),
/**
* @BATADV_TT_CLIENT_NEW: this client has been added to the local table
* but has not been announced yet
*/
BATADV_TT_CLIENT_NEW = (1 << 9),
/**
* @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it
* is kept in the table for one more originator interval for consistency
* purposes
*/
BATADV_TT_CLIENT_PENDING = (1 << 10),
/**
* @BATADV_TT_CLIENT_TEMP: this global client has been detected to be
* part of the network but no node has already announced it
*/
BATADV_TT_CLIENT_TEMP = (1 << 11),
};
/**
* enum batadv_mcast_flags_priv - Private, own multicast flags
*
* These are internal, multicast related flags. Currently they describe certain
* multicast related attributes of the segment this originator bridges into the
* mesh.
*
* Those attributes are used to determine the public multicast flags this
* originator is going to announce via TT.
*
* For netlink, if BATADV_MCAST_FLAGS_BRIDGED is unset then all querier
* related flags are undefined.
*/
enum batadv_mcast_flags_priv {
/**
* @BATADV_MCAST_FLAGS_BRIDGED: There is a bridge on top of the mesh
* interface.
*/
BATADV_MCAST_FLAGS_BRIDGED = (1 << 0),
/**
* @BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS: Whether an IGMP querier
* exists in the mesh
*/
BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS = (1 << 1),
/**
* @BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS: Whether an MLD querier
* exists in the mesh
*/
BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS = (1 << 2),
/**
* @BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING: If an IGMP querier
* exists, whether it is potentially shadowing multicast listeners
* (i.e. querier is behind our own bridge segment)
*/
BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING = (1 << 3),
/**
* @BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING: If an MLD querier
* exists, whether it is potentially shadowing multicast listeners
* (i.e. querier is behind our own bridge segment)
*/
BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING = (1 << 4),
};
/**
* enum batadv_gw_modes - gateway mode of node
*/
enum batadv_gw_modes {
/** @BATADV_GW_MODE_OFF: gw mode disabled */
BATADV_GW_MODE_OFF,
/** @BATADV_GW_MODE_CLIENT: send DHCP requests to gw servers */
BATADV_GW_MODE_CLIENT,
/** @BATADV_GW_MODE_SERVER: announce itself as gateway server */
BATADV_GW_MODE_SERVER,
};
/**
* enum batadv_nl_attrs - batman-adv netlink attributes
*/
enum batadv_nl_attrs {
/**
* @BATADV_ATTR_UNSPEC: unspecified attribute to catch errors
*/
BATADV_ATTR_UNSPEC,
/**
* @BATADV_ATTR_VERSION: batman-adv version string
*/
BATADV_ATTR_VERSION,
/**
* @BATADV_ATTR_ALGO_NAME: name of routing algorithm
*/
BATADV_ATTR_ALGO_NAME,
/**
* @BATADV_ATTR_MESH_IFINDEX: index of the batman-adv interface
*/
BATADV_ATTR_MESH_IFINDEX,
/**
* @BATADV_ATTR_MESH_IFNAME: name of the batman-adv interface
*/
BATADV_ATTR_MESH_IFNAME,
/**
* @BATADV_ATTR_MESH_ADDRESS: mac address of the batman-adv interface
*/
BATADV_ATTR_MESH_ADDRESS,
/**
* @BATADV_ATTR_HARD_IFINDEX: index of the non-batman-adv interface
*/
BATADV_ATTR_HARD_IFINDEX,
/**
* @BATADV_ATTR_HARD_IFNAME: name of the non-batman-adv interface
*/
BATADV_ATTR_HARD_IFNAME,
/**
* @BATADV_ATTR_HARD_ADDRESS: mac address of the non-batman-adv
* interface
*/
BATADV_ATTR_HARD_ADDRESS,
/**
* @BATADV_ATTR_ORIG_ADDRESS: originator mac address
*/
BATADV_ATTR_ORIG_ADDRESS,
/**
* @BATADV_ATTR_TPMETER_RESULT: result of run (see
* batadv_tp_meter_status)
*/
BATADV_ATTR_TPMETER_RESULT,
/**
* @BATADV_ATTR_TPMETER_TEST_TIME: time (msec) the run took
*/
BATADV_ATTR_TPMETER_TEST_TIME,
/**
* @BATADV_ATTR_TPMETER_BYTES: amount of acked bytes during run
*/
BATADV_ATTR_TPMETER_BYTES,
/**
* @BATADV_ATTR_TPMETER_COOKIE: session cookie to match tp_meter session
*/
BATADV_ATTR_TPMETER_COOKIE,
/**
* @BATADV_ATTR_PAD: attribute used for padding for 64-bit alignment
*/
BATADV_ATTR_PAD,
/**
* @BATADV_ATTR_ACTIVE: Flag indicating if the hard interface is active
*/
BATADV_ATTR_ACTIVE,
/**
* @BATADV_ATTR_TT_ADDRESS: Client MAC address
*/
BATADV_ATTR_TT_ADDRESS,
/**
* @BATADV_ATTR_TT_TTVN: Translation table version
*/
BATADV_ATTR_TT_TTVN,
/**
* @BATADV_ATTR_TT_LAST_TTVN: Previous translation table version
*/
BATADV_ATTR_TT_LAST_TTVN,
/**
* @BATADV_ATTR_TT_CRC32: CRC32 over translation table
*/
BATADV_ATTR_TT_CRC32,
/**
* @BATADV_ATTR_TT_VID: VLAN ID
*/
BATADV_ATTR_TT_VID,
/**
* @BATADV_ATTR_TT_FLAGS: Translation table client flags
*/
BATADV_ATTR_TT_FLAGS,
/**
* @BATADV_ATTR_FLAG_BEST: Flags indicating entry is the best
*/
BATADV_ATTR_FLAG_BEST,
/**
* @BATADV_ATTR_LAST_SEEN_MSECS: Time in milliseconds since last seen
*/
BATADV_ATTR_LAST_SEEN_MSECS,
/**
* @BATADV_ATTR_NEIGH_ADDRESS: Neighbour MAC address
*/
BATADV_ATTR_NEIGH_ADDRESS,
/**
* @BATADV_ATTR_TQ: TQ to neighbour
*/
BATADV_ATTR_TQ,
/**
* @BATADV_ATTR_THROUGHPUT: Estimated throughput to Neighbour
*/
BATADV_ATTR_THROUGHPUT,
/**
* @BATADV_ATTR_BANDWIDTH_UP: Reported uplink bandwidth
*/
BATADV_ATTR_BANDWIDTH_UP,
/**
* @BATADV_ATTR_BANDWIDTH_DOWN: Reported downlink bandwidth
*/
BATADV_ATTR_BANDWIDTH_DOWN,
/**
* @BATADV_ATTR_ROUTER: Gateway router MAC address
*/
BATADV_ATTR_ROUTER,
/**
* @BATADV_ATTR_BLA_OWN: Flag indicating own originator
*/
BATADV_ATTR_BLA_OWN,
/**
* @BATADV_ATTR_BLA_ADDRESS: Bridge loop avoidance claim MAC address
*/
BATADV_ATTR_BLA_ADDRESS,
/**
* @BATADV_ATTR_BLA_VID: BLA VLAN ID
*/
BATADV_ATTR_BLA_VID,
/**
* @BATADV_ATTR_BLA_BACKBONE: BLA gateway originator MAC address
*/
BATADV_ATTR_BLA_BACKBONE,
/**
* @BATADV_ATTR_BLA_CRC: BLA CRC
*/
BATADV_ATTR_BLA_CRC,
/**
* @BATADV_ATTR_DAT_CACHE_IP4ADDRESS: Client IPv4 address
*/
BATADV_ATTR_DAT_CACHE_IP4ADDRESS,
/**
* @BATADV_ATTR_DAT_CACHE_HWADDRESS: Client MAC address
*/
BATADV_ATTR_DAT_CACHE_HWADDRESS,
/**
* @BATADV_ATTR_DAT_CACHE_VID: VLAN ID
*/
BATADV_ATTR_DAT_CACHE_VID,
/**
* @BATADV_ATTR_MCAST_FLAGS: Per originator multicast flags
*/
BATADV_ATTR_MCAST_FLAGS,
/**
* @BATADV_ATTR_MCAST_FLAGS_PRIV: Private, own multicast flags
*/
BATADV_ATTR_MCAST_FLAGS_PRIV,
/**
* @BATADV_ATTR_VLANID: VLAN id on top of soft interface
*/
BATADV_ATTR_VLANID,
/**
* @BATADV_ATTR_AGGREGATED_OGMS_ENABLED: whether the batman protocol
* messages of the mesh interface shall be aggregated or not.
*/
BATADV_ATTR_AGGREGATED_OGMS_ENABLED,
/**
* @BATADV_ATTR_AP_ISOLATION_ENABLED: whether the data traffic going
* from a wireless client to another wireless client will be silently
* dropped.
*/
BATADV_ATTR_AP_ISOLATION_ENABLED,
/**
* @BATADV_ATTR_ISOLATION_MARK: the isolation mark which is used to
* classify clients as "isolated" by the Extended Isolation feature.
*/
BATADV_ATTR_ISOLATION_MARK,
/**
* @BATADV_ATTR_ISOLATION_MASK: the isolation (bit)mask which is used to
* classify clients as "isolated" by the Extended Isolation feature.
*/
BATADV_ATTR_ISOLATION_MASK,
/**
* @BATADV_ATTR_BONDING_ENABLED: whether the data traffic going through
* the mesh will be sent using multiple interfaces at the same time.
*/
BATADV_ATTR_BONDING_ENABLED,
/**
* @BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED: whether the bridge loop
* avoidance feature is enabled. This feature detects and avoids loops
* between the mesh and devices bridged with the soft interface
*/
BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED,
/**
* @BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED: whether the distributed
* arp table feature is enabled. This feature uses a distributed hash
* table to answer ARP requests without flooding the request through
* the whole mesh.
*/
BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED,
/**
* @BATADV_ATTR_FRAGMENTATION_ENABLED: whether the data traffic going
* through the mesh will be fragmented or silently discarded if the
* packet size exceeds the outgoing interface MTU.
*/
BATADV_ATTR_FRAGMENTATION_ENABLED,
/**
* @BATADV_ATTR_GW_BANDWIDTH_DOWN: defines the download bandwidth which
* is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set
* to 'server'.
*/
BATADV_ATTR_GW_BANDWIDTH_DOWN,
/**
* @BATADV_ATTR_GW_BANDWIDTH_UP: defines the upload bandwidth which
* is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set
* to 'server'.
*/
BATADV_ATTR_GW_BANDWIDTH_UP,
/**
* @BATADV_ATTR_GW_MODE: defines the state of the gateway features.
* Possible values are specified in enum batadv_gw_modes
*/
BATADV_ATTR_GW_MODE,
/**
* @BATADV_ATTR_GW_SEL_CLASS: defines the selection criteria this node
* will use to choose a gateway if gw_mode was set to 'client'.
*/
BATADV_ATTR_GW_SEL_CLASS,
/**
* @BATADV_ATTR_HOP_PENALTY: defines the penalty which will be applied
* to an originator message's tq-field on every hop and/or per
* hard interface
*/
BATADV_ATTR_HOP_PENALTY,
/**
* @BATADV_ATTR_LOG_LEVEL: bitmask with to define which debug messages
* should be send to the debug log/trace ring buffer
*/
BATADV_ATTR_LOG_LEVEL,
/**
* @BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED: whether multicast
* optimizations should be replaced by simple broadcast-like flooding
* of multicast packets. If set to non-zero then all nodes in the mesh
* are going to use classic flooding for any multicast packet with no
* optimizations.
*/
BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED,
/**
* @BATADV_ATTR_NETWORK_CODING_ENABLED: whether Network Coding (using
* some magic to send fewer wifi packets but still the same content) is
* enabled or not.
*/
BATADV_ATTR_NETWORK_CODING_ENABLED,
/**
* @BATADV_ATTR_ORIG_INTERVAL: defines the interval in milliseconds in
* which batman sends its protocol messages.
*/
BATADV_ATTR_ORIG_INTERVAL,
/**
* @BATADV_ATTR_ELP_INTERVAL: defines the interval in milliseconds in
* which batman emits probing packets for neighbor sensing (ELP).
*/
BATADV_ATTR_ELP_INTERVAL,
/**
* @BATADV_ATTR_THROUGHPUT_OVERRIDE: defines the throughput value to be
* used by B.A.T.M.A.N. V when estimating the link throughput using
* this interface. If the value is set to 0 then batman-adv will try to
* estimate the throughput by itself.
*/
BATADV_ATTR_THROUGHPUT_OVERRIDE,
/**
* @BATADV_ATTR_MULTICAST_FANOUT: defines the maximum number of packet
* copies that may be generated for a multicast-to-unicast conversion.
* Once this limit is exceeded distribution will fall back to broadcast.
*/
BATADV_ATTR_MULTICAST_FANOUT,
/* add attributes above here, update the policy in netlink.c */
/**
* @__BATADV_ATTR_AFTER_LAST: internal use
*/
__BATADV_ATTR_AFTER_LAST,
/**
* @NUM_BATADV_ATTR: total number of batadv_nl_attrs available
*/
NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST,
/**
* @BATADV_ATTR_MAX: highest attribute number currently defined
*/
BATADV_ATTR_MAX = __BATADV_ATTR_AFTER_LAST - 1
};
/**
* enum batadv_nl_commands - supported batman-adv netlink commands
*/
enum batadv_nl_commands {
/**
* @BATADV_CMD_UNSPEC: unspecified command to catch errors
*/
BATADV_CMD_UNSPEC,
/**
* @BATADV_CMD_GET_MESH: Get attributes from softif/mesh
*/
BATADV_CMD_GET_MESH,
/**
* @BATADV_CMD_GET_MESH_INFO: Alias for @BATADV_CMD_GET_MESH
*/
BATADV_CMD_GET_MESH_INFO = BATADV_CMD_GET_MESH,
/**
* @BATADV_CMD_TP_METER: Start a tp meter session
*/
BATADV_CMD_TP_METER,
/**
* @BATADV_CMD_TP_METER_CANCEL: Cancel a tp meter session
*/
BATADV_CMD_TP_METER_CANCEL,
/**
* @BATADV_CMD_GET_ROUTING_ALGOS: Query the list of routing algorithms.
*/
BATADV_CMD_GET_ROUTING_ALGOS,
/**
* @BATADV_CMD_GET_HARDIF: Get attributes from a hardif of the
* current softif
*/
BATADV_CMD_GET_HARDIF,
/**
* @BATADV_CMD_GET_HARDIFS: Alias for @BATADV_CMD_GET_HARDIF
*/
BATADV_CMD_GET_HARDIFS = BATADV_CMD_GET_HARDIF,
/**
* @BATADV_CMD_GET_TRANSTABLE_LOCAL: Query list of local translations
*/
BATADV_CMD_GET_TRANSTABLE_LOCAL,
/**
* @BATADV_CMD_GET_TRANSTABLE_GLOBAL: Query list of global translations
*/
BATADV_CMD_GET_TRANSTABLE_GLOBAL,
/**
* @BATADV_CMD_GET_ORIGINATORS: Query list of originators
*/
BATADV_CMD_GET_ORIGINATORS,
/**
* @BATADV_CMD_GET_NEIGHBORS: Query list of neighbours
*/
BATADV_CMD_GET_NEIGHBORS,
/**
* @BATADV_CMD_GET_GATEWAYS: Query list of gateways
*/
BATADV_CMD_GET_GATEWAYS,
/**
* @BATADV_CMD_GET_BLA_CLAIM: Query list of bridge loop avoidance claims
*/
BATADV_CMD_GET_BLA_CLAIM,
/**
* @BATADV_CMD_GET_BLA_BACKBONE: Query list of bridge loop avoidance
* backbones
*/
BATADV_CMD_GET_BLA_BACKBONE,
/**
* @BATADV_CMD_GET_DAT_CACHE: Query list of DAT cache entries
*/
BATADV_CMD_GET_DAT_CACHE,
/**
* @BATADV_CMD_GET_MCAST_FLAGS: Query list of multicast flags
*/
BATADV_CMD_GET_MCAST_FLAGS,
/**
* @BATADV_CMD_SET_MESH: Set attributes for softif/mesh
*/
BATADV_CMD_SET_MESH,
/**
* @BATADV_CMD_SET_HARDIF: Set attributes for hardif of the
* current softif
*/
BATADV_CMD_SET_HARDIF,
/**
* @BATADV_CMD_GET_VLAN: Get attributes from a VLAN of the
* current softif
*/
BATADV_CMD_GET_VLAN,
/**
* @BATADV_CMD_SET_VLAN: Set attributes for VLAN of the
* current softif
*/
BATADV_CMD_SET_VLAN,
/* add new commands above here */
/**
* @__BATADV_CMD_AFTER_LAST: internal use
*/
__BATADV_CMD_AFTER_LAST,
/**
* @BATADV_CMD_MAX: highest used command number
*/
BATADV_CMD_MAX = __BATADV_CMD_AFTER_LAST - 1
};
/**
* enum batadv_tp_meter_reason - reason of a tp meter test run stop
*/
enum batadv_tp_meter_reason {
/**
* @BATADV_TP_REASON_COMPLETE: sender finished tp run
*/
BATADV_TP_REASON_COMPLETE = 3,
/**
* @BATADV_TP_REASON_CANCEL: sender was stopped during run
*/
BATADV_TP_REASON_CANCEL = 4,
/* error status >= 128 */
/**
* @BATADV_TP_REASON_DST_UNREACHABLE: receiver could not be reached or
* didn't answer
*/
BATADV_TP_REASON_DST_UNREACHABLE = 128,
/**
* @BATADV_TP_REASON_RESEND_LIMIT: (unused) sender retry reached limit
*/
BATADV_TP_REASON_RESEND_LIMIT = 129,
/**
* @BATADV_TP_REASON_ALREADY_ONGOING: test to or from the same node
* already ongoing
*/
BATADV_TP_REASON_ALREADY_ONGOING = 130,
/**
* @BATADV_TP_REASON_MEMORY_ERROR: test was stopped due to low memory
*/
BATADV_TP_REASON_MEMORY_ERROR = 131,
/**
* @BATADV_TP_REASON_CANT_SEND: failed to send via outgoing interface
*/
BATADV_TP_REASON_CANT_SEND = 132,
/**
* @BATADV_TP_REASON_TOO_MANY: too many ongoing sessions
*/
BATADV_TP_REASON_TOO_MANY = 133,
};
/**
* enum batadv_ifla_attrs - batman-adv ifla nested attributes
*/
enum batadv_ifla_attrs {
/**
* @IFLA_BATADV_UNSPEC: unspecified attribute which is not parsed by
* rtnetlink
*/
IFLA_BATADV_UNSPEC,
/**
* @IFLA_BATADV_ALGO_NAME: routing algorithm (name) which should be
* used by the newly registered batadv net_device.
*/
IFLA_BATADV_ALGO_NAME,
/* add attributes above here, update the policy in soft-interface.c */
/**
* @__IFLA_BATADV_MAX: internal use
*/
__IFLA_BATADV_MAX,
};
#define IFLA_BATADV_MAX (__IFLA_BATADV_MAX - 1)
#endif /* _UAPI_LINUX_BATMAN_ADV_H_ */
......@@ -6,26 +6,14 @@ CMAKE_INSTALL:=1
PKG_LICENSE:=BSD-2-Clause
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include ../gluon.mk
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/libgluonutil
SECTION:=libs
CATEGORY:=Libraries
TITLE:=Gluon utility library
DEPENDS:=+libjson-c
endef
CMAKE_OPTIONS += \
-DCMAKE_BUILD_TYPE:String="MINSIZEREL"
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
DEPENDS:=+libjson-c +libuci
endef
define Package/libgluonutil/install
......
cmake_minimum_required(VERSION 2.6)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
project(libgluonutil C)
set(LIBDIR "lib${LIB_SUFFIX}")
find_package(JSON_C REQUIRED)
set_property(DIRECTORY PROPERTY COMPILE_DEFINITIONS _GNU_SOURCE)
add_library(gluonutil SHARED libgluonutil.c)
set_property(TARGET gluonutil PROPERTY COMPILE_FLAGS "-Wall -std=c99 ${JSON_C_CFLAGS_OTHER}")
set_property(TARGET gluonutil PROPERTY LINK_FLAGS "${JSON_C_LDFLAGS_OTHER}")
set_property(TARGET gluonutil APPEND PROPERTY INCLUDE_DIRECTORIES ${JSON_C_INCLUDE_DIR})
target_link_libraries(gluonutil ${JSON_C_LIBRARIES})
set_property(TARGET gluonutil PROPERTY COMPILE_FLAGS "-Wall -std=c99")
target_link_libraries(gluonutil json-c uci)
install(TARGETS gluonutil
ARCHIVE DESTINATION ${LIBDIR}
LIBRARY DESTINATION ${LIBDIR}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/libgluonutil.h DESTINATION include)
# Defines the following variables:
# JSON_C_FOUND
# JSON_C_INCLUDE_DIR
# JSON_C_LIBRARIES
# JSON_C_CFLAGS_OTHER
# JSON_C_LDFLAGS_OTHER
find_package(PkgConfig REQUIRED QUIET)
pkg_check_modules(_JSON_C json-c)
find_path(JSON_C_INCLUDE_DIR NAMES json-c/json.h HINTS ${_JSON_C_INCLUDE_DIRS})
find_library(JSON_C_LIBRARIES NAMES json-c HINTS ${_JSON_C_LIBRARY_DIRS})
set(JSON_C_CFLAGS_OTHER "${_JSON_C_CFLAGS_OTHER}" CACHE STRING "Additional compiler flags for json-c")
set(JSON_C_LDFLAGS_OTHER "${_JSON_C_LDFLAGS_OTHER}" CACHE STRING "Additional linker flags for json-c")
find_package_handle_standard_args(JSON_C REQUIRED_VARS JSON_C_LIBRARIES JSON_C_INCLUDE_DIR)
mark_as_advanced(JSON_C_INCLUDE_DIR JSON_C_LIBRARIES JSON_C_CFLAGS_OTHER JSON_C_LDFLAGS_OTHER)
/*
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* SPDX-FileCopyrightText: 2016 Matthias Schiffer <mschiffer@universe-factory.net> */
/* SPDX-License-Identifier: BSD-2-Clause */
#include "libgluonutil.h"
#include <json-c/json.h>
#include <uci.h>
#include <arpa/inet.h>
#include <errno.h>
#include <glob.h>
#include <libgen.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
/**
* Merges two JSON objects
*
* Both objects are consumed. On conflicts, object b will be preferred.
*/
static struct json_object * merge_json(struct json_object *a, struct json_object *b) {
if (!json_object_is_type(a, json_type_object) || !json_object_is_type(b, json_type_object)) {
json_object_put(a);
return b;
}
json_object *m = json_object_new_object();
json_object_object_foreach(a, key_a, val_a)
json_object_object_add(m, key_a, json_object_get(val_a));
json_object_put(a);
json_object_object_foreach(b, key_b, val_b) {
struct json_object *val_m;
if (json_object_object_get_ex(m, key_b, &val_m))
val_m = merge_json(json_object_get(val_m), json_object_get(val_b));
else
val_m = json_object_get(val_b);
json_object_object_add(m, key_b, val_m);
}
json_object_put(b);
return m;
}
char * gluonutil_read_line(const char *filename) {
FILE *f = fopen(filename, "r");
......@@ -94,6 +111,75 @@ char * gluonutil_get_interface_address(const char *ifname) {
return gluonutil_read_line(path);
}
void gluonutil_get_interface_lower(char out[IF_NAMESIZE], const char *ifname) {
strncpy(out, ifname, IF_NAMESIZE-1);
out[IF_NAMESIZE-1] = 0;
const char *format = "/sys/class/net/%s/lower_*";
char pattern[strlen(format) + IF_NAMESIZE];
while (true) {
snprintf(pattern, sizeof(pattern), format, out);
size_t pattern_len = strlen(pattern);
glob_t lower;
if (glob(pattern, GLOB_NOSORT, NULL, &lower) != 0)
break;
strncpy(out, lower.gl_pathv[0] + pattern_len - 1, IF_NAMESIZE-1);
globfree(&lower);
}
}
enum gluonutil_interface_type lookup_interface_type(const char *devtype) {
if (strcmp(devtype, "wlan") == 0)
return GLUONUTIL_INTERFACE_TYPE_WIRELESS;
if (strcmp(devtype, "l2tpeth") == 0 || strcmp(devtype, "wireguard") == 0)
return GLUONUTIL_INTERFACE_TYPE_TUNNEL;
/* Regular wired interfaces do not set DEVTYPE, so if this point is
* reached, we have something different */
return GLUONUTIL_INTERFACE_TYPE_UNKNOWN;
}
enum gluonutil_interface_type gluonutil_get_interface_type(const char *ifname) {
const char *pattern = "/sys/class/net/%s/%s";
/* Default to wired type when no DEVTYPE is set */
enum gluonutil_interface_type ret = GLUONUTIL_INTERFACE_TYPE_WIRED;
char *line = NULL, path[PATH_MAX];
size_t buflen = 0;
ssize_t len;
FILE *f;
snprintf(path, sizeof(path), pattern, ifname, "tun_flags");
if (access(path, F_OK) == 0)
return GLUONUTIL_INTERFACE_TYPE_TUNNEL;
snprintf(path, sizeof(path), pattern, ifname, "uevent");
f = fopen(path, "r");
if (!f)
return GLUONUTIL_INTERFACE_TYPE_UNKNOWN;
while ((len = getline(&line, &buflen, f)) >= 0) {
if (len == 0)
continue;
if (line[len-1] == '\n')
line[len-1] = '\0';
if (strncmp(line, "DEVTYPE=", 8) == 0) {
ret = lookup_interface_type(line+8);
break;
}
}
free(line);
fclose(f);
return ret;
}
struct json_object * gluonutil_wrap_string(const char *str) {
......@@ -109,6 +195,145 @@ struct json_object * gluonutil_wrap_and_free_string(char *str) {
return ret;
}
bool gluonutil_get_node_prefix6(struct in6_addr *prefix) {
struct json_object *site = gluonutil_load_site_config();
if (!site)
return false;
struct json_object *node_prefix = NULL;
if (!json_object_object_get_ex(site, "node_prefix6", &node_prefix)) {
json_object_put(site);
return false;
}
const char *str_prefix = json_object_get_string(node_prefix);
if (!str_prefix) {
json_object_put(site);
return false;
}
char *prefix_addr = strndup(str_prefix, strchrnul(str_prefix, '/')-str_prefix);
int ret = inet_pton(AF_INET6, prefix_addr, prefix);
free(prefix_addr);
json_object_put(site);
if (ret != 1)
return false;
return true;
}
bool gluonutil_has_domains(void) {
return (access("/lib/gluon/domains/", F_OK) == 0);
}
char * gluonutil_get_domain(void) {
if (!gluonutil_has_domains())
return NULL;
char *ret = NULL;
struct uci_context *ctx = uci_alloc_context();
if (!ctx)
goto uci_fail;
ctx->flags &= ~UCI_FLAG_STRICT;
struct uci_package *p;
if (uci_load(ctx, "gluon", &p))
goto uci_fail;
struct uci_section *s = uci_lookup_section(ctx, p, "core");
if (!s)
goto uci_fail;
const char *domain_code = uci_lookup_option_string(ctx, s, "domain");
if (!domain_code)
goto uci_fail;
ret = strdup(domain_code);
uci_fail:
if (ctx)
uci_free_context(ctx);
return ret;
}
char * gluonutil_get_primary_domain(void) {
if (!gluonutil_has_domains())
return NULL;
char *domain_code = gluonutil_get_domain();
if (!domain_code)
return NULL;
const char *domain_path_fmt = "/lib/gluon/domains/%s.json";
char domain_path[strlen(domain_path_fmt) + strlen(domain_code)];
snprintf(domain_path, sizeof(domain_path), domain_path_fmt, domain_code);
char primary_domain_path[PATH_MAX+1];
char *primary_domain_code;
ssize_t len = readlink(domain_path, primary_domain_path, PATH_MAX);
if (len < 0) {
// EINVAL = file is not a symlink = the domain itself is the primary domain
if (errno != EINVAL) {
free(domain_code);
return NULL;
}
return domain_code;
}
free(domain_code);
primary_domain_path[len] = '\0';
primary_domain_code = basename(primary_domain_path);
char *ext_begin = strrchr(primary_domain_code, '.');
if (!ext_begin)
return NULL;
// strip .json from filename
*ext_begin = '\0';
return strdup(primary_domain_code);
}
struct json_object * gluonutil_load_site_config(void) {
return json_object_from_file("/lib/gluon/site.json");
char *domain_code = NULL;
struct json_object *site = NULL, *domain = NULL;
site = json_object_from_file("/lib/gluon/site.json");
if (!site)
return NULL;
if (!gluonutil_has_domains())
return site;
domain_code = gluonutil_get_domain();
if (!domain_code)
goto err;
{
const char *domain_path_fmt = "/lib/gluon/domains/%s.json";
char domain_path[strlen(domain_path_fmt) + strlen(domain_code)];
snprintf(domain_path, sizeof(domain_path), domain_path_fmt, domain_code);
free(domain_code);
domain = json_object_from_file(domain_path);
}
if (!domain)
goto err;
return merge_json(site, domain);
err:
json_object_put(site);
return NULL;
}
/*
Copyright (c) 2016, Matthias Schiffer <mschiffer@universe-factory.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* SPDX-FileCopyrightText: 2016 Matthias Schiffer <mschiffer@universe-factory.net> */
/* SPDX-License-Identifier: BSD-2-Clause */
#ifndef _LIBGLUON_LIBGLUON_H_
#define _LIBGLUON_LIBGLUON_H_
#include <net/if.h>
#include <netinet/in.h>
#include <stdbool.h>
char * gluonutil_read_line(const char *filename);
char * gluonutil_get_sysconfig(const char *key);
char * gluonutil_get_node_id(void);
enum gluonutil_interface_type {
GLUONUTIL_INTERFACE_TYPE_UNKNOWN,
GLUONUTIL_INTERFACE_TYPE_WIRED,
GLUONUTIL_INTERFACE_TYPE_WIRELESS,
GLUONUTIL_INTERFACE_TYPE_TUNNEL,
};
void gluonutil_get_interface_lower(char out[IF_NAMESIZE], const char *ifname);
char * gluonutil_get_interface_address(const char *ifname);
enum gluonutil_interface_type gluonutil_get_interface_type(const char *ifname);
bool gluonutil_get_node_prefix6(struct in6_addr *prefix);
struct json_object * gluonutil_wrap_string(const char *str);
struct json_object * gluonutil_wrap_and_free_string(char *str);
bool gluonutil_has_domains(void);
char * gluonutil_get_domain(void);
char * gluonutil_get_primary_domain(void);
struct json_object * gluonutil_load_site_config(void);
#endif /* _LIBGLUON_LIBGLUON_H_ */
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Sat, 14 Jan 2017 18:13:14 +0100
Subject: build: move STAGING_DIR_HOSTPKG and BUILD_DIR_HOST back to a common directory for all targets
$(STAGING_DIR)/host is kept in addition to $(STAGING_DIR_HOSTPKG) in most
places; it is still used as destination for host files in Build/InstallDev.
Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
diff --git a/Makefile b/Makefile
index b220dfd3c56a11f3e27d70e3d6e58cc6448abd2f..c1a7285c83df310e987eaef8376500d2b614eafb 100644
--- a/Makefile
+++ b/Makefile
@@ -55,7 +55,7 @@ clean: FORCE
rm -rf $(BUILD_DIR) $(STAGING_DIR) $(BIN_DIR) $(OUTPUT_DIR)/packages/$(ARCH_PACKAGES) $(BUILD_LOG_DIR) $(TOPDIR)/staging_dir/packages
dirclean: clean
- rm -rf $(STAGING_DIR_HOST) $(TOOLCHAIN_DIR) $(BUILD_DIR_HOST) $(BUILD_DIR_TOOLCHAIN)
+ rm -rf $(STAGING_DIR_HOST) $(STAGING_DIR_HOSTPKG) $(TOOLCHAIN_DIR) $(BUILD_DIR_BASE)/host $(BUILD_DIR_BASE)/hostpkg $(BUILD_DIR_TOOLCHAIN)
rm -rf $(TMP_DIR)
ifndef DUMP_TARGET_DB
diff --git a/include/autotools.mk b/include/autotools.mk
index c6aa47e0bef311697b4def7a7183d1ac59dcf599..7bd400ab36d052b39fcb76a66873c8673eb189a0 100644
--- a/include/autotools.mk
+++ b/include/autotools.mk
@@ -75,7 +75,7 @@ define autoreconf_target
$(strip $(call autoreconf, \
$(PKG_BUILD_DIR), $(PKG_REMOVE_FILES), \
$(PKG_AUTOMAKE_PATHS), $(PKG_LIBTOOL_PATHS), \
- $(STAGING_DIR)/host/share/aclocal $(STAGING_DIR)/usr/share/aclocal $(PKG_MACRO_PATHS)))
+ $(STAGING_DIR)/host/share/aclocal $(STAGING_DIR_HOSTPKG)/share/aclocal $(STAGING_DIR)/usr/share/aclocal $(PKG_MACRO_PATHS)))
endef
define patch_libtool_target
diff --git a/include/cmake.mk b/include/cmake.mk
index 5a403cbf41e2bbd6bdb843492639a01aff8cf75b..900dae1d4afc6007f8ac04179dd7f0922a07d4fa 100644
--- a/include/cmake.mk
+++ b/include/cmake.mk
@@ -34,7 +34,7 @@ CMAKE_NM:=$(call cmake_tool,$(TARGET_NM))
CMAKE_RANLIB:=$(call cmake_tool,$(TARGET_RANLIB))
CMAKE_FIND_ROOT_PATH:=$(STAGING_DIR)/usr;$(TOOLCHAIN_DIR)$(if $(CONFIG_EXTERNAL_TOOLCHAIN),;$(CONFIG_TOOLCHAIN_ROOT))
-CMAKE_HOST_FIND_ROOT_PATH:=$(STAGING_DIR)/host;$(STAGING_DIR_HOST)
+CMAKE_HOST_FIND_ROOT_PATH:=$(STAGING_DIR)/host;$(STAGING_DIR_HOSTPKG);$(STAGING_DIR_HOST)
CMAKE_SHARED_LDFLAGS:=-Wl,-Bsymbolic-functions
define Build/Configure/Default
diff --git a/include/host-build.mk b/include/host-build.mk
index 70bf6e5a399615edb91edfae3c43a93504d7b5d8..6c2f91581b895bda1ee9f2ee94afc2e5c06de380 100644
--- a/include/host-build.mk
+++ b/include/host-build.mk
@@ -122,7 +122,7 @@ ifneq ($(if $(HOST_QUILT),,$(CONFIG_AUTOREBUILD)),)
endif
define Host/Exports/Default
- $(1) : export ACLOCAL_INCLUDE=$$(foreach p,$$(wildcard $$(STAGING_DIR_HOST)/share/aclocal $$(STAGING_DIR_HOST)/share/aclocal-* $(if $(IS_PACKAGE_BUILD),$$(STAGING_DIR)/host/share/aclocal $$(STAGING_DIR)/host/share/aclocal-*)),-I $$(p))
+ $(1) : export ACLOCAL_INCLUDE=$$(foreach p,$$(wildcard $$(STAGING_DIR_HOST)/share/aclocal $$(STAGING_DIR_HOST)/share/aclocal-* $(if $(IS_PACKAGE_BUILD),$$(STAGING_DIR)/host/share/aclocal $$(STAGING_DIR_HOSTPKG)/share/aclocal $$(STAGING_DIR)/host/share/aclocal-*)),-I $$(p))
$(1) : export STAGING_PREFIX=$$(HOST_BUILD_PREFIX)
$(1) : export PKG_CONFIG_PATH=$$(STAGING_DIR_HOST)/lib/pkgconfig:$$(HOST_BUILD_PREFIX)/lib/pkgconfig
$(1) : export PKG_CONFIG_LIBDIR=$$(HOST_BUILD_PREFIX)/lib/pkgconfig
diff --git a/include/package.mk b/include/package.mk
index 32485176577b040f6e4a561c5d1144509877bcdf..ea801288eadb139cc0dd2412b4c927c6bd7330e0 100644
--- a/include/package.mk
+++ b/include/package.mk
@@ -130,7 +130,7 @@ ifdef USE_SOURCE_DIR
endif
define Build/Exports/Default
- $(1) : export ACLOCAL_INCLUDE=$$(foreach p,$$(wildcard $$(STAGING_DIR)/usr/share/aclocal $$(STAGING_DIR)/usr/share/aclocal-* $$(STAGING_DIR)/host/share/aclocal $$(STAGING_DIR)/host/share/aclocal-*),-I $$(p))
+ $(1) : export ACLOCAL_INCLUDE=$$(foreach p,$$(wildcard $$(STAGING_DIR)/usr/share/aclocal $$(STAGING_DIR)/usr/share/aclocal-* $$(STAGING_DIR_HOSTPKG)/share/aclocal $$(STAGING_DIR_HOSTPKG)/share/aclocal-* $$(STAGING_DIR)/host/share/aclocal $$(STAGING_DIR)/host/share/aclocal-*),-I $$(p))
$(1) : export STAGING_PREFIX=$$(STAGING_DIR)/usr
$(1) : export PATH=$$(TARGET_PATH_PKG)
$(1) : export CONFIG_SITE:=$$(CONFIG_SITE)
diff --git a/rules.mk b/rules.mk
index 04fd936660bef4af49de5500cd2d7c3601c1b9f6..95b18f9e5c69de479db54c5bdb740103140dcf74 100644
--- a/rules.mk
+++ b/rules.mk
@@ -145,9 +145,9 @@ STAGING_DIR_ROOT:=$(STAGING_DIR)/root-$(BOARD)
BUILD_LOG_DIR:=$(TOPDIR)/logs
PKG_INFO_DIR := $(STAGING_DIR)/pkginfo
-BUILD_DIR_HOST:=$(if $(IS_PACKAGE_BUILD),$(BUILD_DIR)/host,$(BUILD_DIR_BASE)/host)
+BUILD_DIR_HOST:=$(if $(IS_PACKAGE_BUILD),$(BUILD_DIR_BASE)/hostpkg,$(BUILD_DIR_BASE)/host)
STAGING_DIR_HOST:=$(TOPDIR)/staging_dir/host
-STAGING_DIR_HOSTPKG:=$(STAGING_DIR)/host
+STAGING_DIR_HOSTPKG:=$(TOPDIR)/staging_dir/hostpkg
TARGET_PATH:=$(subst $(space),:,$(filter-out .,$(filter-out ./,$(subst :,$(space),$(PATH)))))
TARGET_INIT_PATH:=$(call qstrip,$(CONFIG_TARGET_INIT_PATH))
@@ -206,7 +206,7 @@ ifndef DUMP
endif
endif
endif
-TARGET_PATH_PKG:=$(STAGING_DIR)/host/bin:$(TARGET_PATH)
+TARGET_PATH_PKG:=$(STAGING_DIR)/host/bin:$(STAGING_DIR_HOSTPKG)/bin:$(TARGET_PATH)
ifeq ($(CONFIG_SOFT_FLOAT),y)
SOFT_FLOAT_CONFIG_OPTION:=--with-float=soft
@@ -232,9 +232,9 @@ export PKG_CONFIG
HOSTCC:=gcc
HOSTCXX:=g++
-HOST_CPPFLAGS:=-I$(STAGING_DIR_HOST)/include -I$(STAGING_DIR_HOST)/usr/include $(if $(IS_PACKAGE_BUILD),-I$(STAGING_DIR)/host/include)
+HOST_CPPFLAGS:=-I$(STAGING_DIR_HOST)/include -I$(STAGING_DIR_HOST)/usr/include $(if $(IS_PACKAGE_BUILD),-I$(STAGING_DIR_HOSTPKG)/include -I$(STAGING_DIR)/host/include)
HOST_CFLAGS:=-O2 $(HOST_CPPFLAGS)
-HOST_LDFLAGS:=-L$(STAGING_DIR_HOST)/lib -L$(STAGING_DIR_HOST)/usr/lib $(if $(IS_PACKAGE_BUILD),-L$(STAGING_DIR)/host/lib)
+HOST_LDFLAGS:=-L$(STAGING_DIR_HOST)/lib -L$(STAGING_DIR_HOST)/usr/lib $(if $(IS_PACKAGE_BUILD),-L$(STAGING_DIR_HOSTPKG)/lib -L$(STAGING_DIR)/host/lib)
ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),)
TARGET_AR:=$(TARGET_CROSS)gcc-ar
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Mon, 27 Jul 2015 20:42:50 +0200
Subject: hostapd: prevent channel switch for 5GHz
hostapd would switch the primary and secondary channel on 5GHz networks in
certain circumstances, completely breaking the adhoc interfaces of the WLAN
adapter (they would lose their configuration).
As a temporary fix, disable this channel switch function.
diff --git a/package/network/services/hostapd/patches/900-no_channel_switch.patch b/package/network/services/hostapd/patches/900-no_channel_switch.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c6145156928ffa5a5195ca145b0655bb88c92091
--- /dev/null
+++ b/package/network/services/hostapd/patches/900-no_channel_switch.patch
@@ -0,0 +1,68 @@
+--- a/src/common/hw_features_common.c
++++ b/src/common/hw_features_common.c
+@@ -171,7 +171,6 @@ int check_40mhz_5g(struct hostapd_hw_mod
+ struct wpa_scan_results *scan_res, int pri_chan,
+ int sec_chan)
+ {
+- int pri_freq, sec_freq, pri_bss, sec_bss;
+ int bss_pri_chan, bss_sec_chan;
+ size_t i;
+ int match;
+@@ -180,57 +179,6 @@ int check_40mhz_5g(struct hostapd_hw_mod
+ pri_chan == sec_chan)
+ return 0;
+
+- pri_freq = hw_get_freq(mode, pri_chan);
+- sec_freq = hw_get_freq(mode, sec_chan);
+-
+- /*
+- * Switch PRI/SEC channels if Beacons were detected on selected SEC
+- * channel, but not on selected PRI channel.
+- */
+- pri_bss = sec_bss = 0;
+- for (i = 0; i < scan_res->num; i++) {
+- struct wpa_scan_res *bss = scan_res->res[i];
+- if (bss->freq == pri_freq)
+- pri_bss++;
+- else if (bss->freq == sec_freq)
+- sec_bss++;
+- }
+- if (sec_bss && !pri_bss) {
+- wpa_printf(MSG_INFO,
+- "Switch own primary and secondary channel to get secondary channel with no Beacons from other BSSes");
+- return 2;
+- }
+-
+- /*
+- * Match PRI/SEC channel with any existing HT40 BSS on the same
+- * channels that we are about to use (if already mixed order in
+- * existing BSSes, use own preference).
+- */
+- match = 0;
+- for (i = 0; i < scan_res->num; i++) {
+- struct wpa_scan_res *bss = scan_res->res[i];
+- get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
+- if (pri_chan == bss_pri_chan &&
+- sec_chan == bss_sec_chan) {
+- match = 1;
+- break;
+- }
+- }
+- if (!match) {
+- for (i = 0; i < scan_res->num; i++) {
+- struct wpa_scan_res *bss = scan_res->res[i];
+- get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan);
+- if (pri_chan == bss_sec_chan &&
+- sec_chan == bss_pri_chan) {
+- wpa_printf(MSG_INFO, "Switch own primary and "
+- "secondary channel due to BSS "
+- "overlap with " MACSTR,
+- MAC2STR(bss->bssid));
+- return 2;
+- }
+- }
+- }
+-
+ return 1;
+ }
+