• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/ustp/netif_utils.c

  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