This commit was generated by cvs2svn to compensate for changes in r2587,
[iproute2.git] / ip / ipxfrm.c
1 /* $USAGI: $ */
2
3 /*
4  * Copyright (C)2004 USAGI/WIDE Project
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 /*
21  * based on ip.c, iproute.c
22  */
23 /*
24  * Authors:
25  *      Masahide NAKAMURA @USAGI
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <time.h>
34 #include <netdb.h>
35 #include <net/if.h>
36 #include <linux/netlink.h>
37 #include <linux/rtnetlink.h>
38 #include <linux/xfrm.h>
39
40 #include "utils.h"
41 #include "xfrm.h"
42
43 #define STRBUF_SIZE     (128)
44 #define STRBUF_CAT(buf, str) \
45         do { \
46                 int rest = sizeof(buf) - 1 - strlen(buf); \
47                 if (rest > 0) { \
48                         int len = strlen(str); \
49                         if (len > rest) \
50                                 len = rest; \
51                         strncat(buf, str, len); \
52                         buf[sizeof(buf) - 1] = '\0'; \
53                 } \
54         } while(0);
55
56 struct xfrm_filter filter;
57
58 static void usage(void) __attribute__((noreturn));
59
60 static void usage(void)
61 {
62         fprintf(stderr, 
63                 "Usage: ip xfrm XFRM_OBJECT { COMMAND | help }\n"
64                 "where  XFRM_OBJECT := { state | policy | monitor }\n");
65         exit(-1);
66 }
67
68 /* This is based on utils.c(inet_addr_match) */
69 int xfrm_addr_match(xfrm_address_t *x1, xfrm_address_t *x2, int bits)
70 {
71         __u32 *a1 = (__u32 *)x1;
72         __u32 *a2 = (__u32 *)x2;
73         int words = bits >> 0x05;
74
75         bits &= 0x1f;
76
77         if (words)
78                 if (memcmp(a1, a2, words << 2))
79                         return -1;
80
81         if (bits) {
82                 __u32 w1, w2;
83                 __u32 mask;
84
85                 w1 = a1[words];
86                 w2 = a2[words];
87
88                 mask = htonl((0xffffffff) << (0x20 - bits));
89
90                 if ((w1 ^ w2) & mask)
91                         return 1;
92         }
93
94         return 0;
95 }
96
97 struct typeent {
98         const char *t_name;
99         int t_type;
100 };
101
102 static const struct typeent xfrmproto_types[]= {
103         { "esp", IPPROTO_ESP }, { "ah", IPPROTO_AH }, { "comp", IPPROTO_COMP },
104         { NULL, -1 }
105 };
106
107 int xfrm_xfrmproto_getbyname(char *name)
108 {
109         int i;
110
111         for (i = 0; ; i++) {
112                 const struct typeent *t = &xfrmproto_types[i];
113                 if (!t->t_name || t->t_type == -1)
114                         break;
115
116                 if (strcmp(t->t_name, name) == 0)
117                         return t->t_type;
118         }
119
120         return -1;
121 }
122
123 const char *strxf_xfrmproto(__u8 proto)
124 {
125         int i;
126
127         for (i = 0; ; i++) {
128                 const struct typeent *t = &xfrmproto_types[i];
129                 if (!t->t_name || t->t_type == -1)
130                         break;
131
132                 if (t->t_type == proto)
133                         return t->t_name;
134         }
135
136         return NULL;
137 }
138
139 static const struct typeent algo_types[]= {
140         { "enc", XFRMA_ALG_CRYPT }, { "auth", XFRMA_ALG_AUTH },
141         { "comp", XFRMA_ALG_COMP }, { NULL, -1 }
142 };
143
144 int xfrm_algotype_getbyname(char *name)
145 {
146         int i;
147
148         for (i = 0; ; i++) {
149                 const struct typeent *t = &algo_types[i];
150                 if (!t->t_name || t->t_type == -1)
151                         break;
152
153                 if (strcmp(t->t_name, name) == 0)
154                         return t->t_type;
155         }
156
157         return -1;
158 }
159
160 const char *strxf_algotype(int type)
161 {
162         int i;
163
164         for (i = 0; ; i++) {
165                 const struct typeent *t = &algo_types[i];
166                 if (!t->t_name || t->t_type == -1)
167                         break;
168
169                 if (t->t_type == type)
170                         return t->t_name;
171         }
172
173         return NULL;
174 }
175
176 const char *strxf_mask8(__u8 mask)
177 {
178         static char str[16];
179         const int sn = sizeof(mask) * 8 - 1;
180         __u8 b;
181         int i = 0;
182
183         for (b = (1 << sn); b > 0; b >>= 1)
184                 str[i++] = ((b & mask) ? '1' : '0');
185         str[i] = '\0';
186
187         return str;
188 }
189
190 const char *strxf_mask32(__u32 mask)
191 {
192         static char str[16];
193
194         sprintf(str, "%.8x", mask);
195
196         return str;
197 }
198
199 const char *strxf_share(__u8 share)
200 {
201         static char str[32];
202
203         switch (share) {
204         case XFRM_SHARE_ANY:
205                 strcpy(str, "any");
206                 break;
207         case XFRM_SHARE_SESSION:
208                 strcpy(str, "session");
209                 break;
210         case XFRM_SHARE_USER:
211                 strcpy(str, "user");
212                 break;
213         case XFRM_SHARE_UNIQUE:
214                 strcpy(str, "unique");
215                 break;
216         default:
217                 sprintf(str, "%u", share);
218                 break;
219         }
220
221         return str;
222 }
223
224 const char *strxf_proto(__u8 proto)
225 {
226         static char buf[32];
227         struct protoent *pp;
228         const char *p;
229
230         pp = getprotobynumber(proto);
231         if (pp)
232                 p = pp->p_name;
233         else {
234                 sprintf(buf, "%u", proto);
235                 p = buf;
236         }
237
238         return p;
239 }
240
241 void xfrm_id_info_print(xfrm_address_t *saddr, struct xfrm_id *id,
242                         __u8 mode, __u32 reqid, __u16 family, int force_spi,
243                         FILE *fp, const char *prefix, const char *title)
244 {
245         char abuf[256];
246
247         if (title)
248                 fprintf(fp, title);
249
250         memset(abuf, '\0', sizeof(abuf));
251         fprintf(fp, "src %s ", rt_addr_n2a(family, sizeof(*saddr),
252                                            saddr, abuf, sizeof(abuf)));
253         memset(abuf, '\0', sizeof(abuf));
254         fprintf(fp, "dst %s", rt_addr_n2a(family, sizeof(id->daddr),
255                                           &id->daddr, abuf, sizeof(abuf)));
256         fprintf(fp, "%s", _SL_);
257
258         if (prefix)
259                 fprintf(fp, prefix);
260         fprintf(fp, "\t");
261
262         fprintf(fp, "proto %s ", strxf_xfrmproto(id->proto));
263
264         if (show_stats > 0 || force_spi || id->spi) {
265                 __u32 spi = ntohl(id->spi);
266                 fprintf(fp, "spi 0x%08x", spi);
267                 if (show_stats > 0)
268                         fprintf(fp, "(%u)", spi);
269                 fprintf(fp, " ");
270         }
271
272         fprintf(fp, "reqid %u", reqid);
273         if (show_stats > 0)
274                 fprintf(fp, "(0x%08x)", reqid);
275         fprintf(fp, " ");
276
277         fprintf(fp, "mode ");
278         switch (mode) {
279         case 0:
280                 fprintf(fp, "transport");
281                 break;
282         case 1:
283                 fprintf(fp, "tunnel");
284                 break;
285         default:
286                 fprintf(fp, "%u", mode);
287                 break;
288         }
289         fprintf(fp, "%s", _SL_);
290 }
291
292 static const char *strxf_limit(__u64 limit)
293 {
294         static char str[32];
295         if (limit == XFRM_INF)
296                 strcpy(str, "(INF)");
297         else
298                 sprintf(str, "%llu", (unsigned long long) limit);
299
300         return str;
301 }
302
303 void xfrm_stats_print(struct xfrm_stats *s, FILE *fp, const char *prefix)
304 {
305         if (prefix)
306                 fprintf(fp, prefix);
307         fprintf(fp, "stats:");
308         fprintf(fp, "%s", _SL_);
309
310         if (prefix)
311                 fprintf(fp, prefix);
312         fprintf(fp, "  ");
313         fprintf(fp, "replay-window %u ", s->replay_window);
314         fprintf(fp, "replay %u ", s->replay);
315         fprintf(fp, "failed %u", s->integrity_failed);
316         fprintf(fp, "%s", _SL_);
317 }
318
319 static const char *strxf_time(__u64 time)
320 {
321         static char str[32];
322
323         if (time == 0)
324                 strcpy(str, "-");
325         else {
326                 time_t t;
327                 struct tm *tp;
328
329                 /* XXX: treat time in the same manner of kernel's 
330                  * net/xfrm/xfrm_{user,state}.c
331                  */
332                 t = (long)time;
333                 tp = localtime(&t);
334
335                 strftime(str, sizeof(str), "%Y-%m-%d %T", tp);
336         }
337
338         return str;
339 }
340
341 void xfrm_lifetime_print(struct xfrm_lifetime_cfg *cfg,
342                          struct xfrm_lifetime_cur *cur,
343                          FILE *fp, const char *prefix)
344 {
345         if (cfg) {
346                 if (prefix)
347                         fprintf(fp, prefix);
348                 fprintf(fp, "lifetime config:");
349                 fprintf(fp, "%s", _SL_);
350
351                 if (prefix)
352                         fprintf(fp, prefix);
353                 fprintf(fp, "  ");
354                 fprintf(fp, "limit: ");
355                 fprintf(fp, "soft ");
356                 fprintf(fp, strxf_limit(cfg->soft_byte_limit));
357                 fprintf(fp, "(bytes), hard ");
358                 fprintf(fp, strxf_limit(cfg->hard_byte_limit));
359                 fprintf(fp, "(bytes)");
360                 fprintf(fp, "%s", _SL_);
361
362                 if (prefix)
363                         fprintf(fp, prefix);
364                 fprintf(fp, "  ");
365                 fprintf(fp, "limit: ");
366                 fprintf(fp, "soft ");
367                 fprintf(fp, strxf_limit(cfg->soft_packet_limit));
368                 fprintf(fp, "(packets), hard ");
369                 fprintf(fp, strxf_limit(cfg->hard_packet_limit));
370                 fprintf(fp, "(packets)");
371                 fprintf(fp, "%s", _SL_);
372
373                 if (prefix)
374                         fprintf(fp, prefix);
375                 fprintf(fp, "  ");
376                 fprintf(fp, "expire add: ");
377                 fprintf(fp, "soft ");
378                 fprintf(fp, "%llu", (unsigned long long) cfg->soft_add_expires_seconds);
379                 fprintf(fp, "(sec), hard ");
380                 fprintf(fp, "%llu", (unsigned long long) cfg->hard_add_expires_seconds);
381                 fprintf(fp, "(sec)");
382                 fprintf(fp, "%s", _SL_);
383
384                 if (prefix)
385                         fprintf(fp, prefix);
386                 fprintf(fp, "  ");
387                 fprintf(fp, "expire use: ");
388                 fprintf(fp, "soft ");
389                 fprintf(fp, "%llu", (unsigned long long) cfg->soft_use_expires_seconds);
390                 fprintf(fp, "(sec), hard ");
391                 fprintf(fp, "%llu", (unsigned long long) cfg->hard_use_expires_seconds);
392                 fprintf(fp, "(sec)");
393                 fprintf(fp, "%s", _SL_);
394         }
395         if (cur) {
396                 if (prefix)
397                         fprintf(fp, prefix);
398                 fprintf(fp, "lifetime current:");
399                 fprintf(fp, "%s", _SL_);
400
401                 if (prefix)
402                         fprintf(fp, prefix);
403                 fprintf(fp, "  ");
404                 fprintf(fp, "%llu(bytes), ", (unsigned long long) cur->bytes);
405                 fprintf(fp, "%llu(packets)", (unsigned long long) cur->packets);
406                 fprintf(fp, "%s", _SL_);
407
408                 if (prefix)
409                         fprintf(fp, prefix);
410                 fprintf(fp, "  ");
411                 fprintf(fp, "add %s ", strxf_time(cur->add_time));
412                 fprintf(fp, "use %s", strxf_time(cur->use_time));
413                 fprintf(fp, "%s", _SL_);
414         }
415 }
416
417 void xfrm_selector_print(struct xfrm_selector *sel, __u16 family,
418                          FILE *fp, const char *prefix)
419 {
420         char abuf[256];
421         __u16 f;
422
423         f = sel->family;
424         if (f == AF_UNSPEC)
425                 f = family;
426         if (f == AF_UNSPEC)
427                 f = preferred_family;
428
429         if (prefix)
430                 fprintf(fp, prefix);
431
432         memset(abuf, '\0', sizeof(abuf));
433         fprintf(fp, "src %s/%u ", rt_addr_n2a(f, sizeof(sel->saddr),
434                                               &sel->saddr, abuf, sizeof(abuf)),
435                 sel->prefixlen_s);
436
437         memset(abuf, '\0', sizeof(abuf));
438         fprintf(fp, "dst %s/%u ", rt_addr_n2a(f, sizeof(sel->daddr),
439                                               &sel->daddr, abuf, sizeof(abuf)),
440                 sel->prefixlen_d);
441
442         if (sel->proto)
443                 fprintf(fp, "proto %s ", strxf_proto(sel->proto));
444         switch (sel->proto) {
445         case IPPROTO_TCP:
446         case IPPROTO_UDP:
447         case IPPROTO_SCTP:
448         case IPPROTO_DCCP:
449         default: /* XXX */
450                 if (sel->sport_mask)
451                         fprintf(fp, "sport %u ", ntohs(sel->sport));
452                 if (sel->dport_mask)
453                         fprintf(fp, "dport %u ", ntohs(sel->dport));
454                 break;
455         case IPPROTO_ICMP:
456         case IPPROTO_ICMPV6:
457                 /* type/code is stored at sport/dport in selector */
458                 if (sel->sport_mask)
459                         fprintf(fp, "type %u ", ntohs(sel->sport));
460                 if (sel->dport_mask)
461                         fprintf(fp, "code %u ", ntohs(sel->dport));
462                 break;
463         }
464
465         if (sel->ifindex > 0) {
466                 char buf[IFNAMSIZ];
467
468                 memset(buf, '\0', sizeof(buf));
469                 if_indextoname(sel->ifindex, buf);
470                 fprintf(fp, "dev %s ", buf);
471         }
472
473         if (show_stats > 0)
474                 fprintf(fp, "uid %u", sel->user);
475
476         fprintf(fp, "%s", _SL_);
477 }
478
479 static void xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
480                             FILE *fp, const char *prefix)
481 {
482         int keylen;
483         int i;
484
485         if (prefix)
486                 fprintf(fp, prefix);
487
488         fprintf(fp, "%s ", strxf_algotype(type));
489
490         if (len < sizeof(*algo)) {
491                 fprintf(fp, "(ERROR truncated)");
492                 goto fin;
493         }
494         len -= sizeof(*algo);
495
496         fprintf(fp, "%s ", algo->alg_name);
497
498         keylen = algo->alg_key_len / 8;
499         if (len < keylen) {
500                 fprintf(fp, "(ERROR truncated)");
501                 goto fin;
502         }
503
504         fprintf(fp, "0x");
505         for (i = 0; i < keylen; i ++)
506                 fprintf(fp, "%.2x", (unsigned char)algo->alg_key[i]);
507
508         if (show_stats > 0)
509                 fprintf(fp, " (%d bits)", algo->alg_key_len);
510
511  fin:
512         fprintf(fp, "%s", _SL_);
513 }
514
515 static void xfrm_tmpl_print(struct xfrm_user_tmpl *tmpls, int len,
516                             __u16 family, FILE *fp, const char *prefix)
517 {
518         int ntmpls = len / sizeof(struct xfrm_user_tmpl);
519         int i;
520
521         if (ntmpls <= 0) {
522                 if (prefix)
523                         fprintf(fp, prefix);
524                 fprintf(fp, "(ERROR \"tmpl\" truncated)");
525                 fprintf(fp, "%s", _SL_);
526                 return;
527         }
528
529         for (i = 0; i < ntmpls; i++) {
530                 struct xfrm_user_tmpl *tmpl = &tmpls[i];
531
532                 if (prefix)
533                         fprintf(fp, prefix);
534
535                 xfrm_id_info_print(&tmpl->saddr, &tmpl->id, tmpl->mode,
536                                    tmpl->reqid, family, 0, fp, prefix, "tmpl ");
537
538                 if (show_stats > 0 || tmpl->optional) {
539                         if (prefix)
540                                 fprintf(fp, prefix);
541                         fprintf(fp, "\t");
542                         switch (tmpl->optional) {
543                         case 0:
544                                 if (show_stats > 0)
545                                         fprintf(fp, "level required ");
546                                 break;
547                         case 1:
548                                 fprintf(fp, "level use ");
549                                 break;
550                         default:
551                                 fprintf(fp, "level %u ", tmpl->optional);
552                                 break;
553                         }
554
555                         if (show_stats > 0)
556                                 fprintf(fp, "share %s ", strxf_share(tmpl->share));
557
558                         fprintf(fp, "%s", _SL_);
559                 }
560
561                 if (show_stats > 0) {
562                         if (prefix)
563                                 fprintf(fp, prefix);
564                         fprintf(fp, "\t");
565                         fprintf(fp, "%s-mask %s ",
566                                 strxf_algotype(XFRMA_ALG_CRYPT),
567                                 strxf_mask32(tmpl->ealgos));
568                         fprintf(fp, "%s-mask %s ",
569                                 strxf_algotype(XFRMA_ALG_AUTH),
570                                 strxf_mask32(tmpl->aalgos));
571                         fprintf(fp, "%s-mask %s",
572                                 strxf_algotype(XFRMA_ALG_COMP),
573                                 strxf_mask32(tmpl->calgos));
574
575                         fprintf(fp, "%s", _SL_);
576                 }
577         }
578 }
579
580 void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
581                       FILE *fp, const char *prefix)
582 {
583         if (tb[XFRMA_ALG_AUTH]) {
584                 struct rtattr *rta = tb[XFRMA_ALG_AUTH];
585                 xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta),
586                                 XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix);
587         }
588
589         if (tb[XFRMA_ALG_CRYPT]) {
590                 struct rtattr *rta = tb[XFRMA_ALG_CRYPT];
591                 xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta),
592                                 XFRMA_ALG_CRYPT, RTA_PAYLOAD(rta), fp, prefix);
593         }
594
595         if (tb[XFRMA_ALG_COMP]) {
596                 struct rtattr *rta = tb[XFRMA_ALG_COMP];
597                 xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta),
598                                 XFRMA_ALG_COMP, RTA_PAYLOAD(rta), fp, prefix);
599         }
600
601         if (tb[XFRMA_ENCAP]) {
602                 struct xfrm_encap_tmpl *e;
603                 char abuf[256];
604
605                 if (prefix)
606                         fprintf(fp, prefix);
607                 fprintf(fp, "encap ");
608
609                 if (RTA_PAYLOAD(tb[XFRMA_ENCAP]) < sizeof(*e)) {
610                         fprintf(fp, "(ERROR truncated)");
611                         fprintf(fp, "%s", _SL_);
612                         return;
613                 }
614                 e = (struct xfrm_encap_tmpl *) RTA_DATA(tb[XFRMA_ENCAP]);
615
616                 fprintf(fp, "type ");
617                 switch (e->encap_type) {
618                 case 1:
619                         fprintf(fp, "espinudp-nonike ");
620                         break;
621                 case 2:
622                         fprintf(fp, "espinudp ");
623                         break;
624                 default:
625                         fprintf(fp, "%u ", e->encap_type);
626                         break;
627                 }
628                 fprintf(fp, "sport %u ", ntohs(e->encap_sport));
629                 fprintf(fp, "dport %u ", ntohs(e->encap_dport));
630
631                 memset(abuf, '\0', sizeof(abuf));
632                 fprintf(fp, "addr %s",
633                         rt_addr_n2a(family, sizeof(e->encap_oa),
634                                     &e->encap_oa, abuf, sizeof(abuf)));
635                 fprintf(fp, "%s", _SL_);
636         }
637
638         if (tb[XFRMA_TMPL]) {
639                 struct rtattr *rta = tb[XFRMA_TMPL];
640                 xfrm_tmpl_print((struct xfrm_user_tmpl *) RTA_DATA(rta),
641                                 RTA_PAYLOAD(rta), family, fp, prefix);
642         }
643 }
644
645 static int xfrm_selector_iszero(struct xfrm_selector *s)
646 {
647         struct xfrm_selector s0;
648
649         memset(&s0, 0, sizeof(s0));
650
651         return (memcmp(&s0, s, sizeof(s0)) == 0);
652 }
653
654 void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
655                             struct rtattr *tb[], FILE *fp, const char *prefix,
656                             const char *title)
657 {
658         char buf[STRBUF_SIZE];
659
660         memset(buf, '\0', sizeof(buf));
661
662         xfrm_id_info_print(&xsinfo->saddr, &xsinfo->id, xsinfo->mode,
663                            xsinfo->reqid, xsinfo->family, 1, fp, prefix,
664                            title);
665
666         if (prefix)
667                 STRBUF_CAT(buf, prefix);
668         STRBUF_CAT(buf, "\t");
669
670         fprintf(fp, buf);
671         fprintf(fp, "replay-window %u ", xsinfo->replay_window);
672         if (show_stats > 0)
673                 fprintf(fp, "seq 0x%08u ", xsinfo->seq);
674         if (show_stats > 0 || xsinfo->flags) {
675                 __u8 flags = xsinfo->flags;
676
677                 fprintf(fp, "flag ");
678                 XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_NOECN, "noecn");
679                 XFRM_FLAG_PRINT(fp, flags, XFRM_STATE_DECAP_DSCP, "decap-dscp");
680                 if (flags)
681                         fprintf(fp, "%x", flags);
682                 if (show_stats > 0)
683                         fprintf(fp, " (0x%s)", strxf_mask8(flags));
684         }
685         fprintf(fp, "%s", _SL_);
686
687         xfrm_xfrma_print(tb, xsinfo->family, fp, buf);
688
689         if (!xfrm_selector_iszero(&xsinfo->sel)) {
690                 char sbuf[STRBUF_SIZE];
691
692                 memcpy(sbuf, buf, sizeof(sbuf));
693                 STRBUF_CAT(sbuf, "sel ");
694
695                 xfrm_selector_print(&xsinfo->sel, xsinfo->family, fp, sbuf);
696         }
697
698         if (show_stats > 0) {
699                 xfrm_lifetime_print(&xsinfo->lft, &xsinfo->curlft, fp, buf);
700                 xfrm_stats_print(&xsinfo->stats, fp, buf);
701         }
702 }
703
704 void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo,
705                             struct rtattr *tb[], FILE *fp, const char *prefix,
706                             const char *title)
707 {
708         char buf[STRBUF_SIZE];
709
710         memset(buf, '\0', sizeof(buf));
711
712         xfrm_selector_print(&xpinfo->sel, preferred_family, fp, title);
713
714         if (prefix)
715                 STRBUF_CAT(buf, prefix);
716         STRBUF_CAT(buf, "\t");
717
718         fprintf(fp, buf);
719         fprintf(fp, "dir ");
720         switch (xpinfo->dir) {
721         case XFRM_POLICY_IN:
722                 fprintf(fp, "in");
723                 break;
724         case XFRM_POLICY_OUT:
725                 fprintf(fp, "out");
726                 break;
727         case XFRM_POLICY_FWD:
728                 fprintf(fp, "fwd");
729                 break;
730         default:
731                 fprintf(fp, "%u", xpinfo->dir);
732                 break;
733         }
734         fprintf(fp, " ");
735
736         switch (xpinfo->action) {
737         case XFRM_POLICY_ALLOW:
738                 if (show_stats > 0)
739                         fprintf(fp, "action allow ");
740                 break;
741         case XFRM_POLICY_BLOCK:
742                 fprintf(fp, "action block ");
743                 break;
744         default:
745                 fprintf(fp, "action %u ", xpinfo->action);
746                 break;
747         }
748
749         if (show_stats)
750                 fprintf(fp, "index %u ", xpinfo->index);
751         fprintf(fp, "priority %u ", xpinfo->priority);
752         if (show_stats > 0) {
753                 fprintf(fp, "share %s ", strxf_share(xpinfo->share));
754                 fprintf(fp, "flag 0x%s", strxf_mask8(xpinfo->flags));
755         }
756         fprintf(fp, "%s", _SL_);
757
758         if (show_stats > 0)
759                 xfrm_lifetime_print(&xpinfo->lft, &xpinfo->curlft, fp, buf);
760
761         xfrm_xfrma_print(tb, xpinfo->sel.family, fp, buf);
762 }
763
764 int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family,
765                   int loose, int *argcp, char ***argvp)
766 {
767         int argc = *argcp;
768         char **argv = *argvp;
769         inet_prefix dst;
770         inet_prefix src;
771
772         memset(&dst, 0, sizeof(dst));
773         memset(&src, 0, sizeof(src));
774
775         while (1) {
776                 if (strcmp(*argv, "src") == 0) {
777                         NEXT_ARG();
778
779                         get_prefix(&src, *argv, preferred_family);
780                         if (src.family == AF_UNSPEC)
781                                 invarg("\"src\" address family is AF_UNSPEC", *argv);
782                         if (family)
783                                 *family = src.family;
784
785                         memcpy(saddr, &src.data, sizeof(*saddr));
786
787                         filter.id_src_mask = src.bitlen;
788
789                 } else if (strcmp(*argv, "dst") == 0) {
790                         NEXT_ARG();
791
792                         get_prefix(&dst, *argv, preferred_family);
793                         if (dst.family == AF_UNSPEC)
794                                 invarg("\"dst\" address family is AF_UNSPEC", *argv);
795                         if (family)
796                                 *family = dst.family;
797
798                         memcpy(&id->daddr, &dst.data, sizeof(id->daddr));
799
800                         filter.id_dst_mask = dst.bitlen;
801
802                 } else if (strcmp(*argv, "proto") == 0) {
803                         int ret;
804
805                         NEXT_ARG();
806
807                         ret = xfrm_xfrmproto_getbyname(*argv);
808                         if (ret < 0)
809                                 invarg("\"XFRM_PROTO\" is invalid", *argv);
810
811                         id->proto = (__u8)ret;
812
813                         filter.id_proto_mask = XFRM_FILTER_MASK_FULL;
814
815                 } else if (strcmp(*argv, "spi") == 0) {
816                         __u32 spi;
817
818                         NEXT_ARG();
819                         if (get_u32(&spi, *argv, 0))
820                                 invarg("\"SPI\" is invalid", *argv);
821
822                         spi = htonl(spi);
823                         id->spi = spi;
824
825                         filter.id_spi_mask = XFRM_FILTER_MASK_FULL;
826
827                 } else {
828                         PREV_ARG(); /* back track */
829                         break;
830                 }
831
832                 if (!NEXT_ARG_OK())
833                         break;
834                 NEXT_ARG();
835         }
836
837         if (src.family && dst.family && (src.family != dst.family))
838                 invarg("the same address family is required between \"src\" and \"dst\"", *argv);
839
840         if (loose == 0 && id->proto == 0)
841                 missarg("XFRM_PROTO");
842         if (argc == *argcp)
843                 missarg("ID");
844
845         *argcp = argc;
846         *argvp = argv;
847
848         return 0;
849 }
850
851 int xfrm_mode_parse(__u8 *mode, int *argcp, char ***argvp)
852 {
853         int argc = *argcp;
854         char **argv = *argvp;
855
856         if (matches(*argv, "transport") == 0)
857                 *mode = 0;
858         else if (matches(*argv, "tunnel") == 0)
859                 *mode = 1;
860         else
861                 invarg("\"MODE\" is invalid", *argv);
862
863         *argcp = argc;
864         *argvp = argv;
865
866         return 0;
867 }
868
869 int xfrm_encap_type_parse(__u16 *type, int *argcp, char ***argvp)
870 {
871         int argc = *argcp;
872         char **argv = *argvp;
873
874         if (strcmp(*argv, "espinudp-nonike") == 0)
875                 *type = 1;
876         else if (strcmp(*argv, "espinudp") == 0)
877                 *type = 2;
878         else
879                 invarg("\"ENCAP-TYPE\" is invalid", *argv);
880
881         *argcp = argc;
882         *argvp = argv;
883
884         return 0;
885 }
886
887 /* NOTE: reqid is used by host-byte order */
888 int xfrm_reqid_parse(__u32 *reqid, int *argcp, char ***argvp)
889 {
890         int argc = *argcp;
891         char **argv = *argvp;
892
893         if (get_u32(reqid, *argv, 0))
894                 invarg("\"REQID\" is invalid", *argv);
895
896         *argcp = argc;
897         *argvp = argv;
898
899         return 0;
900 }
901
902 static int xfrm_selector_upspec_parse(struct xfrm_selector *sel,
903                                       int *argcp, char ***argvp)
904 {
905         int argc = *argcp;
906         char **argv = *argvp;
907         char *sportp = NULL;
908         char *dportp = NULL;
909         char *typep = NULL;
910         char *codep = NULL;
911
912         while (1) {
913                 if (strcmp(*argv, "proto") == 0) {
914                         __u8 upspec;
915
916                         NEXT_ARG();
917
918                         if (strcmp(*argv, "any") == 0)
919                                 upspec = 0;
920                         else {
921                                 struct protoent *pp;
922                                 pp = getprotobyname(*argv);
923                                 if (pp)
924                                         upspec = pp->p_proto;
925                                 else {
926                                         if (get_u8(&upspec, *argv, 0))
927                                                 invarg("\"PROTO\" is invalid", *argv);
928                                 }
929                         }
930                         sel->proto = upspec;
931
932                         filter.upspec_proto_mask = XFRM_FILTER_MASK_FULL;
933
934                 } else if (strcmp(*argv, "sport") == 0) {
935                         sportp = *argv;
936
937                         NEXT_ARG();
938
939                         if (get_u16(&sel->sport, *argv, 0))
940                                 invarg("\"PORT\" is invalid", *argv);
941                         sel->sport = htons(sel->sport);
942                         if (sel->sport)
943                                 sel->sport_mask = ~((__u16)0);
944
945                         filter.upspec_sport_mask = XFRM_FILTER_MASK_FULL;
946
947                 } else if (strcmp(*argv, "dport") == 0) {
948                         dportp = *argv;
949
950                         NEXT_ARG();
951
952                         if (get_u16(&sel->dport, *argv, 0))
953                                 invarg("\"PORT\" is invalid", *argv);
954                         sel->dport = htons(sel->dport);
955                         if (sel->dport)
956                                 sel->dport_mask = ~((__u16)0);
957
958                         filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL;
959
960                 } else if (strcmp(*argv, "type") == 0) {
961                         typep = *argv;
962
963                         NEXT_ARG();
964
965                         if (get_u16(&sel->sport, *argv, 0) ||
966                             (sel->sport & ~((__u16)0xff)))
967                                 invarg("\"type\" value is invalid", *argv);
968                         sel->sport = htons(sel->sport);
969                         sel->sport_mask = ~((__u16)0);
970
971                         filter.upspec_sport_mask = XFRM_FILTER_MASK_FULL;
972
973
974                 } else if (strcmp(*argv, "code") == 0) {
975                         codep = *argv;
976
977                         NEXT_ARG();
978
979                         if (get_u16(&sel->dport, *argv, 0) ||
980                             (sel->dport & ~((__u16)0xff)))
981                                 invarg("\"code\" value is invalid", *argv);
982                         sel->dport = htons(sel->dport);
983                         sel->dport_mask = ~((__u16)0);
984
985                         filter.upspec_dport_mask = XFRM_FILTER_MASK_FULL;
986
987                 } else {
988                         PREV_ARG(); /* back track */
989                         break;
990                 }
991
992                 if (!NEXT_ARG_OK())
993                         break;
994                 NEXT_ARG();
995         }
996         if (argc == *argcp)
997                 missarg("UPSPEC");
998         if (sportp || dportp) {
999                 switch (sel->proto) {
1000                 case IPPROTO_TCP:
1001                 case IPPROTO_UDP:
1002                 case IPPROTO_SCTP:
1003                 case IPPROTO_DCCP:
1004                         break;
1005                 default:
1006                         fprintf(stderr, "\"sport\" and \"dport\" are invalid with proto=%s\n", strxf_proto(sel->proto));
1007                         exit(1);
1008                 }
1009         }
1010         if (typep || codep) {
1011                 switch (sel->proto) {
1012                 case IPPROTO_ICMP:
1013                 case IPPROTO_ICMPV6:
1014                         break;
1015                 default:
1016                         fprintf(stderr, "\"type\" and \"code\" are invalid with proto=%s\n", strxf_proto(sel->proto));
1017                         exit(1);
1018                 }
1019         }
1020
1021         *argcp = argc;
1022         *argvp = argv;
1023
1024         return 0;
1025 }
1026
1027 int xfrm_selector_parse(struct xfrm_selector *sel, int *argcp, char ***argvp)
1028 {
1029         int argc = *argcp;
1030         char **argv = *argvp;
1031         inet_prefix dst;
1032         inet_prefix src;
1033         char *upspecp = NULL;
1034
1035         memset(&dst, 0, sizeof(dst));
1036         memset(&src, 0, sizeof(src));
1037
1038         while (1) {
1039                 if (strcmp(*argv, "src") == 0) {
1040                         NEXT_ARG();
1041
1042                         get_prefix(&src, *argv, preferred_family);
1043                         if (src.family == AF_UNSPEC)
1044                                 invarg("\"src\" address family is AF_UNSPEC", *argv);
1045                         sel->family = src.family;
1046
1047                         memcpy(&sel->saddr, &src.data, sizeof(sel->saddr));
1048                         sel->prefixlen_s = src.bitlen;
1049
1050                         filter.sel_src_mask = src.bitlen;
1051
1052                 } else if (strcmp(*argv, "dst") == 0) {
1053                         NEXT_ARG();
1054
1055                         get_prefix(&dst, *argv, preferred_family);
1056                         if (dst.family == AF_UNSPEC)
1057                                 invarg("\"dst\" address family is AF_UNSPEC", *argv);
1058                         sel->family = dst.family;
1059
1060                         memcpy(&sel->daddr, &dst.data, sizeof(sel->daddr));
1061                         sel->prefixlen_d = dst.bitlen;
1062
1063                         filter.sel_dst_mask = dst.bitlen;
1064
1065                 } else if (strcmp(*argv, "dev") == 0) {
1066                         int ifindex;
1067
1068                         NEXT_ARG();
1069
1070                         if (strcmp(*argv, "none") == 0)
1071                                 ifindex = 0;
1072                         else {
1073                                 ifindex = if_nametoindex(*argv);
1074                                 if (ifindex <= 0)
1075                                         invarg("\"DEV\" is invalid", *argv);
1076                         }
1077                         sel->ifindex = ifindex;
1078
1079                         filter.sel_dev_mask = XFRM_FILTER_MASK_FULL;
1080
1081                 } else {
1082                         if (upspecp) {
1083                                 PREV_ARG(); /* back track */
1084                                 break;
1085                         } else {
1086                                 upspecp = *argv;
1087                                 xfrm_selector_upspec_parse(sel, &argc, &argv);
1088                         }
1089                 }
1090
1091                 if (!NEXT_ARG_OK())
1092                         break;
1093
1094                 NEXT_ARG();
1095         }
1096
1097         if (src.family && dst.family && (src.family != dst.family))
1098                 invarg("the same address family is required between \"src\" and \"dst\"", *argv);
1099
1100         if (argc == *argcp)
1101                 missarg("SELECTOR");
1102
1103         *argcp = argc;
1104         *argvp = argv;
1105
1106         return 0;
1107 }
1108
1109 int xfrm_lifetime_cfg_parse(struct xfrm_lifetime_cfg *lft,
1110                             int *argcp, char ***argvp)
1111 {
1112         int argc = *argcp;
1113         char **argv = *argvp;
1114         int ret;
1115
1116         if (strcmp(*argv, "time-soft") == 0) {
1117                 NEXT_ARG();
1118                 ret = get_u64(&lft->soft_add_expires_seconds, *argv, 0);
1119                 if (ret)
1120                         invarg("\"time-soft\" value is invalid", *argv);
1121         } else if (strcmp(*argv, "time-hard") == 0) {
1122                 NEXT_ARG();
1123                 ret = get_u64(&lft->hard_add_expires_seconds, *argv, 0);
1124                 if (ret)
1125                         invarg("\"time-hard\" value is invalid", *argv);
1126         } else if (strcmp(*argv, "time-use-soft") == 0) {
1127                 NEXT_ARG();
1128                 ret = get_u64(&lft->soft_use_expires_seconds, *argv, 0);
1129                 if (ret)
1130                         invarg("\"time-use-soft\" value is invalid", *argv);
1131         } else if (strcmp(*argv, "time-use-hard") == 0) {
1132                 NEXT_ARG();
1133                 ret = get_u64(&lft->hard_use_expires_seconds, *argv, 0);
1134                 if (ret)
1135                         invarg("\"time-use-hard\" value is invalid", *argv);
1136         } else if (strcmp(*argv, "byte-soft") == 0) {
1137                 NEXT_ARG();
1138                 ret = get_u64(&lft->soft_byte_limit, *argv, 0);
1139                 if (ret)
1140                         invarg("\"byte-soft\" value is invalid", *argv);
1141         } else if (strcmp(*argv, "byte-hard") == 0) {
1142                 NEXT_ARG();
1143                 ret = get_u64(&lft->hard_byte_limit, *argv, 0);
1144                 if (ret)
1145                         invarg("\"byte-hard\" value is invalid", *argv);
1146         } else if (strcmp(*argv, "packet-soft") == 0) {
1147                 NEXT_ARG();
1148                 ret = get_u64(&lft->soft_packet_limit, *argv, 0);
1149                 if (ret)
1150                         invarg("\"packet-soft\" value is invalid", *argv);
1151         } else if (strcmp(*argv, "packet-hard") == 0) {
1152                 NEXT_ARG();
1153                 ret = get_u64(&lft->hard_packet_limit, *argv, 0);
1154                 if (ret)
1155                         invarg("\"packet-hard\" value is invalid", *argv);
1156         } else
1157                 invarg("\"LIMIT\" is invalid", *argv);
1158
1159         *argcp = argc;
1160         *argvp = argv;
1161
1162         return 0;
1163 }
1164
1165 int do_xfrm(int argc, char **argv)
1166 {
1167         memset(&filter, 0, sizeof(filter));
1168
1169         if (argc < 1)
1170                 usage();
1171
1172         if (matches(*argv, "state") == 0 ||
1173             matches(*argv, "sa") == 0)
1174                 return do_xfrm_state(argc-1, argv+1);
1175         else if (matches(*argv, "policy") == 0)
1176                 return do_xfrm_policy(argc-1, argv+1);
1177         else if (matches(*argv, "monitor") == 0)
1178                 return do_xfrm_monitor(argc-1, argv+1);
1179         else if (matches(*argv, "help") == 0) {
1180                 usage();
1181                 fprintf(stderr, "xfrm Object \"%s\" is unknown.\n", *argv);
1182                 exit(-1);
1183         }
1184         usage();
1185 }