/* * -------------------------------------------------------------------------- * This function activates the switch by initializing it with all the runtime * state. First it queries all of the MAC addresses set as custom switch policy * to allow sends from, and adds tme to the property list. Then it queries the * NIC list and verifies it can support all of the NICs currently connected to * the switch, and adds the NICs to the NIC list. * -------------------------------------------------------------------------- */ static NDIS_STATUS OvsActivateSwitch(POVS_SWITCH_CONTEXT switchContext) { NDIS_STATUS status; ASSERT(!switchContext->isActivated); OVS_LOG_TRACE("Enter: activate switch %p, dpNo: %ld", switchContext, switchContext->dpNo); status = OvsAddConfiguredSwitchPorts(switchContext); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_WARN("Failed to add configured switch ports"); goto cleanup; } status = OvsInitConfiguredSwitchNics(switchContext); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_WARN("Failed to add configured vports"); OvsClearAllSwitchVports(switchContext); goto cleanup; } switchContext->isActivated = TRUE; OvsPostEvent(OVS_DEFAULT_PORT_NO, OVS_DEFAULT_EVENT_STATUS); cleanup: OVS_LOG_TRACE("Exit: activate switch:%p, isActivated: %s, status = %lx", switchContext, (switchContext->isActivated ? "TRUE" : "FALSE"), status); return status; }
/* * --------------------------------------------------------------------------- * Validate the netlink attribute against the policy * --------------------------------------------------------------------------- */ BOOLEAN NlAttrValidate(const PNL_ATTR nla, const PNL_POLICY policy) { UINT32 minLen; UINT32 maxLen; UINT32 len; BOOLEAN ret = FALSE; if ((policy->type == NL_A_NO_ATTR) || (policy->type == NL_A_VAR_LEN) || (policy->type == NL_A_NESTED)) { /* Do not validate anything for attributes of type var length */ ret = TRUE; goto done; } /* Figure out min and max length. */ minLen = policy->minLen; if (!minLen) { minLen = NlAttrMinLen(policy->type); } maxLen = policy->maxLen; if (!maxLen) { maxLen = NlAttrMaxLen(policy->type); } /* Verify length. */ len = NlAttrGetSize(nla); if (len < minLen || len > maxLen) { OVS_LOG_WARN("Attribute: %p, len: %d, not in valid range, " "min: %d, max: %d", nla, len, minLen, maxLen); goto done; } /* Strings must be null terminated and must not have embedded nulls. */ if (policy->type == NL_A_STRING) { if (((PCHAR) nla)[nla->nlaLen - 1]) { OVS_LOG_WARN("Attributes %p lacks null at the end", nla); goto done; } if (memchr(nla + 1, '\0', len - 1) != NULL) { OVS_LOG_WARN("Attributes %p has bad length", nla); goto done; } } ret = TRUE; done: return ret; }
/* *---------------------------------------------------------------------------- * Parses the netlink message at a given offset (attrOffset) * as a series of attributes. A pointer to the attribute with type * 'type' is stored in attrs at index 'type'. policy is used to define the * attribute type validation parameters. * 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN + OVS_HEADER * * Returns BOOLEAN to indicate success/failure. *---------------------------------------------------------------------------- */ BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 totalAttrLen, const NL_POLICY policy[], PNL_ATTR attrs[], UINT32 n_attrs) { PNL_ATTR nla; UINT32 left; UINT32 iter; BOOLEAN ret = FALSE; RtlZeroMemory(attrs, n_attrs * sizeof *attrs); /* There is nothing to parse */ if (!(NlMsgAttrsLen(nlMsg))) { ret = TRUE; goto done; } if ((NlMsgSize(nlMsg) < attrOffset)) { OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d", nlMsg, attrOffset); goto done; } NL_ATTR_FOR_EACH (nla, left, NlMsgAt(nlMsg, attrOffset), totalAttrLen) { UINT16 type = NlAttrType(nla); if (type < n_attrs && policy[type].type != NL_A_NO_ATTR) { /* Typecasting to keep the compiler happy */ const PNL_POLICY e = (const PNL_POLICY)(&policy[type]); if (!NlAttrValidate(nla, e)) { goto done; } if (attrs[type]) { OVS_LOG_WARN("Duplicate attribute in nlMsg: %p, " "type: %u", nlMsg, type); } attrs[type] = nla; } }
/* * -------------------------------------------------------------------------- * Implements filter driver's FilterRestart function. * -------------------------------------------------------------------------- */ _Use_decl_annotations_ NDIS_STATUS OvsExtRestart(NDIS_HANDLE filterModuleContext, PNDIS_FILTER_RESTART_PARAMETERS filterRestartParameters) { POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext; NDIS_STATUS status = NDIS_STATUS_SUCCESS; BOOLEAN switchActive; UNREFERENCED_PARAMETER(filterRestartParameters); OVS_LOG_TRACE("Enter: filterModuleContext %p", filterModuleContext); /* Activate the switch if this is the first restart. */ if (!switchContext->isActivated && !switchContext->isActivateFailed) { status = OvsQuerySwitchActivationComplete(switchContext, &switchActive); if (status != NDIS_STATUS_SUCCESS) { switchContext->isActivateFailed = TRUE; status = NDIS_STATUS_RESOURCES; goto cleanup; } if (switchActive) { status = OvsActivateSwitch(switchContext); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_WARN("Failed to activate switch, dpNo:%d", switchContext->dpNo); status = NDIS_STATUS_RESOURCES; goto cleanup; } } } ASSERT(switchContext->dataFlowState == OvsSwitchPaused); switchContext->dataFlowState = OvsSwitchRunning; cleanup: OVS_LOG_TRACE("Exit: Restart switch:%p, dpNo: %d, status: %#x", switchContext, switchContext->dpNo, status); return status; }
/* * --------------------------------------------------------------------------- * Default maximum payload size for each type of attribute. * --------------------------------------------------------------------------- */ UINT32 NlAttrMaxLen(NL_ATTR_TYPE type) { switch (type) { case NL_A_NO_ATTR: return SIZE_MAX; case NL_A_UNSPEC: return SIZE_MAX; case NL_A_U8: return 1; case NL_A_U16: return 2; case NL_A_U32: return 4; case NL_A_U64: return 8; case NL_A_STRING: return MAXUINT16; case NL_A_FLAG: return SIZE_MAX; case NL_A_NESTED: return SIZE_MAX; case N_NL_ATTR_TYPES: default: OVS_LOG_WARN("Unsupprted attribute type: %d", type); ASSERT(0); } /* To keep compiler happy */ return 0; }
/* *---------------------------------------------------------------------------- * Traverses all attributes in received buffer in order to insure all are valid *---------------------------------------------------------------------------- */ BOOLEAN NlValidateAllAttrs(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 totalAttrLen, const NL_POLICY policy[], const UINT32 numPolicy) { PNL_ATTR nla; INT left; BOOLEAN ret = TRUE; if ((NlMsgSize(nlMsg) < attrOffset)) { OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d", nlMsg, attrOffset); ret = FALSE; goto done; } NL_ATTR_FOR_EACH_UNSAFE(nla, left, NlMsgAt(nlMsg, attrOffset), totalAttrLen) { if (!NlAttrIsValid(nla, left)) { ret = FALSE; goto done; } UINT16 type = NlAttrType(nla); if (type < numPolicy && policy[type].type != NL_A_NO_ATTR) { /* Typecasting to keep the compiler happy */ const PNL_POLICY e = (const PNL_POLICY)(&policy[type]); if (!NlAttrValidate(nla, e)) { ret = FALSE; goto done; } } } done: return ret; }