1 /***************************************************************************** 2 Copyright (c) 2006 EMC Corporation. 3 Copyright (c) 2011 Factor-SPE 4 5 This program is free software; you can redistribute it and/or modify it 6 under the terms of the GNU General Public License as published by the Free 7 Software Foundation; either version 2 of the License, or (at your option) 8 any later version. 9 10 This program is distributed in the hope that it will be useful, but WITHOUT 11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 more details. 14 15 You should have received a copy of the GNU General Public License along with 16 this program; if not, write to the Free Software Foundation, Inc., 59 17 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 19 The full GNU General Public License is included in this distribution in the 20 file called LICENSE. 21 22 Authors: Srinivas Aji <Aji_Srinivas@emc.com> 23 Authors: Vitalii Demianets <dvitasgs@gmail.com> 24 25 ******************************************************************************/ 26 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 #include <stdbool.h> 31 #include <fcntl.h> 32 #include <limits.h> 33 #include <sys/ioctl.h> 34 #include <sys/types.h> 35 #include <net/if.h> 36 #include <linux/if_ether.h> 37 #include <linux/ethtool.h> 38 #include <linux/sockios.h> 39 40 #include "netif_utils.h" 41 #include "log.h" 42 43 #ifndef SYSFS_CLASS_NET 44 #define SYSFS_CLASS_NET "/sys/class/net" 45 #endif 46 47 static int netsock = -1; 48 49 int netsock_init(void) 50 { 51 netsock = socket(AF_INET, SOCK_DGRAM, 0); 52 if(0 > netsock) 53 { 54 ERROR("Couldn't open inet socket for ioctls: %m\n"); 55 return -1; 56 } 57 return 0; 58 } 59 60 int get_hwaddr(char *ifname, __u8 *hwaddr) 61 { 62 struct ifreq ifr; 63 memset(&ifr, 0, sizeof(ifr)); 64 strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); 65 if(0 > ioctl(netsock, SIOCGIFHWADDR, &ifr)) 66 { 67 ERROR("%s: get hw address failed: %m", ifname); 68 return -1; 69 } 70 memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); 71 return 0; 72 } 73 74 int get_flags(char *ifname) 75 { 76 struct ifreq ifr; 77 memset(&ifr, 0, sizeof(ifr)); 78 strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); 79 if(0 > ioctl(netsock, SIOCGIFFLAGS, &ifr)) 80 { 81 ERROR("%s: get interface flags failed: %m", ifname); 82 return -1; 83 } 84 return ifr.ifr_flags; 85 } 86 87 int if_shutdown(char *ifname) 88 { 89 struct ifreq ifr; 90 91 memset(&ifr, 0, sizeof(ifr)); 92 /* TODO: Let's hope -1 is not a valid flag combination */ 93 if(-1 == (ifr.ifr_flags = get_flags(ifname))) 94 { 95 return -1; 96 } 97 ifr.ifr_flags &= ~IFF_UP; 98 strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); 99 if(0 > ioctl(netsock, SIOCSIFFLAGS, &ifr)) 100 { 101 ERROR("%s: set if_down flag failed: %m", ifname); 102 return -1; 103 } 104 return 0; 105 } 106 107 int ethtool_get_speed_duplex(char *ifname, int *speed, int *duplex) 108 { 109 struct ifreq ifr; 110 memset(&ifr, 0, sizeof(ifr)); 111 strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); 112 struct ethtool_cmd ecmd; 113 114 ecmd.cmd = ETHTOOL_GSET; 115 ifr.ifr_data = (caddr_t)&ecmd; 116 if(0 > ioctl(netsock, SIOCETHTOOL, &ifr)) 117 { 118 INFO("Cannot get speed/duplex for %s: %m\n", ifname); 119 return -1; 120 } 121 *speed = ecmd.speed; /* Ethtool speed is in Mbps */ 122 *duplex = ecmd.duplex; /* We have same convention as ethtool. 123 0 = half, 1 = full */ 124 return 0; 125 } 126 127 /********* Sysfs based utility functions *************/ 128 129 /* This sysfs stuff might break with interface renames */ 130 bool is_bridge(char *if_name) 131 { 132 char path[32 + IFNAMSIZ]; 133 sprintf(path, SYSFS_CLASS_NET "/%s/bridge", if_name); 134 return (0 == access(path, R_OK)); 135 } 136 137 static int get_port_file(const char *if_name, const char *file) 138 { 139 char path[32 + IFNAMSIZ]; 140 sprintf(path, SYSFS_CLASS_NET "/%s/brport/%s", if_name, file); 141 char buf[128]; 142 int fd; 143 long res = -1; 144 TSTM((fd = open(path, O_RDONLY)) >= 0, -1, "%m"); 145 int l; 146 if((l = read(fd, buf, sizeof(buf) - 1)) < 0) { 147 ERROR("Failed to read file %s: error %m", file); 148 return -1; 149 } 150 if(0 == l) 151 { 152 ERROR("Empty %s file", file); 153 goto out; 154 } 155 else if((sizeof(buf) - 1) == l) 156 { 157 ERROR("%s file too long", file); 158 goto out; 159 } 160 buf[l] = 0; 161 if('\n' == buf[l - 1]) 162 buf[l - 1] = 0; 163 char *end; 164 res = strtoul(buf, &end, 0); 165 if(0 != *end || INT_MAX < res) 166 { 167 ERROR("Invalid %s %s", file, buf); 168 res = -1; 169 } 170 out: 171 close(fd); 172 return res; 173 } 174 175 int get_bpdu_filter(char *if_name) 176 { 177 return get_port_file(if_name, "bpdu_filter"); 178 } 179 180 int get_bridge_portno(char *if_name) 181 { 182 return get_port_file(if_name, "port_no"); 183 } 184
This page was automatically generated by LXR 0.3.1. • OpenWrt