1 /* 2 * iplink_hsr.c HSR device support 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 * Authors: Arvid Brodin <arvid.brodin (at) alten.se> 10 * 11 * Based on iplink_vlan.c by Patrick McHardy <kaber (at) trash.net> 12 */ 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <sys/socket.h> /* Needed by linux/if.h for some reason */ 18 #include <linux/if.h> 19 #include <linux/if_arp.h> 20 #include "rt_names.h" 21 #include "utils.h" 22 #include "ip_common.h" 23 24 static void print_usage(FILE *f) 25 { 26 fprintf(f, 27 "Usage:\tip link add name NAME type hsr slave1 SLAVE1-IF slave2 SLAVE2-IF\n" 28 "\t[ supervision ADDR-BYTE ] [version VERSION]\n" 29 "\n" 30 "NAME\n" 31 " name of new hsr device (e.g. hsr0)\n" 32 "SLAVE1-IF, SLAVE2-IF\n" 33 " the two slave devices bound to the HSR device\n" 34 "ADDR-BYTE\n" 35 " 0-255; the last byte of the multicast address used for HSR supervision\n" 36 " frames (default = 0)\n" 37 "VERSION\n" 38 " 0,1; the protocol version to be used. (default = 0)\n"); 39 } 40 41 static void usage(void) 42 { 43 print_usage(stderr); 44 } 45 46 static int hsr_parse_opt(struct link_util *lu, int argc, char **argv, 47 struct nlmsghdr *n) 48 { 49 int ifindex; 50 unsigned char multicast_spec; 51 unsigned char protocol_version; 52 53 while (argc > 0) { 54 if (matches(*argv, "supervision") == 0) { 55 NEXT_ARG(); 56 if (get_u8(&multicast_spec, *argv, 0)) 57 invarg("ADDR-BYTE is invalid", *argv); 58 addattr_l(n, 1024, IFLA_HSR_MULTICAST_SPEC, 59 &multicast_spec, 1); 60 } else if (matches(*argv, "version") == 0) { 61 NEXT_ARG(); 62 if (!(get_u8(&protocol_version, *argv, 0) == 0 || 63 get_u8(&protocol_version, *argv, 0) == 1)) 64 invarg("version is invalid", *argv); 65 addattr_l(n, 1024, IFLA_HSR_VERSION, 66 &protocol_version, 1); 67 } else if (matches(*argv, "slave1") == 0) { 68 NEXT_ARG(); 69 ifindex = ll_name_to_index(*argv); 70 if (ifindex == 0) 71 invarg("No such interface", *argv); 72 addattr_l(n, 1024, IFLA_HSR_SLAVE1, &ifindex, 4); 73 } else if (matches(*argv, "slave2") == 0) { 74 NEXT_ARG(); 75 ifindex = ll_name_to_index(*argv); 76 if (ifindex == 0) 77 invarg("No such interface", *argv); 78 addattr_l(n, 1024, IFLA_HSR_SLAVE2, &ifindex, 4); 79 } else if (matches(*argv, "help") == 0) { 80 usage(); 81 return -1; 82 } else { 83 fprintf(stderr, "hsr: what is \"%s\"?\n", *argv); 84 usage(); 85 return -1; 86 } 87 argc--, argv++; 88 } 89 90 return 0; 91 } 92 93 static void hsr_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) 94 { 95 SPRINT_BUF(b1); 96 97 if (!tb) 98 return; 99 100 if (tb[IFLA_HSR_SLAVE1] && 101 RTA_PAYLOAD(tb[IFLA_HSR_SLAVE1]) < sizeof(__u32)) 102 return; 103 if (tb[IFLA_HSR_SLAVE2] && 104 RTA_PAYLOAD(tb[IFLA_HSR_SLAVE2]) < sizeof(__u32)) 105 return; 106 if (tb[IFLA_HSR_SEQ_NR] && 107 RTA_PAYLOAD(tb[IFLA_HSR_SEQ_NR]) < sizeof(__u16)) 108 return; 109 if (tb[IFLA_HSR_SUPERVISION_ADDR] && 110 RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]) < ETH_ALEN) 111 return; 112 113 if (tb[IFLA_HSR_SLAVE1]) 114 print_string(PRINT_ANY, 115 "slave1", 116 "slave1 %s ", 117 ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE1]))); 118 else 119 print_null(PRINT_ANY, "slave1", "slave1 %s ", "<none>"); 120 121 if (tb[IFLA_HSR_SLAVE2]) 122 print_string(PRINT_ANY, 123 "slave2", 124 "slave2 %s ", 125 ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE2]))); 126 else 127 print_null(PRINT_ANY, "slave2", "slave2 %s ", "<none>"); 128 129 if (tb[IFLA_HSR_SEQ_NR]) 130 print_int(PRINT_ANY, 131 "seq_nr", 132 "sequence %d ", 133 rta_getattr_u16(tb[IFLA_HSR_SEQ_NR])); 134 135 if (tb[IFLA_HSR_SUPERVISION_ADDR]) 136 print_string(PRINT_ANY, 137 "supervision_addr", 138 "supervision %s ", 139 ll_addr_n2a(RTA_DATA(tb[IFLA_HSR_SUPERVISION_ADDR]), 140 RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]), 141 ARPHRD_VOID, 142 b1, sizeof(b1))); 143 } 144 145 static void hsr_print_help(struct link_util *lu, int argc, char **argv, 146 FILE *f) 147 { 148 print_usage(f); 149 } 150 151 struct link_util hsr_link_util = { 152 .id = "hsr", 153 .maxattr = IFLA_HSR_MAX, 154 .parse_opt = hsr_parse_opt, 155 .print_opt = hsr_print_opt, 156 .print_help = hsr_print_help, 157 }; 158