diff --git a/cfgpatch.c b/cfgpatch.c index 1b6f94e..ac4d50a 100644 --- a/cfgpatch.c +++ b/cfgpatch.c @@ -13,6 +13,8 @@ int main(int argc, char *argv[]) { struct filedata *config = get_filedata(argv[1]); + config_patch(config->data, CFG_PASSWORD, "1234"); + config_patch(config->data, CFG_LOCATION, "location"); config_patch(config->data, CFG_SYSNAME, "sysname"); config_patch(config->data, CFG_CONTACT, "contact"); @@ -26,6 +28,22 @@ int main(int argc, char *argv[]) config_patch(config->data, CFG_PORTNAME_MASK + 1, "PORT-001"); config_patch(config->data, CFG_PORTNAME_MASK + 2, "PORT-002"); + config_patch(config->data, CFG_PORTNAME_MASK + 26, "UPLINK"); + + config_patch(config->data, CFG_PORTENABLE_MASK + 25, "off"); + + config_patch(config->data, CFG_SNMP_READ_COMMUNITY, "public1234"); + config_patch(config->data, CFG_SNMP_WRITE_COMMUNITY, "private1234"); + + config_patch(config->data, CFG_CPUVLAN, "124"); + + config_patch(config->data, CFG_PORTVLAN_MASK + 1, "124:check:all"); + config_patch(config->data, CFG_PORTVLAN_MASK + 2, "124:nocheck:tagged"); + + config_patch(config->data, CFG_DOT1QVLAN_MASK + 2, "124:test"); + config_patch(config->data, CFG_DOT1QPORT_MASK + 2, "1:fixed:tagging"); + config_patch(config->data, CFG_DOT1QPORT_MASK + 2, "2:normal:notagging"); + config_patch(config->data, CFG_DOT1QPORT_MASK + 2, "3:forbidden:notagging"); char outname[64]; strncpy(outname, argv[1], sizeof(outname)); diff --git a/configdata.c b/configdata.c index e803966..95a2134 100644 --- a/configdata.c +++ b/configdata.c @@ -1,3 +1,4 @@ +#include #include #include @@ -50,22 +51,149 @@ static int patch_ip(void *config, struct cfg_patch *patch, int code, const char static int patch_defaultgw(void *config, struct cfg_patch *patch, int code, const char *parameter) { - /* metric? */ + /* defaultgw has metric of 2 */ *((uint8_t *)(config + 0x110d)) = 0x02; return patch_ip(config, patch, code, parameter); } -static int patch_portname(void *config, struct cfg_patch *patch, int code, const char *parameter) +static int patch_portenable(void *config, struct cfg_patch *patch, int code, const char *parameter) { - int num = code - patch->code; - if (num < patch->min || num > patch->max) + int port = code - patch->code; + if (port < 1 || port > 26) return -1; - strncpy(config + patch->offset + (num -1) * 0x70, parameter, patch->size); + int status = (strcmp(parameter, "on") == 0); + *((uint8_t *)(config + 0x336b + (port -1) * 0x70)) = (status ? 0x03 : 0x01); + return 0; +} + +static int patch_portname(void *config, struct cfg_patch *patch, int code, const char *parameter) +{ + int port = code - patch->code; + if (port < 1 || port > 26) + return -1; + + 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; +} + +/* TODO: not working "unknown ctl bits" */ +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) +{ + 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; +} + +static int patch_dot1qport(void *config, struct cfg_patch *patch, int code, const char *parameter) +{ + 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); return 0; } static struct cfg_patch patcharr[] = {{ + .code = CFG_PASSWORD, + .patch = patch_string, + .offset = 0x0014, + .size = 0x1d, +}, { .code = CFG_LOCATION, .patch = patch_string, .offset = 0x0034, @@ -80,6 +208,16 @@ static struct cfg_patch patcharr[] = {{ .patch = patch_string, .offset = 0x0074, .size = 0x1d, +}, { + .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, }, { .code = CFG_DEFAULTGW, .patch = patch_defaultgw, @@ -102,13 +240,27 @@ static struct cfg_patch patcharr[] = {{ .patch = patch_16bit, .offset = 0x53e8, .min = 0, .max = 65536, +}, { + .code = CFG_PORTENABLE_MASK, + .mask = 0xFFFFFFE0, + .patch = patch_portenable, }, { .code = CFG_PORTNAME_MASK, .mask = 0xFFFFFFE0, .patch = patch_portname, - .offset = 0x336c, - .size = 9, - .min = 1, .max = 26, + .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, }}; int config_patch(void *config, int code, const char *parameter) @@ -117,8 +269,14 @@ int config_patch(void *config, int code, const char *parameter) for (i = 0; i < (sizeof(patcharr) / sizeof(struct cfg_patch)); i++) { int mask = (patcharr[i].mask != 0) ? patcharr[i].mask : ~0; - if ((code & mask) == patcharr[i].code) - return patcharr[i].patch(config, &patcharr[i], code, parameter); + 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; + } } + printf("nothing found to patch code=0x%x parameter='%s'\n", code, parameter); return -1; } diff --git a/configdata.h b/configdata.h index 251085d..583faa6 100644 --- a/configdata.h +++ b/configdata.h @@ -2,7 +2,8 @@ #define _CONFIGDATA_H_ enum { - CFG_LOCATION = 0x0001, + CFG_PASSWORD = 0x0001, + CFG_LOCATION, CFG_SYSNAME, CFG_CONTACT, @@ -13,7 +14,16 @@ enum { CFG_MACAGEING, - CFG_PORTNAME_MASK = 0x0100, // next 0x0120 + CFG_CPUVLAN, + + CFG_SNMP_READ_COMMUNITY, + CFG_SNMP_WRITE_COMMUNITY, + + CFG_PORTENABLE_MASK = 0x0100, + CFG_PORTNAME_MASK = 0x0120, + CFG_PORTVLAN_MASK = 0x0140, + CFG_DOT1QVLAN_MASK = 0x0160, + CFG_DOT1QPORT_MASK = 0x0180, }; int config_patch(void *config, int code, const char *parameter);