<p>Ludovic Rousseau has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-sim-auth/+/20902">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">ICC.py: convert to Python3 using 2to3<br><br>Change-Id: Ic182573a179d2b4a445c596c8fd87122e348f27b<br>---<br>M card/ICC.py<br>1 file changed, 60 insertions(+), 60 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-sim-auth refs/changes/02/20902/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/card/ICC.py b/card/ICC.py</span><br><span>index a9cfc88..4a2ba0e 100644</span><br><span>--- a/card/ICC.py</span><br><span>+++ b/card/ICC.py</span><br><span>@@ -179,19 +179,19 @@</span><br><span> </span><br><span> check also the more complete "parseATR" tool</span><br><span> '''</span><br><span style="color: hsl(0, 100%, 40%);">- print '\nsmartcard reader: ', self.reader</span><br><span style="color: hsl(120, 100%, 40%);">+ print('\nsmartcard reader: ', self.reader)</span><br><span> if self.ATR != None:</span><br><span style="color: hsl(0, 100%, 40%);">- print "\nsmart card ATR is: %s" % toHexString(self.ATR)</span><br><span style="color: hsl(0, 100%, 40%);">- print 'ATR analysis: '</span><br><span style="color: hsl(0, 100%, 40%);">- print ATR(self.ATR).dump()</span><br><span style="color: hsl(0, 100%, 40%);">- print '\nhistorical bytes: ', \</span><br><span style="color: hsl(0, 100%, 40%);">- toHexString(ATR(self.ATR).getHistoricalBytes())</span><br><span style="color: hsl(120, 100%, 40%);">+ print("\nsmart card ATR is: %s" % toHexString(self.ATR))</span><br><span style="color: hsl(120, 100%, 40%);">+ print('ATR analysis: ')</span><br><span style="color: hsl(120, 100%, 40%);">+ print(ATR(self.ATR).dump())</span><br><span style="color: hsl(120, 100%, 40%);">+ print('\nhistorical bytes: ', \</span><br><span style="color: hsl(120, 100%, 40%);">+ toHexString(ATR(self.ATR).getHistoricalBytes()))</span><br><span> ATRcs = ATR(self.ATR).getChecksum()</span><br><span> if ATRcs :</span><br><span style="color: hsl(0, 100%, 40%);">- print 'checksum: ', "0x%X" % ATRcs</span><br><span style="color: hsl(120, 100%, 40%);">+ print('checksum: ', "0x%X" % ATRcs)</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- print 'no ATR checksum'</span><br><span style="color: hsl(0, 100%, 40%);">- print "\nusing pcsc_scan ATR list file: %s" % smlist_file</span><br><span style="color: hsl(120, 100%, 40%);">+ print('no ATR checksum')</span><br><span style="color: hsl(120, 100%, 40%);">+ print("\nusing pcsc_scan ATR list file: %s" % smlist_file)</span><br><span> if os.path.exists(smlist_file):</span><br><span> smlist = open(smlist_file).readlines()</span><br><span> ATRre = re.compile('(^3[BF]){1}.{1,}$')</span><br><span>@@ -205,11 +205,11 @@</span><br><span> ATRfinger += smlist[i+j][1:]</span><br><span> j += j</span><br><span> if ATRfinger == '' :</span><br><span style="color: hsl(0, 100%, 40%);">- print "no ATR fingerprint found in file: %s" % smlist_file</span><br><span style="color: hsl(120, 100%, 40%);">+ print("no ATR fingerprint found in file: %s" % smlist_file)</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- print "smartcard ATR fingerprint:\n%s" % ATRfinger</span><br><span style="color: hsl(120, 100%, 40%);">+ print("smartcard ATR fingerprint:\n%s" % ATRfinger)</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- print "%s file not found" % smlist_file</span><br><span style="color: hsl(120, 100%, 40%);">+ print("%s file not found" % smlist_file)</span><br><span> </span><br><span> def sw_status(self, sw1, sw2):</span><br><span> '''</span><br><span>@@ -332,7 +332,7 @@</span><br><span> else:</span><br><span> data, sw1, sw2 = self.cardservice.connection.transmit(apdu)</span><br><span> # replaces INS code by strings when available</span><br><span style="color: hsl(0, 100%, 40%);">- if apdu[1] in self.INS_dic.keys(): </span><br><span style="color: hsl(120, 100%, 40%);">+ if apdu[1] in list(self.INS_dic.keys()): </span><br><span> apdu_name = self.INS_dic[apdu[1]] + ' '</span><br><span> else: </span><br><span> apdu_name = ''</span><br><span>@@ -360,7 +360,7 @@</span><br><span> for i in range(start, 256):</span><br><span> ret = self.sr_apdu([i] + param)</span><br><span> if ret[2] != (0x6E, 0x00): </span><br><span style="color: hsl(0, 100%, 40%);">- print ret</span><br><span style="color: hsl(120, 100%, 40%);">+ print(ret)</span><br><span> clist.append(i)</span><br><span> return clist</span><br><span> </span><br><span>@@ -380,11 +380,11 @@</span><br><span> ilist = []</span><br><span> for i in range(start, 256):</span><br><span> if self.dbg > 1: </span><br><span style="color: hsl(0, 100%, 40%);">- print 'DEBUG: testing %d for INS code with %d CLA code' \</span><br><span style="color: hsl(0, 100%, 40%);">- % (i, self.CLA)</span><br><span style="color: hsl(120, 100%, 40%);">+ print('DEBUG: testing %d for INS code with %d CLA code' \</span><br><span style="color: hsl(120, 100%, 40%);">+ % (i, self.CLA))</span><br><span> ret = self.sr_apdu([self.CLA, i, 0x00, 0x00])</span><br><span> if ret[2] != (0x6D, 0x00): </span><br><span style="color: hsl(0, 100%, 40%);">- print ret</span><br><span style="color: hsl(120, 100%, 40%);">+ print(ret)</span><br><span> ilist.append(i)</span><br><span> return ilist</span><br><span> </span><br><span>@@ -677,10 +677,10 @@</span><br><span> '''</span><br><span> ber = BERTLV_parser( Data )</span><br><span> if self.dbg > 1:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] BER structure:\n%s' % ber</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] BER structure:\n%s' % ber)</span><br><span> if len(ber) > 1:</span><br><span> # TODO: implements recursive BER object parsing</span><br><span style="color: hsl(0, 100%, 40%);">- print '[WNG] more than 1 BER object: %s' % ber</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[WNG] more than 1 BER object: %s' % ber)</span><br><span> </span><br><span> # for FCP control structure, precise parsing is done</span><br><span> # this structure seems to be the most used for (U)SIM cards</span><br><span>@@ -694,15 +694,15 @@</span><br><span> if ber[0][0][2] == 0x4: </span><br><span> fil['Control'] = 'FMD'</span><br><span> if self.dbg:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[WNG] FMD file structure parsing not implemented'</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[WNG] FMD file structure parsing not implemented')</span><br><span> elif ber[0][0][2] == 0xF: </span><br><span> fil['Control'] = 'FCI'</span><br><span> if self.dbg:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[WNG] FCI file structure parsing not implemented'</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[WNG] FCI file structure parsing not implemented')</span><br><span> else: </span><br><span> fil['Control'] = ber[0][0]</span><br><span> if self.dbg:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[WNG] unknown file structure'</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[WNG] unknown file structure')</span><br><span> fil['Data'] = ber[0][2]</span><br><span> </span><br><span> return fil</span><br><span>@@ -723,11 +723,11 @@</span><br><span> # would require to work with the BERTLV parser...</span><br><span> [T, L, V] = first_TLV_parser(toProcess)</span><br><span> if self.dbg > 2:</span><br><span style="color: hsl(0, 100%, 40%);">- if T in self.file_tags.keys(): </span><br><span style="color: hsl(120, 100%, 40%);">+ if T in list(self.file_tags.keys()): </span><br><span> Tag = self.file_tags[T]</span><br><span> else: </span><br><span> Tag = T</span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] %s / %s: %s' % (T, Tag, V)</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] %s / %s: %s' % (T, Tag, V))</span><br><span> </span><br><span> # do extra processing here</span><br><span> # File ID, DF name, Short file id</span><br><span>@@ -758,7 +758,7 @@</span><br><span> elif T == 0xA5:</span><br><span> fil = self.parse_proprietary(V, fil)</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- if T in self.file_tags.keys():</span><br><span style="color: hsl(120, 100%, 40%);">+ if T in list(self.file_tags.keys()):</span><br><span> fil[self.file_tags[T]] = V</span><br><span> else:</span><br><span> fil[T] = V</span><br><span>@@ -856,7 +856,7 @@</span><br><span> }</span><br><span> while len(Data) > 0:</span><br><span> [T, L, V] = first_TLV_parser( Data )</span><br><span style="color: hsl(0, 100%, 40%);">- if T in propr_tags.keys(): </span><br><span style="color: hsl(120, 100%, 40%);">+ if T in list(propr_tags.keys()): </span><br><span> fil[propr_tags[T]] = V</span><br><span> Data = Data[L+2:]</span><br><span> return fil</span><br><span>@@ -873,7 +873,7 @@</span><br><span> SC = Data[1:]</span><br><span> sec = '#'</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if 'Type' in fil.keys():</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'Type' in list(fil.keys()):</span><br><span> # DF parsing</span><br><span> if fil['Type'] == 'DF':</span><br><span> if AM & 0b10000000 == 0:</span><br><span>@@ -936,7 +936,7 @@</span><br><span> self.coms.push( self.READ_BINARY(Le=fil['Size']) )</span><br><span> if self.coms()[2] != (0x90, 0x00):</span><br><span> if self.dbg > 1: </span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] %s' % self.coms()</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] %s' % self.coms())</span><br><span> return fil</span><br><span> fil['Data'] = self.coms()[3]</span><br><span> </span><br><span>@@ -952,8 +952,8 @@</span><br><span> # should mean there is an issue </span><br><span> # somewhere in the file parsing process</span><br><span> if self.dbg:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[WNG] error in iterating the RECORD parsing at' \</span><br><span style="color: hsl(0, 100%, 40%);">- ' iteration %s\n%s' % (i, self.coms())</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[WNG] error in iterating the RECORD parsing at' \</span><br><span style="color: hsl(120, 100%, 40%);">+ ' iteration %s\n%s' % (i, self.coms()))</span><br><span> return fil</span><br><span> if self.coms()[3][1:] == len(self.coms()[3][1:]) * [255]:</span><br><span> # record is empty, contains padding only</span><br><span>@@ -1015,7 +1015,7 @@</span><br><span> if is_UICC and self.coms()[2][0] != 0x61 \</span><br><span> or not is_UICC and self.coms()[2][0] != 0x9F:</span><br><span> if self.dbg > 1: </span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] %s' % self.coms()</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] %s' % self.coms())</span><br><span> return None</span><br><span> </span><br><span> # get response and check SW: </span><br><span>@@ -1023,7 +1023,7 @@</span><br><span> self.coms.push(self.GET_RESPONSE(Le=self.coms()[2][1]))</span><br><span> if self.coms()[2] != (0x90, 0x00):</span><br><span> if self.dbg > 1: </span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] %s' % self.coms()</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] %s' % self.coms())</span><br><span> return None</span><br><span> </span><br><span> data = self.coms()[3]</span><br><span>@@ -1073,10 +1073,10 @@</span><br><span> try:</span><br><span> r = self.select(MF)</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[ERR] selecting MF failed'</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[ERR] selecting MF failed')</span><br><span> return</span><br><span> if r == None:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[ERR] MF not found!'</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[ERR] MF not found!')</span><br><span> return</span><br><span> </span><br><span> #if needed, select AID</span><br><span>@@ -1085,10 +1085,10 @@</span><br><span> self.get_AID()</span><br><span> r = self.select_by_aid(under_AID)</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[ERR] selecting AID failed'</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[ERR] selecting AID failed')</span><br><span> return</span><br><span> if r == None:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[ERR] AID not found'</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[ERR] AID not found')</span><br><span> return</span><br><span> </span><br><span> # place on the DF path to bf</span><br><span>@@ -1097,10 +1097,10 @@</span><br><span> try:</span><br><span> path_init = self.select(path, sel_type)</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[ERR] selecting path failed:\n%s' % self.coms()</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[ERR] selecting path failed:\n%s' % self.coms())</span><br><span> return</span><br><span> if path_init == None:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[ERR] path not found: %s' % path</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[ERR] path not found: %s' % path)</span><br><span> return</span><br><span> </span><br><span> # Dany'style programming</span><br><span>@@ -1115,8 +1115,8 @@</span><br><span> i, j = 0, 0</span><br><span> for i in range(hi_addr[0], hi_addr[1]):</span><br><span> if self.dbg and i%2 == 0:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] addr: %s %s %s' % ([hex(v) for v in path], \</span><br><span style="color: hsl(0, 100%, 40%);">- hex(i), hex(j))</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] addr: %s %s %s' % ([hex(v) for v in path], \</span><br><span style="color: hsl(120, 100%, 40%);">+ hex(i), hex(j)))</span><br><span> for j in range(lo_addr[0], lo_addr[1]):</span><br><span> # avoid MF re-selection:</span><br><span> if (i, j) == [0x3F, 0x00]:</span><br><span>@@ -1126,14 +1126,14 @@</span><br><span> fil = self.select([i, j], sel_type)</span><br><span> if fil is not None:</span><br><span> if self.dbg:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] found file at path, id: ' \</span><br><span style="color: hsl(0, 100%, 40%);">- '%s %s' % (path, [i, j])</span><br><span style="color: hsl(0, 100%, 40%);">- if 'File Identifier' in fil.keys():</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] found file at path, id: ' \</span><br><span style="color: hsl(120, 100%, 40%);">+ '%s %s' % (path, [i, j]))</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'File Identifier' in list(fil.keys()):</span><br><span> fil['Absolut Path'] = path+fil['File Identifier']</span><br><span> FS.append(fil)</span><br><span style="color: hsl(0, 100%, 40%);">- if 'Type' in fil.keys() and fil['Type'] == 'DF':</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'Type' in list(fil.keys()) and fil['Type'] == 'DF':</span><br><span> reinit()</span><br><span style="color: hsl(0, 100%, 40%);">- if 'Absolut Path' in fil.keys():</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'Absolut Path' in list(fil.keys()):</span><br><span> DF_to_explore.append(fil['Absolut Path'])</span><br><span> </span><br><span> # re-initialize at MF and return</span><br><span>@@ -1163,12 +1163,12 @@</span><br><span> # recursive method call</span><br><span> # DF contains absolut path</span><br><span> for addr in DF:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] path: %s' % addr</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] path: %s' % addr)</span><br><span> self.recu_files_bf(path=addr, under_AID=under_AID)</span><br><span> </span><br><span> @staticmethod</span><br><span> def __write_dict(dict, fd):</span><br><span style="color: hsl(0, 100%, 40%);">- keys = dict.keys()</span><br><span style="color: hsl(120, 100%, 40%);">+ keys = list(dict.keys())</span><br><span> keys.sort()</span><br><span> fd.write('\n')</span><br><span> for k in keys:</span><br><span>@@ -1320,8 +1320,8 @@</span><br><span> self.AID = []</span><br><span> </span><br><span> if self.dbg:</span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] type definition: %s' % type(self)</span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] CLA definition: %s' % hex(self.CLA)</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] type definition: %s' % type(self))</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] CLA definition: %s' % hex(self.CLA))</span><br><span> #print '[DBG] EF_DIR file selection and reading...'</span><br><span> </span><br><span> def parse_file(self, Data=[]):</span><br><span>@@ -1338,11 +1338,11 @@</span><br><span> fil = ISO7816.parse_file(self, Data)</span><br><span> </span><br><span> # Then UICC extra attributes parsing</span><br><span style="color: hsl(0, 100%, 40%);">- if 0xC6 in fil.keys():</span><br><span style="color: hsl(120, 100%, 40%);">+ if 0xC6 in list(fil.keys()):</span><br><span> fil = self.parse_pin_status(fil[0xC6], fil)</span><br><span> del fil[0xC6]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if 'File Identifier' in fil.keys():</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'File Identifier' in list(fil.keys()):</span><br><span> for ref in self.files:</span><br><span> if fil['File Identifier'] == ref[0]:</span><br><span> fil['Name'] = ref[2]</span><br><span>@@ -1410,7 +1410,7 @@</span><br><span> # EF_DIR is at the MF level and contains Application ID:</span><br><span> EF_DIR = self.select([0x2F, 0x00], typ='pmf')</span><br><span> if self.dbg: </span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] EF_DIR: %s' % EF_DIR</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] EF_DIR: %s' % EF_DIR)</span><br><span> if EF_DIR is None: </span><br><span> return None</span><br><span> </span><br><span>@@ -1430,22 +1430,22 @@</span><br><span> </span><br><span> # get AID application code, depending on SDO...</span><br><span> if aid_rid == (0xA0, 0x00, 0x00, 0x00, 0x09) \</span><br><span style="color: hsl(0, 100%, 40%);">- and aid_app in self.ETSI_AID_app_code.keys(): </span><br><span style="color: hsl(120, 100%, 40%);">+ and aid_app in list(self.ETSI_AID_app_code.keys()): </span><br><span> aid_app = self.ETSI_AID_app_code[aid_app]</span><br><span> if aid_rid == (0xA0, 0x00, 0x00, 0x00, 0x87) \</span><br><span style="color: hsl(0, 100%, 40%);">- and aid_app in self.GPP_AID_app_code.keys(): </span><br><span style="color: hsl(120, 100%, 40%);">+ and aid_app in list(self.GPP_AID_app_code.keys()): </span><br><span> aid_app = self.GPP_AID_app_code[aid_app]</span><br><span> if aid_rid == (0xA0, 0x00, 0x00, 0x03, 0x43) \</span><br><span style="color: hsl(0, 100%, 40%);">- and aid_app in self.GPP2_AID_app_code.keys(): </span><br><span style="color: hsl(120, 100%, 40%);">+ and aid_app in list(self.GPP2_AID_app_code.keys()): </span><br><span> aid_app = self.GPP2_AID_app_code[aid_app]</span><br><span> # get AID responsible SDO and country</span><br><span style="color: hsl(0, 100%, 40%);">- if aid_rid in self.AID_RID.keys(): aid_rid = self.AID_RID[aid_rid]</span><br><span style="color: hsl(0, 100%, 40%);">- if aid_country in self.AID_country_code.keys(): </span><br><span style="color: hsl(120, 100%, 40%);">+ if aid_rid in list(self.AID_RID.keys()): aid_rid = self.AID_RID[aid_rid]</span><br><span style="color: hsl(120, 100%, 40%);">+ if aid_country in list(self.AID_country_code.keys()): </span><br><span> aid_country = self.AID_country_code[aid_country]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- print 'found [AID %s] %s || %s || %s || %s || %s' \</span><br><span style="color: hsl(120, 100%, 40%);">+ print('found [AID %s] %s || %s || %s || %s || %s' \</span><br><span> % (i, aid_rid, aid_app, aid_country, \</span><br><span style="color: hsl(0, 100%, 40%);">- aid_provider, tuple(aid[11:]) )</span><br><span style="color: hsl(120, 100%, 40%);">+ aid_provider, tuple(aid[11:]) ))</span><br><span> i += 1</span><br><span> </span><br><span> def get_ICCID(self):</span><br><span>@@ -1459,7 +1459,7 @@</span><br><span> # EF_ICCID is at the MF level and contains Application ID:</span><br><span> EF_ICCID = self.select([0x2F, 0xE2], typ='pmf')</span><br><span> if self.dbg: </span><br><span style="color: hsl(0, 100%, 40%);">- print '[DBG] EF_ICCID: %s' % EF_ICCID</span><br><span style="color: hsl(120, 100%, 40%);">+ print('[DBG] EF_ICCID: %s' % EF_ICCID)</span><br><span> if EF_ICCID is None: </span><br><span> return None</span><br><span> return decode_BCD( EF_ICCID['Data'] )</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-sim-auth/+/20902">change 20902</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-sim-auth/+/20902"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-sim-auth </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ic182573a179d2b4a445c596c8fd87122e348f27b </div>
<div style="display:none"> Gerrit-Change-Number: 20902 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Ludovic Rousseau <ludovic.rousseau+osmocom@free.fr> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>