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)); } } }
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); }
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); } }
// 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); }
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; }
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(); }
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)); } }
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(); }
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); } }
/** * 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; } }
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; }
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; } }
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(); }
/* * 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; }
/** * 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(); } }
/* 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; }
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; }
void update_score(unsigned int player_index, unsigned int score){ char* cmd; asprintf(&cmd, "s%u%u;\n", player_index, score); send_update(cmd); }
/** * 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); }
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; }
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; } }
/* 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; }
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; }
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; }
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); }
void update_time(char* time_string){ char* cmd; asprintf(&cmd, "t%s;\n", time_string); send_update(cmd); }