]>
git.ipfire.org Git - thirdparty/lldpd.git/blob - src/daemon/interfaces-solaris.c
0f9f5e5380102195170ac130eb24d0d9df12132e
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
,
33 struct interfaces_device_list
*interfaces
,
34 struct interfaces_address_list
*addresses
,
35 struct lifreq
*lifr
) {
38 struct interfaces_address
*address
= NULL
;
39 struct interfaces_device
*device
= NULL
;
41 sa_family_t lifr_af
= lifr
->lifr_addr
.ss_family
;
42 struct lifreq lifrl
= { .lifr_name
= {} };
43 strlcpy(lifrl
.lifr_name
, lifr
->lifr_name
, sizeof(lifrl
.lifr_name
));
46 if (ioctl(cfg
->g_sock
, SIOCGLIFFLAGS
, (caddr_t
)&lifrl
) < 0) {
47 log_warn("interfaces", "unable to get flags for %s",
51 flags
= lifrl
.lifr_flags
;
54 if (ioctl(cfg
->g_sock
, SIOCGLIFINDEX
, (caddr_t
)&lifrl
) < 0) {
55 log_warn("interfaces", "unable to get index for %s",
59 index
= lifrl
.lifr_index
;
61 /* Record the address */
62 if ((address
= malloc(sizeof(struct interfaces_address
))) == NULL
) {
63 log_warn("interfaces",
64 "not enough memory for a new IP address on %s",
68 address
->flags
= flags
;
69 address
->index
= index
;
70 memcpy(&address
->address
,
73 sizeof(struct sockaddr_in
):
74 sizeof(struct sockaddr_in6
));
75 TAILQ_INSERT_TAIL(addresses
, address
, next
);
77 /* Hardware address */
78 if (ioctl(cfg
->g_sock
, SIOCGLIFHWADDR
, (caddr_t
)&lifrl
) < 0) {
79 log_debug("interfaces", "unable to get hardware address for %s",
83 struct sockaddr_dl
*saddrdl
= (struct sockaddr_dl
*)&lifrl
.lifr_addr
;
84 if (saddrdl
->sdl_type
!= 4) {
85 log_debug("interfaces", "skip %s: not an ethernet device (%d)",
86 lifrl
.lifr_name
, saddrdl
->sdl_type
);
90 /* Handle the interface */
91 if ((device
= calloc(1, sizeof(struct interfaces_device
))) == NULL
) {
92 log_warn("interfaces", "unable to allocate memory for %s",
97 device
->name
= strdup(lifrl
.lifr_name
);
98 device
->flags
= flags
;
99 device
->index
= index
;
100 device
->type
= IFACE_PHYSICAL_T
;
101 device
->address
= malloc(ETHER_ADDR_LEN
);
103 memcpy(device
->address
, LLADDR(saddrdl
), ETHER_ADDR_LEN
);
106 if (ioctl(cfg
->g_sock
, SIOCGLIFMTU
, (caddr_t
)&lifrl
) < 0) {
107 log_debug("interfaces", "unable to get MTU for %s",
109 } else device
->mtu
= lifrl
.lifr_mtu
;
111 TAILQ_INSERT_TAIL(interfaces
, device
, next
);
114 extern struct lldpd_ops bpf_ops
;
116 interfaces_update(struct lldpd
*cfg
) {
117 struct lldpd_hardware
*hardware
;
118 caddr_t buffer
= NULL
;
119 struct interfaces_device_list
*interfaces
;
120 struct interfaces_address_list
*addresses
;
121 interfaces
= malloc(sizeof(struct interfaces_device_list
));
122 addresses
= malloc(sizeof(struct interfaces_address_list
));
123 if (interfaces
== NULL
|| addresses
== NULL
) {
124 log_warnx("interfaces", "unable to allocate memory");
127 TAILQ_INIT(interfaces
);
128 TAILQ_INIT(addresses
);
130 struct lifnum lifn
= {
131 .lifn_family
= AF_UNSPEC
,
132 .lifn_flags
= LIFC_ENABLED
134 if (ioctl(cfg
->g_sock
, SIOCGLIFNUM
, &lifn
) < 0) {
135 log_warn("interfaces", "unable to get the number of interfaces");
139 size_t bufsize
= lifn
.lifn_count
* sizeof(struct lifreq
);
140 if ((buffer
= malloc(bufsize
)) == NULL
) {
141 log_warn("interfaces", "unable to allocate buffer to get interfaces");
145 struct lifconf lifc
= {
146 .lifc_family
= AF_UNSPEC
,
147 .lifc_flags
= LIFC_ENABLED
,
151 if (ioctl(cfg
->g_sock
, SIOCGLIFCONF
, (char *)&lifc
) < 0) {
152 log_warn("interfaces", "unable to get the network interfaces");
156 int num
= lifc
.lifc_len
/ sizeof (struct lifreq
);
157 if (num
> lifn
.lifn_count
) num
= lifn
.lifn_count
;
158 log_debug("interfaces", "got %d interfaces", num
);
160 struct lifreq
*lifrp
= (struct lifreq
*)buffer
;
161 for (int n
= 0; n
< num
; n
++, lifrp
++)
162 ifsolaris_extract(cfg
, interfaces
, addresses
, lifrp
);
164 interfaces_helper_whitelist(cfg
, interfaces
);
165 interfaces_helper_physical(cfg
, interfaces
,
166 &bpf_ops
, ifbpf_phys_init
);
167 interfaces_helper_mgmt(cfg
, addresses
);
168 interfaces_helper_chassis(cfg
, interfaces
);
171 TAILQ_FOREACH(hardware
, &cfg
->g_hardware
, h_entries
) {
172 if (!hardware
->h_flags
) continue;
173 /* TODO: mac/phy for Solaris */
174 interfaces_helper_promisc(cfg
, hardware
);
179 interfaces_free_devices(interfaces
);
180 interfaces_free_addresses(addresses
);
184 interfaces_cleanup(struct lldpd
*cfg
)