|
| 1 | +/* SPDX-License-Identifier: AGPL-3.0-or-later */ |
| 2 | +/* |
| 3 | + * Soft: The main goal of gtp-guard is to provide robust and secure |
| 4 | + * extensions to GTP protocol (GPRS Tunneling Procol). GTP is |
| 5 | + * widely used for data-plane in mobile core-network. gtp-guard |
| 6 | + * implements a set of 3 main frameworks: |
| 7 | + * A Proxy feature for data-plane tweaking, a Routing facility |
| 8 | + * to inter-connect and a Firewall feature for filtering, |
| 9 | + * rewriting and redirecting. |
| 10 | + * |
| 11 | + * Authors: Alexandre Cassen, <acassen@gmail.com> |
| 12 | + * |
| 13 | + * This program is free software; you can redistribute it and/or |
| 14 | + * modify it under the terms of the GNU Affero General Public |
| 15 | + * License Version 3.0 as published by the Free Software Foundation; |
| 16 | + * either version 3.0 of the License, or (at your option) any later |
| 17 | + * version. |
| 18 | + * |
| 19 | + * Copyright (C) 2023-2024 Alexandre Cassen, <acassen@gmail.com> |
| 20 | + */ |
| 21 | + |
| 22 | +#include <stdio.h> |
| 23 | +#include <math.h> |
| 24 | +#include <stdlib.h> |
| 25 | +#include <stdint.h> |
| 26 | +#include <unistd.h> |
| 27 | +#include <string.h> |
| 28 | +#include <ctype.h> |
| 29 | +#define _XOPEN_SOURCE |
| 30 | +#include <time.h> |
| 31 | +#include <sys/types.h> |
| 32 | +#include <sys/stat.h> |
| 33 | +#include <arpa/inet.h> |
| 34 | +#include <getopt.h> |
| 35 | +#include <fcntl.h> |
| 36 | +#include <errno.h> |
| 37 | + |
| 38 | +#include "gtp_guard.h" |
| 39 | + |
| 40 | +/* Local data */ |
| 41 | +data_t *daemon_data; |
| 42 | +thread_master_t *master = NULL; |
| 43 | +const char *apn_str; |
| 44 | +const char *plmn_str; |
| 45 | +const char *nameserver; |
| 46 | +const char *service_selection; |
| 47 | + |
| 48 | +/* |
| 49 | + * Usage function |
| 50 | + */ |
| 51 | +static void |
| 52 | +usage(const char *prog) |
| 53 | +{ |
| 54 | + fprintf(stderr, "Usage: %s [OPTION...]\n", prog); |
| 55 | + fprintf(stderr, " -a, --apn Access-Point-Name\n"); |
| 56 | + fprintf(stderr, " -p, --plmn PLMN\n"); |
| 57 | + fprintf(stderr, " -s, --name-server Nameserver IP Address\n"); |
| 58 | + fprintf(stderr, " -S, --service-selection Service selection string\n"); |
| 59 | + fprintf(stderr, " -h, --help Display this help message\n"); |
| 60 | +} |
| 61 | + |
| 62 | + |
| 63 | +/* |
| 64 | + * Command line parser |
| 65 | + */ |
| 66 | +static int |
| 67 | +parse_cmdline(int argc, char **argv) |
| 68 | +{ |
| 69 | + int c, longindex, curind; |
| 70 | + int bad_option = 0; |
| 71 | + |
| 72 | + struct option long_options[] = { |
| 73 | + {"apn", required_argument, NULL, 'a'}, |
| 74 | + {"plmn", required_argument, NULL, 'p'}, |
| 75 | + {"name-server", required_argument, NULL, 's'}, |
| 76 | + {"service-selection", required_argument, NULL, 'S'}, |
| 77 | + {"help", no_argument, NULL, 'h'}, |
| 78 | + {NULL, 0, NULL, 0 } |
| 79 | + }; |
| 80 | + |
| 81 | + if (argc < 5) |
| 82 | + return -1; |
| 83 | + |
| 84 | + curind = optind; |
| 85 | + while (longindex = -1, (c = getopt_long(argc, argv, ":ha:p:s:S:" |
| 86 | + , long_options, &longindex)) != -1) { |
| 87 | + if (longindex >= 0 && long_options[longindex].has_arg == required_argument && |
| 88 | + optarg && !optarg[0]) { |
| 89 | + c = ':'; |
| 90 | + optarg = NULL; |
| 91 | + } |
| 92 | + |
| 93 | + switch (c) { |
| 94 | + case 'h': |
| 95 | + usage(argv[0]); |
| 96 | + exit(0); |
| 97 | + break; |
| 98 | + case 'a': |
| 99 | + apn_str = optarg; |
| 100 | + break; |
| 101 | + case 'p': |
| 102 | + plmn_str = optarg; |
| 103 | + break; |
| 104 | + case 's': |
| 105 | + nameserver = optarg; |
| 106 | + break; |
| 107 | + case 'S': |
| 108 | + service_selection = optarg; |
| 109 | + break; |
| 110 | + case '?': |
| 111 | + if (optopt && argv[curind][1] != '-') |
| 112 | + fprintf(stderr, "Unknown option -%c\n", optopt); |
| 113 | + else |
| 114 | + fprintf(stderr, "Unknown option --%s\n", argv[curind]); |
| 115 | + bad_option = 1; |
| 116 | + break; |
| 117 | + case ':': |
| 118 | + if (optopt && argv[curind][1] != '-') |
| 119 | + fprintf(stderr, "Missing parameter for option -%c\n", optopt); |
| 120 | + else |
| 121 | + fprintf(stderr, "Missing parameter for option --%s\n", long_options[longindex].name); |
| 122 | + bad_option = 1; |
| 123 | + break; |
| 124 | + default: |
| 125 | + exit(1); |
| 126 | + break; |
| 127 | + } |
| 128 | + curind = optind; |
| 129 | + } |
| 130 | + |
| 131 | + if (optind < argc) { |
| 132 | + printf("Unexpected argument(s): "); |
| 133 | + while (optind < argc) |
| 134 | + printf("%s ", argv[optind++]); |
| 135 | + printf("\n"); |
| 136 | + return -1; |
| 137 | + } |
| 138 | + |
| 139 | + if (bad_option) |
| 140 | + return -1; |
| 141 | + |
| 142 | + return 0; |
| 143 | +} |
| 144 | + |
| 145 | + |
| 146 | + |
| 147 | +int main(int argc, char **argv) |
| 148 | +{ |
| 149 | + struct sockaddr_in pgw, sgw; |
| 150 | + gtp_apn_t *apn; |
| 151 | + gtp_service_t *svc; |
| 152 | + int err; |
| 153 | + |
| 154 | + /* Command line parsing */ |
| 155 | + err = parse_cmdline(argc, argv); |
| 156 | + if (err) { |
| 157 | + usage(argv[0]); |
| 158 | + exit(-1); |
| 159 | + } |
| 160 | + |
| 161 | + PMALLOC(apn); |
| 162 | + INIT_LIST_HEAD(&apn->service_selection); |
| 163 | + strlcpy(apn->name, "*", GTP_APN_MAX_LEN); |
| 164 | + inet_stosockaddr(nameserver, 53, &apn->nameserver); |
| 165 | + PMALLOC(svc); |
| 166 | + INIT_LIST_HEAD(&svc->next); |
| 167 | + svc->prio = 10; |
| 168 | + strlcpy(svc->str, service_selection, GTP_APN_MAX_LEN); |
| 169 | + list_add_tail(&svc->next, &apn->service_selection); |
| 170 | + |
| 171 | + memset(&pgw, 0, sizeof(struct sockaddr_in)); |
| 172 | + memset(&sgw, 0, sizeof(struct sockaddr_in)); |
| 173 | + err = gtp_sched_dynamic(apn, apn_str, plmn_str, &pgw, &sgw); |
| 174 | + if (err) { |
| 175 | + fprintf(stderr, " Unable to schedule pGW for apn:'%s.apn.epc.%s.3gppnetwork.org.'" |
| 176 | + , apn_str, plmn_str); |
| 177 | + exit(-1); |
| 178 | + } |
| 179 | + |
| 180 | + printf("Scheduled pGW : %u.%u.%u.%u\n", NIPQUAD(pgw.sin_addr.s_addr)); |
| 181 | + |
| 182 | + exit(0); |
| 183 | +} |
0 commit comments