]>
git.ipfire.org Git - thirdparty/lldpd.git/blob - src/daemon/interfaces-solaris.c
1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2013 Vincent Bernat <bernat@luffy.cx>
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 #include <sys/sockio.h>
22 #include <net/if_types.h>
24 /* Solaris comes with libdladm which seems to be handy to get all the necessary
25 * information. Unfortunately, this library needs a special device file and a
26 * Unix socket to a daemon. This is a bit difficult to use it in a
27 * privilege-separated daemon. Therefore, we keep using ioctl(). This should
28 * also improve compatibility with older versions of Solaris.
32 ifsolaris_extract(struct lldpd
*cfg
, struct interfaces_device_list
*interfaces
,
33 struct interfaces_address_list
*addresses
, struct lifreq
*lifr
)
37 struct interfaces_address
*address
= NULL
;
38 struct interfaces_device
*device
= NULL
;
40 sa_family_t lifr_af
= lifr
->lifr_addr
.ss_family
;
41 struct lifreq lifrl
= { .lifr_name
= {} };
42 strlcpy(lifrl
.lifr_name
, lifr
->lifr_name
, sizeof(lifrl
.lifr_name
));
45 if (ioctl(cfg
->g_sock
, SIOCGLIFFLAGS
, (caddr_t
)&lifrl
) < 0) {
46 log_warn("interfaces", "unable to get flags for %s", lifrl
.lifr_name
);
49 flags
= lifrl
.lifr_flags
;
52 if (ioctl(cfg
->g_sock
, SIOCGLIFINDEX
, (caddr_t
)&lifrl
) < 0) {
53 log_warn("interfaces", "unable to get index for %s", lifrl
.lifr_name
);
56 index
= lifrl
.lifr_index
;
58 /* Record the address */
59 if ((address
= malloc(sizeof(struct interfaces_address
))) == NULL
) {
60 log_warn("interfaces", "not enough memory for a new IP address on %s",
64 address
->flags
= flags
;
65 address
->index
= index
;
66 memcpy(&address
->address
, &lifr
->lifr_addr
,
67 (lifr_af
== AF_INET
) ? sizeof(struct sockaddr_in
) :
68 sizeof(struct sockaddr_in6
));
69 TAILQ_INSERT_TAIL(addresses
, address
, next
);
71 /* Hardware address */
72 if (ioctl(cfg
->g_sock
, SIOCGLIFHWADDR
, (caddr_t
)&lifrl
) < 0) {
73 log_debug("interfaces", "unable to get hardware address for %s",
77 struct sockaddr_dl
*saddrdl
= (struct sockaddr_dl
*)&lifrl
.lifr_addr
;
78 if (saddrdl
->sdl_type
!= 4) {
79 log_debug("interfaces", "skip %s: not an ethernet device (%d)",
80 lifrl
.lifr_name
, saddrdl
->sdl_type
);
84 /* Handle the interface */
85 if ((device
= calloc(1, sizeof(struct interfaces_device
))) == NULL
) {
86 log_warn("interfaces", "unable to allocate memory for %s",
91 device
->name
= strdup(lifrl
.lifr_name
);
92 device
->flags
= flags
;
93 device
->index
= index
;
94 device
->type
= IFACE_PHYSICAL_T
;
95 device
->address
= malloc(ETHER_ADDR_LEN
);
96 if (device
->address
) memcpy(device
->address
, LLADDR(saddrdl
), ETHER_ADDR_LEN
);
99 if (ioctl(cfg
->g_sock
, SIOCGLIFMTU
, (caddr_t
)&lifrl
) < 0) {
100 log_debug("interfaces", "unable to get MTU for %s", lifrl
.lifr_name
);
102 device
->mtu
= lifrl
.lifr_mtu
;
104 TAILQ_INSERT_TAIL(interfaces
, device
, next
);
107 extern struct lldpd_ops bpf_ops
;
109 interfaces_update(struct lldpd
*cfg
)
111 struct lldpd_hardware
*hardware
;
112 caddr_t buffer
= NULL
;
113 struct interfaces_device_list
*interfaces
;
114 struct interfaces_address_list
*addresses
;
115 interfaces
= malloc(sizeof(struct interfaces_device_list
));
116 addresses
= malloc(sizeof(struct interfaces_address_list
));
117 if (interfaces
== NULL
|| addresses
== NULL
) {
118 log_warnx("interfaces", "unable to allocate memory");
121 TAILQ_INIT(interfaces
);
122 TAILQ_INIT(addresses
);
124 struct lifnum lifn
= { .lifn_family
= AF_UNSPEC
, .lifn_flags
= LIFC_ENABLED
};
125 if (ioctl(cfg
->g_sock
, SIOCGLIFNUM
, &lifn
) < 0) {
126 log_warn("interfaces", "unable to get the number of interfaces");
130 size_t bufsize
= lifn
.lifn_count
* sizeof(struct lifreq
);
131 if ((buffer
= malloc(bufsize
)) == NULL
) {
132 log_warn("interfaces", "unable to allocate buffer to get interfaces");
136 struct lifconf lifc
= { .lifc_family
= AF_UNSPEC
,
137 .lifc_flags
= LIFC_ENABLED
,
139 .lifc_buf
= buffer
};
140 if (ioctl(cfg
->g_sock
, SIOCGLIFCONF
, (char *)&lifc
) < 0) {
141 log_warn("interfaces", "unable to get the network interfaces");
145 int num
= lifc
.lifc_len
/ sizeof(struct lifreq
);
146 if (num
> lifn
.lifn_count
) num
= lifn
.lifn_count
;
147 log_debug("interfaces", "got %d interfaces", num
);
149 struct lifreq
*lifrp
= (struct lifreq
*)buffer
;
150 for (int n
= 0; n
< num
; n
++, lifrp
++)
151 ifsolaris_extract(cfg
, interfaces
, addresses
, lifrp
);
153 interfaces_helper_allowlist(cfg
, interfaces
);
154 interfaces_helper_physical(cfg
, interfaces
, &bpf_ops
, ifbpf_phys_init
);
155 interfaces_helper_mgmt(cfg
, addresses
, interfaces
);
156 interfaces_helper_chassis(cfg
, interfaces
);
159 TAILQ_FOREACH (hardware
, &cfg
->g_hardware
, h_entries
) {
160 if (!hardware
->h_flags
) continue;
161 /* TODO: mac/phy for Solaris */
162 interfaces_helper_promisc(cfg
, hardware
);
167 interfaces_free_devices(interfaces
);
168 interfaces_free_addresses(addresses
);
172 interfaces_cleanup(struct lldpd
*cfg
)