struct isis_circuit * isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg) { int old_state; old_state = circuit ? circuit->state : C_STATE_NA; if (isis->debugs & DEBUG_EVENTS) zlog_debug("CSM_EVENT: %s", EVENT2STR(event)); switch (old_state) { case C_STATE_NA: if (circuit) zlog_warn("Non-null circuit while state C_STATE_NA"); assert(circuit == NULL); switch (event) { case ISIS_ENABLE: circuit = isis_circuit_new(); isis_circuit_configure(circuit, (struct isis_area *)arg); circuit->state = C_STATE_CONF; break; case IF_UP_FROM_Z: circuit = isis_circuit_new(); isis_circuit_if_add(circuit, (struct interface *)arg); listnode_add(isis->init_circ_list, circuit); circuit->state = C_STATE_INIT; break; case ISIS_DISABLE: zlog_warn("circuit already disabled"); break; case IF_DOWN_FROM_Z: zlog_warn("circuit already disconnected"); break; } break; case C_STATE_INIT: assert(circuit); switch (event) { case ISIS_ENABLE: isis_circuit_configure(circuit, (struct isis_area *)arg); if (isis_circuit_up(circuit) != ISIS_OK) { isis_circuit_deconfigure( circuit, (struct isis_area *)arg); break; } circuit->state = C_STATE_UP; isis_event_circuit_state_change(circuit, circuit->area, 1); listnode_delete(isis->init_circ_list, circuit); break; case IF_UP_FROM_Z: assert(circuit); zlog_warn("circuit already connected"); break; case ISIS_DISABLE: zlog_warn("circuit already disabled"); break; case IF_DOWN_FROM_Z: isis_circuit_if_del(circuit, (struct interface *)arg); listnode_delete(isis->init_circ_list, circuit); isis_circuit_del(circuit); circuit = NULL; break; } break; case C_STATE_CONF: assert(circuit); switch (event) { case ISIS_ENABLE: zlog_warn("circuit already enabled"); break; case IF_UP_FROM_Z: isis_circuit_if_add(circuit, (struct interface *)arg); if (isis_circuit_up(circuit) != ISIS_OK) { flog_err( ISIS_ERR_CONFIG, "Could not bring up %s because of invalid config.", circuit->interface->name); flog_err( ISIS_ERR_CONFIG, "Clearing config for %s. Please re-examine it.", circuit->interface->name); if (circuit->ip_router) { circuit->ip_router = 0; circuit->area->ip_circuits--; } if (circuit->ipv6_router) { circuit->ipv6_router = 0; circuit->area->ipv6_circuits--; } circuit_update_nlpids(circuit); isis_circuit_deconfigure(circuit, circuit->area); listnode_add(isis->init_circ_list, circuit); circuit->state = C_STATE_INIT; break; } circuit->state = C_STATE_UP; isis_event_circuit_state_change(circuit, circuit->area, 1); break; case ISIS_DISABLE: isis_circuit_deconfigure(circuit, (struct isis_area *)arg); isis_circuit_del(circuit); circuit = NULL; break; case IF_DOWN_FROM_Z: zlog_warn("circuit already disconnected"); break; } break; case C_STATE_UP: assert(circuit); switch (event) { case ISIS_ENABLE: zlog_warn("circuit already configured"); break; case IF_UP_FROM_Z: zlog_warn("circuit already connected"); break; case ISIS_DISABLE: isis_circuit_down(circuit); isis_circuit_deconfigure(circuit, (struct isis_area *)arg); circuit->state = C_STATE_INIT; isis_event_circuit_state_change( circuit, (struct isis_area *)arg, 0); listnode_add(isis->init_circ_list, circuit); break; case IF_DOWN_FROM_Z: isis_circuit_down(circuit); isis_circuit_if_del(circuit, (struct interface *)arg); circuit->state = C_STATE_CONF; isis_event_circuit_state_change(circuit, circuit->area, 0); break; } break; default: zlog_warn("Invalid circuit state %d", old_state); } if (isis->debugs & DEBUG_EVENTS) zlog_debug("CSM_STATE_CHANGE: %s -> %s ", STATE2STR(old_state), circuit ? STATE2STR(circuit->state) : STATE2STR(C_STATE_NA)); return circuit; }
void skinny_isis_daemon() { char errbuf[PCAP_ERRBUF_SIZE]; struct pcap_device device; struct pcap_isis_callback_data cb_data; struct host_addr addr; struct prefix_ipv4 *ipv4; int index, ret; char area_tag[] = "default"; struct isis_area *area; struct isis_circuit *circuit; struct interface interface; memset(&device, 0, sizeof(struct pcap_device)); memset(&cb_data, 0, sizeof(cb_data)); memset(&interface, 0, sizeof(interface)); memset(&isis_spf_deadline, 0, sizeof(isis_spf_deadline)); /* initializing IS-IS structures */ isis_init(); dyn_cache_init(); /* thread master */ master = thread_master_create(); if (!config.nfacctd_isis_iface) { Log(LOG_ERR, "ERROR ( default/core/ISIS ): 'isis_daemon_iface' value is not specified. Terminating thread.\n"); exit(1); } if ((device.dev_desc = pcap_open_live(config.nfacctd_isis_iface, 65535, 0, 1000, errbuf)) == NULL) { Log(LOG_ERR, "ERROR ( default/core/ISIS ): pcap_open_live(): %s\n", errbuf); exit(1); } device.link_type = pcap_datalink(device.dev_desc); for (index = 0; _isis_devices[index].link_type != -1; index++) { if (device.link_type == _isis_devices[index].link_type) device.data = &_isis_devices[index]; } if (device.data == NULL) { Log(LOG_ERR, "ERROR ( default/core/ISIS ): data link not supported: %d\n", device.link_type); return; } else { Log(LOG_INFO, "OK ( default/core/ISIS ): link type is: %d\n", device.link_type); cb_data.device = &device; } area = isis_area_create(); area->area_tag = area_tag; area->is_type = IS_LEVEL_2; area->newmetric = TRUE; listnode_add(isis->area_list, area); Log(LOG_DEBUG, "DEBUG ( default/core/ISIS ): New IS-IS area instance %s\n", area->area_tag); if (config.nfacctd_isis_net) area_net_title(area, config.nfacctd_isis_net); else { Log(LOG_ERR, "ERROR ( default/core/ISIS ): 'isis_daemon_net' value is not specified. Terminating thread.\n"); exit_all(1); } circuit = isis_circuit_new(); circuit->circ_type = CIRCUIT_T_P2P; circuit->fd = pcap_fileno(device.dev_desc); circuit->tx = isis_send_pdu_p2p; circuit->interface = &interface; circuit->state = C_STATE_UP; if (config.nfacctd_isis_ip) { trim_spaces(config.nfacctd_isis_ip); ret = str_to_addr(config.nfacctd_isis_ip, &addr); if (!ret) { Log(LOG_ERR, "ERROR ( default/core/ISIS ): 'isis_daemon_ip' value is not a valid IPv4/IPv6 address. Terminating thread.\n"); exit_all(1); } } else { Log(LOG_ERR, "ERROR ( default/core/ISIS ): 'isis_daemon_ip' value is not specified. Terminating thread.\n"); exit_all(1); } circuit->ip_router = addr.address.ipv4.s_addr; ipv4 = isis_prefix_ipv4_new(); ipv4->prefixlen = 32; ipv4->prefix.s_addr = addr.address.ipv4.s_addr; circuit->ip_addrs = list_new(); listnode_add(circuit->ip_addrs, ipv4); circuit_update_nlpids(circuit); isis_circuit_configure(circuit, area); cb_data.circuit = circuit; area->ip_circuits = 1; memcpy(circuit->interface->name, config.nfacctd_isis_iface, strlen(config.nfacctd_isis_iface)); circuit->interface->ifindex = if_nametoindex(config.nfacctd_isis_iface); if (!config.nfacctd_isis_mtu) config.nfacctd_isis_mtu = SNAPLEN_ISIS_DEFAULT; for (;;) { /* XXX: should get a select() here at some stage? */ pcap_loop(device.dev_desc, -1, isis_pdu_runner, (u_char *) &cb_data); break; } pcap_close(device.dev_desc); }