1 /*
2 * This file is part of RTRlib.
3 *
4 * This file is subject to the terms and conditions of the MIT license.
5 * See the file LICENSE in the top level directory for more details.
6 *
7 * Website: http://rtrlib.realmv6.org/
8 */
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include "rtrlib/rtrlib.h"
15
16 const int connection_timeout = 20;
17 enum rtr_mgr_status connection_status = -1;
18
connection_status_callback(const struct rtr_mgr_group * group,enum rtr_mgr_status status,const struct rtr_socket * socket,void * data)19 static void connection_status_callback(const struct rtr_mgr_group *group,
20 enum rtr_mgr_status status,
21 const struct rtr_socket *socket,
22 void *data)
23 {
24 if (status == RTR_MGR_ERROR)
25 connection_status = status;
26 }
27
connection_error(enum rtr_mgr_status status)28 int connection_error(enum rtr_mgr_status status)
29 {
30 if (status == RTR_MGR_ERROR) {
31 /*
32 * Wait for input before printing error to avoid "broken pipe" error
33 * while communicating with the Python program.
34 */
35 char input[256];
36
37 if (fgets(input, 256, stdin))
38 ;
39 printf("error\n");
40 fflush(stdout);
41 return 1;
42 }
43 return 0;
44 }
45
main(int argc,char * argv[])46 int main(int argc, char *argv[])
47 {
48 /* check arguments, need hostname/IP and port of cache-server */
49 if (argc < 3) {
50 printf("Usage: %s [host] [port]\n", argv[0]);
51 return EXIT_FAILURE;
52 }
53
54 struct tr_socket tr_tcp;
55 struct tr_tcp_config tcp_config = { argv[1], argv[2], NULL };
56 struct rtr_socket rtr_tcp;
57 struct rtr_mgr_config *conf;
58 struct rtr_mgr_group groups[1];
59
60 /* init a TCP transport and create rtr socket */
61 tr_tcp_init(&tcp_config, &tr_tcp);
62 rtr_tcp.tr_socket = &tr_tcp;
63
64 /* create a rtr_mgr_group array with 1 element */
65 groups[0].sockets = malloc(1 * sizeof(struct rtr_socket *));
66 groups[0].sockets_len = 1;
67 groups[0].sockets[0] = &rtr_tcp;
68 groups[0].preference = 1;
69
70 if (rtr_mgr_init(&conf, groups, 1, 30, 600, 600, NULL, NULL,
71 &connection_status_callback, NULL) < 0)
72 return EXIT_FAILURE;
73
74 rtr_mgr_start(conf);
75
76 char input[256];
77 int sleep_counter = 0;
78
79 /* wait till at least one rtr_mgr_group is synchronized with server */
80 while (!rtr_mgr_conf_in_sync(conf)) {
81 if (connection_error(connection_status))
82 return EXIT_FAILURE;
83
84 sleep(1);
85 sleep_counter++;
86 if (sleep_counter >= connection_timeout) {
87 /*
88 * Wait for input before printing "timeout",
89 * to avoid "broken pipee error while communicating
90 * with the Python program
91 */
92 if (fgets(input, 256, stdin))
93 ;
94 printf("timeout\n");
95 fflush(stdout);
96 return EXIT_FAILURE;
97 }
98 }
99
100 char ip[128];
101 int mask;
102 int asn;
103 int counter;
104 /* loop for input */
105 while (1) {
106 int input_len;
107 int spaces;
108
109 /* recheck connection, exit on failure */
110 if (connection_error(connection_status))
111 return EXIT_FAILURE;
112
113 /* try reading from stdin, exit on failure */
114 if (!fgets(input, 256, stdin)) {
115 printf("input error\n");
116 return EXIT_FAILURE;
117 }
118
119 /* remove newline, if present */
120 input_len = strlen(input) - 1;
121 if (input[input_len] == '\n')
122 input[input_len] = '\0';
123
124 /* check if there are exactly 3 arguments */
125 spaces = 0;
126 for (counter = 0; counter < input_len; counter++) {
127 if (input[counter] == ' ' &&
128 input[counter + 1] != ' ' &&
129 input[counter + 1] != '\0' && counter != 0)
130 spaces++;
131 }
132
133 /* check input matching pattern */
134 if (spaces != 2) {
135 printf("Arguments required: IP Mask ASN\n");
136 fflush(stdout);
137 continue;
138 }
139
140 char delims[] = " ";
141 char *input_tok = NULL;
142
143 input_tok = strtok(input, delims);
144 strcpy(ip, input_tok);
145 input_tok = strtok(NULL, delims);
146 mask = atoi(input_tok);
147 input_tok = strtok(NULL, delims); asn = atoi(input_tok);
148
149 struct lrtr_ip_addr pref;
150 enum pfxv_state result;
151 struct pfx_record *reason = NULL;
152 unsigned int reason_len = 0;
153
154 lrtr_ip_str_to_addr(ip, &pref);
155 /* do validation */
156 pfx_table_validate_r(groups[0].sockets[0]->pfx_table, &reason,
157 &reason_len, asn, &pref, mask, &result);
158
159 int validity_code = -1;
160 /* translate validation result */
161 if (result == BGP_PFXV_STATE_VALID)
162 validity_code = 0;
163 else if (result == BGP_PFXV_STATE_NOT_FOUND)
164 validity_code = 1;
165 else if (result == BGP_PFXV_STATE_INVALID)
166 validity_code = 2;
167
168 /* IP Mask BGP-ASN| */
169 printf("%s %d %d|", ip, mask, asn);
170
171 /* ROA-ASN IP MaskMin MaskMax, ... */
172 if (reason && (reason_len > 0)) {
173 unsigned int i;
174
175 for (i = 0; i < reason_len; i++) {
176 char tmp[100];
177
178 lrtr_ip_addr_to_str(&reason[i].prefix,
179 tmp, sizeof(tmp));
180 printf("%u %s %u %u",
181 reason[i].asn, tmp,
182 reason[i].min_len,
183 reason[i].max_len);
184 if ((i + 1) < reason_len)
185 printf(",");
186 }
187 }
188
189 /* |validity_code */
190 printf("|%d", validity_code);
191
192 printf("\n");
193 fflush(stdout);
194 }
195
196 rtr_mgr_stop(conf);
197 rtr_mgr_free(conf);
198 free(groups[0].sockets);
199
200 return EXIT_SUCCESS;
201 }
202