[lldp-devel] [PATCH] lldpad: Use a permament socket for ioctls

Mark Rustad mark.d.rustad at intel.com
Thu Mar 21 20:17:20 UTC 2013


Use a permanent socket for routine ioctls. This not
only is a minor optimization, but it also avoids bizzare
behavior when the process runs out of sockets due to
a socket leak.

Signed-off-by: Mark Rustad <mark.d.rustad at intel.com>
Tested-by: Jack Morgan <jack.morgan at intel.com>
---

 lldp_rtnl.c |   16 +----
 lldp_util.c |  203 ++++++++++++++++++++++-------------------------------------
 2 files changed, 80 insertions(+), 139 deletions(-)

diff --git a/lldp_rtnl.c b/lldp_rtnl.c
index bb0ee54..0c57e62 100644
--- a/lldp_rtnl.c
+++ b/lldp_rtnl.c
@@ -37,6 +37,7 @@
 #include "linux/rtnetlink.h"
 #include "linux/dcbnl.h"
 #include "linux/if.h"
+#include "lldp_util.h"
 #include "lldp_rtnl.h"
 #include "messages.h"
 #include "lldp.h"
@@ -286,20 +287,11 @@ out:
 
 int get_operstate(char *ifname)
 {
-	int s, ifq;
-	int ifindex = 0;
-	struct ifreq ifr;
+	int s;
+	int ifindex;
 	__u8 operstate = IF_OPER_UNKNOWN;
 
-	/* fill in ifr_ifindex for kernel versions that require it */
-	ifq = socket(PF_PACKET, SOCK_DGRAM, 0);
-	if (ifq < 0)
-		return ifq;
-	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
-	if (ioctl(ifq, SIOCGIFINDEX, &ifr) == 0)
-		ifindex = ifr.ifr_ifindex;
-	close(ifq);
-
+	ifindex = get_ifidx(ifname);
 	s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
 	if (s < 0)
 		return s;
diff --git a/lldp_util.c b/lldp_util.c
index 4dc15d5..4a1cc4a 100644
--- a/lldp_util.c
+++ b/lldp_util.c
@@ -134,6 +134,22 @@ char *print_mac(char *mac, char *buf)
 	return buf;
 }
 
+static int get_ioctl_socket(void)
+{
+	static int ioctl_socket = -1;
+
+	if (ioctl_socket >= 0)
+		return ioctl_socket;
+	ioctl_socket = socket(PF_INET, SOCK_DGRAM, 0);
+	if (ioctl_socket < 0) {
+		int err = errno;
+
+		perror("socket create failed\n");
+		errno = err;
+	}
+	return ioctl_socket;
+}
+
 int is_valid_lldp_device(const char *device_name)
 {
 	if (is_loopback(device_name))
@@ -155,22 +171,19 @@ int is_valid_lldp_device(const char *device_name)
  */
 int is_bond(const char *ifname)
 {
-	int fd = -1;
+	int fd;
 	int rc = 0;
 	struct ifreq ifr;
 	ifbond ifb;
 
-	fd = socket(PF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifr, 0, sizeof(ifr));
 		strcpy(ifr.ifr_name, ifname);
 		memset(&ifb, 0, sizeof(ifb));
 		ifr.ifr_data = (caddr_t)&ifb;
 		if (ioctl(fd, SIOCBONDINFOQUERY, &ifr) == 0)
 			rc = 1;
-		close(fd);
-	} else {
-		perror("is_bond() socket create failed");
 	}
 	return rc;
 }
@@ -218,12 +231,9 @@ int	get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr)
 	int found = 0;
 	int i;
 
-	fd = socket(PF_INET, SOCK_DGRAM, 0);
-
-	if (fd <= 0) {
-		perror("get_src_mac_from_bond failed");
+	fd = get_ioctl_socket();
+	if (fd < 0)
 		return 0;
-	}
 
 	memset(bond_mac, 0, sizeof(bond_mac));
 	memset(&ifr, 0, sizeof(ifr));
@@ -259,10 +269,8 @@ int	get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr)
 	}
 
 	/* current port is not a slave of the bond */
-	if (!found) {
-		close(fd);
+	if (!found)
 		return 0;
-	}
 
 	/* Get slave port's current perm MAC address
 	 * This will be the default return value
@@ -274,7 +282,6 @@ int	get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr)
 	}
 	else {
 		perror("error getting slave MAC address");
-		close(fd);
 		return 0;
 	}
 
@@ -298,8 +305,6 @@ int	get_src_mac_from_bond(struct port *bond_port, char *ifname, u8 *addr)
 		break;
 	}
 
-	close(fd);
-
 	return 1;
 }
 
@@ -329,40 +334,34 @@ int read_bool(const char *path)
 
 int get_ifflags(const char *ifname)
 {
-	int fd = -1;
+	int fd;
 	int flags = 0;
 	struct ifreq ifr;
 
 	/* use ioctl */	
-	fd = socket(AF_LOCAL, SOCK_STREAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifr, 0, sizeof(ifr));
 		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-		if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
+		if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
 			flags = ifr.ifr_flags;
-		} else {
-		}
-		close(fd);
 	}
 	return flags;
 }
 
 int get_ifpflags(const char *ifname)
 {
-	int fd = -1;
+	int fd;
 	int flags = 0;
 	struct ifreq ifr;
 
 	/* use ioctl */	
-	fd = socket(AF_LOCAL, SOCK_STREAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifr, 0, sizeof(ifr));
 		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-		if (ioctl(fd, SIOCGIFPFLAGS, &ifr) == 0) {
+		if (ioctl(fd, SIOCGIFPFLAGS, &ifr) == 0)
 			flags = ifr.ifr_flags;
-		} else {
-		}
-		close(fd);
 	}
 	return flags;
 }
@@ -375,15 +374,6 @@ int get_iftype(const char *ifname)
 	return read_int(path);
 }
 
-int get_ifindex(const char *ifname)
-{
-	char path[256];
-
-	snprintf(path, sizeof(path), "/sys/class/net/%s/ifindex", ifname);
-	return read_int(path);
-
-}
-
 int get_iffeatures(const char *ifname)
 {
 	char path[256];
@@ -447,8 +437,8 @@ int is_slave(const char *ifmaster, const char *ifslave)
 	if (!is_mbond(ifmaster))
 		goto out_done;
 
-	fd = socket(PF_INET, SOCK_DGRAM, 0);
-	if (fd <= 0)
+	fd = get_ioctl_socket();
+	if (fd < 0)
 		goto out_done;
 
 	memset(&ifr, 0, sizeof(ifr));
@@ -456,7 +446,7 @@ int is_slave(const char *ifmaster, const char *ifslave)
 	strncpy(ifr.ifr_name, ifmaster, IFNAMSIZ);
 	ifr.ifr_data = (caddr_t)&ifb;
 	if (ioctl(fd, SIOCBONDINFOQUERY, &ifr))
-		goto out_close;
+		goto out_done;
 
 	for (i = 0; i < ifb.num_slaves; i++) {
 		memset(&ifs, 0, sizeof(ifs));
@@ -470,8 +460,6 @@ int is_slave(const char *ifmaster, const char *ifslave)
 		}
 	}
 	
-out_close:
-	close(fd);
 out_done:
 	return rc;
 }
@@ -482,13 +470,12 @@ int get_ifidx(const char *ifname)
 	int idx = 0;
 	struct ifreq ifreq;
 
-	fd = socket(AF_LOCAL, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifreq, 0, sizeof(ifreq));
 		strncpy(ifreq.ifr_name, ifname, IFNAMSIZ);
 		if (ioctl(fd, SIOCGIFINDEX, &ifreq) == 0)
 			idx = ifreq.ifr_ifindex;
-		close(fd);
 	}
 	return idx;
 }
@@ -497,8 +484,8 @@ int get_master(const char *ifname)
 {
 	int i;
 	int idx = 0;
-	int fd = -1;
-	int cnt = 0;
+	int fd;
+	int cnt;
 	struct ifreq *ifr = NULL;
 	struct ifconf ifc;
 	char ifcbuf[sizeof(struct ifreq) * 32];
@@ -507,8 +494,8 @@ int get_master(const char *ifname)
 	if (is_mbond(ifname))
 		return get_ifidx(ifname);
 
-	fd = socket(PF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifc, 0, sizeof(ifc));
 		memset(ifcbuf, 0, sizeof(ifcbuf));
 		ifc.ifc_buf = ifcbuf;
@@ -528,14 +515,13 @@ int get_master(const char *ifname)
 				break;
 			}
 		}
-		close(fd);
 	}
 	return idx;
 }
 
 int is_bridge(const char *ifname)
 {
-	int fd = -1;
+	int fd;
 	int rc = 0;
 	char path[256];
 	DIR *dirp;
@@ -551,8 +537,8 @@ int is_bridge(const char *ifname)
 		rc = 1;
 	} else { 
 		/* use ioctl */	
-		fd = socket(AF_LOCAL, SOCK_STREAM, 0);
-		if (fd > 0) {
+		fd = get_ioctl_socket();
+		if (fd >= 0) {
 			struct ifreq ifr;
 			struct __bridge_info bi;
 			unsigned long args[4] = { BRCTL_GET_BRIDGE_INFO, 
@@ -560,12 +546,8 @@ int is_bridge(const char *ifname)
 
 			ifr.ifr_data = (char *)args;
 			strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-			if (ioctl(fd, SIOCDEVPRIVATE, &ifr) == 0) {
+			if (ioctl(fd, SIOCDEVPRIVATE, &ifr) == 0)
 				rc = 1;
-			}
-			close(fd);
-		} else {
-			perror("is_bridge() open socket failed");
 		}
 	}
 	return rc;
@@ -573,20 +555,17 @@ int is_bridge(const char *ifname)
 
 int is_vlan(const char *ifname)
 {
-	int fd = -1;
+	int fd;
 	int rc = 0;
 	struct vlan_ioctl_args ifv;
 
-	fd = socket(PF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifv, 0, sizeof(ifv));
 		ifv.cmd = GET_VLAN_REALDEV_NAME_CMD;
 		strncpy(ifv.device1, ifname, sizeof(ifv.device1));
 		if (ioctl(fd, SIOCGIFVLAN, &ifv) == 0)
 			rc = 1;
-		close(fd);
-	} else {
-		perror("is_vlan() open socket error");
 	}
 	return rc;
 }
@@ -604,19 +583,16 @@ int is_vlan_capable(const char *ifname)
 
 int is_wlan(const char *ifname)
 {
-	int fd = -1;
+	int fd;
 	int rc = 0;
 	struct iwreq iwreq;
 
-	fd = socket(PF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&iwreq, 0, sizeof(iwreq));
 		strncpy(iwreq.ifr_name, ifname, sizeof(iwreq.ifr_name));
 		if (ioctl(fd, SIOCGIWNAME, &iwreq) == 0)
 			rc = 1;
-		close(fd);
-	} else {
-		perror("is_wlan() open socket error");
 	}
 	return rc;
 }
@@ -724,20 +700,17 @@ static int is_router(void)
 
 int is_active(const char *ifname)
 {
-	int fd = -1;
+	int fd;
 	int rc = 0;
 	struct ifreq ifr;
 
-	fd = socket(PF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifr, 0, sizeof(ifr));
 		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 		if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0)
 			if (ifr.ifr_flags & IFF_UP)
 				rc = 1;
-		close(fd);
-	} else {
-		perror("is_active() open socket error");
 	}
 	return rc;
 }
@@ -745,12 +718,12 @@ int is_active(const char *ifname)
 int is_autoneg_supported(const char *ifname)
 {
 	int rc = 0;
-	int fd = -1;
+	int fd;
 	struct ifreq ifr;
 	struct ethtool_cmd cmd;
 	
-	fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifr, 0, sizeof(ifr));
 		memset(&cmd, 0, sizeof(cmd));
 		cmd.cmd = ETHTOOL_GSET;
@@ -759,9 +732,6 @@ int is_autoneg_supported(const char *ifname)
 		if (ioctl(fd, SIOCETHTOOL, &ifr) == 0)
 			if (cmd.supported & SUPPORTED_Autoneg)
 				rc = 1;
-		close(fd);
-	} else {	
-		perror("is_autoneg_supported() open socket failed");
 	}
 	return rc;
 }
@@ -769,12 +739,12 @@ int is_autoneg_supported(const char *ifname)
 int is_autoneg_enabled(const char *ifname)
 {
 	int rc = 0;
-	int fd = -1;
+	int fd;
 	struct ifreq ifr;
 	struct ethtool_cmd cmd;
 	
-	fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifr, 0, sizeof(ifr));
 		memset(&cmd, 0, sizeof(cmd));
 		cmd.cmd = ETHTOOL_GSET;
@@ -782,9 +752,6 @@ int is_autoneg_enabled(const char *ifname)
 		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 		if (ioctl(fd, SIOCETHTOOL, &ifr) == 0)
 			rc = cmd.autoneg;
-		close(fd);
-	} else {	
-		perror("is_autoneg_enabled() open socket failed");
 	}
 	return rc;
 }
@@ -808,13 +775,13 @@ int is_autoneg_enabled(const char *ifname)
 #define MAUCAPADV_b1000baseTFD	(1 << 15) /* 1000BASE-T full duplex mode */
 int get_maucaps(const char *ifname)
 {
-	int fd = -1;
+	int fd;
 	u16 caps = MAUCAPADV_bOther;
 	struct ifreq ifr;
 	struct ethtool_cmd cmd;
 	
-	fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifr, 0, sizeof(ifr));
 		memset(&cmd, 0, sizeof(cmd));
 		cmd.cmd = ETHTOOL_GSET;
@@ -840,9 +807,6 @@ int get_maucaps(const char *ifname)
 			if (cmd.advertising & (ADVERTISED_Asym_Pause | ADVERTISED_Pause))
 				caps |= MAUCAPADV_bFdxBPause;
 		}
-		close(fd);
-	} else {	
-		perror("is_autoneg() open socket failed");
 	}
 	return caps;
 }
@@ -850,13 +814,13 @@ int get_maucaps(const char *ifname)
 int get_mautype(const char *ifname)
 {
 	int rc = 0;
-	int fd = -1;
+	int fd;
 	struct ifreq ifr;
 	struct ethtool_cmd cmd;
 	u32 speed;
 
-	fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifr, 0, sizeof(ifr));
 		memset(&cmd, 0, sizeof(cmd));
 		cmd.cmd = ETHTOOL_GSET;
@@ -875,29 +839,22 @@ int get_mautype(const char *ifname)
 			else if (speed == SPEED_1000)
 				rc = DOT3MAUTYPE_1000BaseTFD;
 		}
-		close(fd);
-	} else {	
-		perror("is_autoneg() open socket failed");
 	}
 	return rc;
 }
 
 int get_mtu(const char *ifname)
 {
-	int fd = -1;
+	int fd;
 	int rc = 0;
 	struct ifreq ifr;
 
-	fd = socket(AF_LOCAL, SOCK_STREAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		memset(&ifr, 0, sizeof(ifr));
 		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
-		if (ioctl(fd, SIOCGIFMTU, &ifr) == 0) {
+		if (ioctl(fd, SIOCGIFMTU, &ifr) == 0)
 			rc = ifr.ifr_mtu;
-		}
-		close(fd);
-	} else {
-		perror("get_mtu() socket create failed");
 	}
 	return rc;
 }
@@ -919,22 +876,19 @@ int get_mfs(const char *ifname)
 
 int get_mac(const char *ifname, u8 mac[])
 {
-	int fd = -1;
+	int fd;
 	int rc = EINVAL;
 	struct ifreq ifr;
 
 	memset(mac, 0, 6);
-	fd = socket(AF_INET, SOCK_DGRAM, 0);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		ifr.ifr_addr.sa_family = AF_INET;
 		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 		if (!ioctl(fd, SIOCGIFHWADDR, &ifr)) {
 			memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
 			rc = 0;
 		}
-		close(fd);
-	} else {
-		perror("get_mac() socket create failed");
 	}
 	return rc;
 }
@@ -990,19 +944,18 @@ u16 get_caps(const char *ifname)
 
 int get_saddr(const char *ifname, struct sockaddr_in *saddr)
 {
-	int fd = -1;
+	int fd;
 	int rc = EIO;
 	struct ifreq ifr;
 
-	fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
-	if (fd > 0) {
+	fd = get_ioctl_socket();
+	if (fd >= 0) {
 		ifr.ifr_addr.sa_family = AF_INET;
 		strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
 		if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
 			memcpy(saddr, &ifr.ifr_addr, sizeof(*saddr));
 			rc = 0;
 		}
-		close(fd);
 	}
 	return rc;
 }
@@ -1018,7 +971,6 @@ int get_ipaddr(const char *ifname, struct in_addr *in)
 	return rc;
 }
 
-
 int get_ipaddrstr(const char *ifname, char *ipaddr, size_t size)
 {
 	int rc;
@@ -1180,9 +1132,8 @@ int check_link_status(const char *ifname)
 		u32 data;
 	} linkstatus = { ETHTOOL_GLINK, 0};
 
-	fd = socket(PF_INET, SOCK_DGRAM, 0);
-
-	if (fd<=0)
+	fd = get_ioctl_socket();
+	if (fd < 0)
 		return retval;
 
 	memset(&ifr, 0, sizeof(ifr));
@@ -1191,8 +1142,6 @@ int check_link_status(const char *ifname)
 	if (ioctl(fd,SIOCETHTOOL, &ifr) == 0)
 		retval = linkstatus.data;
 
-	close(fd);
-
 	return retval;
 }
 



More information about the lldp-devel mailing list