]> git.ipfire.org Git - people/ms/rstp.git/blob - netif_utils.c
a14e0c31d747aa55f1c368f0f3a55555c426622b
[people/ms/rstp.git] / netif_utils.c
1 /*****************************************************************************
2 Copyright (c) 2006 EMC Corporation.
3
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2 of the License, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 The full GNU General Public License is included in this distribution in the
19 file called LICENSE.
20
21 Authors: Srinivas Aji <Aji_Srinivas@emc.com>
22
23 ******************************************************************************/
24
25 #include "netif_utils.h"
26
27 #include <errno.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <stdint.h>
32 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <fcntl.h>
35
36 #include <net/if.h>
37 #include <linux/if_ether.h>
38 #include <linux/ethtool.h>
39 #include <linux/sockios.h>
40
41 #include "log.h"
42
43
44
45 int netsock = -1;
46
47 int netsock_init(void)
48 {
49 LOG("");
50 netsock = socket(AF_INET, SOCK_DGRAM, 0);
51 if (netsock < 0) {
52 ERROR("Couldn't open inet socket for ioctls: %m\n");
53 return -1;
54 }
55 return 0;
56 }
57
58 int get_hwaddr(char *ifname, unsigned char *hwaddr)
59 {
60 struct ifreq ifr;
61 memset(&ifr, 0, sizeof(ifr));
62 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
63 if (ioctl(netsock, SIOCGIFHWADDR, &ifr) < 0) {
64 ERROR("%s: get hw address failed: %m", ifname);
65 return -1;
66 }
67 memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
68 return 0;
69 }
70
71 int ethtool_get_speed_duplex(char *ifname, int *speed, int *duplex)
72 {
73 struct ifreq ifr;
74 memset(&ifr, 0, sizeof(ifr));
75 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
76 struct ethtool_cmd ecmd;
77
78 ecmd.cmd = ETHTOOL_GSET;
79 ifr.ifr_data = (caddr_t)&ecmd;
80 if (ioctl(netsock, SIOCETHTOOL, &ifr) < 0) {
81 ERROR("Cannot get link status for %s: %m\n", ifname);
82 return -1;
83 }
84 *speed = ecmd.speed; /* Ethtool speed is in Mbps */
85 *duplex = ecmd.duplex; /* We have same convention as ethtool.
86 0 = half, 1 = full */
87 return 0;
88 }
89
90
91 /********* Sysfs based utility functions *************/
92
93 /* This sysfs stuff might break with interface renames */
94 int is_bridge(char *if_name)
95 {
96 char path[32 + IFNAMSIZ];
97 sprintf(path, "/sys/class/net/%s/bridge", if_name);
98 return (access(path, R_OK) == 0);
99 }
100
101 /* This will work even less if the bridge port is renamed after being
102 joined to the bridge.
103 */
104 int is_bridge_slave(char *br_name, char *if_name)
105 {
106 char path[32 + 2 * IFNAMSIZ];
107 sprintf(path, "/sys/class/net/%s/brif/%s", br_name, if_name);
108 return (access(path, R_OK) == 0);
109 }
110
111 int get_bridge_portno(char *if_name)
112 {
113 char path[32 + IFNAMSIZ];
114 sprintf(path, "/sys/class/net/%s/brport/port_no", if_name);
115 char buf[128];
116 int fd;
117 long res = -1;
118 TSTM((fd = open(path, O_RDONLY)) >= 0, -1, "%m");
119 int l;
120 TSTM((l = read(fd, buf, sizeof(buf) - 1)) >= 0, -1, "%m");
121 if (l == 0) {
122 ERROR("Empty port index file");
123 goto out;
124 }
125 else if (l == sizeof(buf) - 1) {
126 ERROR("port_index file too long");
127 goto out;
128 }
129 buf[l] = 0;
130 if (buf[l-1] == '\n')
131 buf[l-1] = 0;
132 char *end;
133 res = strtoul(buf, &end, 0);
134 if (*end != 0 || res > INT_MAX) {
135 ERROR("Invalid port index %s", buf);
136 res = -1;
137 }
138 out:
139 close(fd);
140 return res;
141 }