]> git.ipfire.org Git - people/ms/mstpd.git/blame - netif_utils.c
driver hooks for creating/deleting new MSTI
[people/ms/mstpd.git] / netif_utils.c
CommitLineData
1e6d2d09
VD
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 <vitas@nppfactor.kiev.ua>
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 <net/if.h>
35#include <linux/if_ether.h>
36#include <linux/ethtool.h>
37#include <linux/sockios.h>
38
39#include "log.h"
40
c6ed0c4c 41static int netsock = -1;
1e6d2d09
VD
42
43int netsock_init(void)
44{
45 netsock = socket(AF_INET, SOCK_DGRAM, 0);
46 if(0 > netsock)
47 {
48 ERROR("Couldn't open inet socket for ioctls: %m\n");
49 return -1;
50 }
51 return 0;
52}
53
54int get_hwaddr(char *ifname, __u8 *hwaddr)
55{
56 struct ifreq ifr;
57 memset(&ifr, 0, sizeof(ifr));
58 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
59 if(0 > ioctl(netsock, SIOCGIFHWADDR, &ifr))
60 {
61 ERROR("%s: get hw address failed: %m", ifname);
62 return -1;
63 }
64 memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
65 return 0;
66}
67
68int ethtool_get_link(char *ifname)
69{
70 struct ifreq ifr;
71 memset(&ifr, 0, sizeof(ifr));
72 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
73 struct ethtool_value eval;
74
75 eval.cmd = ETHTOOL_GLINK;
76 ifr.ifr_data = (caddr_t)&eval;
77 if(0 > ioctl(netsock, SIOCETHTOOL, &ifr))
78 {
79 ERROR("Cannot get link status for %s: %m\n", ifname);
80 return -1;
81 }
82 if(eval.data)
83 return 1;
84 return 0;
85}
86
87int ethtool_get_speed_duplex(char *ifname, int *speed, int *duplex)
88{
89 struct ifreq ifr;
90 memset(&ifr, 0, sizeof(ifr));
91 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
92 struct ethtool_cmd ecmd;
93
94 ecmd.cmd = ETHTOOL_GSET;
95 ifr.ifr_data = (caddr_t)&ecmd;
96 if(0 > ioctl(netsock, SIOCETHTOOL, &ifr))
97 {
98 ERROR("Cannot get speed/duplex for %s: %m\n", ifname);
99 return -1;
100 }
101 *speed = ecmd.speed; /* Ethtool speed is in Mbps */
102 *duplex = ecmd.duplex; /* We have same convention as ethtool.
103 0 = half, 1 = full */
104 return 0;
105}
106
107/********* Sysfs based utility functions *************/
108
109/* This sysfs stuff might break with interface renames */
110bool is_bridge(char *if_name)
111{
112 char path[32 + IFNAMSIZ];
113 sprintf(path, "/sys/class/net/%s/bridge", if_name);
114 return (0 == access(path, R_OK));
115}
116
117int get_bridge_portno(char *if_name)
118{
119 char path[32 + IFNAMSIZ];
120 sprintf(path, "/sys/class/net/%s/brport/port_no", if_name);
121 char buf[128];
122 int fd;
123 long res = -1;
124 TSTM((fd = open(path, O_RDONLY)) >= 0, -1, "%m");
125 int l;
126 TSTM((l = read(fd, buf, sizeof(buf) - 1)) >= 0, -1, "%m");
127 if(0 == l)
128 {
129 ERROR("Empty port index file");
130 goto out;
131 }
132 else if((sizeof(buf) - 1) == l)
133 {
134 ERROR("port_index file too long");
135 goto out;
136 }
137 buf[l] = 0;
138 if('\n' == buf[l - 1])
139 buf[l - 1] = 0;
140 char *end;
141 res = strtoul(buf, &end, 0);
142 if(0 != *end || INT_MAX < res)
143 {
144 ERROR("Invalid port index %s", buf);
145 res = -1;
146 }
147out:
148 close(fd);
149 return res;
150}