Пример #1
0
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;
}
Пример #2
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 ;
}
Пример #3
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;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
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;
}
Пример #10
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;
}
Пример #11
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;
}
Пример #12
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;
}
Пример #13
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);
}
Пример #14
0
/* 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;
}
Пример #15
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;
}
Пример #16
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;
}
Пример #17
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;
}
Пример #18
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;
}
Пример #19
0
/* 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;
}
Пример #20
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;
}
Пример #21
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;
}
Пример #22
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;
}
Пример #23
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;
}
Пример #24
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;
}
Пример #25
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;
}
Пример #27
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;
}
Пример #28
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;
}
Пример #29
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;
}
Пример #30
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;
}