Example #1
0
// Bytes returns the bytes
func (m *Message) Bytes() []byte {
	if m.FPort == 0 {
		m.FPort = 1
	}
	macPayload := &lorawan.MACPayload{}
	macPayload.FHDR = lorawan.FHDR{
		DevAddr: lorawan.DevAddr(m.devAddr),
		FCnt:    uint32(m.FCnt),
	}
	macPayload.FPort = pointer.Uint8(uint8(m.FPort))
	macPayload.FRMPayload = []lorawan.Payload{&lorawan.DataPayload{Bytes: m.Payload}}
	phyPayload := &lorawan.PHYPayload{}
	phyPayload.MHDR = lorawan.MHDR{
		MType: lorawan.UnconfirmedDataUp,
		Major: lorawan.LoRaWANR1,
	}
	if m.confirmed {
		phyPayload.MHDR.MType = lorawan.ConfirmedDataUp
	}
	phyPayload.MACPayload = macPayload
	phyPayload.EncryptFRMPayload(lorawan.AES128Key(m.appSKey))
	phyPayload.SetMIC(lorawan.AES128Key(m.nwkSKey))
	uplinkBytes, _ := phyPayload.MarshalBinary()
	return uplinkBytes
}
Example #2
0
// Unmarshal a byte slice into a Message
func (m *Message) Unmarshal(bytes []byte) error {
	payload := &lorawan.PHYPayload{}
	payload.UnmarshalBinary(bytes)
	if micOK, _ := payload.ValidateMIC(lorawan.AES128Key(m.nwkSKey)); !micOK {
		return errors.New("Invalid MIC")
	}
	macPayload, ok := payload.MACPayload.(*lorawan.MACPayload)
	if !ok {
		return errors.New("No MACPayload")
	}
	m.FCnt = int(macPayload.FHDR.FCnt)
	m.FPort = -1
	if macPayload.FPort != nil {
		m.FPort = int(*macPayload.FPort)
	}
	m.Payload = []byte{}
	if len(macPayload.FRMPayload) > 0 {
		payload.DecryptFRMPayload(lorawan.AES128Key(m.appSKey))
		m.Payload = macPayload.FRMPayload[0].(*lorawan.DataPayload).Bytes
	}
	return nil
}
Example #3
0
func (n *networkServer) HandleDownlink(message *pb_broker.DownlinkMessage) (*pb_broker.DownlinkMessage, error) {
	// Get Device
	dev, err := n.devices.Get(*message.AppEui, *message.DevEui)
	if err != nil {
		return nil, err
	}

	n.status.downlink.Mark(1)

	dev.StartUpdate()

	if dev.AppID != message.AppId || dev.DevID != message.DevId {
		return nil, errors.NewErrInvalidArgument("Downlink", "AppID and DevID do not match AppEUI and DevEUI")
	}

	// Unmarshal LoRaWAN Payload
	var phyPayload lorawan.PHYPayload
	err = phyPayload.UnmarshalBinary(message.Payload)
	if err != nil {
		return nil, err
	}
	macPayload, ok := phyPayload.MACPayload.(*lorawan.MACPayload)
	if !ok {
		return nil, errors.NewErrInvalidArgument("Downlink", "does not contain a MAC payload")
	}

	// Set DevAddr
	macPayload.FHDR.DevAddr = lorawan.DevAddr(dev.DevAddr)

	// FIRST set and THEN increment FCntDown
	// TODO: For confirmed downlink, FCntDown should be incremented AFTER ACK
	macPayload.FHDR.FCnt = dev.FCntDown
	dev.FCntDown++
	err = n.devices.Set(dev)
	if err != nil {
		return nil, err
	}

	// Sign MIC
	phyPayload.SetMIC(lorawan.AES128Key(dev.NwkSKey))

	// Update message
	bytes, err := phyPayload.MarshalBinary()
	if err != nil {
		return nil, err
	}
	message.Payload = bytes

	return message, nil
}
Example #4
0
func doTestHandleActivation(h *handler, appEUI types.AppEUI, devEUI types.DevEUI, devNonce [2]byte, appKey types.AppKey) (*pb.DeviceActivationResponse, error) {
	devAddr := types.DevAddr{1, 2, 3, 4}

	requestPHY := lorawan.PHYPayload{
		MHDR: lorawan.MHDR{
			MType: lorawan.JoinRequest,
			Major: lorawan.LoRaWANR1,
		},
		MACPayload: &lorawan.JoinRequestPayload{
			AppEUI:   lorawan.EUI64(appEUI),
			DevEUI:   lorawan.EUI64(devEUI),
			DevNonce: devNonce,
		},
	}
	requestPHY.SetMIC(lorawan.AES128Key(appKey))
	requestBytes, _ := requestPHY.MarshalBinary()

	responsePHY := lorawan.PHYPayload{
		MHDR: lorawan.MHDR{
			MType: lorawan.JoinAccept,
			Major: lorawan.LoRaWANR1,
		},
		MACPayload: &lorawan.JoinAcceptPayload{},
	}
	templateBytes, _ := responsePHY.MarshalBinary()
	return h.HandleActivation(&pb_broker.DeduplicatedDeviceActivationRequest{
		Payload: requestBytes,
		AppEui:  &appEUI,
		AppId:   appEUI.String(),
		DevEui:  &devEUI,
		DevId:   devEUI.String(),
		ActivationMetadata: &pb_protocol.ActivationMetadata{Protocol: &pb_protocol.ActivationMetadata_Lorawan{
			Lorawan: &pb_lorawan.ActivationMetadata{
				DevAddr: &devAddr,
			},
		}},
		ResponseTemplate: &pb_broker.DeviceActivationResponse{
			Payload: templateBytes,
		},
	})
}
Example #5
0
func (b *broker) HandleUplink(uplink *pb.UplinkMessage) (err error) {
	ctx := b.Ctx.WithField("GatewayID", uplink.GatewayMetadata.GatewayId)
	start := time.Now()
	defer func() {
		if err != nil {
			ctx.WithError(err).Warn("Could not handle uplink")
		} else {
			ctx.WithField("Duration", time.Now().Sub(start)).Info("Handled uplink")
		}
	}()

	time := time.Now()

	b.status.uplink.Mark(1)

	// De-duplicate uplink messages
	duplicates := b.deduplicateUplink(uplink)
	if len(duplicates) == 0 {
		return nil
	}

	b.status.uplinkUnique.Mark(1)

	ctx = ctx.WithField("Duplicates", len(duplicates))

	base := duplicates[0]

	if base.ProtocolMetadata.GetLorawan() == nil {
		return errors.NewErrInvalidArgument("Uplink", "does not contain LoRaWAN metadata")
	}

	// LoRaWAN: Unmarshal
	var phyPayload lorawan.PHYPayload
	err = phyPayload.UnmarshalBinary(base.Payload)
	if err != nil {
		return err
	}
	macPayload, ok := phyPayload.MACPayload.(*lorawan.MACPayload)
	if !ok {
		return errors.NewErrInvalidArgument("Uplink", "does not contain a MAC payload")
	}

	// Request devices from NS
	devAddr := types.DevAddr(macPayload.FHDR.DevAddr)
	ctx = ctx.WithFields(log.Fields{
		"DevAddr": devAddr,
		"FCnt":    macPayload.FHDR.FCnt,
	})
	var getDevicesResp *networkserver.DevicesResponse
	getDevicesResp, err = b.ns.GetDevices(b.Component.GetContext(b.nsToken), &networkserver.DevicesRequest{
		DevAddr: &devAddr,
		FCnt:    macPayload.FHDR.FCnt,
	})
	if err != nil {
		return errors.Wrap(errors.FromGRPCError(err), "NetworkServer did not return devices")
	}
	b.status.deduplication.Update(int64(len(getDevicesResp.Results)))
	if len(getDevicesResp.Results) == 0 {
		return errors.NewErrNotFound(fmt.Sprintf("Device with DevAddr %s and FCnt <= %d", devAddr, macPayload.FHDR.FCnt))
	}
	ctx = ctx.WithField("DevAddrResults", len(getDevicesResp.Results))

	// Sort by FCntUp to optimize the number of MIC checks
	sort.Sort(ByFCntUp(getDevicesResp.Results))

	// Find AppEUI/DevEUI through MIC check
	var device *pb_lorawan.Device
	var micChecks int
	var originalFCnt uint32
	for _, candidate := range getDevicesResp.Results {
		nwkSKey := lorawan.AES128Key(*candidate.NwkSKey)

		// First check with the 16 bit counter
		micChecks++
		ok, err = phyPayload.ValidateMIC(nwkSKey)
		if err != nil {
			return err
		}
		if ok {
			device = candidate
			break
		}

		originalFCnt = macPayload.FHDR.FCnt
		if candidate.Uses32BitFCnt {
			macPayload.FHDR.FCnt = fcnt.GetFull(candidate.FCntUp, uint16(originalFCnt))

			// If 32 bit counter has different value, perform another MIC check
			if macPayload.FHDR.FCnt != originalFCnt {
				micChecks++
				ok, err = phyPayload.ValidateMIC(nwkSKey)
				if err != nil {
					return err
				}
				if ok {
					device = candidate
					break
				}
			}
		}

		return errors.NewErrNotFound("device that validates MIC")
	}
	ctx = ctx.WithFields(log.Fields{
		"MICChecks": micChecks,
		"DevEUI":    device.DevEui,
		"AppEUI":    device.AppEui,
		"AppID":     device.AppId,
		"DevID":     device.DevId,
		"FCnt":      originalFCnt,
	})
	if macPayload.FHDR.FCnt != originalFCnt {
		ctx = ctx.WithField("RealFCnt", macPayload.FHDR.FCnt)
	}

	if device.DisableFCntCheck {
		// TODO: Add warning to message?
	} else if device.FCntUp == 0 {

	} else if macPayload.FHDR.FCnt <= device.FCntUp || macPayload.FHDR.FCnt-device.FCntUp > maxFCntGap {
		// Replay attack or FCnt gap too big
		return errors.NewErrNotFound("device with matching FCnt")
	}

	// Add FCnt to Metadata (because it's not marshaled in lorawan payload)
	base.ProtocolMetadata.GetLorawan().FCnt = macPayload.FHDR.FCnt

	// Collect GatewayMetadata and DownlinkOptions
	var gatewayMetadata []*gateway.RxMetadata
	var downlinkOptions []*pb.DownlinkOption
	var downlinkMessage *pb.DownlinkMessage
	for _, duplicate := range duplicates {
		gatewayMetadata = append(gatewayMetadata, duplicate.GatewayMetadata)
		downlinkOptions = append(downlinkOptions, duplicate.DownlinkOptions...)
	}

	// Select best DownlinkOption
	if len(downlinkOptions) > 0 {
		downlinkMessage = &pb.DownlinkMessage{
			DevEui:         device.DevEui,
			AppEui:         device.AppEui,
			AppId:          device.AppId,
			DevId:          device.DevId,
			DownlinkOption: selectBestDownlink(downlinkOptions),
		}
	}

	// Build Uplink
	deduplicatedUplink := &pb.DeduplicatedUplinkMessage{
		Payload:          base.Payload,
		DevEui:           device.DevEui,
		DevId:            device.DevId,
		AppEui:           device.AppEui,
		AppId:            device.AppId,
		ProtocolMetadata: base.ProtocolMetadata,
		GatewayMetadata:  gatewayMetadata,
		ServerTime:       time.UnixNano(),
		ResponseTemplate: downlinkMessage,
	}

	// Pass Uplink through NS
	deduplicatedUplink, err = b.ns.Uplink(b.Component.GetContext(b.nsToken), deduplicatedUplink)
	if err != nil {
		return errors.Wrap(errors.FromGRPCError(err), "NetworkServer did not handle uplink")
	}

	var announcements []*pb_discovery.Announcement
	announcements, err = b.Discovery.GetAllHandlersForAppID(device.AppId)
	if err != nil {
		return err
	}
	if len(announcements) == 0 {
		return errors.NewErrNotFound(fmt.Sprintf("Handler for AppID %s", device.AppId))
	}
	if len(announcements) > 1 {
		return errors.NewErrInternal(fmt.Sprintf("Multiple Handlers for AppID %s", device.AppId))
	}

	var handler chan<- *pb.DeduplicatedUplinkMessage
	handler, err = b.getHandlerUplink(announcements[0].Id)
	if err != nil {
		return err
	}

	handler <- deduplicatedUplink

	return nil
}
Example #6
0
		gtwClient := router.NewRouterClientForGateway(rtrClient, gatewayID, gatewayToken)
		defer gtwClient.Close()

		downlinkStream := router.NewMonitoredDownlinkStream(gtwClient)
		defer downlinkStream.Close()
		time.Sleep(100 * time.Millisecond)

		joinReq := &pb_lorawan.Message{
			MHDR: pb_lorawan.MHDR{MType: pb_lorawan.MType_JOIN_REQUEST, Major: pb_lorawan.Major_LORAWAN_R1},
			Payload: &pb_lorawan.Message_JoinRequestPayload{JoinRequestPayload: &pb_lorawan.JoinRequestPayload{
				AppEui:   appEUI,
				DevEui:   devEUI,
				DevNonce: types.DevNonce(devNonce),
			}}}
		joinPhy := joinReq.PHYPayload()
		joinPhy.SetMIC(lorawan.AES128Key(appKey))
		bytes, _ := joinPhy.MarshalBinary()

		uplink := &router.UplinkMessage{
			Payload:          bytes,
			GatewayMetadata:  util.GetGatewayMetadata("ttnctl", 868100000),
			ProtocolMetadata: util.GetProtocolMetadata("SF7BW125"),
		}
		uplink.UnmarshalPayload()

		uplinkStream := router.NewMonitoredUplinkStream(gtwClient)
		defer uplinkStream.Close()

		err = uplinkStream.Send(uplink)
		if err != nil {
			ctx.WithError(err).Fatal("Could not send uplink to Router")
Example #7
0
func (h *handler) ConvertToLoRaWAN(ctx log.Interface, appDown *types.DownlinkMessage, ttnDown *pb_broker.DownlinkMessage) error {
	// Find Device
	dev, err := h.devices.Get(appDown.AppID, appDown.DevID)
	if err != nil {
		return err
	}

	// LoRaWAN: Unmarshal Downlink
	var phyPayload lorawan.PHYPayload
	err = phyPayload.UnmarshalBinary(ttnDown.Payload)
	if err != nil {
		return err
	}
	macPayload, ok := phyPayload.MACPayload.(*lorawan.MACPayload)
	if !ok {
		return errors.NewErrInvalidArgument("Downlink", "does not contain a MAC payload")
	}
	if ttnDown.DownlinkOption != nil && ttnDown.DownlinkOption.ProtocolConfig.GetLorawan() != nil {
		macPayload.FHDR.FCnt = ttnDown.DownlinkOption.ProtocolConfig.GetLorawan().FCnt
	}

	// Abort when downlink not needed
	if len(appDown.PayloadRaw) == 0 && !macPayload.FHDR.FCtrl.ACK && len(macPayload.FHDR.FOpts) == 0 {
		return ErrNotNeeded
	}

	// Set FPort
	if appDown.FPort != 0 {
		macPayload.FPort = &appDown.FPort
	}

	// Set Payload
	if len(appDown.PayloadRaw) > 0 {
		macPayload.FRMPayload = []lorawan.Payload{&lorawan.DataPayload{Bytes: appDown.PayloadRaw}}
		if macPayload.FPort == nil || *macPayload.FPort == 0 {
			macPayload.FPort = pointer.Uint8(1)
		}
	} else {
		macPayload.FRMPayload = []lorawan.Payload{}
	}

	// Encrypt
	err = phyPayload.EncryptFRMPayload(lorawan.AES128Key(dev.AppSKey))
	if err != nil {
		return err
	}

	// Set MIC
	err = phyPayload.SetMIC(lorawan.AES128Key(dev.NwkSKey))
	if err != nil {
		return err
	}

	// Marshal
	phyPayloadBytes, err := phyPayload.MarshalBinary()
	if err != nil {
		return err
	}

	ttnDown.Payload = phyPayloadBytes

	return nil
}
Example #8
0
func (h *handler) ConvertFromLoRaWAN(ctx log.Interface, ttnUp *pb_broker.DeduplicatedUplinkMessage, appUp *types.UplinkMessage) error {
	// Find Device
	dev, err := h.devices.Get(ttnUp.AppId, ttnUp.DevId)
	if err != nil {
		return err
	}

	// Check for LoRaWAN
	if lorawan := ttnUp.ProtocolMetadata.GetLorawan(); lorawan == nil {
		return errors.NewErrInvalidArgument("Activation", "does not contain LoRaWAN metadata")
	}

	// LoRaWAN: Unmarshal Uplink
	var phyPayload lorawan.PHYPayload
	err = phyPayload.UnmarshalBinary(ttnUp.Payload)
	if err != nil {
		return err
	}
	macPayload, ok := phyPayload.MACPayload.(*lorawan.MACPayload)
	if !ok {
		return errors.NewErrInvalidArgument("Uplink", "does not contain a MAC payload")
	}
	macPayload.FHDR.FCnt = ttnUp.ProtocolMetadata.GetLorawan().FCnt
	appUp.FCnt = macPayload.FHDR.FCnt

	ctx = ctx.WithField("FCnt", appUp.FCnt)

	// LoRaWAN: Validate MIC
	ok, err = phyPayload.ValidateMIC(lorawan.AES128Key(dev.NwkSKey))
	if err != nil {
		return err
	}
	if !ok {
		return errors.NewErrNotFound("device that validates MIC")
	}

	// LoRaWAN: Decrypt
	if macPayload.FPort != nil && *macPayload.FPort != 0 && len(macPayload.FRMPayload) == 1 {
		appUp.FPort = *macPayload.FPort
		ctx = ctx.WithField("FCnt", appUp.FPort)
		if err := phyPayload.DecryptFRMPayload(lorawan.AES128Key(dev.AppSKey)); err != nil {
			return errors.NewErrInternal("Could not decrypt payload")
		}
		if len(macPayload.FRMPayload) == 1 {
			payload, ok := macPayload.FRMPayload[0].(*lorawan.DataPayload)
			if !ok {
				return errors.NewErrInvalidArgument("Uplink FRMPayload", "must be of type *lorawan.DataPayload")
			}
			appUp.PayloadRaw = payload.Bytes
		}
	}

	// LoRaWAN: Publish ACKs as events
	if macPayload.FHDR.FCtrl.ACK {
		h.mqttEvent <- &types.DeviceEvent{
			AppID: appUp.AppID,
			DevID: appUp.DevID,
			Event: types.DownlinkAckEvent,
		}
	}

	return nil
}