add MCC/MNC name lookup to *3gpp_uli converter

This commit is contained in:
ionutboangiu
2026-02-13 20:35:36 +02:00
committed by Dan Christian Bogos
parent 69b940039b
commit 48a9441a39
6 changed files with 3516 additions and 24 deletions

114
data/scripts/gen_mccmnc.go Normal file
View File

@@ -0,0 +1,114 @@
//go:build ignore
// Parses Wireshark's packet-e212.c and generates utils/mccmnc_data.go.
// Run: go generate ./utils/...
package main
import (
"fmt"
"go/format"
"io"
"log"
"net/http"
"os"
"regexp"
"sort"
"strconv"
"strings"
)
const wiresharkURL = "https://raw.githubusercontent.com/wireshark/wireshark/master/epan/dissectors/packet-e212.c"
// matches entries like { 123, "Some Name" } in C value_string arrays
var entryRe = regexp.MustCompile(`\{\s*(\d+),\s*"([^"]+)"\s*\}`)
func main() {
log.SetFlags(0)
src := fetchSource()
countries := parseTable(src, "E212_codes[]", func(code int) string {
return fmt.Sprintf("%03d", code)
})
networks := parseTable(src, "mcc_mnc_2digits_codes[]", func(code int) string {
return fmt.Sprintf("%03d-%02d", code/100, code%100)
})
// 3-digit MNC: only add if no 2-digit entry exists for the same key
for k, v := range parseTable(src, "mcc_mnc_3digits_codes[]", func(code int) string {
return fmt.Sprintf("%03d-%03d", code/1000, code%1000)
}) {
if _, ok := networks[k]; !ok {
networks[k] = v
}
}
var buf strings.Builder
buf.WriteString("// Code generated by gen_mccmnc from Wireshark's packet-e212.c; DO NOT EDIT.\n\npackage utils\n\n")
writeMap(&buf, "mccCountry", "MCC to country name (ITU-T E.212)", countries)
writeMap(&buf, "mccmncNetwork", "MCC-MNC to network/operator name (ITU-T E.212)", networks)
formatted, err := format.Source([]byte(buf.String()))
if err != nil {
log.Fatalf("gofmt: %v", err)
}
if err := os.WriteFile("mccmnc_data.go", formatted, 0644); err != nil {
log.Fatal(err)
}
fmt.Printf("generated mccmnc_data.go: %d countries, %d networks\n", len(countries), len(networks))
}
func fetchSource() string {
resp, err := http.Get(wiresharkURL)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
return string(body)
}
func parseTable(src, name string, formatKey func(int) string) map[string]string {
block := extractBlock(src, name)
if block == "" {
log.Fatalf("table %s not found", name)
}
result := make(map[string]string)
for _, m := range entryRe.FindAllStringSubmatch(block, -1) {
if m[2] == "Unassigned" || m[2] == "Unset" {
continue
}
code, _ := strconv.Atoi(m[1])
result[formatKey(code)] = m[2]
}
return result
}
// extractBlock returns the body of a C value_string array, up to its { 0, NULL } terminator.
func extractBlock(src, name string) string {
marker := "value_string " + name + " = {"
start := strings.Index(src, marker)
if start < 0 {
return ""
}
end := strings.Index(src[start:], "{ 0, NULL }")
if end < 0 {
return ""
}
return src[start : start+end]
}
func writeMap(buf *strings.Builder, varName, comment string, m map[string]string) {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
fmt.Fprintf(buf, "// %s maps %s.\nvar %s = map[string]string{\n", varName, comment, varName)
for _, k := range keys {
fmt.Fprintf(buf, "\t%q: %q,\n", k, m[k])
}
buf.WriteString("}\n\n")
}