示例#1
0
 int parseMAC(char *str, uint64_t *mac)
 {
   u_char macbytes[6];
   if(hexToBinary((u_char *)str, macbytes, 6) != 6) return NO;
   // cast to 64-bit integer by simply copying in the bytes.
   // It doesn't matter whether the architecture is big endian
   // or little endian, we are just using this as a convenient
   // comparison symbol.
   memcpy(mac, macbytes, 6);
   return YES;
 }
示例#2
0
main(int argc, char *argv[]) {
	
	FILE *file = fopen(argv[1], "r");
	char *address = argv[2];
	char hexArray[100] = "";
	char binaryArray[400] = "";
	getHexArray(file, hexArray);
	hexToBinary(hexArray, binaryArray);
	binaryToLC3(binaryArray, address);
	
}
  void readIPv6Addresses(HSP *sp)
  {
    FILE *procFile = fopen("/proc/net/if_inet6", "r");
    if(procFile) {
      char line[MAX_PROC_LINE_CHARS];
      int lineNo = 0;
      while(fgets(line, MAX_PROC_LINE_CHARS, procFile)) {
	// expect lines of the form "<address> <netlink_no> <prefix_len(HEX)> <scope(HEX)> <flags(HEX)> <deviceName>
	// (with a header line on the first row)
	char devName[MAX_PROC_LINE_CHARS];
	u_char addr[MAX_PROC_LINE_CHARS];
	u_int devNo, maskBits, scope, flags;
	++lineNo;
	if(sscanf(line, "%s %x %x %x %x %s",
		  addr,
		  &devNo,
		  &maskBits,
		  &scope,
		  &flags,
		  devName) == 6) {
	  if(debug) {
	    myLog(LOG_INFO, "adaptor %s has v6 address %s with scope 0x%x",
		  devName,
		  addr,
		  scope);
	  }
	  SFLAdaptor *adaptor = adaptorListGet(sp->adaptorList, trimWhitespace(devName));
	  if(adaptor && adaptor->userData) {
	    HSPAdaptorNIO *niostate = (HSPAdaptorNIO *)adaptor->userData;
	    SFLAddress v6addr;
	    v6addr.type = SFLADDRESSTYPE_IP_V6;
	    if(hexToBinary(addr, v6addr.address.ip_v6.addr, 16) == 16) {
	      // we interpret the scope from the address now
	      // scope = remap_proc_net_if_inet6_scope(scope);
	      EnumIPSelectionPriority ipPriority = agentAddressPriority(sp,
									&v6addr,
									niostate->vlan,
									niostate->loopback);
	      if(ipPriority > niostate->ipPriority) {
		// write this in as the preferred sflow-agent-address for this adaptor
		niostate->ipAddr = v6addr;
		niostate->ipPriority = ipPriority;
	      }
	    }
	  }
	}
      }
      fclose(procFile);
    }
  }
  static int containerLinkCB(void *magic, char *line) {
    HSPVMState *vm = (HSPVMState *)magic;
    if(debug) myLog(LOG_INFO, "containerLinkCB: line=<%s>", line);
    char deviceName[HSF_DOCKER_MAX_LINELEN];
    char macStr[HSF_DOCKER_MAX_LINELEN];
    uint32_t ifIndex;
    if(sscanf(line, "VNIC: %u %s %s", &ifIndex, deviceName, macStr) == 3) {
      u_char mac[6];
      if(hexToBinary((u_char *)macStr, mac, 6) == 6) {
	SFLAdaptor *adaptor = adaptorListGet(vm->interfaces, deviceName);
	if(adaptor == NULL) {
	  adaptor = adaptorListAdd(vm->interfaces, deviceName, mac, sizeof(HSPAdaptorNIO));
	}
	// set ifIndex
	adaptor->ifIndex = ifIndex;
	// clear the mark so we don't free it below
	adaptor->marked = NO;
      }
    }
    return YES;
  }
示例#5
0
  static SFLAdaptorList *xenstat_adaptors(HSP *sp, uint32_t dom_id, SFLAdaptorList *myAdaptors)
  {
    for(uint32_t i = 0; i < sp->adaptorList->num_adaptors; i++) {
      SFLAdaptor *adaptor = sp->adaptorList->adaptors[i];
      uint32_t vif_domid;
      uint32_t vif_netid;
      int isVirtual = (sscanf(adaptor->deviceName, "vif%"SCNu32".%"SCNu32, &vif_domid, &vif_netid) == 2);
      if((isVirtual && dom_id == vif_domid) ||
	 (!isVirtual && dom_id == 0)) {
	// include this one (if we have room)
	if(myAdaptors->num_adaptors < HSP_MAX_VIFS) {
	  myAdaptors->adaptors[myAdaptors->num_adaptors++] = adaptor;
	  if(isVirtual) {
	    // for virtual interfaces we need to query for the MAC address
	    char macQuery[256];
	    snprintf(macQuery, sizeof(macQuery), "/local/domain/%u/device/vif/%u/mac", vif_domid, vif_netid);
	    char *macStr = xs_read(sp->xs_handle, XBT_NULL, macQuery, NULL);
	    if(macStr == NULL) {
	      myLog(LOG_ERR, "mac address query failed : %s : %s", macQuery, strerror(errno));
	    }
	    else{
	      // got it - but make sure there is a place to write it
	      if(adaptor->num_macs > 0) {
		// OK, just overwrite the 'dummy' one that was there
		if(hexToBinary((u_char *)macStr, adaptor->macs[0].mac, 6) != 6) {
		  myLog(LOG_ERR, "mac address format error in xenstore query <%s> : %s", macQuery, macStr);
		}
	      }
	      free(macStr);
	    }
	  }
	}
      }
    }
    return myAdaptors;
  }
示例#6
0
/**
 * Updates the switch port list with the information in pSwitchConfig
 * obtained from the filter.
 */
void updateSwitchPorts(HSP *sp, PAllSwitchesConfig config)
{
	if (config->revision <= sp->portInfoRevision) {
		return;
	}
	if (sp->vAdaptorList == NULL) {
		sp->vAdaptorList = adaptorListNew();
	} else {
		adaptorListMarkAll(sp->vAdaptorList);
	}
	PSwitchConfig switchConfig;
	for (uint32_t switchNum = 0; switchNum < config->numSwitches; switchNum++) {
		if (switchNum == 0) {
			switchConfig = GET_FIRST_SWITCH_CONFIG(config);
		} else {
			switchConfig = GET_NEXT_SWITCH_CONFIG(switchConfig);
		}
		wchar_t *switchName = ndiswcsdup(&switchConfig->switchName);
		uint64_t switchId = switchConfig->switchID;
		for (uint32_t portNum = 0; portNum < switchConfig->numPorts; portNum++) {
			PPortEntry portEntry = GET_PORT_ENTRY_AT(switchConfig, portNum);
			uint32_t portId = portEntry->portID;
			wchar_t *portName = ndiswcsdup(&portEntry->portName);
			char portGuid[FORMATTED_GUID_LEN+1];
			guidToString(portName, (UCHAR *)portGuid, FORMATTED_GUID_LEN);
			SFLAdaptor *switchPort = adaptorListGet(sp->vAdaptorList, portGuid);
			if (switchPort == NULL) {
				//new port so add to the vadaptor list
				//convert GUID to uuid format to look up ifIndex/dsIndex
				char uuid[16];
				hexToBinary((UCHAR *)portGuid, (UCHAR *)uuid, 33);
				uint32_t ifIndex = assign_dsIndex(&sp->portStore, uuid, &sp->maxIfIndex, &sp->portStoreInvalid);
				switchPort = addVAdaptor(sp->vAdaptorList, portGuid, ifIndex);
				HVSVPortInfo *portInfo = (HVSVPortInfo *)switchPort->userData;
				portInfo->filterEnabled = TRUE;
				portInfo->portId = portId;
				portInfo->revision = portEntry->revision;
				switchPort->marked = FALSE;
				updatePortSwitchName(switchPort, switchName);
				portInfo->switchId = switchConfig->switchID;
				myLog(LOG_INFO, "updateSwitchPorts: Added new portId=%u ifIndex=%u deviceName=%s switchId=%llu switchName=%S",
					portInfo->portId, switchPort->ifIndex, switchPort->deviceName, portInfo->switchId, portInfo->switchName);
				addPoller(sp, switchPort);
			} else {
				//we already know about this port, so make sure we have a poller
				//and the current info
				SFLDataSource_instance dsi;
				SFL_DS_SET(dsi, 0, switchPort->ifIndex, 0);
				SFLPoller *poller = sfl_agent_getPoller(sp->sFlow->agent, &dsi);
				if (poller == NULL) {
					poller = addPoller(sp, switchPort);
				}
				HVSVPortInfo *portInfo = (HVSVPortInfo *)switchPort->userData;
				if (portEntry->revision > portInfo->revision) {
					updatePortSwitchName(switchPort, switchName);
					portInfo->revision = portEntry->revision;
					if (poller != NULL) {
						sfl_poller_resetCountersSeqNo(poller);
					}
					myLog(LOG_INFO, "updateSwitchPorts: revision changed: portId=%u ifIndex=%u deviceName=%s switchId=%llu switchName=%S", 
						  portInfo->portId, switchPort->ifIndex, switchPort->deviceName, portInfo->switchId, portInfo->switchName);
				}
				portInfo->filterEnabled = TRUE;
				switchPort->marked = FALSE;
			}
			my_free(portName);
		}
		my_free(switchName);
	}
	//now sweep
	//remove the pollers for non-sampling ports
	for (uint32_t i = 0; i < sp->vAdaptorList->num_adaptors; i++) {
		SFLAdaptor *vAdaptor = sp->vAdaptorList->adaptors[i];
		if (vAdaptor->marked) {
			HVSVPortInfo *portInfo = (HVSVPortInfo *)vAdaptor->userData;
			if (portInfo->filterEnabled) {
				//filter (ie sampling) has been disabled in the switch with this port
				((HVSVPortInfo *)vAdaptor->userData)->portId = 0;
				removePoller(sp, vAdaptor);
				portInfo->filterEnabled = FALSE;
				//Clear the mark so this port will not be deleted, the VM and adaptor may still exist.
				//If the adaptor does not exist, it will be removed when we next refresh the VMs.
				vAdaptor->marked = FALSE;
			} else {
				//this was a port added for a vm on a switch with the filter disabled, so
				//just clear the mark so that it will not be deleted.
				vAdaptor->marked = FALSE;
			}	
		}
	}
	//Now remove the marked adaptors and their port info from the list
	adaptorListFreeMarked(sp->vAdaptorList, freePortInfo);
	//TODO ageout the persistent ifIndex->GUID mapping and remove from vAdaptor list.
	sp->portInfoRevision = config->revision;
	readWMISwitchPorts(sp); //update the ifSpeed, MAC, VM name
	sp->refreshVms = TRUE;
}
示例#7
0
// parses the PTTKT sentence into the BD_partialPTTKT structure which is
// copied over to the externally visible PTTKT structure if any non null
// fields are decoded.
BOOL8 navcoreBDParse ::processPTTKT(const char *sentence)
{
  char  work[FIELD_BUFFER_LENGTH];
  UINT8 index;
  const char *field, *wrk;

  lastBDType = NMEA_MESSAGE_TYPE_TRAFFIC;

  field = sentence;

  // MESSAGE SUBTYPE
  if ( (field = findNextField(field)) != NULL ) {
    readField(work,field);
    if (strncmp (work,"DATA",4)==0)
    {
      // contains one field, which is 16 hex characters
      if ((field = findNextField(field)) != NULL)
      {
        if (readField(work,field) == 16)
        {
          // convert 16 hex characters  into UINT8 buffer
          wrk = work;
          for (index = 0; index < 8; index++) {
           BD_partialPTTKT.tmcData[index] = hexToBinary (wrk);
            wrk += 2;
          }

          BD_partialPTTKT.lastMessage = TMC_MSG_TYPE_DATA;
          memcpy (&BD__PTTKT,&BD_partialPTTKT,sizeof(BD__PTTKT));
          return TRUE;
        }
      }
      return FALSE;
    }
    else if (strncmp (work,"STAT",4)==0)
    {
      // contains 5 fields
      for (index = 0; index < 5; index++) {
        if ((field = findNextField(field)) != NULL) {
          readField(work,field);
          switch (index) {
            case 0:
              BD_partialPTTKT.hardwarePresent = (UINT8)atoi(work);
              break;
            case 1: // tuned frequency (decimal number)
              BD_partialPTTKT.frequency = (UINT16)atoi(work);
              break;
            case 2: // Block Count (decimal number)
              BD_partialPTTKT.blockCount = (UINT8)atoi(work);
              break;
            case 3: // Traffic Message Count
              BD_partialPTTKT.tmcCount = (UINT8)atoi(work);
              break;
            case 4: // error rate (decimal number)
              BD_partialPTTKT.errorRate = (UINT8)atoi(work);
              break;
          }
        } else {
          return FALSE;
        }
      }
      BD_partialPTTKT.lastMessage = TMC_MSG_TYPE_STATUS;
      memcpy (&BD__PTTKT,&BD_partialPTTKT,sizeof(BD__PTTKT));
      return TRUE;
    }
    else if (strncmp (work,"TUNE",4)==0)
    {
      // returns the TUNE command sent to the hardware
      // need to get the tune status from this

      // contains 2 fields (only the last is of interest)
      for (index = 0; index < 2; index++) {
        if ((field = findNextField(field)) != NULL) {
          readField(work,field);
          switch (index) {
            case 0: // frequency
              break;
            case 1: // status (0 or 1)
              BD_partialPTTKT.tuneStatus = (UINT8)atoi(work);
              break;
          }
        } else {
          return FALSE;
        }
      }

      BD_partialPTTKT.lastMessage = TMC_MSG_TYPE_TUNE;
      memcpy (&BD__PTTKT,&BD_partialPTTKT,sizeof(BD__PTTKT));
      return TRUE;
    }
    else if (strncmp (work,"WAKE",4)==0)
    {
      // The WAKE command is generated when
      // the (Wince) target comes out of sleep mode
      BD_partialPTTKT.lastMessage = TMC_MSG_TYPE_WAKEUP;
      BD__PTTKT.lastMessage = TMC_MSG_TYPE_WAKEUP;
      return TRUE;
    }
    else if (strncmp (work,"LIST",4)==0)
    {
      // contains 8 fields
      for (index = 0; index < 8; index++)
      {
        if ((field = findNextField(field)) != NULL)
        {
          readField(work,field);
          switch (index)
          {
            case 0: // Flag to indicate tuned freq
              BD_partialPTTKT.stnCurrent = (BOOL8)atoi(work);
              break;
            case 1: // Station Count (decimal number)
              BD_partialPTTKT.stnCount = (UINT8)atoi(work);
              break;
            case 2: // station Index (decimal number)
              BD_partialPTTKT.stnIndex = (UINT8)atoi(work);
              break;
            case 3: // station Frequency (decimal number)
              BD_partialPTTKT.stnFrequency = (UINT16)atoi(work);
              break;
            case 4: // station PI code (hex)
              wrk = work;
              BD_partialPTTKT.stnPI = (hexToBinary (wrk) << 8);
              wrk+=2;
              BD_partialPTTKT.stnPI += (hexToBinary (wrk));
              break;
            case 5: // station signal strength
              BD_partialPTTKT.stnSignal = (UINT8)atoi(work);
              break;
            case 6: // station flag
              BD_partialPTTKT.stnFlag = (UINT8)atoi(work);
              break;
            case 7: // station name
              strcpy (BD_partialPTTKT.stnName, work);
              break;
          }
        } else
        {
          return FALSE;
        }
      }
      BD_partialPTTKT.lastMessage = TMC_MSG_TYPE_LIST;
      memcpy (&BD__PTTKT,&BD_partialPTTKT,sizeof(BD__PTTKT));
      return TRUE;
    }
    else if (strncmp (work,"SGNL",4)==0)
    {
      // contains 3 fields freq, PI, signal
      // station list entries used for storage
      for (index = 0; index < 3; index++)
      {
        if ((field = findNextField(field)) != NULL)
        {
          readField(work,field);
          switch (index)
          {
            case 0: // station Frequency (decimal number)
              BD_partialPTTKT.stnFrequency = (UINT16)atoi(work);
              break;
            case 1: // station PI code (hex)
              wrk = work;
              BD_partialPTTKT.stnPI = (hexToBinary (wrk) << 8);
              wrk+=2;
              BD_partialPTTKT.stnPI += (hexToBinary (wrk));
              break;
            case 2: // station signal strength
              BD_partialPTTKT.stnSignal = (UINT8)atoi(work);
              break;
          }
        } else
        {
          return FALSE;
        }
      }
      BD_partialPTTKT.lastMessage = TMC_MSG_TYPE_SIGSTRENGTH;
      memcpy (&BD__PTTKT,&BD_partialPTTKT,sizeof(BD__PTTKT));
      return TRUE;
    }
    else if (strncmp (work,"RESET",5)==0)
    {
      // return the RESET command sent to the hardware
     BD_partialPTTKT.lastMessage = TMC_MSG_TYPE_RESET;
      BD__PTTKT.lastMessage = TMC_MSG_TYPE_RESET;
      return TRUE;
    }
  }
  return FALSE;
}
示例#8
0
/*
 *	Public API to return an ASN.1 encoded key stream from a PEM private
 *	key file
 *
 *	If password is provided, we only deal with 3des cbc encryption
 *	Function allocates key on success.  User must free.
 */
int32 matrixRsaReadPrivKey(psPool_t *pool, const char *fileName,
				const char *password, unsigned char **keyMem, int32 *keyMemLen)
{
	unsigned char	*keyBuf, *DERout, *start, *end;
	int32			keyBufLen, rc, DERlen, PEMlen = 0;
#ifdef USE_3DES
	sslCipherContext_t	ctx;
	unsigned char	passKey[SSL_DES3_KEY_LEN];
	unsigned char	cipherIV[SSL_DES3_IV_LEN];
	int32			tmp, encrypted = 0;
#endif /* USE_3DES */

	if (fileName == NULL) {
		return 0;
	}
	*keyMem = NULL;
	if ((rc = psGetFileBin(pool, fileName, &keyBuf, &keyBufLen)) < 0) {
		return rc;
	}
	start = end = NULL;

/*
 *	Check header and encryption parameters.
 */
	if ((start = strstr(keyBuf, "-----BEGIN RSA PRIVATE KEY-----")) == NULL) {
		matrixStrDebugMsg("Error parsing private key buffer\n", NULL);
		psFree(keyBuf);
		return -1;
	}
	start += strlen("-----BEGIN RSA PRIVATE KEY-----");
	while (*start == '\r' || *start == '\n') {
		start++;
	}

	if (strstr(keyBuf, "Proc-Type:") && strstr(keyBuf, "4,ENCRYPTED")) {
#ifdef USE_3DES
		encrypted++;
		if (password == NULL) {
			matrixStrDebugMsg("No password given for encrypted private key\n",
				NULL);
			psFree(keyBuf);
			return -1;
		}
		if ((start = strstr(keyBuf, encryptHeader)) == NULL) {
			matrixStrDebugMsg("Unrecognized private key file encoding\n",
				NULL);
			psFree(keyBuf);
			return -1;
		}
		start += strlen(encryptHeader);
		/* SECURITY - we assume here that header points to at least 16 bytes of data */
		tmp = hexToBinary((unsigned char*)start, cipherIV, SSL_DES3_IV_LEN);
		if (tmp < 0) {
			matrixStrDebugMsg("Invalid private key file salt\n", NULL);
			psFree(keyBuf);
			return -1;
		}
		start += tmp;
		generate3DESKey((unsigned char*)password, (int32)strlen(password),
			cipherIV, (unsigned char*)passKey);
#else  /* !USE_3DES */
/*
 *		The private key is encrypted, but 3DES support has been turned off
 */
		matrixStrDebugMsg("3DES has been disabled for private key decrypt\n", NULL);
		psFree(keyBuf);
		return -1;  
#endif /* USE_3DES */
	}

	if ((end = strstr(keyBuf, "-----END RSA PRIVATE KEY-----")) == NULL) {
		matrixStrDebugMsg("Error parsing private key buffer\n", NULL);
		psFree(keyBuf);
		return -1;
	}
	PEMlen = (int32)(end - start);

/*
	Take the raw input and do a base64 decode
 */
	DERout = psMalloc(pool, PEMlen);
	if (DERout == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	DERlen = PEMlen;
	if (ps_base64_decode(start, PEMlen, DERout, (uint32*)&DERlen) != 0) {
		psFree(DERout);
		psFree(keyBuf);
		matrixStrDebugMsg("Unable to base64 decode private key\n", NULL);
		return -1;
	}
	psFree(keyBuf);
#ifdef USE_3DES
/*
 *	Decode
 */
	if (encrypted == 1 && password) {
		matrix3desInit(&ctx, cipherIV, passKey, SSL_DES3_KEY_LEN);
		matrix3desDecrypt(&ctx, DERout, DERout, DERlen);
	}
#endif /* USE_3DES */
/*
	Don't parse this here.  Return the ASN.1 encoded buf to be
	consistent with the other mem APIs.  Use the ParsePrivKey 
	function if you want the structure format
*/
	*keyMem = DERout;
	*keyMemLen = DERlen;
	return rc;
}
示例#9
0
int parseUUID(char *str, char *uuid)
{
    if(hexToBinary((u_char *)str, (u_char *)uuid, 16) != 16) return NO;
    return YES;
}
  void updateBondCounters(HSP *sp, SFLAdaptor *bond) {
    char procFileName[256];
    snprintf(procFileName, 256, "/proc/net/bonding/%s", bond->deviceName);
    FILE *procFile = fopen(procFileName, "r");
    if(procFile) {
      // limit the number of chars we will read from each line
      // (there can be more than this - fgets will chop for us)
#define MAX_PROC_LINE_CHARS 240
      char line[MAX_PROC_LINE_CHARS];
      SFLAdaptor *currentSlave = NULL;
      HSPAdaptorNIO *slave_nio = NULL;
      HSPAdaptorNIO *bond_nio = (HSPAdaptorNIO *)bond->userData;
      HSPAdaptorNIO *aggregator_slave_nio = NULL;
      bond_nio->lacp.attachedAggID = bond->ifIndex;
      uint32_t aggID = 0;
      // make sure we don't hold on to stale data - may need
      // to pick up actorSystemID from a slave port.
      memset(bond_nio->lacp.actorSystemID, 0, 6);
      memset(bond_nio->lacp.partnerSystemID, 0, 6);
      int readingMaster = YES; // bond master data comes first
      int gotActorID = NO;
      while(fgets(line, MAX_PROC_LINE_CHARS, procFile)) {
	char buf_var[MAX_PROC_LINE_CHARS];
	char buf_val[MAX_PROC_LINE_CHARS];
	// buf_var is up to first ':', buf_val is the rest
	if(sscanf(line, "%[^:]:%[^\n]", buf_var, buf_val) == 2) {
	  char *tok_var = trimWhitespace(buf_var);
	  char *tok_val = trimWhitespace(buf_val);
	  
	  if(readingMaster) {
	    if(my_strequal(tok_var, "MII Status")) {
	      if(my_strequal(tok_val, "up")) {
		bond_nio->lacp.portState.v.actorAdmin = 2; // dot3adAggPortActorAdminState
		bond_nio->lacp.portState.v.actorOper = 2;
		bond_nio->lacp.portState.v.partnerAdmin = 2;
		bond_nio->lacp.portState.v.partnerOper = 2;
	      }
	      else {
		bond_nio->lacp.portState.all = 0;
	      }
	    }
	    
	    if(my_strequal(tok_var, "System Identification")) {
	      if(debug) {
		myLog(LOG_INFO, "updateBondCounters: %s system identification %s",
		      bond->deviceName,
		      tok_val);
	      }
	      char sys_mac[MAX_PROC_LINE_CHARS];
	      uint64_t code;
	      if(sscanf(tok_val, "%"SCNu64"  %s", &code, sys_mac) == 2) {
		if(hexToBinary((u_char *)sys_mac,bond_nio->lacp.actorSystemID, 6) != 6) {
		  myLog(LOG_ERR, "updateBondCounters: system mac read error: %s", sys_mac);
		}
		else if(!isAllZero(bond_nio->lacp.actorSystemID, 6)) {
		  gotActorID = YES;
		}
	      }
	    }
	    
	    if(my_strequal(tok_var, "Partner Mac Address")) {
	      if(debug) {
		myLog(LOG_INFO, "updateBondCounters: %s partner mac is %s",
		      bond->deviceName,
		      tok_val);
	      }
	      if(hexToBinary((u_char *)tok_val,bond_nio->lacp.partnerSystemID, 6) != 6) {
		myLog(LOG_ERR, "updateBondCounters: partner mac read error: %s", tok_val);
	      }
	    }
	    
	    if(my_strequal(tok_var, "Aggregator ID")) {
	      aggID = strtol(tok_val, NULL, 0);
	      if(debug) {
		myLog(LOG_INFO, "updateBondCounters: %s aggID %u", bond->deviceName, aggID);
	      }
	    }
	  }
	  
	  // initially the data is for the bond, but subsequently
	  // we get info about each slave. So we started with
	  // (readingMaster=YES,currentSlave=NULL), and now we
	  // detect transitions to slave data:
	  if(my_strequal(tok_var, "Slave Interface")) {
	    readingMaster = NO;
	    currentSlave = adaptorListGet(sp->adaptorList, trimWhitespace(tok_val));
	    slave_nio = currentSlave ? (HSPAdaptorNIO *)currentSlave->userData : NULL;
	    if(debug) {
	      myLog(LOG_INFO, "updateBondCounters: bond %s slave %s %s",
		    bond->deviceName,
		    tok_val,
		    currentSlave ? "found" : "not found");
	    }
	    if(slave_nio) {
	      // initialize from bond
	      slave_nio->lacp.attachedAggID = bond->ifIndex;
	      memcpy(slave_nio->lacp.partnerSystemID, bond_nio->lacp.partnerSystemID, 6);
	      memcpy(slave_nio->lacp.actorSystemID, bond_nio->lacp.actorSystemID, 6);
	      
	      // make sure the parent is going to export separate
	      // counters if the slave is going to (because it was
	      // marked as a switchPort):
	      if(slave_nio->switchPort) {
		bond_nio->switchPort = YES;
	      }
	      // and vice-versa
	      if(bond_nio->switchPort) {
		slave_nio->switchPort = YES;
	      }
	    }
	  }
	  
	  if(readingMaster == NO && slave_nio) {
	    if(my_strequal(tok_var, "MII Status")) {
	      if(my_strequal(tok_val, "up")) {
		slave_nio->lacp.portState.v.actorAdmin = 2; // dot3adAggPortActorAdminState
		slave_nio->lacp.portState.v.actorOper = 2;
		slave_nio->lacp.portState.v.partnerAdmin = 2;
		slave_nio->lacp.portState.v.partnerOper = 2;
	      }
	      else {
		slave_nio->lacp.portState.all = 0;
	      }
	    }
	    
	    if(my_strequal(tok_var, "Permanent HW addr")) {
	      if(!gotActorID) {
		// Still looking for our actorSystemID, so capture this here in case we
		// decide below that it is the one we want.  Note that this mac may not be the
		// same as the mac associated with this port that we read back in readInterfaces.c.
		if(hexToBinary((u_char *)tok_val,slave_nio->lacp.actorSystemID, 6) != 6) {
		  myLog(LOG_ERR, "updateBondCounters: permanent HW addr read error: %s", tok_val);
		}
	      }
	    }
	    
	    if(my_strequal(tok_var, "Aggregator ID")) {
	      uint32_t slave_aggID = strtol(tok_val, NULL, 0);
	      if(slave_aggID == aggID) {
		// remember that is the slave port that has the same aggregator ID as the bond
		aggregator_slave_nio = slave_nio;
	      }
	    }
	  }
	}
      }
      
      if(aggregator_slave_nio && !gotActorID) {
	// go back and fill in the actorSystemID on all the slave ports
	shareActorIDFromSlave(sp, bond_nio, aggregator_slave_nio);
      }
      
      fclose(procFile);
    }
  }