Skip to content

Commit

Permalink
gs: Do not reject proprietary frames in Basics Station
Browse files Browse the repository at this point in the history
  • Loading branch information
adriansmares committed May 13, 2024
1 parent ece0031 commit 1f04366
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 31 deletions.
9 changes: 0 additions & 9 deletions config/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -4949,15 +4949,6 @@
"file": "upstream.go"
}
},
"error:pkg/gatewayserver/io/ws/lbslns:mhdr": {
"translations": {
"en": "invalid MHDR `{mhdr}` received"
},
"description": {
"package": "pkg/gatewayserver/io/ws/lbslns",
"file": "upstream.go"
}
},
"error:pkg/gatewayserver/io/ws/lbslns:session_state_not_found": {
"translations": {
"en": "session state not found"
Expand Down
42 changes: 27 additions & 15 deletions pkg/gatewayserver/io/ws/lbslns/upstream.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ var (
errJoinRequestMessage = errors.Define("join_request_message", "invalid join-request message received")
errUplinkDataFrame = errors.Define("uplink_data_frame", "invalid uplink data frame received")
errUplinkMessage = errors.Define("uplink_message", "invalid uplink message received")
errMDHR = errors.Define("mhdr", "invalid MHDR `{mhdr}` received")
errDataRate = errors.Define("data_rate", "invalid data rate")
)

Expand Down Expand Up @@ -185,14 +184,20 @@ func (tsr TimeSyncResponse) MarshalJSON() ([]byte, error) {
})
}

// toUplinkMessage extracts fields from the Basics Station Join Request "jreq" message and converts them into an UplinkMessage for the network server.
func (req *JoinRequest) toUplinkMessage(ids *ttnpb.GatewayIdentifiers, bandID string, receivedAt time.Time) (*ttnpb.UplinkMessage, error) {
var up ttnpb.UplinkMessage
// toUplinkMessage extracts fields from the Basics Station Join Request "jreq"
// message and converts them into an UplinkMessage for the network server.
func (req *JoinRequest) toUplinkMessage(
ids *ttnpb.GatewayIdentifiers, bandID string, receivedAt time.Time,
) (*ttnpb.UplinkMessage, error) {
up := &ttnpb.UplinkMessage{}
up.ReceivedAt = timestamppb.New(receivedAt)

parsedMHDR := &ttnpb.MHDR{}
if err := lorawan.UnmarshalMHDR([]byte{byte(req.MHdr)}, parsedMHDR); err != nil {
return nil, errMDHR.WithAttributes(`mhdr`, parsedMHDR)
return nil, errJoinRequestMessage.WithCause(err)
}
if err := parsedMHDR.ValidateFields(); err != nil {
return nil, errJoinRequestMessage.WithCause(err)
}

micBytes, err := getInt32AsByteSlice(req.MIC)
Expand Down Expand Up @@ -246,7 +251,7 @@ func (req *JoinRequest) toUplinkMessage(ids *ttnpb.GatewayIdentifiers, bandID st
Time: ttnpb.ProtoTime(tm),
}

return &up, nil
return up, nil
}

// FromUplinkMessage extracts fields from ttnpb.UplinkMessage and creates the LoRa Basics Station Join Request Frame.
Expand Down Expand Up @@ -303,17 +308,20 @@ func (req *JoinRequest) FromUplinkMessage(up *ttnpb.UplinkMessage, bandID string
return nil
}

// toUplinkMessage extracts fields from the LoRa Basics Station Uplink Data Frame "updf" message and converts them into an UplinkMessage for the network server.
func (updf *UplinkDataFrame) toUplinkMessage(ids *ttnpb.GatewayIdentifiers, bandID string, receivedAt time.Time) (*ttnpb.UplinkMessage, error) {
var up ttnpb.UplinkMessage
// toUplinkMessage extracts fields from the LoRa Basics Station Uplink Data Frame "updf"
// message and converts them into an UplinkMessage for the network server.
func (updf *UplinkDataFrame) toUplinkMessage(
ids *ttnpb.GatewayIdentifiers, bandID string, receivedAt time.Time,
) (*ttnpb.UplinkMessage, error) {
up := &ttnpb.UplinkMessage{}
up.ReceivedAt = timestamppb.New(receivedAt)

parsedMHDR := &ttnpb.MHDR{}
if err := lorawan.UnmarshalMHDR([]byte{byte(updf.MHdr)}, parsedMHDR); err != nil {
return nil, errUplinkDataFrame.WithCause(err)
}
if parsedMHDR.MType != ttnpb.MType_UNCONFIRMED_UP && parsedMHDR.MType != ttnpb.MType_CONFIRMED_UP {
return nil, errMDHR.WithAttributes(`mhdr`, parsedMHDR)
if err := parsedMHDR.ValidateFields(); err != nil {
return nil, errUplinkDataFrame.WithCause(err)
}

micBytes, err := getInt32AsByteSlice(updf.MIC)
Expand All @@ -331,8 +339,11 @@ func (updf *UplinkDataFrame) toUplinkMessage(ids *ttnpb.GatewayIdentifiers, band
var devAddr types.DevAddr
devAddr.UnmarshalNumber(uint32(updf.DevAddr))

fctrl := &ttnpb.FCtrl{}
if err := lorawan.UnmarshalFCtrl([]byte{byte(updf.FCtrl)}, fctrl, true); err != nil {
fCtrl := &ttnpb.FCtrl{}
if err := lorawan.UnmarshalFCtrl([]byte{byte(updf.FCtrl)}, fCtrl, true); err != nil {
return nil, errUplinkDataFrame.WithCause(err)
}
if err := fCtrl.ValidateFields(); err != nil {
return nil, errUplinkDataFrame.WithCause(err)
}

Expand All @@ -354,7 +365,7 @@ func (updf *UplinkDataFrame) toUplinkMessage(ids *ttnpb.GatewayIdentifiers, band
FrmPayload: decFRMPayload,
FHdr: &ttnpb.FHDR{
DevAddr: devAddr.Bytes(),
FCtrl: fctrl,
FCtrl: fCtrl,
FCnt: uint32(updf.FCnt),
FOpts: decFOpts,
},
Expand Down Expand Up @@ -397,7 +408,8 @@ func (updf *UplinkDataFrame) toUplinkMessage(ids *ttnpb.GatewayIdentifiers, band
Timestamp: timestamp,
Time: ttnpb.ProtoTime(tm),
}
return &up, nil

return up, nil
}

func getFCtrlAsUint(fCtrl *ttnpb.FCtrl) uint {
Expand Down
12 changes: 6 additions & 6 deletions pkg/gatewayserver/io/ws/lbslns/upstream_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,19 +277,19 @@ func TestUplinkDataFrame(t *testing.T) {
for _, tc := range []struct {
Name string
UplinkDataFrame UplinkDataFrame
GatewayIds *ttnpb.GatewayIdentifiers
GatewayIDs *ttnpb.GatewayIdentifiers
FrequencyPlanID string
ExpectedUplinkMessage *ttnpb.UplinkMessage
ErrorAssertion func(err error) bool
}{
{
Name: "Empty",
UplinkDataFrame: UplinkDataFrame{},
GatewayIds: gtwID,
GatewayIDs: gtwID,
FrequencyPlanID: band.EU_863_870,
ExpectedUplinkMessage: &ttnpb.UplinkMessage{},
ErrorAssertion: func(err error) bool {
return errors.Resemble(err, errMDHR)
return errors.Resemble(err, errUplinkDataFrame)
},
},
{
Expand All @@ -314,7 +314,7 @@ func TestUplinkDataFrame(t *testing.T) {
},
},
},
GatewayIds: gtwID,
GatewayIDs: gtwID,
FrequencyPlanID: band.EU_863_870,
ExpectedUplinkMessage: &ttnpb.UplinkMessage{
Payload: &ttnpb.Message{
Expand Down Expand Up @@ -378,7 +378,7 @@ func TestUplinkDataFrame(t *testing.T) {
},
},
},
GatewayIds: gtwID,
GatewayIDs: gtwID,
FrequencyPlanID: band.EU_863_870,
ExpectedUplinkMessage: &ttnpb.UplinkMessage{
Payload: &ttnpb.Message{
Expand Down Expand Up @@ -425,7 +425,7 @@ func TestUplinkDataFrame(t *testing.T) {
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
a := assertions.New(t)
msg, err := tc.UplinkDataFrame.toUplinkMessage(tc.GatewayIds, tc.FrequencyPlanID, time.Time{})
msg, err := tc.UplinkDataFrame.toUplinkMessage(tc.GatewayIDs, tc.FrequencyPlanID, time.Time{})
if err != nil {
if tc.ErrorAssertion == nil || !a.So(tc.ErrorAssertion(err), should.BeTrue) {
t.Fatalf("Unexpected error: %v", err)
Expand Down
1 change: 0 additions & 1 deletion pkg/webui/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -2058,7 +2058,6 @@
"error:pkg/gatewayserver/io/ws/lbslns:data_rate": "無効なデータレート",
"error:pkg/gatewayserver/io/ws/lbslns:empty_gateway_eui": "ゲートウェイEUIが空",
"error:pkg/gatewayserver/io/ws/lbslns:join_request_message": "無効なジョイン要求メッセージを受信しました",
"error:pkg/gatewayserver/io/ws/lbslns:mhdr": "無効なMHDR`{mhdr}`を受信しました",
"error:pkg/gatewayserver/io/ws/lbslns:session_state_not_found": "セッションステートが見つかりません",
"error:pkg/gatewayserver/io/ws/lbslns:uplink_data_frame": "無効なアップリンクデータフレームを受信しました",
"error:pkg/gatewayserver/io/ws/lbslns:uplink_message": "無効なアップリンクメッセージを受信しました",
Expand Down

0 comments on commit 1f04366

Please sign in to comment.