Ejemplo n.º 1
0
/* Activity on the server socket.  Typically an incoming connection.  Accept the
 * connection and create a new file_info descriptor for it.
 */
static void server_handler(struct file_info *fi, int events){
	if (events & POLLIN) {
		struct sockaddr_in addr;
		socklen_t len = sizeof(addr);
		int skt = accept(fi->fd, (struct sockaddr *) &addr, &len);
		if (skt < 0) {
			perror("accept");
		}

		/* Make the socket non-blocking.
		 */
        // YOUR CODE HERE
        int res = fcntl(skt, F_SETFL, O_NONBLOCK);
    	report_error(res, "fcntl", errno);

		/* Keep track of the socket.
		 */
		struct file_info *fi = file_info_add(FI_INCOMING, skt, message_handler, POLLIN);

		/* We don't know yet who's on the other side exactly until we get the H(ello)
		 * message.  But for debugging it's convenient to keep the peer's socket address.
		 */
		fi->addr = addr;

		printf("New connection from %s:%d on socket %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), skt);

		send_hello(fi);
		gossip_to_peer(fi);
	}
	if (events & ~POLLIN) {
		fprintf(stderr, "server_handler: unknown events %x\n", events);
	}
}
Ejemplo n.º 2
0
void
isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state,
		       const char *reason)
{
  int old_state;
  int level = adj->level;
  struct isis_circuit *circuit;

  old_state = adj->adj_state;
  adj->adj_state = state;

  circuit = adj->circuit;

  if (isis->debugs & DEBUG_ADJ_PACKETS)
    {
      zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
		 circuit->area->area_tag,
		 old_state, state, reason ? reason : "unspecified");
    }

  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
    {
      if (state == ISIS_ADJ_UP)
	circuit->upadjcount[level - 1]++;
      if (state == ISIS_ADJ_DOWN)
	{
	  isis_delete_adj (adj, adj->circuit->u.bc.adjdb[level - 1]);
	  circuit->upadjcount[level - 1]--;
	}

      list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
      isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
				 circuit->u.bc.lan_neighs[level - 1]);
    }
  else if (state == ISIS_ADJ_UP)
    {				/* p2p interface */
      if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
	send_hello (circuit, 1);

      /* update counter & timers for debugging purposes */
      adj->last_flap = time (NULL);
      adj->flaps++;

      /* 7.3.17 - going up on P2P -> send CSNP */
      /* FIXME: yup, I know its wrong... but i will do it! (for now) */
      send_csnp (circuit, 1);
      send_csnp (circuit, 2);
    }
  else if (state == ISIS_ADJ_DOWN)
    {				/* p2p interface */
      adj->circuit->u.p2p.neighbor = NULL;
      isis_delete_adj (adj, NULL);
    }
  return;
}
Ejemplo n.º 3
0
/**
 * Handle the HELLO message sending.
 */
void RF24SNPNode::do_hello(uint8_t retries, uint8_t interval)
{
    for (uint8_t i=0; i<retries; i++)
    {
        send_hello();
        network.update();
        if (network.available())
            break;
        delay(interval);
    }
}
Ejemplo n.º 4
0
 void async_accept()
 {
     auto socket = std::make_shared<tcp::socket>(*io_service_);
     acceptor_.async_accept(*socket, [=](boost::system::error_code const& error) mutable {
         if (!error) {
             send_hello(std::move(socket));
         }
         else {
             std::cout << "accept error: " << error.message() << std::endl;
         }
         async_accept();
     });
 }
Ejemplo n.º 5
0
int main(int argc, char** argv){
	
	if(argc != 4){
		printf("Usage: snowcast_control servername serverport udpport\n");
		exit(-1);
	}
	//get ip addr infos..
	char* server_name = argv[1];
	char* server_port = argv[2];
	char* clnt_udpport = argv[3];
	
#ifdef DEBUG
	printf("%s\n", server_name);
#endif
	int sockfd;
	struct addrinfo hints, *servinfo;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	int rv = 0;
	if((rv = getaddrinfo(server_name,server_port,&hints, &servinfo) == -1)){
		printf("Error in getting address info: %s\n", strerror(errno));
		exit(-1);
	}
	
	if((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1){
		close(sockfd);
		printf("Error in initializing socket: %s\n", strerror(errno));
		exit(-1);
	}

	if((rv = connect(sockfd,servinfo->ai_addr,servinfo->ai_addrlen)) == -1){
		printf("%s\n",strerror(errno));
		//If "connection refused, that is there is no server started yet
		exit(-1);
	}	

	send_hello(sockfd, clnt_udpport);
	//waiting for input
	pthread_t sending_thread;
	pthread_t recving_thread;

	pthread_create(&sending_thread, NULL, send_message_loop, (void*)sockfd);
	pthread_create(&recving_thread, NULL, recv_message_loop, (void*)sockfd);
	pthread_join(sending_thread, 0);
	pthread_join(recving_thread, 0);

	freeaddrinfo(servinfo);
	return 0;
}
Ejemplo n.º 6
0
void pim_interface::property_changed(node *n, const char *name) {
	if (!strcmp(name, "dr_priority")) {
		if (conf()) {
			if (should_log(DEBUG))
				log().xprintf("Changed DR-Priority to %u\n",
					      (uint32_t)conf()->dr_priority());

			send_hello();
			elect_subnet_dr();
		}
	} else if (!strcmp(name, "hello_interval")) {
		update_hello_interval(conf()->hello_interval());
	}
}
Ejemplo n.º 7
0
void pim_interface::found_new_neighbour(pim_neighbour *neigh) {
	if (should_log(NORMAL))
		log().xprintf("New Neighbour at %{Addr}\n", neigh->localaddr());

	send_hello();

#ifndef PIM_NO_BSR
	if (am_dr()) {
		pim->bsr().found_new_neighbour(neigh);
	}
#endif

	pim->found_new_neighbour(neigh);
}
Ejemplo n.º 8
0
/* ARGSUSED */
void
if_hello_timer(int fd, short event, void *arg)
{
	struct iface *iface = arg;
	struct timeval tv;

	send_hello(iface);

	/* reschedule hello_timer */
	timerclear(&tv);
	tv.tv_sec = iface->hello_interval;
	if (evtimer_add(&iface->hello_timer, &tv) == -1)
		fatal("if_hello_timer");
}
Ejemplo n.º 9
0
/* This function is invoked in response to a non-blocking socket connect() call once
 * an outgoing connection is established or fails.
 */
static void connect_handler(struct file_info *fi, int events){
	char buf[512];

	if (events & (POLLERR | POLLHUP)) {
		double time;
		int error;
		socklen_t len = sizeof(error);
		if (getsockopt(fi->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
			perror("getsockopt");
		}
		switch (error) {
		case 0:
			printf("No connection on socket %d\n", fi->fd);
			time = timer_now() + 3;
			break;
		case ETIMEDOUT:
			printf("Timeout on socket %d\n", fi->fd);
			time = fi->u.fi_outgoing.connect_time + 5;
			break;
		default:
			printf("Error '%s' on socket %d\n", strerror(error), fi->fd);
			time = timer_now() + 5;
		}

		/* Start a timer to reconnect.
		 */
		timer_start(time, timer_reconnect, fi->uid);

		close(fi->fd);
		fi->fd = -1;
		fi->u.fi_outgoing.status = FI_CONNECTING;

		return;
	}
	if (events & POLLOUT) {
		printf("Socket %d connected\n", fi->fd);
		fi->handler = message_handler;
		fi->events = POLLIN;
		fi->u.fi_outgoing.status = FI_CONNECTED;

		send_hello(fi);
		gossip_to_peer(fi);
	}
	if (events & ~(POLLOUT|POLLERR|POLLHUP)) {
		printf("message_handler: unknown events %x\n", events);
		fi->events = 0;
	}
}
Ejemplo n.º 10
0
int main(int argc, char *argv[])
{
	struct sockaddr_in addr;
	int s, port = 0, first = 1, len;
	char *host = NULL;
	unsigned int seed;
	struct timeval tv;

	printf("OpenSSL ASN.1 brute forcer (Syzop/2003)\n\n");
	
	if (argc != 3) {
		fprintf(stderr, "Use: %s [ip] [port]\n", argv[0]);
		exit(1);
	}

	host = argv[1];
	port = atoi(argv[2]);
	if ((port < 1) || (port > 65535)) {
		fprintf(stderr, "Port out of range (%d)\n", port);
		exit(1);
	}

	gettimeofday(&tv, NULL);
	seed = (getpid() ^ tv.tv_sec) + (tv.tv_usec * 1000);

	printf("seed = %u\n", seed);
	srand(seed);

	memset(&addr, 0, sizeof(addr));


	signal(SIGPIPE, SIG_IGN); /* Ignore SIGPIPE */

while(1)
{

	if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		fprintf(stderr, "Socket error: %s\n", strerror(errno));
		exit(EXIT_FAILURE);
	}
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(host);
	if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		fprintf(stderr, "Unable to connect: %s\n", strerror(errno));
		if (!first)
			diffit();
		exit(EXIT_FAILURE);
	}
	first = 0;
	printf("."); fflush(stdout);

	len = send_hello();
	write(s, buf, len);
	len = send_crap();
	corruptor(buf, len);
	write(s, buf, len);
	usleep(1000); /* wait.. */
	close(s);
}
	
	exit(EXIT_SUCCESS);
}
Ejemplo n.º 11
0
/**
 ******************************************************************************
 * @brief      df_update
 * @param[in]  None
 * @param[out] None
 * @retval     true-成功、false-失败
 *
 * @details    从串口进行升级
 *
 * @note 
 ******************************************************************************
 */
STATUS
uart_update(void) {
    uint32 startAddress = 0,
           transferSize = 0;
    uint8 size;
    uint8 status;
    uint8 cmd,
		  data[MAX_BUF_SIZE];

    print("Press ESC to upgrade from serial port ...\n\r");

    /* 检测是否要从串口进行升级 */
    if (!esc_key_detect())
        return (OK);

    print("Receiving data ...");

    /* 过滤多余按键或串口切换产生的错误字节 */
    while (!send_hello()) {
    }

    startAddress = 0xffffffff;

    status = COMMAND_RET_SUCCESS;
    while (true) {
        /* 如果未正确接收报文,放弃处理 */
        if (!receive_packet(&cmd, data, &size)) {
            send_nak();
            continue;
        }

        /* 根据命令字进行处理 */
        switch (cmd) {
			/* 测试连接 */
            case COMMAND_PING:
                status = COMMAND_RET_SUCCESS;

                /* 返回确认包 */
                send_ack();

                break;

            /* 开始下载 */
            case COMMAND_DOWNLOAD:
                status = COMMAND_RET_SUCCESS;
                do {
                    /* 检查报文长度 */
                    if (size != 8) {
                        status = COMMAND_RET_INVALID_CMD;

                        break;
                    }

                    /**
                     * 起始地址
                     */
                    startAddress = (data[0] << 24)
                                 | (data[1] << 16)
                                 | (data[2] <<  8)
                                 |  data[3];
                    /* 起始地址必须为0,由各BootLoader自行决定写入位置 */
                    if (startAddress != 0u)
                    {
                        status = COMMAND_RET_INVALID_CMD;
                        break;
                    }
                    startAddress = APP_START_ADDRESS;
                    /**
                     * 下载字节数
                     */
                    transferSize = (data[4] << 24)
                                 | (data[5] << 16)
                                 | (data[6] <<  8)
                                 |  data[7];

                    /**
                     * 初始化Flash
                     */
                    iflash_init();

                    /**
                     * 擦除将要更新的空间
                     */
                    if (!iflash_erase(startAddress, transferSize))
                        status = COMMAND_RET_FLASH_FAIL;
                } while(false);

                if (status != COMMAND_RET_SUCCESS)
                    transferSize = 0;

                /**
                 * 确认报文已得到处理
                 */
                send_ack();

                break;

            /**
             * 获取状态
             */
            case COMMAND_GET_STATUS:
                /**
                 * 返回确认包
                 */
                send_ack();

                /**
                 * 返回当前状态
                 */
                send_status(status);

                break;
            /**
             * 数据
             */
            case COMMAND_SEND_DATA:
                status = COMMAND_RET_SUCCESS;

                /**
                 * 注意:后台程序应保证size按字对齐,否则写入结果无法预料
                 * 检查是否还有数据未写入
                 */
                if (transferSize >= size) {
                    if (!iflash_write(startAddress, data, size))
                        status = COMMAND_RET_FLASH_FAIL;
                    else {
                        transferSize -= size;
                        startAddress += size;
                    }
                }
                else status = COMMAND_RET_INVALID_PARA;

                /**
                 * 返回确认包
                 */
                send_ack();

                break;
            /**
             * 复位
             */
            case COMMAND_RESET:
                /**
                 * 返回确认包
                 */
                send_ack();

                // 复位
                reset();

                // 死循环
                while (true) {
                    ;
                }
                break;
            default: // 未知命令
                // 返回确认包
                send_ack();

                // 状态设为未知命令
                status = COMMAND_RET_UNKNOWN_CMD;
                break;
        }
    }
    return OK;
}
Ejemplo n.º 12
0
void
isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state new_state,
		       const char *reason)
{
  int old_state;
  int level;
  struct isis_circuit *circuit;

  old_state = adj->adj_state;
  adj->adj_state = new_state;

  circuit = adj->circuit;

  if (isis->debugs & DEBUG_ADJ_PACKETS)
    {
      zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s",
		 circuit->area->area_tag,
		 old_state, new_state, reason ? reason : "unspecified");
    }

  if (circuit->area->log_adj_changes)
    {
      const char *adj_name;
      struct isis_dynhn *dyn;

      dyn = dynhn_find_by_id (adj->sysid);
      if (dyn)
	adj_name = (const char *)dyn->name.name;
      else
	adj_name = adj->sysid ? sysid_print (adj->sysid) : "unknown";

      zlog_info ("%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s",
		 adj_name,
		 adj->circuit->interface->name,
		 adj_state2string (old_state),
		 adj_state2string (new_state),
		 reason ? reason : "unspecified");
    }

  if (circuit->circ_type == CIRCUIT_T_BROADCAST)
    {
      for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++)
      {
        if ((adj->level & level) == 0)
          continue;
        if (new_state == ISIS_ADJ_UP)
        {
          circuit->upadjcount[level - 1]++;
          isis_event_adjacency_state_change (adj, new_state);
          /* update counter & timers for debugging purposes */
          adj->last_flap = time (NULL);
          adj->flaps++;
        }
        else if (new_state == ISIS_ADJ_DOWN)
        {
          listnode_delete (circuit->u.bc.adjdb[level - 1], adj);
          circuit->upadjcount[level - 1]--;
          if (circuit->upadjcount[level - 1] == 0)
            {
              /* Clean lsp_queue when no adj is up. */
              if (circuit->lsp_queue)
                list_delete_all_node (circuit->lsp_queue);
            }
          isis_event_adjacency_state_change (adj, new_state);
          isis_delete_adj (adj);
        }

        if (circuit->u.bc.lan_neighs[level - 1])
          {
            list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
            isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
                                       circuit->u.bc.lan_neighs[level - 1]);
          }

        /* On adjacency state change send new pseudo LSP if we are the DR */
        if (circuit->u.bc.is_dr[level - 1])
          lsp_regenerate_schedule_pseudo (circuit, level);
      }
    }
  else if (circuit->circ_type == CIRCUIT_T_P2P)
    {
      for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++)
      {
        if ((adj->level & level) == 0)
          continue;
        if (new_state == ISIS_ADJ_UP)
        {
          circuit->upadjcount[level - 1]++;
          isis_event_adjacency_state_change (adj, new_state);

          if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN)
            send_hello (circuit, level);

          /* update counter & timers for debugging purposes */
          adj->last_flap = time (NULL);
          adj->flaps++;

          /* 7.3.17 - going up on P2P -> send CSNP */
          /* FIXME: yup, I know its wrong... but i will do it! (for now) */
          send_csnp (circuit, level);
        }
        else if (new_state == ISIS_ADJ_DOWN)
        {
          if (adj->circuit->u.p2p.neighbor == adj)
            adj->circuit->u.p2p.neighbor = NULL;
          circuit->upadjcount[level - 1]--;
          if (circuit->upadjcount[level - 1] == 0)
            {
              /* Clean lsp_queue when no adj is up. */
              if (circuit->lsp_queue)
                list_delete_all_node (circuit->lsp_queue);
            }
          isis_event_adjacency_state_change (adj, new_state);
          isis_delete_adj (adj);
        }
      }
    }

  return;
}
Ejemplo n.º 13
0
int
main(int argc, char **argv)
{
    struct sockaddr_in6 sin6;
    int rc, fd, i, opt;
    time_t expiry_time, source_expiry_time, kernel_dump_time;
    const char **config_files = NULL;
    int num_config_files = 0;
    void *vrc;
    unsigned int seed;
    struct interface *ifp;

    gettime(&now);

    rc = read_random_bytes(&seed, sizeof(seed));
    if(rc < 0) {
        perror("read(random)");
        seed = 42;
    }

    seed ^= (now.tv_sec ^ now.tv_usec);
    srandom(seed);

    parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL);
    protocol_port = 6696;
    change_smoothing_half_life(4);
    has_ipv6_subtrees = kernel_has_ipv6_subtrees();

    while(1) {
        opt = getopt(argc, argv,
                     "m:p:h:H:i:k:A:sruS:d:g:G:lwz:M:t:T:c:C:DL:I:V");
        if(opt < 0)
            break;

        switch(opt) {
        case 'm':
            rc = parse_address(optarg, protocol_group, NULL);
            if(rc < 0)
                goto usage;
            if(protocol_group[0] != 0xff) {
                fprintf(stderr,
                        "%s is not a multicast address\n", optarg);
                goto usage;
            }
            if(protocol_group[1] != 2) {
                fprintf(stderr,
                        "Warning: %s is not a link-local multicast address\n",
                        optarg);
            }
            break;
        case 'p':
            protocol_port = parse_nat(optarg);
            if(protocol_port <= 0 || protocol_port > 0xFFFF)
                goto usage;
            break;
        case 'h':
            default_wireless_hello_interval = parse_thousands(optarg);
            if(default_wireless_hello_interval <= 0 ||
               default_wireless_hello_interval > 0xFFFF * 10)
                goto usage;
            break;
        case 'H':
            default_wired_hello_interval = parse_thousands(optarg);
            if(default_wired_hello_interval <= 0 ||
               default_wired_hello_interval > 0xFFFF * 10)
                goto usage;
            break;
        case 'k':
            kernel_metric = parse_nat(optarg);
            if(kernel_metric < 0 || kernel_metric > 0xFFFF)
                goto usage;
            break;
        case 'A':
            allow_duplicates = parse_nat(optarg);
            if(allow_duplicates < 0 || allow_duplicates > 0xFFFF)
                goto usage;
            break;
        case 's':
            split_horizon = 0;
            break;
        case 'r':
            random_id = 1;
            break;
        case 'u':
            keep_unfeasible = 1;
            break;
        case 'S':
            state_file = optarg;
            break;
        case 'd':
            debug = parse_nat(optarg);
            if(debug < 0)
                goto usage;
            break;
        case 'g':
        case 'G':
            if(opt == 'g')
                local_server_write = 0;
            else
                local_server_write = 1;
            if(optarg[0] == '/') {
                local_server_port = -1;
                free(local_server_path);
                local_server_path = strdup(optarg);
            } else {
                local_server_port = parse_nat(optarg);
                free(local_server_path);
                local_server_path = NULL;
                if(local_server_port <= 0 || local_server_port > 0xFFFF)
                    goto usage;
            }
            break;
        case 'l':
            link_detect = 1;
            break;
        case 'w':
            all_wireless = 1;
            break;
        case 'z':
            {
                char *comma;
                diversity_kind = (int)strtol(optarg, &comma, 0);
                if(*comma == '\0')
                    diversity_factor = 128;
                else if(*comma == ',')
                    diversity_factor = parse_nat(comma + 1);
                else
                    goto usage;
                if(diversity_factor <= 0 || diversity_factor > 256)
                    goto usage;
            }
            break;
        case 'M': {
            int l = parse_nat(optarg);
            if(l < 0 || l > 3600)
                goto usage;
            change_smoothing_half_life(l);
            break;
        }
        case 't':
            export_table = parse_nat(optarg);
            if(export_table < 0 || export_table > 0xFFFF)
                goto usage;
            break;
        case 'T':
            if(add_import_table(parse_nat(optarg)))
                goto usage;
            break;
        case 'c':
            config_files = realloc(config_files,
                                   (num_config_files + 1) * sizeof(char*));
            if(config_files == NULL) {
                fprintf(stderr, "Couldn't allocate config file.\n");
                exit(1);
            }
            config_files[num_config_files++] = optarg;
            break;
        case 'C':
            rc = parse_config_from_string(optarg, strlen(optarg), NULL);
            if(rc != CONFIG_ACTION_DONE) {
                fprintf(stderr,
                        "Couldn't parse configuration from command line.\n");
                exit(1);
            }
            break;
        case 'D':
            do_daemonise = 1;
            break;
        case 'L':
            logfile = optarg;
            break;
        case 'I':
            pidfile = optarg;
            break;
        case 'V':
            fprintf(stderr, "%s\n", BABELD_VERSION);
            exit(0);
            break;
        default:
            goto usage;
        }
    }

    if(num_config_files == 0) {
        if(access("/etc/babeld.conf", F_OK) >= 0) {
            config_files = malloc(sizeof(char*));
            if(config_files == NULL) {
                fprintf(stderr, "Couldn't allocate config file.\n");
                exit(1);
            }
            config_files[num_config_files++] = "/etc/babeld.conf";
        }
    }

    for(i = 0; i < num_config_files; i++) {
        int line;
        rc = parse_config_from_file(config_files[i], &line);
        if(rc < 0) {
            fprintf(stderr,
                    "Couldn't parse configuration from file %s "
                    "(error at line %d).\n",
                    config_files[i], line);
            exit(1);
        }
    }

    free(config_files);

    if(default_wireless_hello_interval <= 0)
        default_wireless_hello_interval = 4000;
    default_wireless_hello_interval = MAX(default_wireless_hello_interval, 5);

    if(default_wired_hello_interval <= 0)
        default_wired_hello_interval = 4000;
    default_wired_hello_interval = MAX(default_wired_hello_interval, 5);

    resend_delay = 2000;
    resend_delay = MIN(resend_delay, default_wireless_hello_interval / 2);
    resend_delay = MIN(resend_delay, default_wired_hello_interval / 2);
    resend_delay = MAX(resend_delay, 20);

    if(do_daemonise) {
        if(logfile == NULL)
            logfile = "/var/log/babeld.log";
    }

    rc = reopen_logfile();
    if(rc < 0) {
        perror("reopen_logfile()");
        exit(1);
    }

    fd = open("/dev/null", O_RDONLY);
    if(fd < 0) {
        perror("open(null)");
        exit(1);
    }

    rc = dup2(fd, 0);
    if(rc < 0) {
        perror("dup2(null, 0)");
        exit(1);
    }

    close(fd);

    if(do_daemonise) {
        rc = daemonise();
        if(rc < 0) {
            perror("daemonise");
            exit(1);
        }
    }

    if(pidfile && pidfile[0] != '\0') {
        int pfd, len;
        char buf[100];

        len = snprintf(buf, 100, "%lu", (unsigned long)getpid());
        if(len < 0 || len >= 100) {
            perror("snprintf(getpid)");
            exit(1);
        }

        pfd = open(pidfile, O_WRONLY | O_CREAT | O_EXCL, 0644);
        if(pfd < 0) {
            char buf[40];
            snprintf(buf, 40, "creat(%s)", pidfile);
            buf[39] = '\0';
            perror(buf);
            exit(1);
        }

        rc = write(pfd, buf, len);
        if(rc < len) {
            perror("write(pidfile)");
            goto fail_pid;
        }

        close(pfd);
    }

    rc = kernel_setup(1);
    if(rc < 0) {
        fprintf(stderr, "kernel_setup failed.\n");
        goto fail_pid;
    }

    rc = kernel_setup_socket(1);
    if(rc < 0) {
        fprintf(stderr, "kernel_setup_socket failed.\n");
        kernel_setup(0);
        goto fail_pid;
    }

    rc = finalise_config();
    if(rc < 0) {
        fprintf(stderr, "Couldn't finalise configuration.\n");
        goto fail;
    }

    for(i = optind; i < argc; i++) {
        vrc = add_interface(argv[i], NULL);
        if(vrc == NULL)
            goto fail;
    }

    if(interfaces == NULL) {
        fprintf(stderr, "Eek... asked to run on no interfaces!\n");
        goto fail;
    }

    if(!have_id && !random_id) {
        /* We use all available interfaces here, since this increases the
           chances of getting a stable router-id in case the set of Babel
           interfaces changes. */

        for(i = 1; i < 256; i++) {
            char buf[IF_NAMESIZE], *ifname;
            unsigned char eui[8];
            ifname = if_indextoname(i, buf);
            if(ifname == NULL)
                continue;
            rc = if_eui64(ifname, i, eui);
            if(rc < 0)
                continue;
            memcpy(myid, eui, 8);
            have_id = 1;
            break;
        }
    }

    if(!have_id) {
        if(!random_id)
            fprintf(stderr,
                    "Warning: couldn't find router id -- "
                    "using random value.\n");
        rc = read_random_bytes(myid, 8);
        if(rc < 0) {
            perror("read(random)");
            goto fail;
        }
        /* Clear group and global bits */
        myid[0] &= ~3;
    }

    myseqno = (random() & 0xFFFF);

    fd = open(state_file, O_RDONLY);
    if(fd < 0 && errno != ENOENT)
        perror("open(babel-state)");
    rc = unlink(state_file);
    if(fd >= 0 && rc < 0) {
        perror("unlink(babel-state)");
        /* If we couldn't unlink it, it's probably stale. */
        close(fd);
        fd = -1;
    }
    if(fd >= 0) {
        char buf[100];
        int s;
        rc = read(fd, buf, 99);
        if(rc < 0) {
            perror("read(babel-state)");
        } else {
            buf[rc] = '\0';
            rc = sscanf(buf, "%d\n", &s);
            if(rc == 1 && s >= 0 && s <= 0xFFFF) {
                myseqno = seqno_plus(s, 1);
            } else {
                fprintf(stderr, "Couldn't parse babel-state.\n");
            }
        }
        close(fd);
        fd = -1;
    }

    protocol_socket = babel_socket(protocol_port);
    if(protocol_socket < 0) {
        perror("Couldn't create link local socket");
        goto fail;
    }

    if(local_server_port >= 0) {
        local_server_socket = tcp_server_socket(local_server_port, 1);
        if(local_server_socket < 0) {
            perror("local_server_socket");
            goto fail;
        }
    } else if(local_server_path) {
        local_server_socket = unix_server_socket(local_server_path);
        if(local_server_socket < 0) {
            perror("local_server_socket");
            goto fail;
        }
    }

    init_signals();
    rc = resize_receive_buffer(1500);
    if(rc < 0)
        goto fail;
    if(receive_buffer == NULL)
        goto fail;

    check_interfaces();

    rc = check_xroutes(0);
    if(rc < 0)
        fprintf(stderr, "Warning: couldn't check exported routes.\n");
    rc = check_rules();
    if(rc < 0)
        fprintf(stderr, "Warning: couldn't check rules.\n");

    kernel_routes_changed = 0;
    kernel_rules_changed = 0;
    kernel_link_changed = 0;
    kernel_addr_changed = 0;
    kernel_dump_time = now.tv_sec + roughly(30);
    schedule_neighbours_check(5000, 1);
    schedule_interfaces_check(30000, 1);
    expiry_time = now.tv_sec + roughly(30);
    source_expiry_time = now.tv_sec + roughly(300);

    /* Make some noise so that others notice us, and send retractions in
       case we were restarted recently */
    FOR_ALL_INTERFACES(ifp) {
        if(!if_up(ifp))
            continue;
        /* Apply jitter before we send the first message. */
        usleep(roughly(10000));
        gettime(&now);
        send_hello(ifp);
        send_wildcard_retraction(ifp);
    }

    FOR_ALL_INTERFACES(ifp) {
        if(!if_up(ifp))
            continue;
        usleep(roughly(10000));
        gettime(&now);
        send_hello(ifp);
        send_wildcard_retraction(ifp);
        send_self_update(ifp);
        send_request(ifp, NULL, 0, NULL, 0);
        flushupdates(ifp);
        flushbuf(ifp);
    }

    debugf("Entering main loop.\n");

    while(1) {
        struct timeval tv;
        fd_set readfds;

        gettime(&now);

        tv = check_neighbours_timeout;
        timeval_min(&tv, &check_interfaces_timeout);
        timeval_min_sec(&tv, expiry_time);
        timeval_min_sec(&tv, source_expiry_time);
        timeval_min_sec(&tv, kernel_dump_time);
        timeval_min(&tv, &resend_time);
        FOR_ALL_INTERFACES(ifp) {
            if(!if_up(ifp))
                continue;
            timeval_min(&tv, &ifp->flush_timeout);
            timeval_min(&tv, &ifp->hello_timeout);
            timeval_min(&tv, &ifp->update_timeout);
            timeval_min(&tv, &ifp->update_flush_timeout);
        }
        timeval_min(&tv, &unicast_flush_timeout);
        FD_ZERO(&readfds);
        if(timeval_compare(&tv, &now) > 0) {
            int maxfd = 0;
            timeval_minus(&tv, &tv, &now);
            FD_SET(protocol_socket, &readfds);
            maxfd = MAX(maxfd, protocol_socket);
            if(kernel_socket < 0) kernel_setup_socket(1);
            if(kernel_socket >= 0) {
                FD_SET(kernel_socket, &readfds);
                maxfd = MAX(maxfd, kernel_socket);
            }
            if(local_server_socket >= 0 &&
               num_local_sockets < MAX_LOCAL_SOCKETS) {
                FD_SET(local_server_socket, &readfds);
                maxfd = MAX(maxfd, local_server_socket);
            }
            for(i = 0; i < num_local_sockets; i++) {
                FD_SET(local_sockets[i].fd, &readfds);
                maxfd = MAX(maxfd, local_sockets[i].fd);
            }
            rc = select(maxfd + 1, &readfds, NULL, NULL, &tv);
            if(rc < 0) {
                if(errno != EINTR) {
                    perror("select");
                    sleep(1);
                }
                rc = 0;
                FD_ZERO(&readfds);
            }
        }

        gettime(&now);

        if(exiting)
            break;

        if(kernel_socket >= 0 && FD_ISSET(kernel_socket, &readfds)) {
            struct kernel_filter filter = {0};
            filter.route = kernel_route_notify;
            filter.addr = kernel_addr_notify;
            filter.link = kernel_link_notify;
            filter.rule = kernel_rule_notify;
            kernel_callback(&filter);
        }

        if(FD_ISSET(protocol_socket, &readfds)) {
            rc = babel_recv(protocol_socket,
                            receive_buffer, receive_buffer_size,
                            (struct sockaddr*)&sin6, sizeof(sin6));
            if(rc < 0) {
                if(errno != EAGAIN && errno != EINTR) {
                    perror("recv");
                    sleep(1);
                }
            } else {
                FOR_ALL_INTERFACES(ifp) {
                    if(!if_up(ifp))
                        continue;
                    if(ifp->ifindex == sin6.sin6_scope_id) {
                        parse_packet((unsigned char*)&sin6.sin6_addr, ifp,
                                     receive_buffer, rc);
                        VALGRIND_MAKE_MEM_UNDEFINED(receive_buffer,
                                                    receive_buffer_size);
                        break;
                    }
                }
            }
        }

        if(local_server_socket >= 0 && FD_ISSET(local_server_socket, &readfds))
           accept_local_connections();

        i = 0;
        while(i < num_local_sockets) {
            if(FD_ISSET(local_sockets[i].fd, &readfds)) {
                rc = local_read(&local_sockets[i]);
                if(rc <= 0) {
                    if(rc < 0) {
                        if(errno == EINTR || errno == EAGAIN)
                            continue;
                        perror("read(local_socket)");
                    }
                    local_socket_destroy(i);
                }
            }
            i++;
        }

        if(reopening) {
            kernel_dump_time = now.tv_sec;
            check_neighbours_timeout = now;
            expiry_time = now.tv_sec;
            rc = reopen_logfile();
            if(rc < 0) {
                perror("reopen_logfile");
                break;
            }
            reopening = 0;
        }

        if(kernel_link_changed || kernel_addr_changed) {
            check_interfaces();
            kernel_link_changed = 0;
        }

        if(kernel_routes_changed || kernel_addr_changed ||
           kernel_rules_changed || now.tv_sec >= kernel_dump_time) {
            rc = check_xroutes(1);
            if(rc < 0)
                fprintf(stderr, "Warning: couldn't check exported routes.\n");
            rc = check_rules();
            if(rc < 0)
                fprintf(stderr, "Warning: couldn't check rules.\n");
            kernel_routes_changed = kernel_rules_changed =
                kernel_addr_changed = 0;
            if(kernel_socket >= 0)
                kernel_dump_time = now.tv_sec + roughly(300);
            else
                kernel_dump_time = now.tv_sec + roughly(30);
        }

        if(timeval_compare(&check_neighbours_timeout, &now) < 0) {
            int msecs;
            msecs = check_neighbours();
            /* Multiply by 3/2 to allow neighbours to expire. */
            msecs = MAX(3 * msecs / 2, 10);
            schedule_neighbours_check(msecs, 1);
        }

        if(timeval_compare(&check_interfaces_timeout, &now) < 0) {
            check_interfaces();
            schedule_interfaces_check(30000, 1);
        }

        if(now.tv_sec >= expiry_time) {
            expire_routes();
            expire_resend();
            expiry_time = now.tv_sec + roughly(30);
        }

        if(now.tv_sec >= source_expiry_time) {
            expire_sources();
            source_expiry_time = now.tv_sec + roughly(300);
        }

        FOR_ALL_INTERFACES(ifp) {
            if(!if_up(ifp))
                continue;
            if(timeval_compare(&now, &ifp->hello_timeout) >= 0)
                send_hello(ifp);
            if(timeval_compare(&now, &ifp->update_timeout) >= 0)
                send_update(ifp, 0, NULL, 0, NULL, 0);
            if(timeval_compare(&now, &ifp->update_flush_timeout) >= 0)
                flushupdates(ifp);
        }

        if(resend_time.tv_sec != 0) {
            if(timeval_compare(&now, &resend_time) >= 0)
                do_resend();
        }

        if(unicast_flush_timeout.tv_sec != 0) {
            if(timeval_compare(&now, &unicast_flush_timeout) >= 0)
                flush_unicast(1);
        }

        FOR_ALL_INTERFACES(ifp) {
            if(!if_up(ifp))
                continue;
            if(ifp->flush_timeout.tv_sec != 0) {
                if(timeval_compare(&now, &ifp->flush_timeout) >= 0)
                    flushbuf(ifp);
            }
        }

        if(UNLIKELY(debug || dumping)) {
            dump_tables(stdout);
            dumping = 0;
        }
    }
Ejemplo n.º 14
0
int
main(int argc, char **argv)
{
    int i, opt, rc;
    int sock;
    struct timeval now;

    gettime(&now);

    inet_pton(AF_INET6, "ff02::1:6", &babel_group);
    babel_port = 6696;

    srand(now.tv_sec ^ now.tv_usec);

    while(1) {
        opt = getopt(argc, argv, "p:u:h:c:");
        if(opt < 0)
            break;

        switch(opt) {
        case 'p':               /* prefix */
            if(have_prefix)
                goto usage;
            rc = inet_pton(AF_INET6, optarg, &myprefix);
            if(rc != 1)
                goto usage;
            have_prefix = 1;
            break;
        case 'u':               /* update interval */
            update_interval = atoi(optarg);
            if(update_interval <= 0)
                goto usage;
            break;
        case 'h':               /* hello interval */
            hello_interval = atoi(optarg);
            if(hello_interval <= 0)
                goto usage;
            break;
        case 'c':               /* link cost */
            link_cost = atoi(optarg);
            if(link_cost <= 0)
                goto usage;
            break;
        default:
            goto usage;
        }
    }

    if(!have_prefix)
        fprintf(stderr, "Warning: you didn't ask me to announce a prefix.\n");

    if(argc - optind > MAXINTERFACES) {
        fprintf(stderr, "Too many interfaces.\n");
        exit(1);
    }

    for(i = 0; i < argc - optind; i++) {
        int index;

        index = if_nametoindex(argv[optind + i]);
        if(index <= 0) {
            fprintf(stderr, "Unknown interface %s\n", argv[i]);
            exit(1);
        }
        memset(&interfaces[i], 0, sizeof(interfaces[i]));
        interfaces[i].ifindex = index;
        interfaces[i].ifname = argv[optind + i];
        rc = get_local_address(interfaces[i].ifindex, &interfaces[i].address);
        if(rc < 0) {
            perror("get_local_address");
            fprintf(stderr, "Continuing anyway -- "
                    "won't perform reachibility detection "
                    "on interface %s.\n", interfaces[i].ifname);
        }
        interfaces[i].seqno = rand() & 0xFFFF;
    }
    numinterfaces = argc - optind;

    random_eui64(my_router_id);
    myseqno = rand() & 0xFFFF;

    sock = babel_socket(babel_port);
    if(sock < 0) {
        perror("babel_socket");
        exit(1);
    }

    for(i = 0; i < numinterfaces; i++) {
        rc = join_group(sock, interfaces[i].ifindex, &babel_group);
        if(rc < 0) {
            perror("setsockopt(IPV6_JOIN_GROUP)");
            exit(1);
        }
    }

    catch_signals(sigexit);

    while(!exiting) {
        struct sockaddr_in6 sin6;
        unsigned char buf[BUF_SIZE];
        struct timeval tv, update, zerotv = {0, 0};
        fd_set readfds;
        int hello_count = 0;

        /* Compute when to wake up. */
        gettime(&now);
        timeval_add_msec(&tv, &last_hello, hello_interval * 700 + rand() % 300);
        timeval_add_msec(&update, &last_update,
                         update_interval * 700 + rand() % 300);
        timeval_min(&tv, &update);

        if(selected_nexthop_metric < INFINITY) {
            int n = find_neighbour(selected_interface, &selected_nexthop, 0);
            assert(n >= 0);
            timeval_min(&tv, &neighbours[n].timeout);
            timeval_min(&tv, &selected_nexthop_timeout);
        }

        if(timeval_compare(&tv, &now) > 0)
            timeval_minus(&tv, &tv, &now);
        else
            tv = zerotv;

        FD_ZERO(&readfds);
        FD_SET(sock, &readfds);

        rc = select(sock + 1, &readfds, NULL, NULL, &tv);
        if(rc < 0 && errno != EINTR) {
            perror("select");
            nap(1000);
            continue;
        }

        if(rc > 0) {
            /* Oh good, a packet. */
            socklen_t sin6len = sizeof(sin6);
            rc = recvfrom(sock, buf, BUF_SIZE, 0,
                          (struct sockaddr*)&sin6, &sin6len);

            if(rc < 0 || rc >= BUF_SIZE) {
                if(rc < 0 && errno != EAGAIN) {
                    perror("recv");
                    nap(100);
                }
                continue;
            }

            if(sin6.sin6_family != PF_INET6) {
                fprintf(stderr, "Received unexpected packet in family %d.\n",
                        sin6.sin6_family);
                nap(100);
                continue;
            }

            i = find_interface(sin6.sin6_scope_id);
            if(i < 0) {
                fprintf(stderr, "Received packet on unknown interface %d.\n",
                        sin6.sin6_scope_id);
                nap(100);
                continue;
            }
            handle_packet(sock, buf, rc, &interfaces[i], &sin6.sin6_addr);
        }

        gettime(&now);

        if(selected_nexthop_metric < INFINITY) {
            int n = find_neighbour(selected_interface, &selected_nexthop, 0);
            assert(n >= 0);

            if(neighbour_expired(n, &now)) {
                /* Expire neighbour. */
                flush_default_route();
                delete_neighbour(n);
            } else if(timeval_compare(&now, &selected_nexthop_timeout) > 0) {
                /* Expire route. */
                flush_default_route();
            }
            /* Send a request? */
        }

        /* Is it time to send hellos? */
        if(timeval_minus_msec(&now, &last_hello) > hello_interval * 700) {
            for(i = 0; i < numinterfaces; i++)
                send_hello(sock, &interfaces[i]);
            last_hello = now;
            hello_count++;
            /* Make an expiry pass every ten hellos. */
            if(hello_count >= 10) {
                expire_neighbours();
                hello_count = 0;
            }
        }

        /* Is it time to send an update? */
        if(timeval_minus_msec(&now, &last_update) > update_interval * 700) {
            for(i = 0; i < numinterfaces; i++)
                send_update(sock, &interfaces[i], 0);
            last_update = now;
        }
    }

    /* Send a bunch of retractions. */
    for(i = 0; i < numinterfaces; i++)
        send_update(sock, &interfaces[i], 1);

    flush_default_route();

    return 0;

 usage:
    fprintf(stderr,
            "Usage: sbabeld "
            "[-p prefix] [-u interval] [-h interval] [-c cost] interface...\n");
    return 1;
}
Ejemplo n.º 15
0
int
interface_up(struct interface *ifp, int up)
{
    int mtu, rc, wired;
    struct ipv6_mreq mreq;

    if((!!up) == if_up(ifp))
        return 0;

    if(up)
        ifp->flags |= IF_UP;
    else
        ifp->flags &= ~IF_UP;

    if(up) {
        if(ifp->ifindex <= 0) {
            fprintf(stderr,
                    "Upping unknown interface %s.\n", ifp->name);
            goto fail;
        }

        rc = kernel_setup_interface(1, ifp->name, ifp->ifindex);
        if(rc < 0) {
            fprintf(stderr, "kernel_setup_interface(%s, %d) failed.\n",
                    ifp->name, ifp->ifindex);
            goto fail;
        }

        mtu = kernel_interface_mtu(ifp->name, ifp->ifindex);
        if(mtu < 0) {
            fprintf(stderr, "Warning: couldn't get MTU of interface %s (%d).\n",
                    ifp->name, ifp->ifindex);
            mtu = 1280;
        }

        /* We need to be able to fit at least two messages into a packet,
           so MTUs below 116 require lower layer fragmentation. */
        /* In IPv6, the minimum MTU is 1280, and every host must be able
           to reassemble up to 1500 bytes, but I'd rather not rely on this. */
        if(mtu < 128) {
            fprintf(stderr, "Suspiciously low MTU %d on interface %s (%d).\n",
                    mtu, ifp->name, ifp->ifindex);
            mtu = 128;
        }

        if(ifp->sendbuf)
            free(ifp->sendbuf);

        /* 40 for IPv6 header, 8 for UDP header, 12 for good luck. */
        ifp->bufsize = mtu - sizeof(packet_header) - 60;
        ifp->sendbuf = malloc(ifp->bufsize);
        if(ifp->sendbuf == NULL) {
            fprintf(stderr, "Couldn't allocate sendbuf.\n");
            ifp->bufsize = 0;
            goto fail;
        }

        rc = resize_receive_buffer(mtu);
        if(rc < 0)
            fprintf(stderr, "Warning: couldn't resize "
                    "receive buffer for interface %s (%d) (%d bytes).\n",
                    ifp->name, ifp->ifindex, mtu);

        if(IF_CONF(ifp, wired) == CONFIG_NO) {
            wired = 0;
        } else if(IF_CONF(ifp, wired) == CONFIG_YES) {
            wired = 1;
        } else if(all_wireless) {
            wired = 0;
        } else {
            rc = kernel_interface_wireless(ifp->name, ifp->ifindex);
            if(rc < 0) {
                fprintf(stderr,
                        "Warning: couldn't determine whether %s (%d) "
                        "is a wireless interface.\n",
                        ifp->name, ifp->ifindex);
                wired = 0;
            } else {
                wired = !rc;
            }
        }

        if(wired) {
            ifp->flags |= IF_WIRED;
            ifp->cost = IF_CONF(ifp, cost);
            if(ifp->cost <= 0) ifp->cost = 96;
            if(IF_CONF(ifp, split_horizon) == CONFIG_NO)
                ifp->flags &= ~IF_SPLIT_HORIZON;
            else if(IF_CONF(ifp, split_horizon) == CONFIG_YES)
                ifp->flags |= IF_SPLIT_HORIZON;
            else if(split_horizon)
                ifp->flags |= IF_SPLIT_HORIZON;
            else
                ifp->flags &= ~IF_SPLIT_HORIZON;
            if(IF_CONF(ifp, lq) == CONFIG_YES)
                ifp->flags |= IF_LQ;
            else
                ifp->flags &= ~IF_LQ;
        } else {
            ifp->flags &= ~IF_WIRED;
            ifp->cost = IF_CONF(ifp, cost);
            if(ifp->cost <= 0) ifp->cost = 256;
            if(IF_CONF(ifp, split_horizon) == CONFIG_YES)
                ifp->flags |= IF_SPLIT_HORIZON;
            else
                ifp->flags &= ~IF_SPLIT_HORIZON;
            if(IF_CONF(ifp, lq) == CONFIG_NO)
                ifp->flags &= ~IF_LQ;
            else
                ifp->flags |= IF_LQ;
        }

        if(IF_CONF(ifp, faraway) == CONFIG_YES)
            ifp->flags |= IF_FARAWAY;

        if(IF_CONF(ifp, hello_interval) > 0)
            ifp->hello_interval = IF_CONF(ifp, hello_interval);
        else if((ifp->flags & IF_WIRED))
            ifp->hello_interval = default_wired_hello_interval;
        else
            ifp->hello_interval = default_wireless_hello_interval;

        ifp->update_interval =
            IF_CONF(ifp, update_interval) > 0 ?
            IF_CONF(ifp, update_interval) :
            ifp->hello_interval * 4;

        ifp->rtt_decay =
            IF_CONF(ifp, rtt_decay) > 0 ?
            IF_CONF(ifp, rtt_decay) : 42;

        ifp->rtt_min =
            IF_CONF(ifp, rtt_min) > 0 ?
            IF_CONF(ifp, rtt_min) : 10000;
        ifp->rtt_max =
            IF_CONF(ifp, rtt_max) > 0 ?
            IF_CONF(ifp, rtt_max) : 120000;
        if(ifp->rtt_max <= ifp->rtt_min) {
            fprintf(stderr,
                    "Uh, rtt-max is less than or equal to rtt-min (%d <= %d). "
                    "Setting it to %d.\n", ifp->rtt_max, ifp->rtt_min,
                    ifp->rtt_min + 10000);
            ifp->rtt_max = ifp->rtt_min + 10000;
        }
        ifp->max_rtt_penalty = IF_CONF(ifp, max_rtt_penalty);

        if(IF_CONF(ifp, enable_timestamps) == CONFIG_YES ||
           (IF_CONF(ifp, enable_timestamps) == CONFIG_DEFAULT &&
            ifp->max_rtt_penalty > 0))
            ifp->flags |= IF_TIMESTAMPS;

        rc = check_link_local_addresses(ifp);
        if(rc < 0) {
            goto fail;
        }
        memset(&mreq, 0, sizeof(mreq));
        memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
        mreq.ipv6mr_interface = ifp->ifindex;
        rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_JOIN_GROUP,
                        (char*)&mreq, sizeof(mreq));
        if(rc < 0) {
            perror("setsockopt(IPV6_JOIN_GROUP)");
            goto fail;
        }

        check_interface_channel(ifp);
        update_interface_metric(ifp);
        rc = check_interface_ipv4(ifp);

        debugf("Upped interface %s (%s, cost=%d, channel=%d%s).\n",
               ifp->name,
               (ifp->flags & IF_WIRED) ? "wired" : "wireless",
               ifp->cost,
               ifp->channel,
               ifp->ipv4 ? ", IPv4" : "");

        set_timeout(&ifp->hello_timeout, ifp->hello_interval);
        set_timeout(&ifp->update_timeout, ifp->update_interval);
        send_hello(ifp);
        if(rc > 0)
            send_update(ifp, 0, NULL, 0, NULL, 0);
        send_request(ifp, NULL, 0, NULL, 0);
    } else {
        flush_interface_routes(ifp, 0);
        ifp->buffered = 0;
        ifp->bufsize = 0;
        free(ifp->sendbuf);
        ifp->num_buffered_updates = 0;
        ifp->update_bufsize = 0;
        if(ifp->buffered_updates)
            free(ifp->buffered_updates);
        ifp->buffered_updates = NULL;
        ifp->sendbuf = NULL;
        if(ifp->ifindex > 0) {
            memset(&mreq, 0, sizeof(mreq));
            memcpy(&mreq.ipv6mr_multiaddr, protocol_group, 16);
            mreq.ipv6mr_interface = ifp->ifindex;
            rc = setsockopt(protocol_socket, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
                            (char*)&mreq, sizeof(mreq));
            if(rc < 0)
                perror("setsockopt(IPV6_LEAVE_GROUP)");
            kernel_setup_interface(0, ifp->name, ifp->ifindex);
        }
        if(ifp->ll)
            free(ifp->ll);
        ifp->ll = NULL;
        ifp->numll = 0;
    }

    local_notify_interface(ifp, LOCAL_CHANGE);

    return 1;

 fail:
    assert(up);
    interface_up(ifp, 0);
    local_notify_interface(ifp, LOCAL_CHANGE);
    return -1;
}
Ejemplo n.º 16
0
/**
 * It's assumed the server buffers will be reset upon close(), so we must make
 * sure to _not_ release the ringbuffer if that happens.
 */
static void
handle_read(lcbio_CTX *ioctx, unsigned nb)
{
    mc_pSESSREQ sreq = lcbio_ctx_data(ioctx);
    packet_info info;
    unsigned required;
    uint16_t status;
    sreq_STATE state = SREQ_S_WAIT;
    int rc;

    GT_NEXT_PACKET:

    memset(&info, 0, sizeof(info));
    rc = lcb_pktinfo_ectx_get(&info, ioctx, &required);
    if (rc == 0) {
        LCBIO_CTX_RSCHEDULE(ioctx, required);
        return;
    } else if (rc < 0) {
        state = SREQ_S_ERROR;
    }

    status = PACKET_STATUS(&info);

    switch (PACKET_OPCODE(&info)) {
    case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: {
        lcb_string str;
        int saslrc;
        const char *mechlist_data;
        unsigned int nmechlist_data;
        if (lcb_string_init(&str)) {
            set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL);
            state = SREQ_S_ERROR;
            break;
        }

        if (lcb_string_append(&str, info.payload, PACKET_NBODY(&info))) {
            lcb_string_release(&str);
            set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL);
            state = SREQ_S_ERROR;
            break;
        }

        saslrc = set_chosen_mech(sreq, &str, &mechlist_data, &nmechlist_data);
        if (saslrc == 0) {
            if (0 == send_sasl_auth(sreq, mechlist_data, nmechlist_data)) {
                state = SREQ_S_WAIT;
            } else {
                state = SREQ_S_ERROR;
            }

        } else if (saslrc < 0) {
            state = SREQ_S_ERROR;

        } else {
            state = SREQ_S_HELLODONE;
        }
        lcb_string_release(&str);
        break;
    }

    case PROTOCOL_BINARY_CMD_SASL_AUTH: {
        if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
            send_hello(sreq);
            state = SREQ_S_AUTHDONE;
            break;
        }

        if (status != PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) {
            set_error_ex(sreq, LCB_AUTH_ERROR, "SASL AUTH failed");
            state = SREQ_S_ERROR;
            break;
        }
        if (send_sasl_step(sreq, &info) == 0 && send_hello(sreq) == 0) {
            state = SREQ_S_WAIT;
        } else {
            state = SREQ_S_ERROR;
        }
        break;
    }

    case PROTOCOL_BINARY_CMD_SASL_STEP: {
        if (status != PROTOCOL_BINARY_RESPONSE_SUCCESS) {
            lcb_log(LOGARGS(sreq, WARN), SESSREQ_LOGFMT "SASL auth failed with STATUS=0x%x", SESSREQ_LOGID(sreq), status);
            set_error_ex(sreq, LCB_AUTH_ERROR, "SASL Step Failed");
            state = SREQ_S_ERROR;
        } else {
            /* Wait for pipelined HELLO response */
            state = SREQ_S_AUTHDONE;
        }
        break;
    }

    case PROTOCOL_BINARY_CMD_HELLO: {
        state = SREQ_S_HELLODONE;
        if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) {
            parse_hello(sreq, &info);
        } else if (status == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND ||
                status == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED) {
            lcb_log(LOGARGS(sreq, DEBUG), SESSREQ_LOGFMT "Server does not support HELLO", SESSREQ_LOGID(sreq));
            /* nothing */
        } else {
            set_error_ex(sreq, LCB_PROTOCOL_ERROR, "Hello response unexpected");
            state = SREQ_S_ERROR;
        }
        break;
    }

    default: {
        state = SREQ_S_ERROR;
        lcb_log(LOGARGS(sreq, ERROR), SESSREQ_LOGFMT "Received unknown response. OP=0x%x. RC=0x%x", SESSREQ_LOGID(sreq), PACKET_OPCODE(&info), PACKET_STATUS(&info));
        set_error_ex(sreq, LCB_NOT_SUPPORTED, "Received unknown response");
        break;
    }
    }

    lcb_pktinfo_ectx_done(&info, ioctx);
    if (sreq->err != LCB_SUCCESS) {
        bail_pending(sreq);
    } else if (state == SREQ_S_ERROR) {
        set_error_ex(sreq, LCB_ERROR, "FIXME: Error code set without description");
    } else if (state == SREQ_S_HELLODONE) {
        negotiation_success(sreq);
    } else {
        goto GT_NEXT_PACKET;
    }

    (void)nb;
}
Ejemplo n.º 17
0
void process_hello(void *packet, u_int32_t from, u_int32_t to, unsigned int size, struct ospf_interface *oiface) {
	struct ospfhdr *ospfheader;
	struct ospf_hello *hello;
	struct ospf_neighbor *nbr;
	struct in_addr ospf_mcast, *neighbors;
	int nbr_count=0, i=0;
	nbr = NULL;
	ospfheader = (struct ospfhdr *)packet;
	hello = (struct ospf_hello *)(packet+OSPFHDR_LEN);

	inet_pton(AF_INET,OSPF_MULTICAST_ALLROUTERS,&ospf_mcast);
	if((to == ospf_mcast.s_addr) || (to == oiface->iface->ip.s_addr)) {
		add_neighbor(from,ospfheader->src_router,oiface,hello);
		nbr_count = ((size-sizeof(struct ospfhdr)) - (sizeof(struct ospf_hello) - sizeof(struct in_addr)))/(sizeof(struct in_addr));
		if(nbr_count>0) {
			neighbors = (struct in_addr *)(packet + (size - (sizeof(struct in_addr)*nbr_count)));
			for(i=0;i<nbr_count;i++) {
				if(neighbors[i].s_addr == ospf0->router_id.s_addr) {
					nbr = find_neighbor_by_ip(from);

					//if(nbr) send_dbdesc(nbr);
				}
			}
		}
		send_hello(oiface,NULL);
		if(nbr) {
			//check if adjacency should form
			/* - p2p
			* - this is DR
			* - this is BDR
			* - other is DR
			* - other is BDR
			*
			*/
			// set the nbr state to 2way since hello has been seen
			if(nbr->state<=OSPF_NBRSTATE_2WAY) {
				nbr->state = OSPF_NBRSTATE_2WAY;

				//dr-bdr negotiation: handles most scenarios but not RFC compliant
				//if the dr is empty
				if(oiface->dr.s_addr == 0) {
					// figure out who is dr
					// if the nbr doesn't know...
					if(nbr->dr.s_addr==0) {
						//set it to whoever has larger priority or if equal then to greater router id
						if(oiface->priority>nbr->priority) {
							oiface->dr.s_addr = ospf0->router_id.s_addr;
						} else if (nbr->priority>oiface->priority) {
							oiface->dr.s_addr = nbr->router_id.s_addr;
						} else {
							if(ntohl(ospf0->router_id.s_addr)<ntohl(nbr->router_id.s_addr)) {
								oiface->dr.s_addr = nbr->router_id.s_addr;
							} else {
								oiface->dr.s_addr = ospf0->router_id.s_addr;
							}
						}
					//if nbr has a dr of itself then use it
					} else if (nbr->dr.s_addr == nbr->router_id.s_addr){
						oiface->dr.s_addr = nbr->router_id.s_addr;
					//if nbr has a dr of this rtr then go ahead and use ourself as dr
					} else if (nbr->dr.s_addr == ospf0->router_id.s_addr){
						oiface->dr.s_addr = ospf0->router_id.s_addr;
					} else {
						//wait for dr to talk
					}
					send_hello(oiface,NULL);
				// if the bdr is empty
				} else if (oiface->bdr.s_addr == 0){
					//figure out who is bdr
					//if the nbr thinks it is the bdr believe it
					if (nbr->bdr.s_addr == nbr->router_id.s_addr) {
						oiface->bdr.s_addr = nbr->bdr.s_addr;
					}
				}
				if(nbr->dr.s_addr&&(nbr->dr.s_addr!=oiface->dr.s_addr)) {
					oiface->dr.s_addr = nbr->dr.s_addr;
				}

				//if self or nbr is dr or bdr then go to exstart and send dbdesc

				if((oiface->dr.s_addr == oiface->iface->ip.s_addr)||(oiface->bdr.s_addr==oiface->iface->ip.s_addr)||(nbr->dr.s_addr==nbr->ip.s_addr)||(nbr->bdr.s_addr==nbr->ip.s_addr)) {
					//if so, go to exstart
					nbr->state = OSPF_NBRSTATE_EXSTART;
					nbr->lsa_send_list = copy_lsalist();
					nbr->lsa_send_count = ospf0->lsdb->count;
					send_dbdesc(nbr,0);
				}

			}

		}

	} else {
		// how did this packet get here
	}
}