1 /* 2 * iplink_vxcan.c vxcan device support (Virtual CAN Tunnel) 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Author: Oliver Hartkopp <socketcan (at) hartkopp.net> 10 * Based on: link_veth.c from Pavel Emelianov <xemul (at) openvz.org> 11 */ 12 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <string.h> 16 #include <net/if.h> 17 #include <linux/can/vxcan.h> 18 19 #include "utils.h" 20 #include "ip_common.h" 21 22 static void print_usage(FILE *f) 23 { 24 printf("Usage: ip link <options> type vxcan [peer <options>]\n" 25 "To get <options> type 'ip link add help'\n"); 26 } 27 28 static void usage(void) 29 { 30 print_usage(stderr); 31 } 32 33 static int vxcan_parse_opt(struct link_util *lu, int argc, char **argv, 34 struct nlmsghdr *hdr) 35 { 36 char *dev = NULL; 37 char *name = NULL; 38 char *link = NULL; 39 char *type = NULL; 40 int index = 0; 41 int err, len; 42 struct rtattr *data; 43 int group; 44 struct ifinfomsg *ifm, *peer_ifm; 45 unsigned int ifi_flags, ifi_change; 46 47 if (strcmp(argv[0], "peer") != 0) { 48 usage(); 49 return -1; 50 } 51 52 ifm = NLMSG_DATA(hdr); 53 ifi_flags = ifm->ifi_flags; 54 ifi_change = ifm->ifi_change; 55 ifm->ifi_flags = 0; 56 ifm->ifi_change = 0; 57 58 data = NLMSG_TAIL(hdr); 59 addattr_l(hdr, 1024, VXCAN_INFO_PEER, NULL, 0); 60 61 hdr->nlmsg_len += sizeof(struct ifinfomsg); 62 63 err = iplink_parse(argc - 1, argv + 1, (struct iplink_req *)hdr, 64 &name, &type, &link, &dev, &group, &index); 65 if (err < 0) 66 return err; 67 68 if (name) { 69 len = strlen(name) + 1; 70 if (len > IFNAMSIZ) 71 invarg("\"name\" too long\n", *argv); 72 addattr_l(hdr, 1024, IFLA_IFNAME, name, len); 73 } 74 75 peer_ifm = RTA_DATA(data); 76 peer_ifm->ifi_index = index; 77 peer_ifm->ifi_flags = ifm->ifi_flags; 78 peer_ifm->ifi_change = ifm->ifi_change; 79 ifm->ifi_flags = ifi_flags; 80 ifm->ifi_change = ifi_change; 81 82 if (group != -1) 83 addattr32(hdr, 1024, IFLA_GROUP, group); 84 85 data->rta_len = (void *)NLMSG_TAIL(hdr) - (void *)data; 86 return argc - 1 - err; 87 } 88 89 static void vxcan_print_help(struct link_util *lu, int argc, char **argv, 90 FILE *f) 91 { 92 print_usage(f); 93 } 94 95 struct link_util vxcan_link_util = { 96 .id = "vxcan", 97 .parse_opt = vxcan_parse_opt, 98 .print_help = vxcan_print_help, 99 }; 100