Example #1
0
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;
}
Example #2
0
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);
}