示例#1
0
int
netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
    int len;
    struct ifinfomsg *ifi;
    struct rtattr *tb [IFLA_MAX + 1];
    struct interface *ifp;
    char *name;

    ifi = NLMSG_DATA (h);

    if (! (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
    {
        /* If this is not link add/delete message so print warning. */
        zlog_warn ("netlink_link_change: wrong kernel message %d\n",
                   h->nlmsg_type);
        return 0;
    }

    len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
    if (len < 0)
        return -1;

    /* Looking up interface name. */
    memset (tb, 0, sizeof tb);
    netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);
    if (tb[IFLA_IFNAME] == NULL)
        return -1;
    name = (char *)RTA_DATA(tb[IFLA_IFNAME]);

    /* Add interface. */
    if (h->nlmsg_type == RTM_NEWLINK)
    {
        ifp = if_lookup_by_name (name);

        if (ifp == NULL || ! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
        {
            if (ifp == NULL)
                ifp = if_get_by_name (name);

            ifp->ifindex = ifi->ifi_index;
            ifp->flags = ifi->ifi_flags & 0x0000fffff;
            ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
            ifp->metric = 1;

            /* If new link is added. */
            if_add_update(ifp);
        }
        else
        {
            /* Interface status change. */
            ifp->ifindex = ifi->ifi_index;
            ifp->mtu = *(int *)RTA_DATA (tb[IFLA_MTU]);
            ifp->metric = 1;

            if (if_is_up (ifp))
            {
                ifp->flags = ifi->ifi_flags & 0x0000fffff;
                if (! if_is_up (ifp))
                    if_down (ifp);
            }
            else
            {
                ifp->flags = ifi->ifi_flags & 0x0000fffff;
                if (if_is_up (ifp))
                    if_up (ifp);
            }
        }
    }
    else
    {
        /* RTM_DELLINK. */
        ifp = if_lookup_by_name (name);

        if (ifp == NULL)
        {
            zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
                  ifp->name);
            return 0;
        }

        if_delete_update (ifp);
    }

    return 0;
}
示例#2
0
/* Interface's address information get. */
int
ifam_read (struct ifa_msghdr *ifam)
{
  struct interface *ifp = NULL;
  union sockunion addr, mask, brd;
  char ifname[INTERFACE_NAMSIZ];
  short ifnlen = 0;
  char isalias = 0;
  int flags = 0;
  
  ifname[0] = ifname[INTERFACE_NAMSIZ - 1] = '\0';
  
  /* Allocate and read address information. */
  ifam_read_mesg (ifam, &addr, &mask, &brd, ifname, &ifnlen);
  
  if ((ifp = if_lookup_by_index(ifam->ifam_index)) == NULL)
    {
      zlog_warn ("%s: no interface for ifname %s, index %d", 
                 __func__, ifname, ifam->ifam_index);
      return -1;
    }
  
  if (ifnlen && strncmp (ifp->name, ifname, INTERFACE_NAMSIZ))
    isalias = 1;
  
  /* N.B. The info in ifa_msghdr does not tell us whether the RTA_BRD
     field contains a broadcast address or a peer address, so we are forced to
     rely upon the interface type. */
  if (if_is_pointopoint(ifp))
    SET_FLAG(flags, ZEBRA_IFA_PEER);

#if 0
  /* it might seem cute to grab the interface metric here, however
   * we're processing an address update message, and so some systems
   * (e.g. FBSD) dont bother to fill in ifam_metric. Disabled, but left
   * in deliberately, as comment.
   */
  ifp->metric = ifam->ifam_metric;
#endif

  /* Add connected address. */
  switch (sockunion_family (&addr))
    {
    case AF_INET:
      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv4 (ifp, flags, &addr.sin.sin_addr, 
			    ip_masklen (mask.sin.sin_addr),
			    &brd.sin.sin_addr,
			    (isalias ? ifname : NULL));
      else
	connected_delete_ipv4 (ifp, flags, &addr.sin.sin_addr, 
			       ip_masklen (mask.sin.sin_addr),
			       &brd.sin.sin_addr);
      break;
#ifdef HAVE_IPV6
    case AF_INET6:
      /* Unset interface index from link-local address when IPv6 stack
	 is KAME. */
      if (IN6_IS_ADDR_LINKLOCAL (&addr.sin6.sin6_addr))
	SET_IN6_LINKLOCAL_IFINDEX (addr.sin6.sin6_addr, 0);

      if (ifam->ifam_type == RTM_NEWADDR)
	connected_add_ipv6 (ifp, flags, &addr.sin6.sin6_addr, 
			    ip6_masklen (mask.sin6.sin6_addr),
			    &brd.sin6.sin6_addr,
			    (isalias ? ifname : NULL));
      else
	connected_delete_ipv6 (ifp,
			       &addr.sin6.sin6_addr, 
			       ip6_masklen (mask.sin6.sin6_addr),
			       &brd.sin6.sin6_addr);
      break;
#endif /* HAVE_IPV6 */
    default:
      /* Unsupported family silently ignore... */
      break;
    }
  
  /* Check interface flag for implicit up of the interface. */
  if_refresh (ifp);

#ifdef SUNOS_5
  /* In addition to lacking IFANNOUNCE, on SUNOS IFF_UP is strange. 
   * See comments for SUNOS_5 in interface.c::if_flags_mangle.
   * 
   * Here we take care of case where the real IFF_UP was previously
   * unset (as kept in struct zebra_if.primary_state) and the mangled
   * IFF_UP (ie IFF_UP set || listcount(connected) has now transitioned
   * to unset due to the lost non-primary address having DELADDR'd.
   *
   * we must delete the interface, because in between here and next
   * event for this interface-name the administrator could unplumb
   * and replumb the interface.
   */
  if (!if_is_up (ifp))
    if_delete_update (ifp);
#endif /* SUNOS_5 */
  
  return 0;
}
示例#3
0
static int open_dlpi_dev(struct isis_circuit *circuit)
{
	int fd = -1, unit, retval;
	char devpath[MAXPATHLEN];
	dl_info_ack_t *dia = (dl_info_ack_t *)dlpi_ctl;
	ssize_t acklen;

	/* Only broadcast-type are supported at the moment */
	if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
		zlog_warn("%s: non-broadcast interface %s", __func__,
			  circuit->interface->name);
		return ISIS_WARNING;
	}

	/* Try the vanity node first, if permitted */
	if (getenv("DLPI_DEVONLY") == NULL) {
		(void)snprintf(devpath, sizeof(devpath), "/dev/net/%s",
			       circuit->interface->name);
		fd = dlpiopen(devpath, &acklen);
	}

	/* Now try as an ordinary Style 1 node */
	if (fd == -1) {
		(void)snprintf(devpath, sizeof(devpath), "/dev/%s",
			       circuit->interface->name);
		unit = -1;
		fd = dlpiopen(devpath, &acklen);
	}

	/* If that fails, try again as Style 2 */
	if (fd == -1) {
		char *cp;

		cp = devpath + strlen(devpath);
		while (--cp >= devpath && isdigit(*cp))
			;
		unit = strtol(cp, NULL, 0);
		*cp = '\0';
		fd = dlpiopen(devpath, &acklen);

		/* If that too fails, then the device really doesn't exist */
		if (fd == -1) {
			zlog_warn("%s: unknown interface %s", __func__,
				  circuit->interface->name);
			return ISIS_WARNING;
		}

		/* Double check the DLPI style */
		if (dia->dl_provider_style != DL_STYLE2) {
			zlog_warn(
				"open_dlpi_dev(): interface %s: %s is not style 2",
				circuit->interface->name, devpath);
			close(fd);
			return ISIS_WARNING;
		}

		/* If it succeeds, then we need to attach to the unit specified
		 */
		dlpiattach(fd, unit);

		/* Reget the information, as it may be different per node */
		if ((acklen = dlpiinfo(fd)) == -1) {
			close(fd);
			return ISIS_WARNING;
		}
	} else {
		/* Double check the DLPI style */
		if (dia->dl_provider_style != DL_STYLE1) {
			zlog_warn(
				"open_dlpi_dev(): interface %s: %s is not style 1",
				circuit->interface->name, devpath);
			close(fd);
			return ISIS_WARNING;
		}
	}

	/* Check that the interface we've got is the kind we expect */
	if ((dia->dl_sap_length != 2 && dia->dl_sap_length != -2)
	    || dia->dl_service_mode != DL_CLDLS
	    || dia->dl_addr_length != ETHERADDRL + 2
	    || dia->dl_brdcst_addr_length != ETHERADDRL) {
		zlog_warn("%s: unsupported interface type for %s", __func__,
			  circuit->interface->name);
		close(fd);
		return ISIS_WARNING;
	}
	switch (dia->dl_mac_type) {
	case DL_CSMACD:
	case DL_ETHER:
	case DL_100VG:
	case DL_100VGTPR:
	case DL_ETH_CSMA:
	case DL_100BT:
		break;
	default:
		zlog_warn("%s: unexpected mac type on %s: %lld", __func__,
			  circuit->interface->name,
			  (long long)dia->dl_mac_type);
		close(fd);
		return ISIS_WARNING;
	}

	circuit->sap_length = dia->dl_sap_length;

	/*
	 * The local hardware address is something that should be provided by
	 * way of
	 * sockaddr_dl for the interface, but isn't on Solaris.  We set it here
	 * based
	 * on DLPI's reported address to avoid roto-tilling the world.
	 * (Note that isis_circuit_if_add on Solaris doesn't set the snpa.)
	 *
	 * Unfortunately, GLD is broken and doesn't provide the address after
	 * attach,
	 * so we need to be careful and use DL_PHYS_ADDR_REQ instead.
	 */
	if (dlpiaddr(fd, circuit->u.bc.snpa) == -1) {
		zlog_warn(
			"open_dlpi_dev(): interface %s: unable to get MAC address",
			circuit->interface->name);
		close(fd);
		return ISIS_WARNING;
	}

	/* Now bind to SAP 0.  This gives us 802-type traffic. */
	if (dlpibind(fd) == -1) {
		zlog_warn("%s: cannot bind SAP 0 on %s", __func__,
			  circuit->interface->name);
		close(fd);
		return ISIS_WARNING;
	}

	/*
	 * Join to multicast groups according to
	 * 8.4.2 - Broadcast subnetwork IIH PDUs
	 */
	retval = 0;
	retval |= dlpimcast(fd, ALL_L1_ISS);
	retval |= dlpimcast(fd, ALL_ISS);
	retval |= dlpimcast(fd, ALL_L2_ISS);

	if (retval != 0) {
		zlog_warn("%s: unable to join multicast on %s", __func__,
			  circuit->interface->name);
		close(fd);
		return ISIS_WARNING;
	}

	/* Push on the packet filter to avoid stray 802 packets */
	if (ioctl(fd, I_PUSH, "pfmod") == 0) {
		struct packetfilt pfil;
		struct strioctl sioc;

		pfil.Pf_Priority = 0;
		pfil.Pf_FilterLen = sizeof(pf_filter) / sizeof(unsigned short);
		memcpy(pfil.Pf_Filter, pf_filter, sizeof(pf_filter));
		/* pfmod does not support transparent ioctls */
		sioc.ic_cmd = PFIOCSETF;
		sioc.ic_timout = 5;
		sioc.ic_len = sizeof(struct packetfilt);
		sioc.ic_dp = (char *)&pfil;
		if (ioctl(fd, I_STR, &sioc) == -1)
			zlog_warn("%s: could not perform PF_IOCSETF on %s",
				  __func__, circuit->interface->name);
	}

	circuit->fd = fd;

	return ISIS_OK;
}
示例#4
0
文件: connected.c 项目: yubo/quagga
/* Add connected IPv4 route to the interface. */
void
connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
		   u_char prefixlen, struct in_addr *broad, const char *label)
{
	struct prefix_ipv4 *p;
	struct connected *ifc;

	/* Make connected structure. */
	ifc = connected_new();
	ifc->ifp = ifp;
	ifc->flags = flags;
	/* If we get a notification from the kernel,
	 * we can safely assume the address is known to the kernel */
	SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);

	/* Allocate new connected address. */
	p = prefix_ipv4_new();
	p->family = AF_INET;
	p->prefix = *addr;
	p->prefixlen = prefixlen;
	ifc->address = (struct prefix *)p;

	/* If there is broadcast or peer address. */
	if (broad) {
		p = prefix_ipv4_new();
		p->family = AF_INET;
		p->prefix = *broad;
		p->prefixlen = prefixlen;
		ifc->destination = (struct prefix *)p;

		/* validate the destination address */
		if (CONNECTED_PEER(ifc)) {
			if (IPV4_ADDR_SAME(addr, broad))
				zlog_warn
				    ("warning: interface %s has same local and peer "
				     "address %s, routing protocols may malfunction",
				     ifp->name, inet_ntoa(*addr));
		} else {
			if (broad->s_addr !=
			    ipv4_broadcast_addr(addr->s_addr, prefixlen)) {
				char buf[2][INET_ADDRSTRLEN];
				struct in_addr bcalc;
				bcalc.s_addr =
				    ipv4_broadcast_addr(addr->s_addr,
							prefixlen);
				zlog_warn
				    ("warning: interface %s broadcast addr %s/%d != "
				     "calculated %s, routing protocols may malfunction",
				     ifp->name, inet_ntop(AF_INET, broad,
							  buf[0],
							  sizeof(buf[0])),
				     prefixlen, inet_ntop(AF_INET, &bcalc,
							  buf[1],
							  sizeof(buf[1])));
			}
		}

	} else {
		if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
			zlog_warn("warning: %s called for interface %s "
				  "with peer flag set, but no peer address supplied",
				  __func__, ifp->name);
			UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
		}

		/* no broadcast or destination address was supplied */
		if ((prefixlen == IPV4_MAX_PREFIXLEN) && if_is_pointopoint(ifp))
			zlog_warn
			    ("warning: PtP interface %s with addr %s/%d needs a "
			     "peer address", ifp->name, inet_ntoa(*addr),
			     prefixlen);
	}

	/* Label of this address. */
	if (label)
		ifc->label = XSTRDUP(MTYPE_CONNECTED_LABEL, label);

	/* For all that I know an IPv4 address is always ready when we receive
	 * the notification. So it should be safe to set the REAL flag here. */
	SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);

	connected_update(ifp, ifc);
}
示例#5
0
/*
 * Handle struct if_msghdr obtained from reading routing socket or
 * sysctl (from interface_list).  There may or may not be sockaddrs
 * present after the header.
 */
int
ifm_read (struct if_msghdr *ifm)
{
  struct interface *ifp = NULL;
  char ifname[IFNAMSIZ];
  short ifnlen = 0;
  caddr_t *cp;
  
  /* terminate ifname at head (for strnlen) and tail (for safety) */
  ifname[IFNAMSIZ - 1] = '\0';
  
  /* paranoia: sanity check structure */
  if (ifm->ifm_msglen < sizeof(struct if_msghdr))
    {
      zlog_err ("ifm_read: ifm->ifm_msglen %d too short\n",
		ifm->ifm_msglen);
      return -1;
    }

  /*
   * Check for a sockaddr_dl following the message.  First, point to
   * where a socakddr might be if one follows the message.
   */
  cp = (void *)(ifm + 1);

#ifdef SUNOS_5
  /* 
   * XXX This behavior should be narrowed to only the kernel versions
   * for which the structures returned do not match the headers.
   *
   * if_msghdr_t on 64 bit kernels in Solaris 9 and earlier versions
   * is 12 bytes larger than the 32 bit version.
   */
  if (((struct sockaddr *) cp)->sa_family == AF_UNSPEC)
  	cp = cp + 12;
#endif

  RTA_ADDR_GET (NULL, RTA_DST, ifm->ifm_addrs, cp);
  RTA_ADDR_GET (NULL, RTA_GATEWAY, ifm->ifm_addrs, cp);
  RTA_ATTR_GET (NULL, RTA_NETMASK, ifm->ifm_addrs, cp);
  RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifm_addrs, cp);
  RTA_NAME_GET (ifname, RTA_IFP, ifm->ifm_addrs, cp, ifnlen);
  RTA_ADDR_GET (NULL, RTA_IFA, ifm->ifm_addrs, cp);
  RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifm_addrs, cp);
  RTA_ADDR_GET (NULL, RTA_BRD, ifm->ifm_addrs, cp);
  
  if (IS_ZEBRA_DEBUG_KERNEL)
    zlog_debug ("%s: sdl ifname %s", __func__, (ifnlen ? ifname : "(nil)"));
  
  /* 
   * Look up on ifindex first, because ifindices are the primary handle for
   * interfaces across the user/kernel boundary, for most systems.  (Some
   * messages, such as up/down status changes on NetBSD, do not include a
   * sockaddr_dl).
   */
  if ( (ifp = if_lookup_by_index (ifm->ifm_index)) != NULL )
    {
      /* we have an ifp, verify that the name matches as some systems,
       * eg Solaris, have a 1:many association of ifindex:ifname
       * if they dont match, we dont have the correct ifp and should
       * set it back to NULL to let next check do lookup by name
       */
      if (ifnlen && (strncmp (ifp->name, ifname, IFNAMSIZ) != 0) )
        {
          if (IS_ZEBRA_DEBUG_KERNEL)
            zlog_debug ("%s: ifp name %s doesnt match sdl name %s",
                        __func__, ifp->name, ifname);
          ifp = NULL;
        }
    }
  
  /* 
   * If we dont have an ifp, try looking up by name.  Particularly as some
   * systems (Solaris) have a 1:many mapping of ifindex:ifname - the ifname
   * is therefore our unique handle to that interface.
   *
   * Interfaces specified in the configuration file for which the ifindex
   * has not been determined will have ifindex == IFINDEX_INTERNAL, and such
   * interfaces are found by this search, and then their ifindex values can
   * be filled in.
   */
  if ( (ifp == NULL) && ifnlen)
    ifp = if_lookup_by_name (ifname);

  /*
   * If ifp still does not exist or has an invalid index (IFINDEX_INTERNAL),
   * create or fill in an interface.
   */
  if ((ifp == NULL) || (ifp->ifindex == IFINDEX_INTERNAL))
    {
      /*
       * To create or fill in an interface, a sockaddr_dl (via
       * RTA_IFP) is required.
       */
      if (!ifnlen)
	{
	  zlog_warn ("Interface index %d (new) missing ifname\n",
		     ifm->ifm_index);
	  return -1;
	}

#ifndef RTM_IFANNOUNCE
      /* Down->Down interface should be ignored here.
       * See further comment below.
       */
      if (!CHECK_FLAG (ifm->ifm_flags, IFF_UP))
        return 0;
#endif /* !RTM_IFANNOUNCE */
      
      if (ifp == NULL)
        {
	  /* Interface that zebra was not previously aware of, so create. */ 
	  ifp = if_create (ifname, ifnlen);
	  if (IS_ZEBRA_DEBUG_KERNEL)
	    zlog_debug ("%s: creating ifp for ifindex %d", 
	                __func__, ifm->ifm_index);
        }

      if (IS_ZEBRA_DEBUG_KERNEL)
        zlog_debug ("%s: updated/created ifp, ifname %s, ifindex %d",
                    __func__, ifp->name, ifp->ifindex);
      /* 
       * Fill in newly created interface structure, or larval
       * structure with ifindex IFINDEX_INTERNAL.
       */
      ifp->ifindex = ifm->ifm_index;
      
#ifdef HAVE_BSD_LINK_DETECT /* translate BSD kernel msg for link-state */
      bsd_linkdetect_translate(ifm);
#endif /* HAVE_BSD_LINK_DETECT */

      if_flags_update (ifp, ifm->ifm_flags);
#if defined(__bsdi__)
      if_kvm_get_mtu (ifp);
#else
      if_get_mtu (ifp);
#endif /* __bsdi__ */
      if_get_metric (ifp);

      if_add_update (ifp);
    }
  else
    /*
     * Interface structure exists.  Adjust stored flags from
     * notification.  If interface has up->down or down->up
     * transition, call state change routines (to adjust routes,
     * notify routing daemons, etc.).  (Other flag changes are stored
     * but apparently do not trigger action.)
     */
    {
      if (ifp->ifindex != ifm->ifm_index)
        {
          zlog_warn ("%s: index mismatch, ifname %s, ifp index %d, "
                     "ifm index %d", 
                     __func__, ifp->name, ifp->ifindex, ifm->ifm_index);
          return -1;
        }
      
#ifdef HAVE_BSD_LINK_DETECT /* translate BSD kernel msg for link-state */
      bsd_linkdetect_translate(ifm);
#endif /* HAVE_BSD_LINK_DETECT */

      /* update flags and handle operative->inoperative transition, if any */
      if_flags_update (ifp, ifm->ifm_flags);
      
#ifndef RTM_IFANNOUNCE
      if (!if_is_up (ifp))
          {
            /* No RTM_IFANNOUNCE on this platform, so we can never
             * distinguish between ~IFF_UP and delete. We must presume
             * it has been deleted.
             * Eg, Solaris will not notify us of unplumb.
             *
             * XXX: Fixme - this should be runtime detected
             * So that a binary compiled on a system with IFANNOUNCE
             * will still behave correctly if run on a platform without
             */
            if_delete_update (ifp);
          }
#endif /* RTM_IFANNOUNCE */
      if (if_is_up (ifp))
      {
#if defined(__bsdi__)
        if_kvm_get_mtu (ifp);
#else
        if_get_mtu (ifp);
#endif /* __bsdi__ */
        if_get_metric (ifp);
      }
    }

#ifdef HAVE_NET_RT_IFLIST
  ifp->stats = ifm->ifm_data;
#endif /* HAVE_NET_RT_IFLIST */

  if (IS_ZEBRA_DEBUG_KERNEL)
    zlog_debug ("%s: interface %s index %d", 
                __func__, ifp->name, ifp->ifindex);

  return 0;
}
示例#6
0
/* Parse SMUX message. */
int
smux_parse (char *ptr, size_t len)
{
  /* This buffer we'll use for SOUT message. We could allocate it with
     malloc and save only static pointer/lenght, but IMHO static
     buffer is a faster solusion. */
  static u_char sout_save_buff[SMUXMAXPKTSIZE];
  static int sout_save_len = 0;

  int len_income = len; /* see note below: YYY */
  u_char type;
  u_char rollback;

  rollback = ptr[2]; /* important only for SMUX_SOUT */

process_rest: /* see note below: YYY */

  /* Parse SMUX message type and subsequent length. */
  ptr = asn_parse_header (ptr, &len, &type);

  if (debug_smux)
    zlog_debug ("SMUX message received type: %d rest len: %ld", type, len);

  switch (type)
    {
    case SMUX_OPEN:
      /* Open must be not send from SNMP agent. */
      zlog_warn ("SMUX_OPEN received: resetting connection.");
      return -1;
      break;
    case SMUX_RREQ:
      /* SMUX_RREQ message is invalid for us. */
      zlog_warn ("SMUX_RREQ received: resetting connection.");
      return -1;
      break;
    case SMUX_SOUT:
      /* SMUX_SOUT message is now valied for us. */
      if (debug_smux)
        zlog_debug ("SMUX_SOUT(%s)", rollback ? "rollback" : "commit");

      if (sout_save_len > 0)
        {
          smux_parse_set (sout_save_buff, sout_save_len, rollback ? FREE : COMMIT);
          sout_save_len = 0;
        }
      else
        zlog_warn ("SMUX_SOUT sout_save_len=%d - invalid", (int) sout_save_len);

      if (len_income > 3) 
        {
          /* YYY: this strange code has to solve the "slow peer"
             problem: When agent sends SMUX_SOUT message it doesn't
             wait any responce and may send some next message to
             subagent. Then the peer in 'smux_read()' will recieve
             from socket the 'concatenated' buffer, contaning both
             SMUX_SOUT message and the next one
             (SMUX_GET/SMUX_GETNEXT/SMUX_GET). So we should check: if
             the buffer is longer than 3 ( length of SMUX_SOUT ), we
             must process the rest of it.  This effect may be observed
             if 'debug_smux' is set to '1' */
          ptr++;
          len = len_income - 3;
          goto process_rest;
        }
      break;
    case SMUX_GETRSP:
      /* SMUX_GETRSP message is invalid for us. */
      zlog_warn ("SMUX_GETRSP received: resetting connection.");
      return -1;
      break;
    case SMUX_CLOSE:
      /* Close SMUX connection. */
      if (debug_smux)
	zlog_debug ("SMUX_CLOSE");
      smux_parse_close (ptr, len);
      return -1;
      break;
    case SMUX_RRSP:
      /* This is response for register message. */
      if (debug_smux)
	zlog_debug ("SMUX_RRSP");
      smux_parse_rrsp (ptr, len);
      break;
    case SMUX_GET:
      /* Exact request for object id. */
      if (debug_smux)
	zlog_debug ("SMUX_GET");
      smux_parse_get (ptr, len, 1);
      break;
    case SMUX_GETNEXT:
      /* Next request for object id. */
      if (debug_smux)
	zlog_debug ("SMUX_GETNEXT");
      smux_parse_get (ptr, len, 0);
      break;
    case SMUX_SET:
      /* SMUX_SET is supported with some limitations. */
      if (debug_smux)
	zlog_debug ("SMUX_SET");

      /* save the data for future SMUX_SOUT */
      memcpy (sout_save_buff, ptr, len);
      sout_save_len = len;
      smux_parse_set (ptr, len, RESERVE1);
      break;
    default:
      zlog_info ("Unknown type: %d", type);
      break;
    }
  return 0;
}
示例#7
0
static int sys_func_dl_prepare(int slot_id, uint64_t blk_start, uint64_t blk_num, uint32_t req_frag)
{
    int ret;
    sys_ctx_t* ctx = &sys_ctx;
    int repo_num = ctx->vault->repo_num;
    size_t cache_sz = SYS_CACHE_SIZE;
    int i, j;
    int interlace_sz = SYS_INTERLACE_SIZE;

    sys_cache_t* file_cache = ctx->file_cache;
    assert(file_cache);
    assert(file_cache->data);

    // get slot_sz
    ssize_t slot_sz;
    if (file_cache->slot_id == slot_id ) {
        slot_sz = file_cache->slot_sz;
    } else {
        slot_sz = dfv_vault_get_slotsize(ctx->vault, slot_id);
        if (slot_sz < 0) {
            zlog_error(sys_zc, "bad file size: slot_id=%d", slot_id);
            return(SPKERR_BADRES);
        }
    }

    // request region
    uint64_t req_start = blk_start * SYS_CACHE_SIZE;
    uint64_t req_end = (blk_num>0)?(req_start + blk_num * SYS_CACHE_SIZE):slot_sz;

    // frag region
    uint64_t frag_start = req_start + (uint64_t)req_frag * CMI_MAX_FRAGSIZE;
    uint64_t frag_end = frag_start + CMI_MAX_FRAGSIZE;

    // check if region is valid
    if (frag_start > slot_sz) {
        zlog_error(sys_zc, "illegal frag_start: slot_id=%d, slot_sz=%zu, "
                   "frag_start=%lu, req_frag=%u",
                   slot_id, slot_sz, frag_start, req_frag);
        return(SPKERR_PARAM);
    }

    if (frag_end > slot_sz) {
        zlog_warn(sys_zc, "truncate frag: slot_id=%d, slot_sz=%zu, "
                  "frag=%lu+%lu",
                  slot_id, slot_sz, frag_start, frag_end);
        frag_end = slot_sz;
    }

    // check cache hit
    int cache_hit = 0;
    do {
        if (file_cache->slot_id != slot_id) {
            // slot not match
            break;
        }
        if (frag_start < file_cache->offset ||
            frag_end > file_cache->offset + file_cache->len) {
            break;
        }
        cache_hit = 1;
    } while(0);

    if (cache_hit) {
        return(SPK_SUCCESS);
    }

    // do caching
    cache_sz = MIN(SYS_CACHE_SIZE, slot_sz - frag_start);
    size_t cache_sz_repo = cache_sz / repo_num;
    zlog_notice(sys_zc, "cache file: slot_id=%d, slot_sz=%zu, req_frag=%u, "
                "req=%lu+%lu, frag=%lu+%lu, cache_sz=%zu, blk=%lu+%lu",
                slot_id, slot_sz, req_frag,
                req_start, req_end-req_start,
                frag_start, frag_end-frag_start,
                cache_sz, blk_start, blk_num);

    struct dfv_file* file_ctx = NULL;
    void* file_buffer = memalign(SYS_INTERLACE_SIZE, cache_sz_repo);
    for (i=0; i<repo_num; i++) {
        struct dfv_repo * repo = ctx->vault->repo_tbl[i];
        assert(repo);

        file_ctx = dfv_file_open(repo, slot_id, SPK_DIR_READ, NULL, 12+4*i);
        if (!file_ctx) {
            ret = SPKERR_BADRES;
            goto out;
        }

        ret = dfv_file_seek(file_ctx, frag_start / repo_num);
        if (ret) {
            goto out;
        }

        ssize_t read_sz = dfv_file_read(file_ctx, file_buffer, cache_sz_repo);
        if (read_sz != cache_sz_repo) {
            ret = SPKERR_BADRES;
            goto out;
        }

        dfv_file_close(file_ctx);
        file_ctx = NULL;

        // do interlace while copy data
        for (j=0; j<cache_sz_repo/interlace_sz; j++) {
            memcpy(file_cache->data+(j*repo_num+i)*interlace_sz,
                   file_buffer+j*interlace_sz,
                   interlace_sz);
        }
    }
    // cache done
    file_cache->slot_id = slot_id;
    file_cache->offset = frag_start;
    file_cache->len = cache_sz;
    file_cache->slot_sz = slot_sz;
    zlog_notice(sys_zc, "cache done: slot_id=%d, slot_sz=%lu, cache=%lu+%lu",
                slot_id, slot_sz, file_cache->offset,
                file_cache->len);

    ret = SPK_SUCCESS;

out:
    if (file_ctx) {
        dfv_file_close(file_ctx);
        file_ctx = NULL;
    }
    SAFE_RELEASE(file_buffer);

    return(ret);
}
示例#8
0
/* Interface looking up using infamous SIOCGIFCONF. */
static int
interface_list_ioctl (void)
{
  int ret;
  int sock;
#define IFNUM_BASE 32
  int ifnum;
  struct ifreq *ifreq;
  struct ifconf ifconf;
  struct interface *ifp;
  int n;
  int lastlen;

  /* Normally SIOCGIFCONF works with AF_INET socket. */
  sock = socket (AF_INET, SOCK_DGRAM, 0);
  if (sock < 0) 
    {
      zlog_warn ("Can't make AF_INET socket stream: %s", safe_strerror (errno));
      return -1;
    }

  /* Set initial ifreq count.  This will be double when SIOCGIFCONF
     fail.  Solaris has SIOCGIFNUM. */
#ifdef SIOCGIFNUM
  ret = ioctl (sock, SIOCGIFNUM, &ifnum);
  if (ret < 0)
    ifnum = IFNUM_BASE;
  else
    ifnum++;
#else
  ifnum = IFNUM_BASE;
#endif /* SIOCGIFNUM */

  ifconf.ifc_buf = NULL;

  lastlen = 0;
  /* Loop until SIOCGIFCONF success. */
  for (;;) 
    {
      ifconf.ifc_len = sizeof (struct ifreq) * ifnum;
      ifconf.ifc_buf = XREALLOC(MTYPE_TMP, ifconf.ifc_buf, ifconf.ifc_len);

      ret = ioctl(sock, SIOCGIFCONF, &ifconf);

      if (ret < 0) 
	{
	  zlog_warn ("SIOCGIFCONF: %s", safe_strerror(errno));
	  goto end;
	}
      /* Repeatedly get info til buffer fails to grow. */
      if (ifconf.ifc_len > lastlen)
	{
          lastlen = ifconf.ifc_len;
	  ifnum += 10;
	  continue;
	}
      /* Success. */
      break;
    }

  /* Allocate interface. */
  ifreq = ifconf.ifc_req;

#ifdef OPEN_BSD
  for (n = 0; n < ifconf.ifc_len; )
    {
      int size;

      ifreq = (struct ifreq *)((caddr_t) ifconf.ifc_req + n);
      ifp = if_get_by_name_len(ifreq->ifr_name,
			       strnlen(ifreq->ifr_name,
				       sizeof(ifreq->ifr_name)));
      if_add_update (ifp);
      size = ifreq->ifr_addr.sa_len;
      if (size < sizeof (ifreq->ifr_addr))
	size = sizeof (ifreq->ifr_addr);
      size += sizeof (ifreq->ifr_name);
      n += size;
    }
#else
  for (n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq))
    {
      ifp = if_get_by_name_len(ifreq->ifr_name,
			       strnlen(ifreq->ifr_name,
				       sizeof(ifreq->ifr_name)));
      if_add_update (ifp);
      ifreq++;
    }
#endif /* OPEN_BSD */

 end:
  close (sock);
  XFREE (MTYPE_TMP, ifconf.ifc_buf);

  return ret;
}
示例#9
0
static int
netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
  int len;
  struct ifinfomsg *ifi;
  struct rtattr *tb[IFLA_MAX + 1];
  struct interface *ifp;
  char *name;

  ifi = NLMSG_DATA (h);

  if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK))
    {
      /* If this is not link add/delete message so print warning. */
      zlog_warn ("netlink_link_change: wrong kernel message %d\n",
                 h->nlmsg_type);
      return 0;
    }

  len = h->nlmsg_len - NLMSG_LENGTH (sizeof (struct ifinfomsg));
  if (len < 0)
    return -1;

  /* Looking up interface name. */
  memset (tb, 0, sizeof tb);
  netlink_parse_rtattr (tb, IFLA_MAX, IFLA_RTA (ifi), len);

#ifdef IFLA_WIRELESS
  /* check for wireless messages to ignore */
  if ((tb[IFLA_WIRELESS] != NULL) && (ifi->ifi_change == 0))
    {
      if (IS_DEBUG_HA(kroute, KROUTE))
        zlog_debug ("%s: ignoring IFLA_WIRELESS message", __func__);
      return 0;
    }
#endif /* IFLA_WIRELESS */
  
  if (tb[IFLA_IFNAME] == NULL)
    return -1;
  name = (char *) RTA_DATA (tb[IFLA_IFNAME]);

  /* Add interface. */
  if (h->nlmsg_type == RTM_NEWLINK)
    {
      ifp = if_lookup_by_name (name);

      if (ifp == NULL || !CHECK_FLAG (ifp->status, KROUTE_INTERFACE_ACTIVE))
        {
          if (ifp == NULL)
            ifp = if_get_by_name (name);

          set_ifindex(ifp, ifi->ifi_index);
          ifp->flags = ifi->ifi_flags & 0x0000fffff;
          ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
          ifp->metric = 1;

          netlink_interface_update_hw_addr (tb, ifp);

          /* If new link is added. */
          if_add_update (ifp);
        }
      else
        {
          /* Interface status change. */
          set_ifindex(ifp, ifi->ifi_index);
          ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]);
          ifp->metric = 1;

          netlink_interface_update_hw_addr (tb, ifp);

          if (if_is_operative (ifp))
            {
              ifp->flags = ifi->ifi_flags & 0x0000fffff;
              if (!if_is_operative (ifp))
                if_down (ifp);
	      else
		/* Must notify client daemons of new interface status. */
	        kroute_interface_up_update (ifp);
            }
          else
            {
              ifp->flags = ifi->ifi_flags & 0x0000fffff;
              if (if_is_operative (ifp))
                if_up (ifp);
            }
        }
    }
  else
    {
      /* RTM_DELLINK. */
      ifp = if_lookup_by_name (name);

      if (ifp == NULL)
        {
          zlog (NULL, LOG_WARNING, "interface %s is deleted but can't find",
                name);
          return 0;
        }

      if_delete_update (ifp);
    }

  return 0;
}
void pim_if_addr_add(struct connected *ifc)
{
  struct pim_interface *pim_ifp;
  struct interface *ifp;
  struct in_addr ifaddr;

  zassert(ifc);

  ifp = ifc->ifp;
  zassert(ifp);
  pim_ifp = ifp->info;
  if (!pim_ifp)
    return;

  if (!if_is_operative(ifp))
    return;

  /* if (PIM_DEBUG_ZEBRA) */ {
    char buf[BUFSIZ];
    prefix2str(ifc->address, buf, BUFSIZ);
    zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
	       __PRETTY_FUNCTION__,
	       ifp->name, ifp->ifindex, buf,
	       CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY) ?
	       "secondary" : "primary");
  }

  ifaddr = ifc->address->u.prefix4;

  detect_address_change(ifp, 0, __PRETTY_FUNCTION__);

  if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
    struct igmp_sock *igmp;

    /* lookup IGMP socket */
    igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
				       ifaddr);
    if (!igmp) {
      /* if addr new, add IGMP socket */
      pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr, ifp);
    }
  } /* igmp */

  if (PIM_IF_TEST_PIM(pim_ifp->options)) {

    /* Interface has a valid primary address ? */
    if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {

      /* Interface has a valid socket ? */
      if (pim_ifp->pim_sock_fd < 0) {
	if (pim_sock_add(ifp)) {
	  zlog_warn("Failure creating PIM socket for interface %s",
		    ifp->name);
	}
      }

    }
  } /* pim */

  if (PIM_MROUTE_IS_ENABLED) {
    /*
      PIM or IGMP is enabled on interface, and there is at least one
      address assigned, then try to create a vif_index.
    */
    if (pim_ifp->mroute_vif_index < 0) {
      pim_if_add_vif(ifp);
    }
  }
}
示例#11
0
/* Interface address lookup by ioctl.  This function only looks up
   IPv4 address. */
int
if_get_addr (struct interface *ifp)
{
  int ret;
  struct ifreq ifreq;
  struct sockaddr_in addr;
  struct sockaddr_in mask;
  struct sockaddr_in dest;
  struct in_addr *dest_pnt;
  u_char prefixlen;

  /* Interface's name and address family. */
  strncpy (ifreq.ifr_name, ifp->name, IFNAMSIZ);
  ifreq.ifr_addr.sa_family = AF_INET;

  /* Interface's address. */
  ret = if_ioctl (SIOCGIFADDR, (caddr_t) &ifreq);
  if (ret < 0) 
    {
      if (errno != EADDRNOTAVAIL)
	{
	  zlog_warn ("SIOCGIFADDR fail: %s", safe_strerror (errno));
	  return ret;
	}
      return 0;
    }
  memcpy (&addr, &ifreq.ifr_addr, sizeof (struct sockaddr_in));

  /* Interface's network mask. */
  ret = if_ioctl (SIOCGIFNETMASK, (caddr_t) &ifreq);
  if (ret < 0) 
    {
      if (errno != EADDRNOTAVAIL) 
	{
	  zlog_warn ("SIOCGIFNETMASK fail: %s", safe_strerror (errno));
	  return ret;
	}
      return 0;
    }
#ifdef ifr_netmask
  memcpy (&mask, &ifreq.ifr_netmask, sizeof (struct sockaddr_in));
#else
  memcpy (&mask, &ifreq.ifr_addr, sizeof (struct sockaddr_in));
#endif /* ifr_netmask */
  prefixlen = ip_masklen (mask.sin_addr);

  /* Point to point or borad cast address pointer init. */
  dest_pnt = NULL;

  if (ifp->flags & IFF_POINTOPOINT) 
    {
      ret = if_ioctl (SIOCGIFDSTADDR, (caddr_t) &ifreq);
      if (ret < 0) 
	{
	  if (errno != EADDRNOTAVAIL) 
	    {
	      zlog_warn ("SIOCGIFDSTADDR fail: %s", safe_strerror (errno));
	      return ret;
	    }
	  return 0;
	}
      memcpy (&dest, &ifreq.ifr_dstaddr, sizeof (struct sockaddr_in));
      dest_pnt = &dest.sin_addr;
    }
  if (ifp->flags & IFF_BROADCAST)
    {
      ret = if_ioctl (SIOCGIFBRDADDR, (caddr_t) &ifreq);
      if (ret < 0) 
	{
	  if (errno != EADDRNOTAVAIL) 
	    {
	      zlog_warn ("SIOCGIFBRDADDR fail: %s", safe_strerror (errno));
	      return ret;
	    }
	  return 0;
	}
      memcpy (&dest, &ifreq.ifr_broadaddr, sizeof (struct sockaddr_in));
      dest_pnt = &dest.sin_addr;
    }


  /* Set address to the interface. */
  connected_add_ipv4 (ifp, 0, &addr.sin_addr, prefixlen, dest_pnt, NULL);

  return 0;
}
int pim_if_igmp_join_add(struct interface *ifp,
			 struct in_addr group_addr,
			 struct in_addr source_addr)
{
  struct pim_interface *pim_ifp;
  struct igmp_join *ij;

  pim_ifp = ifp->info;
  if (!pim_ifp) {
    zlog_warn("%s: multicast not enabled on interface %s",
	      __PRETTY_FUNCTION__, 
	      ifp->name);
    return -1;
  }

  if (!pim_ifp->igmp_join_list) {
    pim_ifp->igmp_join_list = list_new();
    if (!pim_ifp->igmp_join_list) {
      zlog_err("%s %s: failure: igmp_join_list=list_new()",
	       __FILE__, __PRETTY_FUNCTION__);
      return -2;
    }
    pim_ifp->igmp_join_list->del = (void (*)(void *)) igmp_join_free;
  }

  ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
  if (ij) {
    char group_str[100];
    char source_str[100];
    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_warn("%s: can't re-join existing IGMP group %s source %s on interface %s",
	      __PRETTY_FUNCTION__,
	      group_str, source_str, ifp->name);
    return -3;
  }

  ij = igmp_join_new(ifp, group_addr, source_addr);
  if (!ij) {
    char group_str[100];
    char source_str[100];
    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_warn("%s: igmp_join_new() failure for IGMP group %s source %s on interface %s",
	      __PRETTY_FUNCTION__,
	      group_str, source_str, ifp->name);
    return -4;
  }

  {
    char group_str[100];
    char source_str[100];
    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
    zlog_debug("%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
	       __PRETTY_FUNCTION__,
	       source_str, group_str, ifp->name);
  }

  return 0;
}
示例#13
0
static int
open_bpf_dev (struct isis_circuit *circuit)
{
    int i = 0, fd;
    char bpfdev[128];
    struct ifreq ifr;
    u_int16_t blen;
    int true = 1, false = 0;
    struct timeval timeout;
    struct bpf_program bpf_prog;

    do
    {
        (void) snprintf (bpfdev, sizeof (bpfdev), "/dev/bpf%d", i++);
        fd = open (bpfdev, O_RDWR);
    }
    while (fd < 0 && errno == EBUSY);

    if (fd < 0)
    {
        zlog_warn ("open_bpf_dev(): failed to create bpf socket: %s",
                   safe_strerror (errno));
        return ISIS_WARNING;
    }

    zlog_debug ("Opened BPF device %s", bpfdev);

    memcpy (ifr.ifr_name, circuit->interface->name, sizeof (ifr.ifr_name));
    if (ioctl (fd, BIOCSETIF, (caddr_t) & ifr) < 0)
    {
        zlog_warn ("open_bpf_dev(): failed to bind to interface: %s",
                   safe_strerror (errno));
        return ISIS_WARNING;
    }

    if (ioctl (fd, BIOCGBLEN, (caddr_t) & blen) < 0)
    {
        zlog_warn ("failed to get BPF buffer len");
        blen = circuit->interface->mtu;
    }

    readblen = blen;

    if (readbuff == NULL)
        readbuff = malloc (blen);

    zlog_debug ("BPF buffer len = %u", blen);

    /*  BPF(4): reads return immediately upon packet reception.
     *  Otherwise, a read will block until either the kernel
     *  buffer becomes full or a timeout occurs.
     */
    if (ioctl (fd, BIOCIMMEDIATE, (caddr_t) & true) < 0)
    {
        zlog_warn ("failed to set BPF dev to immediate mode");
    }

#ifdef BIOCSSEESENT
    /*
     * We want to see only incoming packets
     */
    if (ioctl (fd, BIOCSSEESENT, (caddr_t) & false) < 0)
    {
        zlog_warn ("failed to set BPF dev to incoming only mode");
    }
#endif

    /*
     * ...but all of them
     */
    if (ioctl (fd, BIOCPROMISC, (caddr_t) & true) < 0)
    {
        zlog_warn ("failed to set BPF dev to promiscuous mode");
    }

    /*
     * If the buffer length is smaller than our mtu, lets try to increase it
     */
    if (blen < circuit->interface->mtu)
    {
        if (ioctl (fd, BIOCSBLEN, &circuit->interface->mtu) < 0)
        {
            zlog_warn ("failed to set BPF buffer len (%u to %u)", blen,
                       circuit->interface->mtu);
        }
    }

    /*
     * Set a timeout parameter - hope this helps select()
     */
    timeout.tv_sec = 600;
    timeout.tv_usec = 0;
    if (ioctl (fd, BIOCSRTIMEOUT, (caddr_t) & timeout) < 0)
    {
        zlog_warn ("failed to set BPF device timeout");
    }

    /*
     * And set the filter
     */
    memset (&bpf_prog, 0, sizeof (struct bpf_program));
    bpf_prog.bf_len = 8;
    bpf_prog.bf_insns = &(llcfilter[0]);
    if (ioctl (fd, BIOCSETF, (caddr_t) & bpf_prog) < 0)
    {
        zlog_warn ("open_bpf_dev(): failed to install filter: %s",
                   safe_strerror (errno));
        return ISIS_WARNING;
    }

    assert (fd > 0);

    circuit->fd = fd;

    return ISIS_OK;
}
示例#14
0
static int
open_packet_socket (struct isis_circuit *circuit)
{
    struct sockaddr_ll s_addr;
    int fd, retval = ISIS_OK;

    fd = socket (PF_PACKET, SOCK_DGRAM, htons (ETH_P_ALL));
    if (fd < 0)
    {
        zlog_warn ("open_packet_socket(): socket() failed %s",
                   safe_strerror (errno));
        return ISIS_WARNING;
    }

    /*
     * Bind to the physical interface
     */
    memset (&s_addr, 0, sizeof (struct sockaddr_ll));
    s_addr.sll_family = AF_PACKET;
    s_addr.sll_protocol = htons (ETH_P_ALL);
    s_addr.sll_ifindex = circuit->interface->ifindex;

    if (bind (fd, (struct sockaddr *) (&s_addr),
              sizeof (struct sockaddr_ll)) < 0)
    {
        zlog_warn ("open_packet_socket(): bind() failed: %s", safe_strerror (errno));
        return ISIS_WARNING;
    }

    circuit->fd = fd;

    if (circuit->circ_type == CIRCUIT_T_BROADCAST)
    {
        /*
         * Join to multicast groups
         * according to
         * 8.4.2 - Broadcast subnetwork IIH PDUs
         * FIXME: is there a case only one will fail??
         */
        if (circuit->circuit_is_type & IS_LEVEL_1)
        {
            /* joining ALL_L1_ISS */
            retval = isis_multicast_join (circuit->fd, 1,
                                          circuit->interface->ifindex);
            /* joining ALL_ISS */
            retval = isis_multicast_join (circuit->fd, 3,
                                          circuit->interface->ifindex);
        }
        if (circuit->circuit_is_type & IS_LEVEL_2)
            /* joining ALL_L2_ISS */
            retval = isis_multicast_join (circuit->fd, 2,
                                          circuit->interface->ifindex);
    }
    else
    {
        retval =
            isis_multicast_join (circuit->fd, 0, circuit->interface->ifindex);
    }

    return retval;
}
示例#15
0
文件: buffer.c 项目: rgmabs19357/HA
/* This function (unlike other buffer_flush* functions above) is designed
to work with non-blocking sockets.  It does not attempt to write out
all of the queued data, just a "big" chunk.  It returns 0 if it was
able to empty out the buffers completely, 1 if more flushing is
required later, or -1 on a fatal write error. */
buffer_status_t
buffer_flush_available(struct buffer *b, int fd)
{

/* These are just reasonable values to make sure a significant amount of
data is written.  There's no need to go crazy and try to write it all
in one shot. */
#ifdef IOV_MAX
#define MAX_CHUNKS ((IOV_MAX >= 16) ? 16 : IOV_MAX)
#else
#define MAX_CHUNKS 16
#endif
#define MAX_FLUSH 131072

  struct buffer_data *d;
  size_t written;
  struct iovec iov[MAX_CHUNKS];
  size_t iovcnt = 0;
  size_t nbyte = 0;

  for (d = b->head; d && (iovcnt < MAX_CHUNKS) && (nbyte < MAX_FLUSH);
       d = d->next, iovcnt++)
    {
      iov[iovcnt].iov_base = d->data+d->sp;
      nbyte += (iov[iovcnt].iov_len = d->cp-d->sp);
    }

  if (!nbyte)
    /* No data to flush: should we issue a warning message? */
    return BUFFER_EMPTY;

  /* only place where written should be sign compared */
  if ((ssize_t)(written = writev(fd,iov,iovcnt)) < 0)
    {
      if (ERRNO_IO_RETRY(errno))
	/* Calling code should try again later. */
        return BUFFER_PENDING;
      zlog_warn("%s: write error on fd %d: %s",
		__func__, fd, safe_strerror(errno));
      return BUFFER_ERROR;
    }

  /* Free printed buffer data. */
  while (written > 0)
    {
      struct buffer_data *d;
      if (!(d = b->head))
        {
          zlog_err("%s: corruption detected: buffer queue empty, "
		   "but written is %lu", __func__, (u_long)written);
	  break;
        }
      if (written < d->cp-d->sp)
        {
	  d->sp += written;
	  return BUFFER_PENDING;
	}

      written -= (d->cp-d->sp);
      if (!(b->head = d->next))
        b->tail = NULL;
      BUFFER_DATA_FREE(d);
    }

  return b->head ? BUFFER_PENDING : BUFFER_EMPTY;

#undef MAX_CHUNKS
#undef MAX_FLUSH
}
示例#16
0
static int
netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
  zlog_warn ("netlink_talk: ignoring message type 0x%04x", h->nlmsg_type);
  return 0;
}
示例#17
0
int
smux_socket ()
{
  int ret;
#ifdef HAVE_IPV6
  struct addrinfo hints, *res0, *res;
  int gai;
#else
  struct sockaddr_in serv;
  struct servent *sp;
#endif
  int sock = 0;

#ifdef HAVE_IPV6
  memset(&hints, 0, sizeof(hints));
  hints.ai_family = PF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  gai = getaddrinfo(NULL, "smux", &hints, &res0);
  if (gai == EAI_SERVICE)
    {
      char servbuf[NI_MAXSERV];
      sprintf(servbuf,"%d",SMUX_PORT_DEFAULT);
      servbuf[sizeof (servbuf) - 1] = '\0';
      gai = getaddrinfo(NULL, servbuf, &hints, &res0);
    }
  if (gai)
    {
      zlog_warn("Cannot locate loopback service smux");
      return -1;
    }
  for(res=res0; res; res=res->ai_next)
    {
      if (res->ai_family != AF_INET 
#ifdef HAVE_IPV6
	  && res->ai_family != AF_INET6
#endif /* HAVE_IPV6 */
	  )
	continue;

      sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
      if (sock < 0)
	continue;
      sockopt_reuseaddr (sock);
      sockopt_reuseport (sock);
      ret = connect (sock, res->ai_addr, res->ai_addrlen);
      if (ret < 0)
	{
	  close(sock);
	  sock = -1;
	  continue;
	}
      break;
    }
  freeaddrinfo(res0);
  if (sock < 0)
    zlog_warn ("Can't connect to SNMP agent with SMUX");
#else
  sock = socket (AF_INET, SOCK_STREAM, 0);
  if (sock < 0)
    {
      zlog_warn ("Can't make socket for SNMP");
      return -1;
    }

  memset (&serv, 0, sizeof (struct sockaddr_in));
  serv.sin_family = AF_INET;
#ifdef HAVE_SIN_LEN
  serv.sin_len = sizeof (struct sockaddr_in);
#endif /* HAVE_SIN_LEN */

  sp = getservbyname ("smux", "tcp");
  if (sp != NULL) 
    serv.sin_port = sp->s_port;
  else
    serv.sin_port = htons (SMUX_PORT_DEFAULT);

  serv.sin_addr.s_addr = htonl (INADDR_LOOPBACK);

  sockopt_reuseaddr (sock);
  sockopt_reuseport (sock);

  ret = connect (sock, (struct sockaddr *) &serv, sizeof (struct sockaddr_in));
  if (ret < 0)
    {
      close (sock);
      smux_sock = -1;
      zlog_warn ("Can't connect to SNMP agent with SMUX");
      return -1;
    }
#endif
  return sock;
}
示例#18
0
/* Execute NSM event process. */
int
ospf_nsm_event (struct thread *thread)
{
  int event;
  int next_state;
  struct ospf_neighbor *nbr;

  nbr = THREAD_ARG (thread);
  event = THREAD_VAL (thread);

  if (IS_DEBUG_OSPF (nsm, NSM_EVENTS))
    zlog_debug ("NSM[%s:%s]: %s (%s)", IF_NAME (nbr->oi),
	       inet_ntoa (nbr->router_id),
	       LOOKUP (ospf_nsm_state_msg, nbr->state),
	       ospf_nsm_event_str [event]);
  
  next_state = NSM [nbr->state][event].next_state;

  /* Call function. */
  if (NSM [nbr->state][event].func != NULL)
    {
      int func_state = (*(NSM [nbr->state][event].func))(nbr);
      
      if (NSM [nbr->state][event].next_state == NSM_DependUpon)
        next_state = func_state;
      else if (func_state)
        {
          /* There's a mismatch between the FSM tables and what an FSM
           * action/state-change function returned. State changes which
           * do not have conditional/DependUpon next-states should not
           * try set next_state.
           */
          zlog_warn ("NSM[%s:%s]: %s (%s): "
                     "Warning: action tried to change next_state to %s",
                     IF_NAME (nbr->oi), inet_ntoa (nbr->router_id),
                     LOOKUP (ospf_nsm_state_msg, nbr->state),
                     ospf_nsm_event_str [event],
                     LOOKUP (ospf_nsm_state_msg, func_state));
        }
    }

  assert (next_state != NSM_DependUpon);
  
  /* If state is changed. */
  if (next_state != nbr->state)
    {
      nsm_notice_state_change (nbr, next_state, event);
      nsm_change_state (nbr, next_state);
    }

  /* Make sure timer is set. */
  nsm_timer_set (nbr);

  /* When event is NSM_KillNbr, InactivityTimer or LLDown, the neighbor
   * is deleted.
   *
   * Rather than encode knowledge here of which events lead to NBR
   * delete, we take our cue from the NSM table, via the dummy
   * 'Deleted' neighbour state.
   */
  if (nbr->state == NSM_Deleted)
    ospf_nbr_delete (nbr);

  return 0;
}
示例#19
0
static int __sys_job_do_record(sys_wkr_ctx_t* wkr_ctx,
                                 IPS_EPID src_id, int pc_id, size_t ips_sec_sz,
                                 dfv_slot_def_t* slot_def,
                                 dfv_slice_def_t* slice_def)
{
    int ret = -1;
#ifdef ARCH_ppc64
    struct ips_pcctx* pcctx = NULL;
    struct dfv_file* file_ctx = NULL;
    int wkr_id = wkr_ctx->wkr_id;
    spk_stats_t* stats = &wkr_ctx->stats;

    void* chunk_buf = NULL;
    size_t chunk_size = slice_def->size * slice_def->num;
    int dfv_cpu_base = 12+4*wkr_ctx->wkr_id;

    zlog_notice(sys_zc, "wkr#%d> prepare for recording: ips={0x%x:%d}, dfv={repo={%d:%d}, "
                        "slice={%d, 0x%lx}, cpu_base=%d}",
                        wkr_id,
                        src_id, pc_id,
                        dfv_repo_get_id(slot_def->repo), slot_def->slot_id,
                        slice_def->num, slice_def->size,
                        dfv_cpu_base);

    // reset stats
    spk_stats_reset(stats);

    // open dfv slot
    file_ctx = dfv_file_open(slot_def->repo, slot_def->slot_id, SPK_DIR_WRITE, slice_def,
                             dfv_cpu_base);
    if (!file_ctx) {
        zlog_fatal(sys_zc, "wkr#%d> failed to open dfv file", wkr_id);
        ret = SPKERR_BADRES;
        goto out;
    }

    // write to dfv
#if 0
    if (!(sys_env.dbg_flag & SYSDBG_REC_NOTSAVE2DISK)) {
        size_t warmup_sz = 128*1024*1024;
        size_t xferred = 0;
        void * txbuf = NULL;

        txbuf = memalign(SYS_INTERLACE_SIZE, DFV_CHUNK_SIZE);
        assert(txbuf);
        memset(txbuf, 0xfe, DFV_CHUNK_SIZE);
        while(xferred < warmup_sz) {
            ssize_t xfer = dfv_file_write(file_ctx, txbuf, DFV_CHUNK_SIZE);
            if (xfer != DFV_CHUNK_SIZE) {
                zlog_fatal(sys_zc, "wkr#%d> failed to write to dfv: xfer=%ld, expect=%u",
                                    wkr_id, xfer, DFV_CHUNK_SIZE);
                ret = SPKERR_EACCESS;
                SAFE_RELEASE(txbuf);
                goto out;
            }
            xferred += xfer;
        }
        dfv_file_seek(file_ctx, 0);
        SAFE_RELEASE(txbuf);
    }
    zlog_notice(sys_zc, "wkr#%d> dfv warmup done", wkr_id);
#endif

    // open ips srio
    pcctx = ips_chan_open(src_id, pc_id);
    if (!pcctx) {
        zlog_fatal(sys_zc, "wkr#%d> failed to open ips channel", wkr_id);
        ret = SPKERR_EACCESS;
        goto out;
    }

    ret = ips_chan_start(pcctx, SPK_DIR_READ);
    if (ret != SPK_SUCCESS) {
        zlog_fatal(sys_zc, "wkr#%d> failed to start ips channel", wkr_id);
        goto out;
    }
    zlog_info(sys_zc, "wkr#%d> ips channel started for reading", wkr_id);

    // start recording
    uint64_t now = spk_get_tick_count();
    uint64_t tm_upstats = now;
    uint64_t tm_log = now;
    uint64_t tm_heartbeat = now;
    ret = SPK_SUCCESS;
    size_t xfer;
    zlog_notice(sys_zc, "wkr#%d> ---------- start recording ----------", wkr_id);
    while(!wkr_ctx->reset_req) {
        // read from ips for one chunk
        // FIXME: our link partner must have enough data
        // before being stopped
        ssize_t read_size = ips_chan_read(pcctx, &chunk_buf, chunk_size, chunk_size);
        if (read_size > 0) {
            // got a chunk from ips
            assert(read_size == chunk_size);
            // preserve first buf for snapshot use
            pthread_mutex_lock(&wkr_ctx->buf_snap_lock);
            memcpy(wkr_ctx->buf_snap, chunk_buf, SYS_SNAP_BUF_SZ);
            pthread_mutex_unlock(&wkr_ctx->buf_snap_lock);

            // write to dfv
            if (sys_env.dbg_flag & SYSDBG_REC_NOTSAVE2DISK) {
                xfer = chunk_size;
            } else {
                xfer = dfv_file_write(file_ctx, chunk_buf, read_size);
            }
            // notify ips to free buffer first
            ips_chan_free_buf(pcctx, read_size);

            if (xfer != read_size) {
                zlog_fatal(sys_zc, "wkr#%d> failed to write to dfv: xfer=%ld, expect=%lu",
                                    wkr_id, xfer, read_size);
                ret = SPKERR_EACCESS;
                break;
            }
        } else if (read_size == 0) {
            // no data
            if (sys_ctx.auto_rec) {
                if (spk_get_tick_count() - tm_heartbeat > SYS_AUTOSTOP_TIMEOUT*1000) {
                    // timeout
                    zlog_warn(sys_zc, "wkr#%d> no data received since last %d secs, stop.",
                              wkr_id, SYS_AUTOSTOP_TIMEOUT);
                    break;
                }
            }
        } else {
            // failed to got a chunk from ips
            zlog_fatal(sys_zc, "wkr#%d> failed to read from ips: read_size=%ld", wkr_id, read_size);
            ret = read_size;
            break;
        }

        tm_heartbeat = now = spk_get_tick_count();

        // update local stats
        spk_stats_inc_xfer(stats, read_size, (read_size / ips_sec_sz));
        if (now > tm_upstats) {
            if (!(sys_env.features & SYSFEA_USE_LOCALSTATS)) {
                // update channel stats
                sys_job_update_stats(pcctx, wkr_id);
            }
            tm_upstats = now + 1000;
        }

        if (now > tm_log) {
            zlog_notice(sys_zc, "    wkr#%d> time=%lu pkts=%lu bytes=%lu ovfl=%lu spd=%.3f MBPS",
                        wkr_id,
                        spk_stats_get_time_elapsed(stats)/1000,
                        spk_stats_get_xfer_pkts(stats),
                        spk_stats_get_xfer_bytes(stats),
                        spk_stats_get_overflow_bytes(stats),
                        BYTE2MB(spk_stats_get_bps_overall(stats)));
            tm_log = now + 10*1000;
        }
    }

    //
    // stop recording
    //
    // 1. send stop to link partner
    int stop_ret = ips_chan_stop(pcctx);
    if (stop_ret != SPK_SUCCESS) {
        zlog_fatal(sys_zc, "wkr#%d> failed to close ips channel: ret=%d",
                            wkr_id, stop_ret);
        ret = stop_ret;
        goto out;
    }

    // 2. drain remained data
    if (ret == SPK_SUCCESS) {
        // wait for link partner to do padding
        sleep(1);

        ssize_t tail_size;
        do {
            tail_size = ips_chan_read(pcctx, &chunk_buf, 0, chunk_size);
            if (tail_size <= 0) {
                // done
                break;
            }
            zlog_notice(sys_zc, "wkr#%d> got remained data: size=%zd", wkr_id, tail_size);
            // data must been padded to 64k alignment by link partner
            assert(!(tail_size & (0x10000-1)));

            // save remained data to dfv slot
            if (sys_env.dbg_flag & SYSDBG_REC_NOTSAVE2DISK) {
                xfer = tail_size;
            } else {
                xfer = dfv_file_write(file_ctx, chunk_buf, tail_size);
            }
            ips_chan_free_buf(pcctx, tail_size);
            if (xfer != tail_size) {
                zlog_fatal(sys_zc, "wkr#%d> failed to write to dfv: xfer=%ld, expect=%lu",
                                    wkr_id, xfer, tail_size);
                ret = SPKERR_EACCESS;
                goto out;
            }
        } while(1);
    }

    // 3. update chstat for last time
    if (!(sys_env.features & SYSFEA_USE_LOCALSTATS)) {
        sys_job_update_stats(pcctx, wkr_id);
    }

out:
    zlog_notice(sys_zc, "wkr#%d> ---------- stop recording ---------- ret=%d,", wkr_id, ret);
    if (stats) {
        zlog_notice(sys_zc, "wkr#%d> elapsed=%lu, pkts=%lu, bytes=%lu, ovfl=%lu",
                            wkr_id, spk_stats_get_time_elapsed(stats)/1000,
                            stats->xfer.pkts, stats->xfer.bytes, stats->overflow.bytes);
    }

    // close dfv slot
    if (file_ctx) {
        dfv_file_close(file_ctx);
        file_ctx = NULL;
    }

    // close ips srio
    if (pcctx) {
        ips_chan_close(pcctx);
        pcctx = NULL;
    }
#endif
    return(ret);
}
示例#20
0
struct connected *
zebra_interface_address_read (int type, struct stream *s)
{
  unsigned int ifindex;
  struct interface *ifp;
  struct connected *ifc;
  struct prefix p, d;
  int family;
  int plen;
  u_char ifc_flags;

  memset (&p, 0, sizeof(p));
  memset (&d, 0, sizeof(d));

  /* Get interface index. */
  ifindex = stream_getl (s);

  /* Lookup index. */
  ifp = if_lookup_by_index (ifindex);
  if (ifp == NULL)
    {
      zlog_warn ("zebra_interface_address_read(%s): "
                 "Can't find interface by ifindex: %d ",
                 (type == ZEBRA_INTERFACE_ADDRESS_ADD? "ADD" : "DELETE"),
                 ifindex);
      return NULL;
    }

  /* Fetch flag. */
  ifc_flags = stream_getc (s);

  /* Fetch interface address. */
  family = p.family = stream_getc (s);

  plen = prefix_blen (&p);
  stream_get (&p.u.prefix, s, plen);
  p.prefixlen = stream_getc (s);

  /* Fetch destination address. */
  stream_get (&d.u.prefix, s, plen);
  d.family = family;

  if (type == ZEBRA_INTERFACE_ADDRESS_ADD) 
    {
       /* N.B. NULL destination pointers are encoded as all zeroes */
       ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
					      NULL : &d));
       if (ifc != NULL)
	 {
	   ifc->flags = ifc_flags;
	   if (ifc->destination)
	     ifc->destination->prefixlen = ifc->address->prefixlen;
	   else if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER))
	     {
	       /* carp interfaces on OpenBSD with 0.0.0.0/0 as "peer" */
	       char buf[BUFSIZ];
	       prefix2str (ifc->address, buf, sizeof(buf));
	       zlog_warn("warning: interface %s address %s "
		    "with peer flag set, but no peer address!",
		    ifp->name, buf);
	       UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
	     }
	 }
    }
  else
    {
      assert (type == ZEBRA_INTERFACE_ADDRESS_DELETE);
      ifc = connected_delete_by_prefix(ifp, &p);
    }

  return ifc;
}
示例#21
0
void* __sys_wkr_job(void* args)
{
    sys_wkr_ctx_t* wkr_ctx = (sys_wkr_ctx_t*)args;

    int wkr_id = wkr_ctx->wkr_id;
    int ips_pipe_id = wkr_id;
    int ips_pcid = 0;
    int dfv_pipe_id = wkr_id;

    sys_ctx_t* ctx = &sys_ctx;
    sys_env_t* env = &sys_env;

    ips_epdesc_t* epdesc = &env->ips_desc_tbl[ips_pipe_id];
    ips_pcdesc_t* pcdesc = &epdesc->pcdesc_tbl[ips_pcid];
    IPS_EPID epid = pcdesc->src_id;

    dfv_vault_t* vault = ctx->vault;
    struct dfv_repo* repo = vault->repo_tbl[dfv_pipe_id];
    size_t ips_sec_sz = pcdesc->sector_sz;

    dfv_slice_def_t slice_def;
    memset(&slice_def, 0, sizeof(dfv_slice_def_t));
    slice_def.num = DFV_SLICE_NUM;
    slice_def.size = DFV_SLICE_SIZE;

    dfv_slot_def_t slot_def;

    int cpu = wkr_id + 5;
    spk_worker_set_affinity(cpu);
    zlog_notice(sys_zc, "wkr#%d> spawn: cpu=%d", wkr_id, cpu);

    int ret = -1;

    while(!wkr_ctx->quit_req) {
        wkr_ctx->reset_req = 0;
        ret = -1;
        sys_jobq_node_t* job_node = sys_jobq_dequeue(&wkr_ctx->job_in);
        if (!job_node) {
            // idle
            usleep(100);
            continue;
        }
        int job_type = job_node->job_type;
        // got job to do
        zlog_notice(sys_zc, "wkr#%d> start job: job_type=%s",
                             wkr_id, cmi_desc_cmdtype2str(job_type));

        if (job_node->job_type == cmd_type_config) {
            // config : immediate job
            ret = __sys_job_do_config(wkr_ctx, epid, ips_pcid,
                                      (char*)job_node->cmd_ref->u.all.words,
                                      sizeof(job_node->cmd_ref->u.all));
            job_node->resp = ret;
            sys_jobq_enqueue(&wkr_ctx->job_out, job_node);
        } else if (job_node->job_type == cmd_type_start_rec) {
            // start_rec: deferred job
            int slot_id = (int)(intptr_t)job_node->arg;
            memset(&slot_def, 0, sizeof(dfv_slot_def_t));
            slot_def.repo = repo;
            slot_def.slot_id = slot_id;
            __JOB_RESPONSE(sys_state_rec, SPK_SUCCESS);
            spk_stats_reset(&wkr_ctx->stats);
            ret = __sys_job_do_record(wkr_ctx,
                                      epid, ips_pcid, ips_sec_sz,
                                      &slot_def, &slice_def);
            spk_stats_reset(&wkr_ctx->stats);
        } else if (job_node->job_type == cmd_type_start_play) {
            // start_play: deferred job
            uint64_t slot_sz = job_node->arg;
            int slot_id = job_node->cmd_ref->u.file.index;
            __JOB_RESPONSE(sys_state_play, SPK_SUCCESS);
            spk_stats_reset(&wkr_ctx->stats);
            memset(&slot_def, 0, sizeof(dfv_slot_def_t));
            slot_def.repo = repo;
            slot_def.slot_id = slot_id;
            ret = __sys_job_do_playback(wkr_ctx,
                                        epid, ips_pcid, ips_sec_sz,
                                        &slot_def, slot_sz);
            spk_stats_reset(&wkr_ctx->stats);
        } else if (job_node->job_type == cmd_type_start_dl) {
            // start_dl: immediate/deferred job
            assert(wkr_id == 0);
            int slot_id = job_node->cmd_ref->u.file.index;
            uint32_t req_frag = job_node->cmd_ref->u.file.frag_id;
            uint64_t blk_start = job_node->cmd_ref->u.file.blk_start;
            uint64_t blk_num = job_node->cmd_ref->u.file.blk_num;
            if (req_frag == (uint32_t)-1) {
                // fast mode : deferred
                __JOB_RESPONSE(sys_state_dl, SPK_SUCCESS);
                ret = __sys_job_do_download(wkr_ctx,
                                            slot_id,
                                            req_frag,
                                            blk_start,
                                            blk_num);
            } else {
                // slow mode: immediate
                ret = sys_func_dl_prepare(slot_id,
                                          blk_start,
                                          blk_num,
                                          req_frag);
                if (ret == SPK_SUCCESS) {
                    ret = sys_func_dl_sendfrag(slot_id,
                                               blk_start,
                                               blk_num,
                                               req_frag,
                                               NULL);
                }
                job_node->resp = ret;
                sys_jobq_enqueue(&wkr_ctx->job_out, job_node);
            }
        } else if (job_node->job_type == cmd_type_format) {
            // format: deferred job
            assert(wkr_id == 0);
            __JOB_RESPONSE(sys_state_format, SPK_SUCCESS);
            ret = dfv_vault_format(sys_ctx.vault);
            sys_ctx.diskcap = dfv_vault_get_diskcap(sys_ctx.vault);
        } else {
            // unknown job
            assert(0);
        }
        zlog_notice(sys_zc, "wkr#%d> job done: job_type=%s, ret=%d",
                             wkr_id, cmi_desc_cmdtype2str(job_type), ret);

        if (wkr_id == 0 && ret == SPKERR_RESETSYS) {
            zlog_warn(sys_zc, "wkr#%d> disconnect cmi due to errors", wkr_id);
            cmi_intf_disconnect(sys_ctx.cmi_intf);
        }

        wkr_ctx->wkr_state = sys_state_idle;
    }

    zlog_notice(sys_zc, "wkr#%d> terminated", wkr_id);

    return(NULL);
}
示例#22
0
/* Zebra client message read function. */
static int
zclient_read (struct thread *thread)
{
  size_t already;
  uint16_t length, command;
  uint8_t marker, version;
  struct zclient *zclient;

  /* Get socket to zebra. */
  zclient = THREAD_ARG (thread);
  zclient->t_read = NULL;

  /* Read zebra header (if we don't have it already). */
  if ((already = stream_get_endp(zclient->ibuf)) < ZEBRA_HEADER_SIZE)
    {
      ssize_t nbyte;
      if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
				     ZEBRA_HEADER_SIZE-already)) == 0) ||
	  (nbyte == -1))
	{
	  if (zclient_debug)
	   zlog_debug ("zclient connection closed socket [%d].", zclient->sock);
	  return zclient_failed(zclient);
	}
      if (nbyte != (ssize_t)(ZEBRA_HEADER_SIZE-already))
	{
	  /* Try again later. */
	  zclient_event (ZCLIENT_READ, zclient);
	  return 0;
	}
      already = ZEBRA_HEADER_SIZE;
    }

  /* Reset to read from the beginning of the incoming packet. */
  stream_set_getp(zclient->ibuf, 0);

  /* Fetch header values. */
  length = stream_getw (zclient->ibuf);
  marker = stream_getc (zclient->ibuf);
  version = stream_getc (zclient->ibuf);
  command = stream_getw (zclient->ibuf);
  
  if (marker != ZEBRA_HEADER_MARKER || version != ZSERV_VERSION)
    {
      zlog_err("%s: socket %d version mismatch, marker %d, version %d",
               __func__, zclient->sock, marker, version);
      return zclient_failed(zclient);
    }
  
  if (length < ZEBRA_HEADER_SIZE) 
    {
      zlog_err("%s: socket %d message length %u is less than %d ",
	       __func__, zclient->sock, length, ZEBRA_HEADER_SIZE);
      return zclient_failed(zclient);
    }

  /* Length check. */
  if (length > STREAM_SIZE(zclient->ibuf))
    {
      struct stream *ns;
      zlog_warn("%s: message size %u exceeds buffer size %lu, expanding...",
	        __func__, length, (u_long)STREAM_SIZE(zclient->ibuf));
      ns = stream_new(length);
      stream_copy(ns, zclient->ibuf);
      stream_free (zclient->ibuf);
      zclient->ibuf = ns;
    }

  /* Read rest of zebra packet. */
  if (already < length)
    {
      ssize_t nbyte;
      if (((nbyte = stream_read_try(zclient->ibuf, zclient->sock,
				     length-already)) == 0) ||
	  (nbyte == -1))
	{
	  if (zclient_debug)
	    zlog_debug("zclient connection closed socket [%d].", zclient->sock);
	  return zclient_failed(zclient);
	}
      if (nbyte != (ssize_t)(length-already))
	{
	  /* Try again later. */
	  zclient_event (ZCLIENT_READ, zclient);
	  return 0;
	}
    }

  length -= ZEBRA_HEADER_SIZE;

  if (zclient_debug)
    zlog_debug("zclient 0x%p command 0x%x \n", (void *)zclient, command);

  switch (command)
    {
    case ZEBRA_ROUTER_ID_UPDATE:
      if (zclient->router_id_update)
	(*zclient->router_id_update) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_ADD:
      if (zclient->interface_add)
	(*zclient->interface_add) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_DELETE:
      if (zclient->interface_delete)
	(*zclient->interface_delete) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_ADDRESS_ADD:
      if (zclient->interface_address_add)
	(*zclient->interface_address_add) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_ADDRESS_DELETE:
      if (zclient->interface_address_delete)
	(*zclient->interface_address_delete) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_UP:
      if (zclient->interface_up)
	(*zclient->interface_up) (command, zclient, length);
      break;
    case ZEBRA_INTERFACE_DOWN:
      if (zclient->interface_down)
	(*zclient->interface_down) (command, zclient, length);
      break;
    case ZEBRA_IPV4_ROUTE_ADD:
      if (zclient->ipv4_route_add)
	(*zclient->ipv4_route_add) (command, zclient, length);
      break;
    case ZEBRA_IPV4_ROUTE_DELETE:
      if (zclient->ipv4_route_delete)
	(*zclient->ipv4_route_delete) (command, zclient, length);
      break;
    case ZEBRA_IPV6_ROUTE_ADD:
      if (zclient->ipv6_route_add)
	(*zclient->ipv6_route_add) (command, zclient, length);
      break;
    case ZEBRA_IPV6_ROUTE_DELETE:
      if (zclient->ipv6_route_delete)
	(*zclient->ipv6_route_delete) (command, zclient, length);
      break;
    default:
      break;
    }

  if (zclient->sock < 0)
    /* Connection was closed during packet processing. */
    return -1;

  /* Register read thread. */
  stream_reset(zclient->ibuf);
  zclient_event (ZCLIENT_READ, zclient);

  return 0;
}
示例#23
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;
}
示例#24
0
/* Wake up configured address if it is not in current kernel
   address. */
void
if_addr_wakeup (struct interface *ifp)
{
  struct listnode *node;
  struct connected *ifc;
  struct prefix *p;
  int ret;

  for (node = listhead (ifp->connected); node; nextnode (node))
    {
      ifc = getdata (node);
      p = ifc->address;
	
      if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)
	  && ! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))
	{
	  /* Address check. */
	  if (p->family == AF_INET)
	    {
	      if (! if_is_up (ifp))
		{
		  if_set_flags (ifp, IFF_UP | IFF_RUNNING);
		  if_refresh (ifp);
		}

	      ret = if_set_prefix (ifp, ifc);
	      if (ret < 0)
		{
		  zlog_warn ("Can't set interface's address: %s", 
			     strerror(errno));
		  continue;
		}
	      SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);

	      zebra_interface_address_add_update (ifp, ifc);

	      if (if_is_up(ifp))
		connected_up_ipv4 (ifp, ifc);
	    }
#ifdef HAVE_IPV6
	  if (p->family == AF_INET6)
	    {
	      if (! if_is_up (ifp))
		{
		  if_set_flags (ifp, IFF_UP | IFF_RUNNING);
		  if_refresh (ifp);
		}

	      ret = if_prefix_add_ipv6 (ifp, ifc);
	      if (ret < 0)
		{
		  zlog_warn ("Can't set interface's address: %s", 
			     strerror(errno));
		  continue;
		}
	      SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);

	      zebra_interface_address_add_update (ifp, ifc);

	      if (if_is_up(ifp))
		connected_up_ipv6 (ifp, ifc);
	    }
#endif /* HAVE_IPV6 */
	}
    }
}
示例#25
0
/* Address read from struct ifa_msghdr. */
static void
ifam_read_mesg (struct ifa_msghdr *ifm,
		union sockunion *addr,
		union sockunion *mask,
		union sockunion *brd,
		char *ifname,
		short *ifnlen)
{
  caddr_t pnt, end;
  union sockunion dst;
  union sockunion gateway;

  pnt = (caddr_t)(ifm + 1);
  end = ((caddr_t)ifm) + ifm->ifam_msglen;

  /* Be sure structure is cleared */
  memset (mask, 0, sizeof (union sockunion));
  memset (addr, 0, sizeof (union sockunion));
  memset (brd, 0, sizeof (union sockunion));
  memset (&dst, 0, sizeof (union sockunion));
  memset (&gateway, 0, sizeof (union sockunion));

  /* We fetch each socket variable into sockunion. */
  RTA_ADDR_GET (&dst, RTA_DST, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (&gateway, RTA_GATEWAY, ifm->ifam_addrs, pnt);
  RTA_ATTR_GET (mask, RTA_NETMASK, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (NULL, RTA_GENMASK, ifm->ifam_addrs, pnt);
  RTA_NAME_GET (ifname, RTA_IFP, ifm->ifam_addrs, pnt, *ifnlen);
  RTA_ADDR_GET (addr, RTA_IFA, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (NULL, RTA_AUTHOR, ifm->ifam_addrs, pnt);
  RTA_ADDR_GET (brd, RTA_BRD, ifm->ifam_addrs, pnt);

  if (IS_ZEBRA_DEBUG_KERNEL)
    {
      switch (sockunion_family(addr))
        {
	case AF_INET:
	  {
	    char buf[4][INET_ADDRSTRLEN];
	    zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
			"ifam_flags 0x%x, addr %s/%d broad %s dst %s "
			"gateway %s",
			__func__, ifm->ifam_index,
			(ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
			ifm->ifam_flags,
			inet_ntop(AF_INET,&addr->sin.sin_addr,
			          buf[0],sizeof(buf[0])),
			ip_masklen(mask->sin.sin_addr),
			inet_ntop(AF_INET,&brd->sin.sin_addr,
			          buf[1],sizeof(buf[1])),
			inet_ntop(AF_INET,&dst.sin.sin_addr,
			          buf[2],sizeof(buf[2])),
			inet_ntop(AF_INET,&gateway.sin.sin_addr,
			          buf[3],sizeof(buf[3])));
	  }
	  break;
#ifdef HAVE_IPV6
	case AF_INET6:
	  {
	    char buf[4][INET6_ADDRSTRLEN];
	    zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x, "
			"ifam_flags 0x%x, addr %s/%d broad %s dst %s "
			"gateway %s",
			__func__, ifm->ifam_index, 
			(ifnlen ? ifname : "(nil)"), ifm->ifam_addrs,
			ifm->ifam_flags,
			inet_ntop(AF_INET6,&addr->sin6.sin6_addr,
			          buf[0],sizeof(buf[0])),
			ip6_masklen(mask->sin6.sin6_addr),
			inet_ntop(AF_INET6,&brd->sin6.sin6_addr,
			          buf[1],sizeof(buf[1])),
			inet_ntop(AF_INET6,&dst.sin6.sin6_addr,
			          buf[2],sizeof(buf[2])),
			inet_ntop(AF_INET6,&gateway.sin6.sin6_addr,
			          buf[3],sizeof(buf[3])));
	  }
	  break;
#endif /* HAVE_IPV6 */
        default:
	  zlog_debug ("%s: ifindex %d, ifname %s, ifam_addrs 0x%x",
		      __func__, ifm->ifam_index, 
		      (ifnlen ? ifname : "(nil)"), ifm->ifam_addrs);
	  break;
        }
    }

  /* Assert read up end point matches to end point */
  if (pnt != end)
    zlog_warn ("ifam_read() does't read all socket data");
}
示例#26
0
struct isis_circuit *
isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg)
{
	int old_state;

	old_state = circuit ? circuit->state : C_STATE_NA;
	if (isis->debugs & DEBUG_EVENTS)
		zlog_debug("CSM_EVENT: %s", EVENT2STR(event));

	switch (old_state) {
	case C_STATE_NA:
		if (circuit)
			zlog_warn("Non-null circuit while state C_STATE_NA");
		assert(circuit == NULL);
		switch (event) {
		case ISIS_ENABLE:
			circuit = isis_circuit_new();
			isis_circuit_configure(circuit,
					       (struct isis_area *)arg);
			circuit->state = C_STATE_CONF;
			break;
		case IF_UP_FROM_Z:
			circuit = isis_circuit_new();
			isis_circuit_if_add(circuit, (struct interface *)arg);
			listnode_add(isis->init_circ_list, circuit);
			circuit->state = C_STATE_INIT;
			break;
		case ISIS_DISABLE:
			zlog_warn("circuit already disabled");
			break;
		case IF_DOWN_FROM_Z:
			zlog_warn("circuit already disconnected");
			break;
		}
		break;
	case C_STATE_INIT:
		assert(circuit);
		switch (event) {
		case ISIS_ENABLE:
			isis_circuit_configure(circuit,
					       (struct isis_area *)arg);
			if (isis_circuit_up(circuit) != ISIS_OK) {
				isis_circuit_deconfigure(
					circuit, (struct isis_area *)arg);
				break;
			}
			circuit->state = C_STATE_UP;
			isis_event_circuit_state_change(circuit, circuit->area,
							1);
			listnode_delete(isis->init_circ_list, circuit);
			break;
		case IF_UP_FROM_Z:
			assert(circuit);
			zlog_warn("circuit already connected");
			break;
		case ISIS_DISABLE:
			zlog_warn("circuit already disabled");
			break;
		case IF_DOWN_FROM_Z:
			isis_circuit_if_del(circuit, (struct interface *)arg);
			listnode_delete(isis->init_circ_list, circuit);
			isis_circuit_del(circuit);
			circuit = NULL;
			break;
		}
		break;
	case C_STATE_CONF:
		assert(circuit);
		switch (event) {
		case ISIS_ENABLE:
			zlog_warn("circuit already enabled");
			break;
		case IF_UP_FROM_Z:
			isis_circuit_if_add(circuit, (struct interface *)arg);
			if (isis_circuit_up(circuit) != ISIS_OK) {
				flog_err(
					ISIS_ERR_CONFIG,
					"Could not bring up %s because of invalid config.",
					circuit->interface->name);
				flog_err(
					ISIS_ERR_CONFIG,
					"Clearing config for %s. Please re-examine it.",
					circuit->interface->name);
				if (circuit->ip_router) {
					circuit->ip_router = 0;
					circuit->area->ip_circuits--;
				}
				if (circuit->ipv6_router) {
					circuit->ipv6_router = 0;
					circuit->area->ipv6_circuits--;
				}
				circuit_update_nlpids(circuit);
				isis_circuit_deconfigure(circuit,
							 circuit->area);
				listnode_add(isis->init_circ_list, circuit);
				circuit->state = C_STATE_INIT;
				break;
			}
			circuit->state = C_STATE_UP;
			isis_event_circuit_state_change(circuit, circuit->area,
							1);
			break;
		case ISIS_DISABLE:
			isis_circuit_deconfigure(circuit,
						 (struct isis_area *)arg);
			isis_circuit_del(circuit);
			circuit = NULL;
			break;
		case IF_DOWN_FROM_Z:
			zlog_warn("circuit already disconnected");
			break;
		}
		break;
	case C_STATE_UP:
		assert(circuit);
		switch (event) {
		case ISIS_ENABLE:
			zlog_warn("circuit already configured");
			break;
		case IF_UP_FROM_Z:
			zlog_warn("circuit already connected");
			break;
		case ISIS_DISABLE:
			isis_circuit_down(circuit);
			isis_circuit_deconfigure(circuit,
						 (struct isis_area *)arg);
			circuit->state = C_STATE_INIT;
			isis_event_circuit_state_change(
				circuit, (struct isis_area *)arg, 0);
			listnode_add(isis->init_circ_list, circuit);
			break;
		case IF_DOWN_FROM_Z:
			isis_circuit_down(circuit);
			isis_circuit_if_del(circuit, (struct interface *)arg);
			circuit->state = C_STATE_CONF;
			isis_event_circuit_state_change(circuit, circuit->area,
							0);
			break;
		}
		break;

	default:
		zlog_warn("Invalid circuit state %d", old_state);
	}

	if (isis->debugs & DEBUG_EVENTS)
		zlog_debug("CSM_STATE_CHANGE: %s -> %s ", STATE2STR(old_state),
			   circuit ? STATE2STR(circuit->state)
				   : STATE2STR(C_STATE_NA));

	return circuit;
}
示例#27
0
/* Interface function for the kernel routing table updates.  Support
 * for RTM_CHANGE will be needed.
 * Exported only for rt_socket.c
 */
int
rtm_write (int message,
	   union sockunion *dest,
	   union sockunion *mask,
	   union sockunion *gate,
	   unsigned int index,
	   int zebra_flags,
	   int metric)
{
  int ret;
  caddr_t pnt;
  struct interface *ifp;

  /* Sequencial number of routing message. */
  static int msg_seq = 0;

  /* Struct of rt_msghdr and buffer for storing socket's data. */
  struct 
  {
    struct rt_msghdr rtm;
    char buf[512];
  } msg;
  
  if (routing_sock < 0)
    return ZEBRA_ERR_EPERM;

  /* Clear and set rt_msghdr values */
  memset (&msg, 0, sizeof (struct rt_msghdr));
  msg.rtm.rtm_version = RTM_VERSION;
  msg.rtm.rtm_type = message;
  msg.rtm.rtm_seq = msg_seq++;
  msg.rtm.rtm_addrs = RTA_DST;
  msg.rtm.rtm_addrs |= RTA_GATEWAY;
  msg.rtm.rtm_flags = RTF_UP;
  msg.rtm.rtm_index = index;

  if (metric != 0)
    {
      msg.rtm.rtm_rmx.rmx_hopcount = metric;
      msg.rtm.rtm_inits |= RTV_HOPCOUNT;
    }

  ifp = if_lookup_by_index (index);

  if (gate && message == RTM_ADD)
    msg.rtm.rtm_flags |= RTF_GATEWAY;

  /* When RTF_CLONING is unavailable on BSD, should we set some
   * other flag instead?
   */
#ifdef RTF_CLONING
  if (! gate && message == RTM_ADD && ifp &&
      (ifp->flags & IFF_POINTOPOINT) == 0)
    msg.rtm.rtm_flags |= RTF_CLONING;
#endif /* RTF_CLONING */

  /* If no protocol specific gateway is specified, use link
     address for gateway. */
  if (! gate)
    {
      if (!ifp)
        {
          char dest_buf[INET_ADDRSTRLEN] = "NULL", mask_buf[INET_ADDRSTRLEN] = "255.255.255.255";
          if (dest)
            inet_ntop (AF_INET, &dest->sin.sin_addr, dest_buf, INET_ADDRSTRLEN);
          if (mask)
            inet_ntop (AF_INET, &mask->sin.sin_addr, mask_buf, INET_ADDRSTRLEN);
          zlog_warn ("%s: %s/%s: gate == NULL and no gateway found for ifindex %d",
            __func__, dest_buf, mask_buf, index);
          return -1;
        }
      gate = (union sockunion *) & ifp->sdl;
    }

  if (mask)
    msg.rtm.rtm_addrs |= RTA_NETMASK;
  else if (message == RTM_ADD) 
    msg.rtm.rtm_flags |= RTF_HOST;

  /* Tagging route with flags */
  msg.rtm.rtm_flags |= (RTF_PROTO1);

  /* Additional flags. */
  if (zebra_flags & ZEBRA_FLAG_BLACKHOLE)
    msg.rtm.rtm_flags |= RTF_BLACKHOLE;
  if (zebra_flags & ZEBRA_FLAG_REJECT)
    msg.rtm.rtm_flags |= RTF_REJECT;


#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
#define SOCKADDRSET(X,R) \
  if (msg.rtm.rtm_addrs & (R)) \
    { \
      int len = ROUNDUP ((X)->sa.sa_len); \
      memcpy (pnt, (caddr_t)(X), len); \
      pnt += len; \
    }
#else 
#define SOCKADDRSET(X,R) \
  if (msg.rtm.rtm_addrs & (R)) \
    { \
      int len = SAROUNDUP (X); \
      memcpy (pnt, (caddr_t)(X), len); \
      pnt += len; \
    }
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */

  pnt = (caddr_t) msg.buf;

  /* Write each socket data into rtm message buffer */
  SOCKADDRSET (dest, RTA_DST);
  SOCKADDRSET (gate, RTA_GATEWAY);
  SOCKADDRSET (mask, RTA_NETMASK);

  msg.rtm.rtm_msglen = pnt - (caddr_t) &msg;

  ret = write (routing_sock, &msg, msg.rtm.rtm_msglen);

  if (ret != msg.rtm.rtm_msglen) 
    {
      if (errno == EEXIST) 
	return ZEBRA_ERR_RTEXIST;
      if (errno == ENETUNREACH)
	return ZEBRA_ERR_RTUNREACH;
      if (errno == ESRCH)
	return ZEBRA_ERR_RTNOEXIST;
      
      zlog_warn ("%s: write : %s (%d)", __func__, safe_strerror (errno), errno);
      return ZEBRA_ERR_KERNEL;
    }
  return ZEBRA_ERR_NOERROR;
}
示例#28
0
文件: buffer.c 项目: rgmabs19357/HA
/* Flush enough data to fill a terminal window of the given scene (used only
   by vty telnet interface). */
buffer_status_t
buffer_flush_window (struct buffer *b, int fd, int width, int height, 
		     int erase_flag, int no_more_flag)
{
  int nbytes;
  int iov_alloc;
  int iov_index;
  struct iovec *iov;
  struct iovec small_iov[3];
  char more[] = " --More-- ";
  char erase[] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
		   ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
		   0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
  struct buffer_data *data;
  int column;

  if (!b->head)
    return BUFFER_EMPTY;

  if (height < 1)
    {
      zlog_warn("%s called with non-positive window height %d, forcing to 1",
      		__func__, height);
      height = 1;
    }
  else if (height >= 2)
    height--;
  if (width < 1)
    {
      zlog_warn("%s called with non-positive window width %d, forcing to 1",
      		__func__, width);
      width = 1;
    }

  /* For erase and more data add two to b's buffer_data count.*/
  if (b->head->next == NULL)
    {
      iov_alloc = sizeof(small_iov)/sizeof(small_iov[0]);
      iov = small_iov;
    }
  else
    {
      iov_alloc = ((height*(width+2))/b->size)+10;
      iov = XMALLOC(MTYPE_TMP, iov_alloc*sizeof(*iov));
    }
  iov_index = 0;

  /* Previously print out is performed. */
  if (erase_flag)
    {
      iov[iov_index].iov_base = erase;
      iov[iov_index].iov_len = sizeof erase;
      iov_index++;
    }

  /* Output data. */
  column = 1;  /* Column position of next character displayed. */
  for (data = b->head; data && (height > 0); data = data->next)
    {
      size_t cp;

      cp = data->sp;
      while ((cp < data->cp) && (height > 0))
        {
	  /* Calculate lines remaining and column position after displaying
	     this character. */
	  if (data->data[cp] == '\r')
	    column = 1;
	  else if ((data->data[cp] == '\n') || (column == width))
	    {
	      column = 1;
	      height--;
	    }
	  else
	    column++;
	  cp++;
        }
      iov[iov_index].iov_base = (char *)(data->data + data->sp);
      iov[iov_index++].iov_len = cp-data->sp;
      data->sp = cp;

      if (iov_index == iov_alloc)
	/* This should not ordinarily happen. */
        {
	  iov_alloc *= 2;
	  if (iov != small_iov)
	    {
	      zlog_warn("%s: growing iov array to %d; "
			"width %d, height %d, size %lu",
			__func__, iov_alloc, width, height, (u_long)b->size);
	      iov = XREALLOC(MTYPE_TMP, iov, iov_alloc*sizeof(*iov));
	    }
	  else
	    {
	      /* This should absolutely never occur. */
	      zlog_err("%s: corruption detected: iov_small overflowed; "
		       "head %p, tail %p, head->next %p",
		       __func__, b->head, b->tail, b->head->next);
	      iov = XMALLOC(MTYPE_TMP, iov_alloc*sizeof(*iov));
	      memcpy(iov, small_iov, sizeof(small_iov));
	    }
	}
    }

  /* In case of `more' display need. */
  if (b->tail && (b->tail->sp < b->tail->cp) && !no_more_flag)
    {
      iov[iov_index].iov_base = more;
      iov[iov_index].iov_len = sizeof more;
      iov_index++;
    }


#ifdef IOV_MAX
  /* IOV_MAX are normally defined in <sys/uio.h> , Posix.1g.
     example: Solaris2.6 are defined IOV_MAX size at 16.     */
  {
    struct iovec *c_iov = iov;
    nbytes = 0; /* Make sure it's initialized. */

    while (iov_index > 0)
      {
	 int iov_size;

	 iov_size = ((iov_index > IOV_MAX) ? IOV_MAX : iov_index);
	 if ((nbytes = writev(fd, c_iov, iov_size)) < 0)
	   {
	     zlog_warn("%s: writev to fd %d failed: %s",
		       __func__, fd, safe_strerror(errno));
	     break;
	   }

	 /* move pointer io-vector */
	 c_iov += iov_size;
	 iov_index -= iov_size;
      }
  }
#else  /* IOV_MAX */
   if ((nbytes = writev (fd, iov, iov_index)) < 0)
     zlog_warn("%s: writev to fd %d failed: %s",
	       __func__, fd, safe_strerror(errno));
#endif /* IOV_MAX */

  /* Free printed buffer data. */
  while (b->head && (b->head->sp == b->head->cp))
    {
      struct buffer_data *del;
      if (!(b->head = (del = b->head)->next))
        b->tail = NULL;
      BUFFER_DATA_FREE(del);
    }

  if (iov != small_iov)
    XFREE (MTYPE_TMP, iov);

  return (nbytes < 0) ? BUFFER_ERROR :
  			(b->head ? BUFFER_PENDING : BUFFER_EMPTY);
}
示例#29
0
int isis_recv_pdu_bcast(struct isis_circuit *circuit, uint8_t *ssnpa)
{
	struct pollfd fds[1];
	struct strbuf ctlbuf, databuf;
	int flags, retv;
	dl_unitdata_ind_t *dui = (dl_unitdata_ind_t *)dlpi_ctl;

	memset(fds, 0, sizeof(fds));
	fds[0].fd = circuit->fd;
	fds[0].events = POLLIN | POLLPRI;
	if (poll(fds, 1, 0) <= 0)
		return ISIS_WARNING;

	memset(&ctlbuf, 0, sizeof(ctlbuf));
	memset(&databuf, 0, sizeof(databuf));
	ctlbuf.maxlen = sizeof(dlpi_ctl);
	ctlbuf.buf = (void *)dlpi_ctl;
	databuf.maxlen = sizeof(sock_buff);
	databuf.buf = (void *)sock_buff;
	flags = 0;
	retv = getmsg(circuit->fd, &ctlbuf, &databuf, &flags);

	if (retv < 0) {
		zlog_warn("isis_recv_pdu_bcast: getmsg failed: %s",
			  safe_strerror(errno));
		return ISIS_WARNING;
	}

	if (retv & (MORECTL | MOREDATA)) {
		while (retv & (MORECTL | MOREDATA)) {
			flags = 0;
			retv = getmsg(circuit->fd, &ctlbuf, &databuf, &flags);
		}
		return ISIS_WARNING;
	}

	if (ctlbuf.len < (ssize_t)DL_UNITDATA_IND_SIZE
	    || dui->dl_primitive != DL_UNITDATA_IND)
		return ISIS_WARNING;

	if (dui->dl_src_addr_length != ETHERADDRL + 2
	    || dui->dl_src_addr_offset < DL_UNITDATA_IND_SIZE
	    || dui->dl_src_addr_offset + dui->dl_src_addr_length
		       > (size_t)ctlbuf.len)
		return ISIS_WARNING;

	memcpy(ssnpa,
	       (char *)dui + dui->dl_src_addr_offset
		       + (circuit->sap_length > 0 ? circuit->sap_length : 0),
	       ETHERADDRL);

	if (databuf.len < LLC_LEN || sock_buff[0] != ISO_SAP
	    || sock_buff[1] != ISO_SAP || sock_buff[2] != 3)
		return ISIS_WARNING;

	stream_write(circuit->rcv_stream, sock_buff + LLC_LEN,
		     databuf.len - LLC_LEN);
	stream_set_getp(circuit->rcv_stream, 0);

	return ISIS_OK;
}
示例#30
0
/* Routing information change from the kernel. */
int
netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h)
{
    int len;
    struct rtmsg *rtm;
    struct rtattr *tb [RTA_MAX + 1];

    char anyaddr[16] = {0};

    int index;
    int table;
    void *dest;
    void *gate;

    rtm = NLMSG_DATA (h);

    if (! (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE))
    {
        /* If this is not route add/delete message print warning. */
        zlog_warn ("Kernel message: %d\n", h->nlmsg_type);
        return 0;
    }

    /* Connected route. */
    if (IS_ZEBRA_DEBUG_KERNEL)
        zlog_info ("%s %s %s proto %s",
                   h->nlmsg_type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
                   rtm->rtm_family == AF_INET ? "ipv4" : "ipv6",
                   rtm->rtm_type == RTN_UNICAST ? "unicast" : "multicast",
                   lookup (rtproto_str, rtm->rtm_protocol));

    if (rtm->rtm_type != RTN_UNICAST)
    {
        return 0;
    }

    table = rtm->rtm_table;
    if (table != RT_TABLE_MAIN && table != rtm_table_default)
    {
        return 0;
    }

    len = h->nlmsg_len - NLMSG_LENGTH(sizeof (struct rtmsg));
    if (len < 0)
        return -1;

    memset (tb, 0, sizeof tb);
    netlink_parse_rtattr (tb, RTA_MAX, RTM_RTA (rtm), len);

    if (rtm->rtm_flags & RTM_F_CLONED)
        return 0;
    if (rtm->rtm_protocol == RTPROT_REDIRECT)
        return 0;
    if (rtm->rtm_protocol == RTPROT_KERNEL)
        return 0;

    if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE)
        return 0;

    if (rtm->rtm_src_len != 0)
    {
        zlog_warn ("netlink_route_change(): no src len");
        return 0;
    }

    index = 0;
    dest = NULL;
    gate = NULL;

    if (tb[RTA_OIF])
        index = *(int *) RTA_DATA (tb[RTA_OIF]);

    if (tb[RTA_DST])
        dest = RTA_DATA (tb[RTA_DST]);
    else
        dest = anyaddr;

    if (tb[RTA_GATEWAY])
        gate = RTA_DATA (tb[RTA_GATEWAY]);

    if (rtm->rtm_family == AF_INET)
    {
        struct prefix_ipv4 p;
        p.family = AF_INET;
        memcpy (&p.prefix, dest, 4);
        p.prefixlen = rtm->rtm_dst_len;

        if (IS_ZEBRA_DEBUG_KERNEL)
        {
            if (h->nlmsg_type == RTM_NEWROUTE)
                zlog_info ("RTM_NEWROUTE %s/%d",
                           inet_ntoa (p.prefix), p.prefixlen);
            else
                zlog_info ("RTM_DELROUTE %s/%d",
                           inet_ntoa (p.prefix), p.prefixlen);
        }

        if (h->nlmsg_type == RTM_NEWROUTE)
            rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table, 0, 0);
        else
            rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, table);
    }

#ifdef HAVE_IPV6
    if (rtm->rtm_family == AF_INET6)
    {
        struct prefix_ipv6 p;
        char buf[BUFSIZ];

        p.family = AF_INET6;
        memcpy (&p.prefix, dest, 16);
        p.prefixlen = rtm->rtm_dst_len;

        if (IS_ZEBRA_DEBUG_KERNEL)
        {
            if (h->nlmsg_type == RTM_NEWROUTE)
                zlog_info ("RTM_NEWROUTE %s/%d",
                           inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
                           p.prefixlen);
            else
                zlog_info ("RTM_DELROUTE %s/%d",
                           inet_ntop (AF_INET6, &p.prefix, buf, BUFSIZ),
                           p.prefixlen);
        }

        if (h->nlmsg_type == RTM_NEWROUTE)
            rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
        else
            rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL, 0, &p, gate, index, 0);
    }
#endif /* HAVE_IPV6 */

    return 0;
}