Skip to content

Commit

Permalink
Merge pull request #183 from nickvsnetworking/ReAuth_Testing
Browse files Browse the repository at this point in the history
ReAuth / Gx fixes
  • Loading branch information
davidkneipp authored Jan 15, 2024
2 parents eff246b + 72a4b17 commit 213f43f
Showing 1 changed file with 90 additions and 7 deletions.
97 changes: 90 additions & 7 deletions lib/diameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import json
import time
import traceback
import re

class Diameter:

Expand Down Expand Up @@ -176,6 +177,7 @@ def DecodePLMN(self, plmn):
return mcc, mnc

def EncodePLMN(self, mcc, mnc):
plmn = list('XXXXXX')
if len(mnc) == 2:
plmn[0] = self.Reverse(mcc)[1]
plmn[1] = self.Reverse(mcc)[2]
Expand Down Expand Up @@ -581,6 +583,7 @@ def getConnectedPeersByType(self, peerType: str) -> list:
return []

def getPeerByHostname(self, hostname: str) -> dict:
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [getPeerByHostname] Looking for peer with hostname {hostname}", redisClient=self.redisMessaging)
try:
hostname = hostname.lower()
activePeers = json.loads(self.redisMessaging.getValue(key="ActiveDiameterPeers").decode())
Expand All @@ -590,6 +593,7 @@ def getPeerByHostname(self, hostname: str) -> dict:
return(activePeers.get(key, {}))

except Exception as e:
self.logTool.log(service='HSS', level='error', message=f"[diameter.py] [getPeerByHostname] Failed to find peer with hostname {hostname}", redisClient=self.redisMessaging)
return {}

def getDiameterMessageType(self, binaryData: str) -> dict:
Expand Down Expand Up @@ -704,10 +708,12 @@ def awaitDiameterRequestAndResponse(self, requestType: str, hostname: str, timeo
except Exception as e:
continue
connectedPeer = self.getPeerByHostname(hostname=hostname)
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [awaitDiameterRequestAndResponse] [{requestType}] Sending request via connected peer {connectedPeer} from hostname {hostname}", redisClient=self.redisMessaging)
try:
peerIp = connectedPeer['ipAddress']
peerPort = connectedPeer['port']
except Exception as e:
self.logTool.log(service='HSS', level='error', message=f"[diameter.py] [awaitDiameterRequestAndResponse] [{requestType}] Could not get connection information for connectedPeer: {connectedPeer}", redisClient=self.redisMessaging)
return ''
request = diameterApplication["requestMethod"](**kwargs)
responseType = diameterApplication["responseAcronym"]
Expand Down Expand Up @@ -1180,7 +1186,7 @@ def Charging_Rule_Generator(self, ChargingRules=None, ue_ip=None, chargingRuleNa
#Populate all Flow Information AVPs
Flow_Information = ''
for tft in ChargingRules['tft']:
self.logTool.log(service='HSS', level='debug', message=tft, redisClient=self.redisMessaging)
self.logTool.log(service='HSS', level='debug', message="Adding TFT: " + str(tft), redisClient=self.redisMessaging)
#If {{ UE_IP }} in TFT splice in the real UE IP Value
try:
tft['tft_string'] = tft['tft_string'].replace('{{ UE_IP }}', str(ue_ip))
Expand Down Expand Up @@ -2882,6 +2888,81 @@ def Answer_16777236_265(self, packet_vars, avps):
except Exception as e:
pass

#Extract the SDP for each direction to find the source and destination IP Addresses and Ports used for the RTP streams
try:
sdp1 = self.get_avp_data(avps, 524)[0]
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] got first SDP body raw: " + str(sdp1), redisClient=self.redisMessaging)
sdp1 = binascii.unhexlify(sdp1).decode('utf-8')
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] got first SDP body decoded: " + str(sdp1), redisClient=self.redisMessaging)
sdp2 = self.get_avp_data(avps, 524)[1]
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] got second SDP body raw: " + str(sdp2), redisClient=self.redisMessaging)
sdp2 = binascii.unhexlify(sdp2).decode('utf-8')
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] got second SDP body decoded: " + str(sdp2), redisClient=self.redisMessaging)

regex_ipv4 = r"IN IP4 (\d*\.\d*\.\d*\.\d*)"
regex_ipv6 = r"IN IP6 ([0-9a-fA-F:]{3,39})"
regex_port_audio = r"m=audio (\d*)"
regex_port_rtcp = r"a=rtcp:(\d*)"

#Check for IPv4 Matches in first SDP Body
matches_ipv4 = re.search(regex_ipv4, sdp1, re.MULTILINE)
if matches_ipv4:
sdp1_ipv4 = str(matches_ipv4.group(1))
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] Matched SDP IPv4" + str(sdp1_ipv4), redisClient=self.redisMessaging)
else:
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] No matches for IPv4 in SDP", redisClient=self.redisMessaging)
if not matches_ipv4:
#Check for IPv6 Matches
matches_ipv6 = re.search(regex_ipv6, sdp1, re.MULTILINE)
if matches_ipv6:
sdp1_ipv6 = str(matches_ipv6.group(1))
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] Matched SDP IPv6" + str(sdp1_ipv6), redisClient=self.redisMessaging)
else:
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] No matches for IPv6 in SDP", redisClient=self.redisMessaging)


#Check for IPv4 Matches in second SDP Body
matches_ipv4 = re.search(regex_ipv4, sdp2, re.MULTILINE)
if matches_ipv4:
sdp2_ipv4 = str(matches_ipv4.group(1))
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] Matched SDP2 IPv4 " + str(sdp2_ipv4), redisClient=self.redisMessaging)
else:
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] No matches for IPv4 in SDP2", redisClient=self.redisMessaging)
if not matches_ipv4:
#Check for IPv6 Matches
matches_ipv6 = re.search(regex_ipv6, sdp2, re.MULTILINE)
if matches_ipv6:
sdp2_ipv6 = str(matches_ipv6.group(1))
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] Matched SDP2 IPv6 " + str(sdp2_ipv6), redisClient=self.redisMessaging)
else:
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] No matches for IPv6 in SDP", redisClient=self.redisMessaging)

#Extract RTP Port
matches_rtp_port = re.search(regex_port_audio, sdp2, re.MULTILINE)
if matches_rtp_port:
sdp2_rtp_port = str(matches_rtp_port.group(1))
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] Matched SDP2 RTP Port " + str(sdp2_rtp_port), redisClient=self.redisMessaging)

#Extract RTP Port
matches_rtp_port = re.search(regex_port_audio, sdp1, re.MULTILINE)
if matches_rtp_port:
sdp1_rtp_port = str(matches_rtp_port.group(1))
sdp1_rtcp_port = int(sdp1_rtp_port) - 1
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] Matched SDP1 RTP Port " + str(sdp1_rtp_port), redisClient=self.redisMessaging)


#Extract RTP Port
matches_rtp_port = re.search(regex_port_audio, sdp2, re.MULTILINE)
if matches_rtp_port:
sdp2_rtp_port = str(matches_rtp_port.group(1))
sdp2_rtcp_port = int(sdp2_rtp_port) - 1
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] Matched SDP2 RTP Port " + str(sdp2_rtp_port), redisClient=self.redisMessaging)


except Exception as e:
self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] Failed to extract SDP due to error" + str(e), redisClient=self.redisMessaging)


"""
The below logic is applied:
1. Grab the Flow Rules and bitrates from the PCSCF in the AAR,
Expand All @@ -2894,14 +2975,14 @@ def Answer_16777236_265(self, packet_vars, avps):
chargingRule = {
"charging_rule_id": 1000,
"qci": 1,
"arp_preemption_capability": True,
"arp_preemption_capability": False,
"mbr_dl": dlBandwidth,
"mbr_ul": ulBandwidth,
"gbr_ul": ulBandwidth,
"precedence": 100,
"arp_priority": 2,
"precedence": 40,
"arp_priority": 15,
"rule_name": "GBR-Voice",
"arp_preemption_vulnerability": False,
"arp_preemption_vulnerability": True,
"gbr_dl": dlBandwidth,
"tft_group_id": 1,
"rating_group": None,
Expand All @@ -2910,20 +2991,22 @@ def Answer_16777236_265(self, packet_vars, avps):
"tft_group_id": 1,
"direction": 1,
"tft_id": 1,
"tft_string": "permit out 17 from {{ UE_IP }}/32 1-65535 to any 1-65535"
"tft_string": "permit out 17 from " + str(sdp2_ipv4) + "/32 " + str(sdp2_rtcp_port) + "-" + str(sdp2_rtp_port) + " to " + str(ueIp) + "/32 " + str(sdp1_rtcp_port) + "-" + str(sdp1_rtp_port)
},
{
"tft_group_id": 1,
"direction": 2,
"tft_id": 2,
"tft_string": "permit out 17 from {{ UE_IP }}/32 1-65535 to any 1-65535"
"tft_string": "permit out 17 from " + str(sdp2_ipv4) + "/32 " + str(sdp2_rtcp_port) + "-" + str(sdp2_rtp_port) + " to " + str(ueIp) + "/32 " + str(sdp1_rtcp_port) + "-" + str(sdp1_rtp_port)
}
]
}

if not emergencySubscriber:
self.database.Update_Proxy_CSCF(imsi=imsi, proxy_cscf=aarOriginHost, pcscf_realm=aarOriginRealm, pcscf_peer=remotePeer, pcscf_active_session=sessionId)


self.logTool.log(service='HSS', level='debug', message=f"[diameter.py] [Answer_16777236_265] [AAA] RAR Generated to be sent to serving PGW: {servingPgw} via peer {servingPgwPeer}", redisClient=self.redisMessaging)
reAuthAnswer = self.awaitDiameterRequestAndResponse(
requestType='RAR',
hostname=servingPgwPeer,
Expand Down

0 comments on commit 213f43f

Please sign in to comment.