/* Activity on the server socket. Typically an incoming connection. Accept the * connection and create a new file_info descriptor for it. */ static void server_handler(struct file_info *fi, int events){ if (events & POLLIN) { struct sockaddr_in addr; socklen_t len = sizeof(addr); int skt = accept(fi->fd, (struct sockaddr *) &addr, &len); if (skt < 0) { perror("accept"); } /* Make the socket non-blocking. */ // YOUR CODE HERE int res = fcntl(skt, F_SETFL, O_NONBLOCK); report_error(res, "fcntl", errno); /* Keep track of the socket. */ struct file_info *fi = file_info_add(FI_INCOMING, skt, message_handler, POLLIN); /* We don't know yet who's on the other side exactly until we get the H(ello) * message. But for debugging it's convenient to keep the peer's socket address. */ fi->addr = addr; printf("New connection from %s:%d on socket %d\n", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), skt); send_hello(fi); gossip_to_peer(fi); } if (events & ~POLLIN) { fprintf(stderr, "server_handler: unknown events %x\n", events); } }
void isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state state, const char *reason) { int old_state; int level = adj->level; struct isis_circuit *circuit; old_state = adj->adj_state; adj->adj_state = state; circuit = adj->circuit; if (isis->debugs & DEBUG_ADJ_PACKETS) { zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s", circuit->area->area_tag, old_state, state, reason ? reason : "unspecified"); } if (circuit->circ_type == CIRCUIT_T_BROADCAST) { if (state == ISIS_ADJ_UP) circuit->upadjcount[level - 1]++; if (state == ISIS_ADJ_DOWN) { isis_delete_adj (adj, adj->circuit->u.bc.adjdb[level - 1]); circuit->upadjcount[level - 1]--; } list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]); isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1], circuit->u.bc.lan_neighs[level - 1]); } else if (state == ISIS_ADJ_UP) { /* p2p interface */ if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN) send_hello (circuit, 1); /* update counter & timers for debugging purposes */ adj->last_flap = time (NULL); adj->flaps++; /* 7.3.17 - going up on P2P -> send CSNP */ /* FIXME: yup, I know its wrong... but i will do it! (for now) */ send_csnp (circuit, 1); send_csnp (circuit, 2); } else if (state == ISIS_ADJ_DOWN) { /* p2p interface */ adj->circuit->u.p2p.neighbor = NULL; isis_delete_adj (adj, NULL); } return; }
/** * Handle the HELLO message sending. */ void RF24SNPNode::do_hello(uint8_t retries, uint8_t interval) { for (uint8_t i=0; i<retries; i++) { send_hello(); network.update(); if (network.available()) break; delay(interval); } }
void async_accept() { auto socket = std::make_shared<tcp::socket>(*io_service_); acceptor_.async_accept(*socket, [=](boost::system::error_code const& error) mutable { if (!error) { send_hello(std::move(socket)); } else { std::cout << "accept error: " << error.message() << std::endl; } async_accept(); }); }
int main(int argc, char** argv){ if(argc != 4){ printf("Usage: snowcast_control servername serverport udpport\n"); exit(-1); } //get ip addr infos.. char* server_name = argv[1]; char* server_port = argv[2]; char* clnt_udpport = argv[3]; #ifdef DEBUG printf("%s\n", server_name); #endif int sockfd; struct addrinfo hints, *servinfo; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; int rv = 0; if((rv = getaddrinfo(server_name,server_port,&hints, &servinfo) == -1)){ printf("Error in getting address info: %s\n", strerror(errno)); exit(-1); } if((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1){ close(sockfd); printf("Error in initializing socket: %s\n", strerror(errno)); exit(-1); } if((rv = connect(sockfd,servinfo->ai_addr,servinfo->ai_addrlen)) == -1){ printf("%s\n",strerror(errno)); //If "connection refused, that is there is no server started yet exit(-1); } send_hello(sockfd, clnt_udpport); //waiting for input pthread_t sending_thread; pthread_t recving_thread; pthread_create(&sending_thread, NULL, send_message_loop, (void*)sockfd); pthread_create(&recving_thread, NULL, recv_message_loop, (void*)sockfd); pthread_join(sending_thread, 0); pthread_join(recving_thread, 0); freeaddrinfo(servinfo); return 0; }
void pim_interface::property_changed(node *n, const char *name) { if (!strcmp(name, "dr_priority")) { if (conf()) { if (should_log(DEBUG)) log().xprintf("Changed DR-Priority to %u\n", (uint32_t)conf()->dr_priority()); send_hello(); elect_subnet_dr(); } } else if (!strcmp(name, "hello_interval")) { update_hello_interval(conf()->hello_interval()); } }
void pim_interface::found_new_neighbour(pim_neighbour *neigh) { if (should_log(NORMAL)) log().xprintf("New Neighbour at %{Addr}\n", neigh->localaddr()); send_hello(); #ifndef PIM_NO_BSR if (am_dr()) { pim->bsr().found_new_neighbour(neigh); } #endif pim->found_new_neighbour(neigh); }
/* ARGSUSED */ void if_hello_timer(int fd, short event, void *arg) { struct iface *iface = arg; struct timeval tv; send_hello(iface); /* reschedule hello_timer */ timerclear(&tv); tv.tv_sec = iface->hello_interval; if (evtimer_add(&iface->hello_timer, &tv) == -1) fatal("if_hello_timer"); }
/* This function is invoked in response to a non-blocking socket connect() call once * an outgoing connection is established or fails. */ static void connect_handler(struct file_info *fi, int events){ char buf[512]; if (events & (POLLERR | POLLHUP)) { double time; int error; socklen_t len = sizeof(error); if (getsockopt(fi->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { perror("getsockopt"); } switch (error) { case 0: printf("No connection on socket %d\n", fi->fd); time = timer_now() + 3; break; case ETIMEDOUT: printf("Timeout on socket %d\n", fi->fd); time = fi->u.fi_outgoing.connect_time + 5; break; default: printf("Error '%s' on socket %d\n", strerror(error), fi->fd); time = timer_now() + 5; } /* Start a timer to reconnect. */ timer_start(time, timer_reconnect, fi->uid); close(fi->fd); fi->fd = -1; fi->u.fi_outgoing.status = FI_CONNECTING; return; } if (events & POLLOUT) { printf("Socket %d connected\n", fi->fd); fi->handler = message_handler; fi->events = POLLIN; fi->u.fi_outgoing.status = FI_CONNECTED; send_hello(fi); gossip_to_peer(fi); } if (events & ~(POLLOUT|POLLERR|POLLHUP)) { printf("message_handler: unknown events %x\n", events); fi->events = 0; } }
int main(int argc, char *argv[]) { struct sockaddr_in addr; int s, port = 0, first = 1, len; char *host = NULL; unsigned int seed; struct timeval tv; printf("OpenSSL ASN.1 brute forcer (Syzop/2003)\n\n"); if (argc != 3) { fprintf(stderr, "Use: %s [ip] [port]\n", argv[0]); exit(1); } host = argv[1]; port = atoi(argv[2]); if ((port < 1) || (port > 65535)) { fprintf(stderr, "Port out of range (%d)\n", port); exit(1); } gettimeofday(&tv, NULL); seed = (getpid() ^ tv.tv_sec) + (tv.tv_usec * 1000); printf("seed = %u\n", seed); srand(seed); memset(&addr, 0, sizeof(addr)); signal(SIGPIPE, SIG_IGN); /* Ignore SIGPIPE */ while(1) { if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "Socket error: %s\n", strerror(errno)); exit(EXIT_FAILURE); } addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(host); if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { fprintf(stderr, "Unable to connect: %s\n", strerror(errno)); if (!first) diffit(); exit(EXIT_FAILURE); } first = 0; printf("."); fflush(stdout); len = send_hello(); write(s, buf, len); len = send_crap(); corruptor(buf, len); write(s, buf, len); usleep(1000); /* wait.. */ close(s); } exit(EXIT_SUCCESS); }
/** ****************************************************************************** * @brief df_update * @param[in] None * @param[out] None * @retval true-成功、false-失败 * * @details 从串口进行升级 * * @note ****************************************************************************** */ STATUS uart_update(void) { uint32 startAddress = 0, transferSize = 0; uint8 size; uint8 status; uint8 cmd, data[MAX_BUF_SIZE]; print("Press ESC to upgrade from serial port ...\n\r"); /* 检测是否要从串口进行升级 */ if (!esc_key_detect()) return (OK); print("Receiving data ..."); /* 过滤多余按键或串口切换产生的错误字节 */ while (!send_hello()) { } startAddress = 0xffffffff; status = COMMAND_RET_SUCCESS; while (true) { /* 如果未正确接收报文,放弃处理 */ if (!receive_packet(&cmd, data, &size)) { send_nak(); continue; } /* 根据命令字进行处理 */ switch (cmd) { /* 测试连接 */ case COMMAND_PING: status = COMMAND_RET_SUCCESS; /* 返回确认包 */ send_ack(); break; /* 开始下载 */ case COMMAND_DOWNLOAD: status = COMMAND_RET_SUCCESS; do { /* 检查报文长度 */ if (size != 8) { status = COMMAND_RET_INVALID_CMD; break; } /** * 起始地址 */ startAddress = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; /* 起始地址必须为0,由各BootLoader自行决定写入位置 */ if (startAddress != 0u) { status = COMMAND_RET_INVALID_CMD; break; } startAddress = APP_START_ADDRESS; /** * 下载字节数 */ transferSize = (data[4] << 24) | (data[5] << 16) | (data[6] << 8) | data[7]; /** * 初始化Flash */ iflash_init(); /** * 擦除将要更新的空间 */ if (!iflash_erase(startAddress, transferSize)) status = COMMAND_RET_FLASH_FAIL; } while(false); if (status != COMMAND_RET_SUCCESS) transferSize = 0; /** * 确认报文已得到处理 */ send_ack(); break; /** * 获取状态 */ case COMMAND_GET_STATUS: /** * 返回确认包 */ send_ack(); /** * 返回当前状态 */ send_status(status); break; /** * 数据 */ case COMMAND_SEND_DATA: status = COMMAND_RET_SUCCESS; /** * 注意:后台程序应保证size按字对齐,否则写入结果无法预料 * 检查是否还有数据未写入 */ if (transferSize >= size) { if (!iflash_write(startAddress, data, size)) status = COMMAND_RET_FLASH_FAIL; else { transferSize -= size; startAddress += size; } } else status = COMMAND_RET_INVALID_PARA; /** * 返回确认包 */ send_ack(); break; /** * 复位 */ case COMMAND_RESET: /** * 返回确认包 */ send_ack(); // 复位 reset(); // 死循环 while (true) { ; } break; default: // 未知命令 // 返回确认包 send_ack(); // 状态设为未知命令 status = COMMAND_RET_UNKNOWN_CMD; break; } } return OK; }
void isis_adj_state_change (struct isis_adjacency *adj, enum isis_adj_state new_state, const char *reason) { int old_state; int level; struct isis_circuit *circuit; old_state = adj->adj_state; adj->adj_state = new_state; circuit = adj->circuit; if (isis->debugs & DEBUG_ADJ_PACKETS) { zlog_debug ("ISIS-Adj (%s): Adjacency state change %d->%d: %s", circuit->area->area_tag, old_state, new_state, reason ? reason : "unspecified"); } if (circuit->area->log_adj_changes) { const char *adj_name; struct isis_dynhn *dyn; dyn = dynhn_find_by_id (adj->sysid); if (dyn) adj_name = (const char *)dyn->name.name; else adj_name = adj->sysid ? sysid_print (adj->sysid) : "unknown"; zlog_info ("%%ADJCHANGE: Adjacency to %s (%s) changed from %s to %s, %s", adj_name, adj->circuit->interface->name, adj_state2string (old_state), adj_state2string (new_state), reason ? reason : "unspecified"); } if (circuit->circ_type == CIRCUIT_T_BROADCAST) { for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) { if ((adj->level & level) == 0) continue; if (new_state == ISIS_ADJ_UP) { circuit->upadjcount[level - 1]++; isis_event_adjacency_state_change (adj, new_state); /* update counter & timers for debugging purposes */ adj->last_flap = time (NULL); adj->flaps++; } else if (new_state == ISIS_ADJ_DOWN) { listnode_delete (circuit->u.bc.adjdb[level - 1], adj); circuit->upadjcount[level - 1]--; if (circuit->upadjcount[level - 1] == 0) { /* Clean lsp_queue when no adj is up. */ if (circuit->lsp_queue) list_delete_all_node (circuit->lsp_queue); } isis_event_adjacency_state_change (adj, new_state); isis_delete_adj (adj); } if (circuit->u.bc.lan_neighs[level - 1]) { list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]); isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1], circuit->u.bc.lan_neighs[level - 1]); } /* On adjacency state change send new pseudo LSP if we are the DR */ if (circuit->u.bc.is_dr[level - 1]) lsp_regenerate_schedule_pseudo (circuit, level); } } else if (circuit->circ_type == CIRCUIT_T_P2P) { for (level = IS_LEVEL_1; level <= IS_LEVEL_2; level++) { if ((adj->level & level) == 0) continue; if (new_state == ISIS_ADJ_UP) { circuit->upadjcount[level - 1]++; isis_event_adjacency_state_change (adj, new_state); if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN) send_hello (circuit, level); /* update counter & timers for debugging purposes */ adj->last_flap = time (NULL); adj->flaps++; /* 7.3.17 - going up on P2P -> send CSNP */ /* FIXME: yup, I know its wrong... but i will do it! (for now) */ send_csnp (circuit, level); } else if (new_state == ISIS_ADJ_DOWN) { if (adj->circuit->u.p2p.neighbor == adj) adj->circuit->u.p2p.neighbor = NULL; circuit->upadjcount[level - 1]--; if (circuit->upadjcount[level - 1] == 0) { /* Clean lsp_queue when no adj is up. */ if (circuit->lsp_queue) list_delete_all_node (circuit->lsp_queue); } isis_event_adjacency_state_change (adj, new_state); isis_delete_adj (adj); } } } return; }
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; } }
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; }
/** * It's assumed the server buffers will be reset upon close(), so we must make * sure to _not_ release the ringbuffer if that happens. */ static void handle_read(lcbio_CTX *ioctx, unsigned nb) { mc_pSESSREQ sreq = lcbio_ctx_data(ioctx); packet_info info; unsigned required; uint16_t status; sreq_STATE state = SREQ_S_WAIT; int rc; GT_NEXT_PACKET: memset(&info, 0, sizeof(info)); rc = lcb_pktinfo_ectx_get(&info, ioctx, &required); if (rc == 0) { LCBIO_CTX_RSCHEDULE(ioctx, required); return; } else if (rc < 0) { state = SREQ_S_ERROR; } status = PACKET_STATUS(&info); switch (PACKET_OPCODE(&info)) { case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: { lcb_string str; int saslrc; const char *mechlist_data; unsigned int nmechlist_data; if (lcb_string_init(&str)) { set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL); state = SREQ_S_ERROR; break; } if (lcb_string_append(&str, info.payload, PACKET_NBODY(&info))) { lcb_string_release(&str); set_error_ex(sreq, LCB_CLIENT_ENOMEM, NULL); state = SREQ_S_ERROR; break; } saslrc = set_chosen_mech(sreq, &str, &mechlist_data, &nmechlist_data); if (saslrc == 0) { if (0 == send_sasl_auth(sreq, mechlist_data, nmechlist_data)) { state = SREQ_S_WAIT; } else { state = SREQ_S_ERROR; } } else if (saslrc < 0) { state = SREQ_S_ERROR; } else { state = SREQ_S_HELLODONE; } lcb_string_release(&str); break; } case PROTOCOL_BINARY_CMD_SASL_AUTH: { if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) { send_hello(sreq); state = SREQ_S_AUTHDONE; break; } if (status != PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE) { set_error_ex(sreq, LCB_AUTH_ERROR, "SASL AUTH failed"); state = SREQ_S_ERROR; break; } if (send_sasl_step(sreq, &info) == 0 && send_hello(sreq) == 0) { state = SREQ_S_WAIT; } else { state = SREQ_S_ERROR; } break; } case PROTOCOL_BINARY_CMD_SASL_STEP: { if (status != PROTOCOL_BINARY_RESPONSE_SUCCESS) { lcb_log(LOGARGS(sreq, WARN), SESSREQ_LOGFMT "SASL auth failed with STATUS=0x%x", SESSREQ_LOGID(sreq), status); set_error_ex(sreq, LCB_AUTH_ERROR, "SASL Step Failed"); state = SREQ_S_ERROR; } else { /* Wait for pipelined HELLO response */ state = SREQ_S_AUTHDONE; } break; } case PROTOCOL_BINARY_CMD_HELLO: { state = SREQ_S_HELLODONE; if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS) { parse_hello(sreq, &info); } else if (status == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND || status == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED) { lcb_log(LOGARGS(sreq, DEBUG), SESSREQ_LOGFMT "Server does not support HELLO", SESSREQ_LOGID(sreq)); /* nothing */ } else { set_error_ex(sreq, LCB_PROTOCOL_ERROR, "Hello response unexpected"); state = SREQ_S_ERROR; } break; } default: { state = SREQ_S_ERROR; lcb_log(LOGARGS(sreq, ERROR), SESSREQ_LOGFMT "Received unknown response. OP=0x%x. RC=0x%x", SESSREQ_LOGID(sreq), PACKET_OPCODE(&info), PACKET_STATUS(&info)); set_error_ex(sreq, LCB_NOT_SUPPORTED, "Received unknown response"); break; } } lcb_pktinfo_ectx_done(&info, ioctx); if (sreq->err != LCB_SUCCESS) { bail_pending(sreq); } else if (state == SREQ_S_ERROR) { set_error_ex(sreq, LCB_ERROR, "FIXME: Error code set without description"); } else if (state == SREQ_S_HELLODONE) { negotiation_success(sreq); } else { goto GT_NEXT_PACKET; } (void)nb; }
void process_hello(void *packet, u_int32_t from, u_int32_t to, unsigned int size, struct ospf_interface *oiface) { struct ospfhdr *ospfheader; struct ospf_hello *hello; struct ospf_neighbor *nbr; struct in_addr ospf_mcast, *neighbors; int nbr_count=0, i=0; nbr = NULL; ospfheader = (struct ospfhdr *)packet; hello = (struct ospf_hello *)(packet+OSPFHDR_LEN); inet_pton(AF_INET,OSPF_MULTICAST_ALLROUTERS,&ospf_mcast); if((to == ospf_mcast.s_addr) || (to == oiface->iface->ip.s_addr)) { add_neighbor(from,ospfheader->src_router,oiface,hello); nbr_count = ((size-sizeof(struct ospfhdr)) - (sizeof(struct ospf_hello) - sizeof(struct in_addr)))/(sizeof(struct in_addr)); if(nbr_count>0) { neighbors = (struct in_addr *)(packet + (size - (sizeof(struct in_addr)*nbr_count))); for(i=0;i<nbr_count;i++) { if(neighbors[i].s_addr == ospf0->router_id.s_addr) { nbr = find_neighbor_by_ip(from); //if(nbr) send_dbdesc(nbr); } } } send_hello(oiface,NULL); if(nbr) { //check if adjacency should form /* - p2p * - this is DR * - this is BDR * - other is DR * - other is BDR * */ // set the nbr state to 2way since hello has been seen if(nbr->state<=OSPF_NBRSTATE_2WAY) { nbr->state = OSPF_NBRSTATE_2WAY; //dr-bdr negotiation: handles most scenarios but not RFC compliant //if the dr is empty if(oiface->dr.s_addr == 0) { // figure out who is dr // if the nbr doesn't know... if(nbr->dr.s_addr==0) { //set it to whoever has larger priority or if equal then to greater router id if(oiface->priority>nbr->priority) { oiface->dr.s_addr = ospf0->router_id.s_addr; } else if (nbr->priority>oiface->priority) { oiface->dr.s_addr = nbr->router_id.s_addr; } else { if(ntohl(ospf0->router_id.s_addr)<ntohl(nbr->router_id.s_addr)) { oiface->dr.s_addr = nbr->router_id.s_addr; } else { oiface->dr.s_addr = ospf0->router_id.s_addr; } } //if nbr has a dr of itself then use it } else if (nbr->dr.s_addr == nbr->router_id.s_addr){ oiface->dr.s_addr = nbr->router_id.s_addr; //if nbr has a dr of this rtr then go ahead and use ourself as dr } else if (nbr->dr.s_addr == ospf0->router_id.s_addr){ oiface->dr.s_addr = ospf0->router_id.s_addr; } else { //wait for dr to talk } send_hello(oiface,NULL); // if the bdr is empty } else if (oiface->bdr.s_addr == 0){ //figure out who is bdr //if the nbr thinks it is the bdr believe it if (nbr->bdr.s_addr == nbr->router_id.s_addr) { oiface->bdr.s_addr = nbr->bdr.s_addr; } } if(nbr->dr.s_addr&&(nbr->dr.s_addr!=oiface->dr.s_addr)) { oiface->dr.s_addr = nbr->dr.s_addr; } //if self or nbr is dr or bdr then go to exstart and send dbdesc if((oiface->dr.s_addr == oiface->iface->ip.s_addr)||(oiface->bdr.s_addr==oiface->iface->ip.s_addr)||(nbr->dr.s_addr==nbr->ip.s_addr)||(nbr->bdr.s_addr==nbr->ip.s_addr)) { //if so, go to exstart nbr->state = OSPF_NBRSTATE_EXSTART; nbr->lsa_send_list = copy_lsalist(); nbr->lsa_send_count = ospf0->lsdb->count; send_dbdesc(nbr,0); } } } } else { // how did this packet get here } }