2 #define _GNU_SOURCE 1 /* strdup() prototype, broken arpa/inet.h */
14 #include <sys/types.h>
15 #include <arpa/inet.h>
18 #include <libgtpnl/gtp.h>
19 #include <libgtpnl/gtpnl.h>
20 #include <libmnl/libmnl.h>
26 #include "../lib/tun.h"
27 #include "../lib/syserr.h"
28 #include "../gtp/pdp.h"
29 #include "../gtp/gtp.h"
31 #include <libgtpnl/gtp.h>
32 #include <libgtpnl/gtpnl.h>
33 #include <libmnl/libmnl.h>
35 #include "gtp-kernel.h"
37 static void pdp_debug(struct pdp_t
*pdp
)
45 printf("version %u\n", pdp
->version
);
46 if (pdp
->version
== 0) {
47 teid
= pdp_gettid(pdp
->imsi
, pdp
->nsapi
);
48 printf("flowid %u\n", pdp
->flru
);
50 teid
= pdp
->teid_gn
; /* GTPIE_TEI_DI */
53 printf("teid %llx\n", teid
);
54 printf("address (%u)\n", pdp
->eua
.l
);
56 /* Byte 0: 0xf1 == IETF */
57 /* Byte 1: 0x21 == IPv4 */
58 /* Byte 2-6: IPv4 address */
60 for (i
= 0; i
< 6; i
++)
61 printf("%x ", pdp
->eua
.v
[i
] & 0xff); /* GTPIE_EUA */
64 printf("sgsn-addr (%u)\n", pdp
->gsnrc
.l
);
66 for (i
= 0; i
< 4; i
++)
67 printf("%x ", pdp
->gsnrc
.v
[i
] & 0xff); /* GTPIE_GSN_ADDR */
74 struct mnl_socket
*nl
;
78 /* Always forces the kernel to allocate gtp0. If it exists it hits EEXIST */
79 #define GTP_DEVNAME "gtp0"
81 int gtp_kernel_init(struct gsn_t
*gsn
, struct in_addr
*net
,
82 size_t prefixlen
, const char *net_arg
)
84 if (gtp_dev_create(-1, GTP_DEVNAME
, gsn
->fd0
, gsn
->fd1u
) < 0) {
85 SYS_ERR(DGGSN
, LOGL_ERROR
, 0,
86 "cannot create GTP tunnel device: %s\n",
90 gtp_nl
.enabled
= true;
92 gtp_nl
.nl
= genl_socket_open();
93 if (gtp_nl
.nl
== NULL
) {
94 SYS_ERR(DGGSN
, LOGL_ERROR
, 0,
95 "cannot create genetlink socket\n");
98 gtp_nl
.genl_id
= genl_lookup_family(gtp_nl
.nl
, "gtp");
99 if (gtp_nl
.genl_id
< 0) {
100 SYS_ERR(DGGSN
, LOGL_ERROR
, 0,
101 "cannot lookup GTP genetlink ID\n");
105 SYS_ERR(DGGSN
, LOGL_NOTICE
, 0,
106 "Using the GTP kernel mode (genl ID is %d)\n",
110 DEBUGP(DGGSN
, "Setting route to reach %s via %s\n",
111 net_arg
, GTP_DEVNAME
);
113 if (gtp_dev_config(GTP_DEVNAME
, net
, prefixlen
) < 0) {
114 SYS_ERR(DGGSN
, LOGL_ERROR
, 0,
115 "Cannot add route to reach network %s\n",
119 /* launch script if it is set to bring up the route to reach
120 * the MS, eg. ip ro add 10.0.0.0/8 dev gtp0. Better add this
121 * using native rtnetlink interface given that we know the
122 * MS network mask, later.
128 /* eg. /home/ggsn/ipup gtp0 10.0.0.0/8 */
129 snprintf(cmd
, sizeof(cmd
), "%s %s %s",
130 ipup
, GTP_DEVNAME
, net_arg
);
131 cmd
[sizeof(cmd
)-1] = '\0';
135 SYS_ERR(DGGSN
, LOGL_ERROR
, 0,
136 "Failed to launch script `%s'", ipup
);
140 SYS_ERR(DGGSN
, LOGL_NOTICE
, 0, "GTP kernel configured\n");
145 void gtp_kernel_stop(void)
150 gtp_dev_destroy(GTP_DEVNAME
);
153 int gtp_kernel_tunnel_add(struct pdp_t
*pdp
)
155 struct in_addr ms
, sgsn
;
156 struct gtp_tunnel
*t
;
164 t
= gtp_tunnel_alloc();
168 memcpy(&ms
, &pdp
->eua
.v
[2], sizeof(struct in_addr
));
169 memcpy(&sgsn
, &pdp
->gsnrc
.v
[0], sizeof(struct in_addr
));
171 gtp_tunnel_set_ifidx(t
, if_nametoindex(GTP_DEVNAME
));
172 gtp_tunnel_set_version(t
, pdp
->version
);
173 gtp_tunnel_set_ms_ip4(t
, &ms
);
174 gtp_tunnel_set_sgsn_ip4(t
, &sgsn
);
175 if (pdp
->version
== 0) {
176 gtp_tunnel_set_tid(t
, pdp_gettid(pdp
->imsi
, pdp
->nsapi
));
177 gtp_tunnel_set_flowid(t
, pdp
->flru
);
179 gtp_tunnel_set_i_tei(t
, pdp
->teid_own
);
180 /* use the TEI advertised by SGSN when sending packets
181 * towards the SGSN */
182 gtp_tunnel_set_o_tei(t
, pdp
->teid_gn
);
185 ret
= gtp_add_tunnel(gtp_nl
.genl_id
, gtp_nl
.nl
, t
);
191 int gtp_kernel_tunnel_del(struct pdp_t
*pdp
)
193 struct gtp_tunnel
*t
;
201 t
= gtp_tunnel_alloc();
205 gtp_tunnel_set_ifidx(t
, if_nametoindex(GTP_DEVNAME
));
206 gtp_tunnel_set_version(t
, pdp
->version
);
207 if (pdp
->version
== 0) {
208 gtp_tunnel_set_tid(t
, pdp_gettid(pdp
->imsi
, pdp
->nsapi
));
209 gtp_tunnel_set_flowid(t
, pdp
->flru
);
211 gtp_tunnel_set_i_tei(t
, pdp
->teid_own
);
214 ret
= gtp_del_tunnel(gtp_nl
.genl_id
, gtp_nl
.nl
, t
);
220 int gtp_kernel_enabled(void)
222 return gtp_nl
.enabled
;