2007-05-02 01:34:59 +02:00
|
|
|
#include <stdio.h>
|
2007-04-30 16:35:22 +02:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
|
|
#include "configdata.h"
|
|
|
|
|
|
|
|
struct cfg_patch {
|
|
|
|
int code;
|
|
|
|
int mask;
|
|
|
|
int (* patch)(void *config, struct cfg_patch *patch, int code, const char *parameter);
|
|
|
|
int offset;
|
|
|
|
int size;
|
|
|
|
int min;
|
|
|
|
int max;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int patch_8bit(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
|
|
|
int value = atoi(parameter);
|
|
|
|
if (value < patch->min || value > patch->max)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
*((uint8_t *)(config + patch->offset)) = value;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-04-30 17:43:51 +02:00
|
|
|
static int patch_16bit(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
|
|
|
int value = atoi(parameter);
|
|
|
|
if (value < patch->min || value > patch->max)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
*((uint16_t *)(config + patch->offset)) = htons(value);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-04-30 16:35:22 +02:00
|
|
|
static int patch_string(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
|
|
|
strncpy(config + patch->offset, parameter, patch->size);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int patch_ip(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
|
|
|
return (inet_pton(AF_INET, parameter, config + patch->offset) <= 0) ? -1 : 0;
|
|
|
|
}
|
|
|
|
|
2007-04-30 21:57:10 +02:00
|
|
|
static int patch_defaultgw(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
2007-05-02 01:34:59 +02:00
|
|
|
/* defaultgw has metric of 2 */
|
2007-04-30 21:57:10 +02:00
|
|
|
*((uint8_t *)(config + 0x110d)) = 0x02;
|
|
|
|
return patch_ip(config, patch, code, parameter);
|
|
|
|
}
|
|
|
|
|
2007-05-02 01:34:59 +02:00
|
|
|
static int patch_portenable(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
|
|
|
int port = code - patch->code;
|
|
|
|
if (port < 1 || port > 26)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
int status = (strcmp(parameter, "on") == 0);
|
|
|
|
*((uint8_t *)(config + 0x336b + (port -1) * 0x70)) = (status ? 0x03 : 0x01);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-04-30 17:43:51 +02:00
|
|
|
static int patch_portname(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
2007-05-02 01:34:59 +02:00
|
|
|
int port = code - patch->code;
|
|
|
|
if (port < 1 || port > 26)
|
2007-04-30 17:43:51 +02:00
|
|
|
return -1;
|
|
|
|
|
2007-05-02 01:34:59 +02:00
|
|
|
strncpy(config + 0x336c + (port -1) * 0x70, parameter, patch->size);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int patch_snmp_community(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
|
|
|
strncpy(config + 0x00A0 + patch->offset, parameter, patch->size);
|
|
|
|
*((uint8_t *)(config + 0x0101)) = 0x01;
|
|
|
|
|
|
|
|
strncpy(config + 0x9914 + patch->offset, parameter, patch->size);
|
|
|
|
*((uint8_t *)(config + 0x9975)) = 0x01;
|
|
|
|
|
|
|
|
strncpy(config + 0x9984 + patch->offset, parameter, patch->size);
|
|
|
|
*((uint8_t *)(config + 0x99e5)) = 0x01;
|
|
|
|
|
|
|
|
strncpy(config + 0x99f4 + patch->offset, parameter, patch->size);
|
|
|
|
*((uint8_t *)(config + 0x9a55)) = 0x01;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int patch_portvlan(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
|
|
|
int port = code - patch->code;
|
|
|
|
if (port < 1 || port > 26)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
char *tmp, *buf = strdup(parameter);
|
|
|
|
int vlanid = atoi(strtok_r(buf, ":", &tmp));
|
|
|
|
int check_ingress = (strcmp(strtok_r(NULL, ":", &tmp), "check") == 0);
|
|
|
|
int accept_all = (strcmp(strtok_r(NULL, ":", &tmp), "all") == 0);
|
|
|
|
free(buf);
|
|
|
|
|
|
|
|
if (vlanid < 0 || vlanid > 255)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
*((uint8_t *)(config + 0x5eff + (port -1) * 0x30)) = vlanid;
|
|
|
|
*((uint8_t *)(config + 0x5f00 + (port -1) * 0x30)) = accept_all ? 0x00 : 0x01;
|
|
|
|
*((uint8_t *)(config + 0x5f01 + (port -1) * 0x30)) = check_ingress ? 0x01 : 0x00;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: not working "unknown ctl bits" */
|
|
|
|
static int patch_dot1qvlan(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
2007-05-02 20:28:50 +02:00
|
|
|
return -1;
|
|
|
|
|
2007-05-02 01:34:59 +02:00
|
|
|
int id = code - patch->code;
|
|
|
|
if (id < 1 || id > 32)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
char *tmp, *buf = strdup(parameter);
|
|
|
|
int vlanid = atoi(strtok_r(buf, ":", &tmp));
|
|
|
|
char *name = strtok_r(NULL, ":", &tmp);
|
|
|
|
|
|
|
|
strncpy(config + 0x63e8 + (id -1) * 0xd0, name, 12);
|
|
|
|
*((uint16_t *)(config + 0x64b4 + (id -1) * 0xd0)) = htons(vlanid);
|
|
|
|
*((uint8_t *)(config + 0x64b6 + (id -1) * 0xd0)) = 0x03;
|
|
|
|
|
|
|
|
/* all ports forbidden & not tagging as default */
|
|
|
|
*((uint32_t *)(config + 0x63f4 + (id -1) * 0xd0)) = 0x03FFFFFF;
|
|
|
|
*((uint32_t *)(config + 0x6434 + (id -1) * 0xd0)) = 0x03FFFFFF;
|
|
|
|
*((uint32_t *)(config + 0x6474 + (id -1) * 0xd0)) = 0;
|
|
|
|
|
|
|
|
free(buf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-05-02 20:28:50 +02:00
|
|
|
/* TODO: not working "unknown ctl bits" */
|
2007-05-02 01:34:59 +02:00
|
|
|
static int patch_dot1qport(void *config, struct cfg_patch *patch, int code, const char *parameter)
|
|
|
|
{
|
2007-05-02 20:28:50 +02:00
|
|
|
return -1;
|
|
|
|
|
2007-05-02 01:34:59 +02:00
|
|
|
int id = code - patch->code;
|
|
|
|
if (id < 1 || id > 32)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
char *tmp, *buf = strdup(parameter);
|
|
|
|
int port = atoi(strtok_r(buf, ":", &tmp));
|
|
|
|
char *control = strtok_r(NULL, ":", &tmp);
|
|
|
|
char *tagging = strtok_r(NULL, ":", &tmp);
|
|
|
|
|
|
|
|
if (port < 1 || port > 26) {
|
|
|
|
free(buf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t *a = (uint32_t *)(config + 0x63f4 + (id -1) * 0xd0);
|
|
|
|
uint32_t *b = (uint32_t *)(config + 0x6434 + (id -1) * 0xd0);
|
|
|
|
uint32_t *c = (uint32_t *)(config + 0x6474 + (id -1) * 0xd0);
|
|
|
|
|
|
|
|
uint32_t value = (1 << (port -1));
|
|
|
|
if (strcmp(control, "normal") == 0) {
|
|
|
|
*a &= ~value;
|
|
|
|
*b &= ~value;
|
|
|
|
|
|
|
|
} else if (strcmp(control, "fixed") == 0) {
|
|
|
|
*a &= ~value;
|
|
|
|
*b |= value;
|
|
|
|
|
|
|
|
} else if (strcmp(control, "forbidden") == 0) {
|
|
|
|
*a |= value;
|
|
|
|
*b |= value;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
free(buf);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(tagging, "tagging") == 0)
|
|
|
|
*c |= value;
|
|
|
|
else
|
|
|
|
*c &= ~value;
|
|
|
|
|
|
|
|
free(buf);
|
2007-04-30 17:43:51 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-04-30 16:35:22 +02:00
|
|
|
static struct cfg_patch patcharr[] = {{
|
2007-05-02 01:34:59 +02:00
|
|
|
.code = CFG_PASSWORD,
|
|
|
|
.patch = patch_string,
|
|
|
|
.offset = 0x0014,
|
|
|
|
.size = 0x1d,
|
|
|
|
}, {
|
2007-04-30 16:35:22 +02:00
|
|
|
.code = CFG_LOCATION,
|
|
|
|
.patch = patch_string,
|
|
|
|
.offset = 0x0034,
|
|
|
|
.size = 0x1d,
|
|
|
|
}, {
|
|
|
|
.code = CFG_SYSNAME,
|
|
|
|
.patch = patch_string,
|
|
|
|
.offset = 0x0054,
|
|
|
|
.size = 0x1d,
|
|
|
|
}, {
|
|
|
|
.code = CFG_CONTACT,
|
|
|
|
.patch = patch_string,
|
|
|
|
.offset = 0x0074,
|
|
|
|
.size = 0x1d,
|
2007-05-02 01:34:59 +02:00
|
|
|
}, {
|
|
|
|
.code = CFG_SNMP_READ_COMMUNITY,
|
|
|
|
.patch = patch_snmp_community,
|
|
|
|
.offset = 0x0000,
|
|
|
|
.size = 0x1f,
|
|
|
|
}, {
|
|
|
|
.code = CFG_SNMP_WRITE_COMMUNITY,
|
|
|
|
.patch = patch_snmp_community,
|
|
|
|
.offset = 0x0020,
|
|
|
|
.size = 0x1f,
|
2007-04-30 16:35:22 +02:00
|
|
|
}, {
|
|
|
|
.code = CFG_DEFAULTGW,
|
2007-04-30 21:57:10 +02:00
|
|
|
.patch = patch_defaultgw,
|
2007-04-30 16:35:22 +02:00
|
|
|
.offset = 0x10fc,
|
|
|
|
}, {
|
|
|
|
.code = CFG_IPADDRESS,
|
|
|
|
.patch = patch_ip,
|
|
|
|
.offset = 0x2df8,
|
|
|
|
}, {
|
|
|
|
.code = CFG_NETMASK,
|
|
|
|
.patch = patch_8bit,
|
|
|
|
.offset = 0x2dfe,
|
2007-05-01 20:43:03 +02:00
|
|
|
.min = 0, .max = 32,
|
2007-04-30 16:35:22 +02:00
|
|
|
}, {
|
|
|
|
.code = CFG_NAMESERVER,
|
|
|
|
.patch = patch_ip,
|
|
|
|
.offset = 0x32dc,
|
2007-04-30 17:43:51 +02:00
|
|
|
}, {
|
|
|
|
.code = CFG_MACAGEING,
|
|
|
|
.patch = patch_16bit,
|
|
|
|
.offset = 0x53e8,
|
2007-05-01 20:43:03 +02:00
|
|
|
.min = 0, .max = 65536,
|
2007-05-02 20:28:50 +02:00
|
|
|
}, {
|
|
|
|
.code = CFG_CPUVLANID,
|
|
|
|
.patch = patch_8bit,
|
|
|
|
.offset = 0x5d69,
|
|
|
|
.min = 1, .max = 255,
|
2007-05-02 01:34:59 +02:00
|
|
|
}, {
|
|
|
|
.code = CFG_PORTENABLE_MASK,
|
|
|
|
.mask = 0xFFFFFFE0,
|
|
|
|
.patch = patch_portenable,
|
2007-04-30 17:43:51 +02:00
|
|
|
}, {
|
|
|
|
.code = CFG_PORTNAME_MASK,
|
|
|
|
.mask = 0xFFFFFFE0,
|
|
|
|
.patch = patch_portname,
|
2007-05-02 01:34:59 +02:00
|
|
|
.size = 0x9,
|
|
|
|
}, {
|
|
|
|
.code = CFG_PORTVLAN_MASK,
|
|
|
|
.mask = 0xFFFFFFE0,
|
|
|
|
.patch = patch_portvlan,
|
|
|
|
}, {
|
|
|
|
.code = CFG_DOT1QVLAN_MASK,
|
|
|
|
.mask = 0xFFFFFFE0,
|
|
|
|
.patch = patch_dot1qvlan,
|
|
|
|
}, {
|
|
|
|
.code = CFG_DOT1QPORT_MASK,
|
|
|
|
.mask = 0xFFFFFFE0,
|
|
|
|
.patch = patch_dot1qport,
|
2007-04-30 16:35:22 +02:00
|
|
|
}};
|
|
|
|
|
|
|
|
int config_patch(void *config, int code, const char *parameter)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < (sizeof(patcharr) / sizeof(struct cfg_patch)); i++) {
|
|
|
|
int mask = (patcharr[i].mask != 0) ? patcharr[i].mask : ~0;
|
|
|
|
|
2007-05-02 01:34:59 +02:00
|
|
|
if ((code & mask) == patcharr[i].code) {
|
|
|
|
int retval = patcharr[i].patch(config, &patcharr[i], code, parameter);
|
|
|
|
if (retval != 0)
|
|
|
|
printf("failed to patch code=0x%x parameter='%s'\n", code, parameter);
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
2007-04-30 16:35:22 +02:00
|
|
|
}
|
2007-05-02 01:34:59 +02:00
|
|
|
printf("nothing found to patch code=0x%x parameter='%s'\n", code, parameter);
|
2007-04-30 16:35:22 +02:00
|
|
|
return -1;
|
|
|
|
}
|