Exemple #1
0
static void
print_stream (struct stream *s)
{
  size_t getp = stream_get_getp (s);
  
  printf ("endp: %zu, readable: %zu, writeable: %zu\n",
          stream_get_endp (s),
          STREAM_READABLE (s),
          STREAM_WRITEABLE (s));
  
  while (STREAM_READABLE (s))
    {
      printf ("0x%x ", *stream_pnt (s));
      stream_forward_getp (s, 1);
    }
  
  printf ("\n");
  
  /* put getp back to where it was */
  stream_set_getp (s, getp);
}
static int mcp_ppp_all_config_syn_parse_update(struct stream *data_s)
{
	int type;
	int len;
	struct stream* tmp_s;

    tmp_s = stream_new(10240);
	while(STREAM_READABLE(data_s) >= 4)
	{
		type = stream_getw(data_s);
		len = stream_getw(data_s);
		//zlog_debug("<%s,%d> type:%d len:%d", __FUNCTION__, __LINE__, type, len);

        if(len == 0)
            continue;
            
		switch(type)
		{
		    case MCP_PPPD_CONFIG_SYN_REMOT_USERINFO: 
				stream_put(tmp_s, data_s->data + stream_get_getp(data_s), len);
				mcp_recv_pppd_remote_userinfo_ack(tmp_s);
				stream_forward_getp(data_s, len);
				stream_reset(tmp_s);
				break;
				
			case MCP_PPPD_CONFIG_SYN_MULTILINK_INFO: 
				stream_put(tmp_s, data_s->data + stream_get_getp(data_s), len);
				mcp_recv_pppd_multilink_info_ack(tmp_s);
				stream_forward_getp(data_s, len);
				stream_reset(tmp_s);
				break;

			case MCP_PPPD_CONFIG_SYN_INTERFACE_INFO: 
			    stream_put(tmp_s, data_s->data + stream_get_getp(data_s), len);
			    mcp_recv_pppd_interface_info_ack(tmp_s, 1);
				stream_forward_getp(data_s, len);
				stream_reset(tmp_s);
				break;
			    
			default:
				zlog_err("mcp<%s:%d> wrong type:%u",__FUNCTION__,__LINE__,type);
				goto error;
		}		
	}

    stream_free(tmp_s);
	return 0;

error:
    stream_free(tmp_s);
	return -1;	
}
static struct list* mcp_pppd_interface_parse(struct stream *data_s)
{
	int type;
	int len;
	struct list* digt_list;
	struct pppd_interface_info* info = NULL;

    digt_list = list_new();
    digt_list->del = (void (*) (void *))mcp_ppp_config_info_free;
	
	while(STREAM_READABLE(data_s) >= 4)
	{
		type = stream_getw(data_s);
		len = stream_getw(data_s);
		//zlog_debug("<%s,%d> type:%d len:%d", __FUNCTION__, __LINE__, type, len);
		if(STREAM_READABLE(data_s) < 2) {
			zlog_err("mcp<%s:%d> stream readable bytes %d less %d",__FUNCTION__,__LINE__,((data_s)->endp-(data_s)->getp),len);
			return NULL;
		}

		switch(type)
		{
		    case PPP_INTERFACE_SEQ: 
		        info = mcp_pppd_interface_new();
				info->seq = stream_getl(data_s);
				//zlog_err("yang test ...seq:%u", (info->seq));
				break;
				
			case PPP_INTERFACE_GWID: 
				info->gwid= stream_getl(data_s);
				//zlog_err("yang test ...gwid:%s", remark_ip2str(info->gwid));
				break;

			case PPP_INTERFACE_SEVTYPE: 
			    info->dev_type = stream_getl(data_s);
				//zlog_err("yang test ...dev_type:%u", (info->dev_type));
				break;
				
            case PPP_INTERFACE_INTERFACEID:
                info->interfaceid = stream_getl(data_s);
				//zlog_err("yang test ...dev_type:%u", (info->dev_type));
				break;

			case PPP_INTERFACE_MULTIFLAGE:
			    info->multi_group = stream_getl(data_s);
				//zlog_err("yang test ...multi_flag:%u", (info->multi_group));
				break;
				
			case PPP_INTERFACE_INTERFACEIP: 
			    memset(info->interfaceip, 0, sizeof(info->interfaceip));
				stream_get(info->interfaceip, data_s, len);
				//zlog_err("yang test interfaceip:%s", info->interfaceip);
				break;

			case PPP_INTERFACE_ENABLE:
			    info->enable = stream_getl(data_s);
			    break;

			case PPP_INTERFACE_AUTHTYPE:
			    info->auth_type = stream_getl(data_s);
				//zlog_err("yang test ...auth_type:%u", (info->auth_type));
			    break;
			    
			case PPP_INTERFACE_AUTHNAME:
			    memset(info->auth_name, 0, sizeof(info->auth_name));
				stream_get(info->auth_name, data_s, len);
				//zlog_err("yang test auth_name:%s", info->auth_name);
				break;

			case PPP_INTERFACE_USERNAME:
			    memset(info->username, 0, sizeof(info->username));
				stream_get(info->username, data_s, len);
				//zlog_err("yang test username:%s", info->username);
                break;
                
			case PPP_INTERFACE_PSWD:
				memset(info->pswd, 0, sizeof(info->pswd));
				stream_get(info->pswd, data_s, len);
				//zlog_err("yang test pswd:%s", info->pswd);
                break;

            case PPP_INTERFACE_TIME:
				memset(info->time, 0, sizeof(info->time));
				stream_get(info->time, data_s, len);
				//zlog_err("yang test time:%s", info->time);
                break;
                
            case PPP_INTERFACE_REMARK:
                memset(info->remark, 0, sizeof(info->remark));
				stream_get(info->remark, data_s, len);
				//zlog_err("yang test remark:%s", info->remark);
                break;

             case PPP_INTERFACE_ACTION:
                info->action = stream_getl(data_s);
                listnode_add(digt_list, info);
				//zlog_err("yang test ...action:%u", (info->action));
                break;
            
			default:
			    list_delete(digt_list);
				zlog_err("mcp<%s:%d> wrong type:%u",__FUNCTION__,__LINE__,type);
				goto error;
		}		
	}

	return digt_list;

error:
	return NULL;	
}
static struct list* mcp_ppp_multilink_info_parse(struct stream *data_s)
{
	int type;
	int len;
	struct list* digt_list;
	struct pppd_multilink_info* info = NULL;

    digt_list = list_new();
    digt_list->del = (void (*) (void *))mcp_ppp_config_info_free;
	
	while(STREAM_READABLE(data_s) >= 4)
	{
		type = stream_getw(data_s);
		len = stream_getw(data_s);
		//zlog_debug("<%s,%d> type:%d len:%d", __FUNCTION__, __LINE__, type, len);
		if(STREAM_READABLE(data_s) < 2) {
			zlog_err("mcp<%s:%d> stream readable bytes %d less %d",__FUNCTION__,__LINE__,((data_s)->endp-(data_s)->getp),len);
			return NULL;
		}

		switch(type)
		{
		    case PPP_MULTILINK_INFO_SEQ: 
		        info = mcp_pppd_multilink_malloc_new();
				info->seq = stream_getl(data_s);
				//zlog_err("yang test ...seq:%u", (info->seq));
				break;
				
			case PPP_MULTILINK_INFO_GWID: 
				info->gwid= stream_getl(data_s);
				//zlog_err("yang test ...gwid:%s", remark_ip2str(info->gwid));
				break;

			case PPP_MULTILINK_INFO_MULTIIP: 
			    memset(info->multi_ip, 0, sizeof(info->multi_ip));
				stream_get(info->multi_ip, data_s, len);
				//zlog_err("yang test multi_ip:%s", info->multi_ip);
				break;
				
            case PPP_MULTILINK_INFO_TIME:
                memset(info->create_time, 0, sizeof(info->create_time));
                stream_get(info->create_time, data_s, len);
				//zlog_err("yang test create_time:%s", info->create_time);
				break;
				
			case PPP_MULTILINK_INFO_REMARK: 
			    memset(info->remark, 0, sizeof(info->remark));
				stream_get(info->remark, data_s, len);
				//zlog_err("yang test remark:%s", info->remark);
				break;

			case PPP_MULTILINK_INFO_ACTION:
			    info->action = stream_getl(data_s);
			    listnode_add(digt_list, info);
				//zlog_err("yang test ...action:%u", (info->action));
				break;
			    
			default:
			    list_delete(digt_list);
				zlog_err("mcp<%s:%d> wrong type:%u",__FUNCTION__,__LINE__,type);
				goto error;
		}		
	}

	return digt_list;

error:
	return NULL;	
}
Exemple #5
0
/**
 * Parse open option.
 *
 * @param[out] mp_capability @see bgp_capability_parse() for semantics.
 */
int
bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
{
  int ret;
  u_char *error;
  u_char error_data[BGP_MAX_PACKET_SIZE];
  struct stream *s = BGP_INPUT(peer);
  size_t end = stream_get_getp (s) + length;

  ret = 0;
  error = error_data;

  if (BGP_DEBUG (normal, NORMAL))
    zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
	       peer->host, length);
  
  while (stream_get_getp(s) < end)
    {
      u_char opt_type;
      u_char opt_length;
      
      /* Must have at least an OPEN option header */
      if (STREAM_READABLE(s) < 2)
	{
	  zlog_info ("%s Option length error", peer->host);
	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
	  return -1;
	}

      /* Fetch option type and length. */
      opt_type = stream_getc (s);
      opt_length = stream_getc (s);
      
      /* Option length check. */
      if (STREAM_READABLE (s) < opt_length)
	{
	  zlog_info ("%s Option length error", peer->host);
	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
	  return -1;
	}

      if (BGP_DEBUG (normal, NORMAL))
	zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
		   peer->host, opt_type,
		   opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
		   opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
		   opt_length);
  
      switch (opt_type)
	{
	case BGP_OPEN_OPT_AUTH:
	  ret = bgp_auth_parse (peer, opt_length);
	  break;
	case BGP_OPEN_OPT_CAP:
	  ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
	  break;
	default:
	  bgp_notify_send (peer, 
			   BGP_NOTIFY_OPEN_ERR, 
			   BGP_NOTIFY_OPEN_UNSUP_PARAM); 
	  ret = -1;
	  break;
	}

      /* Parse error.  To accumulate all unsupported capability codes,
         bgp_capability_parse does not return -1 when encounter
         unsupported capability code.  To detect that, please check
         error and erro_data pointer, like below.  */
      if (ret < 0)
	return -1;
    }

  /* All OPEN option is parsed.  Check capability when strict compare
     flag is enabled.*/
  if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
    {
      /* If Unsupported Capability exists. */
      if (error != error_data)
	{
	  bgp_notify_send_with_data (peer, 
				     BGP_NOTIFY_OPEN_ERR, 
				     BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
				     error_data, error - error_data);
	  return -1;
	}

      /* Check local capability does not negotiated with remote
         peer. */
      if (! strict_capability_same (peer))
	{
	  bgp_notify_send (peer, 
			   BGP_NOTIFY_OPEN_ERR, 
			   BGP_NOTIFY_OPEN_UNSUP_CAPBL);
	  return -1;
	}
    }

  /* Check there are no common AFI/SAFIs and send Unsupported Capability
     error. */
  if (*mp_capability &&
      ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
    {
      if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] 
	  && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
	  && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
	  && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
	  && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
	{
	  plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
		    "overlap with received MP capabilities",
		    peer->host);

	  if (error != error_data)

	    bgp_notify_send_with_data (peer, 
				       BGP_NOTIFY_OPEN_ERR, 
				       BGP_NOTIFY_OPEN_UNSUP_CAPBL, 
				       error_data, error - error_data);
	  else
	    bgp_notify_send (peer, 
			     BGP_NOTIFY_OPEN_ERR, 
			     BGP_NOTIFY_OPEN_UNSUP_CAPBL);
	  return -1;
	}
    }
  return 0;
}
Exemple #6
0
/* peek into option, stores ASN to *as4 if the AS4 capability was found.
 * Returns  0 if no as4 found, as4cap value otherwise.
 */
as_t
peek_for_as4_capability (struct peer *peer, u_char length)
{
  struct stream *s = BGP_INPUT (peer);
  size_t orig_getp = stream_get_getp (s);
  size_t end = orig_getp + length;
  as_t as4 = 0;
  
  /* The full capability parser will better flag the error.. */
  if (STREAM_READABLE(s) < length)
    return 0;

  if (BGP_DEBUG (as4, AS4))
    zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
                " peeking for as4",
	        peer->host, length);
  /* the error cases we DONT handle, we ONLY try to read as4 out of
   * correctly formatted options.
   */
  while (stream_get_getp(s) < end) 
    {
      u_char opt_type;
      u_char opt_length;
      
      /* Check the length. */
      if (stream_get_getp (s) + 2 > end)
        goto end;
      
      /* Fetch option type and length. */
      opt_type = stream_getc (s);
      opt_length = stream_getc (s);
      
      /* Option length check. */
      if (stream_get_getp (s) + opt_length > end)
        goto end;
      
      if (opt_type == BGP_OPEN_OPT_CAP)
        {
          unsigned long capd_start = stream_get_getp (s);
          unsigned long capd_end = capd_start + opt_length;
          
          assert (capd_end <= end);
          
	  while (stream_get_getp (s) < capd_end)
	    {
	      struct capability_header hdr;
	      
	      if (stream_get_getp (s) + 2 > capd_end)
                goto end;
              
              hdr.code = stream_getc (s);
              hdr.length = stream_getc (s);
              
	      if ((stream_get_getp(s) +  hdr.length) > capd_end)
		goto end;

	      if (hdr.code == CAPABILITY_CODE_AS4)
	        {
	          if (BGP_DEBUG (as4, AS4))
	            zlog_info ("[AS4] found AS4 capability, about to parse");
	          as4 = bgp_capability_as4 (peer, &hdr);
	          
	          goto end;
                }
              stream_forward_getp (s, hdr.length);
	    }
	}
    }

end:
  stream_set_getp (s, orig_getp);
  return as4;
}
Exemple #7
0
/**
 * Parse given capability.
 * XXX: This is reading into a stream, but not using stream API
 *
 * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
 *                           capabilities were encountered.
 */
static int
bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
		      u_char **error)
{
  int ret;
  struct stream *s = BGP_INPUT (peer);
  size_t end = stream_get_getp (s) + length;
  
  assert (STREAM_READABLE (s) >= length);
  
  while (stream_get_getp (s) < end)
    {
      size_t start;
      u_char *sp = stream_pnt (s);
      struct capability_header caphdr;
      
      /* We need at least capability code and capability length. */
      if (stream_get_getp(s) + 2 > end)
	{
	  zlog_info ("%s Capability length error (< header)", peer->host);
	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
	  return -1;
	}
      
      caphdr.code = stream_getc (s);
      caphdr.length = stream_getc (s);
      start = stream_get_getp (s);
      
      /* Capability length check sanity check. */
      if (start + caphdr.length > end)
	{
	  zlog_info ("%s Capability length error (< length)", peer->host);
	  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
	  return -1;
	}
      
      if (BGP_DEBUG (normal, NORMAL))
	zlog_debug ("%s OPEN has %s capability (%u), length %u",
		   peer->host,
		   LOOKUP (capcode_str, caphdr.code),
		   caphdr.code, caphdr.length);
      
      /* Length sanity check, type-specific, for known capabilities */
      switch (caphdr.code)
        {
          case CAPABILITY_CODE_MP:
          case CAPABILITY_CODE_REFRESH:
          case CAPABILITY_CODE_REFRESH_OLD:
          case CAPABILITY_CODE_ORF:
          case CAPABILITY_CODE_ORF_OLD:
          case CAPABILITY_CODE_RESTART:
          case CAPABILITY_CODE_AS4:
          case CAPABILITY_CODE_DYNAMIC:
              /* Check length. */
              if (caphdr.length < cap_minsizes[caphdr.code])
                {
                  zlog_info ("%s %s Capability length error: got %u,"
                             " expected at least %u",
                             peer->host, 
                             LOOKUP (capcode_str, caphdr.code),
                             caphdr.length, 
			     (unsigned) cap_minsizes[caphdr.code]);
                  bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
                  return -1;
                }
          /* we deliberately ignore unknown codes, see below */
          default:
            break;
        }
      
      switch (caphdr.code)
        {
          case CAPABILITY_CODE_MP:
            {
	      *mp_capability = 1;

              /* Ignore capability when override-capability is set. */
              if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
                {
                  /* Set negotiated value. */
                  ret = bgp_capability_mp (peer, &caphdr);

                  /* Unsupported Capability. */
                  if (ret < 0)
                    {
                      /* Store return data. */
                      memcpy (*error, sp, caphdr.length + 2);
                      *error += caphdr.length + 2;
                    }
                }
            }
            break;
          case CAPABILITY_CODE_REFRESH:
          case CAPABILITY_CODE_REFRESH_OLD:
            {
              /* BGP refresh capability */
              if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
                SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
              else
                SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
            }
            break;
          case CAPABILITY_CODE_ORF:
          case CAPABILITY_CODE_ORF_OLD:
            if (bgp_capability_orf (peer, &caphdr))
              return -1;
            break;
          case CAPABILITY_CODE_RESTART:
            if (bgp_capability_restart (peer, &caphdr))
              return -1;
            break;
          case CAPABILITY_CODE_DYNAMIC:
            SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
            break;
          case CAPABILITY_CODE_AS4:
              /* Already handled as a special-case parsing of the capabilities
               * at the beginning of OPEN processing. So we care not a jot
               * for the value really, only error case.
               */
              if (!bgp_capability_as4 (peer, &caphdr))
                return -1;
              break;            
          default:
            if (caphdr.code > 128)
              {
                /* We don't send Notification for unknown vendor specific
                   capabilities.  It seems reasonable for now...  */
                zlog_warn ("%s Vendor specific capability %d",
                           peer->host, caphdr.code);
              }
            else
              {
                zlog_warn ("%s unrecognized capability code: %d - ignored",
                           peer->host, caphdr.code);
                memcpy (*error, sp, caphdr.length + 2);
                *error += caphdr.length + 2;
              }
          }
      if (stream_get_getp(s) != (start + caphdr.length))
        {
          if (stream_get_getp(s) > (start + caphdr.length))
            zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
                       peer->host, LOOKUP (capcode_str, caphdr.code),
                       caphdr.length);
          stream_set_getp (s, start + caphdr.length);
        }
    }
  return 0;
}