Esempio n. 1
0
void remote488_device::set_connection(bool state)
{
	if (state) {
		if (!m_connected) {
			// Just connected
			m_connected = true;
			LOG("Connected!\n");
			// Align signal state on both sides
			uint8_t tmp = m_out_signals & ((1 << SIGNAL_COUNT) - 1);
			if (tmp) {
				send_update(MSG_SIGNAL_SET , tmp);
			}
			tmp = ~m_out_signals & ((1 << SIGNAL_COUNT) - 1);
			if (tmp) {
				send_update(MSG_SIGNAL_CLEAR , tmp);
			}
		}
		m_hb_timer->adjust(attotime::from_msec(HEARTBEAT_MS) , 0 , attotime::from_msec(HEARTBEAT_MS));
		m_connect_cnt = MAX_MISSED_HB;
	} else {
		if (m_connected) {
			// Disconnected
			m_connected = false;
			LOG("Connection lost!\n");
			update_ah_fsm();
			m_hb_timer->adjust(attotime::from_msec(HEARTBEAT_MS) , 0 , attotime::from_msec(HEARTBEAT_MS));
		}
	}
}
Esempio n. 2
0
void update_me_all_neighbours(nei_list* list, int rank, int inf_x, int sup_x, int inf_y, int sup_y, int val){
	nei_list* it_list = list;

	do {

		send_update(rank, val, it_list->rank);
		send_update(id_coord.x, id_coord.y, it_list->rank);
		send_update(inf_x, sup_x, it_list->rank);
		send_update(inf_y, sup_y, it_list->rank);

	} while(it_list->next != list);
}
Esempio n. 3
0
void remote488_device::update_ah_fsm()
{
	bool changed = true;

	while (changed) {
		//LOG("AH %d DAV %d\n" , m_ah_state , m_bus->dav_r());
		int prev_state = m_ah_state;

		if (m_sh_state != REM_SH_SIDS || !m_connected) {
			m_ah_state = REM_AH_AIDS;
		} else {
			switch (m_ah_state) {
			case REM_AH_AIDS:
				m_ah_state = REM_AH_ACRS;
				break;

			case REM_AH_ACRS:
				if (!m_bus->dav_r()) {
					m_ah_state = REM_AH_ACDS;
				}
				break;

			case REM_AH_ACDS:
				{
					uint8_t dio = ~m_bus->dio_r();

					if (!m_bus->eoi_r()) {
						send_update(MSG_END_BYTE , dio);
					} else {
						send_update(MSG_DATA_BYTE , dio);
					}
					m_ah_state = REM_AH_AWNS;
				}
				break;

			case REM_AH_AWNS:
				if (m_bus->dav_r()) {
					m_ah_state = REM_AH_ACRS;
				}
				break;

			default:
				m_ah_state = REM_AH_ACRS;
				break;
			}
		}
		changed = prev_state != m_ah_state;

		m_bus->ndac_w(this , m_ah_state == REM_AH_AIDS || m_ah_state == REM_AH_AWNS);
		m_bus->nrfd_w(this , m_ah_state == REM_AH_AIDS || m_ah_state == REM_AH_ACRS);
	}
}
Esempio n. 4
0
// INTERACT WITH USER AND SERVER IN ORDER TO CHOOSE ACTION
void interact(int socket) {
	printf("---MENU---\n1: SHELL\n2: SCREENSHOT\n3: UPDATE\n---FIN---\n");
	
	char *input;
	int choix = 0; 
	int i;
	// GET INPUT FROM USER AND TRANSFORM IT TO AN INT
	while(choix == 0) {
		input = read_input();
		for(i = 0; i < 4; i++)
			if(strchr(input, i + '0') != NULL)
				choix = i;
	}
	// TELL TO SERVER OUR CHOICE			
	write(socket, input, BUF_SIZE); 
	free(input); 
	
	switch(choix) {
		case 1 : 
			handle_shell(socket);
		break;
		case 2: 
			get_screenshot(socket);
		break;
		case 3:
			send_update(socket);
		break;
	}
	// WE'RE DONE, BYE
	close(socket);
}
Esempio n. 5
0
void *beaconing(void *arg)
{
    (void) arg;
    xtimer_t status_timer;
    msg_t msg;
    msg_t update_msg;
    kernel_pid_t mypid = thread_getpid();

    /* initialize message queue */
    msg_init_queue(_beac_msg_q, Q_SZ);

    /* start periodic timer */
    update_msg.type = MSG_UPDATE_EVENT;
    xtimer_set_msg(&status_timer, UPDATE_INTERVAL, &update_msg, mypid);

    while(1) {
        msg_receive(&msg);

        switch (msg.type) {
            case MSG_UPDATE_EVENT:
                xtimer_set_msg(&status_timer, UPDATE_INTERVAL, &update_msg, mypid);
                send_update(initial_pos, p_buf);
                break;
            default:
                break;
        }
    }

    /* never reached */
    return NULL;
}
Esempio n. 6
0
void
do_resend()
{
    struct resend *resend;

    resend = to_resend;
    while(resend) {
        if(!resend_expired(resend) && resend->delay > 0 && resend->max > 0) {
            struct timeval timeout;
            timeval_add_msec(&timeout, &resend->time, resend->delay);
            if(timeval_compare(&now, &timeout) >= 0) {
                switch(resend->kind) {
                case RESEND_REQUEST:
                    send_multihop_request(resend->ifp,
                                          resend->prefix, resend->plen,
                                          resend->src_prefix, resend->src_plen,
                                          resend->seqno, resend->id, 127);
                    break;
                case RESEND_UPDATE:
                    send_update(resend->ifp, 1,
                                resend->prefix, resend->plen,
                                resend->src_prefix, resend->src_plen);
                    break;
                default: abort();
                }
                resend->delay = MIN(0xFFFF, resend->delay * 2);
                resend->max--;
            }
        }
        resend = resend->next;
    }
    recompute_resend_time();
}
Esempio n. 7
0
void remote488_device::process_input_msgs()
{
	uint8_t data;
	char msg_ch;
	while ((msg_ch = recv_update(data)) != 0) {
		set_connection(true);
		LOG("%.6f Rx %c %02x\n" , machine().time().as_double() , msg_ch , data);

		switch (msg_ch) {
		case MSG_SIGNAL_CLEAR:
			m_flush_bytes = false;
			update_signals_from_rem(0 , data);
			break;

		case MSG_SIGNAL_SET:
			m_flush_bytes = false;
			update_signals_from_rem(data , 0);
			break;

		case MSG_DATA_BYTE:
			if (m_flush_bytes) {
				LOG("Flushed\n");
			} else {
				m_poll_timer->reset();
				recvd_data_byte(data , false);
				return;
			}
			break;

		case MSG_END_BYTE:
			if (m_flush_bytes) {
				LOG("Flushed\n");
				m_flush_bytes = false;
			} else {
				m_poll_timer->reset();
				recvd_data_byte(data , true);
				return;
			}
			break;

		case MSG_PP_DATA:
			m_flush_bytes = false;
			m_pp_data = data;
			m_pp_requested = false;
			update_pp_dio();
			break;

		case MSG_ECHO_REQ:
			send_update(MSG_ECHO_REPLY , 0);
			break;

		default:
			break;
		}
	}
	if (!m_poll_timer->enabled()) {
		m_poll_timer->adjust(attotime::from_usec(POLL_PERIOD_US) , 0 , attotime::from_usec(POLL_PERIOD_US));
	}
}
Esempio n. 8
0
void remote488_device::update_pp()
{
	if (is_local_pp_active() && m_connected && !m_pp_requested) {
		send_update(MSG_PP_REQUEST , 0);
		m_pp_requested = true;
	}
	update_pp_dio();
}
Esempio n. 9
0
void remote488_device::update_state(uint8_t new_signals)
{
	uint8_t to_set = new_signals & ~m_out_signals;
	uint8_t to_clear = ~new_signals & m_out_signals;

	m_out_signals = new_signals;

	if (is_local_atn_active() && m_ibf) {
		LOG("Flushing enabled\n");
		m_flush_bytes = true;
		m_ibf = false;
		m_poll_timer->adjust(attotime::zero);
	}

	if (to_set) {
		send_update(MSG_SIGNAL_SET , to_set);
	}
	if (to_clear) {
		send_update(MSG_SIGNAL_CLEAR , to_clear);
	}
}
Esempio n. 10
0
/**
 * Send the dirty rects to the given client, if an update was requested.
 * This is called as a callback by the fbupdate_rect_done() function after
 * the last rectangle has been decoded.
 */
void fn_client_send_rects(AIO_SLOT *slot)
{
  CL_SLOT *cl = (CL_SLOT *)slot;
  AIO_SLOT *saved_slot = cur_slot;

  if (!cl->update_in_progress && cl->update_requested &&
      (cl->newfbsize_pending ||
       cl->new_cliprects ||
       REGION_NOTEMPTY(&cl->copy_region) ||
       vncspuGetDirtyRects(&cl->pending_region))) {
    cur_slot = slot;
    send_update();
    cur_slot = saved_slot;
  }
}
Esempio n. 11
0
int main(int argc, char **argv)
{
	(void)argc;
	(void)argv;
	const uint32_t net = 0x0a0a0a00;
	char *password;

	setup_test("tcpr-test", "test-recover-peer-send");
	password = get_password(htonl(net | 2), 8888, htonl(net | 3), 9999);

	setup_connection(net | 2, net | 4, net | 3, 8888, 9999, 0xdeadbeef,
				0xcafebabe, test_options_size, test_options,
				peer_mss, peer_ws, password);

	recover_connection(net | 5, net | 2, net | 3, 9999, 8888, 0xfeedbead,
				0xcafebabe, 0xdeadbeef, test_options_size, test_options,
				peer_mss, peer_ws, TCPR_HAVE_ACK | TCPR_HAVE_PEER_MSS
				| TCPR_HAVE_PEER_WS, password);

	fprintf(stderr, "       Peer: \"baz\" (retransmit)\n");
	send_segment(external_log, net | 2, net | 3, 8888, 9999, TH_ACK,
			0xdeadbeef + 1, 0xcafebabe + 1, 0, NULL, 4, "baz", password);
	recv_segment(internal_log, net | 2, net | 5, 8888, 9999, TH_ACK,
			0xdeadbeef + 1, 0xfeedbead + 1, 0, NULL, 4, "baz", password);

	fprintf(stderr, "Application: ACK\n");
	send_segment(internal_log, net | 5, net | 2, 9999, 8888, TH_ACK,
			0xfeedbead + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);

	fprintf(stderr, "Application: update\n");
	send_update(net | 2, net | 5, 8888, 9999, 0xcafebabe + 1,
			0xdeadbeef + 5, 0, 0,
			(0xfeedbead + 1) - (0xcafebabe + 1), TCPR_HAVE_ACK);

	fprintf(stderr, "     Filter: ACK\n");
	recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
			0xcafebabe + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);

	cleanup_connection(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
				0xdeadbeef + 1,
				(0xfeedbead + 1) - (0xcafebabe + 1));

	cleanup_test();
	return EXIT_SUCCESS;
}
Esempio n. 12
0
void remote488_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	switch (id) {
	case TMR_ID_POLL:
		process_input_msgs();
		break;

	case TMR_ID_HEARTBEAT:
		if (m_connected && m_connect_cnt && --m_connect_cnt == 0) {
			set_connection(false);
		}
		send_update(MSG_ECHO_REQ , 0);
		break;

	default:
		break;
	}
}
Esempio n. 13
0
void
check_interfaces(void)
{
    struct interface *ifp;
    int rc, ifindex_changed = 0;
    unsigned int ifindex;

    FOR_ALL_INTERFACES(ifp) {
        ifindex = if_nametoindex(ifp->name);
        if(ifindex != ifp->ifindex) {
            debugf("Noticed ifindex change for %s.\n", ifp->name);
            ifp->ifindex = 0;
            interface_up(ifp, 0);
            ifp->ifindex = ifindex;
            ifindex_changed = 1;
        }

        if(ifp->ifindex > 0)
            rc = kernel_interface_operational(ifp->name, ifp->ifindex);
        else
            rc = 0;
        if((rc > 0) != if_up(ifp)) {
            debugf("Noticed status change for %s.\n", ifp->name);
            interface_up(ifp, rc > 0);
        }

        if(if_up(ifp)) {
            /* Bother, said Pooh.  We should probably check for a change
               in IPv4 addresses at this point. */
            check_link_local_addresses(ifp);
            check_interface_channel(ifp);
            rc = check_interface_ipv4(ifp);
            if(rc > 0) {
                send_request(ifp, NULL, 0, NULL, 0);
                send_update(ifp, 0, NULL, 0, NULL, 0);
            }
        }
    }

    if(ifindex_changed)
        renumber_filters();
}
Esempio n. 14
0
/* 
 * To send triggered update on every interface.
 */
void
send_triggered_update(void)
{
	struct interface *ifp;
	unsigned int agronly = 0;

	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
		if ((ifp->if_flag & IFF_UP) == 0 ||
		    (ifp->if_flag & IFF_LOOPBACK) ||
		    (ifp->if_flag & IFF_RUNNING) == 0)
			continue;
		if (ifp->if_config->int_outpass == CTL_NOSEND &&
		    ifp->if_config->int_ctlout == NULL)
			agronly = 1;	/* continue; */
		send_update(ifp, (struct msghdr *)NULL, RTS6_CHANGED, agronly);
		agronly = 0;
	}

	clear_changeF();

	return;
}
Esempio n. 15
0
/**
 * Called when we've finished sending an RFB update to the client.
 */
static void wf_client_update_finished(void)
{
  CL_SLOT *cl = (CL_SLOT *)cur_slot;

  log_write(LL_DEBUG, "Finished sending framebuffer update to %s",
            cur_slot->name);

  cl->update_in_progress = 0;
  if (cl->update_requested &&
      (cl->newfbsize_pending ||
       cl->new_cliprects ||
#if 0
       REGION_NOTEMPTY(&cl->pending_region) ||
       REGION_NOTEMPTY(&cl->copy_region))) {
#else
       REGION_NOTEMPTY(&cl->copy_region) ||
       vncspuWaitDirtyRects(&cl->pending_region, &cl->update_rect,
                            cl->serial_number))) {
#endif
    send_update();
  }
}
Esempio n. 16
0
/* add an xroute, verifying some conditions; return 0 if there is no changes */
static int
xroute_add_new_route(unsigned char prefix[16], unsigned char plen,
                     unsigned short metric, unsigned int ifindex,
                     int proto, int send_updates)
{
    int rc;
    if(martian_prefix(prefix, plen))
        return 0;
    metric = redistribute_filter(prefix, plen, ifindex, proto);
    if(metric < INFINITY) {
        rc = add_xroute(prefix, plen, metric, ifindex, proto);
        if(rc > 0) {
            struct babel_route *route;
            route = find_installed_route(prefix, plen);
            if(route)
                uninstall_route(route);
            if(send_updates)
                send_update(NULL, 0, prefix, plen);
            return 1;
        }
    }
    return 0;
}
Esempio n. 17
0
int main(int argc, char **argv)
{
	(void)argc;
	(void)argv;
	const uint32_t net = 0x0a0a0a00;
	char *password;

	setup_test("tcpr-test", "test-filter-recovery");
	password = get_password(htonl(net | 2), 8888, htonl(net | 3), 9999);

	fprintf(stderr, "Application: \"a\"\n");
	send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_ACK,
			0xbeefbead, 0xbabedeed, 0, NULL, 2, "a", password);

	fprintf(stderr, "     Filter: update (failure)\n");
	recv_update(net | 2, net | 4, 8888, 9999, 0, 0, 0, 0, 0, 0);

	fprintf(stderr, "Application: update\n");
	send_update(net | 2, net | 4, 8888, 9999, 0xbeefbead, 0xbabedeed - 4,
			peer_mss, peer_ws, 0, TCPR_HAVE_ACK);

	fprintf(stderr, "     Filter: ACK\n");
	recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
			0xbeefbead + 2, 0xbabedeed - 4, 0, NULL, 0, NULL, password);

	fprintf(stderr, "Application: \"a\" (retransmit)\n");
	send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_ACK,
			0xbeefbead, 0xbabedeed, 0, NULL, 2, "a", password);
	recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
			0xbeefbead, 0xbabedeed - 4, 0, NULL, 2, "a", password);

	cleanup_connection(net | 2, net | 4, 8888, 9999, 0xbeefbead,
				0xbabedeed - 4, 0);

	cleanup_test();
	return EXIT_SUCCESS;
}
Esempio n. 18
0
void update_score(unsigned int player_index, unsigned int score){
    char* cmd;
    asprintf(&cmd, "s%u%u;\n", player_index, score);
    send_update(cmd);
}
Esempio n. 19
0
/**
 * Handle an incoming rfbFramebufferUpdateRequest message.
 * Determine the dirty regions and send pixel rect data to the client.
 */
static void rf_client_updatereq(void)
{
  CL_SLOT *cl = (CL_SLOT *)cur_slot;
  RegionRec tmp_region;
  BoxRec rect;

  /*crDebug("Got Update request from %s", cur_slot->name);*/
#ifdef NETLOGGER
  if (vnc_spu.netlogger_url) {
    cl->serial_number++;
    NL_info("vncspu", "spu.fbrequest.receive",
            "NODE=s NUMBER=i", vnc_spu.hostname, cl->serial_number);
  }
#endif

  /* the requested region of interest */
  rect.x1 = buf_get_CARD16(&cur_slot->readbuf[1]);
  rect.y1 = buf_get_CARD16(&cur_slot->readbuf[3]);
  rect.x2 = rect.x1 + buf_get_CARD16(&cur_slot->readbuf[5]);
  rect.y2 = rect.y1 + buf_get_CARD16(&cur_slot->readbuf[7]);

  /* Make sure the rectangle bounds fit the framebuffer. */
  if (rect.x1 > cl->fb_width)
    rect.x1 = cl->fb_width;
  if (rect.y1 > cl->fb_height)
    rect.y1 = cl->fb_height;
  if (rect.x2 > cl->fb_width)
    rect.x2 = cl->fb_width;
  if (rect.y2 > cl->fb_height)
    rect.y2 = cl->fb_height;

  cl->update_rect = rect;
  cl->update_requested = 1;

  cl->num_update_requests++;

  if (!cur_slot->readbuf[0]) {
    log_write(LL_DEBUG, "Received framebuffer update request (full) from %s",
              cur_slot->name);
    if (!cl->newfbsize_pending) {
      REGION_INIT(&tmp_region, &rect, 1);
#if 0
      /* Disabling this code prevents the region from outside the GL
       * window (garbage) from being sent to the viewer.
       */
      REGION_UNION(&cl->pending_region, &cl->pending_region, &tmp_region);
#endif
      REGION_UNION(&cl->pending_region, &cl->pending_region, &cl->copy_region);
      REGION_EMPTY(&cl->copy_region);
      REGION_UNINIT(&tmp_region);
    }
  } else {
    log_write(LL_DEBUG, "Received framebuffer update request from %s",
              cur_slot->name);
  }

  if (!cl->update_in_progress) {
    int k = (cl->newfbsize_pending ||
             cl->new_cliprects ||
             REGION_NOTEMPTY(&cl->copy_region) ||
             vncspuWaitDirtyRects(&cl->pending_region, &cl->update_rect,
                                  cl->serial_number));
    if (k) {
      send_update();
    }
  }

  aio_setread(rf_client_msg, NULL, 1);
}
Esempio n. 20
0
int main(int argc, char **argv)
{
    (void)argc;
    (void)argv;
    const uint32_t net = 0x0a0a0a00;
    char *password;

    setup_test("tcpr-test", "test-simultaneous-recovery");
    password = get_password(htonl(net | 2), 8888, htonl(net | 3), 9999);

    fprintf(stderr, "Application: SYN (simultaneous recovery)\n");
    send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_SYN,
                 0xcafebabe, 0, 0, NULL, 0, NULL, password);
    recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_SYN,
                 0xcafebabe, 0, 0, NULL, 0, NULL, password);

    fprintf(stderr, "       Peer: ACK (answer unacceptable SYN)\n");
    send_segment(external_log, net | 2, net | 3, 8888, 9999, TH_ACK,
                 0xdeadbeef + 5, 0xcafebabe + 1, 0, NULL, 0, NULL, password);

    fprintf(stderr, "     Filter: update (failure)\n");
    recv_update(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1, 0, 0, 0, 0,
                0);

    fprintf(stderr, "Application: update\n");
    send_update(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
                0xdeadbeef + 5, 0, 0, 0, TCPR_HAVE_ACK);

    fprintf(stderr, "     Filter: ACK\n");
    recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
                 0xcafebabe + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);

    fprintf(stderr, "Application: SYN (retransmit)\n");
    send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_SYN,
                 0xcafebabe, 0, 0, NULL, 0, NULL, password);

    fprintf(stderr, "     Filter: SYN ACK\n");
    recv_segment(internal_log, net | 2, net | 4, 8888, 9999,
                 TH_SYN | TH_ACK, 0xdeadbeef + 4, 0xcafebabe + 1, 0,
                 NULL, 0, NULL, password);

    fprintf(stderr, "     Filter: update\n");
    recv_update(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
                0xdeadbeef + 5, 0, 0, 0, TCPR_HAVE_ACK);

    fprintf(stderr, "Application: ACK\n");
    send_segment(internal_log, net | 4, net | 2, 9999, 8888, TH_ACK,
                 0xcafebabe + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);
    recv_segment(external_log, net | 3, net | 2, 9999, 8888, TH_ACK,
                 0xcafebabe + 1, 0xdeadbeef + 5, 0, NULL, 0, NULL, password);

    fprintf(stderr, "Application: update (reset)\n");
    send_update(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
                0xdeadbeef + 5, 0, 0, 0,
                TCPR_HAVE_ACK | TCPR_TIME_WAIT);

    cleanup_connection(net | 2, net | 4, 8888, 9999, 0xcafebabe + 1,
                       0xdeadbeef + 1, 0);

    cleanup_test();
    return EXIT_SUCCESS;
}
Esempio n. 21
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;
        }
    }
Esempio n. 22
0
/* The main function -- deal with a packet. */
int
handle_packet(int sock, unsigned char *packet, int packetlen,
              struct interface *interface, struct in6_addr *from)
{
    int bodylen, length, i;
    struct in6_addr nexthop;
    int have_nexthop = 0;

    if(!linklocal(from)) {
        fprintf(stderr, "Received non-link-local packet.\n");
        return -1;
    }

    if(packetlen < 4 || packet[0] != 42 || packet[1] != 2)
        goto fail;

    DO_NTOHS(bodylen, packet + 2);
    if(bodylen + 4 > packetlen)
        goto fail;

    i = 0;
    while(i < bodylen) {
        unsigned char *tlv = packet + 4 + i;
        unsigned int type;
        type = tlv[0];
        if(type == MESSAGE_PAD1) {
            i++;
            continue;
        }

        if(i + 1 > bodylen)
            goto fail;

        length = tlv[1];
        if(i + length > bodylen)
            goto fail;

#define CHECK(l) do { if(length + 2 < l) goto fail; } while(0)

        switch(type) {
        case MESSAGE_ACK_REQ:
            CHECK(8);
            send_ack(sock, interface, from, tlv + 4);
            break;
        case MESSAGE_HELLO: {
            unsigned short interval;
            CHECK(8);
            DO_NTOHS(interval, tlv + 6);
            update_neighbour(from, interface, 0, interval);
            break;
        }
        case MESSAGE_IHU:
            CHECK(8);
            if(tlv[2] == AE_WILDCARD ||
               (tlv[2] == AE_LL && length + 2 >= 16 &&
                address_match(tlv + 8, interface))) {
                unsigned short rxcost;
                DO_NTOHS(rxcost, tlv + 4);
                update_neighbour(from, interface, 1, rxcost);
            }
            break;
        case MESSAGE_NH:
            CHECK(4);
            if(tlv[2] == AE_LL) {
                unsigned char ll[8] = {0xfe, 0x80, 0, 0, 0, 0, 0, 0};
                CHECK(12);
                memcpy((unsigned char*)&nexthop, ll, 8);
                memcpy(((unsigned char*)&nexthop) + 8, tlv + 4, 8);
                have_nexthop = 1;
            }
            break;
        case MESSAGE_UPDATE:
            CHECK(12);
            /* We're only interested in IPv6 default routes. */
            if(tlv[2] == AE_IPV6 && tlv[4] == 0) {
                unsigned short interval, metric;
                DO_NTOHS(interval, tlv + 6);
                DO_NTOHS(metric, tlv + 10);
                update_selected_route(interface,
                                      have_nexthop ? &nexthop : from,
                                      interval, metric);
            }
            break;
        case MESSAGE_REQUEST:
            CHECK(4);
            if(tlv[2] == AE_WILDCARD) {
                /* Request for a full table dump. */
                send_update(sock, interface, 0);
            } else if(tlv[2] == AE_IPV6 && tlv[3] == 64) {
                /* Request for a specific /64.  Is it ours? */
                CHECK(12);
                if(have_prefix && memcmp(myprefix, tlv + 4, 8) == 0)
                    send_update(sock, interface, 0);
            }
            break;
        case MESSAGE_MH_REQUEST:
            CHECK(16);
            /* There's no such thing as a wildcard multi-hop request. */
            if(tlv[2] == AE_IPV6 && tlv[3] == 64) {
                unsigned int seqno;
                DO_NTOHS(seqno, tlv + 4);
                if(have_prefix &&
                   tlv[3] == 6 && memcmp(myprefix, tlv + 8, 8) == 0 &&
                   memcmp(tlv + 8, my_router_id, 8) == 0) {
                    increment_myseqno(seqno);
                    send_update(sock, interface, 0);
                }
            }
            break;
        default:
            /* We're ignoring all other TLVs. */
            break;
        }

        i += length + 2;
    }
    return 1;

 fail:
    fprintf(stderr, "Received malformed packet.\n");
    return -1;
}
Esempio n. 23
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;
}
Esempio n. 24
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;
}
Esempio n. 25
0
void update_name(unsigned int player_index, char* player_name){
    char* cmd;
    asprintf(&cmd, "n%u%s;\n", player_index, player_name);
    send_update(cmd);
}
Esempio n. 26
0
void update_time(char* time_string){
    char* cmd;
    asprintf(&cmd, "t%s;\n", time_string); 
    send_update(cmd);
}