#include #include #include #include #include "babd.h" #include "dfs_parser.h" #include "l2tpd.h" #include "l2tp_tunnel.h" #define STRINGIFY(x) #x #define DEFINE_TAG(x) static lookup_tag_t lookup_tag_##x(STRINGIFY(x)); #define RESTORE_INT(x) x = obj->tag_int(&lookup_tag_##x) #define RESTORE_STRING(x) my_strncpy(x, obj->tag_str(&lookup_tag_##x), sizeof(x)) #define RESTORE_BYTES(x) obj->tag_bytes(&lookup_tag_##x, x, sizeof(x)) #define DUMP_INT(x) cfd->printf("\t\t" STRINGIFY(x) "(%d)\n", x); #define DUMP_STRING(x) cfd->printf("\t\t" STRINGIFY(x) "(\"%s\")\n", x); static void my_strncpy(char *dst, const char *src, size_t len) { if (!src) { memset(dst, 0, len); return; } strncpy(dst, src, len); } const char **tags; int num_tags; int tag_compare(const void *left, const void *right) { return strcmp(*(char **)left, *(char **)right); } const char *lookup_tag(const char *name, int create) { if (tags) { char **tagp; tagp = (char **)bsearch(&name, (void *)tags, num_tags, sizeof(*tags), tag_compare); if (tagp) return *tagp; } if (!create) return NULL; name = strdup(name); num_tags++; tags = (const char **)realloc(tags, num_tags * sizeof(*tags)); tags[num_tags-1] = name; qsort((void *)tags, num_tags, sizeof(*tags), tag_compare); return name; } void indent(int level) { while (level-- > 0) putchar('\t'); } void skip_spaces(FILE *fp) { int ch; while (EOF != (ch = getc(fp))) { if (!isspace(ch)) break; } if (ch != EOF) ungetc(ch, fp); } int next_non_space(FILE *fp) { int ch; while (EOF != (ch = getc(fp))) { if (!isspace(ch)) break; } return ch; } const char *get_name(FILE *fp, int make_tag) { char buf[255]; int i = 0; int ch; int is_number = 1; const char *name; ch = next_non_space(fp); do { if (!isdigit(ch) && ch != '-') is_number = 0; if (!isalnum(ch) && ch != '_' && ch != ':' && ch != '.' && ch != '-') break; buf[i++] = ch; } while (EOF != (ch = getc(fp))) ; if (ch != EOF) ungetc(ch, fp); buf[i] = 0; if (!i) return NULL; if (make_tag) return lookup_tag(buf, 1); name = lookup_tag(buf, 0); if (name) return name; return strdup(buf); } const char *get_name_or_string(FILE *fp) { char buf[256]; int i = 0; int ch = next_non_space(fp); if (ch == EOF) return NULL; if (ch != '"') { ungetc(ch, fp); return get_name(fp, 0); } goto in; do { buf[i++] = ch; in: ch = fgetc(fp); if (ch == EOF) { fprintf(stderr, "get_name_or_string: EOF\n"); return NULL; } if (ch == '\n') { fprintf(stderr, "get_name_or_string: newline in string\n"); return NULL; } } while (ch != '"'); buf[i] = 0; return strdup(buf); } int parse_one_obj_or_tag(FILE *fp, dfs_object_t *parent, int level) { const char *obj_name = get_name(fp, 1); int ch; if (!obj_name) return 0; ch = next_non_space(fp); if (ch == '{') { dfs_object_t *new_obj = new dfs_object_t(obj_name); parent->add_child(new_obj); #ifdef DEBUG indent(level); printf("object(%s) {\n", obj_name); #endif do { parse_one_obj_or_tag(fp, new_obj, level + 1); ch = next_non_space(fp); if (ch == '}') break; if (ch == EOF) { fprintf(stderr, "syntax error(object: EOF)\n"); return -1; } ungetc(ch, fp); } while (1); #ifdef DEBUG indent(level); printf("}\n"); #endif } else if (ch == '(') { const char *value = get_name_or_string(fp); #if 0 if (!value) { ch = next_non_space(fp); if (ch != ')') { fprintf(stderr, "syntax error parser tag1(%c) (%s)\n", ch, obj_name); return 0; } } #endif parent->add_child(new dfs_tag_t(obj_name, value)); ch = next_non_space(fp); if (ch != ')') { fprintf(stderr, "syntax error parser tag2(%c)(%s)(%s)\n", ch, obj_name, value); return 0; } #ifdef DEBUG indent(level); printf("tag(%s)(\"%s\")\n", obj_name, value); #endif } else if (ch == EOF) return 0; return 1; } static int parser(FILE *fp, dfs_object_t **topp) { int ret; *topp = new dfs_object_t("top"); do { ret = parse_one_obj_or_tag(fp, *topp, 0); } while (ret > 0); return ret; } dfs_object_t *dfs_parse_state(FILE *fp) { dfs_object_t *top = NULL; if (parser(fp, &top)) return NULL; return top; } #if 0 int main (void) { dfs_object_t *top = NULL; int ret; lookup_tag("established", 1); lookup_tag("LAC", 1); lookup_tag("LNS", 1); ret = parser(&top); if (ret < 0) { fprintf(stderr, "syntax error detected\n"); return 2; } printf("success!\n"); top->dump(0); for (int i=0; inext) if (child->do_name == tag->m_name) return child; return NULL; } dfs_object_t *dfs_object_t::find_next_object(lookup_tag_t *tag) { for (dfs_object_t *child = this->next; child; child = child->next) if (child->do_name == tag->m_name) return child; return NULL; } int dfs_sau(dfs_object_t *parent, lookup_tag_t *tag, union sockaddr_union *sau) { dfs_object_t *obj = parent->find_child_object(tag); if (!obj) { fprintf(stderr, "dfs_sau: unable to find tag(%s)\n", tag->m_name); return -1; } if (!obj->is_tag()) { fprintf(stderr, "dfs_sau: not a tag\n"); obj->dump(0); return -1; } dfs_tag_t *tag_obj = (dfs_tag_t *)obj; memset(sau, 0, sizeof(*sau)); sau_parse(sau, tag_obj->value); /* FIXME */ const char *str = strchr(tag_obj->value, ':'); if (!str || !*++str) { fprintf(stderr, "dfs_sau: no port in '%s'\n", tag_obj->value); return -1; } sau->sin.sin_port = htons(atoi(str)); return 0; } const char *dfs_str(dfs_object_t *parent, lookup_tag_t *tag) { dfs_object_t *obj = parent->find_child_object(tag); if (!obj) { fprintf(stderr, "dfs_str: unable to find tag(%s) in %s\n", tag->m_name, parent->do_name); return NULL; } if (!obj->is_tag()) { fprintf(stderr, "dfs_str: not a tag\n"); return NULL; } dfs_tag_t *tag_obj = (dfs_tag_t *)obj; return tag_obj->value; } DEFINE_TAG(CInterface); int dfs_build_state(dfs_object_t *top) { dfs_object_t *l2tp_peer_obj; if (debug) { top->dump(0); for (int i=0; ifind_child_object(&lookup_tag_l2tp_peer); while (l2tp_peer_obj) { union sockaddr_union peer_sau; if (dfs_sau(l2tp_peer_obj, &lookup_tag_peer, &peer_sau)) return -1; const char *secret = l2tp_peer_obj->tag_str(&lookup_tag_secret, 1); l2tp_peer_t *peer = the_l2tpd->find_make_peer(&peer_sau, secret, NULL/*FIXME*/); if (!peer) { fprintf(stderr, "dfs_build_state: unable to make peer\n"); return -1; } if (peer->dfs_restore(l2tp_peer_obj)) return -1; l2tp_peer_obj = l2tp_peer_obj->find_next_object(&lookup_tag_l2tp_peer); } dfs_object_t *CInterface_obj = top->find_child_object(&lookup_tag_CInterface); while (CInterface_obj) { /* FIXME: virtual namespace needs username in CInterface */ CInterface *iface = new CInterface(NULL, NULL); iface->dfs_restore(CInterface_obj); CInterface_obj = CInterface_obj->find_next_object(&lookup_tag_CInterface); } return 0; } int l2tp_peer_t::dfs_restore(dfs_object_t *obj) { static lookup_tag_t l2tp_tunnel_tag("l2tp_tunnel"); dfs_object_t *tunnel_obj = obj->find_child_object(&l2tp_tunnel_tag); while (tunnel_obj) { new l2tp_tunnel_t(this, tunnel_obj); tunnel_obj = tunnel_obj->find_next_object(&l2tp_tunnel_tag); } return 0; } const char *dfs_object_t::tag_str(lookup_tag_t *tag, int may_fail) { dfs_object_t *obj = find_child_object(tag); if (!obj) { if (!may_fail) fprintf(stderr, "dfs_object_t::tag_str: unable to find tag(%s) in %s\n", tag->m_name, do_name); return NULL; } if (!obj->is_tag()) { fprintf(stderr, "dfs_object_t::tag_int: not a tag\n"); return NULL; } dfs_tag_t *tag_obj = (dfs_tag_t *)obj; return tag_obj->value; } int dfs_object_t::tag_int(lookup_tag_t *tag, int *ptr) { int val = atoi(tag_str(tag)); if (ptr) *ptr = val; return val; } long dfs_object_t::tag_long(lookup_tag_t *tag, long *ptr) { long val = atol(tag_str(tag)); if (ptr) *ptr = val; return val; } static inline int hexit(char ch) { if (isdigit(ch)) return ch - '0'; if (ch >= 'a' && ch <= 'f') return ch - 'a' + 0xA; if (ch >= 'A' && ch <= 'F') return ch - 'A' + 0xA; return -1; } void dfs_object_t::tag_bytes(lookup_tag_t *tag, u8 *bytes, size_t size) { const char *str = tag_str(tag); unsigned i = 0; while (*str && i < size) { if (str[0] == '\\' && str[1] == 'x') { int j = 0, n = 0; int a = hexit(str[2]), b = hexit(str[3]); if (a >= 0 && b >= 0) { j = a << 4 | b; n = 2; } else { j = a; n = 1; } bytes[i++] = j; str += 2 + n; } else bytes[i++] = *str++; } } enum l2tp_tunnel_t::L2TP_Tunnel_States l2tp_tunnel_t::tag_to_tunnel_state(const char *str) { if (str == lookup_tag_idle.m_name) return L2TP_Tunnel_Idle; if (str == lookup_tag_waitctlreply.m_name) return L2TP_Tunnel_WaitCtlReply; if (str == lookup_tag_waitctlconn.m_name) return L2TP_Tunnel_WaitCtlConn; if (str == lookup_tag_established.m_name) return L2TP_Tunnel_Established; fprintf(stderr, "l2tp_tunnel_t::tag_to_tunnel_state: unknown(%s)", str); exit(2); // FIXME } DEFINE_TAG(l2tp_tx_queue_t); l2tp_tunnel_t::l2tp_tunnel_t(l2tp_peer_t *_peer, dfs_object_t *obj) : l2tp_tx_queue_t(), l2tp_tunnel_hello() { tunnel_state = tag_to_tunnel_state(obj->tag_str(&lookup_tag_state)); peer = _peer; tunnel_Ns = obj->tag_int(&lookup_tag_Ns); tunnel_Nr = obj->tag_int(&lookup_tag_Nr); call_serial_number = 0; need_zlb = 0; tunnel_aborted = 0; tunnel_id = obj->tag_int(&lookup_tag_local); peer_tunnel_id = obj->tag_int(&lookup_tag_peer); int allocd = peer->alloc_tunnel_id(this, tunnel_id, peer_tunnel_id); if (tunnel_id != allocd) fprintf(stderr, "alloc_tunnel_id: %d vs %d\n", tunnel_id, allocd); get_random(challenge_bytes, sizeof challenge_bytes); dfs_object_t *sessions_obj = obj->find_child_object(&lookup_tag_sessions); if (sessions_obj) { for (dfs_object_t *session_obj = sessions_obj->find_child_object(&lookup_tag_l2tp_session); session_obj; session_obj = session_obj->find_next_object(&lookup_tag_l2tp_session)) new l2tp_session_t(this, session_obj); } dfs_object_t *tx_obj = obj->find_child_object(&lookup_tag_l2tp_tx_queue_t); if (tx_obj) l2tp_tx_queue_t::dfs_restore(tx_obj); if (tunnel_state == L2TP_Tunnel_Established) start_hello_timer(); } enum l2tp_session_t::L2TP_Session_States l2tp_session_t::tag_to_session_state(const char *str) { if (str == lookup_tag_idle.m_name) return L2TP_Session_Idle; if (str == lookup_tag_waitconnect.m_name) return L2TP_Session_WaitConnect; if (str == lookup_tag_established.m_name) return L2TP_Session_Established; if (str == lookup_tag_waittunnel.m_name) return L2TP_Session_WaitTunnel; fprintf(stderr, "l2tp_session_t::tag_to_session_state: unknown(%s)", str); exit(2); // FIXME } enum l2tp_session_t::Session_Modes l2tp_session_t::tag_to_session_mode(const char *str) { if (str == lookup_tag_none.m_name) return Session_None; if (str == lookup_tag_LAC.m_name) return Session_LAC; if (str == lookup_tag_LNS.m_name) return Session_LNS; fprintf(stderr, "l2tp_session_t::tag_to_session_mode: unknown(%s)", str); exit(2); // FIXME } l2tp_session_t *l2tpd_t::find_l2tp_session(const char *multihop) { int tunnel_id, peer_session_id, session_id; if (3 != sscanf(multihop, "%d/%d:%d", &tunnel_id, &peer_session_id, &session_id)) { fprintf(stderr, "find_l2tp_session(\"%s\"): parse error\n", multihop); exit(2); } if (tunnel_id < 0 || tunnel_id > 65535) return NULL; l2tp_tunnel_t *tun = l2tp_tunnels[tunnel_id]; if (!tun) return NULL; if (session_id < 0 || session_id > 65535) return NULL; return tun->sessions[session_id]; } l2tp_session_t::l2tp_session_t(l2tp_tunnel_t *tun, dfs_object_t *obj) { u16 peer_id = obj->tag_int(&lookup_tag_peer); u16 id = obj->tag_int(&lookup_tag_local); init_session(tun, peer_id, id, NULL, obj->tag_str(&lookup_tag_site, 1)); session_state = tag_to_session_state(obj->tag_str(&lookup_tag_state)); session_mode = tag_to_session_mode(obj->tag_str(&lookup_tag_mode)); ch.dfs_restore(obj->find_child_object(&lookup_tag_ch)); CLink *link = this; link->dfs_restore(obj->find_child_object(&lookup_tag_CLink)); const char *multihop = obj->tag_str(&lookup_tag_multihop, 1); multihop_session = NULL; if (multihop) { multihop_session = the_l2tpd->find_l2tp_session(multihop); if (multihop_session) { multihop_session->multihop_session = this; if (m_channel->state == CS_CONNECTED && multihop_session->m_channel->state == CS_CONNECTED) { fprintf(stderr, "kernel_multihop_up()\n"); kernel_multihop_up(multihop_session); } } } } DEFINE_TAG(DEAD); DEFINE_TAG(DISCONNECTING); DEFINE_TAG(DIALING); DEFINE_TAG(CONNECTED); DEFINE_TAG(ESTABLISH); DEFINE_TAG(AUTHENTICATE); DEFINE_TAG(MLCP); DEFINE_TAG(TERMINATE); DEFINE_TAG(NETWORK); enum Phase str_to_phase(const char *str) { if (str == lookup_tag_DEAD.m_name) return PHASE_DEAD; if (str == lookup_tag_DISCONNECTING.m_name) return PHASE_DISCONNECTING; if (str == lookup_tag_DIALING.m_name) return PHASE_DIALING; if (str == lookup_tag_CONNECTED.m_name) return PHASE_CONNECTED; if (str == lookup_tag_ESTABLISH.m_name) return PHASE_ESTABLISH; if (str == lookup_tag_AUTHENTICATE.m_name) return PHASE_AUTHENTICATE; if (str == lookup_tag_MLCP.m_name) return PHASE_MLCP; if (str == lookup_tag_TERMINATE.m_name) return PHASE_TERMINATE; if (str == lookup_tag_NETWORK.m_name) return PHASE_NETWORK; fprintf(stderr, "str_to_phase: unknown(%s)", str); exit(2); // FIXME } DEFINE_TAG(m_connect_time); DEFINE_TAG(m_hard_mru); DEFINE_TAG(m_hard_mtu); DEFINE_TAG(m_wereAcked); DEFINE_TAG(m_peerAcked); DEFINE_TAG(m_loop_count); DEFINE_TAG(m_ident); DEFINE_TAG(m_ldisc); DEFINE_TAG(m_lastStatus); DEFINE_TAG(m_phase); DEFINE_TAG(m_lpolicy); DEFINE_TAG(m_npolicy); DEFINE_TAG(m_rpolicy); DEFINE_TAG(m_policy); DEFINE_TAG(ifOptions); DEFINE_TAG(m_lcpProto); DEFINE_TAG(m_papProto); DEFINE_TAG(m_chapProto); DEFINE_TAG(m_mlcpProto); void CLink::dfs_restore(dfs_object_t *obj) { m_hard_mru = obj->tag_int(&lookup_tag_m_hard_mru); m_hard_mtu = obj->tag_int(&lookup_tag_m_hard_mtu); m_wereAcked = obj->tag_int(&lookup_tag_m_wereAcked); m_peerAcked = obj->tag_int(&lookup_tag_m_peerAcked); m_loop_count = obj->tag_int(&lookup_tag_m_loop_count); m_ident = obj->tag_int(&lookup_tag_m_ident); m_lastStatus = obj->tag_int(&lookup_tag_m_lastStatus); m_phase = str_to_phase(obj->tag_str(&lookup_tag_m_phase)); m_connect_time.tv_sec = obj->tag_long(&lookup_tag_m_connect_time); //FIXME m_connect_time.tv_nsec = obj->tag_long(&lookup_tag_m_connect_time); m_lpolicy.dfs_restore(obj->find_child_object(&lookup_tag_m_lpolicy)); m_npolicy.dfs_restore(obj->find_child_object(&lookup_tag_m_npolicy)); m_rpolicy.dfs_restore(obj->find_child_object(&lookup_tag_m_rpolicy)); m_policy.dfs_restore(obj->find_child_object(&lookup_tag_m_policy)); ifOptions.dfs_restore(obj->find_child_object(&lookup_tag_ifOptions)); m_lcpProto.dfs_restore(obj->find_child_object(&lookup_tag_m_lcpProto)); m_papProto.dfs_restore(obj->find_child_object(&lookup_tag_m_papProto)); m_chapProto.dfs_restore(obj->find_child_object(&lookup_tag_m_chapProto)); m_mlcpProto.dfs_restore(obj->find_child_object(&lookup_tag_m_mlcpProto)); } DEFINE_TAG(is_up); DEFINE_TAG(have_ip); DEFINE_TAG(links_dialing); DEFINE_TAG(is_static); DEFINE_TAG(m_lcfg); DEFINE_TAG(m_ipcpProto); DEFINE_TAG(m_phone); DEFINE_TAG(m_site); DEFINE_TAG(m_closeReason); DEFINE_TAG(lflags); DEFINE_TAG(rflags); DEFINE_TAG(redial_interval); DEFINE_TAG(idle_secs); DEFINE_TAG(links); DEFINE_TAG(ndev_id); void CInterface::dfs_restore(dfs_object_t *obj) { int t_is_up = is_up; obj->tag_int(&lookup_tag_is_up, &t_is_up); is_up = t_is_up; obj->tag_int(&lookup_tag_have_ip, &have_ip); obj->tag_int(&lookup_tag_redial_interval, &redial_interval); obj->tag_int(&lookup_tag_idle_secs, &idle_secs); obj->tag_int(&lookup_tag_links_dialing, &links_dialing); obj->tag_int(&lookup_tag_is_static, &is_static); obj->tag_int(&lookup_tag_lflags, &lflags); obj->tag_int(&lookup_tag_rflags, &rflags); obj->tag_int(&lookup_tag_ndev_id, &ndev_id); m_lcfg.dfs_restore(obj->find_child_object(&lookup_tag_m_lcfg)); m_rpolicy.dfs_restore(obj->find_child_object(&lookup_tag_m_rpolicy)); m_ipcpProto.dfs_restore(obj->find_child_object(&lookup_tag_m_ipcpProto)); m_ipcpProto.m_parent = this; m_phone = obj->tag_str(&lookup_tag_m_phone, 1); m_site = obj->tag_str(&lookup_tag_m_site, 1); m_closeReason = obj->tag_str(&lookup_tag_m_closeReason, 1); if (is_up) { dfs_object_t *links_obj = obj->find_child_object(&lookup_tag_links); if (links_obj) { dfs_object_t *link_obj = links_obj->find_child_object(&lookup_tag_CLink); while (link_obj) { if (link_obj->is_tag()) { dfs_tag_t *tag = (dfs_tag_t *)link_obj; CLink *link = NULL; if (tag) { channel_t *chan; chan = findchan(tag->value); if (chan) link = chan->link; } printf("AddLink(%s) : %p\n", tag->value, link); if (link->m_interface) *(char *)0 = 0; link->m_interface = this; AddLink(link); } link_obj = link_obj->find_next_object(&lookup_tag_CLink); } } /* re-add our ip address and routes */ if (have_ip) Ready(NULL); } } DEFINE_TAG(rem_ip); DEFINE_TAG(loc_ip); DEFINE_TAG(dns_primary); DEFINE_TAG(dns_second); DEFINE_TAG(netmask); DEFINE_TAG(loc_fpeer); DEFINE_TAG(rem_fpeer); DEFINE_TAG(addtime); DEFINE_TAG(droptime); DEFINE_TAG(min_links); DEFINE_TAG(max_links); DEFINE_TAG(rx_drop_bpls); DEFINE_TAG(rx_raise_bpls); DEFINE_TAG(tx_drop_bpls); DEFINE_TAG(tx_raise_bpls); DEFINE_TAG(call_info); DEFINE_TAG(user); DEFINE_TAG(passwd); //DEFINE_TAG(site); DEFINE_TAG(phone); DEFINE_TAG(dev_class); DEFINE_TAG(port); DEFINE_TAG(chap_lvalue_len); DEFINE_TAG(chap_lvalue); DEFINE_TAG(chap_rvalue_len); DEFINE_TAG(chap_rvalue); DEFINE_TAG(is_valid); DEFINE_TAG(vj); DEFINE_TAG(vjc); DEFINE_TAG(netroute); DEFINE_TAG(proxy); DEFINE_TAG(defroute); DEFINE_TAG(reserved); DEFINE_TAG(challenge); DEFINE_TAG(auth_info); DEFINE_TAG(proto_id); void OptionSet_t::dfs_restore(dfs_object_t *obj) { RESTORE_INT(rem_ip); RESTORE_INT(loc_ip); RESTORE_INT(dns_primary); RESTORE_INT(dns_second); RESTORE_INT(netmask); RESTORE_INT(loc_fpeer); RESTORE_INT(rem_fpeer); RESTORE_INT(addtime); RESTORE_INT(droptime); RESTORE_INT(min_links); RESTORE_INT(max_links); RESTORE_INT(rx_drop_bpls); RESTORE_INT(rx_raise_bpls); RESTORE_INT(tx_drop_bpls); RESTORE_INT(tx_raise_bpls); RESTORE_INT(call_info); RESTORE_STRING(user); RESTORE_STRING(passwd); RESTORE_STRING(site); RESTORE_STRING(phone); RESTORE_STRING(dev_class); RESTORE_STRING(port); RESTORE_INT(chap_lvalue_len); RESTORE_BYTES(chap_lvalue); RESTORE_INT(chap_rvalue_len); RESTORE_BYTES(chap_rvalue); RESTORE_INT(is_valid); RESTORE_INT(vj); RESTORE_INT(vjc); RESTORE_INT(netroute); RESTORE_INT(proxy); RESTORE_INT(defroute); RESTORE_INT(reserved); RESTORE_INT(challenge); RESTORE_INT(auth_info); RESTORE_INT(proto_id); call = NULL; } void OptionSet_t::dump_full_state(ctrlfd_t *cfd) { DUMP_STRING(user); DUMP_STRING(passwd); if (site) DUMP_STRING(site); if (phone) DUMP_STRING(phone); if (dev_class) DUMP_STRING(dev_class); if (port) DUMP_STRING(port); DUMP_INT(rem_ip); DUMP_INT(loc_ip); DUMP_INT(dns_primary); DUMP_INT(dns_second); DUMP_INT(netmask); DUMP_INT(loc_fpeer); DUMP_INT(rem_fpeer); DUMP_INT(addtime); DUMP_INT(droptime); DUMP_INT(min_links); DUMP_INT(max_links); DUMP_INT(rx_drop_bpls); DUMP_INT(rx_raise_bpls); DUMP_INT(tx_drop_bpls); DUMP_INT(tx_raise_bpls); DUMP_INT(call_info); DUMP_INT(chap_lvalue_len); cfd->dfs_print_bytes("\t\tchap_lvalue", chap_lvalue, chap_lvalue_len); DUMP_INT(chap_rvalue_len); cfd->dfs_print_bytes("\t\tchap_rvalue", chap_rvalue, chap_rvalue_len); DUMP_INT(is_valid); DUMP_INT(vj); DUMP_INT(vjc); DUMP_INT(netroute); DUMP_INT(proxy); DUMP_INT(defroute); DUMP_INT(reserved); DUMP_INT(challenge); DUMP_INT(auth_info); DUMP_INT(proto_id); } DEFINE_TAG(P_MAGIC); DEFINE_TAG(P_MRU); DEFINE_TAG(P_MRRU); DEFINE_TAG(P_PFC); DEFINE_TAG(P_ACFC); DEFINE_TAG(P_AUTH); DEFINE_TAG(P_ANSWER); DEFINE_TAG(P_ACCM); DEFINE_TAG(P_SSN); DEFINE_TAG(P_ECHO); DEFINE_TAG(P_LDISC); DEFINE_TAG(P_CALL_INFO); DEFINE_TAG(P_EPD_CLASS); DEFINE_TAG(P_EPD_LENGTH); DEFINE_TAG(valid_mask); DEFINE_TAG(epd_addr); void policy_t::dfs_restore(dfs_object_t *obj) { #define RESTORE_POLICY(x) data[x] = obj->tag_int(&lookup_tag_##x) RESTORE_POLICY(P_MAGIC); RESTORE_POLICY(P_MRU); RESTORE_POLICY(P_MRRU); RESTORE_POLICY(P_PFC); RESTORE_POLICY(P_ACFC); RESTORE_POLICY(P_AUTH); RESTORE_POLICY(P_ANSWER); RESTORE_POLICY(P_ACCM); RESTORE_POLICY(P_SSN); RESTORE_POLICY(P_ECHO); RESTORE_POLICY(P_LDISC); RESTORE_POLICY(P_CALL_INFO); RESTORE_POLICY(P_EPD_CLASS); RESTORE_POLICY(P_EPD_LENGTH); RESTORE_INT(valid_mask); RESTORE_BYTES(epd_addr); } void policy_t::dump_full_state(ctrlfd_t *cfd) { cfd->printf("valid_mask(%d)\n", valid_mask); cfd->dfs_print_bytes("epd_addr", epd_addr, sizeof epd_addr); #define DUMP_POLICY(x) cfd->printf("%s(%d)\n", STRINGIFY(x), data[x]) DUMP_POLICY(P_MAGIC); DUMP_POLICY(P_MRU); DUMP_POLICY(P_MRRU); DUMP_POLICY(P_PFC); DUMP_POLICY(P_ACFC); DUMP_POLICY(P_AUTH); DUMP_POLICY(P_ANSWER); DUMP_POLICY(P_ACCM); DUMP_POLICY(P_SSN); DUMP_POLICY(P_ECHO); DUMP_POLICY(P_LDISC); DUMP_POLICY(P_CALL_INFO); DUMP_POLICY(P_EPD_CLASS); DUMP_POLICY(P_EPD_LENGTH); } DEFINE_TAG(m_acked); DEFINE_TAG(m_will); DEFINE_TAG(CFsmProtocol); void CIpcpProtocol::dump_full_state(ctrlfd_t *cfd) { cfd->printf("CFsmProtocol {\n"); CFsmProtocol *fsm = this; fsm->dump_full_state(cfd); cfd->printf("}\n"); cfd->printf("m_acked {\n"); m_acked.dump_full_state(cfd); cfd->printf("}\n"); cfd->printf("m_will {\n"); m_will.dump_full_state(cfd); cfd->printf("}\n"); } void CIpcpProtocol::dfs_restore(dfs_object_t *obj) { m_acked.dfs_restore(obj->find_child_object(&lookup_tag_m_acked)); m_will.dfs_restore(obj->find_child_object(&lookup_tag_m_will)); CFsmProtocol *fsm = this; fsm->dfs_restore(obj->find_child_object(&lookup_tag_CFsmProtocol)); } DEFINE_TAG(INITIAL); DEFINE_TAG(STARTING); DEFINE_TAG(CLOSED); DEFINE_TAG(STOPPED); DEFINE_TAG(CLOSING); DEFINE_TAG(STOPPING); DEFINE_TAG(REQSENT); DEFINE_TAG(ACKRCVD); DEFINE_TAG(ACKSENT); DEFINE_TAG(OPENED); static enum FsmState fsmState(const char *str) { #define FSMSTATE(x) \ if (!strcmp(str, lookup_tag_##x.m_name)) \ return ST_##x; FSMSTATE(INITIAL); FSMSTATE(STARTING); FSMSTATE(CLOSED); FSMSTATE(STOPPED); FSMSTATE(CLOSING); FSMSTATE(STOPPING); FSMSTATE(REQSENT); FSMSTATE(ACKRCVD); FSMSTATE(ACKSENT); FSMSTATE(OPENED); fprintf(stderr, "fsmState: unknown(%s)\n", str); exit(2); // FIXME } DEFINE_TAG(cntConfig); DEFINE_TAG(cntTerminate); DEFINE_TAG(cntFailure); DEFINE_TAG(maxConfig); DEFINE_TAG(maxTerminate); DEFINE_TAG(maxFailure); DEFINE_TAG(modePassive); DEFINE_TAG(modeRestart); void CFsmProtocol::dfs_restore(dfs_object_t *obj) { RESTORE_INT(cntConfig); RESTORE_INT(cntTerminate); RESTORE_INT(cntFailure); RESTORE_INT(maxConfig); RESTORE_INT(maxTerminate); RESTORE_INT(maxFailure); RESTORE_INT(modePassive); RESTORE_INT(modeRestart); state = fsmState(obj->tag_str(&lookup_tag_state)); } void CFsmProtocol::dump_full_state(ctrlfd_t *cfd) { DUMP_INT(cntConfig); DUMP_INT(cntTerminate); DUMP_INT(cntFailure); DUMP_INT(maxConfig); DUMP_INT(maxTerminate); DUMP_INT(maxFailure); DUMP_INT(modePassive); DUMP_INT(modeRestart); cfd->printf("state(\"%s\")\n", fsmStateName[state]); } void CInterface::dump_full_state(ctrlfd_t *cfd) { cfd->printf("CInterface {\n"); cfd->printf("\tm_name(%s)\n", GetName()); cfd->printf("\tis_up(%d)\n", is_up); cfd->printf("\tname_has_ip(%d)\n", name_has_ip); cfd->printf("\thave_ip(%d)\n", have_ip); cfd->printf("\tredial_interval(%d)\n", redial_interval); cfd->printf("\tidle_secs(%d)\n", idle_secs); cfd->printf("\tlinks_dialing(%d)\n", links_dialing); cfd->printf("\tis_static(%d)\n", is_static); cfd->printf("\tlflags(%d)\n", lflags); cfd->printf("\trflags(%d)\n", rflags); cfd->printf("\tndev_id(%d)\n", ndev_id); cfd->printf("\tlinks {\n"); for (CLink *link = links; link; link = link->m_nextBundled) cfd->printf("\t\tCLink(%s)\n", link->get_name()); cfd->printf("\t}\n"); cfd->printf("\tm_rpolicy {\n"); m_rpolicy.dump_full_state(cfd); cfd->printf("\t}\n"); cfd->printf("\tm_lcfg {\n"); m_lcfg.dump_full_state(cfd); cfd->printf("\t}\n"); cfd->printf("\tm_ipcpProto {\n"); m_ipcpProto.dump_full_state(cfd); cfd->printf("\t}\n"); cfd->printf("}\n"); } void dfs_dump_interfaces(ctrlfd_t *cfd) { CInterface *iface; for (iface = ifListHead; iface; iface = iface->next) iface->dump_full_state(cfd); } DEFINE_TAG(device_id); DEFINE_TAG(devclass_id); DEFINE_TAG(unit); DEFINE_TAG(no_auth); DEFINE_TAG(file_name); DEFINE_TAG(device_name); void channel_t::dump_full_state(ctrlfd_t *cfd) { DUMP_INT(device_id); DUMP_INT(devclass_id); DUMP_INT(unit); DUMP_INT(state); DUMP_INT(no_auth); /* FIXME: x_accm, r_accm, link? */ if (file_name) DUMP_STRING(file_name); if (device_name) DUMP_STRING(device_name); if (dev_class) DUMP_STRING(dev_class); } void channel_t::dfs_restore(dfs_object_t *obj) { RESTORE_INT(device_id); RESTORE_INT(devclass_id); RESTORE_INT(unit); RESTORE_INT(state); RESTORE_INT(no_auth); /* FIXME: x_accm, r_accm, link? */ file_name = obj->tag_str(&lookup_tag_file_name, 1); device_name = obj->tag_str(&lookup_tag_device_name, 1); dev_class = obj->tag_str(&lookup_tag_dev_class, 1); } void l2tp_tx_queue_t::dfs_l2tp_tx_queue_t(ctrlfd_t *cfd) { if (IsEmpty()) return; cfd->printf("l2tp_tx_queue_t {\n"); for (CPppPacket *pkt = (CPppPacket *)Peek(); pkt; pkt = (CPppPacket *)pkt->GetNext()) { cfd->printf("CPppPacket {\n"); pkt->dump_full_state(cfd); cfd->printf("}\n"); } cfd->printf("}\n"); } DEFINE_TAG(CPppPacket); void l2tp_tx_queue_t::dfs_restore(dfs_object_t *obj) { dfs_object_t *child; for (child = obj->find_child_object(&lookup_tag_CPppPacket); child; child = child->find_next_object(&lookup_tag_CPppPacket)) { CPppPacket *pkt = new CPppPacket(child); tx_append(pkt); } } void CPppPacket::dump_full_state(ctrlfd_t *cfd) { if (link) *(char *)0 = 0; CuscArray::dump_full_state(cfd); } void CuscArray::dump_full_state(ctrlfd_t *cfd) { cfd->printf("\tm_length(%ld)\n", (long)m_length); if (m_length > 0) cfd->dfs_print_bytes("\tm_start", m_start, m_length); } DEFINE_TAG(m_length); DEFINE_TAG(m_start); CuscArray::CuscArray(dfs_object_t *obj) { int len = obj->tag_int(&lookup_tag_m_length); ::CuscArray(); ExpandBuffer(len); obj->tag_bytes(&lookup_tag_m_start, m_start, len); m_length += len; m_end = m_start + m_length; } void CLcpProtocol::dump_full_state(ctrlfd_t *cfd) { DUMP_INT(m_echoTime); DUMP_INT(m_lastEchoIdent); DUMP_INT(m_echoSent); DUMP_INT(m_mruNaks); DUMP_INT(m_rxPackets); cfd->printf("m_echoTimer {\n"); m_echoTimer.dump_full_state(cfd); cfd->printf("}\n"); cfd->printf("CFsmProtocol {\n"); CFsmProtocol::dump_full_state(cfd); cfd->printf("}\n"); } DEFINE_TAG(m_echoTime); DEFINE_TAG(m_lastEchoIdent); DEFINE_TAG(m_echoSent); DEFINE_TAG(m_mruNaks); DEFINE_TAG(m_rxPackets); void CLcpProtocol::dfs_restore(dfs_object_t *obj) { RESTORE_INT(m_echoTime); RESTORE_INT(m_lastEchoIdent); RESTORE_INT(m_echoSent); RESTORE_INT(m_mruNaks); RESTORE_INT(m_rxPackets); CFsmProtocol::dfs_restore(obj->find_child_object(&lookup_tag_CFsmProtocol)); } void CPapProtocol::dump_full_state(ctrlfd_t *cfd) { cfd->printf("m_parent(%s)\n", m_parent->get_name()); cfd->printf("m_authTimer {\n"); m_authTimer.dump_full_state(cfd); cfd->printf("}\n"); cfd->printf("CTimedProtocol {\n"); CTimedProtocol *ct = this; ct->dump_full_state(cfd); cfd->printf("}\n"); } DEFINE_TAG(m_authTimer); DEFINE_TAG(CTimedProtocol); void CPapProtocol::dfs_restore(dfs_object_t *obj) { m_authTimer.dfs_restore(obj->find_child_object(&lookup_tag_m_authTimer)); CTimedProtocol *p = this; p->dfs_restore(obj->find_child_object(&lookup_tag_CTimedProtocol)); } void CChapProtocol::dump_full_state(ctrlfd_t *cfd) { DUMP_INT(m_restart_count); cfd->printf("m_parent(%s)\n", m_parent->get_name()); cfd->printf("m_pollTimer {\n"); m_pollTimer.dump_full_state(cfd); cfd->printf("}\n"); cfd->printf("CTimedProtocol {\n"); CTimedProtocol *ct = this; ct->dump_full_state(cfd); cfd->printf("}\n"); } DEFINE_TAG(m_pollTimer); void CChapProtocol::dfs_restore(dfs_object_t *obj) { m_pollTimer.dfs_restore(obj->find_child_object(&lookup_tag_m_pollTimer)); CTimedProtocol *p = this; p->dfs_restore(obj->find_child_object(&lookup_tag_CTimedProtocol)); } void CTimedProtocol::dump_full_state(ctrlfd_t *cfd) { DUMP_INT(installed); DUMP_INT(m_restartTime); cfd->printf("ktimer {\n"); ktimer.dump_full_state(cfd); cfd->printf("}\n"); cfd->printf("CProtocol {\n"); CProtocol *p = this; p->dump_full_state(cfd); cfd->printf("}\n"); } DEFINE_TAG(installed); DEFINE_TAG(m_restartTime); DEFINE_TAG(ktimer); DEFINE_TAG(CProtocol); void CTimedProtocol::dfs_restore(dfs_object_t *obj) { RESTORE_INT(installed); RESTORE_INT(m_restartTime); ktimer.dfs_restore(obj->find_child_object(&lookup_tag_ktimer)); CProtocol *p = this; p->dfs_restore(obj->find_child_object(&lookup_tag_CProtocol)); } void CProtocol::dump_full_state(ctrlfd_t *cfd) { DUMP_INT(m_lastSentIdent); DUMP_INT(m_lastRcvdIdent); DUMP_INT(m_dropCause); DUMP_STRING(m_protocolName); } DEFINE_TAG(m_lastSentIdent); DEFINE_TAG(m_lastRcvdIdent); DEFINE_TAG(m_dropCause); DEFINE_TAG(m_protocolName); void CProtocol::dfs_restore(dfs_object_t *obj) { RESTORE_INT(m_lastSentIdent); RESTORE_INT(m_lastRcvdIdent); RESTORE_INT(m_dropCause); m_protocolName = obj->tag_str(&lookup_tag_m_protocolName, 0); } void CTimer::dump_full_state(ctrlfd_t *cfd) { DUMP_INT(active); DUMP_INT(set); if (set || active) cfd->printf("\t\tetv(%Ld)\n", etv.scalar()); } DEFINE_TAG(active); DEFINE_TAG(set); DEFINE_TAG(etv); void CTimer::dfs_restore(dfs_object_t *obj) { RESTORE_INT(active); RESTORE_INT(set); const char *str = obj->tag_str(&lookup_tag_etv, 1); if (str) { etv.Set(str); if (active) Start(); } } void CMlcpProtocol::dump_full_state(ctrlfd_t *cfd) { DUMP_INT(their_mrru); DUMP_INT(our_mrru); DUMP_INT(acked_mrru); cfd->printf("m_will {\n"); m_will.dump_full_state(cfd); cfd->printf("}\n"); cfd->printf("m_acked {\n"); m_acked.dump_full_state(cfd); cfd->printf("}\n"); cfd->printf("CFsmProtocol {\n"); CFsmProtocol *p = this; p->dump_full_state(cfd); cfd->printf("}\n"); } DEFINE_TAG(their_mrru); DEFINE_TAG(our_mrru); DEFINE_TAG(acked_mrru); void CMlcpProtocol::dfs_restore(dfs_object_t *obj) { RESTORE_INT(their_mrru); RESTORE_INT(our_mrru); RESTORE_INT(acked_mrru); m_will.dfs_restore(obj->find_child_object(&lookup_tag_m_will)); m_acked.dfs_restore(obj->find_child_object(&lookup_tag_m_acked)); CFsmProtocol *p = this; p->dfs_restore(obj->find_child_object(&lookup_tag_CFsmProtocol)); }