/* If something other than dhcpcd removes a route,
* we need to remove it from our internal table. */
int
-route_deleted(const struct in_addr *dst,
- const struct in_addr *net,
- const struct in_addr *gate)
+route_deleted(const struct rt *rt)
{
- struct rt rt, *f, *l;
+ struct rt *f, *l;
- rt.dest.s_addr = dst->s_addr;
- rt.net.s_addr = net->s_addr;
- rt.gate.s_addr = gate->s_addr;
- rt.iface = NULL;
- rt.next = NULL;
-
- f = find_route(routes, &rt, &l, NULL);
+ f = find_route(routes, rt, &l, NULL);
if (f == NULL)
return 0;
- desc_route("removing", f, f->iface->name);
+ desc_route("removing", f, rt->iface->name);
if (l)
l->next = f->next;
else
int send_interface(int, const struct interface *);
int run_script(const struct interface *);
int configure(struct interface *);
-int route_deleted(const struct in_addr *,
- const struct in_addr *,
- const struct in_addr *);
-
+int route_deleted(const struct rt *);
#endif
static int margc;
static char **ifv;
static int ifc;
-static int linkfd = -1;
static char *cffile;
static char *pidfile;
+static int linkfd = -1;
struct dhcp_op {
uint8_t value;
}
}
+struct interface *
+find_interface(const char *ifname)
+{
+ struct interface *ifp;
+
+ for (ifp = ifaces; ifp; ifp = ifp->next)
+ if (strcmp(ifp->name, ifname) == 0)
+ return ifp;
+ return NULL;
+}
static void
stop_interface(struct interface *iface)
if (ifn)
continue;
init_state(ifp, 2, UNCONST(argv));
- start_interface(ifp);
if (ifl)
ifl->next = ifp;
else
ifaces = ifp;
+ start_interface(ifp);
}
}
}
{
struct interface *iface;
- for (iface = ifaces; iface; iface = iface->next)
- if (strcmp(iface->name, ifname) == 0) {
- stop_interface(iface);
- break;
- }
+ iface = find_interface(ifname);
+ if (iface != NULL)
+ stop_interface(iface);
}
/* ARGSUSED */
syslog(LOG_INFO, "version " VERSION " starting");
- if ((signal_fd =signal_init()) == -1)
+ if ((signal_fd = signal_init()) == -1)
exit(EXIT_FAILURE);
if (signal_setup() == -1)
exit(EXIT_FAILURE);
}
}
+ init_socket();
if (ifo->options & DHCPCD_LINK) {
linkfd = open_link_socket();
if (linkfd == -1)
extern char **ifdv;
extern struct interface *ifaces;
+struct interface *find_interface(const char *);
int handle_args(struct fd_list *, int, char **);
void handle_exit_timeout(void *);
void start_interface(void *);
1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
#endif
+static int a_fd = -1;
+static int r_fd = -1;
+
+int
+init_socket(void)
+{
+ if ((a_fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ return -1;
+ set_cloexec(a_fd);
+ if ((r_fd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
+ return -1;
+ set_cloexec(a_fd);
+ return 0;
+}
+
int
getifssid(const char *ifname, char *ssid)
{
- int s, retval = -1;
+ int retval = -1;
#if defined(SIOCG80211NWID)
struct ifreq ifr;
struct ieee80211_nwid nwid;
char nwid[IEEE80211_NWID_LEN + 1];
#endif
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- return retval;
#if defined(SIOCG80211NWID) /* NetBSD */
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
memset(&nwid, 0, sizeof(nwid));
ifr.ifr_data = (void *)&nwid;
- if (ioctl(s, SIOCG80211NWID, &ifr) == 0) {
+ if (ioctl(a_fd, SIOCG80211NWID, &ifr) == 0) {
retval = nwid.i_len;
memcpy(ssid, nwid.i_nwid, nwid.i_len);
ssid[nwid.i_len] = '\0';
ireq.i_type = IEEE80211_IOC_SSID;
ireq.i_val = -1;
ireq.i_data = &nwid;
- if (ioctl(s, SIOCG80211, &ireq) == 0) {
+ if (ioctl(a_fd, SIOCG80211, &ireq) == 0) {
retval = ireq.i_len;
memcpy(ssid, nwid, ireq.i_len);
ssid[ireq.i_len] = '\0';
}
#endif
- close(s);
return retval;
}
const struct in_addr *netmask, const struct in_addr *broadcast,
int action)
{
- int s;
int retval;
struct ifaliasreq ifa;
union {
struct sockaddr_in *sin;
} _s;
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- return -1;
-
memset(&ifa, 0, sizeof(ifa));
strlcpy(ifa.ifra_name, iface->name, sizeof(ifa.ifra_name));
#undef ADDADDR
if (action < 0)
- retval = ioctl(s, SIOCDIFADDR, &ifa);
+ retval = ioctl(a_fd, SIOCDIFADDR, &ifa);
else
- retval = ioctl(s, SIOCAIFADDR, &ifa);
- close(s);
+ retval = ioctl(a_fd, SIOCAIFADDR, &ifa);
return retval;
}
const struct in_addr *net, const struct in_addr *gate,
_unused int metric, int action)
{
- int s;
union sockunion {
struct sockaddr sa;
struct sockaddr_in sin;
ADDSU(su); \
}
- if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
- return -1;
-
memset(&rtm, 0, sizeof(rtm));
rtm.hdr.rtm_version = RTM_VERSION;
rtm.hdr.rtm_seq = 1;
ADDADDR(&iface->addr);
rtm.hdr.rtm_msglen = l = bp - (char *)&rtm;
- if (write(s, &rtm, l) == -1)
+ if (write(r_fd, &rtm, l) == -1)
retval = -1;
- close(s);
return retval;
}
int
arp_flush(void)
{
- int s, mib[6], retval = 0;
+ int mib[6], retval = 0;
size_t buffer_len = 0;
char *buffer, *e, *p;
struct rt_msghdr *rtm;
- if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
- return -1;
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
if (rtm->rtm_flags & RTF_STATIC)
continue;
rtm->rtm_type = RTM_DELETE;
- if (write(s, rtm, rtm->rtm_msglen) == -1) {
+ if (write(r_fd, rtm, rtm->rtm_msglen) == -1) {
retval = -1;
break;
}
}
free(buffer);
- close(s);
return retval;
}
#include "config.h"
#include "common.h"
+#include "configure.h"
#include "dhcp.h"
#include "net.h"
static void (*nl_add)(const char *);
static void (*nl_remove)(const char *);
+static int sock_fd;
+static struct sockaddr_nl sock_nl;
+
int
getifssid(const char *ifname, char *ssid)
{
return retval;
}
-int
-open_link_socket(void)
+static int
+_open_link_socket(struct sockaddr_nl *nl)
{
int fd;
- struct sockaddr_nl nl;
if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
return -1;
- memset(&nl, 0, sizeof(nl));
- nl.nl_family = AF_NETLINK;
- nl.nl_groups = RTMGRP_LINK;
- if (bind(fd, (struct sockaddr *)&nl, sizeof(nl)) == -1)
+ nl->nl_family = AF_NETLINK;
+ if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1)
return -1;
set_cloexec(fd);
return fd;
}
+int
+init_socket(void)
+{
+ sock_fd = _open_link_socket(&sock_nl);
+ return sock_fd;
+}
+
+int
+open_link_socket(void)
+{
+ struct sockaddr_nl snl;
+
+ memset(&snl, 0, sizeof(snl));
+ snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE;
+ return _open_link_socket(&snl);
+}
+
static int
get_netlink(int fd, int flags,
int (*callback)(struct nlmsghdr *))
return -1;
}
+static int
+link_delroute(struct nlmsghdr *nlm)
+{
+ int len, idx, metric;
+ struct rtattr *rta;
+ struct rtmsg *rtm;
+ struct rt rt;
+ char ifn[IF_NAMESIZE + 1];
+
+ len = nlm->nlmsg_len - sizeof(*nlm);
+ if ((size_t)len < sizeof(*rtm)) {
+ errno = EBADMSG;
+ return -1;
+ }
+ rtm = NLMSG_DATA(nlm);
+ if (rtm->rtm_type != RTN_UNICAST ||
+ rtm->rtm_table != RT_TABLE_MAIN ||
+ rtm->rtm_family != AF_INET ||
+ nlm->nlmsg_pid == (uint32_t)getpid())
+ return 1;
+ rta = (struct rtattr *) ((char *)rtm + NLMSG_ALIGN(sizeof(*rtm)));
+ len = NLMSG_PAYLOAD(nlm, sizeof(*rtm));
+ rt.iface = NULL;
+ rt.next = NULL;
+ metric = 0;
+ while (RTA_OK(rta, len)) {
+ switch (rta->rta_type) {
+ case RTA_DST:
+ memcpy(&rt.dest.s_addr, RTA_DATA(rta),
+ sizeof(rt.dest.s_addr));
+ break;
+ case RTA_GATEWAY:
+ memcpy(&rt.gate.s_addr, RTA_DATA(rta),
+ sizeof(rt.gate.s_addr));
+ break;
+ case RTA_OIF:
+ idx = *(int *)RTA_DATA(rta);
+ if (if_indextoname(idx, ifn))
+ rt.iface = find_interface(ifn);
+ break;
+ case RTA_PRIORITY:
+ metric = *(int *)RTA_DATA(rta);
+ break;
+ }
+ rta = RTA_NEXT(rta, len);
+ }
+ if (rt.iface != NULL) {
+ if (metric == rt.iface->metric) {
+ if (rt.dest.s_addr == INADDR_BROADCAST)
+ rt.dest.s_addr = INADDR_ANY;
+ inet_cidrtoaddr(rtm->rtm_dst_len, &rt.net);
+ route_deleted(&rt);
+ }
+ }
+ return 1;
+}
+
static int
link_netlink(struct nlmsghdr *nlm)
{
struct ifinfomsg *ifi;
char ifn[IF_NAMESIZE + 1];
+ if (nlm->nlmsg_type == RTM_DELROUTE)
+ return link_delroute(nlm);
+
if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK)
return 0;
len = nlm->nlmsg_len - sizeof(*nlm);
static int
send_netlink(struct nlmsghdr *hdr)
{
- int fd, r;
- struct sockaddr_nl nl;
+ int r;
struct iovec iov;
struct msghdr msg;
static unsigned int seq;
- if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
- return -1;
- memset(&nl, 0, sizeof(nl));
- nl.nl_family = AF_NETLINK;
- if (bind(fd, (struct sockaddr *)&nl, sizeof(nl)) == -1) {
- close(fd);
- return -1;
- }
memset(&iov, 0, sizeof(iov));
iov.iov_base = hdr;
iov.iov_len = hdr->nlmsg_len;
memset(&msg, 0, sizeof(msg));
- msg.msg_name = &nl;
- msg.msg_namelen = sizeof(nl);
+ msg.msg_name = &sock_nl;
+ msg.msg_namelen = sizeof(sock_nl);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
/* Request a reply */
hdr->nlmsg_flags |= NLM_F_ACK;
hdr->nlmsg_seq = ++seq;
- if (sendmsg(fd, &msg, 0) != -1)
- r = get_netlink(fd, 0, &err_netlink);
+ if (sendmsg(sock_fd, &msg, 0) != -1)
+ r = get_netlink(sock_fd, 0, &err_netlink);
else
r = -1;
- close(fd);
return r;
}
const void *, ssize_t);
ssize_t get_raw_packet(struct interface *, int, void *, ssize_t);
+int init_socket(void);
int open_link_socket(void);
int manage_link(int,
void (*)(const char *),