int if_opensockets_os(struct dhcpcd_ctx *ctx) { struct priv *priv; struct sockaddr_nl snl; socklen_t len; #ifdef NETLINK_BROADCAST_ERROR int on = 1; #endif /* Open the link socket first so it gets pid() for the socket. * Then open our persistent route socket so we get a unique * pid that doesn't clash with a process id for after we fork. */ memset(&snl, 0, sizeof(snl)); snl.nl_groups = RTMGRP_LINK; #ifdef INET snl.nl_groups |= RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR; #endif #ifdef INET6 snl.nl_groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_NEIGH; #endif ctx->link_fd = _open_link_socket(&snl, NETLINK_ROUTE); if (ctx->link_fd == -1) return -1; #ifdef NETLINK_BROADCAST_ERROR setsockopt(ctx->link_fd, SOL_NETLINK, NETLINK_BROADCAST_ERROR, &on, sizeof(on)); #endif if ((priv = calloc(1, sizeof(*priv))) == NULL) return -1; ctx->priv = priv; memset(&snl, 0, sizeof(snl)); priv->route_fd = _open_link_socket(&snl, NETLINK_ROUTE); if (priv->route_fd == -1) return -1; len = sizeof(snl); if (getsockname(priv->route_fd, (struct sockaddr *)&snl, &len) == -1) return -1; priv->route_pid = snl.nl_pid; return 0; }
int open_sockets(void) { if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return -1; set_cloexec(socket_afnet); sock_fd = _open_link_socket(&sock_nl); set_cloexec(sock_fd); return sock_fd; }
int open_link_socket(void) { struct sockaddr_nl snl; memset(&snl, 0, sizeof(snl)); snl.nl_groups = RTMGRP_LINK; #ifdef INET snl.nl_groups |= RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR; #endif #ifdef INET6 snl.nl_groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR; #endif return _open_link_socket(&snl); }
static int send_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp, int protocol, struct nlmsghdr *hdr, int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *)) { int s, r; struct sockaddr_nl snl; struct iovec iov[1]; struct msghdr msg; memset(&snl, 0, sizeof(snl)); snl.nl_family = AF_NETLINK; if (protocol == NETLINK_ROUTE) { struct priv *priv; priv = (struct priv *)ctx->priv; s = priv->route_fd; } else { if ((s = _open_link_socket(&snl, protocol)) == -1) return -1; } memset(&msg, 0, sizeof(msg)); msg.msg_name = &snl; msg.msg_namelen = sizeof(snl); memset(&iov, 0, sizeof(iov)); iov[0].iov_base = hdr; iov[0].iov_len = hdr->nlmsg_len; msg.msg_iov = iov; msg.msg_iovlen = 1; /* Request a reply */ hdr->nlmsg_flags |= NLM_F_ACK; hdr->nlmsg_seq = (uint32_t)++ctx->seq; if (sendmsg(s, &msg, 0) != -1) { struct priv *priv; priv = (struct priv *)ctx->priv; r = get_netlink(ctx, priv->sndrcv_iov, ifp, s, 0, callback); } else r = -1; if (protocol != NETLINK_ROUTE) close(s); return r; }