static int ext_client_bgp_accept(struct thread * thread) { int accept_fd; union sockunion su; struct ext_client_bgp * ext_client_bgp = THREAD_ARG(thread); struct bgp_listener * listener; accept_fd = THREAD_FD(thread); if (accept_fd < 0) { printf("accept_fd is negative value %d", accept_fd); return -1; } LIST_FOR_EACH(listener, struct bgp_listener, node, &ext_client_bgp->listen_sockets) { // if we found a listener matching fd, we are done if(listener->accept_fd == accept_fd) break; } ext_client_bgp_event(EXT_CLIENT_BGP_ACCEPT, ext_client_bgp, listener); /* Accept connections */ listener->peer_fd = sockunion_accept (accept_fd, &su); if (listener->peer_fd < 0) { printf("[Error] BGP socket accept failed (%s)", strerror (errno)); return -1; } ext_client_bgp_event(EXT_CLIENT_BGP_READ, ext_client_bgp, listener); return 0; }
s32 ldp_accept(struct thread * t) { s32 fd ; union sockunion su ; struct ldp_peer * peer ; s32 sock = THREAD_FD(t); struct ldp * ldp = THREAD_ARG(t); ldp->t_accept = NULL ; THREAD_READ_ON(master, ldp->t_accept, ldp_accept, ldp, sock); fd = sockunion_accept(sock, &su); if( fd <= 0 ) return -1 ; peer = ldp_peer_new(); if( NULL == peer ) { close(fd); return -1 ; } peer->state = ACCEPT_PEER ; peer->fd = fd ; peer->ldp = ldp; peer->transport = su.sin.sin_addr.s_addr; peer->input = stream_new(LDP_MAX_PDU_LEN); listnode_add(ldp->accepts, peer); LDP_FSM_EVENT(peer, ConnectSuccess); return 0 ; }
/* Accept code of zebra server socket. */ static int zebra_accept (struct thread *thread) { int accept_sock; int client_sock; struct sockaddr_in client; socklen_t len; accept_sock = THREAD_FD (thread); /* Reregister myself. */ zebra_event (ZEBRA_SERV, accept_sock, NULL); len = sizeof (struct sockaddr_in); client_sock = accept (accept_sock, (struct sockaddr *) &client, &len); if (client_sock < 0) { zlog_warn ("Can't accept zebra socket: %s", safe_strerror (errno)); return -1; } /* Make client socket non-blocking. */ set_nonblocking(client_sock); /* Create new zebra client. */ zebra_client_create (client_sock); return 0; }
/* SMUX message read function. */ int smux_read (struct thread *t) { int sock; int len; u_char buf[SMUXMAXPKTSIZE]; int ret; /* Clear thread. */ sock = THREAD_FD (t); smux_read_thread = NULL; if (debug_smux) zlog_debug ("SMUX read start"); /* Read message from SMUX socket. */ len = recv (sock, buf, SMUXMAXPKTSIZE, 0); if (len < 0) { zlog_warn ("Can't read all SMUX packet: %s", safe_strerror (errno)); close (sock); smux_sock = -1; smux_event (SMUX_CONNECT, 0); return -1; } if (len == 0) { zlog_warn ("SMUX connection closed: %d", sock); close (sock); smux_sock = -1; smux_event (SMUX_CONNECT, 0); return -1; } if (debug_smux) zlog_debug ("SMUX read len: %d", len); /* Parse the message. */ ret = smux_parse (buf, len); if (ret < 0) { close (sock); smux_sock = -1; smux_event (SMUX_CONNECT, 0); return -1; } /* Regiser read thread. */ smux_event (SMUX_READ, sock); return 0; }
/* Kernel route reflection. */ int kernel_read (struct thread *thread) { int ret; int sock; sock = THREAD_FD (thread); ret = netlink_parse_info (netlink_information_fetch, &netlink); thread_add_read (master, kernel_read, NULL, netlink.sock); return 0; }
/* When the file is ready move to queueu. */ int thread_process_fd (struct thread_master *m, struct thread_list *list, pal_sock_set_t *fdset, pal_sock_set_t *mfdset) { struct thread *thread; struct thread *next; int ready = 0; for (thread = list->head; thread; thread = next) { next = thread->next; if (PAL_SOCK_HANDLESET_ISSET (THREAD_FD (thread), fdset)) { PAL_SOCK_HANDLESET_CLR(THREAD_FD (thread), mfdset); thread_list_delete (list, thread); thread_enqueue_middle (m, thread); ready++; } } return ready; }
int irdp_read_raw(struct thread *r) { struct interface *ifp; struct zebra_if *zi; struct irdp_interface *irdp; char buf[IRDP_RX_BUF]; int ret, ifindex = 0; int irdp_sock = THREAD_FD(r); t_irdp_raw = thread_add_read(zebrad.master, irdp_read_raw, NULL, irdp_sock); ret = irdp_recvmsg(irdp_sock, (u_char *) buf, IRDP_RX_BUF, &ifindex); if (ret < 0) zlog_warn("IRDP: RX Error length = %d", ret); ifp = if_lookup_by_index(ifindex); if (!ifp) return ret; zi = ifp->info; if (!zi) return ret; irdp = &zi->irdp; if (!irdp) return ret; if (!(irdp->flags & IF_ACTIVE)) { if (irdp->flags & IF_DEBUG_MISC) zlog_debug("IRDP: RX ICMP for disabled interface %s\n", ifp->name); return 0; } if (irdp->flags & IF_DEBUG_PACKET) { int i; zlog_debug("IRDP: RX (idx %d) ", ifindex); for (i = 0; i < ret; i++) zlog_debug("IRDP: RX %x ", buf[i] & 0xFF); } parse_irdp_packet(buf, ret, ifp); return ret; }
static int ssmpingd_sock_read(struct thread *t) { struct ssmpingd_sock *ss; int sock_fd; int result; zassert(t); ss = THREAD_ARG(t); zassert(ss); sock_fd = THREAD_FD(t); zassert(sock_fd == ss->sock_fd); result = ssmpingd_read_msg(ss); /* Keep reading */ ss->t_sock_read = 0; ssmpingd_read_on(ss); return result; }
int zebra_server_dequeue (struct thread *t) { int sock; int nbytes; struct zebra_message_queue *queue; sock = THREAD_FD (t); t_write = NULL; queue = (struct zebra_message_queue *) FIFO_HEAD (&message_queue); if (queue) { nbytes = write (sock, queue->buf + queue->written, queue->length - queue->written); if (nbytes <= 0) { if (errno != EAGAIN) return -1; } else if (nbytes != (queue->length - queue->written)) { queue->written += nbytes; } else { FIFO_DEL (queue); XFREE (MTYPE_TMP, queue->buf); XFREE (MTYPE_TMP, queue); } } if (FIFO_TOP (&message_queue)) THREAD_WRITE_ON (zebrad.master, t_write, zebra_server_dequeue, NULL, sock); return 0; }
static int kernel_bfd_read (struct thread *th) { int ret; int sock; struct bfd_nl_peerinfo *peer; sock = THREAD_FD (th); if(bfd_ioctl_sock < 0) return 0; peer = XCALLOC(MTYPE_BFD_PEER, sizeof(*peer)); ret = read(bfd_ioctl_sock, peer, sizeof(*peer)); if(ret < 0) zlog_warn("read notify %s", strerror(errno)); bfd_ioctl_state_change(peer); thread_add_read (master, kernel_bfd_read, NULL, bfd_ioctl_sock); XFREE(MTYPE_BFD_PEER, peer); return 0; }
int shim_sisis_accept(struct thread * thread) { int accept_sock; int sisis_sock; struct sisis_listener *listener; union sockunion su; char buf[SU_ADDRSTRLEN]; accept_sock = THREAD_FD (thread); if (accept_sock < 0) { zlog_err ("accept_sock is negative value %d", accept_sock); return -1; } thread_add_read (master, shim_sisis_accept, NULL, accept_sock); sisis_sock = sockunion_accept(accept_sock, &su); if (sisis_sock < 0) { zlog_err ("[Error] SISIS socket accept failed (%s)", safe_strerror (errno)); return -1; } zlog_notice ("SISIS connection from host %s", inet_sutop (&su, buf)); listener = XMALLOC (MTYPE_SHIM_SISIS_LISTENER, sizeof(*listener)); listener->fd = accept_sock; listener->ibuf = stream_new (SV_HEADER_SIZE + 1500); // memcpy(&listener->su, sa, salen); listener->sisis_fd = sisis_sock; listener->dif = stream_fifo_new(); listener->chksum_stream = stream_new(4 * 20); // need to figure out good size for buffering listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); listnode_add (sm->listen_sockets, listener); return 0; }
/* Accept code of zebra server socket. */ static int zebra_accept (struct thread *thread) { int val; int accept_sock; int client_sock; struct sockaddr_in client; socklen_t len; accept_sock = THREAD_FD (thread); len = sizeof (struct sockaddr_in); client_sock = accept (accept_sock, (struct sockaddr *) &client, &len); if (client_sock < 0) { zlog_warn ("Can't accept zebra socket: %s", safe_strerror (errno)); return -1; } /* Make client socket non-blocking. */ /* XXX: We dont requeue failed writes, so this leads to inconsistencies. * for now socket must remain blocking, regardless of risk of deadlocks. */ /* val = fcntl (client_sock, F_GETFL, 0); fcntl (client_sock, F_SETFL, (val | O_NONBLOCK)); */ /* Create new zebra client. */ zebra_client_create (client_sock); /* Register myself. */ zebra_event (ZEBRA_SERV, accept_sock, NULL); return 0; }
/* Receive a message */ static int sisis_recvfrom(struct thread *thread) { int sisis_sock; struct sisis_listener *listener = THREAD_ARG(thread); sisis_sock = THREAD_FD (thread); if (sisis_sock < 0) { zlog_err ("sisis_sock is negative value %d", sisis_sock); return -1; } // Add thread again listener->thread = thread_add_read (sisis_info->master, sisis_recvfrom, listener, sisis_sock); // Get message struct sockaddr from; memset (&from, 0, sizeof (struct sockaddr)); char buf[1024]; memset (buf, 0, 1024); int recv_len; unsigned int from_len = sizeof from; recv_len = recvfrom(sisis_sock, buf, 1024, 0, &from, &from_len); if (recv_len < 0) { zlog_err ("Receive length is negative value %d. Error #%d: %s", recv_len, errno, safe_strerror(errno)); return -1; } char fromStr[256]; inet_ntop(from.sa_family, &(from.sa_data), fromStr, sizeof fromStr); //printf("Message from %s[%d]: %s\n", fromStr, recv_len, buf); // Process message sisis_process_message(buf, recv_len, sisis_sock, &from, recv_len); }
/* This thread handles asynchronous messages coming in from the OSPF API server */ static int lsa_read (struct thread *thread) { struct ospf_apiclient *oclient; int fd; int ret; printf ("lsa_read called\n"); oclient = THREAD_ARG (thread); fd = THREAD_FD (thread); /* Handle asynchronous message */ ret = ospf_apiclient_handle_async (oclient); if (ret < 0) { printf ("Connection closed, exiting..."); exit(0); } /* Reschedule read thread */ thread_add_read (master, lsa_read, oclient, fd); return 0; }
/* Kernel routing table and interface updates via routing socket. */ static int kernel_read (struct thread *thread) { int sock; int nbytes; struct rt_msghdr *rtm; /* * This must be big enough for any message the kernel might send. * Rather than determining how many sockaddrs of what size might be * in each particular message, just use RTAX_MAX of sockaddr_storage * for each. Note that the sockaddrs must be after each message * definition, or rather after whichever happens to be the largest, * since the buffer needs to be big enough for a message and the * sockaddrs together. */ union { /* Routing information. */ struct { struct rt_msghdr rtm; struct sockaddr_storage addr[RTAX_MAX]; } r; /* Interface information. */ struct { struct if_msghdr ifm; struct sockaddr_storage addr[RTAX_MAX]; } im; /* Interface address information. */ struct { struct ifa_msghdr ifa; struct sockaddr_storage addr[RTAX_MAX]; } ia; #ifdef RTM_IFANNOUNCE /* Interface arrival/departure */ struct { struct if_announcemsghdr ifan; struct sockaddr_storage addr[RTAX_MAX]; } ian; #endif /* RTM_IFANNOUNCE */ } buf; /* Fetch routing socket. */ sock = THREAD_FD (thread); nbytes= read (sock, &buf, sizeof buf); if (nbytes <= 0) { if (nbytes < 0 && errno != EWOULDBLOCK && errno != EAGAIN) zlog_warn ("routing socket error: %s", safe_strerror (errno)); return 0; } thread_add_read (zebrad.master, kernel_read, NULL, sock); if (IS_ZEBRA_DEBUG_KERNEL) rtmsg_debug (&buf.r.rtm); rtm = &buf.r.rtm; /* * Ensure that we didn't drop any data, so that processing routines * can assume they have the whole message. */ if (rtm->rtm_msglen != nbytes) { zlog_warn ("kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d\n", rtm->rtm_msglen, nbytes, rtm->rtm_type); return -1; } switch (rtm->rtm_type) { case RTM_ADD: case RTM_DELETE: case RTM_CHANGE: rtm_read (rtm); break; case RTM_IFINFO: ifm_read (&buf.im.ifm); break; case RTM_NEWADDR: case RTM_DELADDR: ifam_read (&buf.ia.ifa); break; #ifdef RTM_IFANNOUNCE case RTM_IFANNOUNCE: ifan_read (&buf.ian.ifan); break; #endif /* RTM_IFANNOUNCE */ default: if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("Unprocessed RTM_type: %d", rtm->rtm_type); break; } return 0; }
int shim_sisis_read(struct thread * thread) { struct sisis_listener *listener; int sisis_sock; uint16_t length, checksum; int already; u_int ifindex; struct shim_interface * si; struct in6_addr src; char src_buf[INET6_ADDRSTRLEN]; struct in6_addr dst; char dst_buf[INET6_ADDRSTRLEN]; zlog_notice("Reading packet from SISIS connection!"); /* first of all get listener pointer. */ listener = THREAD_ARG (thread); sisis_sock = THREAD_FD (thread); stream_reset(listener->ibuf); if ((already = stream_get_endp(listener->ibuf)) < SVZ_OUT_HEADER_SIZE) { ssize_t nbytes; if (((nbytes = stream_read_try (listener->ibuf, sisis_sock, SVZ_OUT_HEADER_SIZE-already)) == 0) || (nbytes == -1)) { return -1; } if(nbytes != (SVZ_OUT_HEADER_SIZE - already)) { listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); return 0; } already = SVZ_OUT_HEADER_SIZE; } stream_set_getp(listener->ibuf, 0); length = stream_getw(listener->ibuf); checksum = stream_getw(listener->ibuf); if(length > STREAM_SIZE(listener->ibuf)) { struct stream * ns; zlog_warn("message size exceeds buffer size"); ns = stream_new(length); stream_copy(ns, listener->ibuf); stream_free(listener->ibuf); listener->ibuf = ns; } if(already < length) { ssize_t nbytes; if(((nbytes = stream_read_try(listener->ibuf, sisis_sock, length-already)) == 0) || nbytes == -1) { return -1; } if(nbytes != (length-already)) { listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); return 0; } } unsigned int num_of_addrs = number_of_sisis_addrs_for_process_type(SISIS_PTYPE_RIBCOMP_OSPF6); unsigned int num_of_listeners = number_of_listeners(); zlog_notice("Number of addr: %d", num_of_addrs); zlog_notice("Number of listeners: %d", num_of_listeners); pthread_mutex_lock(&bmap_mutex); struct bmap * bmap = bmap_set(checksum); // if we added initially // set timer at which to recycle bmap // if there are no more processes sending data if(bmap->count == 0) { uint16_t * chcksum_ptr = malloc(sizeof(uint16_t)); *chcksum_ptr = checksum; listener->bmap_thread = thread_add_timer_msec (master, svz_sisis_clean_bmap, chcksum_ptr, 100); } bmap->count++; zlog_notice("# of streams %d for checksum %d with length %d", bmap->count, checksum, length); float received_ratio = (float)bmap->count/(float)num_of_addrs; stream_putw(listener->chksum_stream, checksum); if((received_ratio > 1.0/2.0) && !bmap->sent) { if(are_checksums_same()) { zlog_notice("Checksums are all the same"); if(primary_listener == NULL) primary_listener = listener; reset_checksum_streams(); svz_send(listener->ibuf); bmap->sent = 1; } else { zlog_notice("Checksums are not all the same"); stream_fifo_push(listener->dif, listener->ibuf); listener->dif_size++; } } else if(!bmap->sent) { zlog_notice("Not enough processes have sent their data; buffering..."); } else { zlog_notice("Data has already been sent..."); } if((bmap->count == num_of_addrs) && (bmap->sent)) { zlog_notice("Bmap no longer needed, freeing..."); bmap->count = 0; bmap->sent = 0; clear_checksum_streams(checksum); bmap_unset(checksum); } pthread_mutex_unlock(&bmap_mutex); if (sisis_sock < 0) /* Connection was closed during packet processing. */ return -1; /* Register read thread. */ // stream_reset(listener->ibuf); /* prepare for next packet. */ listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); return 0; }
static int ext_client_bgp_recv(struct thread * t) { struct ext_client_bgp * ext_client_bgp = THREAD_ARG(t); struct bgp_header * bgph; u_int16_t length; size_t bgph_size = sizeof(struct bgp_header); struct rfp_forward_bgp * rfpb; size_t already = 0; size_t nbytes; struct rfpbuf * bgp_buf = rfpbuf_new(bgph_size); struct bgp_listener * listener; unsigned int peer_fd = THREAD_FD(t); printf("ext_client_bgp_recv called\n"); LIST_FOR_EACH(listener, struct bgp_listener, node, &ext_client_bgp->listen_sockets) { // if we found a listener matching fd, we are done if(listener->peer_fd == peer_fd) break; } if(((nbytes = rfpbuf_read_try(bgp_buf, peer_fd, bgph_size - already)) == 0) || (nbytes == -1)) { // failed return -1; } if(nbytes != bgph_size - already) { /* Try again later */ ext_client_bgp_event(EXT_CLIENT_BGP_READ, ext_client_bgp, listener); return 0; } already = bgph_size; bgph = rfpbuf_at_assert(bgp_buf, 0, sizeof(struct bgp_header)); length = ntohs(bgph->length); rfpbuf_prealloc_tailroom(bgp_buf, length - already); if(already < length) { if(((nbytes = rfpbuf_read_try(bgp_buf, peer_fd, length - already)) == 0) || (nbytes == -1)) { // failed return -1; } if(nbytes != length - already) { /* Try again later */ ext_client_bgp_event(EXT_CLIENT_BGP_READ, ext_client_bgp, listener); return 0; } } // put a header P(ext_client_bgp).ibuf = routeflow_alloc_xid(RFPT_FORWARD_BGP, RFP10_VERSION, 0, sizeof(struct rfp_forward_bgp)); rfpb = rfpbuf_at_assert(P(ext_client_bgp).ibuf, 0, sizeof(struct rfp_forward_bgp)); memcpy(&rfpb->bgp_header, bgp_buf->data, bgph_size); // call our parent's class ext_client_recv(&P(ext_client_bgp)); // sent the data so free the memomry rfpbuf_delete(bgp_buf); rfpbuf_delete(P(ext_client_bgp).ibuf); P(ext_client_bgp).ibuf = 0; ext_client_bgp_event(EXT_CLIENT_BGP_READ, ext_client_bgp, listener); return 0; }
static int pim_igmp_read(struct thread *t) { struct igmp_sock *igmp; int fd; struct sockaddr_in from; struct sockaddr_in to; socklen_t fromlen = sizeof(from); socklen_t tolen = sizeof(to); uint8_t buf[PIM_IGMP_BUFSIZE_READ]; int len; int ifindex = -1; int result = -1; /* defaults to bad */ zassert(t); igmp = THREAD_ARG(t); zassert(igmp); fd = THREAD_FD(t); zassert(fd == igmp->fd); len = pim_socket_recvfromto(fd, buf, sizeof(buf), &from, &fromlen, &to, &tolen, &ifindex); if (len < 0) { zlog_warn("Failure receiving IP IGMP packet on fd=%d: errno=%d: %s", fd, errno, safe_strerror(errno)); goto done; } if (PIM_DEBUG_IGMP_PACKETS) { char from_str[100]; char to_str[100]; if (!inet_ntop(AF_INET, &from.sin_addr, from_str, sizeof(from_str))) sprintf(from_str, "<from?>"); if (!inet_ntop(AF_INET, &to.sin_addr, to_str, sizeof(to_str))) sprintf(to_str, "<to?>"); zlog_debug("Recv IP IGMP pkt size=%d from %s to %s on fd=%d on ifindex=%d (sock_ifindex=%d)", len, from_str, to_str, fd, ifindex, igmp->interface->ifindex); } #ifdef PIM_CHECK_RECV_IFINDEX_SANITY /* ifindex sanity check */ if (ifindex != (int) igmp->interface->ifindex) { char from_str[100]; char to_str[100]; struct interface *ifp; if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str))) sprintf(from_str, "<from?>"); if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str))) sprintf(to_str, "<to?>"); ifp = if_lookup_by_index(ifindex); if (ifp) { zassert(ifindex == (int) ifp->ifindex); } #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH zlog_warn("Interface mismatch: recv IGMP pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", from_str, to_str, fd, ifindex, ifp ? ifp->name : "<if-notfound>", igmp->interface->ifindex, igmp->interface->name); #endif goto done; } #endif if (pim_igmp_packet(igmp, (char *)buf, len)) { goto done; } result = 0; /* good */ done: igmp_read_on(igmp); return result; }
/* Handler of zebra service request. */ static int zebra_client_read (struct thread *thread) { int sock; struct zserv *client; int nbyte; u_short length; u_char command; /* Get thread data. Reset reading thread because I'm running. */ sock = THREAD_FD (thread); client = THREAD_ARG (thread); client->t_read = NULL; /* Read length and command. */ nbyte = stream_read (client->ibuf, sock, 3); if (nbyte <= 0) { if (IS_ZEBRA_DEBUG_EVENT) zlog_debug ("connection closed socket [%d]", sock); zebra_client_close (client); return -1; } length = stream_getw (client->ibuf); command = stream_getc (client->ibuf); if (length < 3) { if (IS_ZEBRA_DEBUG_EVENT) zlog_debug ("length %d is less than 3 ", length); zebra_client_close (client); return -1; } length -= 3; /* Read rest of data. */ if (length) { nbyte = stream_read (client->ibuf, sock, length); if (nbyte <= 0) { if (IS_ZEBRA_DEBUG_EVENT) zlog_debug ("connection closed [%d] when reading zebra data", sock); zebra_client_close (client); return -1; } } /* Debug packet information. */ if (IS_ZEBRA_DEBUG_EVENT) zlog_debug ("zebra message comes from socket [%d]", sock); if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) zlog_debug ("zebra message received [%s] %d", zebra_command_str[command], length); switch (command) { case ZEBRA_ROUTER_ID_ADD: zread_router_id_add (client, length); break; case ZEBRA_ROUTER_ID_DELETE: zread_router_id_delete (client, length); break; case ZEBRA_INTERFACE_ADD: zread_interface_add (client, length); break; case ZEBRA_INTERFACE_DELETE: zread_interface_delete (client, length); break; case ZEBRA_IPV4_ROUTE_ADD: zread_ipv4_add (client, length); break; case ZEBRA_IPV4_ROUTE_DELETE: zread_ipv4_delete (client, length); break; #ifdef HAVE_IPV6 case ZEBRA_IPV6_ROUTE_ADD: zread_ipv6_add (client, length); break; case ZEBRA_IPV6_ROUTE_DELETE: zread_ipv6_delete (client, length); break; #endif /* HAVE_IPV6 */ case ZEBRA_REDISTRIBUTE_ADD: zebra_redistribute_add (command, client, length); break; case ZEBRA_REDISTRIBUTE_DELETE: zebra_redistribute_delete (command, client, length); break; case ZEBRA_REDISTRIBUTE_DEFAULT_ADD: zebra_redistribute_default_add (command, client, length); break; case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE: zebra_redistribute_default_delete (command, client, length); break; case ZEBRA_IPV4_NEXTHOP_LOOKUP: zread_ipv4_nexthop_lookup (client, length); break; #ifdef HAVE_IPV6 case ZEBRA_IPV6_NEXTHOP_LOOKUP: zread_ipv6_nexthop_lookup (client, length); break; #endif /* HAVE_IPV6 */ case ZEBRA_IPV4_IMPORT_LOOKUP: zread_ipv4_import_lookup (client, length); break; default: zlog_info ("Zebra received unknown command %d", command); break; } stream_reset (client->ibuf); zebra_event (ZEBRA_READ, sock, client); return 0; }
/* Accept bgp connection. */ static int bgp_accept (struct thread *thread) { int bgp_sock; int accept_sock; union sockunion su; struct peer *peer; struct peer *peer1; struct bgp *bgp; char buf[SU_ADDRSTRLEN]; /* Regiser accept thread. */ accept_sock = THREAD_FD (thread); bgp = THREAD_ARG (thread); if (accept_sock < 0) { zlog_err ("accept_sock is nevative value %d", accept_sock); return -1; } thread_add_read (master, bgp_accept, bgp, accept_sock); /* Accept client connection. */ bgp_sock = sockunion_accept (accept_sock, &su); if (bgp_sock < 0) { zlog_err ("[Error] BGP socket accept failed (%s)", strerror (errno)); return -1; } if (BGP_DEBUG (events, EVENTS)) zlog_info ("[Event] BGP connection from host %s", inet_sutop (&su, buf)); /* Check remote IP address */ peer1 = peer_lookup (bgp, &su); if (! peer1 || peer1->status == Idle) { if (BGP_DEBUG (events, EVENTS)) { if (! peer1) zlog_info ("[Event] BGP connection IP address %s is not configured", inet_sutop (&su, buf)); else zlog_info ("[Event] BGP connection IP address %s is Idle state", inet_sutop (&su, buf)); } close (bgp_sock); return -1; } /* In case of peer is EBGP, we should set TTL for this connection. */ if (peer_sort (peer1) == BGP_PEER_EBGP) sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl); if (! bgp) bgp = peer1->bgp; /* Make dummy peer until read Open packet. */ if (BGP_DEBUG (events, EVENTS)) zlog_info ("[Event] Make dummy peer structure until read Open packet"); { char buf[SU_ADDRSTRLEN + 1]; peer = peer_create_accept (bgp); SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER); peer->su = su; peer->fd = bgp_sock; peer->status = Active; peer->local_id = peer1->local_id; /* Make peer's address string. */ sockunion2str (&su, buf, SU_ADDRSTRLEN); peer->host = strdup (buf); } BGP_EVENT_ADD (peer, TCP_connection_open); return 0; }
/* Zebra client message read function. */ int zclient_read (struct thread *thread) { int ret; int nbytes; int sock; zebra_size_t length; zebra_command_t command; #undef zclient struct_zclient *zclient; /* Get socket to zebra. */ sock = THREAD_FD (thread); zclient = THREAD_ARG (thread); zclient->t_read = NULL; /* Clear input buffer. */ stream_reset (zclient->ibuf); /* Read zebra header. */ nbytes = stream_read (zclient->ibuf, sock, ZEBRA_HEADER_SIZE); /* zebra socket is closed. */ if (nbytes == 0) { if (zclient_debug) zlog_debug ("zclient connection closed socket [%d].", sock); zclient->fail++; zclient_stop (zclient); zclient_event (ZCLIENT_CONNECT, zclient); return -1; } /* zebra read error. */ if (nbytes < 0 || nbytes != ZEBRA_HEADER_SIZE) { if (zclient_debug) zlog_debug ("Can't read all packet (length %d).", nbytes); zclient->fail++; zclient_stop (zclient); zclient_event (ZCLIENT_CONNECT, zclient); return -1; } /* Fetch length and command. */ length = stream_getw (zclient->ibuf); command = stream_getc (zclient->ibuf); /* Length check. */ if (length >= zclient->ibuf->size) { stream_free (zclient->ibuf); zclient->ibuf = stream_new (length + 1); } length -= ZEBRA_HEADER_SIZE; /* Read rest of zebra packet. */ nbytes = stream_read (zclient->ibuf, sock, length); if (nbytes != length) { if (zclient_debug) zlog_debug ("zclient connection closed socket [%d].", sock); zclient->fail++; zclient_stop (zclient); zclient_event (ZCLIENT_CONNECT, zclient); return -1; } if (zclient_debug) zlog_debug("zclient 0x%p command 0x%x \n", zclient, command); switch (command) { case ZEBRA_ROUTER_ID_UPDATE: if (zclient->router_id_update) ret = (*zclient->router_id_update) (command, zclient, length); break; case ZEBRA_INTERFACE_ADD: if (zclient->interface_add) ret = (*zclient->interface_add) (command, zclient, length); break; case ZEBRA_INTERFACE_DELETE: if (zclient->interface_delete) ret = (*zclient->interface_delete) (command, zclient, length); break; case ZEBRA_INTERFACE_ADDRESS_ADD: if (zclient->interface_address_add) ret = (*zclient->interface_address_add) (command, zclient, length); break; case ZEBRA_INTERFACE_ADDRESS_DELETE: if (zclient->interface_address_delete) ret = (*zclient->interface_address_delete) (command, zclient, length); break; case ZEBRA_INTERFACE_UP: if (zclient->interface_up) ret = (*zclient->interface_up) (command, zclient, length); break; case ZEBRA_INTERFACE_DOWN: if (zclient->interface_down) ret = (*zclient->interface_down) (command, zclient, length); break; case ZEBRA_IPV4_ROUTE_ADD: if (zclient->ipv4_route_add) ret = (*zclient->ipv4_route_add) (command, zclient, length); break; case ZEBRA_IPV4_ROUTE_DELETE: if (zclient->ipv4_route_delete) ret = (*zclient->ipv4_route_delete) (command, zclient, length); break; case ZEBRA_IPV6_ROUTE_ADD: if (zclient->ipv6_route_add) ret = (*zclient->ipv6_route_add) (command, zclient, length); break; case ZEBRA_IPV6_ROUTE_DELETE: if (zclient->ipv6_route_delete) ret = (*zclient->ipv6_route_delete) (command, zclient, length); break; default: break; } /* Register read thread. */ zclient_event (ZCLIENT_READ, zclient); return 0; }
/* Accept bgp connection. */ static int bgp_accept (struct thread *thread) { int bgp_sock; //socket used for BGP connection int accept_sock; union sockunion su; struct bgp_listener *listener = THREAD_ARG(thread); struct peer *peer; struct peer *peer1; char buf[SU_ADDRSTRLEN]; /* Register accept thread to accept connections from a client */ accept_sock = THREAD_FD (thread); if (accept_sock < 0) { zlog_err ("accept_sock is nevative value %d", accept_sock); return -1; } /*creating a new reading thread*/ listener->thread = thread_add_read (master, bgp_accept, listener, accept_sock); /* -------------------------------------------------- * - BGP ACCEPT - * -------------------------------------------------- * */ printf("\n BGP ACCEPT: About to initialise SSL \n"); ssl_init(); //initialise the library, method, contact of ssl session, returns nothing printf("\n BGP ACCEPT: About to do socket call \n"); bgp_sock = sockunion_accept (accept_sock, &su); SSL_accept(BGPoTLS->ssl); if (bgp_sock < 0) { zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno)); return -1; } set_nonblocking (bgp_sock); if (BGP_DEBUG (events, EVENTS)) zlog_debug("[Event] BGP connection from host %s", inet_sutop (&su, buf)); /* Check remote IP address */ peer1 = peer_lookup (NULL, &su); if (! peer1 || peer1->status == Idle) { if (BGP_DEBUG (events, EVENTS)) { if (! peer1) zlog_debug ("[Event] BGP connection IP address %s is not configured", inet_sutop (&su, buf)); else zlog_debug ("[Event] BGP connection IP address %s is Idle state", inet_sutop (&su, buf)); } close (bgp_sock); return -1; } /* In case of peer is EBGP, we should set TTL for this connection. */ if (peer1->sort == BGP_PEER_EBGP) { sockopt_ttl (peer1->su.sa.sa_family, bgp_sock, peer1->ttl); if (peer1->gtsm_hops) sockopt_minttl (peer1->su.sa.sa_family, bgp_sock, MAXTTL + 1 - peer1->gtsm_hops); } /* Make dummy peer until read Open packet. */ if (BGP_DEBUG (events, EVENTS)) zlog_debug ("[Event] Make dummy peer structure until read Open packet"); { char buf[SU_ADDRSTRLEN]; peer = peer_create_accept (peer1->bgp); SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER); peer->su = su; peer->fd = bgp_sock; peer->status = Active; peer->local_id = peer1->local_id; peer->v_holdtime = peer1->v_holdtime; peer->v_keepalive = peer1->v_keepalive; /* Make peer's address string. */ sockunion2str (&su, buf, SU_ADDRSTRLEN); peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf); } BGP_EVENT_ADD (peer, TCP_connection_open); return 0; }
/* Accept bgp connection. */ static int bgp_accept(struct thread *thread) { int bgp_sock; int accept_sock; union sockunion su; struct bgp_listener *listener = THREAD_ARG(thread); struct peer *peer; struct peer *peer1; char buf[SU_ADDRSTRLEN]; struct bgp *bgp = NULL; sockunion_init(&su); /* Register accept thread. */ accept_sock = THREAD_FD(thread); if (accept_sock < 0) { flog_err_sys(EC_LIB_SOCKET, "accept_sock is nevative value %d", accept_sock); return -1; } listener->thread = NULL; thread_add_read(bm->master, bgp_accept, listener, accept_sock, &listener->thread); /* Accept client connection. */ bgp_sock = sockunion_accept(accept_sock, &su); if (bgp_sock < 0) { flog_err_sys(EC_LIB_SOCKET, "[Error] BGP socket accept failed (%s)", safe_strerror(errno)); return -1; } set_nonblocking(bgp_sock); /* Obtain BGP instance this connection is meant for. * - if it is a VRF netns sock, then BGP is in listener structure * - otherwise, the bgp instance need to be demultiplexed */ if (listener->bgp) bgp = listener->bgp; else if (bgp_get_instance_for_inc_conn(bgp_sock, &bgp)) { if (bgp_debug_neighbor_events(NULL)) zlog_debug( "[Event] Could not get instance for incoming conn from %s", inet_sutop(&su, buf)); close(bgp_sock); return -1; } /* Set socket send buffer size */ setsockopt_so_sendbuf(bgp_sock, BGP_SOCKET_SNDBUF_SIZE); /* Check remote IP address */ peer1 = peer_lookup(bgp, &su); if (!peer1) { peer1 = peer_lookup_dynamic_neighbor(bgp, &su); if (peer1) { /* Dynamic neighbor has been created, let it proceed */ peer1->fd = bgp_sock; bgp_fsm_change_status(peer1, Active); BGP_TIMER_OFF( peer1->t_start); /* created in peer_create() */ if (peer_active(peer1)) BGP_EVENT_ADD(peer1, TCP_connection_open); return 0; } } if (!peer1) { if (bgp_debug_neighbor_events(NULL)) { zlog_debug( "[Event] %s connection rejected - not configured" " and not valid for dynamic", inet_sutop(&su, buf)); } close(bgp_sock); return -1; } if (CHECK_FLAG(peer1->flags, PEER_FLAG_SHUTDOWN)) { if (bgp_debug_neighbor_events(peer1)) zlog_debug( "[Event] connection from %s rejected due to admin shutdown", inet_sutop(&su, buf)); close(bgp_sock); return -1; } /* * Do not accept incoming connections in Clearing state. This can result * in incorect state transitions - e.g., the connection goes back to * Established and then the Clearing_Completed event is generated. Also, * block incoming connection in Deleted state. */ if (peer1->status == Clearing || peer1->status == Deleted) { if (bgp_debug_neighbor_events(peer1)) zlog_debug( "[Event] Closing incoming conn for %s (%p) state %d", peer1->host, peer1, peer1->status); close(bgp_sock); return -1; } /* Check that at least one AF is activated for the peer. */ if (!peer_active(peer1)) { if (bgp_debug_neighbor_events(peer1)) zlog_debug( "%s - incoming conn rejected - no AF activated for peer", peer1->host); close(bgp_sock); return -1; } if (bgp_debug_neighbor_events(peer1)) zlog_debug("[Event] BGP connection from host %s fd %d", inet_sutop(&su, buf), bgp_sock); if (peer1->doppelganger) { /* We have an existing connection. Kill the existing one and run with this one. */ if (bgp_debug_neighbor_events(peer1)) zlog_debug( "[Event] New active connection from peer %s, Killing" " previous active connection", peer1->host); peer_delete(peer1->doppelganger); } if (bgp_set_socket_ttl(peer1, bgp_sock) < 0) if (bgp_debug_neighbor_events(peer1)) zlog_debug( "[Event] Unable to set min/max TTL on peer %s, Continuing", peer1->host); peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as, peer1->as, peer1->as_type, 0, 0, NULL); hash_release(peer->bgp->peerhash, peer); hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); peer_xfer_config(peer, peer1); UNSET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE); peer->doppelganger = peer1; peer1->doppelganger = peer; peer->fd = bgp_sock; vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer)); bgp_fsm_change_status(peer, Active); BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */ SET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER); /* Make dummy peer until read Open packet. */ if (peer1->status == Established && CHECK_FLAG(peer1->sflags, PEER_STATUS_NSF_MODE)) { /* If we have an existing established connection with graceful * restart * capability announced with one or more address families, then * drop * existing established connection and move state to connect. */ peer1->last_reset = PEER_DOWN_NSF_CLOSE_SESSION; SET_FLAG(peer1->sflags, PEER_STATUS_NSF_WAIT); bgp_event_update(peer1, TCP_connection_closed); } if (peer_active(peer)) { BGP_EVENT_ADD(peer, TCP_connection_open); } return 0; }
/* Handler of zebra service request. */ static int zebra_client_read (struct thread *thread) { int sock; struct zserv *client; size_t already; uint16_t length, command; uint8_t marker, version; /* Get thread data. Reset reading thread because I'm running. */ sock = THREAD_FD (thread); client = THREAD_ARG (thread); client->t_read = NULL; if (client->t_suicide) { zebra_client_close(client); return -1; } /* Read length and command (if we don't have it already). */ if ((already = stream_get_endp(client->ibuf)) < ZEBRA_HEADER_SIZE) { ssize_t nbyte; if (((nbyte = stream_read_try (client->ibuf, sock, ZEBRA_HEADER_SIZE-already)) == 0) || (nbyte == -1)) { if (IS_ZEBRA_DEBUG_EVENT) zlog_debug ("connection closed socket [%d]", sock); zebra_client_close (client); return -1; } if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already)) { /* Try again later. */ zebra_event (ZEBRA_READ, sock, client); return 0; } already = ZEBRA_HEADER_SIZE; } /* Reset to read from the beginning of the incoming packet. */ stream_set_getp(client->ibuf, 0); /* Fetch header values */ length = stream_getw (client->ibuf); marker = stream_getc (client->ibuf); version = stream_getc (client->ibuf); command = stream_getw (client->ibuf); if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION) { zlog_err("%s: socket %d version mismatch, marker %d, version %d", __func__, sock, marker, version); zebra_client_close (client); return -1; } if (length < ZEBRA_HEADER_SIZE) { zlog_warn("%s: socket %d message length %u is less than header size %d", __func__, sock, length, ZEBRA_HEADER_SIZE); zebra_client_close (client); return -1; } if (length > STREAM_SIZE(client->ibuf)) { zlog_warn("%s: socket %d message length %u exceeds buffer size %lu", __func__, sock, length, (u_long)STREAM_SIZE(client->ibuf)); zebra_client_close (client); return -1; } /* Read rest of data. */ if (already < length) { ssize_t nbyte; if (((nbyte = stream_read_try (client->ibuf, sock, length-already)) == 0) || (nbyte == -1)) { if (IS_ZEBRA_DEBUG_EVENT) zlog_debug ("connection closed [%d] when reading zebra data", sock); zebra_client_close (client); return -1; } if (nbyte != (ssize_t)(length-already)) { /* Try again later. */ zebra_event (ZEBRA_READ, sock, client); return 0; } } length -= ZEBRA_HEADER_SIZE; /* Debug packet information. */ if (IS_ZEBRA_DEBUG_EVENT) zlog_debug ("zebra message comes from socket [%d]", sock); if (IS_ZEBRA_DEBUG_PACKET && IS_ZEBRA_DEBUG_RECV) zlog_debug ("zebra message received [%s] %d", zserv_command_string (command), length); switch (command) { case ZEBRA_ROUTER_ID_ADD: zread_router_id_add (client, length); break; case ZEBRA_ROUTER_ID_DELETE: zread_router_id_delete (client, length); break; case ZEBRA_INTERFACE_ADD: zread_interface_add (client, length); break; case ZEBRA_INTERFACE_DELETE: zread_interface_delete (client, length); break; case ZEBRA_IPV4_ROUTE_ADD: zread_ipv4_add (client, length); break; case ZEBRA_IPV4_ROUTE_DELETE: zread_ipv4_delete (client, length); break; #ifdef HAVE_IPV6 case ZEBRA_IPV6_ROUTE_ADD: zread_ipv6_add (client, length); break; case ZEBRA_IPV6_ROUTE_DELETE: zread_ipv6_delete (client, length); break; #endif /* HAVE_IPV6 */ case ZEBRA_REDISTRIBUTE_ADD: zebra_redistribute_add (command, client, length); break; case ZEBRA_REDISTRIBUTE_DELETE: zebra_redistribute_delete (command, client, length); break; case ZEBRA_REDISTRIBUTE_DEFAULT_ADD: zebra_redistribute_default_add (command, client, length); break; case ZEBRA_REDISTRIBUTE_DEFAULT_DELETE: zebra_redistribute_default_delete (command, client, length); break; case ZEBRA_IPV4_NEXTHOP_LOOKUP: zread_ipv4_nexthop_lookup (client, length); break; #ifdef HAVE_IPV6 case ZEBRA_IPV6_NEXTHOP_LOOKUP: zread_ipv6_nexthop_lookup (client, length); break; #endif /* HAVE_IPV6 */ case ZEBRA_IPV4_IMPORT_LOOKUP: zread_ipv4_import_lookup (client, length); break; case ZEBRA_HELLO: zread_hello (client); break; default: zlog_info ("Zebra received unknown command %d", command); break; } if (client->t_suicide) { /* No need to wait for thread callback, just kill immediately. */ zebra_client_close(client); return -1; } stream_reset (client->ibuf); zebra_event (ZEBRA_READ, sock, client); return 0; }
/* BGP Peer Incoming Connection Accept thread handler */ s_int32_t bpn_sock_accept (struct thread *t_accept) { struct bgp_listen_sock_lnode *tmp_lnode; struct bgp_peer_inconn_req *peer_icr; u_int8_t su_buf [SU_ADDRSTRLEN]; pal_sock_handle_t accept_sock; pal_sock_handle_t bgp_sock; struct lib_globals *blg; struct bgp_peer *peer; union sockunion su; struct bgp *bgp; s_int32_t ret; bgp_sock = THREAD_FD (t_accept); blg = THREAD_GLOB (t_accept); bgp = THREAD_ARG (t_accept); ret = 0; /* Sanity check thread variables */ if (! blg || &BLG != blg) { ret = -1; goto EXIT; } if (! bgp) { zlog_err (&BLG, "[NETWORK] Accept Thread: Invalid Vital Vars, " "blg(%p) bgp(%p)", blg, bgp); ret = -1; goto EXIT; } /* Verify integrity of thread variables */ for (tmp_lnode = bgp->listen_sock_lnode; tmp_lnode; tmp_lnode = tmp_lnode->next) { if (tmp_lnode->listen_sock == bgp_sock) break; } if (! tmp_lnode) { zlog_err (&BLG, "[NETWORK] Accept Thread: Mismatch in thread args" "blg(%p) bgp(%p)", blg, bgp); ret = -1; goto EXIT; } /* Set BGP VR Context */ BGP_SET_VR_CONTEXT (&BLG, bgp->owning_bvr); /* Re-regiser accept thread */ t_accept = NULL; BGP_READ_ON (&BLG, t_accept, bgp, bpn_sock_accept, bgp_sock); /* Update the Accept Thread List Node */ tmp_lnode->t_accept = t_accept; /* Accept Incoming Connection (Blocking) */ accept_sock = sockunion_accept (&BLG, bgp_sock, &su); if (accept_sock < 0) { zlog_err (&BLG, "[NETWORK] Accept Thread: accept() Failed for Server" " Sock %d, Err:%d-%s", bgp_sock, errno, pal_strerror (errno)); ret = -1; goto EXIT; } if (BGP_DEBUG (events, EVENTS)) zlog_info (&BLG, "[NETWORK] Accept Thread: Incoming conn from host" " %s (FD=%u)", inet_sutop (&su, su_buf), accept_sock); /* Search for Configured Peer with same Remote IP address */ peer = bgp_peer_search (bgp, &su); if (! peer) { if (BGP_DEBUG (events, EVENTS)) zlog_info (&BLG, "[NETWORK] Accept Thread: %s - No such Peer " "configured", inet_sutop (&su, su_buf)); SSOCK_FD_CLOSE (&BLG, accept_sock); ret = -1; goto EXIT; } /* Prepare an Incoming Connection Req. Info structure */ peer_icr = XCALLOC (MTYPE_TMP, sizeof (struct bgp_peer_inconn_req)); if (! peer_icr) { zlog_err (&BLG, "[NETWORK] Accept Thread:" " Cannot allocate memory (%d) @ %s:%d", sizeof (struct bgp_peer_inconn_req), __FILE__, __LINE__); SSOCK_FD_CLOSE (&BLG, accept_sock); ret = -1; goto EXIT; } /* Initialize the FIFO Node */ FIFO_INIT (&peer_icr->icr_fifo); /* Store the ICR Information */ peer_icr->icr_sock = accept_sock; switch (su.sa.sa_family) { case AF_INET: peer_icr->icr_port = su.sin.sin_port; break; #ifdef HAVE_IPV6 case AF_INET6: peer_icr->icr_port = su.sin6.sin6_port; break; #endif /* HAVE_IPV6 */ } /* Enqueue into Peer's 'bicr_fifo' */ FIFO_ADD (&peer->bicr_fifo, &peer_icr->icr_fifo); /* Generate BGP Peer FSM ICR Event */ BGP_PEER_FSM_EVENT_ADD (&BLG, peer, BPF_EVENT_TCP_CONN_VALID); EXIT: return ret; }
/* Accept bgp connection. */ static int bgp_accept (struct thread *thread) { int bgp_sock; int accept_sock; union sockunion su; struct bgp_listener *listener = THREAD_ARG(thread); struct peer *peer; struct peer *peer1; char buf[SU_ADDRSTRLEN]; /* Register accept thread. */ accept_sock = THREAD_FD (thread); if (accept_sock < 0) { zlog_err ("accept_sock is nevative value %d", accept_sock); return -1; } listener->thread = thread_add_read (master, bgp_accept, listener, accept_sock); /* Accept client connection. */ bgp_sock = sockunion_accept (accept_sock, &su); if (bgp_sock < 0) { zlog_err ("[Error] BGP socket accept failed (%s)", safe_strerror (errno)); return -1; } set_nonblocking (bgp_sock); /* Set socket send buffer size */ bgp_update_sock_send_buffer_size(bgp_sock); if (BGP_DEBUG (events, EVENTS)) zlog_debug ("[Event] BGP connection from host %s", inet_sutop (&su, buf)); /* Check remote IP address */ peer1 = peer_lookup (NULL, &su); if (! peer1 || peer1->status == Idle) { if (BGP_DEBUG (events, EVENTS)) { if (! peer1) zlog_debug ("[Event] BGP connection IP address %s is not configured", inet_sutop (&su, buf)); else zlog_debug ("[Event] BGP connection IP address %s is Idle state", inet_sutop (&su, buf)); } close (bgp_sock); return -1; } bgp_set_socket_ttl (peer1, bgp_sock); /* Make dummy peer until read Open packet. */ if (BGP_DEBUG (events, EVENTS)) zlog_debug ("[Event] Make dummy peer structure until read Open packet"); { char buf[SU_ADDRSTRLEN]; peer = peer_create_accept (peer1->bgp); SET_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER); peer->su = su; peer->fd = bgp_sock; peer->status = Active; peer->local_id = peer1->local_id; peer->v_holdtime = peer1->v_holdtime; peer->v_keepalive = peer1->v_keepalive; /* Make peer's address string. */ sockunion2str (&su, buf, SU_ADDRSTRLEN); peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf); } BGP_EVENT_ADD (peer, TCP_connection_open); return 0; }
/* passive peer socket accept */ static int pim_msdp_sock_accept(struct thread *thread) { union sockunion su; struct pim_instance *pim = THREAD_ARG(thread); int accept_sock; int msdp_sock; struct pim_msdp_peer *mp; char buf[SU_ADDRSTRLEN]; sockunion_init(&su); /* re-register accept thread */ accept_sock = THREAD_FD(thread); if (accept_sock < 0) { flog_err(LIB_ERR_DEVELOPMENT, "accept_sock is negative value %d", accept_sock); return -1; } pim->msdp.listener.thread = NULL; thread_add_read(master, pim_msdp_sock_accept, pim, accept_sock, &pim->msdp.listener.thread); /* accept client connection. */ msdp_sock = sockunion_accept(accept_sock, &su); if (msdp_sock < 0) { flog_err_sys(LIB_ERR_SOCKET, "pim_msdp_sock_accept failed (%s)", safe_strerror(errno)); return -1; } /* see if have peer config for this */ mp = pim_msdp_peer_find(pim, su.sin.sin_addr); if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) { ++pim->msdp.rejected_accepts; if (PIM_DEBUG_MSDP_EVENTS) { flog_err(PIM_ERR_MSDP_PACKET, "msdp peer connection refused from %s", sockunion2str(&su, buf, SU_ADDRSTRLEN)); } close(msdp_sock); return -1; } if (PIM_DEBUG_MSDP_INTERNAL) { zlog_debug("MSDP peer %s accept success%s", mp->key_str, mp->fd >= 0 ? "(dup)" : ""); } /* if we have an existing connection we need to kill that one * with this one */ if (mp->fd >= 0) { if (PIM_DEBUG_MSDP_EVENTS) { zlog_notice( "msdp peer new connection from %s stop old connection", sockunion2str(&su, buf, SU_ADDRSTRLEN)); } pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */); } mp->fd = msdp_sock; set_nonblocking(mp->fd); pim_msdp_update_sock_send_buffer_size(mp->fd); pim_msdp_peer_established(mp); return 0; }
int shim_sisis_read(struct thread * thread) { struct sisis_listener *listener; int sisis_sock; uint16_t length, command, checksum; int already; u_int ifindex; struct shim_interface * si; struct in6_addr src; char src_buf[INET6_ADDRSTRLEN]; struct in6_addr dst; char dst_buf[INET6_ADDRSTRLEN]; zlog_notice("Reading packet from SISIS connection!\n"); /* first of all get listener pointer. */ listener = THREAD_ARG (thread); sisis_sock = THREAD_FD (thread); if ((already = stream_get_endp(listener->ibuf)) < SV_HEADER_SIZE) { ssize_t nbytes; if (((nbytes = stream_read_try (listener->ibuf, sisis_sock, SV_HEADER_SIZE-already)) == 0) || (nbytes == -1)) { return -1; } if(nbytes != (SV_HEADER_SIZE - already)) { listener->thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); return 0; } already = SV_HEADER_SIZE; } stream_set_getp(listener->ibuf, 0); /* read header packet. */ length = stream_getw (listener->ibuf); command = stream_getw (listener->ibuf); // will be 0 so may be discarded stream_get (&src, listener->ibuf, sizeof (struct in6_addr)); stream_get (&dst, listener->ibuf, sizeof (struct in6_addr)); ifindex = stream_getl(listener->ibuf); checksum = stream_getw(listener->ibuf); inet_ntop(AF_INET6, &src, src_buf, sizeof(src_buf)); inet_ntop(AF_INET6, &dst, dst_buf, sizeof(dst_buf)); zlog_debug("SISIS: length: %d, command: %d, ifindex: %d, checksum: %d sock %d, src: %s, dst: %s\n", length, command, ifindex, checksum, sisis_sock, src_buf, dst_buf); if(length > STREAM_SIZE(listener->ibuf)) { struct stream * ns; zlog_warn("message size exceeds buffer size"); ns = stream_new(length); stream_copy(ns, listener->ibuf); stream_free(listener->ibuf); listener->ibuf = ns; } if(already < length) { ssize_t nbytes; if(((nbytes = stream_read_try(listener->ibuf, sisis_sock, length-already)) == 0) || nbytes == -1) { return -1; } if(nbytes != (length-already)) { listener->thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); return 0; } } length -= SV_HEADER_SIZE; switch(command) { case SV_JOIN_ALLSPF: zlog_debug("join allspf received"); shim_join_allspfrouters (ifindex); break; case SV_LEAVE_ALLSPF: zlog_debug("leave allspf received"); shim_leave_allspfrouters (ifindex); zlog_debug("index: %d\n", ifindex); break; case SV_JOIN_ALLD: zlog_debug("join alld received"); shim_join_alldrouters (ifindex); zlog_debug("index: %d", ifindex); break; case SV_LEAVE_ALLD: zlog_debug("leave alld received"); shim_leave_alldrouters (ifindex); zlog_debug("index: %d", ifindex); break; case SV_MESSAGE: zlog_debug("SISIS message received"); unsigned int num_of_addrs = number_of_sisis_addrs_for_process_type(SISIS_PTYPE_RIBCOMP_OSPF6); unsigned int num_of_listeners = number_of_listeners(); zlog_debug("num of listeners: %d, num of addrs: %d", num_of_listeners, num_of_addrs); float received_ratio = num_of_listeners/num_of_addrs; listener->chksum = checksum; if(received_ratio > (1/2)) { if(are_checksums_same()) { si = shim_interface_lookup_by_ifindex (ifindex); reset_checksums(); shim_send(&src, &dst, si, listener->ibuf, length); // shim_send(si->linklocal_addr, &dst, si, listener->ibuf, length); } else { zlog_notice("Checksums are not all the same"); } } else { zlog_notice("Not enough processes have sent their data: buffering ..."); } break; default: break; } if (sisis_sock < 0) /* Connection was closed during packet processing. */ return -1; /* Register read thread. */ stream_reset(listener->ibuf); /* prepare for next packet. */ listener->thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock); return 0; }
/* Kernel routing table and interface updates via routing socket. */ int kernel_read (struct thread *thread) { int sock; int nbytes; struct rt_msghdr *rtm; union { /* Routing information. */ struct { struct rt_msghdr rtm; struct sockaddr addr[RTAX_MAX]; } r; /* Interface information. */ struct { struct if_msghdr ifm; struct sockaddr addr[RTAX_MAX]; } im; /* Interface address information. */ struct { struct ifa_msghdr ifa; struct sockaddr addr[RTAX_MAX]; } ia; #ifdef RTM_IFANNOUNCE /* Interface arrival/departure */ struct { struct if_announcemsghdr ifan; struct sockaddr addr[RTAX_MAX]; } ian; #endif /* RTM_IFANNOUNCE */ } buf; /* Fetch routing socket. */ sock = THREAD_FD (thread); nbytes= read (sock, &buf, sizeof buf); if (nbytes <= 0) { if (nbytes < 0 && errno != EWOULDBLOCK) zlog_warn ("routing socket error: %s", strerror (errno)); return 0; } thread_add_read (master, kernel_read, NULL, sock); #ifdef DEBUG rtmsg_debug (&buf.r.rtm); #endif /* DEBUG */ rtm = &buf.r.rtm; switch (rtm->rtm_type) { case RTM_ADD: case RTM_DELETE: rtm_read (rtm); break; case RTM_IFINFO: ifm_read (&buf.im.ifm); break; case RTM_NEWADDR: case RTM_DELADDR: ifam_read (&buf.ia.ifa); break; #ifdef RTM_IFANNOUNCE case RTM_IFANNOUNCE: ifan_read (&buf.ian.ifan); break; #endif /* RTM_IFANNOUNCE */ default: break; } return 0; }
static int pim_sock_read(struct thread *t) { struct interface *ifp; struct pim_interface *pim_ifp; int fd; struct sockaddr_in from; struct sockaddr_in to; socklen_t fromlen = sizeof(from); socklen_t tolen = sizeof(to); uint8_t buf[PIM_PIM_BUFSIZE_READ]; int len; int ifindex = -1; int result = -1; /* defaults to bad */ zassert(t); ifp = THREAD_ARG(t); zassert(ifp); fd = THREAD_FD(t); pim_ifp = ifp->info; zassert(pim_ifp); zassert(fd == pim_ifp->pim_sock_fd); len = pim_socket_recvfromto(fd, buf, sizeof(buf), &from, &fromlen, &to, &tolen, &ifindex); if (len < 0) { zlog_warn("Failure receiving IP PIM packet on fd=%d: errno=%d: %s", fd, errno, safe_strerror(errno)); goto done; } if (PIM_DEBUG_PIM_PACKETS) { char from_str[100]; char to_str[100]; if (!inet_ntop(AF_INET, &from.sin_addr, from_str, sizeof(from_str))) sprintf(from_str, "<from?>"); if (!inet_ntop(AF_INET, &to.sin_addr, to_str, sizeof(to_str))) sprintf(to_str, "<to?>"); zlog_debug("Recv IP PIM pkt size=%d from %s to %s on fd=%d on ifindex=%d (sock_ifindex=%d)", len, from_str, to_str, fd, ifindex, ifp->ifindex); } if (PIM_DEBUG_PIM_PACKETDUMP_RECV) { pim_pkt_dump(__PRETTY_FUNCTION__, buf, len); } #ifdef PIM_CHECK_RECV_IFINDEX_SANITY /* ifindex sanity check */ if (ifindex != (int) ifp->ifindex) { char from_str[100]; char to_str[100]; struct interface *recv_ifp; if (!inet_ntop(AF_INET, &from.sin_addr, from_str , sizeof(from_str))) sprintf(from_str, "<from?>"); if (!inet_ntop(AF_INET, &to.sin_addr, to_str , sizeof(to_str))) sprintf(to_str, "<to?>"); recv_ifp = if_lookup_by_index(ifindex); if (recv_ifp) { zassert(ifindex == (int) recv_ifp->ifindex); } #ifdef PIM_REPORT_RECV_IFINDEX_MISMATCH zlog_warn("Interface mismatch: recv PIM pkt from %s to %s on fd=%d: recv_ifindex=%d (%s) sock_ifindex=%d (%s)", from_str, to_str, fd, ifindex, recv_ifp ? recv_ifp->name : "<if-notfound>", ifp->ifindex, ifp->name); #endif goto done; } #endif int fail = pim_pim_packet(ifp, buf, len); if (fail) { zlog_warn("%s: pim_pim_packet() return=%d", __PRETTY_FUNCTION__, fail); goto done; } result = 0; /* good */ done: pim_sock_read_on(ifp); if (result) { ++pim_ifp->pim_ifstat_hello_recvfail; } return result; }