contrib: remove abandonned projects

Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
This commit is contained in:
Jo-Philipp Wich 2015-01-08 16:35:30 +01:00
parent d82b889a7b
commit 7e4fff2514
27 changed files with 0 additions and 6926 deletions

View file

@ -1,2 +0,0 @@
include ../../build/config.mk
include ../../build/module.mk

View file

@ -1,18 +0,0 @@
CFLAGS := -ggdb3 -O0 -Wall -I./uci -I./iptables-1.4.5/include
LDFLAGS := -luci -liptc -lxtables -ldl -L./iptables-1.4.5/libiptc/.libs -L./iptables-1.4.5/.libs -Wl,--export-dynamic
fwd:
$(CC) $(CFLAGS) -c -o ucix.o ucix.c
$(CC) $(CFLAGS) -c -o fwd_addr.o fwd_addr.c
$(CC) $(CFLAGS) -c -o fwd_rules.o fwd_rules.c
$(CC) $(CFLAGS) -c -o fwd_config.o fwd_config.c
$(CC) $(CFLAGS) -c -o fwd_xtables.o fwd_xtables.c
$(CC) $(CFLAGS) -c -o fwd_ipc.o fwd_ipc.c
$(CC) $(CFLAGS) -c -o fwd_utils.o fwd_utils.c
$(CC) $(CFLAGS) -c -o fwd.o fwd.c
$(CC) $(LDFLAGS) -o fwd fwd.o fwd_addr.o fwd_rules.o fwd_config.o fwd_xtables.o fwd_ipc.o fwd_utils.o ucix.o
ln -s fwd fw
clean:
rm -f *~ fwd fw *.o

View file

@ -1,320 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - main part
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#include "fwd.h"
#include "fwd_addr.h"
#include "fwd_rules.h"
#include "fwd_config.h"
#include "fwd_xtables.h"
#include "fwd_ipc.h"
#include "fwd_utils.h"
static void fwd_foreach_network(
struct fwd_handle *h,
void (*cb)(struct fwd_handle *h, struct fwd_network *net)
) {
struct fwd_data *data;
struct fwd_network *net;
for( data = h->conf; data; data = data->next )
{
if( data->type != FWD_S_ZONE )
continue;
for( net = data->section.zone.networks; net; net = net->next )
cb(h, net);
}
}
static void fwd_addif_all_cb(struct fwd_handle *h, struct fwd_network *net)
{
fwd_ipt_addif(h, net->name);
}
static void fwd_delif_all_cb(struct fwd_handle *h, struct fwd_network *net)
{
fwd_ipt_delif(h, net->name);
}
#define fwd_addif_all(h) fwd_foreach_network(h, fwd_addif_all_cb)
#define fwd_delif_all(h) fwd_foreach_network(h, fwd_delif_all_cb)
static int fwd_server_main(int argc, const char *argv[])
{
struct fwd_handle *h;
struct fwd_network *net;
struct fwd_addr *addrs;
struct fwd_data *data;
struct fwd_cidr *addr_old, *addr_new;
struct sigaction sa;
int unix_client;
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
if( getuid() > 0 )
fwd_fatal("Need root permissions!");
if( !(h = fwd_alloc_ptr(struct fwd_handle)) )
fwd_fatal("Out of memory");
if( (h->rtnl_socket = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1 )
fwd_fatal("Failed to create AF_NETLINK socket (%m)");
if( (h->unix_socket = fwd_ipc_listen()) == -1 )
fwd_fatal("Failed to create AF_UNIX socket (%m)");
if( !(h->conf = fwd_read_config(h)) )
fwd_fatal("Failed to read configuration");
fwd_log_init();
fwd_ipt_build_ruleset(h);
fwd_addif_all(h);
while(1)
{
if( (addrs = fwd_get_addrs(h->rtnl_socket, AF_INET)) != NULL )
{
for( data = h->conf; data; data = data->next )
{
if( data->type != FWD_S_ZONE )
continue;
for( net = data->section.zone.networks; net; net = net->next )
{
addr_new = fwd_lookup_addr(addrs, net->ifname);
addr_old = net->addr;
if( !fwd_empty_cidr(addr_new) && fwd_empty_cidr(addr_old) )
{
fwd_log_info(
"Interface %s brought up - adding rules",
net->ifname
);
fwd_update_cidr(addr_old, addr_new);
fwd_ipt_addif(h, net->name);
}
else if( fwd_empty_cidr(addr_new) && !fwd_empty_cidr(addr_old) )
{
fwd_log_info(
"Interface %s went down - removing rules",
net->ifname
);
fwd_update_cidr(addr_old, NULL);
fwd_ipt_delif(h, net->name);
}
else if( ! fwd_equal_cidr(addr_old, addr_new) )
{
fwd_log_info(
"Interface %s changed IP - rebuilding rules",
net->ifname
);
fwd_update_cidr(addr_old, addr_new);
fwd_ipt_chgif(h, net->name);
}
}
}
fwd_free_addrs(addrs);
}
if( (unix_client = fwd_ipc_accept(h->unix_socket)) > -1 )
{
struct fwd_ipc_msg msg;
memset(&msg, 0, sizeof(struct fwd_ipc_msg));
while( fwd_ipc_recvmsg(unix_client, &msg, sizeof(struct fwd_ipc_msg)) > 0 )
{
fwd_log_info("Got message [%i]", msg.type);
switch(msg.type)
{
case FWD_IPC_FLUSH:
fwd_log_info("Flushing rules ...");
fwd_ipt_clear_ruleset(h);
fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
break;
case FWD_IPC_BUILD:
fwd_log_info("Building rules ...");
fwd_ipt_clear_ruleset(h);
fwd_ipt_build_ruleset(h);
fwd_addif_all(h);
fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
break;
case FWD_IPC_RELOAD:
if( (data = fwd_read_config(h)) != NULL )
{
fwd_log_info("Flushing rules ...");
fwd_ipt_clear_ruleset(h);
fwd_free_config(h->conf);
h->conf = data;
fwd_log_info("Building rules ...");
fwd_ipt_build_ruleset(h);
fwd_addif_all(h);
fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
}
else
{
fwd_log_err("Cannot reload configuration!");
fwd_ipc_sendtype(unix_client, FWD_IPC_ERROR);
}
break;
case FWD_IPC_ADDIF:
case FWD_IPC_DELIF:
if( strlen(msg.data.network) > 0 )
{
fwd_ipt_delif(h, msg.data.network);
if( msg.type == FWD_IPC_ADDIF )
fwd_ipt_addif(h, msg.data.network);
fwd_ipc_sendtype(unix_client, FWD_IPC_OK);
}
else
{
fwd_log_err("No network name provided!");
fwd_ipc_sendtype(unix_client, FWD_IPC_ERROR);
}
break;
case FWD_IPC_OK:
case FWD_IPC_ERROR:
break;
}
}
fwd_ipc_shutdown(unix_client);
}
sleep(1);
}
fwd_delif_all(h);
fwd_ipt_clear_ruleset(h);
close(h->rtnl_socket);
fwd_free_config(h->conf);
fwd_free_ptr(h);
return 0;
}
static void fwd_client_usage(const char *msg)
{
printf(
"%s\n\n"
"Usage:\n"
" fw flush\n"
" Flush all rules in the firewall and reset policy\n\n"
" fw build\n"
" Rebuild firewall rules\n\n"
" fw reload\n"
" Reload configuration and rebuild firewall rules\n\n"
" fw addif {network}\n"
" Add rules for given network\n\n"
" fw delif {network}\n"
" Remove rules for given network\n\n"
"", msg
);
exit(1);
}
static int fwd_client_main(int argc, const char *argv[])
{
int unix_server;
struct fwd_ipc_msg msg;
enum fwd_ipc_msgtype type;
if( argc < 2 )
fwd_client_usage("Command required");
if( (unix_server = fwd_ipc_connect()) < 0 )
fwd_fatal("Cannot connect to server instance (%m)");
memset(&msg, 0, sizeof(struct fwd_ipc_msg));
if( !strcmp(argv[1], "flush") )
type = FWD_IPC_FLUSH;
else if( !strcmp(argv[1], "build") )
type = FWD_IPC_BUILD;
else if( !strcmp(argv[1], "reload") )
type = FWD_IPC_RELOAD;
else if( !strcmp(argv[1], "addif") || !strcmp(argv[1], "delif") )
{
if( argc < 3 )
fwd_client_usage("The command requires a parameter.");
type = strcmp(argv[1], "addif") ? FWD_IPC_DELIF : FWD_IPC_ADDIF;
strncpy(msg.data.network, argv[2], sizeof(msg.data.network));
}
else
fwd_client_usage("Invalid command given.");
msg.type = type;
fwd_ipc_sendmsg(unix_server, &msg, sizeof(struct fwd_ipc_msg));
memset(&msg, 0, sizeof(struct fwd_ipc_msg));
while( fwd_ipc_recvmsg(unix_server, &msg, sizeof(struct fwd_ipc_msg)) == 0 )
continue;
switch(msg.type)
{
case FWD_IPC_OK:
printf("Success\n");
break;
case FWD_IPC_ERROR:
printf("The server reported an error, check logread!\n");
break;
default:
fwd_fatal("Unexpected response type %i", msg.type);
}
fwd_ipc_shutdown(unix_server);
return 0;
}
int main(int argc, const char *argv[])
{
if( strstr(argv[0], "fwd") )
return fwd_server_main(argc, argv);
else
return fwd_client_main(argc, argv);
}

View file

@ -1,182 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - data structures
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __FWD_H__
#define __FWD_H__
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <getopt.h>
#include <signal.h>
#include <netinet/in.h>
enum fwd_policy {
FWD_P_UNSPEC = 0,
FWD_P_DROP = 1,
FWD_P_REJECT = 2,
FWD_P_ACCEPT = 3
};
enum fwd_stype {
FWD_S_DEFAULTS = 0,
FWD_S_ZONE = 1,
FWD_S_FORWARD = 2,
FWD_S_REDIRECT = 3,
FWD_S_RULE = 4,
FWD_S_INCLUDE = 5
};
enum fwd_ptype {
FWD_PR_CUSTOM = 0,
FWD_PR_TCP = 1,
FWD_PR_UDP = 2,
FWD_PR_TCPUDP = 3,
FWD_PR_ICMP = 4,
FWD_PR_ALL = 5
};
struct fwd_portrange {
unsigned short min;
unsigned short max;
};
struct fwd_cidr {
struct in_addr addr;
int prefix;
};
struct fwd_mac {
unsigned char mac[6];
};
struct fwd_proto {
enum fwd_ptype type;
int proto;
};
struct fwd_icmptype {
char name[32];
int type;
int code;
};
struct fwd_network {
char *name;
char *ifname;
int isalias;
struct fwd_cidr *addr;
struct fwd_network *next;
};
struct fwd_defaults {
enum fwd_policy input;
enum fwd_policy forward;
enum fwd_policy output;
int syn_flood;
int syn_rate;
int syn_burst;
int drop_invalid;
};
struct fwd_zone {
char *name;
struct fwd_network *networks;
struct fwd_data *forwardings;
struct fwd_data *redirects;
struct fwd_data *rules;
enum fwd_policy input;
enum fwd_policy forward;
enum fwd_policy output;
int masq;
int mtu_fix;
int conntrack;
};
struct fwd_forwarding {
struct fwd_zone *src;
struct fwd_zone *dest;
int mtu_fix; /* legacy */
int masq; /* new */
};
struct fwd_redirect {
struct fwd_zone *src;
struct fwd_cidr *src_ip;
struct fwd_mac *src_mac;
struct fwd_portrange *src_port;
struct fwd_portrange *src_dport;
struct fwd_cidr *dest_ip;
struct fwd_portrange *dest_port;
struct fwd_proto *proto;
int clone; /* true if rule is cloned (tcpudp -> tcp + udp) */
};
struct fwd_rule {
struct fwd_zone *src;
struct fwd_zone *dest;
struct fwd_cidr *src_ip;
struct fwd_mac *src_mac;
struct fwd_portrange *src_port;
struct fwd_cidr *dest_ip;
struct fwd_portrange *dest_port;
struct fwd_proto *proto;
struct fwd_icmptype *icmp_type;
enum fwd_policy target;
int clone; /* true if rule is cloned (tcpudp -> tcp + udp) */
};
struct fwd_include {
char *path;
};
struct fwd_data {
enum fwd_stype type;
struct fwd_data *next;
union {
struct fwd_defaults defaults;
struct fwd_zone zone;
struct fwd_forwarding forwarding;
struct fwd_redirect redirect;
struct fwd_rule rule;
struct fwd_include include;
} section;
};
struct fwd_handle {
int rtnl_socket;
int unix_socket;
struct fwd_data *conf;
};
/* fwd_fatal(fmt, ...)
* Prints message to stderr and termintes program. */
#define fwd_fatal(...) do { \
fprintf(stderr, "ERROR: "); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
exit(1); \
} while(0)
#endif

View file

@ -1,162 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - rtnetlink communication
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#include "fwd.h"
#include "fwd_addr.h"
#include "fwd_utils.h"
struct fwd_addr * fwd_get_addrs(int fd, int family)
{
struct {
struct nlmsghdr n;
struct ifaddrmsg r;
} req;
int offlen;
int rtattrlen;
int dump_done;
char buf[16384];
struct rtattr *rta;
struct rtattr *rtatp;
struct nlmsghdr *nlmp;
struct ifaddrmsg *rtmp;
struct fwd_addr *head, *entry;
/* Build request */
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT;
req.n.nlmsg_type = RTM_GETADDR;
req.r.ifa_family = family;
rta = (struct rtattr *)(((char *)&req) + NLMSG_ALIGN(req.n.nlmsg_len));
rta->rta_len = RTA_LENGTH(family == AF_INET ? 4 : 16);
head = entry = NULL;
/* Send request */
if( send(fd, &req, sizeof(req), 0) <= 0 )
goto error;
/* Receive responses */
for( dump_done = 0; !dump_done; )
{
if( (offlen = recv(fd, buf, sizeof(buf), 0)) <= 0 )
goto error;
/* Parse message */
for(nlmp = (struct nlmsghdr *)buf; offlen > sizeof(*nlmp);)
{
/* Dump finished? */
if( nlmp->nlmsg_type == NLMSG_DONE )
{
dump_done = 1;
break;
}
int len = nlmp->nlmsg_len;
int req_len = len - sizeof(*nlmp);
if( req_len<0 || len>offlen )
goto error;
if( !NLMSG_OK(nlmp, offlen) )
goto error;
rtmp = (struct ifaddrmsg *) NLMSG_DATA(nlmp);
rtatp = (struct rtattr *) IFA_RTA(rtmp);
if( !(entry = fwd_alloc_ptr(struct fwd_addr)) )
goto error;
entry->index = rtmp->ifa_index;
if_indextoname(rtmp->ifa_index, (char *)&entry->ifname);
rtattrlen = IFA_PAYLOAD(nlmp);
for( ; RTA_OK(rtatp, rtattrlen); rtatp = RTA_NEXT(rtatp, rtattrlen) )
{
if( rtatp->rta_type == IFA_ADDRESS )
{
memcpy(&entry->ipaddr.addr, (char *) RTA_DATA(rtatp), rtatp->rta_len);
entry->ipaddr.prefix = rtmp->ifa_prefixlen;
entry->family = family;
}
else if( rtatp->rta_type == IFA_LABEL)
{
memcpy(&entry->label, (char *) RTA_DATA(rtatp), rtatp->rta_len);
}
}
entry->next = head;
head = entry;
offlen -= NLMSG_ALIGN(len);
nlmp = (struct nlmsghdr*)((char*)nlmp + NLMSG_ALIGN(len));
}
}
return head;
error:
fwd_free_addrs(head);
head = entry = NULL;
return NULL;
}
struct fwd_cidr * fwd_lookup_addr(struct fwd_addr *head, const char *ifname)
{
struct fwd_addr *entry;
for( entry = head; entry; entry = entry->next )
if( !strncmp(entry->ifname, ifname, IFNAMSIZ) )
return &entry->ipaddr;
return NULL;
}
void fwd_free_addrs(struct fwd_addr *head)
{
struct fwd_addr *entry = head;
while( entry != NULL )
{
head = entry->next;
free(entry);
entry = head;
}
head = entry = NULL;
}
struct fwd_addr * fwd_append_addrs(struct fwd_addr *head, struct fwd_addr *add)
{
struct fwd_addr *entry = head;
while( entry->next != NULL )
entry = entry->next;
return (entry->next = add);
}

View file

@ -1,50 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - header for rtnetlink communication
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __FWD_ADDR_H__
#define __FWD_ADDR_H__
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <arpa/inet.h>
struct fwd_addr {
char ifname[IFNAMSIZ];
char label[IFNAMSIZ];
int family;
int index;
struct fwd_cidr ipaddr;
struct fwd_addr *next;
};
struct fwd_addr * fwd_get_addrs(int, int);
struct fwd_addr * fwd_append_addrs(struct fwd_addr *, struct fwd_addr *);
void fwd_free_addrs(struct fwd_addr *);
struct fwd_cidr * fwd_lookup_addr(struct fwd_addr *, const char *);
#define fwd_foreach_addrs(head, entry) for(entry = head; entry; entry = entry->next)
#endif

View file

@ -1,987 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - config parsing
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#include "fwd.h"
#include "fwd_addr.h"
#include "fwd_config.h"
#include "fwd_utils.h"
#include "ucix.h"
#define fwd_read_error(...) do { \
fwd_log_err(__VA_ARGS__); \
return; \
} while(0)
/*
* Parse helpers
*/
static int
fwd_read_policy(struct uci_context *uci, const char *s, const char *o)
{
const char *val = ucix_get_option(uci, "firewall", s, o);
if( val != NULL )
{
switch( val[0] )
{
case 'D':
case 'd':
return FWD_P_DROP;
case 'R':
case 'r':
return FWD_P_REJECT;
case 'A':
case 'a':
return FWD_P_ACCEPT;
}
}
return FWD_P_UNSPEC;
}
static int
fwd_read_bool(struct uci_context *uci, const char *s, const char *o, int d)
{
const char *val = ucix_get_option(uci, "firewall", s, o);
if( val != NULL )
{
if( !strcmp(val, "yes") || !strcmp(val, "true") || !strcmp(val, "1") )
return 1;
else
return 0;
}
return d;
}
static unsigned int
fwd_read_uint(struct uci_context *uci, const char *s, const char *o, unsigned int d)
{
const char *val = ucix_get_option(uci, "firewall", s, o);
if( val != NULL )
{
return atoi(val);
}
return d;
}
static int
fwd_read_cidr(struct uci_context *uci, const char *s, const char *o, struct fwd_cidr **c)
{
const char *val = ucix_get_option(uci, "firewall", s, o);
char ip[32], prefix[32];
struct in_addr ina;
memset(ip, 0, 32);
memset(prefix, 0, 32);
if( val == NULL )
{
return 0;
}
else if( (strlen(val) < 32) && (sscanf(val, "%[^/]/%s", ip, prefix) > 0) )
{
if( !(*c = fwd_alloc_ptr(struct fwd_cidr)) )
goto inval;
if( inet_aton(ip, &ina) )
{
(*c)->addr.s_addr = ina.s_addr;
if( strchr(prefix, '.') )
{
if( inet_aton(prefix, &ina) )
{
(*c)->prefix = 32;
ina.s_addr = ntohl(ina.s_addr);
while( !(ina.s_addr & 1) )
{
ina.s_addr >>= 1;
(*c)->prefix--;
}
}
else
{
goto inval;
}
}
else
{
(*c)->prefix = prefix[0] ? atoi(prefix) : 32;
if( ((*c)->prefix < 0) || ((*c)->prefix > 32) )
{
goto inval;
}
}
return 0;
}
}
inval:
fwd_free_ptr(*c);
return -1;
}
static int
fwd_read_mac(struct uci_context *uci, const char *s, const char *o, struct fwd_mac **m)
{
const char *val = ucix_get_option(uci, "firewall", s, o);
if( val == NULL )
{
return 0;
}
else
{
if( (*m = fwd_alloc_ptr(struct fwd_mac)) != NULL )
{
unsigned int i1, i2, i3, i4, i5, i6;
if( sscanf(val, "%2x:%2x:%2x:%2x:%2x:%2x",
&i1, &i2, &i3, &i4, &i5, &i6) == 6
) {
(*m)->mac[0] = (unsigned char)i1;
(*m)->mac[1] = (unsigned char)i2;
(*m)->mac[2] = (unsigned char)i3;
(*m)->mac[3] = (unsigned char)i4;
(*m)->mac[4] = (unsigned char)i5;
(*m)->mac[5] = (unsigned char)i6;
return 0;
}
}
}
fwd_free_ptr(*m);
return -1;
}
static int
fwd_read_portrange(struct uci_context *uci, const char *s, const char *o, struct fwd_portrange **p)
{
const char *val = ucix_get_option(uci, "firewall", s, o);
int min = -1;
int max = -1;
unsigned int tmp;
if( val == NULL )
{
return 0;
}
else if( sscanf(val, "%u%*[:-]%u", &min, &max) > 0 )
{
if( max == -1 )
{
max = min;
}
else if( min > max )
{
tmp = max;
max = min;
min = tmp;
}
if( (min >= 0) && (min <= 65535) && (max >= 0) && (max <= 65535) )
{
if( (*p = fwd_alloc_ptr(struct fwd_portrange)) != NULL )
{
(*p)->min = min;
(*p)->max = max;
return 0;
}
}
}
fwd_free_ptr(*p);
return -1;
}
static int
fwd_read_proto(struct uci_context *uci, const char *s, const char *o, struct fwd_proto **p)
{
const char *val = ucix_get_option(uci, "firewall", s, o);
int proto;
if( val == NULL )
{
return 0;
}
else
{
if( (*p = fwd_alloc_ptr(struct fwd_proto)) != NULL )
{
proto = atoi(val);
if( !strcasecmp(val, "all") )
{
(*p)->type = FWD_PR_ALL;
(*p)->proto = 0;
}
else if( !strcasecmp(val, "icmp") )
{
(*p)->type = FWD_PR_ICMP;
(*p)->proto = 0;
}
else if( !strcasecmp(val, "udp") )
{
(*p)->type = FWD_PR_UDP;
(*p)->proto = 0;
}
else if( !strcasecmp(val, "tcp") )
{
(*p)->type = FWD_PR_TCP;
(*p)->proto = 0;
}
else if( !strcasecmp(val, "tcpudp") )
{
(*p)->type = FWD_PR_TCPUDP;
(*p)->proto = 0;
}
else if( proto > 0 )
{
(*p)->type = FWD_PR_CUSTOM;
(*p)->proto = proto;
}
else
{
goto inval;
}
return 0;
}
}
inval:
fwd_free_ptr(*p);
return -1;
}
static int
fwd_read_icmptype(struct uci_context *uci, const char *s, const char *o, struct fwd_icmptype **i)
{
const char *val = ucix_get_option(uci, "firewall", s, o);
unsigned int type, code;
if( val == NULL )
{
return 0;
}
else
{
if( (*i = fwd_alloc_ptr(struct fwd_icmptype)) != NULL )
{
if( sscanf(val, "%u/%u", &type, &code) == 2 )
{
if( (type > 255) || (code > 255) )
goto inval;
(*i)->type = type;
(*i)->code = code;
return 0;
}
else if( sscanf(val, "%u", &type) == 1 )
{
if( type > 255 )
goto inval;
(*i)->type = type;
(*i)->code = -1;
return 0;
}
/* XXX: no validity check here but I do not want to
duplicate libipt_icmp.c ... */
else if( sscanf(val, "%31s", (*i)->name) == 1 )
{
return 0;
}
}
}
inval:
fwd_free_ptr(*i);
return -1;
}
static const char *
fwd_read_string(struct uci_context *uci, const char *s, const char *o)
{
return ucix_get_option(uci, "firewall", s, o);
}
static void
fwd_append_config(struct fwd_data *h, struct fwd_data *a)
{
while( h->next )
h = h->next;
h->next = a;
}
/*
* config defaults
*/
static void fwd_read_defaults_cb(
struct uci_context *uci,
const char *s, struct fwd_defaults *d
) {
d->input = fwd_read_policy(uci, s, "input");
d->forward = fwd_read_policy(uci, s, "forward");
d->output = fwd_read_policy(uci, s, "output");
d->syn_flood = fwd_read_bool(uci, s, "syn_flood", 1);
d->syn_rate = fwd_read_uint(uci, s, "syn_rate", 25);
d->syn_burst = fwd_read_uint(uci, s, "syn_burst", 50);
d->drop_invalid = fwd_read_bool(uci, s, "drop_invalid", 1);
}
static struct fwd_data *
fwd_read_defaults(struct uci_context *uci)
{
struct fwd_data *dt;
struct fwd_defaults d;
if( (dt = fwd_alloc_ptr(struct fwd_data)) != NULL )
{
memset(&d, 0, sizeof(d));
ucix_for_each_section_type(uci, "firewall", "defaults",
(void *)fwd_read_defaults_cb, &d);
memcpy(&dt->section.defaults, &d, sizeof(d));
dt->type = FWD_S_DEFAULTS;
dt->next = NULL;
return dt;
}
return NULL;
}
/*
* config zone
*/
static void fwd_read_zone_networks_cb(
const char *net, struct fwd_network **np
) {
struct fwd_network *nn;
if( (nn = fwd_alloc_ptr(struct fwd_network)) != NULL )
{
nn->name = strdup(net);
nn->next = *np;
*np = nn;
}
}
static void fwd_read_zones_cb(
struct uci_context *uci,
const char *s, struct fwd_data_conveyor *cv
) {
struct fwd_data *dtn;
struct fwd_network *net = NULL;
const char *name;
if( !(name = fwd_read_string(uci, s, "name")) )
fwd_read_error("section '%s' is missing 'name' option!", s);
if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
{
dtn->section.zone.name = strdup(name);
dtn->section.zone.masq = fwd_read_bool(uci, s, "masq", 0);
dtn->section.zone.mtu_fix = fwd_read_bool(uci, s, "mtu_fix", 0);
dtn->section.zone.conntrack = fwd_read_bool(uci, s, "conntrack", 0);
dtn->section.zone.input = fwd_read_policy(uci, s, "input")
?: cv->head->section.defaults.input ?: FWD_P_DROP;
dtn->section.zone.forward = fwd_read_policy(uci, s, "forward")
?: cv->head->section.defaults.forward ?: FWD_P_DROP;
dtn->section.zone.output = fwd_read_policy(uci, s, "output")
?: cv->head->section.defaults.output ?: FWD_P_DROP;
/* try to parse option/list network ... */
if( ucix_for_each_list(uci, "firewall", s, "network",
(void *)&fwd_read_zone_networks_cb, &net) < 0 )
{
/* ... didn't work, fallback to option name */
fwd_read_zone_networks_cb(name, &net);
}
dtn->section.zone.networks = net;
dtn->type = FWD_S_ZONE;
dtn->next = cv->cursor;
cv->cursor = dtn;
}
}
static struct fwd_data *
fwd_read_zones(struct uci_context *uci, struct fwd_data *def)
{
struct fwd_data_conveyor cv;
cv.cursor = NULL;
cv.head = def;
ucix_for_each_section_type(uci, "firewall", "zone",
(void *)fwd_read_zones_cb, &cv);
return cv.cursor;
}
/*
* config forwarding
*/
static void fwd_read_forwards_cb(
struct uci_context *uci,
const char *s, struct fwd_data_conveyor *cv
) {
const char *src, *dest;
struct fwd_data *dtn;
struct fwd_zone *zsrc = NULL;
struct fwd_zone *zdest = NULL;
if( !(src = fwd_read_string(uci, s, "src")) )
fwd_read_error("section '%s' is missing 'src' option!", s);
else if( !(zsrc = fwd_lookup_zone(cv->head, src)) )
fwd_read_error("section '%s' references unknown src zone '%s'!", s, src);
else if( !(dest = fwd_read_string(uci, s, "dest")) )
fwd_read_error("section '%s' is missing 'dest' option!", s);
else if( !(zdest = fwd_lookup_zone(cv->head, dest)) )
fwd_read_error("section '%s' references unknown dest zone '%s'!", s, dest);
if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
{
dtn->section.forwarding.src = zsrc;
dtn->section.forwarding.dest = zdest;
dtn->section.forwarding.mtu_fix = fwd_read_bool(uci, s, "mtu_fix", 0);
dtn->section.forwarding.masq = fwd_read_bool(uci, s, "masq", 0);
dtn->type = FWD_S_FORWARD;
if( zsrc )
{
dtn->next = zsrc->forwardings;
zsrc->forwardings = dtn;
}
else
{
dtn->next = cv->cursor;
cv->cursor = dtn;
}
}
else
{
fwd_read_error("out of memory while parsing config!");
}
}
static struct fwd_data *
fwd_read_forwards(struct uci_context *uci, struct fwd_data *zones)
{
struct fwd_data_conveyor cv;
cv.cursor = NULL;
cv.head = zones;
ucix_for_each_section_type(uci, "firewall", "forwarding",
(void *)fwd_read_forwards_cb, &cv);
return cv.cursor;
}
/*
* config redirect
*/
static void fwd_read_redirects_cb(
struct uci_context *uci,
const char *s, struct fwd_data_conveyor *cv
) {
const char *src;
struct fwd_data *dtn = NULL;
struct fwd_data *dtn2 = NULL;
struct fwd_zone *zsrc = NULL;
/* check zone */
if( !(src = fwd_read_string(uci, s, "src")) )
fwd_read_error(
"section '%s' is missing 'src' option!",
s
);
else if( !(zsrc = fwd_lookup_zone(cv->head, src)) )
fwd_read_error(
"section '%s' references unknown src zone '%s'!",
s, src
);
/* uci context, section, name, type */
fwd_check_option(uci, s, src_ip, cidr);
fwd_check_option(uci, s, src_mac, mac);
fwd_check_option(uci, s, src_port, portrange);
fwd_check_option(uci, s, src_dport, portrange);
fwd_check_option(uci, s, dest_ip, cidr);
fwd_check_option(uci, s, dest_port, portrange);
fwd_check_option(uci, s, proto, proto);
if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
{
dtn->section.redirect.proto = proto;
dtn->section.redirect.src = zsrc;
dtn->section.redirect.src_ip = src_ip;
dtn->section.redirect.src_mac = src_mac;
dtn->section.redirect.src_port = src_port;
dtn->section.redirect.src_dport = src_dport;
dtn->section.redirect.dest_ip = dest_ip;
dtn->section.redirect.dest_port = dest_port;
dtn->type = FWD_S_REDIRECT;
dtn->next = zsrc->redirects;
zsrc->redirects = dtn;
if( (proto != NULL) && (proto->type == FWD_PR_TCPUDP) )
{
if( !(dtn2 = fwd_alloc_ptr(struct fwd_data)) ||
!(dtn2->section.redirect.proto = fwd_alloc_ptr(struct fwd_proto))
) {
fwd_free_ptr(dtn2);
fwd_read_error("out of memory while parsing config!");
}
dtn->section.redirect.proto->type = FWD_PR_UDP;
dtn2->section.redirect.proto->type = FWD_PR_TCP;
dtn2->section.redirect.src = zsrc;
dtn2->section.redirect.src_ip = src_ip;
dtn2->section.redirect.src_mac = src_mac;
dtn2->section.redirect.src_port = src_port;
dtn2->section.redirect.src_dport = src_dport;
dtn2->section.redirect.dest_ip = dest_ip;
dtn2->section.redirect.dest_port = dest_port;
dtn2->section.redirect.clone = 1;
dtn2->type = FWD_S_REDIRECT;
dtn2->next = zsrc->redirects;
zsrc->redirects = dtn2;
}
}
else
{
fwd_read_error("out of memory while parsing config!");
}
}
static struct fwd_data *
fwd_read_redirects(struct uci_context *uci, struct fwd_data *zones)
{
struct fwd_data_conveyor cv;
cv.cursor = NULL;
cv.head = zones;
ucix_for_each_section_type(uci, "firewall", "redirect",
(void *)fwd_read_redirects_cb, &cv);
return cv.cursor;
}
/*
* config rule
*/
static void fwd_read_rules_cb(
struct uci_context *uci,
const char *s, struct fwd_data_conveyor *cv
) {
const char *src, *dest;
struct fwd_data *dtn = NULL;
struct fwd_data *dtn2 = NULL;
struct fwd_zone *zsrc = NULL;
struct fwd_zone *zdest = NULL;
/* check zones */
if( !(src = fwd_read_string(uci, s, "src")) )
fwd_read_error(
"section '%s' is missing 'src' option!",
s
);
else if( !(zsrc = fwd_lookup_zone(cv->head, src)) )
fwd_read_error(
"section '%s' references unknown src zone '%s'!",
s, src
);
if( (dest = fwd_read_string(uci, s, "dest")) != NULL )
if( !(zdest = fwd_lookup_zone(cv->head, dest)) )
fwd_read_error(
"section '%s' references unknown dest zone '%s'!",
s, dest
);
/* uci context, section, name, type */
fwd_check_option(uci, s, src_ip, cidr);
fwd_check_option(uci, s, src_mac, mac);
fwd_check_option(uci, s, src_port, portrange);
fwd_check_option(uci, s, dest_ip, cidr);
fwd_check_option(uci, s, dest_port, portrange);
fwd_check_option(uci, s, proto, proto);
fwd_check_option(uci, s, icmptype, icmptype);
if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
{
dtn->section.rule.proto = proto;
dtn->section.rule.icmp_type = icmptype;
dtn->section.rule.src = zsrc;
dtn->section.rule.src_ip = src_ip;
dtn->section.rule.src_mac = src_mac;
dtn->section.rule.src_port = src_port;
dtn->section.rule.dest = zdest;
dtn->section.rule.dest_ip = dest_ip;
dtn->section.rule.dest_port = dest_port;
dtn->section.rule.target = fwd_read_policy(uci, s, "target");
dtn->type = FWD_S_RULE;
dtn->next = zsrc->rules;
zsrc->rules = dtn;
if( (proto != NULL) && (proto->type == FWD_PR_TCPUDP) )
{
if( !(dtn2 = fwd_alloc_ptr(struct fwd_data)) ||
!(dtn2->section.rule.proto = fwd_alloc_ptr(struct fwd_proto))
) {
fwd_free_ptr(dtn2);
fwd_read_error("out of memory while parsing config!");
}
dtn->section.rule.proto->type = FWD_PR_UDP;
dtn2->section.rule.proto->type = FWD_PR_TCP;
dtn2->section.rule.src = zsrc;
dtn2->section.rule.src_ip = src_ip;
dtn2->section.rule.src_mac = src_mac;
dtn2->section.rule.src_port = src_port;
dtn2->section.rule.dest = zdest;
dtn2->section.rule.dest_ip = dest_ip;
dtn2->section.rule.dest_port = dest_port;
dtn2->section.rule.target = dtn->section.rule.target;
dtn2->section.rule.clone = 1;
dtn2->type = FWD_S_RULE;
dtn2->next = zsrc->rules;
zsrc->rules = dtn2;
}
}
else
{
fwd_read_error("out of memory while parsing config!");
}
}
static struct fwd_data *
fwd_read_rules(struct uci_context *uci, struct fwd_data *zones)
{
struct fwd_data_conveyor cv;
cv.cursor = NULL;
cv.head = zones;
ucix_for_each_section_type(uci, "firewall", "rule",
(void *)fwd_read_rules_cb, &cv);
return cv.cursor;
}
/*
* config include
*/
static void fwd_read_includes_cb(
struct uci_context *uci,
const char *s, struct fwd_data_conveyor *cv
) {
const char *path = fwd_read_string(uci, s, "path");
struct fwd_data *dtn = NULL;
if( path != NULL )
{
if( (dtn = fwd_alloc_ptr(struct fwd_data)) != NULL )
{
dtn->section.include.path = strdup(path);
dtn->type = FWD_S_INCLUDE;
dtn->next = cv->cursor;
cv->cursor = dtn;
}
else
{
fwd_read_error("out of memory while parsing config!");
}
}
}
static struct fwd_data *
fwd_read_includes(struct uci_context *uci)
{
struct fwd_data_conveyor cv;
cv.cursor = NULL;
cv.head = NULL;
ucix_for_each_section_type(uci, "firewall", "include",
(void *)fwd_read_includes_cb, &cv);
return cv.cursor;
}
/*
* config interface
*/
static void fwd_read_network_data(
struct uci_context *uci, struct fwd_network *net
) {
struct fwd_network *e;
const char *type, *ifname;
for( e = net; e; e = e->next )
{
if( (type = ucix_get_option(uci, "network", e->name, NULL)) != NULL )
{
if( !(ifname = ucix_get_option(uci, "network", e->name, "ifname")) )
fwd_read_error(
"section '%s' is missing 'ifname' option!",
e->name
);
e->isalias = (strcmp(type, "alias") ? 0 : 1);
e->ifname = strdup(ifname);
}
}
}
static void fwd_read_networks(
struct uci_context *uci, struct fwd_data *zones
) {
struct fwd_data *e;
for( e = zones; e; e = e->next )
if( e->type == FWD_S_ZONE )
fwd_read_network_data(uci, e->section.zone.networks);
}
static void fwd_free_networks(struct fwd_network *h)
{
struct fwd_network *e = h;
while( h != NULL )
{
e = h->next;
fwd_free_ptr(h->name);
fwd_free_ptr(h->ifname);
fwd_free_ptr(h->addr);
free(h);
h = e;
}
e = h = NULL;
}
static struct fwd_cidr * fwd_alloc_cidr(struct fwd_cidr *addr)
{
struct fwd_cidr *cidr;
if( (cidr = fwd_alloc_ptr(struct fwd_cidr)) != NULL )
{
if( addr != NULL )
{
cidr->addr.s_addr = addr->addr.s_addr;
cidr->prefix = addr->prefix;
}
return cidr;
}
return NULL;
}
struct fwd_data * fwd_read_config(struct fwd_handle *h)
{
struct uci_context *ctx;
struct fwd_data *defaults, *zones, *e;
struct fwd_addr *addrs;
struct fwd_network *net;
struct fwd_zone *zone;
if( (ctx = ucix_init("firewall")) != NULL )
{
if( !(defaults = fwd_read_defaults(ctx)) )
goto error;
if( !(zones = fwd_read_zones(ctx, defaults)) )
goto error;
fwd_append_config(defaults, zones);
fwd_append_config(defaults, fwd_read_forwards(ctx, zones));
fwd_append_config(defaults, fwd_read_redirects(ctx, zones));
fwd_append_config(defaults, fwd_read_rules(ctx, zones));
fwd_append_config(defaults, fwd_read_includes(ctx));
ucix_cleanup(ctx);
if( (ctx = ucix_init("network")) != NULL )
{
fwd_read_networks(ctx, zones);
ucix_cleanup(ctx);
if( !(addrs = fwd_get_addrs(h->rtnl_socket, AF_INET)) )
goto error;
for( e = zones; e && (zone = &e->section.zone); e = e->next )
{
if( e->type != FWD_S_ZONE )
break;
for( net = zone->networks; net; net = net->next )
{
net->addr = fwd_alloc_cidr(
fwd_lookup_addr(addrs, net->ifname)
);
}
}
fwd_free_addrs(addrs);
return defaults;
}
}
error:
if( ctx ) ucix_cleanup(ctx);
fwd_free_config(defaults);
fwd_free_config(zones);
return NULL;
}
void fwd_free_config(struct fwd_data *h)
{
struct fwd_data *e = h;
while( h != NULL )
{
e = h->next;
switch(h->type)
{
case FWD_S_INCLUDE:
fwd_free_ptr(h->section.include.path);
break;
case FWD_S_ZONE:
fwd_free_ptr(h->section.zone.name);
fwd_free_networks(h->section.zone.networks);
fwd_free_config(h->section.zone.rules);
fwd_free_config(h->section.zone.redirects);
fwd_free_config(h->section.zone.forwardings);
break;
case FWD_S_REDIRECT:
/* Clone rules share all pointers except proto.
Prevent a double-free here */
if( ! h->section.redirect.clone )
{
fwd_free_ptr(h->section.redirect.src_ip);
fwd_free_ptr(h->section.redirect.src_mac);
fwd_free_ptr(h->section.redirect.src_port);
fwd_free_ptr(h->section.redirect.src_dport);
fwd_free_ptr(h->section.redirect.dest_ip);
fwd_free_ptr(h->section.redirect.dest_port);
}
fwd_free_ptr(h->section.redirect.proto);
break;
case FWD_S_RULE:
/* Clone rules share all pointers except proto.
Prevent a double-free here */
if( ! h->section.rule.clone )
{
fwd_free_ptr(h->section.rule.src_ip);
fwd_free_ptr(h->section.rule.src_mac);
fwd_free_ptr(h->section.rule.src_port);
fwd_free_ptr(h->section.rule.dest_ip);
fwd_free_ptr(h->section.rule.dest_port);
fwd_free_ptr(h->section.rule.icmp_type);
}
fwd_free_ptr(h->section.rule.proto);
break;
case FWD_S_DEFAULTS:
case FWD_S_FORWARD:
/* Make gcc happy */
break;
}
fwd_free_ptr(h);
h = e;
}
e = h = NULL;
}
struct fwd_zone *
fwd_lookup_zone(struct fwd_data *h, const char *n)
{
struct fwd_data *e;
if( n != NULL )
{
for( e = h; e; e = e->next )
{
if( (e->type = FWD_S_ZONE) && !strcmp(e->section.zone.name, n) )
return &e->section.zone;
}
}
return NULL;
}

View file

@ -1,29 +0,0 @@
#ifndef __FWD_CONFIG_H__
#define __FWD_CONFIG_H__
#include "fwd.h"
#include "ucix.h"
/* fwd_check_option(uci_ctx, section, name, type) */
#define fwd_check_option(uci, sct, name, type) \
struct fwd_##type *name = NULL; \
if( fwd_read_##type(uci, sct, #name, &name) ) \
{ \
printf("ERROR: section '%s' contains invalid %s in '%s'!\n", \
sct, #type, #name); \
return; \
}
/* structure to access fwd_data* in uci iter callbacks */
struct fwd_data_conveyor {
struct fwd_data *head;
struct fwd_data *cursor;
};
/* api */
struct fwd_data * fwd_read_config(struct fwd_handle *);
struct fwd_zone * fwd_lookup_zone(struct fwd_data *, const char *);
void fwd_free_config(struct fwd_data *);
#endif

View file

@ -1,98 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - unix domain socket parts
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#include "fwd.h"
#include "fwd_ipc.h"
int fwd_ipc_listen(void)
{
int fd;
struct sockaddr_un addr;
if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 )
fwd_fatal("Cannot create AF_UNIX socket: %m");
memset(&addr, 0, sizeof(struct sockaddr_un));
strcpy(addr.sun_path, FWD_SOCKET_PATH);
addr.sun_family = AF_UNIX;
unlink(FWD_SOCKET_PATH);
if( bind(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0 )
fwd_fatal("Cannot bind AF_UNIX socket: %m");
if( listen(fd, 1) < 0 )
fwd_fatal("Cannot listen on AF_UNIX socket: %m");
//fcntl(fd, F_SETFL, O_NONBLOCK);
return fd;
}
int fwd_ipc_accept(int fd)
{
return accept(fd, NULL, NULL);
}
int fwd_ipc_connect(void)
{
int fd;
struct sockaddr_un addr;
if( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0 )
fwd_fatal("Cannot create AF_UNIX socket: %m");
memset(&addr, 0, sizeof(struct sockaddr_un));
strcpy(addr.sun_path, FWD_SOCKET_PATH);
addr.sun_family = AF_UNIX;
if( connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0 )
fwd_fatal("Cannot connect AF_UNIX socket: %m");
fcntl(fd, F_SETFL, O_NONBLOCK);
return fd;
}
int fwd_ipc_recvmsg(int fd, void *buf, int len)
{
return recv(fd, buf, len, 0);
}
int fwd_ipc_sendmsg(int fd, void *buf, int len)
{
return send(fd, buf, len, 0);
}
void fwd_ipc_shutdown(int fd)
{
shutdown(fd, SHUT_RDWR);
close(fd);
}
int fwd_ipc_sendtype(int fd, enum fwd_ipc_msgtype type)
{
struct fwd_ipc_msg msg;
memset(&msg, 0, sizeof(struct fwd_ipc_msg));
msg.type = type;
return fwd_ipc_sendmsg(fd, &msg, sizeof(struct fwd_ipc_msg));
}

View file

@ -1,61 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - unix domain socket headers
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __FWD_IPC_H__
#define __FWD_IPC_H__
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#define FWD_SOCKET_PATH "/var/run/fwd.sock"
enum fwd_ipc_msgtype {
FWD_IPC_OK = 0,
FWD_IPC_ERROR = 1,
FWD_IPC_FLUSH = 2,
FWD_IPC_BUILD = 3,
FWD_IPC_RELOAD = 4,
FWD_IPC_ADDIF = 5,
FWD_IPC_DELIF = 6
};
struct fwd_ipc_msg {
enum fwd_ipc_msgtype type;
union {
char network[256];
} data;
};
int fwd_ipc_listen(void);
int fwd_ipc_accept(int);
int fwd_ipc_connect(void);
int fwd_ipc_recvmsg(int, void *, int);
int fwd_ipc_sendmsg(int, void *, int);
void fwd_ipc_shutdown(int);
int fwd_ipc_sendtype(int, enum fwd_ipc_msgtype);
#endif

View file

@ -1,886 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - iptables rule set
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#include "fwd.h"
#include "fwd_addr.h"
#include "fwd_rules.h"
#include "fwd_xtables.h"
#include "fwd_utils.h"
/* -P <chain> <policy> */
static void fwd_r_set_policy(
struct iptc_handle *h, const char *chain, const char *policy
) {
iptc_set_policy(chain, policy, NULL, h);
}
/* -N <chain> */
static void fwd_r_new_chain(struct iptc_handle *h, const char *chain)
{
iptc_create_chain(chain, h);
}
/* -A <chain1> -j <chain2> */
static void fwd_r_jump_chain(
struct iptc_handle *h, const char *chain1, const char *chain2
) {
struct fwd_xt_rule *r;
if( (r = fwd_xt_init_rule(h)) != NULL )
{
fwd_xt_get_target(r, chain2);
fwd_xt_append_rule(r, chain1);
}
}
/* -A <chain> -m state --state INVALID -j DROP */
static void fwd_r_drop_invalid(struct iptc_handle *h, const char *chain)
{
struct fwd_xt_rule *r;
struct xtables_match *m;
if( (r = fwd_xt_init_rule(h)) != NULL )
{
if( (m = fwd_xt_get_match(r, "state")) != NULL )
{
fwd_xt_parse_match(r, m, "--state", "INVALID");
fwd_xt_get_target(r, "DROP");
fwd_xt_append_rule(r, chain);
}
}
}
/* -A <chain> -m state --state RELATED,ESTABLISHED -j ACCEPT */
static void fwd_r_accept_related(struct iptc_handle *h, const char *chain)
{
struct fwd_xt_rule *r;
struct xtables_match *m;
if( (r = fwd_xt_init_rule(h)) != NULL )
{
if( (m = fwd_xt_get_match(r, "state")) != NULL )
{
fwd_xt_parse_match(r, m, "--state", "RELATED,ESTABLISHED");
fwd_xt_get_target(r, "ACCEPT");
fwd_xt_append_rule(r, chain);
}
}
}
/* -A INPUT -i lo -j ACCEPT; -A OUTPUT -o lo -j ACCEPT */
static void fwd_r_accept_lo(struct iptc_handle *h)
{
struct fwd_network n;
struct fwd_xt_rule *r;
n.ifname = "lo";
if( (r = fwd_xt_init_rule(h)) != NULL )
{
fwd_xt_parse_in(r, &n, 0);
fwd_xt_get_target(r, "ACCEPT");
fwd_xt_append_rule(r, "INPUT");
}
if( (r = fwd_xt_init_rule(h)) != NULL )
{
fwd_xt_parse_out(r, &n, 0);
fwd_xt_get_target(r, "ACCEPT");
fwd_xt_append_rule(r, "OUTPUT");
}
}
/* build syn_flood chain and jump rule */
static void fwd_r_add_synflood(struct iptc_handle *h, struct fwd_defaults *def)
{
struct fwd_proto p;
struct fwd_xt_rule *r;
struct xtables_match *m;
char buf[32];
/* -N syn_flood */
fwd_r_new_chain(h, "syn_flood");
/* return rule */
if( (r = fwd_xt_init_rule(h)) != NULL )
{
/* -p tcp */
p.type = FWD_PR_TCP;
fwd_xt_parse_proto(r, &p, 0);
/* -m tcp --syn */
if( (m = fwd_xt_get_match(r, "tcp")) != NULL )
{
fwd_xt_parse_match(r, m, "--syn");
}
/* -m limit --limit x/second --limit-burst y */
if( (m = fwd_xt_get_match(r, "limit")) != NULL )
{
sprintf(buf, "%i/second", def->syn_rate);
fwd_xt_parse_match(r, m, "--limit", buf);
sprintf(buf, "%i", def->syn_burst);
fwd_xt_parse_match(r, m, "--limit-burst", buf);
}
/* -j RETURN; -A syn_flood */
fwd_xt_get_target(r, "RETURN");
fwd_xt_append_rule(r, "syn_flood");
}
/* drop rule */
if( (r = fwd_xt_init_rule(h)) != NULL )
{
/* -j DROP; -A syn_flood */
fwd_xt_get_target(r, "DROP");
fwd_xt_append_rule(r, "syn_flood");
}
/* jump to syn_flood rule */
if( (r = fwd_xt_init_rule(h)) != NULL )
{
/* -p tcp */
p.type = FWD_PR_TCP;
fwd_xt_parse_proto(r, &p, 0);
/* -m tcp --syn */
if( (m = fwd_xt_get_match(r, "tcp")) != NULL )
{
fwd_xt_parse_match(r, m, "--syn");
}
/* -j syn_flood; -A INPUT */
fwd_xt_get_target(r, "syn_flood");
fwd_xt_append_rule(r, "INPUT");
}
}
/* build reject target chain */
static void fwd_r_handle_reject(struct iptc_handle *h)
{
struct fwd_proto p;
struct fwd_xt_rule *r;
struct xtables_target *t;
/* -N handle_reject */
fwd_r_new_chain(h, "handle_reject");
/* tcp reject rule */
if( (r = fwd_xt_init_rule(h)) != NULL )
{
/* -p tcp */
p.type = FWD_PR_TCP;
fwd_xt_parse_proto(r, &p, 0);
/* -j REJECT --reject-with tcp-reset */
if( (t = fwd_xt_get_target(r, "REJECT")) != NULL )
{
fwd_xt_parse_target(r, t, "--reject-with", "tcp-reset");
}
/* -A handle_reject */
fwd_xt_append_rule(r, "handle_reject");
}
/* common reject rule */
if( (r = fwd_xt_init_rule(h)) != NULL )
{
/* -j REJECT --reject-with icmp-port-unreachable */
if( (t = fwd_xt_get_target(r, "REJECT")) != NULL )
{
fwd_xt_parse_target(r, t, "--reject-with",
"icmp-port-unreachable");
}
/* -A handle_reject */
fwd_xt_append_rule(r, "handle_reject");
}
}
/* build drop target chain */
static void fwd_r_handle_drop(struct iptc_handle *h)
{
struct fwd_xt_rule *r;
/* -N handle_drop */
fwd_r_new_chain(h, "handle_drop");
/* common drop rule */
if( (r = fwd_xt_init_rule(h)) != NULL )
{
/* -j DROP; -A handle_drop */
fwd_xt_get_target(r, "DROP");
fwd_xt_append_rule(r, "handle_drop");
}
}
/* build accept target chain */
static void fwd_r_handle_accept(struct iptc_handle *h)
{
struct fwd_xt_rule *r;
/* -N handle_accept */
fwd_r_new_chain(h, "handle_accept");
/* common accept rule */
if( (r = fwd_xt_init_rule(h)) != NULL )
{
/* -j ACCEPT; -A handle_accept */
fwd_xt_get_target(r, "ACCEPT");
fwd_xt_append_rule(r, "handle_accept");
}
}
/* add comment match */
static void fwd_r_add_comment(
struct fwd_xt_rule *r, const char *t, struct fwd_zone *z,
struct fwd_network *n
) {
struct xtables_match *m;
char buf[256];
if( (m = fwd_xt_get_match(r, "comment")) != NULL )
{
snprintf(buf, sizeof(buf), "%s:net=%s zone=%s", t, n->name, z->name);
fwd_xt_parse_match(r, m, "--comment", buf);
}
}
/* add --sport (if applicable) */
static void fwd_r_add_sport(
struct fwd_xt_rule *r, struct fwd_portrange *p
) {
int proto = r->entry->ip.proto;
char buf[12];
struct xtables_match *m;
/* have portrange and proto is tcp or udp ... */
if( (p != NULL) && ((proto == 6) || (proto == 17)) )
{
/* get match ... */
if( (m = fwd_xt_get_match(r, (proto == 6) ? "tcp" : "udp")) != NULL )
{
snprintf(buf, sizeof(buf), "%u:%u", p->min, p->max);
fwd_xt_parse_match(r, m, "--sport", buf);
}
}
}
/* add --dport (if applicable) */
static void fwd_r_add_dport(
struct fwd_xt_rule *r, struct fwd_portrange *p
) {
int proto = r->entry->ip.proto;
char buf[12];
struct xtables_match *m;
/* have portrange and proto is tcp or udp ... */
if( (p != NULL) && ((proto == 6) || (proto == 17)) )
{
/* get match ... */
if( (m = fwd_xt_get_match(r, (proto == 6) ? "tcp" : "udp")) != NULL )
{
snprintf(buf, sizeof(buf), "%u:%u", p->min, p->max);
fwd_xt_parse_match(r, m, "--dport", buf);
}
}
}
/* add --icmp-type (of applicable) */
static void fwd_r_add_icmptype(
struct fwd_xt_rule *r, struct fwd_icmptype *i
) {
int proto = r->entry->ip.proto;
struct xtables_match *m;
char buf[32];
/* have icmp-type and proto is icmp ... */
if( (i != NULL) && (proto == 1) )
{
/* get match ... */
if( (m = fwd_xt_get_match(r, "icmp")) != NULL )
{
if( i->name[0] )
snprintf(buf, sizeof(buf), "%s", i->name);
else
snprintf(buf, sizeof(buf), "%u/%u", i->type, i->code);
fwd_xt_parse_match(r, m, "--icmp-type", buf);
}
}
}
/* add -m mac --mac-source ... */
static void fwd_r_add_srcmac(
struct fwd_xt_rule *r, struct fwd_mac *mac
) {
struct xtables_match *m;
char buf[18];
if( mac != NULL )
{
if( (m = fwd_xt_get_match(r, "mac")) != NULL )
{
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
mac->mac[0], mac->mac[1], mac->mac[2],
mac->mac[3], mac->mac[4], mac->mac[5]);
fwd_xt_parse_match(r, m, "--mac-source", buf);
}
}
}
/* add policy target */
static void fwd_r_add_policytarget(
struct fwd_xt_rule *r, enum fwd_policy pol
) {
switch(pol)
{
case FWD_P_ACCEPT:
fwd_xt_get_target(r, "handle_accept");
break;
case FWD_P_REJECT:
fwd_xt_get_target(r, "handle_reject");
break;
case FWD_P_DROP:
case FWD_P_UNSPEC:
fwd_xt_get_target(r, "handle_drop");
break;
}
}
/* add dnat target */
static void fwd_r_add_dnattarget(
struct fwd_xt_rule *r, struct fwd_cidr *c, struct fwd_portrange *p
) {
struct xtables_target *t;
char buf[32];
if( c != NULL )
{
if( (t = fwd_xt_get_target(r, "DNAT")) != NULL )
{
if( p != NULL )
snprintf(buf, sizeof(buf), "%s:%u-%u",
inet_ntoa(c->addr), p->min, p->max);
else
snprintf(buf, sizeof(buf), "%s", inet_ntoa(c->addr));
fwd_xt_parse_target(r, t, "--to-destination", buf);
}
}
}
/* parse comment string and look for match */
static int fwd_r_cmp(const char *what, const char *cmt, const char *cmp)
{
char *match;
if( (match = strstr(cmt, what)) == NULL )
return 0;
match += strlen(what);
if( strncmp(match, cmp, strlen(cmp)) != 0 )
return 0;
if( (match[strlen(cmp)] != ' ') && (match[strlen(cmp)] != '\0') )
return 0;
return 1;
}
static void fwd_ipt_defaults_create(struct fwd_data *d)
{
struct fwd_defaults *def = &d->section.defaults;
struct iptc_handle *h_filter, *h_nat;
if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
fwd_fatal("Unable to obtain libiptc handle");
/* policies */
fwd_r_set_policy(h_filter, "INPUT",
def->input == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
fwd_r_set_policy(h_filter, "OUTPUT",
def->output == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
fwd_r_set_policy(h_filter, "FORWARD",
def->forward == FWD_P_ACCEPT ? "ACCEPT" : "DROP");
/* invalid state drop */
if( def->drop_invalid )
{
fwd_r_drop_invalid(h_filter, "INPUT");
fwd_r_drop_invalid(h_filter, "OUTPUT");
fwd_r_drop_invalid(h_filter, "FORWARD");
}
/* default accept related */
fwd_r_accept_related(h_filter, "INPUT");
fwd_r_accept_related(h_filter, "OUTPUT");
fwd_r_accept_related(h_filter, "FORWARD");
/* default accept on lo */
fwd_r_accept_lo(h_filter);
/* syn flood protection */
if( def->syn_flood )
{
fwd_r_add_synflood(h_filter, def);
}
/* rule container chains */
fwd_r_new_chain(h_filter, "mssfix");
fwd_r_new_chain(h_filter, "zones");
fwd_r_new_chain(h_filter, "rules");
fwd_r_new_chain(h_filter, "redirects");
fwd_r_new_chain(h_filter, "forwardings");
fwd_r_jump_chain(h_filter, "INPUT", "rules");
fwd_r_jump_chain(h_filter, "FORWARD", "mssfix");
fwd_r_jump_chain(h_filter, "FORWARD", "zones");
fwd_r_jump_chain(h_filter, "FORWARD", "rules");
fwd_r_jump_chain(h_filter, "FORWARD", "redirects");
fwd_r_jump_chain(h_filter, "FORWARD", "forwardings");
fwd_r_new_chain(h_nat, "zonemasq");
fwd_r_new_chain(h_nat, "redirects");
fwd_r_new_chain(h_nat, "loopback");
fwd_r_jump_chain(h_nat, "POSTROUTING", "zonemasq");
fwd_r_jump_chain(h_nat, "PREROUTING", "redirects");
fwd_r_jump_chain(h_nat, "POSTROUTING", "loopback");
/* standard drop, accept, reject chain */
fwd_r_handle_drop(h_filter);
fwd_r_handle_accept(h_filter);
fwd_r_handle_reject(h_filter);
if( !iptc_commit(h_nat) )
fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
if( !iptc_commit(h_filter) )
fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
iptc_free(h_nat);
iptc_free(h_filter);
}
void fwd_ipt_build_ruleset(struct fwd_handle *h)
{
struct fwd_data *e;
fwd_xt_init();
for( e = h->conf; e; e = e->next )
{
switch(e->type)
{
case FWD_S_DEFAULTS:
fwd_log_info("Loading defaults");
fwd_ipt_defaults_create(e);
break;
case FWD_S_INCLUDE:
fwd_log_info("Loading include: %s",
e->section.include.path);
break;
case FWD_S_ZONE:
case FWD_S_FORWARD:
case FWD_S_REDIRECT:
case FWD_S_RULE:
/* Make gcc happy */
break;
}
}
}
static struct fwd_zone *
fwd_lookup_zone(struct fwd_handle *h, const char *net)
{
struct fwd_data *e;
struct fwd_network *n;
for( e = h->conf; e; e = e->next )
if( e->type == FWD_S_ZONE )
for( n = e->section.zone.networks; n; n = n->next )
if( !strcmp(n->name, net) )
return &e->section.zone;
return NULL;
}
static struct fwd_network *
fwd_lookup_network(struct fwd_zone *z, const char *net)
{
struct fwd_network *n;
for( n = z->networks; n; n = n->next )
if( !strcmp(n->name, net) )
return n;
return NULL;
}
void fwd_ipt_addif(struct fwd_handle *h, const char *net)
{
struct fwd_data *e;
struct fwd_zone *z;
struct fwd_rule *c;
struct fwd_redirect *r;
struct fwd_forwarding *f;
struct fwd_cidr *a, *a2;
struct fwd_network *n, *n2;
struct fwd_proto p;
struct fwd_xt_rule *x;
struct xtables_match *m;
struct xtables_target *t;
struct iptc_handle *h_filter, *h_nat;
if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
fwd_fatal("Unable to obtain libiptc handle");
if( !(z = fwd_lookup_zone(h, net)) )
return;
if( !(n = fwd_lookup_network(z, net)) )
return;
if( !(a = n->addr) || fwd_empty_cidr(a) )
return;
fwd_log_info("Adding network %s (interface %s)",
n->name, n->ifname);
/* Build masquerading rule */
if( z->masq )
{
if( (x = fwd_xt_init_rule(h_nat)) != NULL )
{
fwd_xt_parse_out(x, n, 0); /* -o ... */
fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */
fwd_r_add_comment(x, "masq", z, n); /* -m comment ... */
fwd_xt_append_rule(x, "zonemasq"); /* -A zonemasq */
}
}
/* Build MSS fix rule */
if( z->mtu_fix )
{
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
{
p.type = FWD_PR_TCP;
fwd_xt_parse_out(x, n, 0); /* -o ... */
fwd_xt_parse_proto(x, &p, 0); /* -p tcp */
/* -m tcp --tcp-flags SYN,RST SYN */
if( (m = fwd_xt_get_match(x, "tcp")) != NULL )
fwd_xt_parse_match(x, m, "--tcp-flags", "SYN,RST", "SYN");
/* -j TCPMSS --clamp-mss-to-pmtu */
if( (t = fwd_xt_get_target(x, "TCPMSS")) != NULL )
fwd_xt_parse_target(x, t, "--clamp-mss-to-pmtu");
/* -m comment ... */
fwd_r_add_comment(x, "mssfix", z, n);
/* -A mssfix */
fwd_xt_append_rule(x, "mssfix");
}
}
/* Build intra-zone forwarding rules */
for( n2 = z->networks; n2; n2 = n2->next )
{
if( (a2 = n2->addr) != NULL )
{
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
{
fwd_xt_parse_in(x, n, 0); /* -i ... */
fwd_xt_parse_out(x, n2, 0); /* -o ... */
fwd_r_add_policytarget(x, z->forward); /* -j handle_... */
fwd_r_add_comment(x, "zone", z, n); /* -m comment ... */
fwd_xt_append_rule(x, "zones"); /* -A zones */
}
}
}
/* Build inter-zone forwarding rules */
for( e = z->forwardings; e && (f = &e->section.forwarding); e = e->next )
{
for( n2 = f->dest->networks; n2; n2 = n2->next )
{
/* Build forwarding rule */
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
{
fwd_xt_parse_in(x, n, 0); /* -i ... */
fwd_xt_parse_out(x, n2, 0); /* -o ... */
fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_... */
fwd_r_add_comment(x, "forward", z, n); /* -m comment ... */
fwd_xt_append_rule(x, "forwardings"); /* -A forwardings */
}
}
}
/* Build DNAT rules */
for( e = z->redirects; e && (r = &e->section.redirect); e = e->next )
{
/* DNAT */
if( (x = fwd_xt_init_rule(h_nat)) != NULL )
{
fwd_xt_parse_in(x, n, 0); /* -i ... */
fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */
fwd_xt_parse_dest(x, a, 0); /* -d ... */
fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
fwd_r_add_sport(x, r->src_port); /* --sport ... */
fwd_r_add_dport(x, r->src_dport); /* --dport ... */
fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */
fwd_r_add_dnattarget(x, r->dest_ip, r->dest_port); /* -j DNAT ... */
fwd_r_add_comment(x, "redir", z, n); /* -m comment ... */
fwd_xt_append_rule(x, "redirects"); /* -A redirects */
}
/* Forward */
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
{
fwd_xt_parse_in(x, n, 0); /* -i ... */
fwd_xt_parse_src(x, r->src_ip, 0); /* -s ... */
fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */
fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
fwd_r_add_srcmac(x, r->src_mac); /* -m mac --mac-source ... */
fwd_r_add_sport(x, r->src_port); /* --sport ... */
fwd_r_add_dport(x, r->dest_port); /* --dport ... */
fwd_r_add_policytarget(x, FWD_P_ACCEPT); /* -j handle_accept */
fwd_r_add_comment(x, "redir", z, n); /* -m comment ... */
fwd_xt_append_rule(x, "redirects"); /* -A redirects */
}
/* Add loopback rule if neither src_ip nor src_mac are defined */
if( !r->src_ip && !r->src_mac )
{
if( (x = fwd_xt_init_rule(h_nat)) != NULL )
{
fwd_xt_parse_in(x, n, 1); /* -i ! ... */
fwd_xt_parse_dest(x, r->dest_ip, 0); /* -d ... */
fwd_xt_parse_proto(x, r->proto, 0); /* -p ... */
fwd_r_add_sport(x, r->src_port); /* --sport ... */
fwd_r_add_dport(x, r->src_dport); /* --dport ... */
fwd_xt_get_target(x, "MASQUERADE"); /* -j MASQUERADE */
fwd_r_add_comment(x, "redir", z, n); /* -m comment ... */
fwd_xt_append_rule(x, "loopback"); /* -A loopback */
}
}
}
/* Build rules */
for( e = z->rules; e && (c = &e->section.rule); e = e->next )
{
/* Has destination, add forward rule for each network in target zone */
if( c->dest )
{
for( n2 = c->dest->networks; n2; n2 = n2->next )
{
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
{
fwd_xt_parse_in(x, n, 0); /* -i ... */
fwd_xt_parse_out(x, n2, 0); /* -o ... */
fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */
fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */
fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */
fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */
fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */
fwd_r_add_sport(x, c->src_port); /* --sport ... */
fwd_r_add_dport(x, c->dest_port); /* --dport ... */
fwd_r_add_policytarget(x, c->target); /* -j handle_... */
fwd_r_add_comment(x, "rule", z, n); /* -m comment ... */
fwd_xt_append_rule(x, "rules"); /* -A rules */
}
}
}
/* No destination specified, treat it as input rule */
else
{
if( (x = fwd_xt_init_rule(h_filter)) != NULL )
{
fwd_xt_parse_in(x, n, 0); /* -i ... */
fwd_xt_parse_src(x, c->src_ip, 0); /* -s ... */
fwd_xt_parse_dest(x, c->dest_ip, 0); /* -d ... */
fwd_xt_parse_proto(x, c->proto, 0); /* -p ... */
fwd_r_add_icmptype(x, c->icmp_type); /* --icmp-type ... */
fwd_r_add_srcmac(x, c->src_mac); /* --mac-source ... */
fwd_r_add_sport(x, c->src_port); /* --sport ... */
fwd_r_add_dport(x, c->dest_port); /* --dport ... */
fwd_r_add_policytarget(x, c->target); /* -j handle_... */
fwd_r_add_comment(x, "rule", z, n); /* -m comment ... */
fwd_xt_append_rule(x, "rules"); /* -A rules */
}
}
}
if( !iptc_commit(h_nat) )
fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
if( !iptc_commit(h_filter) )
fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
iptc_free(h_nat);
iptc_free(h_filter);
}
static void fwd_ipt_delif_table(struct iptc_handle *h, const char *net)
{
const struct xt_entry_match *m;
const struct ipt_entry *e;
const char *chain, *comment;
size_t off = 0, num = 0;
/* iterate chains */
for( chain = iptc_first_chain(h); chain;
chain = iptc_next_chain(h)
) {
/* iterate rules */
for( e = iptc_first_rule(chain, h), num = 0; e;
e = iptc_next_rule(e, h), num++
) {
repeat_rule:
/* skip entries w/o matches */
if( ! e->target_offset )
continue;
/* iterate matches */
for( off = sizeof(struct ipt_entry);
off < e->target_offset;
off += m->u.match_size
) {
m = (void *)e + off;
/* yay */
if( ! strcmp(m->u.user.name, "comment") )
{
/* better use struct_xt_comment_info but well... */
comment = (void *)m + sizeof(struct xt_entry_match);
if( fwd_r_cmp("net=", comment, net) )
{
e = iptc_next_rule(e, h);
iptc_delete_num_entry(chain, num, h);
if( e != NULL )
goto repeat_rule;
else
break;
}
}
}
}
}
}
void fwd_ipt_delif(struct fwd_handle *h, const char *net)
{
struct iptc_handle *h_filter, *h_nat;
if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
fwd_fatal("Unable to obtain libiptc handle");
fwd_log_info("Removing network %s", net);
/* delete network related rules */
fwd_ipt_delif_table(h_nat, net);
fwd_ipt_delif_table(h_filter, net);
if( !iptc_commit(h_nat) )
fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
if( !iptc_commit(h_filter) )
fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
iptc_free(h_nat);
iptc_free(h_filter);
}
void fwd_ipt_chgif(struct fwd_handle *h, const char *net)
{
/* XXX: should alter rules in-place, tbd */
fwd_ipt_delif(h, net);
fwd_ipt_addif(h, net);
}
static void fwd_ipt_clear_ruleset_table(struct iptc_handle *h)
{
const char *chain;
/* pass 1: flush all chains */
for( chain = iptc_first_chain(h); chain;
chain = iptc_next_chain(h)
) {
iptc_flush_entries(chain, h);
}
/* pass 2: remove user defined chains */
for( chain = iptc_first_chain(h); chain;
chain = iptc_next_chain(h)
) {
if( ! iptc_builtin(chain, h) )
iptc_delete_chain(chain, h);
}
}
void fwd_ipt_clear_ruleset(struct fwd_handle *h)
{
struct iptc_handle *h_filter, *h_nat;
if( !(h_filter = iptc_init("filter")) || !(h_nat = iptc_init("nat")) )
fwd_fatal("Unable to obtain libiptc handle");
/* flush tables */
fwd_ipt_clear_ruleset_table(h_nat);
fwd_ipt_clear_ruleset_table(h_filter);
/* revert policies */
fwd_r_set_policy(h_filter, "INPUT", "ACCEPT");
fwd_r_set_policy(h_filter, "OUTPUT", "ACCEPT");
fwd_r_set_policy(h_filter, "FORWARD", "ACCEPT");
if( !iptc_commit(h_nat) )
fwd_fatal("Cannot commit nat table: %s", iptc_strerror(errno));
if( !iptc_commit(h_filter) )
fwd_fatal("Cannot commit filter table: %s", iptc_strerror(errno));
iptc_free(h_nat);
iptc_free(h_filter);
}

View file

@ -1,32 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - header for iptables rule set
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __FWD_RULES_H__
#define __FWD_RULES_H__
#include "fwd.h"
void fwd_ipt_build_ruleset(struct fwd_handle *h);
void fwd_ipt_clear_ruleset(struct fwd_handle *h);
void fwd_ipt_addif(struct fwd_handle *h, const char *net);
void fwd_ipt_delif(struct fwd_handle *h, const char *net);
void fwd_ipt_chgif(struct fwd_handle *h, const char *net);
#endif

View file

@ -1,78 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - commmon utility functions
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#include "fwd_utils.h"
void fwd_log_init(void)
{
openlog("Firewall", 0, LOG_DAEMON | LOG_PERROR);
}
void __fwd_log(int prio, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
vsyslog(prio, msg, ap);
va_end(ap);
}
int fwd_empty_cidr(struct fwd_cidr *c)
{
if( (c == NULL) || ((c->addr.s_addr == 0) && (c->prefix == 0)) )
return 1;
return 0;
}
int fwd_equal_cidr(struct fwd_cidr *a, struct fwd_cidr *b)
{
if( fwd_empty_cidr(a) && fwd_empty_cidr(b) )
return 1;
else if( (a->addr.s_addr == b->addr.s_addr) && (a->prefix == b->prefix) )
return 1;
return 0;
}
void fwd_update_cidr(struct fwd_cidr *a, struct fwd_cidr *b)
{
if( a != NULL )
{
a->addr.s_addr = b ? b->addr.s_addr : 0;
a->prefix = b ? b->prefix : 0;
}
}
/* fwd_zmalloc(size_t)
* Allocates a zeroed buffer of the given size. */
void * fwd_zmalloc(size_t s)
{
void *b = malloc(s);
if( b != NULL )
memset(b, 0, s);
return b;
}

View file

@ -1,50 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - commmon utility header
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __FWD_UTILS_H__
#define __FWD_UTILS_H__
#include <syslog.h>
#include "fwd.h"
void fwd_log_init(void);
void __fwd_log(int, const char *, ...);
#define fwd_log_info(...) __fwd_log(LOG_INFO, __VA_ARGS__)
#define fwd_log_err(...) __fwd_log(LOG_ERR, __VA_ARGS__)
int fwd_empty_cidr(struct fwd_cidr *);
int fwd_equal_cidr(struct fwd_cidr *, struct fwd_cidr *);
void fwd_update_cidr(struct fwd_cidr *, struct fwd_cidr *);
/* fwd_zmalloc(size_t)
* Allocates a zeroed buffer of the given size. */
void * fwd_zmalloc(size_t);
/* fwd_alloc_ptr(type)
* Allocates a buffer with the size of the given datatype
* and returns a pointer to it. */
#define fwd_alloc_ptr(t) (t *) fwd_zmalloc(sizeof(t))
/* fwd_free_ptr(void *)
* Frees the given pointer and sets it to NULL.
* Safe for NULL values. */
#define fwd_free_ptr(x) do { if(x != NULL) free(x); x = NULL; } while(0)
#endif

View file

@ -1,412 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - libiptc/libxtables interface
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#include "fwd.h"
#include "fwd_xtables.h"
#include "fwd_utils.h"
/* Required by certain extensions like SNAT and DNAT */
int kernel_version;
extern void
get_kernel_version(void) {
static struct utsname uts;
int x = 0, y = 0, z = 0;
if (uname(&uts) == -1) {
fprintf(stderr, "Unable to retrieve kernel version.\n");
xtables_free_opts(1);
exit(1);
}
sscanf(uts.release, "%d.%d.%d", &x, &y, &z);
kernel_version = LINUX_VERSION(x, y, z);
}
static void xt_exit_error(enum xtables_exittype status, const char *msg, ...)
{
va_list ap;
va_start(ap, msg);
vprintf(msg, ap);
va_end(ap);
exit(1);
}
void fwd_xt_init(void)
{
struct xtables_globals xt_globals = {
.option_offset = 0,
.program_version = IPTABLES_VERSION,
.opts = 0,
.orig_opts = 0,
.exit_err = (void *)&xt_exit_error,
};
xtables_init();
xtables_set_nfproto(NFPROTO_IPV4);
xtables_set_params(&xt_globals);
}
struct fwd_xt_rule * fwd_xt_init_rule(struct iptc_handle *h)
{
struct fwd_xt_rule *r;
if( (r = fwd_alloc_ptr(struct fwd_xt_rule)) != NULL )
{
if( (r->entry = fwd_alloc_ptr(struct ipt_entry)) != NULL )
{
r->iptc = h;
return r;
}
}
fwd_free_ptr(r);
return NULL;
}
void fwd_xt_parse_frag(
struct fwd_xt_rule *r, int frag, int inv
) {
if( frag )
{
r->entry->ip.flags |= IPT_F_FRAG;
if( inv )
r->entry->ip.invflags |= IPT_INV_FRAG;
}
}
void fwd_xt_parse_proto(
struct fwd_xt_rule *r, struct fwd_proto *p, int inv
) {
if( p != NULL )
{
switch(p->type)
{
case FWD_PR_TCP:
r->entry->ip.proto = 6;
break;
case FWD_PR_UDP:
r->entry->ip.proto = 17;
break;
case FWD_PR_ICMP:
r->entry->ip.proto = 1;
break;
case FWD_PR_CUSTOM:
r->entry->ip.proto = p->proto;
break;
case FWD_PR_ALL:
case FWD_PR_TCPUDP:
r->entry->ip.proto = 0;
break;
}
if( inv )
r->entry->ip.invflags |= IPT_INV_PROTO;
}
}
void fwd_xt_parse_in(
struct fwd_xt_rule *r, struct fwd_network *n, int inv
) {
if( n != NULL )
{
strncpy(r->entry->ip.iniface, n->ifname, IFNAMSIZ);
if( inv )
r->entry->ip.invflags |= IPT_INV_VIA_IN;
}
}
void fwd_xt_parse_out(
struct fwd_xt_rule *r, struct fwd_network *n, int inv
) {
if( n != NULL )
{
strncpy(r->entry->ip.outiface, n->ifname, IFNAMSIZ);
if( inv )
r->entry->ip.invflags |= IPT_INV_VIA_OUT;
}
}
void fwd_xt_parse_src(
struct fwd_xt_rule *r, struct fwd_cidr *c, int inv
) {
if( c != NULL )
{
r->entry->ip.src.s_addr = c->addr.s_addr;
r->entry->ip.smsk.s_addr = htonl(~((1 << (32 - c->prefix)) - 1));
if( inv )
r->entry->ip.invflags |= IPT_INV_SRCIP;
}
}
void fwd_xt_parse_dest(
struct fwd_xt_rule *r, struct fwd_cidr *c, int inv
) {
if( c != NULL )
{
r->entry->ip.dst.s_addr = c->addr.s_addr;
r->entry->ip.dmsk.s_addr = htonl(~((1 << (32 - c->prefix)) - 1));
if( inv )
r->entry->ip.invflags |= IPT_INV_DSTIP;
}
}
struct xtables_match * fwd_xt_get_match(
struct fwd_xt_rule *r, const char *name
) {
struct xtables_match *m = xtables_find_match(name, XTF_TRY_LOAD, &r->matches);
size_t s;
if( m != NULL )
{
s = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
if( (m->m = malloc(s)) != NULL )
{
memset(m->m, 0, s);
strcpy(m->m->u.user.name, m->name);
m->m->u.match_size = s;
if( m->init )
m->init(m->m);
return m;
}
}
return NULL;
}
void __fwd_xt_parse_match(
struct fwd_xt_rule *r, struct xtables_match *m, ...
) {
char optc;
char *s, **opts;
size_t len = 1;
int inv = 0;
va_list ap;
va_start(ap, m);
opts = malloc(len * sizeof(*opts));
opts[0] = "x";
while( (s = (char *)va_arg(ap, char *)) != NULL )
{
opts = realloc(opts, ++len * sizeof(*opts));
opts[len-1] = s;
}
va_end(ap);
if( len > 1 )
{
optind = 0;
while( (optc = getopt_long(len, opts, "", m->extra_opts, NULL)) > -1 )
{
if( (optc == '?') && (optarg[0] == '!') && (optarg[1] == '\0') )
{
inv = 1;
continue;
}
m->parse(optc, opts, inv, &m->mflags, r->entry, &m->m);
inv = 0;
}
}
free(opts);
}
struct xtables_target * fwd_xt_get_target(
struct fwd_xt_rule *r, const char *name
) {
struct xtables_target *t = xtables_find_target(name, XTF_TRY_LOAD);
size_t s;
if( !t )
t = xtables_find_target(IPT_STANDARD_TARGET, XTF_LOAD_MUST_SUCCEED);
if( t != NULL )
{
s = IPT_ALIGN(sizeof(struct ipt_entry_target)) + t->size;
if( (t->t = malloc(s)) != NULL )
{
memset(t->t, 0, s);
strcpy(t->t->u.user.name, name);
t->t->u.target_size = s;
xtables_set_revision(t->t->u.user.name, t->revision);
if( t->init )
t->init(t->t);
r->target = t;
return t;
}
}
return NULL;
}
void __fwd_xt_parse_target(
struct fwd_xt_rule *r, struct xtables_target *t, ...
) {
char optc;
char *s, **opts;
size_t len = 1;
int inv = 0;
va_list ap;
va_start(ap, t);
opts = malloc(len * sizeof(*opts));
opts[0] = "x";
while( (s = (char *)va_arg(ap, char *)) != NULL )
{
opts = realloc(opts, ++len * sizeof(*opts));
opts[len-1] = s;
}
va_end(ap);
if( len > 1 )
{
optind = 0;
while( (optc = getopt_long(len, opts, "", t->extra_opts, NULL)) > -1 )
{
if( (optc == '?') && (optarg[0] == '!') && (optarg[1] == '\0') )
{
inv = 1;
continue;
}
t->parse(optc, opts, inv, &t->tflags, r->entry, &t->t);
inv = 0;
}
}
free(opts);
}
static int fwd_xt_exec_rule(struct fwd_xt_rule *r, const char *chain, int pos)
{
size_t s;
struct xtables_rule_match *m, *next;
struct xtables_match *em;
struct xtables_target *et;
struct ipt_entry *e;
int rv = 0;
s = IPT_ALIGN(sizeof(struct ipt_entry));
for( m = r->matches; m; m = m->next )
s += m->match->m->u.match_size;
if( (e = malloc(s + r->target->t->u.target_size)) != NULL )
{
memset(e, 0, s + r->target->t->u.target_size);
memcpy(e, r->entry, sizeof(struct ipt_entry));
e->target_offset = s;
e->next_offset = s + r->target->t->u.target_size;
s = 0;
for( m = r->matches; m; m = m->next )
{
memcpy(e->elems + s, m->match->m, m->match->m->u.match_size);
s += m->match->m->u.match_size;
}
memcpy(e->elems + s, r->target->t, r->target->t->u.target_size);
rv = (pos > -1)
? iptc_insert_entry(chain, e, (unsigned int) pos, r->iptc)
: iptc_append_entry(chain, e, r->iptc)
;
}
else
{
errno = ENOMEM;
}
fwd_free_ptr(e);
fwd_free_ptr(r->entry);
fwd_free_ptr(r->target->t);
for( m = r->matches; m; )
{
next = m->next;
fwd_free_ptr(m->match->m);
if( m->match == m->match->next )
fwd_free_ptr(m->match);
fwd_free_ptr(m);
m = next;
}
fwd_free_ptr(r);
/* reset all targets and matches */
for (em = xtables_matches; em; em = em->next)
em->mflags = 0;
for (et = xtables_targets; et; et = et->next)
{
et->tflags = 0;
et->used = 0;
}
return rv;
}
int fwd_xt_insert_rule(
struct fwd_xt_rule *r, const char *chain, unsigned int pos
) {
return fwd_xt_exec_rule(r, chain, pos);
}
int fwd_xt_append_rule(
struct fwd_xt_rule *r, const char *chain
) {
return fwd_xt_exec_rule(r, chain, -1);
}

View file

@ -1,70 +0,0 @@
/*
* fwd - OpenWrt firewall daemon - libiptc/libxtables interface headers
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.org>
*
* The fwd program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* The fwd program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the fwd program. If not, see http://www.gnu.org/licenses/.
*/
#ifndef __FWD_XTABLES_H__
#define __FWD_XTABLES_H__
#include <iptables.h>
#include <xtables.h>
#include <libiptc/libxtc.h>
#include <dlfcn.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/utsname.h>
struct fwd_xt_rule {
struct iptc_handle *iptc;
struct ipt_entry *entry;
struct xtables_rule_match *matches;
struct xtables_target *target;
};
/* Required by certain extensions like SNAT and DNAT */
extern int kernel_version;
extern void get_kernel_version(void);
void fwd_xt_init(void);
struct fwd_xt_rule * fwd_xt_init_rule(struct iptc_handle *h);
void fwd_xt_parse_proto(struct fwd_xt_rule *r, struct fwd_proto *p, int inv);
void fwd_xt_parse_in(struct fwd_xt_rule *r, struct fwd_network *n, int inv);
void fwd_xt_parse_out(struct fwd_xt_rule *r, struct fwd_network *n, int inv);
void fwd_xt_parse_src(struct fwd_xt_rule *r, struct fwd_cidr *c, int inv);
void fwd_xt_parse_dest(struct fwd_xt_rule *r, struct fwd_cidr *c, int inv);
void fwd_xt_parse_frag(struct fwd_xt_rule *r, int frag, int inv);
struct xtables_match * fwd_xt_get_match(struct fwd_xt_rule *r, const char *name);
void __fwd_xt_parse_match(struct fwd_xt_rule *r, struct xtables_match *m, ...);
#define fwd_xt_parse_match(r, m, ...) __fwd_xt_parse_match(r, m, __VA_ARGS__, NULL)
struct xtables_target * fwd_xt_get_target(struct fwd_xt_rule *r, const char *name);
void __fwd_xt_parse_target(struct fwd_xt_rule *r, struct xtables_target *t, ...);
#define fwd_xt_parse_target(r, t, ...) __fwd_xt_parse_target(r, t, __VA_ARGS__, NULL)
int fwd_xt_append_rule(struct fwd_xt_rule *r, const char *chain);
int fwd_xt_insert_rule(struct fwd_xt_rule *r, const char *chain, unsigned int pos);
#endif

View file

@ -1,236 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Copyright (C) 2008 John Crispin <blogic@openwrt.org>
*/
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <uci_config.h>
#include <uci.h>
#include "ucix.h"
static struct uci_ptr ptr;
static inline int ucix_get_ptr(struct uci_context *ctx, const char *p, const char *s, const char *o, const char *t)
{
memset(&ptr, 0, sizeof(ptr));
ptr.package = p;
ptr.section = s;
ptr.option = o;
ptr.value = t;
return uci_lookup_ptr(ctx, &ptr, NULL, true);
}
struct uci_context* ucix_init(const char *config_file)
{
struct uci_context *ctx = uci_alloc_context();
uci_add_history_path(ctx, "/var/state");
if(uci_load(ctx, config_file, NULL) != UCI_OK)
{
printf("%s/%s is missing or corrupt\n", ctx->savedir, config_file);
return NULL;
}
return ctx;
}
struct uci_context* ucix_init_path(const char *path, const char *config_file)
{
struct uci_context *ctx = uci_alloc_context();
if(path)
uci_set_confdir(ctx, path);
if(uci_load(ctx, config_file, NULL) != UCI_OK)
{
printf("%s/%s is missing or corrupt\n", ctx->savedir, config_file);
return NULL;
}
return ctx;
}
int ucix_load(struct uci_context *ctx, const char *config_file)
{
if(uci_load(ctx, config_file, NULL) != UCI_OK)
{
printf("%s/%s is missing or corrupt\n", ctx->savedir, config_file);
return 0;
}
return 1;
}
void ucix_cleanup(struct uci_context *ctx)
{
uci_free_context(ctx);
}
void ucix_save(struct uci_context *ctx)
{
uci_set_savedir(ctx, "/tmp/.uci/");
uci_save(ctx, NULL);
}
void ucix_save_state(struct uci_context *ctx)
{
uci_set_savedir(ctx, "/var/state/");
uci_save(ctx, NULL);
}
const char* ucix_get_option(struct uci_context *ctx, const char *p, const char *s, const char *o)
{
struct uci_element *e = NULL;
const char *value = NULL;
if(ucix_get_ptr(ctx, p, s, o, NULL))
return NULL;
if (!(ptr.flags & UCI_LOOKUP_COMPLETE))
return NULL;
e = ptr.last;
switch (e->type)
{
case UCI_TYPE_SECTION:
value = uci_to_section(e)->type;
break;
case UCI_TYPE_OPTION:
switch(ptr.o->type) {
case UCI_TYPE_STRING:
value = ptr.o->v.string;
break;
default:
value = NULL;
break;
}
break;
default:
return 0;
}
return value;
}
int ucix_for_each_list(
struct uci_context *ctx, const char *p, const char *s, const char *o,
void (*cb)(const char*, void*), void *priv)
{
struct uci_element *e = NULL;
char *value = NULL;
int count = 0;
if(ucix_get_ptr(ctx, p, s, o, NULL))
return -1;
if (!(ptr.flags & UCI_LOOKUP_COMPLETE))
return -1;
e = ptr.last;
if(e->type == UCI_TYPE_OPTION)
{
switch(ptr.o->type)
{
case UCI_TYPE_LIST:
uci_foreach_element(&ptr.o->v.list, e) {
cb(e->name, priv);
count++;
}
break;
case UCI_TYPE_STRING:
if( (value = strdup(ptr.o->v.string)) != NULL )
{
char *ts, *tt, *tp;
for( ts = value; 1; ts = NULL )
{
if( (tt = strtok_r(ts, " \t", &tp)) != NULL )
{
cb(tt, priv);
count++;
}
else
{
break;
}
}
free(value);
}
break;
}
return count;
}
return -1;
}
int ucix_get_option_int(struct uci_context *ctx, const char *p, const char *s, const char *o, int def)
{
const char *tmp = ucix_get_option(ctx, p, s, o);
int ret = def;
if (tmp)
ret = atoi(tmp);
return ret;
}
void ucix_add_section(struct uci_context *ctx, const char *p, const char *s, const char *t)
{
if(ucix_get_ptr(ctx, p, s, NULL, t))
return;
uci_set(ctx, &ptr);
}
void ucix_add_option(struct uci_context *ctx, const char *p, const char *s, const char *o, const char *t)
{
if(ucix_get_ptr(ctx, p, s, o, (t)?(t):("")))
return;
uci_set(ctx, &ptr);
}
void ucix_add_option_int(struct uci_context *ctx, const char *p, const char *s, const char *o, int t)
{
char tmp[64];
snprintf(tmp, 64, "%d", t);
ucix_add_option(ctx, p, s, o, tmp);
}
void ucix_del(struct uci_context *ctx, const char *p, const char *s, const char *o)
{
if(!ucix_get_ptr(ctx, p, s, o, NULL))
uci_delete(ctx, &ptr);
}
void ucix_revert(struct uci_context *ctx, const char *p, const char *s, const char *o)
{
if(!ucix_get_ptr(ctx, p, s, o, NULL))
uci_revert(ctx, &ptr);
}
void ucix_for_each_section_type(struct uci_context *ctx,
const char *p, const char *t,
void (*cb)(struct uci_context *, const char*, void*), void *priv)
{
struct uci_element *e;
if(ucix_get_ptr(ctx, p, NULL, NULL, NULL))
return;
uci_foreach_element(&ptr.p->sections, e)
if (!strcmp(t, uci_to_section(e)->type))
cb(ctx, e->name, priv);
}
int ucix_commit(struct uci_context *ctx, const char *p)
{
if(ucix_get_ptr(ctx, p, NULL, NULL, NULL))
return 1;
return uci_commit(ctx, &ptr.p, false);
}

View file

@ -1,50 +0,0 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*
* Copyright (C) 2008 John Crispin <blogic@openwrt.org>
*/
#ifndef __UCIX_H__
#define __UCIX_H_
struct uci_context* ucix_init(const char *config_file);
struct uci_context* ucix_init_path(const char *path, const char *config_file);
int ucix_load(struct uci_context *ctx, const char *config_file);
void ucix_cleanup(struct uci_context *ctx);
void ucix_save(struct uci_context *ctx);
void ucix_save_state(struct uci_context *ctx);
const char* ucix_get_option(struct uci_context *ctx,
const char *p, const char *s, const char *o);
int ucix_for_each_list(struct uci_context *ctx,
const char *p, const char *s, const char *o,
void (*cb)(const char*, void*), void *priv);
int ucix_get_option_int(struct uci_context *ctx,
const char *p, const char *s, const char *o, int def);
void ucix_add_section(struct uci_context *ctx,
const char *p, const char *s, const char *t);
void ucix_add_option(struct uci_context *ctx,
const char *p, const char *s, const char *o, const char *t);
void ucix_add_option_int(struct uci_context *ctx,
const char *p, const char *s, const char *o, int t);
void ucix_for_each_section_type(struct uci_context *ctx,
const char *p, const char *t,
void (*cb)(struct uci_context *, const char*, void*), void *priv);
int ucix_commit(struct uci_context *ctx, const char *p);
void ucix_revert(struct uci_context *ctx,
const char *p, const char *s, const char *o);
void ucix_del(struct uci_context *ctx, const char *p,
const char *s, const char *o);
#endif

View file

@ -1,13 +0,0 @@
GCC := gcc
CFLAGS := -Wall
LDFLAGS :=
OBJ = cli.o lar.o md5.o
BIN = lar
compile:
cli: $(OBJ)
$(GCC) $(CFLAGS) -o $(BIN) $(OBJ) $(LDFLAGS)
clean:
rm -f $(OBJ) $(BIN)

View file

@ -1,131 +0,0 @@
#include "lar.h"
int do_print_member( lar_archive *ar, const char *name )
{
lar_member *member;
if( (member = lar_open_member(ar, name)) != NULL )
{
write(fileno(stdout), member->data, member->length);
lar_close_member(member);
}
else
LAR_DIE("Unable to locate archive member");
return 0;
}
int do_print_index( lar_archive *ar )
{
lar_index *index = ar->index;
if( ar->has_filenames )
{
while(index)
{
if( index->type == LAR_TYPE_REGULAR )
{
printf("%s\n", index->filename);
}
index = index->next;
}
return 0;
}
LAR_DIE("The archive contains no file list");
return 1;
}
int do_require( const char *package, const char *path )
{
int stat = 1;
lar_archive *ar;
lar_member *mb;
if( (ar = lar_find_archive(package, path, 1)) != NULL )
{
if( (mb = lar_find_member(ar, package)) != NULL )
{
write(fileno(stdout), mb->data, mb->length);
lar_close_member(mb);
stat = 0;
}
lar_close(ar);
}
return stat;
}
int do_findfile( const char *filename, const char *path )
{
int stat = 1;
lar_archive *ar;
lar_member *mb;
if( (ar = lar_find_archive(filename, path, 0)) != NULL )
{
if( (mb = lar_open_member(ar, filename)) != NULL )
{
write(fileno(stdout), mb->data, mb->length);
lar_close_member(mb);
stat = 0;
}
lar_close(ar);
}
return stat;
}
int main( int argc, const char* argv[] )
{
lar_archive *ar;
int stat = 0;
if( argv[1] != NULL && argv[2] != NULL )
{
switch(argv[1][0])
{
case 's':
if( (ar = lar_open(argv[2])) != NULL )
{
if( argv[3] != NULL )
stat = do_print_member(ar, argv[3]);
else
stat = do_print_index(ar);
lar_close(ar);
}
else
{
LAR_DIE("Failed to open archive");
}
break;
case 'r':
stat = do_require(argv[2], argv[3]);
break;
case 'f':
stat = do_findfile(argv[2], argv[3]);
break;
}
return stat;
}
else
{
printf("Usage:\n");
printf("\tlar show <archive> [<member>]\n");
printf("\tlar require <package> [<path>]\n");
printf("\tlar find <filename> [<path>]\n");
return 1;
}
return 0;
}

View file

@ -1,328 +0,0 @@
/*
* lar - Lua Archive Library
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.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.
*/
#include "lar.h"
static int lar_read32( int fd, uint32_t *val )
{
uint8_t buffer[5];
if( read(fd, buffer, 4) < 4 )
LAR_DIE("Unexpected EOF while reading data");
buffer[4] = 0;
*val = ntohl(*((uint32_t *) buffer));
return 0;
}
static int lar_read16( int fd, uint16_t *val )
{
uint8_t buffer[3];
if( read(fd, buffer, 2) < 2 )
LAR_DIE("Unexpected EOF while reading data");
buffer[2] = 0;
*val = ntohs(*((uint16_t *) buffer));
return 0;
}
static void lar_md5( char *md5, const char *data, int len )
{
md5_state_t state;
md5_init(&state);
md5_append(&state, (const md5_byte_t *)data, len);
md5_finish(&state, (md5_byte_t *)md5);
}
static int lar_read_filenames( lar_archive *ar )
{
int i;
int j;
char *filelist;
size_t pgof;
size_t pgsz = getpagesize();
lar_index *idx_ptr;
lar_index *idx_filelist = ar->index;
while(idx_filelist)
{
if( idx_filelist->type == LAR_TYPE_FILELIST )
break;
idx_filelist = idx_filelist->next;
}
if( idx_filelist != NULL )
{
pgof = ( idx_filelist->offset % pgsz );
filelist = mmap(
0, idx_filelist->length + pgof, PROT_READ, MAP_PRIVATE,
ar->fd, idx_filelist->offset - pgof
);
if( filelist == MAP_FAILED )
LAR_DIE("Failed to mmap() file list");
idx_ptr = ar->index;
i = pgof;
while(idx_ptr)
{
if( idx_ptr->type == LAR_TYPE_REGULAR )
{
j = strlen(&filelist[i]) + 1;
if( (j >= LAR_FNAME_BUFFER) ||
((i+j) > (idx_filelist->length+pgof)) )
LAR_DIE("Filename exceeds maximum allowed length");
idx_ptr->filename = (char *)malloc(j);
memcpy(idx_ptr->filename, &filelist[i], j);
i += j;
}
idx_ptr = idx_ptr->next;
}
munmap(filelist, idx_filelist->length + pgof);
return 1;
}
return 0;
}
lar_index * lar_get_index( lar_archive *ar )
{
uint32_t i;
uint32_t idx_offset;
uint32_t idx_length;
lar_index *idx_map;
lar_index *idx_ptr;
if( lseek(ar->fd, -(sizeof(idx_offset)), SEEK_END) == -1 )
LAR_DIE("Unable to seek to end of archive");
lar_read32(ar->fd, &idx_offset);
idx_length = ( ar->length - idx_offset - sizeof(idx_offset) );
if( lseek(ar->fd, idx_offset, SEEK_SET) == -1 )
LAR_DIE("Unable to seek to archive index");
idx_map = NULL;
for( i = 0; i < idx_length; i += (sizeof(lar_index) - 2 * sizeof(char *)) )
{
idx_ptr = (lar_index *)malloc(sizeof(lar_index));
idx_ptr->filename = NULL;
lar_read32(ar->fd, &idx_ptr->offset);
lar_read32(ar->fd, &idx_ptr->length);
lar_read16(ar->fd, &idx_ptr->type);
lar_read16(ar->fd, &idx_ptr->flags);
if(read(ar->fd,&idx_ptr->id,sizeof(idx_ptr->id)) < sizeof(idx_ptr->id))
LAR_DIE("Unexpected EOF while reading member id");
idx_ptr->next = idx_map;
idx_map = idx_ptr;
}
return idx_map;
}
lar_member * lar_mmap_member( lar_archive *ar, lar_index *idx_ptr )
{
lar_member *member;
size_t pgsz = getpagesize();
size_t pgof = ( idx_ptr->offset % pgsz );
char *memberdata = mmap(
0, idx_ptr->length + pgof, PROT_READ, MAP_PRIVATE,
ar->fd, idx_ptr->offset - pgof
);
if( memberdata == MAP_FAILED )
LAR_DIE("Failed to mmap() member data");
member = (lar_member *)malloc(sizeof(lar_member));
member->type = idx_ptr->type;
member->flags = idx_ptr->flags;
member->length = idx_ptr->length;
member->data = &memberdata[pgof];
member->mmap = memberdata;
member->mlen = idx_ptr->length + pgof;
return member;
}
lar_member * lar_open_member( lar_archive *ar, const char *name )
{
lar_index *idx_ptr = ar->index;
char mbid[sizeof(idx_ptr->id)];
lar_md5(mbid, name, strlen(name));
while(idx_ptr)
{
if( !strncmp(mbid, idx_ptr->id, sizeof(mbid)) )
return lar_mmap_member(ar, idx_ptr);
idx_ptr = idx_ptr->next;
}
return NULL;
}
int lar_close_member( lar_member *member )
{
int stat = munmap(member->mmap, member->mlen);
free(member);
member = NULL;
return stat;
}
lar_archive * lar_open( const char *filename )
{
int fd;
struct stat as;
lar_archive *ar;
if( stat(filename, &as) == -1 )
return NULL;
if( !(as.st_mode & S_IFREG) )
return NULL;
if( (fd = open(filename, O_RDONLY)) != -1 )
{
ar = (lar_archive *)malloc(sizeof(lar_archive));
ar->fd = fd;
ar->length = as.st_size;
ar->index = lar_get_index(ar);
strncpy(ar->filename, filename, sizeof(ar->filename));
ar->has_filenames = lar_read_filenames(ar);
return ar;
}
return NULL;
}
int lar_close( lar_archive *ar )
{
lar_index *idx_head;
lar_index *idx_next;
close(ar->fd);
idx_head = ar->index;
do {
idx_next = idx_head->next;
free(idx_head->filename);
free(idx_head);
} while( (idx_head = idx_next) != NULL );
free(ar);
ar = NULL;
return 0;
}
lar_archive * lar_find_archive( const char *package, const char *path, int pkg )
{
uint32_t i;
uint32_t j;
uint32_t seg = 1;
uint32_t len = 0;
uint32_t pln = 0;
char sep = ( pkg ? '.' : '/' );
struct stat s;
LAR_FNAME(buffer);
if( path )
{
for( pln = 0; path[pln] != '\0'; pln++ )
if( pln >= (sizeof(buffer) - 5) )
LAR_DIE("Library path exceeds maximum allowed length");
memcpy(buffer, path, pln);
}
if( buffer[pln-1] != '/' )
buffer[pln++] = '/';
for( len = 0; package[len] != '\0'; len++ )
{
if( len >= (sizeof(buffer) - 5 - pln) )
LAR_DIE("Package name exceeds maximum allowed length");
if( package[len] == sep ) seg++;
}
while( seg > 0 )
{
for( i = 0, j = 1; (i < len) && (j <= seg); i++ )
{
if( package[i] == sep ) {
if( j < seg ) j++; else break;
}
buffer[pln+i] = ( package[i] == sep ) ? LAR_DIRSEP : package[i];
}
strcpy(&buffer[pln+i], ".lar");
if( (stat(buffer, &s) > -1) && (s.st_mode & S_IFREG) )
return lar_open(buffer);
seg--;
}
return NULL;
}
lar_member * lar_find_member( lar_archive *ar, const char *package )
{
int len;
LAR_FNAME(buffer);
for( len = 0; package[len] != '\0'; len++ )
{
if( len >= (sizeof(buffer) - 5) )
LAR_DIE("Package name exceeds maximum allowed length");
buffer[len] = ( package[len] == '.' ) ? '/' : package[len];
}
strcpy(&buffer[len], ".lua");
return lar_open_member(ar, buffer);
}

View file

@ -1,108 +0,0 @@
/*
* lar - Lua Archive Library
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.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 __LAR_H
#define __LAR_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "md5.h"
#define LAR_DIE(s) \
do { \
fprintf(stderr, "%s(%i): %s(): %s\n", \
__FILE__, __LINE__, __FUNCTION__, s); \
if( errno ) fprintf(stderr, "%s(%i): %s\n", \
__FILE__, __LINE__, strerror(errno) ); \
exit(1); \
} while(0)
#define LAR_FNAME_BUFFER 1024
#define LAR_FNAME(s) char s[LAR_FNAME_BUFFER]
#define LAR_TYPE_REGULAR 0x0000
#define LAR_TYPE_FILELIST 0xFFFF
#ifdef __WIN32__
#define LAR_DIRSEP '\\'
#else
#define LAR_DIRSEP '/'
#endif
struct lar_index_item {
uint32_t offset;
uint32_t length;
uint16_t type;
uint16_t flags;
char id[16];
char *filename;
struct lar_index_item *next;
};
struct lar_member_item {
uint16_t type;
uint16_t flags;
uint32_t length;
char *data;
char *mmap;
size_t mlen;
};
struct lar_archive_handle {
int fd;
int has_filenames;
off_t length;
char filename[LAR_FNAME_BUFFER];
struct lar_index_item *index;
};
typedef struct lar_index_item lar_index;
typedef struct lar_member_item lar_member;
typedef struct lar_archive_handle lar_archive;
lar_index * lar_get_index( lar_archive *ar );
lar_member * lar_mmap_member( lar_archive *ar, lar_index *idx_ptr );
lar_member * lar_open_member( lar_archive *ar, const char *name );
int lar_close_member( lar_member *member );
lar_archive * lar_open( const char *filename );
int lar_close( lar_archive *ar );
lar_archive * lar_find_archive( const char *package, const char *path, int pkg);
lar_member * lar_find_member( lar_archive *ar, const char *package );
#endif

View file

@ -1,50 +0,0 @@
#!/usr/bin/perl
use strict;
@ARGV || die "Usage: $0 <file1> <file2> ... <fileN>\n";
my @index;
my $offset = 0;
foreach my $file ( @ARGV )
{
if( -f $file && open F, "< $file" )
{
warn sprintf "Member at 0x%08X\n", $offset;
push @index, [ ];
my $size = length $file;
print $file;
print "\0" x ( $size % 4 );
$index[-1][0] = $offset;
$index[-1][1] = $size;
$index[-1][2] = $offset + $size + ( $size % 4 );
$size = 0;
while( read F, my $buffer, 4096 ) {
$size += length $buffer;
print $buffer;
}
print "\0" x ( $size % 4 );
$index[-1][3] = $size;
$offset = $index[-1][2] + $size + ( $size % 4 );
close F;
}
}
my $count = 1;
foreach my $file ( @index )
{
warn sprintf "Index[%4d]: 0x%08X 0x%08X 0x%08X 0x%08X\n", $count++, $file->[0], $file->[1], $file->[2], $file->[3];
print pack "NNNNnn", $file->[0], $file->[1], $file->[2], $file->[3], 0x0000, 0x0000;
}
warn sprintf "Index at 0x%08X, length 0x%08X\n", $offset, @index * 20;
print pack "N", $offset;

View file

@ -1,540 +0,0 @@
/*
* lar - Lua Archive Library
*
* Copyright (C) 2009 Jo-Philipp Wich <xm@subsignal.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.
*/
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "lar.h"
typedef struct {
int fd;
char *data;
size_t length;
} mmap_handle;
static int larlib_perror( lua_State *L, const char *message )
{
lua_pushnil(L);
lua_pushstring(L, message);
return 2;
}
int larlib_open( lua_State *L )
{
lar_archive *ar, **udata;
const char *filename = luaL_checkstring( L, 1 );
if( filename != NULL && (ar = lar_open(filename)) != NULL )
{
if( (udata = lua_newuserdata(L, sizeof(lar_archive *))) != NULL )
{
*udata = ar;
luaL_getmetatable(L, "lar.archive");
lua_setmetatable(L, -2);
}
else
{
return luaL_error(L, "Out of memory");
}
}
else
{
return larlib_perror(L, "Archive not found");
}
return 1;
}
int larlib_find( lua_State *L )
{
const char *filename = luaL_checkstring( L, 1 );
const char *basepath = luaL_optstring( L, 2, "./" );
int is_pkg = strstr(filename, "/") ? 0 : 1;
lar_archive *ar, **udata;
if( ((ar = lar_find_archive(filename, basepath, is_pkg)) != NULL) ||
((ar = lar_find_archive(filename, LUA_LDIR, is_pkg)) != NULL) ||
((ar = lar_find_archive(filename, LUA_CDIR, is_pkg)) != NULL) )
{
if( (udata = lua_newuserdata(L, sizeof(lar_archive *))) != NULL )
{
*udata = ar;
luaL_getmetatable(L, "lar.archive");
lua_setmetatable(L, -2);
}
else
{
return luaL_error(L, "Out of memory");
}
}
else
{
return larlib_perror(L, "Archive not found");
}
return 1;
}
int larlib_md5( lua_State *L )
{
int i;
char md5[16], md5_hex[33];
const char *data = luaL_checkstring( L, 1 );
md5_state_t state;
md5_init(&state);
md5_append(&state, (const md5_byte_t *)data, strlen(data));
md5_finish(&state, (md5_byte_t *)md5);
for( i = 0; i < 16; i++ )
sprintf(&md5_hex[i*2], "%02x", (unsigned char)md5[i]);
lua_pushstring(L, md5_hex);
return 1;
}
int larlib_md5_file( lua_State *L )
{
int i, fd, len;
char md5[16], md5_hex[33], buffer[1024];
const char *filename = luaL_checkstring( L, 1 );
md5_state_t state;
if( (fd = open(filename, O_RDONLY)) != -1 )
{
md5_init(&state);
while( (len = read(fd, buffer, 1024)) > 0 )
md5_append(&state, (const md5_byte_t *)buffer, len);
md5_finish(&state, (md5_byte_t *)md5);
for( i = 0; i < 16; i++ )
sprintf(&md5_hex[i*2], "%02x", (unsigned char)md5[i]);
close(fd);
lua_pushstring(L, md5_hex);
}
else
{
return larlib_perror(L, strerror(errno));
}
return 1;
}
static int larlib_mkpath( const char *name, const char *path, char *buffer )
{
int nlen = strlen(name);
int plen = strlen(path);
if( (nlen + plen + 1) <= LAR_FNAME_BUFFER )
{
strcpy(buffer, path);
if( buffer[plen-1] != '/' )
buffer[plen++] = '/';
strcpy(&buffer[plen], name);
buffer[plen + nlen] = '\0';
return 0;
}
return 1;
}
static int larlib__gc( lua_State *L )
{
lar_archive **archive = luaL_checkudata( L, 1, "lar.archive" );
if( *archive )
lar_close(*archive);
*archive = NULL;
return 0;
}
static int larlib_member__open( lua_State *L, lar_member *mb )
{
lar_archive **archive = NULL;
const char *filename = NULL;
lar_member **udata;
if( mb == NULL )
{
*archive = luaL_checkudata( L, 1, "lar.archive" );
filename = luaL_checkstring( L, 2 );
}
if( mb != NULL || (mb = lar_open_member(*archive, filename)) != NULL )
{
if( (udata = lua_newuserdata(L, sizeof(lar_member *))) != NULL )
{
*udata = mb;
luaL_getmetatable(L, "lar.member");
lua_setmetatable(L, -2);
}
else
{
return luaL_error(L, "Out of memory");
}
}
else
{
return larlib_perror(L, "Member not found in archive");
}
return 1;
}
int larlib_member_open( lua_State *L )
{
return larlib_member__open( L, NULL );
}
int larlib_member_find( lua_State *L )
{
lar_archive **archive = luaL_checkudata( L, 1, "lar.archive" );
const char *package = luaL_checkstring( L, 2 );
lar_member *mb, **udata;
if( (mb = lar_find_member(*archive, package)) != NULL )
{
if( (udata = lua_newuserdata(L, sizeof(lar_member *))) != NULL )
{
*udata = mb;
luaL_getmetatable(L, "lar.member");
lua_setmetatable(L, -2);
}
else
{
return luaL_error(L, "Out of memory");
}
}
else
{
return larlib_perror(L, "Member not found in archive");
}
return 1;
}
int larlib_member_size( lua_State *L )
{
lar_member **member = luaL_checkudata( L, 1, "lar.member" );
lua_pushnumber(L, (*member)->length);
return 1;
}
int larlib_member_type( lua_State *L )
{
lar_member **member = luaL_checkudata( L, 1, "lar.member" );
lua_pushnumber(L, (*member)->type);
return 1;
}
int larlib_member_flags( lua_State *L )
{
lar_member **member = luaL_checkudata( L, 1, "lar.member" );
lua_pushnumber(L, (*member)->flags);
return 1;
}
int larlib_member_read( lua_State *L )
{
lar_member **member = luaL_checkudata( L, 1, "lar.member" );
int start = luaL_checknumber( L, 2 );
int length = luaL_optnumber( L, 3, (*member)->length );
char *stringcopy;
if( (start >= 0) && (start < (*member)->length) && (length > 0) )
{
if( (start + length) >= (*member)->length )
length = (*member)->length - start;
if( (stringcopy = (char *)malloc(length + 1)) != NULL )
{
memcpy(stringcopy, &(*member)->data[start], length);
stringcopy[length] = '\0';
lua_pushstring(L, stringcopy);
free(stringcopy);
}
else
{
return luaL_error(L, "Out of memory");
}
}
else
{
return larlib_perror(L, "Invalid argument");
}
return 1;
}
int larlib_member_data( lua_State *L )
{
lar_member **member = luaL_checkudata( L, 1, "lar.member" );
lua_pushstring(L, (*member)->data);
return 1;
}
int larlib_member_load( lua_State *L )
{
lar_member **member = luaL_checkudata( L, 1, "lar.member" );
int status = luaL_loadbuffer( L, (*member)->data, (*member)->length,
"=(lar member)" );
if( status )
{
lua_pushnil(L);
lua_insert(L, -2);
return 2;
}
return 1;
}
static int larlib_member__gc( lua_State *L )
{
lar_member **member = luaL_checkudata( L, 1, "lar.member" );
if( *member )
lar_close_member(*member);
*member = NULL;
return 0;
}
static int larlib_mmfile__open( lua_State *L, const char *filename )
{
struct stat s;
mmap_handle *fh, **udata;
if( filename == NULL )
filename = (const char *)luaL_checkstring( L, 1 );
if( (fh = (mmap_handle *)malloc(sizeof(mmap_handle))) == NULL )
return larlib_perror(L, "Out of memory");
if( stat(filename, &s) > -1 && (fh->fd = open(filename, O_RDONLY)) > -1 )
{
fh->length = s.st_size;
fh->data = mmap( 0, s.st_size, PROT_READ, MAP_PRIVATE, fh->fd, 0 );
if( fh->data == MAP_FAILED )
return larlib_perror(L, "Failed to mmap() file");
if( (udata = lua_newuserdata(L, sizeof(char *))) != NULL )
{
*udata = fh;
luaL_getmetatable(L, "lar.mmfile");
lua_setmetatable(L, -2);
}
else
{
return larlib_perror(L, "Out of memory");
}
}
else
{
return larlib_perror(L, strerror(errno));
}
return 1;
}
int larlib_mmfile_open( lua_State *L )
{
return larlib_mmfile__open(L, NULL);
}
int larlib_mmfile_size( lua_State *L )
{
mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
lua_pushnumber(L, (*fh)->length);
return 1;
}
int larlib_mmfile_read( lua_State *L )
{
mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
int start = luaL_checknumber( L, 2 );
int length = luaL_optnumber( L, 3, (*fh)->length );
char *stringcopy;
if( (start >= 0) && (start < (*fh)->length) && (length > 0) )
{
if( (start + length) >= (*fh)->length )
length = (*fh)->length - start;
if( (stringcopy = (char *)malloc(length + 1)) != NULL )
{
memcpy(stringcopy, &(*fh)->data[start], length);
stringcopy[length] = '\0';
lua_pushstring(L, stringcopy);
free(stringcopy);
}
else
{
return luaL_error(L, "Out of memory");
}
}
else
{
return larlib_perror(L, "Invalid argument");
}
return 1;
}
int larlib_mmfile_data( lua_State *L )
{
mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
lua_pushstring(L, (*fh)->data);
return 1;
}
int larlib_mmfile_load( lua_State *L )
{
mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
int status = luaL_loadbuffer(L, (*fh)->data, (*fh)->length, "=(mmap file)");
if( status )
{
lua_pushnil(L);
lua_insert(L, -2);
return 2;
}
return 1;
}
static int larlib_mmfile__gc( lua_State *L )
{
mmap_handle **fh = luaL_checkudata( L, 1, "lar.mmfile" );
if( *fh )
{
close((*fh)->fd);
munmap((*fh)->data, (*fh)->length);
free(*fh);
*fh = NULL;
}
return 0;
}
int larlib_findfile( lua_State *L )
{
int i;
const char *filename = luaL_checkstring( L, 1 );
const char *basepath = luaL_optstring( L, 2, "./" );
struct stat s;
lar_archive *ar;
lar_member *mb;
LAR_FNAME(filepath);
const char *searchpath[3] = { basepath, LUA_LDIR, LUA_CDIR };
for( i = 0; i < 3; i++ )
if( !larlib_mkpath(filename, searchpath[i], filepath) )
if( stat(filepath, &s) > -1 && (s.st_mode & S_IFREG) )
return larlib_mmfile__open( L, filepath );
for( i = 0; i < 3; i++ )
if( (ar = lar_find_archive(filename, searchpath[i], 0)) != NULL )
if( (mb = lar_open_member(ar, filename)) != NULL )
return larlib_member__open( L, mb );
return larlib_perror(L, "File not found");
}
static const luaL_reg LAR_REG[] = {
{ "open", larlib_open },
{ "find", larlib_find },
{ "md5", larlib_md5 },
{ "md5_file", larlib_md5_file },
{ "mmap", larlib_mmfile_open },
{ "findfile", larlib_findfile },
{ NULL, NULL }
};
static const luaL_reg LAR_ARCHIVE_REG[] = {
{ "member", larlib_member_open },
{ "find", larlib_member_find },
{ "__gc", larlib__gc },
{ NULL, NULL }
};
static const luaL_reg LAR_MEMBER_REG[] = {
{ "size", larlib_member_size },
{ "type", larlib_member_type },
{ "flags", larlib_member_flags },
{ "read", larlib_member_read },
{ "data", larlib_member_data },
{ "load", larlib_member_load },
{ "__gc", larlib_member__gc },
{ NULL, NULL }
};
static const luaL_reg LAR_MMFILE_REG[] = {
{ "size", larlib_mmfile_size },
{ "read", larlib_mmfile_read },
{ "data", larlib_mmfile_data },
{ "load", larlib_mmfile_load },
{ "__gc", larlib_mmfile__gc },
{ NULL, NULL }
};
LUALIB_API int luaopen_larlib( lua_State *L )
{
luaL_newmetatable(L, "lar");
luaL_register(L, NULL, LAR_REG);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_setglobal(L, "lar");
luaL_newmetatable(L, "lar.archive");
luaL_register(L, NULL, LAR_ARCHIVE_REG);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_setglobal(L, "lar.archive");
luaL_newmetatable(L, "lar.member");
luaL_register(L, NULL, LAR_MEMBER_REG);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_setglobal(L, "lar.member");
luaL_newmetatable(L, "lar.mmfile");
luaL_register(L, NULL, LAR_MMFILE_REG);
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_setglobal(L, "lar.mmfile");
return 1;
}

View file

@ -1,381 +0,0 @@
/*
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.c is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
either statically or dynamically; added missing #include <string.h>
in library.
2002-03-11 lpd Corrected argument list for main(), and added int return
type, in test program and T value program.
2002-02-21 lpd Added missing #include <stdio.h> in test program.
2000-07-03 lpd Patched to eliminate warnings about "constant is
unsigned in ANSI C, signed in traditional"; made test program
self-checking.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
1999-05-03 lpd Original version.
*/
#include "md5.h"
#include <string.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
# define BYTE_ORDER 0
#endif
#define T_MASK ((md5_word_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
static void
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
md5_word_t
a = pms->abcd[0], b = pms->abcd[1],
c = pms->abcd[2], d = pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
md5_word_t X[16];
#else
/* Define storage for little-endian or both types of CPUs. */
md5_word_t xbuf[16];
const md5_word_t *X;
#endif
{
#if BYTE_ORDER == 0
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static const int w = 1;
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
#endif
#if BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
if (!((data - (const md5_byte_t *)0) & 3)) {
/* data are properly aligned */
X = (const md5_word_t *)data;
} else {
/* not aligned */
memcpy(xbuf, data, 64);
X = xbuf;
}
}
#endif
#if BYTE_ORDER == 0
else /* dynamic big-endian */
#endif
#if BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes in the
* right order.
*/
const md5_byte_t *xp = data;
int i;
# if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
# else
# define xbuf X /* (static only) */
# endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
#endif
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + F(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
SET(c, d, a, b, 2, 17, T3);
SET(b, c, d, a, 3, 22, T4);
SET(a, b, c, d, 4, 7, T5);
SET(d, a, b, c, 5, 12, T6);
SET(c, d, a, b, 6, 17, T7);
SET(b, c, d, a, 7, 22, T8);
SET(a, b, c, d, 8, 7, T9);
SET(d, a, b, c, 9, 12, T10);
SET(c, d, a, b, 10, 17, T11);
SET(b, c, d, a, 11, 22, T12);
SET(a, b, c, d, 12, 7, T13);
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
#undef SET
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + G(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
SET(c, d, a, b, 11, 14, T19);
SET(b, c, d, a, 0, 20, T20);
SET(a, b, c, d, 5, 5, T21);
SET(d, a, b, c, 10, 9, T22);
SET(c, d, a, b, 15, 14, T23);
SET(b, c, d, a, 4, 20, T24);
SET(a, b, c, d, 9, 5, T25);
SET(d, a, b, c, 14, 9, T26);
SET(c, d, a, b, 3, 14, T27);
SET(b, c, d, a, 8, 20, T28);
SET(a, b, c, d, 13, 5, T29);
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
#undef SET
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti)\
t = a + H(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
SET(c, d, a, b, 11, 16, T35);
SET(b, c, d, a, 14, 23, T36);
SET(a, b, c, d, 1, 4, T37);
SET(d, a, b, c, 4, 11, T38);
SET(c, d, a, b, 7, 16, T39);
SET(b, c, d, a, 10, 23, T40);
SET(a, b, c, d, 13, 4, T41);
SET(d, a, b, c, 0, 11, T42);
SET(c, d, a, b, 3, 16, T43);
SET(b, c, d, a, 6, 23, T44);
SET(a, b, c, d, 9, 4, T45);
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
#undef SET
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + I(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
SET(c, d, a, b, 14, 15, T51);
SET(b, c, d, a, 5, 21, T52);
SET(a, b, c, d, 12, 6, T53);
SET(d, a, b, c, 3, 10, T54);
SET(c, d, a, b, 10, 15, T55);
SET(b, c, d, a, 1, 21, T56);
SET(a, b, c, d, 8, 6, T57);
SET(d, a, b, c, 15, 10, T58);
SET(c, d, a, b, 6, 15, T59);
SET(b, c, d, a, 13, 21, T60);
SET(a, b, c, d, 4, 6, T61);
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
#undef SET
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
was started.) */
pms->abcd[0] += a;
pms->abcd[1] += b;
pms->abcd[2] += c;
pms->abcd[3] += d;
}
void
md5_init(md5_state_t *pms)
{
pms->count[0] = pms->count[1] = 0;
pms->abcd[0] = 0x67452301;
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
pms->abcd[3] = 0x10325476;
}
void
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
{
const md5_byte_t *p = data;
int left = nbytes;
int offset = (pms->count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
md5_process(pms, p);
/* Process a final partial block. */
if (left)
memcpy(pms->buf, p, left);
}
void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}

View file

@ -1,91 +0,0 @@
/*
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.h is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Removed support for non-ANSI compilers; removed
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
1999-05-03 lpd Original version.
*/
#ifndef md5_INCLUDED
# define md5_INCLUDED
/*
* This package supports both compile-time and run-time determination of CPU
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
* defined as non-zero, the code will be compiled to run only on big-endian
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
* run on either big- or little-endian CPUs, but will run slightly less
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#ifdef __cplusplus
extern "C"
{
#endif
/* Initialize the algorithm. */
void md5_init(md5_state_t *pms);
/* Append a string to the message. */
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
/* Finish the message and return the digest. */
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* md5_INCLUDED */

File diff suppressed because it is too large Load diff