blob: 9c12f757f0c5d25ca0019203ad4313e7d8402260 [file] [log] [blame]
Harald Welte51b00a62014-04-03 09:37:38 -04001/* Command line utility to create GTP link */
2
3/* (C) 2014 by sysmocom - s.f.m.c. GmbH
Pablo Neira Ayuso448bce42016-05-08 21:43:40 +02004 * (C) 2016 by Pablo Neira Ayuso <pablo@netfilter.org>
5 *
Harald Welte51b00a62014-04-03 09:37:38 -04006 * Author: Pablo Neira Ayuso <pablo@gnumonks.org>
7 *
8 * All Rights Reserved
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
Pablo Neira Ayuso14506662014-02-20 18:43:15 +010025#include <stdio.h>
26#include <stdlib.h>
27#include <unistd.h>
28#include <string.h>
29#include <time.h>
Pablo Neira Ayuso50826a52016-05-10 18:00:51 +020030#include <netinet/in.h>
31#include <arpa/inet.h>
Pablo Neira Ayuso14506662014-02-20 18:43:15 +010032
33#include <libmnl/libmnl.h>
34#include <linux/if.h>
35#include <linux/if_link.h>
36#include <linux/rtnetlink.h>
37
Pablo Neira Ayusob9f6ffe2016-05-08 18:27:55 +020038#include <linux/gtp.h>
39#include <linux/if_link.h>
Pablo Neira Ayuso14506662014-02-20 18:43:15 +010040
Pablo Neira Ayuso448bce42016-05-08 21:43:40 +020041#include <libgtpnl/gtpnl.h>
42
Pablo Neira Ayuso14506662014-02-20 18:43:15 +010043int main(int argc, char *argv[])
44{
45 struct mnl_socket *nl;
46 char buf[MNL_SOCKET_BUFFER_SIZE];
47 struct nlmsghdr *nlh;
48 struct ifinfomsg *ifm;
49 int ret;
Pablo Neira Ayuso7b30c552016-05-08 21:50:05 +020050 unsigned int seq, portid;
Pablo Neira Ayuso14506662014-02-20 18:43:15 +010051 struct nlattr *nest, *nest2;
52
Pablo Neira Ayuso448bce42016-05-08 21:43:40 +020053 if (argc != 3) {
54 printf("Usage: %s <add|del> <device>\n", argv[0]);
Pablo Neira Ayuso14506662014-02-20 18:43:15 +010055 exit(EXIT_FAILURE);
56 }
57
Pablo Neira Ayuso448bce42016-05-08 21:43:40 +020058 if (!strcmp(argv[1], "del")) {
59 printf("destroying gtp interface...\n");
60 if (gtp_dev_destroy(argv[2]) < 0)
61 perror("gtp_dev_destroy");
62
63 return 0;
64 }
65
Pablo Neira Ayuso14506662014-02-20 18:43:15 +010066 nlh = mnl_nlmsg_put_header(buf);
67 nlh->nlmsg_type = RTM_NEWLINK;
Pablo Neira Ayuso7aa20872014-02-24 11:38:52 +010068 nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL |NLM_F_ACK;
Pablo Neira Ayuso14506662014-02-20 18:43:15 +010069 nlh->nlmsg_seq = seq = time(NULL);
70 ifm = mnl_nlmsg_put_extra_header(nlh, sizeof(*ifm));
71 ifm->ifi_family = AF_INET;
72 ifm->ifi_change |= IFF_UP;
73 ifm->ifi_flags |= IFF_UP;
74
Pablo Neira Ayuso7aa20872014-02-24 11:38:52 +010075 int fd1 = socket(AF_INET, SOCK_DGRAM, 0);
76 int fd2 = socket(AF_INET, SOCK_DGRAM, 0);
Pablo Neira Ayuso50826a52016-05-10 18:00:51 +020077 struct sockaddr_in sockaddr_fd1 = {
78 .sin_family = AF_INET,
79 .sin_port = htons(3386),
80 .sin_addr = {
81 .s_addr = INADDR_ANY,
82 },
83 };
84 struct sockaddr_in sockaddr_fd2 = {
85 .sin_family = AF_INET,
86 .sin_port = htons(2152),
87 .sin_addr = {
88 .s_addr = INADDR_ANY,
89 },
90 };
91
92 if (bind(fd1, (struct sockaddr *) &sockaddr_fd1,
93 sizeof(sockaddr_fd1)) < 0) {
94 perror("bind");
95 exit(EXIT_FAILURE);
96 }
97 if (bind(fd2, (struct sockaddr *) &sockaddr_fd2,
98 sizeof(sockaddr_fd2)) < 0) {
99 perror("bind");
100 exit(EXIT_FAILURE);
101 }
Pablo Neira Ayuso7aa20872014-02-24 11:38:52 +0100102
Pablo Neira Ayuso448bce42016-05-08 21:43:40 +0200103 mnl_attr_put_str(nlh, IFLA_IFNAME, argv[2]);
Pablo Neira Ayuso14506662014-02-20 18:43:15 +0100104 nest = mnl_attr_nest_start(nlh, IFLA_LINKINFO);
105 mnl_attr_put_str(nlh, IFLA_INFO_KIND, "gtp");
106 nest2 = mnl_attr_nest_start(nlh, IFLA_INFO_DATA);
Pablo Neira Ayuso7aa20872014-02-24 11:38:52 +0100107 mnl_attr_put_u32(nlh, IFLA_GTP_FD0, fd1);
108 mnl_attr_put_u32(nlh, IFLA_GTP_FD1, fd2);
Pablo Neira Ayusob9f6ffe2016-05-08 18:27:55 +0200109 mnl_attr_put_u32(nlh, IFLA_GTP_PDP_HASHSIZE, 131072);
Pablo Neira Ayuso14506662014-02-20 18:43:15 +0100110 mnl_attr_nest_end(nlh, nest2);
111 mnl_attr_nest_end(nlh, nest);
112
113 nl = mnl_socket_open(NETLINK_ROUTE);
114 if (nl == NULL) {
115 perror("mnl_socket_open");
116 exit(EXIT_FAILURE);
117 }
118
119 if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
120 perror("mnl_socket_bind");
121 exit(EXIT_FAILURE);
122 }
123 portid = mnl_socket_get_portid(nl);
124
125 mnl_nlmsg_fprintf(stdout, nlh, nlh->nlmsg_len,
126 sizeof(struct ifinfomsg));
127
128 if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
129 perror("mnl_socket_send");
130 exit(EXIT_FAILURE);
131 }
132
133 ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
134 if (ret == -1) {
135 perror("read");
136 exit(EXIT_FAILURE);
137 }
138
139 ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
140 if (ret == -1){
141 perror("callback");
142 exit(EXIT_FAILURE);
143 }
144
145 mnl_socket_close(nl);
146
Pablo Neira Ayuso448bce42016-05-08 21:43:40 +0200147 fprintf(stderr, "WARNING: attaching dummy socket descriptors. Keep "
148 "this process running for testing purposes.\n");
Pablo Neira Ayuso50826a52016-05-10 18:00:51 +0200149
150 while (1) {
151 struct sockaddr_in addr;
152 socklen_t len = sizeof(addr);
153
154 ret = recvfrom(fd1, buf, sizeof(buf), 0,
155 (struct sockaddr *)&addr, &len);
156 printf("received %d bytes via UDP socket\n", ret);
157 }
Pablo Neira Ayuso448bce42016-05-08 21:43:40 +0200158
Pablo Neira Ayuso14506662014-02-20 18:43:15 +0100159 return 0;
160}