Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a08d11b09 |
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/target
|
||||||
|
SIM_config.csv
|
||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "sim_card_batcher"
|
name = "sim_card_batcher"
|
||||||
version = "0.2.0"
|
version = "0.3.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|||||||
73
src/main.rs
73
src/main.rs
@ -1,13 +1,11 @@
|
|||||||
use std::fs::File;
|
|
||||||
use std::io::prelude::*;
|
|
||||||
use std::process::{Command, exit};
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use colored::*;
|
use colored::*;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::prelude::*;
|
||||||
|
use std::process::{exit, Command};
|
||||||
|
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
|
|
||||||
// setup cli parser
|
// setup cli parser
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(
|
#[command(
|
||||||
@ -21,7 +19,7 @@ pub struct CliArgs {
|
|||||||
/// The path to the csv file to read
|
/// The path to the csv file to read
|
||||||
#[arg(short = 'c', long = "csv")]
|
#[arg(short = 'c', long = "csv")]
|
||||||
csv: String,
|
csv: String,
|
||||||
/// Set the output file with the commands for the HSS on the core
|
/// Set the output file with the commands for the UDM/Sql on the core
|
||||||
#[arg(short = 'o', long = "output", default_value_t = String::from("output"))]
|
#[arg(short = 'o', long = "output", default_value_t = String::from("output"))]
|
||||||
output_file: String,
|
output_file: String,
|
||||||
/// The name of the nework
|
/// The name of the nework
|
||||||
@ -44,9 +42,9 @@ pub struct CliArgs {
|
|||||||
use_op: bool,
|
use_op: bool,
|
||||||
#[arg(long = "op", default_value_t = String::from("00000000000000000000000000000000"))]
|
#[arg(long = "op", default_value_t = String::from("00000000000000000000000000000000"))]
|
||||||
op: String,
|
op: String,
|
||||||
/// Set true if IMS is used
|
/// Set the ACC
|
||||||
#[arg(long = "ims", default_value_t = false)]
|
#[arg(long = "acc", default_value_t = String::from("0020"))]
|
||||||
ims: bool,
|
acc: String,
|
||||||
/// Set true to only do a dry run (print commands and not execute them)
|
/// Set true to only do a dry run (print commands and not execute them)
|
||||||
#[arg(long = "dry-run", default_value_t = false)]
|
#[arg(long = "dry-run", default_value_t = false)]
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
@ -72,12 +70,19 @@ fn main() {
|
|||||||
print!(" {}", pysim_arg);
|
print!(" {}", pysim_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !wait_for_user(&format!("Please insert the sim-card with IMSI ending in: {}", imsi_ending.green())) {
|
if !wait_for_user(&format!(
|
||||||
|
"Please insert the sim-card with IMSI ending in: {}",
|
||||||
|
imsi_ending.green()
|
||||||
|
)) {
|
||||||
exit_programm(1);
|
exit_programm(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.dry_run {
|
if args.dry_run {
|
||||||
println!("{}: The command is not executed since {} is enabled", "WARNING".yellow(), "dry_run".yellow());
|
println!(
|
||||||
|
"{}: The command is not executed since {} is enabled",
|
||||||
|
"WARNING".yellow(),
|
||||||
|
"dry_run".yellow()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
let mut command = Command::new(&args.bin);
|
let mut command = Command::new(&args.bin);
|
||||||
for pysim_arg in pysim_args {
|
for pysim_arg in pysim_args {
|
||||||
@ -96,19 +101,21 @@ fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// add command to be run on the open5gcore
|
// add command to be run on the open5gcore
|
||||||
/*
|
/*
|
||||||
* S = imsi
|
* S = imsi
|
||||||
* k = Ki
|
* k = Ki
|
||||||
* a = 8000 amf
|
* a = 8000 amf
|
||||||
* o = opc/op
|
* o = opc/op
|
||||||
* s = sqn (= 0)
|
* s = sqn (= 000000000017)
|
||||||
* t = auth_type (= 0)
|
* t = auth_type (= 0)
|
||||||
* c = op is opc
|
* c = op is opc
|
||||||
* u = usim_type (= 0)
|
* u = usim_type (= 0)
|
||||||
*/
|
* n = Domain Name (= mnc030.mcc999.3gppnetwork.org)
|
||||||
let mut user_provision_command = format!("./provision_user.sh -S {} -k {} -a {} -o {} -s {} -t {} -c {} -u {}",
|
* T = MSISDN/Phone Number (= 49{imsi_ending})
|
||||||
|
*/
|
||||||
|
let user_provision_command = format!(
|
||||||
|
"./provision_user.sh -S {} -k {} -a {} -o {} -s {} -t {} -c {} -u {} -n {} -T 49{}",
|
||||||
String::from(&conf.IMSI),
|
String::from(&conf.IMSI),
|
||||||
args.ki,
|
args.ki,
|
||||||
"8000",
|
"8000",
|
||||||
@ -119,7 +126,7 @@ fn main() {
|
|||||||
&args.opc
|
&args.opc
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"0",
|
"000000000017",
|
||||||
"0",
|
"0",
|
||||||
{
|
{
|
||||||
if args.use_op {
|
if args.use_op {
|
||||||
@ -128,13 +135,17 @@ fn main() {
|
|||||||
"1"
|
"1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"0"
|
"0",
|
||||||
|
{
|
||||||
|
if args.mnc.len() == 3 {
|
||||||
|
format!("mnc{}.mcc{}.3gppnetwork.org", args.mnc, args.mcc)
|
||||||
|
} else {
|
||||||
|
format!("mnc0{}.mcc{}.3gppnetwork.org", args.mnc, args.mcc)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
imsi_ending
|
||||||
);
|
);
|
||||||
|
|
||||||
if args.ims {
|
|
||||||
user_provision_command.push_str(&format!(" -n mnc{}.mcc{}.3gppnetwork.org -T 49{}", args.mnc, args.mcc, imsi_ending));
|
|
||||||
}
|
|
||||||
|
|
||||||
user_provision_commands.push(user_provision_command);
|
user_provision_commands.push(user_provision_command);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,10 +168,8 @@ fn wait_for_user(msg: &str) -> bool {
|
|||||||
println!("\n{}\nPress enter to continue or 'a' to abort:", msg);
|
println!("\n{}\nPress enter to continue or 'a' to abort:", msg);
|
||||||
let mut next_string = String::new();
|
let mut next_string = String::new();
|
||||||
match std::io::stdin().read_line(&mut next_string) {
|
match std::io::stdin().read_line(&mut next_string) {
|
||||||
Ok(n) if n > 0 => {
|
Ok(n) if n > 0 => !next_string.starts_with('a'),
|
||||||
!next_string.starts_with('a')
|
Ok(_) => true, // other input is ignored
|
||||||
}
|
|
||||||
Ok(_) => true, // other input is ignored
|
|
||||||
Err(err) => panic!("{}", err),
|
Err(err) => panic!("{}", err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io::{self, BufRead};
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
use std::io::{self, BufRead};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use csv::StringRecord;
|
use csv::StringRecord;
|
||||||
@ -8,7 +8,6 @@ use serde::Deserialize;
|
|||||||
|
|
||||||
use crate::CliArgs;
|
use crate::CliArgs;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug, Clone)]
|
#[derive(Deserialize, Debug, Clone)]
|
||||||
// disable compiler warnings as this is just a struct to save data as it is in csv data
|
// disable compiler warnings as this is just a struct to save data as it is in csv data
|
||||||
#[allow(dead_code, non_snake_case)]
|
#[allow(dead_code, non_snake_case)]
|
||||||
@ -39,7 +38,8 @@ pub fn get_imsi_ending(card_config: &mut CardValues) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_imsi(card_config: &mut CardValues, cli_args: &CliArgs) {
|
pub fn update_imsi(card_config: &mut CardValues, cli_args: &CliArgs) {
|
||||||
card_config.IMSI = format!("{}{}{}",
|
card_config.IMSI = format!(
|
||||||
|
"{}{}{}",
|
||||||
cli_args.mcc,
|
cli_args.mcc,
|
||||||
cli_args.mnc,
|
cli_args.mnc,
|
||||||
&card_config.IMSI[(cli_args.mnc.len() + cli_args.mcc.len())..]
|
&card_config.IMSI[(cli_args.mnc.len() + cli_args.mcc.len())..]
|
||||||
@ -47,43 +47,24 @@ pub fn update_imsi(card_config: &mut CardValues, cli_args: &CliArgs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_pysim_args(card_config: &CardValues, cli_args: &CliArgs) -> Vec<String> {
|
pub fn generate_pysim_args(card_config: &CardValues, cli_args: &CliArgs) -> Vec<String> {
|
||||||
// calculate new imsi
|
// calculate new imsi
|
||||||
let p = format!("-p{}", cli_args.device);
|
let p = format!("-p{}", cli_args.device);
|
||||||
let imsi = format!("--imsi={}", card_config.IMSI);
|
let imsi = format!("--imsi={}", card_config.IMSI);
|
||||||
let name = format!("--name=\"{}\"", cli_args.name);
|
let name = format!("--name=\"{}\"", cli_args.name);
|
||||||
let mnc = format!("--mnc={}", cli_args.mnc);
|
let mnc = format!("--mnc={}", cli_args.mnc);
|
||||||
let mcc = format!("--mcc={}", cli_args.mcc);
|
let mcc = format!("--mcc={}", cli_args.mcc);
|
||||||
let iccid = format!("--iccid={}", card_config.ICCID);
|
let iccid = format!("--iccid={}", card_config.ICCID);
|
||||||
let pin_adm = format!("--pin-adm={}", card_config.ADM1);
|
let pin_adm = format!("--pin-adm={}", card_config.ADM1);
|
||||||
let ki = format!("--ki={}", cli_args.ki);
|
let ki = format!("--ki={}", cli_args.ki);
|
||||||
|
let acc = format!("--acc={}", cli_args.acc);
|
||||||
|
|
||||||
if cli_args.use_op {
|
if cli_args.use_op {
|
||||||
let op = format!("--op={}", cli_args.op);
|
let op = format!("--op={}", cli_args.op);
|
||||||
vec![
|
vec![p, imsi, name, mnc, mcc, iccid, pin_adm, ki, acc, op]
|
||||||
p,
|
} else {
|
||||||
imsi,
|
let opc = format!("--opc={}", cli_args.opc);
|
||||||
name,
|
vec![p, imsi, name, mnc, mcc, iccid, pin_adm, ki, acc, opc]
|
||||||
mnc,
|
}
|
||||||
mcc,
|
|
||||||
iccid,
|
|
||||||
pin_adm,
|
|
||||||
ki,
|
|
||||||
op
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
let opc = format!("--opc={}", cli_args.opc);
|
|
||||||
vec![
|
|
||||||
p,
|
|
||||||
imsi,
|
|
||||||
name,
|
|
||||||
mnc,
|
|
||||||
mcc,
|
|
||||||
iccid,
|
|
||||||
pin_adm,
|
|
||||||
ki,
|
|
||||||
opc
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_csv(path: &str) -> Result<Vec<CardValues>, Box<dyn Error>> {
|
pub fn parse_csv(path: &str) -> Result<Vec<CardValues>, Box<dyn Error>> {
|
||||||
@ -94,15 +75,17 @@ pub fn parse_csv(path: &str) -> Result<Vec<CardValues>, Box<dyn Error>> {
|
|||||||
let first_line: Vec<&str> = first_line.split(',').collect();
|
let first_line: Vec<&str> = first_line.split(',').collect();
|
||||||
let header = StringRecord::from(first_line);
|
let header = StringRecord::from(first_line);
|
||||||
// now we got the header. Continue to deserialize every other line
|
// now we got the header. Continue to deserialize every other line
|
||||||
Ok(lines.map(|line| {
|
Ok(lines
|
||||||
// unpack line
|
.map(|line| {
|
||||||
let line = line.unwrap();
|
// unpack line
|
||||||
let line = line.replace(' ', "");
|
let line = line.unwrap();
|
||||||
let line: Vec<&str> = line.split(',').collect();
|
let line = line.replace(' ', "");
|
||||||
let record = StringRecord::from(line);
|
let line: Vec<&str> = line.split(',').collect();
|
||||||
let sim_conf: CardValues = record.deserialize(Some(&header)).unwrap();
|
let record = StringRecord::from(line);
|
||||||
sim_conf
|
let sim_conf: CardValues = record.deserialize(Some(&header)).unwrap();
|
||||||
}).collect())
|
sim_conf
|
||||||
|
})
|
||||||
|
.collect())
|
||||||
} else {
|
} else {
|
||||||
panic!("could not read csv");
|
panic!("could not read csv");
|
||||||
}
|
}
|
||||||
@ -111,7 +94,9 @@ pub fn parse_csv(path: &str) -> Result<Vec<CardValues>, Box<dyn Error>> {
|
|||||||
// The output is wrapped in a Result to allow matching on errors
|
// The output is wrapped in a Result to allow matching on errors
|
||||||
// Returns an Iterator to the Reader of the lines of the file.
|
// Returns an Iterator to the Reader of the lines of the file.
|
||||||
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>
|
||||||
where P: AsRef<Path>, {
|
where
|
||||||
|
P: AsRef<Path>,
|
||||||
|
{
|
||||||
let file = File::open(filename)?;
|
let file = File::open(filename)?;
|
||||||
Ok(io::BufReader::new(file).lines())
|
Ok(io::BufReader::new(file).lines())
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user