srtconfig.c revision 1.5 1 1.5 pgoyette /* $NetBSD: srtconfig.c,v 1.5 2019/03/25 23:43:56 pgoyette Exp $ */
2 1.1 mouse /* This file is in the public domain. */
3 1.1 mouse
4 1.1 mouse #include <stdio.h>
5 1.1 mouse #include <errno.h>
6 1.1 mouse #include <fcntl.h>
7 1.1 mouse #include <stdlib.h>
8 1.1 mouse #include <strings.h>
9 1.1 mouse #include <sys/ioctl.h>
10 1.1 mouse #include <arpa/inet.h>
11 1.1 mouse #include <net/if_srt.h>
12 1.1 mouse
13 1.1 mouse extern const char *__progname;
14 1.1 mouse
15 1.1 mouse #define ACT_ERROR 1 /* none of the below */
16 1.1 mouse #define ACT_QUERYALL 2 /* srtX */
17 1.1 mouse #define ACT_QUERYONE 3 /* srtX N */
18 1.1 mouse #define ACT_DEL 4 /* srtX del N */
19 1.1 mouse #define ACT_ADD 5 /* srtX add srcaddr mask dstif dstaddr */
20 1.1 mouse #define ACT_SET 6 /* srtX set N srcaddr mask dstif dstaddr */
21 1.1 mouse #define ACT_FLAGS 7 /* srtX flags */
22 1.1 mouse #define ACT_SFLAG 8 /* srtX flags [+|-]flag */
23 1.1 mouse #define ACT_DEBUG 9 /* srtX debug */
24 1.1 mouse static int action = ACT_ERROR;
25 1.1 mouse
26 1.1 mouse static char *txt_dev;
27 1.1 mouse static char *txt_n;
28 1.1 mouse static char *txt_flg;
29 1.1 mouse static char *txt_addr;
30 1.1 mouse static char *txt_mask;
31 1.1 mouse static char *txt_dstif;
32 1.1 mouse static char *txt_dstaddr;
33 1.1 mouse
34 1.1 mouse static int devfd;
35 1.1 mouse
36 1.1 mouse static struct {
37 1.1 mouse const char *name;
38 1.1 mouse unsigned int bit;
39 1.1 mouse } flagbits[] = { { "mtulock", SSF_MTULOCK },
40 1.3 lukem { 0, 0 } };
41 1.1 mouse
42 1.1 mouse static void handleargs(int ac, char **av)
43 1.1 mouse {
44 1.1 mouse txt_dev = av[1];
45 1.1 mouse if (ac == 2)
46 1.1 mouse { action = ACT_QUERYALL;
47 1.1 mouse }
48 1.1 mouse else if ((ac == 3) && !strcmp(av[2],"debug"))
49 1.1 mouse { action = ACT_DEBUG;
50 1.1 mouse }
51 1.1 mouse else if ((ac == 3) && !strcmp(av[2],"flags"))
52 1.1 mouse { action = ACT_FLAGS;
53 1.1 mouse }
54 1.1 mouse else if (ac == 3)
55 1.1 mouse { action = ACT_QUERYONE;
56 1.1 mouse txt_n = av[2];
57 1.1 mouse }
58 1.1 mouse else if ((ac == 4) && !strcmp(av[2],"del"))
59 1.1 mouse { action = ACT_DEL;
60 1.1 mouse txt_n = av[3];
61 1.1 mouse }
62 1.1 mouse else if ((ac == 4) && !strcmp(av[2],"flags"))
63 1.1 mouse { action = ACT_SFLAG;
64 1.1 mouse txt_flg = av[3];
65 1.1 mouse }
66 1.1 mouse else if ((ac == 7) && !strcmp(av[2],"add"))
67 1.1 mouse { action = ACT_ADD;
68 1.1 mouse txt_addr = av[3];
69 1.1 mouse txt_mask = av[4];
70 1.1 mouse txt_dstif = av[5];
71 1.1 mouse txt_dstaddr = av[6];
72 1.1 mouse }
73 1.1 mouse else if ((ac == 8) && !strcmp(av[2],"set"))
74 1.1 mouse { action = ACT_SET;
75 1.1 mouse txt_n = av[3];
76 1.1 mouse txt_addr = av[4];
77 1.1 mouse txt_mask = av[5];
78 1.1 mouse txt_dstif = av[6];
79 1.1 mouse txt_dstaddr = av[7];
80 1.1 mouse }
81 1.1 mouse if (action == ACT_ERROR)
82 1.1 mouse { fprintf(stderr,"Usage: %s srtX\n",__progname);
83 1.1 mouse fprintf(stderr," %s srtX N\n",__progname);
84 1.1 mouse fprintf(stderr," %s srtX del N\n",__progname);
85 1.1 mouse fprintf(stderr," %s srtX add addr mask dstif dstaddr\n",__progname);
86 1.1 mouse fprintf(stderr," %s srtX set N addr mask dstif dstaddr\n",__progname);
87 1.1 mouse fprintf(stderr," %s srtX flags {[+|-]flag}\n",__progname);
88 1.1 mouse fprintf(stderr," %s srtX debug\n",__progname);
89 1.1 mouse exit(1);
90 1.1 mouse }
91 1.1 mouse }
92 1.1 mouse
93 1.1 mouse static void open_dev(int how)
94 1.1 mouse {
95 1.1 mouse if (! index(txt_dev,'/'))
96 1.1 mouse { char *tmp;
97 1.1 mouse asprintf(&tmp,"/dev/%s",txt_dev);
98 1.1 mouse txt_dev = tmp;
99 1.1 mouse }
100 1.1 mouse devfd = open(txt_dev,how,0);
101 1.1 mouse if (devfd < 0)
102 1.5 pgoyette { fprintf(stderr,"%s: can't open %s: %s\n",__progname,txt_dev,strerror(errno));
103 1.1 mouse exit(1);
104 1.1 mouse }
105 1.1 mouse }
106 1.1 mouse
107 1.1 mouse static void query_n(int n)
108 1.1 mouse {
109 1.1 mouse struct srt_rt r;
110 1.1 mouse char obuf[64];
111 1.1 mouse
112 1.1 mouse r.inx = n;
113 1.1 mouse if (ioctl(devfd,SRT_GETRT,&r) < 0)
114 1.1 mouse { fprintf(stderr,"%s: can't get rt #%d: %s\n",__progname,n,strerror(errno));
115 1.1 mouse return;
116 1.1 mouse }
117 1.1 mouse printf("%d:",n);
118 1.1 mouse printf(" %s",inet_ntop(r.af,&r.srcmatch,&obuf[0],sizeof(obuf)));
119 1.1 mouse printf(" /%d",r.srcmask);
120 1.1 mouse printf(" %.*s",(int)sizeof(r.u.dstifn),&r.u.dstifn[0]);
121 1.1 mouse switch (r.af)
122 1.1 mouse { case AF_INET:
123 1.1 mouse printf(" %s",inet_ntoa(r.dst.sin.sin_addr));
124 1.1 mouse break;
125 1.1 mouse case AF_INET6:
126 1.1 mouse printf(" %s",inet_ntop(AF_INET6,&r.dst.sin6.sin6_addr,&obuf[0],sizeof(obuf)));
127 1.1 mouse break;
128 1.1 mouse default:
129 1.1 mouse printf(" ?af%d",r.af);
130 1.1 mouse break;
131 1.1 mouse }
132 1.1 mouse printf("\n");
133 1.1 mouse }
134 1.1 mouse
135 1.1 mouse static void do_query(int narg)
136 1.1 mouse {
137 1.1 mouse int i;
138 1.1 mouse int n;
139 1.1 mouse
140 1.1 mouse open_dev(O_RDONLY);
141 1.1 mouse if (narg >= 0)
142 1.1 mouse { query_n(narg);
143 1.1 mouse }
144 1.1 mouse else
145 1.1 mouse { if (ioctl(devfd,SRT_GETNRT,&n) < 0)
146 1.1 mouse { fprintf(stderr,"%s: can't get count: %s\n",__progname,strerror(errno));
147 1.1 mouse exit(1);
148 1.1 mouse }
149 1.1 mouse for (i=0;i<n;i++) query_n(i);
150 1.1 mouse }
151 1.1 mouse }
152 1.1 mouse
153 1.1 mouse static void do_del(unsigned int n)
154 1.1 mouse {
155 1.1 mouse open_dev(O_RDWR);
156 1.1 mouse if (ioctl(devfd,SRT_DELRT,&n) < 0)
157 1.1 mouse { fprintf(stderr,"%s: can't delete #%u: %s\n",__progname,n,strerror(errno));
158 1.1 mouse exit(1);
159 1.1 mouse }
160 1.1 mouse }
161 1.1 mouse
162 1.1 mouse static void do_set(int n)
163 1.1 mouse {
164 1.1 mouse struct srt_rt r;
165 1.1 mouse int w;
166 1.1 mouse int maxw;
167 1.1 mouse void *dp;
168 1.1 mouse
169 1.1 mouse open_dev(O_RDWR);
170 1.1 mouse if (n < 0)
171 1.1 mouse { unsigned int v;
172 1.1 mouse if (ioctl(devfd,SRT_GETNRT,&v) < 0)
173 1.1 mouse { fprintf(stderr,"%s: can't get count: %s\n",__progname,strerror(errno));
174 1.1 mouse exit(1);
175 1.1 mouse }
176 1.1 mouse n = v;
177 1.1 mouse }
178 1.1 mouse bzero(&r.dst,sizeof(r.dst));
179 1.1 mouse r.inx = n;
180 1.1 mouse if (inet_pton(AF_INET,txt_addr,&r.srcmatch.v4) == 1)
181 1.1 mouse { r.af = AF_INET;
182 1.1 mouse r.dst.sin.sin_family = AF_INET;
183 1.1 mouse r.dst.sin.sin_len = sizeof(r.dst.sin);
184 1.1 mouse dp = &r.dst.sin.sin_addr;
185 1.1 mouse maxw = 32;
186 1.1 mouse }
187 1.1 mouse else if (inet_pton(AF_INET6,txt_addr,&r.srcmatch.v6) == 1)
188 1.1 mouse { r.af = AF_INET6;
189 1.1 mouse r.dst.sin6.sin6_family = AF_INET6;
190 1.1 mouse r.dst.sin6.sin6_len = sizeof(r.dst.sin6);
191 1.1 mouse dp = &r.dst.sin6.sin6_addr;
192 1.1 mouse maxw = 128;
193 1.1 mouse }
194 1.1 mouse else
195 1.1 mouse { fprintf(stderr,"%s: %s: invalid match address\n",__progname,txt_addr);
196 1.1 mouse exit(1);
197 1.1 mouse }
198 1.1 mouse if (txt_mask[0] == '/') txt_mask ++;
199 1.1 mouse w = atoi(txt_mask);
200 1.1 mouse if ((w < 0) || (w > maxw))
201 1.1 mouse { fprintf(stderr,"%s: %s: out-of-range CIDR width\n",__progname,txt_mask);
202 1.1 mouse exit(1);
203 1.1 mouse }
204 1.1 mouse r.srcmask = w;
205 1.1 mouse if (strlen(txt_dstif) > sizeof(r.u.dstifn)-1)
206 1.1 mouse { fprintf(stderr,"%s: %s: too long\n",__progname,txt_dstif);
207 1.1 mouse exit(1);
208 1.1 mouse }
209 1.1 mouse strncpy(&r.u.dstifn[0],txt_dstif,sizeof(r.u.dstifn));
210 1.1 mouse if (inet_pton(r.af,txt_dstaddr,dp) != 1)
211 1.1 mouse { fprintf(stderr,"%s: %s: invalid destination address\n",__progname,txt_dstaddr);
212 1.1 mouse exit(1);
213 1.1 mouse }
214 1.1 mouse if (ioctl(devfd,SRT_SETRT,&r) < 0)
215 1.1 mouse { fprintf(stderr,"%s: can't set route: %s\n",__progname,strerror(errno));
216 1.1 mouse exit(1);
217 1.1 mouse }
218 1.1 mouse }
219 1.1 mouse
220 1.1 mouse static void do_flags(void)
221 1.1 mouse {
222 1.1 mouse unsigned int f;
223 1.1 mouse int i;
224 1.1 mouse
225 1.1 mouse open_dev(O_RDONLY);
226 1.1 mouse if (ioctl(devfd,SRT_GFLAGS,&f) < 0)
227 1.1 mouse { fprintf(stderr,"%s: can't get flags: %s\n",__progname,strerror(errno));
228 1.1 mouse exit(1);
229 1.1 mouse }
230 1.1 mouse for (i=0;flagbits[i].name;i++)
231 1.1 mouse { printf(" %c%s",(f&flagbits[i].bit)?'+':'-',flagbits[i].name);
232 1.1 mouse f &= ~flagbits[i].bit;
233 1.1 mouse }
234 1.1 mouse if (f) printf(" +0x%x",f);
235 1.1 mouse printf("\n");
236 1.1 mouse }
237 1.1 mouse
238 1.1 mouse static void do_sflag(void)
239 1.1 mouse {
240 1.1 mouse unsigned int f;
241 1.1 mouse unsigned int b;
242 1.1 mouse int i;
243 1.1 mouse
244 1.1 mouse switch (txt_flg[0])
245 1.1 mouse { case '+': case '-': break;
246 1.1 mouse default:
247 1.1 mouse fprintf(stderr,"%s: last argument must be +flag or -flag\n",__progname);
248 1.1 mouse exit(1);
249 1.1 mouse break;
250 1.1 mouse }
251 1.1 mouse for (i=0;flagbits[i].name;i++) if (!strcmp(flagbits[i].name,txt_flg+1)) break;
252 1.1 mouse if (! flagbits[i].name)
253 1.1 mouse { fprintf(stderr,"%s: unrecognized flag bit `%s'\n",__progname,txt_flg+1);
254 1.1 mouse exit(1);
255 1.1 mouse }
256 1.1 mouse b = flagbits[i].bit;
257 1.1 mouse open_dev(O_RDWR);
258 1.1 mouse if (ioctl(devfd,SRT_GFLAGS,&f) < 0)
259 1.1 mouse { fprintf(stderr,"%s: can't get flags: %s\n",__progname,strerror(errno));
260 1.1 mouse exit(1);
261 1.1 mouse }
262 1.1 mouse if (txt_flg[0] == '+') f |= b; else f &= ~b;
263 1.1 mouse if (ioctl(devfd,SRT_SFLAGS,&f) < 0)
264 1.1 mouse { fprintf(stderr,"%s: can't set flags: %s\n",__progname,strerror(errno));
265 1.1 mouse exit(1);
266 1.1 mouse }
267 1.1 mouse }
268 1.1 mouse
269 1.1 mouse static void do_debug(void)
270 1.1 mouse {
271 1.1 mouse void *vp;
272 1.1 mouse
273 1.1 mouse open_dev(O_RDWR);
274 1.1 mouse vp = 0;
275 1.1 mouse if (ioctl(devfd,SRT_DEBUG,&vp) < 0)
276 1.1 mouse { fprintf(stderr,"%s: can't SRT_DEBUG: %s\n",__progname,strerror(errno));
277 1.1 mouse exit(1);
278 1.1 mouse }
279 1.1 mouse }
280 1.1 mouse
281 1.1 mouse int main(int ac, char **av)
282 1.1 mouse {
283 1.1 mouse handleargs(ac,av);
284 1.1 mouse switch (action)
285 1.1 mouse { case ACT_QUERYALL:
286 1.1 mouse do_query(-1);
287 1.1 mouse break;
288 1.1 mouse case ACT_QUERYONE:
289 1.1 mouse do_query(atoi(txt_n));
290 1.1 mouse break;
291 1.1 mouse case ACT_DEL:
292 1.1 mouse do_del(atoi(txt_n));
293 1.1 mouse break;
294 1.1 mouse case ACT_ADD:
295 1.1 mouse do_set(-1);
296 1.1 mouse break;
297 1.1 mouse case ACT_SET:
298 1.1 mouse do_set(atoi(txt_n));
299 1.1 mouse break;
300 1.1 mouse case ACT_FLAGS:
301 1.1 mouse do_flags();
302 1.1 mouse break;
303 1.1 mouse case ACT_SFLAG:
304 1.1 mouse do_sflag();
305 1.1 mouse break;
306 1.1 mouse case ACT_DEBUG:
307 1.1 mouse do_debug();
308 1.1 mouse break;
309 1.1 mouse default:
310 1.1 mouse abort();
311 1.1 mouse break;
312 1.1 mouse }
313 1.1 mouse exit(0);
314 1.1 mouse }
315