def update_subscriber(self, subscriber_data): """ Method that updates the subscriber. edit_subscriber should be generally used since that guarantees the read/update/write atomicity, but this can be used if the application can guarantee the atomicity using a lock. Args: subscriber_data - SubscriberData protobuf message Raises: SubscriberNotFoundError if the subscriber is not present """ sid = SIDUtils.to_str(subscriber_data.sid) data_str = subscriber_data.SerializeToString() with self.conn: res = self.conn.execute( "UPDATE subscriberdb SET data = ? " "WHERE subscriber_id = ?", (data_str, sid)) if not res.rowcount: raise SubscriberNotFoundError(sid)
def get_gsm_auth_vector(self, imsi): """ Returns the gsm auth tuple for the subsciber by querying the store for the crypto algo and secret keys. """ sid = SIDUtils.to_str(SubscriberID(id=imsi, type=SubscriberID.IMSI)) subs = self._store.get_subscriber_data(sid) if subs.gsm.state != GSMSubscription.ACTIVE: raise CryptoError("GSM service not active for %s" % sid) # The only GSM crypto algo we support now if subs.gsm.auth_algo != GSMSubscription.PRECOMPUTED_AUTH_TUPLES: raise CryptoError("Unknown crypto (%s) for %s" % (subs.gsm.auth_algo, sid)) gsm_crypto = UnsafePreComputedA3A8() if len(subs.gsm.auth_tuples) == 0: raise CryptoError("Auth key not present for %s" % sid) return gsm_crypto.generate_auth_tuple(subs.gsm.auth_tuples[0])
def AllocateIPAddress(self, request, context): """ Allocate an IP address from the free IP pool """ resp = IPAddress() if request.version == AllocateIPRequest.IPV4: try: subscriber_id = SIDUtils.to_str(request.sid) ip = self._ipv4_allocator.alloc_ip_address(subscriber_id) logging.info("Allocated IPv4 %s for sid %s" % (ip, subscriber_id)) resp.version = IPAddress.IPV4 resp.address = ip.packed except NoAvailableIPError: context.set_details('No free IPv4 IP available') context.set_code(grpc.StatusCode.RESOURCE_EXHAUSTED) except DuplicatedIPAllocationError: context.set_details( 'IP has been allocated for this subscriber') context.set_code(grpc.StatusCode.ALREADY_EXISTS) else: self._unimplemented_ip_version_error(context) return resp
def _get_allocate_ip_response(self, composite_sid, version, context, ip_addr, request): try: ip, vlan = self._ip_address_man.alloc_ip_address(composite_sid, version) logging.info("Allocated IP %s for sid %s for apn %s" % (ip, SIDUtils.to_str(request.sid), request.apn)) ip_addr.version = version ip_addr.address = ip.packed return AllocateIPAddressResponse(ip_list=[ip_addr], vlan=str(vlan)) except NoAvailableIPError: context.set_details('No free IP available') context.set_code(grpc.StatusCode.RESOURCE_EXHAUSTED) except DuplicatedIPAllocationError: context.set_details( 'IP has been allocated for this subscriber') context.set_code(grpc.StatusCode.ALREADY_EXISTS) except DuplicateIPAssignmentError: context.set_details( 'IP has been allocated for other subscriber') context.set_code(grpc.StatusCode.ALREADY_EXISTS) except MaxCalculationError: context.set_details( 'Reached maximum IPv6 calculation tries') context.set_code(grpc.StatusCode.RESOURCE_EXHAUSTED) except SubscriberDBConnectionError: context.set_details( 'Could not connect to SubscriberDB') context.set_code(grpc.StatusCode.FAILED_PRECONDITION) except SubscriberDBStaticIPValueError: context.set_details( 'Could not parse static IP response from SubscriberDB') context.set_code(grpc.StatusCode.FAILED_PRECONDITION) except SubscriberDBMultiAPNValueError: context.set_details( 'Could not parse MultiAPN IP response from SubscriberDB') context.set_code(grpc.StatusCode.FAILED_PRECONDITION) return AllocateIPAddressResponse()
def add_subscriber(self, subscriber_data): """ Method that adds the subscriber. """ sid = SIDUtils.to_str(subscriber_data.sid) data_str = subscriber_data.SerializeToString() db_location = self._db_locations[self._sid2bucket(sid)] conn = sqlite3.connect(db_location, uri=True) try: with conn: res = conn.execute( "SELECT data FROM subscriberdb WHERE " "subscriber_id = ?", (sid, )) if res.fetchone(): raise DuplicateSubscriberError(sid) conn.execute( "INSERT INTO subscriberdb(subscriber_id, data) " "VALUES (?, ?)", (sid, data_str)) finally: conn.close() self._on_ready.add_subscriber(subscriber_data)
def GetSubscriberData(self, request, context): """ Return the subscription data for the subscriber """ print_grpc( request, self._print_grpc_payload, "Get Subscriber Data Request:", ) sid = SIDUtils.to_str(request) try: response = self._store.get_subscriber_data(sid) except SubscriberNotFoundError: context.set_details("Subscriber not found: %s" % sid) context.set_code(grpc.StatusCode.NOT_FOUND) response = subscriberdb_pb2.SubscriberData() print_grpc( response, self._print_grpc_payload, "Get Subscriber Data Response:", ) return response
def UpdateSubscriber(self, request, context): """ Update the subscription data """ try: print_grpc( request, self._print_grpc_payload, "Update Subscriber Request", ) except Exception as e: # pylint: disable=broad-except logging.debug("Exception while trying to log GRPC: %s", e) sid = SIDUtils.to_str(request.data.sid) try: with self._store.edit_subscriber(sid) as subs: request.mask.MergeMessage( request.data, subs, replace_message_field=True, ) except SubscriberNotFoundError: context.set_details("Subscriber not found: %s" % sid) context.set_code(grpc.StatusCode.NOT_FOUND)
def list_subscribers(client, args): for sid in client.ListSubscribers(Void()).sids: print(SIDUtils.to_str(sid))
def get_subscriber_ip_table_handler(client, args): table = client.GetSubscriberIPTable(Void()) print("SID\t\tIP\t\tAPN") for entry in table.entries: ip = ipaddress.ip_address(entry.ip.address) print("%s\t%s\t%s" % (SIDUtils.to_str(entry.sid), ip, entry.apn))