]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - ip/iptunnel.c
Merge branch 'iproute2-master' into iproute2-next
[mirror_iproute2.git] / ip / iptunnel.c
index 66390555c292ffede7d3b0e0cb8aa4e4c001ad39..d597908fa209e63bb7928ab87fac2640fdd6e199 100644 (file)
@@ -213,10 +213,8 @@ static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p)
 
        if (medium) {
                p->link = ll_name_to_index(medium);
-               if (p->link == 0) {
-                       fprintf(stderr, "Cannot find device \"%s\"\n", medium);
-                       return -1;
-               }
+               if (!p->link)
+                       return nodev(medium);
        }
 
        if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) {
@@ -286,8 +284,9 @@ static int do_del(int argc, char **argv)
        return tnl_del_ioctl(tnl_defname(&p) ? : p.name, p.name, &p);
 }
 
-static void print_tunnel(struct ip_tunnel_parm *p)
+static void print_tunnel(const void *t)
 {
+       const struct ip_tunnel_parm *p = t;
        struct ip_tunnel_6rd ip6rd = {};
        char s1[1024];
        char s2[1024];
@@ -373,90 +372,52 @@ static void print_tunnel(struct ip_tunnel_parm *p)
                printf("%s  Checksum output packets.", _SL_);
 }
 
-static int do_tunnels_list(struct ip_tunnel_parm *p)
-{
-       char buf[512];
-       int err = -1;
-       FILE *fp = fopen("/proc/net/dev", "r");
 
-       if (fp == NULL) {
-               perror("fopen");
-               return -1;
-       }
+static void ip_tunnel_parm_initialize(const struct tnl_print_nlmsg_info *info)
+{
+       struct ip_tunnel_parm *p2 = info->p2;
 
-       /* skip header lines */
-       if (!fgets(buf, sizeof(buf), fp) ||
-           !fgets(buf, sizeof(buf), fp)) {
-               fprintf(stderr, "/proc/net/dev read error\n");
-               goto end;
-       }
+       memset(p2, 0, sizeof(*p2));
+}
 
-       while (fgets(buf, sizeof(buf), fp) != NULL) {
-               char name[IFNAMSIZ];
-               int index, type;
-               struct ip_tunnel_parm p1 = {};
-               char *ptr;
-
-               buf[sizeof(buf) - 1] = 0;
-               ptr = strchr(buf, ':');
-               if (ptr == NULL ||
-                   (*ptr++ = 0, sscanf(buf, "%s", name) != 1)) {
-                       fprintf(stderr, "Wrong format for /proc/net/dev. Giving up.\n");
-                       goto end;
-               }
-               if (p->name[0] && strcmp(p->name, name))
-                       continue;
-               index = ll_name_to_index(name);
-               if (index == 0)
-                       continue;
-               type = ll_index_to_type(index);
-               if (type == -1) {
-                       fprintf(stderr, "Failed to get type of \"%s\"\n", name);
-                       continue;
-               }
-               if (type != ARPHRD_TUNNEL && type != ARPHRD_IPGRE && type != ARPHRD_SIT)
-                       continue;
-               if (tnl_get_ioctl(name, &p1))
-                       continue;
-               if ((p->link && p1.link != p->link) ||
-                   (p->name[0] && strcmp(p1.name, p->name)) ||
-                   (p->iph.daddr && p1.iph.daddr != p->iph.daddr) ||
-                   (p->iph.saddr && p1.iph.saddr != p->iph.saddr) ||
-                   (p->i_key && p1.i_key != p->i_key))
-                       continue;
-               print_tunnel(&p1);
-               if (show_stats) {
-                       struct rtnl_link_stats64 s;
-
-                       if (!tnl_get_stats(ptr, &s))
-                               tnl_print_stats(&s);
-               }
-               printf("\n");
-       }
-       err = 0;
- end:
-       fclose(fp);
-       return err;
+static bool ip_tunnel_parm_match(const struct tnl_print_nlmsg_info *info)
+{
+       const struct ip_tunnel_parm *p1 = info->p1;
+       const struct ip_tunnel_parm *p2 = info->p2;
+
+       return ((!p1->link || p1->link == p2->link) &&
+               (!p1->name[0] || strcmp(p1->name, p2->name) == 0) &&
+               (!p1->iph.daddr || p1->iph.daddr == p2->iph.daddr) &&
+               (!p1->iph.saddr || p1->iph.saddr == p2->iph.saddr) &&
+               (!p1->i_key || p1->i_key == p2->i_key));
 }
 
 static int do_show(int argc, char **argv)
 {
-       struct ip_tunnel_parm p;
+       struct ip_tunnel_parm p, p1;
        const char *basedev;
 
-       ll_init_map(&rth);
        if (parse_args(argc, argv, SIOCGETTUNNEL, &p) < 0)
                return -1;
 
        basedev = tnl_defname(&p);
-       if (!basedev)
-               return do_tunnels_list(&p);
+       if (!basedev) {
+               struct tnl_print_nlmsg_info info = {
+                       .p1    = &p,
+                       .p2    = &p1,
+                       .init  = ip_tunnel_parm_initialize,
+                       .match = ip_tunnel_parm_match,
+                       .print = print_tunnel,
+               };
+
+               return do_tunnels_list(&info);
+       }
 
        if (tnl_get_ioctl(p.name[0] ? p.name : basedev, &p))
                return -1;
 
        print_tunnel(&p);
-       printf("\n");
+       fputc('\n', stdout);
        return 0;
 }