diff options
Diffstat (limited to 'libsysutils')
-rw-r--r-- | libsysutils/Android.mk | 2 | ||||
-rw-r--r-- | libsysutils/EventLogTags.logtags | 4 | ||||
-rw-r--r-- | libsysutils/src/FrameworkListener.cpp | 8 | ||||
-rw-r--r-- | libsysutils/src/NetlinkEvent.cpp | 361 | ||||
-rw-r--r-- | libsysutils/src/NetlinkListener.cpp | 8 | ||||
-rw-r--r-- | libsysutils/src/SocketClient.cpp | 36 | ||||
-rw-r--r-- | libsysutils/src/SocketListener.cpp | 6 |
7 files changed, 296 insertions, 129 deletions
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk index 1451b0d0b..246f954cb 100644 --- a/libsysutils/Android.mk +++ b/libsysutils/Android.mk @@ -18,7 +18,7 @@ LOCAL_MODULE:= libsysutils LOCAL_C_INCLUDES := -LOCAL_CFLAGS := +LOCAL_CFLAGS := -Werror LOCAL_SHARED_LIBRARIES := libcutils liblog diff --git a/libsysutils/EventLogTags.logtags b/libsysutils/EventLogTags.logtags index 7aa5cadc8..713f8cd6b 100644 --- a/libsysutils/EventLogTags.logtags +++ b/libsysutils/EventLogTags.logtags @@ -1,5 +1,5 @@ # See system/core/logcat/event.logtags for a description of the format of this file. # FrameworkListener dispatchCommand overflow -78001 dispatchCommand_overflow -65537 netlink_failure (uid|1) +78001 exp_det_dispatchCommand_overflow +65537 exp_det_netlink_failure (uid|1) diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index 15f126b33..579ead991 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -39,6 +39,11 @@ FrameworkListener::FrameworkListener(const char *socketName) : init(socketName, false); } +FrameworkListener::FrameworkListener(int sock) : + SocketListener(sock, true) { + init(NULL, false); +} + void FrameworkListener::init(const char *socketName UNUSED, bool withSeq) { mCommands = new FrameworkCommandCollection(); errorRate = 0; @@ -98,7 +103,6 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { char *qlimit = tmp + sizeof(tmp) - 1; bool esc = false; bool quote = false; - int k; bool haveCmdNum = !mWithSeq; memset(argv, 0, sizeof(argv)); @@ -172,7 +176,7 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { goto overflow; argv[argc++] = strdup(tmp); #if 0 - for (k = 0; k < argc; k++) { + for (int k = 0; k < argc; k++) { SLOGD("arg[%d] = '%s'", k, argv[k]); } #endif diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp index 34f20160e..9d596ef55 100644 --- a/libsysutils/src/NetlinkEvent.cpp +++ b/libsysutils/src/NetlinkEvent.cpp @@ -29,6 +29,8 @@ #include <net/if.h> #include <linux/if.h> +#include <linux/if_addr.h> +#include <linux/if_link.h> #include <linux/netfilter/nfnetlink.h> #include <linux/netfilter_ipv4/ipt_ULOG.h> /* From kernel's net/netfilter/xt_quota2.c */ @@ -46,6 +48,8 @@ const int NetlinkEvent::NlActionLinkDown = 5; const int NetlinkEvent::NlActionAddressUpdated = 6; const int NetlinkEvent::NlActionAddressRemoved = 7; const int NetlinkEvent::NlActionRdnss = 8; +const int NetlinkEvent::NlActionRouteUpdated = 9; +const int NetlinkEvent::NlActionRouteRemoved = 10; NetlinkEvent::NetlinkEvent() { mAction = NlActionUnknown; @@ -78,38 +82,115 @@ void NetlinkEvent::dump() { } /* - * Parse a RTM_NEWADDR or RTM_DELADDR message. + * Returns the message name for a message in the NETLINK_ROUTE family, or NULL + * if parsing that message is not supported. + */ +static const char *rtMessageName(int type) { +#define NL_EVENT_RTM_NAME(rtm) case rtm: return #rtm; + switch (type) { + NL_EVENT_RTM_NAME(RTM_NEWLINK); + NL_EVENT_RTM_NAME(RTM_DELLINK); + NL_EVENT_RTM_NAME(RTM_NEWADDR); + NL_EVENT_RTM_NAME(RTM_DELADDR); + NL_EVENT_RTM_NAME(RTM_NEWROUTE); + NL_EVENT_RTM_NAME(RTM_DELROUTE); + NL_EVENT_RTM_NAME(RTM_NEWNDUSEROPT); + NL_EVENT_RTM_NAME(QLOG_NL_EVENT); + default: + return NULL; + } +#undef NL_EVENT_RTM_NAME +} + +/* + * Checks that a binary NETLINK_ROUTE message is long enough for a payload of + * size bytes. */ -bool NetlinkEvent::parseIfAddrMessage(int type, struct ifaddrmsg *ifaddr, - int rtasize) { +static bool checkRtNetlinkLength(const struct nlmsghdr *nh, size_t size) { + if (nh->nlmsg_len < NLMSG_LENGTH(size)) { + SLOGE("Got a short %s message\n", rtMessageName(nh->nlmsg_type)); + return false; + } + return true; +} + +/* + * Utility function to log errors. + */ +static bool maybeLogDuplicateAttribute(bool isDup, + const char *attributeName, + const char *messageName) { + if (isDup) { + SLOGE("Multiple %s attributes in %s, ignoring\n", attributeName, messageName); + return true; + } + return false; +} + +/* + * Parse a RTM_NEWLINK message. + */ +bool NetlinkEvent::parseIfInfoMessage(const struct nlmsghdr *nh) { + struct ifinfomsg *ifi = (struct ifinfomsg *) NLMSG_DATA(nh); + if (!checkRtNetlinkLength(nh, sizeof(*ifi))) + return false; + + if ((ifi->ifi_flags & IFF_LOOPBACK) != 0) { + return false; + } + + int len = IFLA_PAYLOAD(nh); struct rtattr *rta; + for (rta = IFLA_RTA(ifi); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { + switch(rta->rta_type) { + case IFLA_IFNAME: + asprintf(&mParams[0], "INTERFACE=%s", (char *) RTA_DATA(rta)); + mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? NlActionLinkUp : + NlActionLinkDown; + mSubsystem = strdup("net"); + return true; + } + } + + return false; +} + +/* + * Parse a RTM_NEWADDR or RTM_DELADDR message. + */ +bool NetlinkEvent::parseIfAddrMessage(const struct nlmsghdr *nh) { + struct ifaddrmsg *ifaddr = (struct ifaddrmsg *) NLMSG_DATA(nh); struct ifa_cacheinfo *cacheinfo = NULL; char addrstr[INET6_ADDRSTRLEN] = ""; + char ifname[IFNAMSIZ]; + + if (!checkRtNetlinkLength(nh, sizeof(*ifaddr))) + return false; // Sanity check. + int type = nh->nlmsg_type; if (type != RTM_NEWADDR && type != RTM_DELADDR) { SLOGE("parseIfAddrMessage on incorrect message type 0x%x\n", type); return false; } // For log messages. - const char *msgtype = (type == RTM_NEWADDR) ? "RTM_NEWADDR" : "RTM_DELADDR"; + const char *msgtype = rtMessageName(type); - for (rta = IFA_RTA(ifaddr); RTA_OK(rta, rtasize); - rta = RTA_NEXT(rta, rtasize)) { + struct rtattr *rta; + int len = IFA_PAYLOAD(nh); + for (rta = IFA_RTA(ifaddr); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { if (rta->rta_type == IFA_ADDRESS) { // Only look at the first address, because we only support notifying // one change at a time. - if (*addrstr != '\0') { - SLOGE("Multiple IFA_ADDRESSes in %s, ignoring\n", msgtype); + if (maybeLogDuplicateAttribute(*addrstr != '\0', "IFA_ADDRESS", msgtype)) continue; - } // Convert the IP address to a string. if (ifaddr->ifa_family == AF_INET) { struct in_addr *addr4 = (struct in_addr *) RTA_DATA(rta); if (RTA_PAYLOAD(rta) < sizeof(*addr4)) { - SLOGE("Short IPv4 address (%d bytes) in %s", + SLOGE("Short IPv4 address (%zu bytes) in %s", RTA_PAYLOAD(rta), msgtype); continue; } @@ -117,7 +198,7 @@ bool NetlinkEvent::parseIfAddrMessage(int type, struct ifaddrmsg *ifaddr, } else if (ifaddr->ifa_family == AF_INET6) { struct in6_addr *addr6 = (struct in6_addr *) RTA_DATA(rta); if (RTA_PAYLOAD(rta) < sizeof(*addr6)) { - SLOGE("Short IPv6 address (%d bytes) in %s", + SLOGE("Short IPv6 address (%zu bytes) in %s", RTA_PAYLOAD(rta), msgtype); continue; } @@ -128,40 +209,23 @@ bool NetlinkEvent::parseIfAddrMessage(int type, struct ifaddrmsg *ifaddr, } // Find the interface name. - char ifname[IFNAMSIZ + 1]; if (!if_indextoname(ifaddr->ifa_index, ifname)) { SLOGE("Unknown ifindex %d in %s", ifaddr->ifa_index, msgtype); return false; } - // Fill in interface information. - mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated : - NlActionAddressRemoved; - mSubsystem = strdup("net"); - asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr, - ifaddr->ifa_prefixlen); - asprintf(&mParams[1], "INTERFACE=%s", ifname); - asprintf(&mParams[2], "FLAGS=%u", ifaddr->ifa_flags); - asprintf(&mParams[3], "SCOPE=%u", ifaddr->ifa_scope); } else if (rta->rta_type == IFA_CACHEINFO) { // Address lifetime information. - if (cacheinfo) { - // We only support one address. - SLOGE("Multiple IFA_CACHEINFOs in %s, ignoring\n", msgtype); + if (maybeLogDuplicateAttribute(cacheinfo, "IFA_CACHEINFO", msgtype)) continue; - } if (RTA_PAYLOAD(rta) < sizeof(*cacheinfo)) { - SLOGE("Short IFA_CACHEINFO (%d vs. %d bytes) in %s", + SLOGE("Short IFA_CACHEINFO (%zu vs. %zu bytes) in %s", RTA_PAYLOAD(rta), sizeof(cacheinfo), msgtype); continue; } cacheinfo = (struct ifa_cacheinfo *) RTA_DATA(rta); - asprintf(&mParams[4], "PREFERRED=%u", cacheinfo->ifa_prefered); - asprintf(&mParams[5], "VALID=%u", cacheinfo->ifa_valid); - asprintf(&mParams[6], "CSTAMP=%u", cacheinfo->cstamp); - asprintf(&mParams[7], "TSTAMP=%u", cacheinfo->tstamp); } } @@ -170,15 +234,145 @@ bool NetlinkEvent::parseIfAddrMessage(int type, struct ifaddrmsg *ifaddr, return false; } + // Fill in netlink event information. + mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated : + NlActionAddressRemoved; + mSubsystem = strdup("net"); + asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr, + ifaddr->ifa_prefixlen); + asprintf(&mParams[1], "INTERFACE=%s", ifname); + asprintf(&mParams[2], "FLAGS=%u", ifaddr->ifa_flags); + asprintf(&mParams[3], "SCOPE=%u", ifaddr->ifa_scope); + + if (cacheinfo) { + asprintf(&mParams[4], "PREFERRED=%u", cacheinfo->ifa_prefered); + asprintf(&mParams[5], "VALID=%u", cacheinfo->ifa_valid); + asprintf(&mParams[6], "CSTAMP=%u", cacheinfo->cstamp); + asprintf(&mParams[7], "TSTAMP=%u", cacheinfo->tstamp); + } + + return true; +} + +/* + * Parse a QLOG_NL_EVENT message. + */ +bool NetlinkEvent::parseUlogPacketMessage(const struct nlmsghdr *nh) { + const char *devname; + ulog_packet_msg_t *pm = (ulog_packet_msg_t *) NLMSG_DATA(nh); + if (!checkRtNetlinkLength(nh, sizeof(*pm))) + return false; + + devname = pm->indev_name[0] ? pm->indev_name : pm->outdev_name; + asprintf(&mParams[0], "ALERT_NAME=%s", pm->prefix); + asprintf(&mParams[1], "INTERFACE=%s", devname); + mSubsystem = strdup("qlog"); + mAction = NlActionChange; + return true; +} + +/* + * Parse a RTM_NEWROUTE or RTM_DELROUTE message. + */ +bool NetlinkEvent::parseRtMessage(const struct nlmsghdr *nh) { + uint8_t type = nh->nlmsg_type; + const char *msgname = rtMessageName(type); + + // Sanity check. + if (type != RTM_NEWROUTE && type != RTM_DELROUTE) { + SLOGE("%s: incorrect message type %d (%s)\n", __func__, type, msgname); + return false; + } + + struct rtmsg *rtm = (struct rtmsg *) NLMSG_DATA(nh); + if (!checkRtNetlinkLength(nh, sizeof(*rtm))) + return false; + + if (// Ignore static routes we've set up ourselves. + (rtm->rtm_protocol != RTPROT_KERNEL && + rtm->rtm_protocol != RTPROT_RA) || + // We're only interested in global unicast routes. + (rtm->rtm_scope != RT_SCOPE_UNIVERSE) || + (rtm->rtm_type != RTN_UNICAST) || + // We don't support source routing. + (rtm->rtm_src_len != 0) || + // Cloned routes aren't real routes. + (rtm->rtm_flags & RTM_F_CLONED)) { + return false; + } + + int family = rtm->rtm_family; + int prefixLength = rtm->rtm_dst_len; + + // Currently we only support: destination, (one) next hop, ifindex. + char dst[INET6_ADDRSTRLEN] = ""; + char gw[INET6_ADDRSTRLEN] = ""; + char dev[IFNAMSIZ] = ""; + + size_t len = RTM_PAYLOAD(nh); + struct rtattr *rta; + for (rta = RTM_RTA(rtm); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { + switch (rta->rta_type) { + case RTA_DST: + if (maybeLogDuplicateAttribute(*dst, "RTA_DST", msgname)) + continue; + if (!inet_ntop(family, RTA_DATA(rta), dst, sizeof(dst))) + return false; + continue; + case RTA_GATEWAY: + if (maybeLogDuplicateAttribute(*gw, "RTA_GATEWAY", msgname)) + continue; + if (!inet_ntop(family, RTA_DATA(rta), gw, sizeof(gw))) + return false; + continue; + case RTA_OIF: + if (maybeLogDuplicateAttribute(*dev, "RTA_OIF", msgname)) + continue; + if (!if_indextoname(* (int *) RTA_DATA(rta), dev)) + return false; + default: + continue; + } + } + + // If there's no RTA_DST attribute, then: + // - If the prefix length is zero, it's the default route. + // - If the prefix length is nonzero, there's something we don't understand. + // Ignore the event. + if (!*dst && !prefixLength) { + if (family == AF_INET) { + strncpy(dst, "0.0.0.0", sizeof(dst)); + } else if (family == AF_INET6) { + strncpy(dst, "::", sizeof(dst)); + } + } + + // A useful route must have a destination and at least either a gateway or + // an interface. + if (!*dst || (!*gw && !*dev)) + return false; + + // Fill in netlink event information. + mAction = (type == RTM_NEWROUTE) ? NlActionRouteUpdated : + NlActionRouteRemoved; + mSubsystem = strdup("net"); + asprintf(&mParams[0], "ROUTE=%s/%d", dst, prefixLength); + asprintf(&mParams[1], "GATEWAY=%s", (*gw) ? gw : ""); + asprintf(&mParams[2], "INTERFACE=%s", (*dev) ? dev : ""); + return true; } /* -<<<<<<< HEAD * Parse a RTM_NEWNDUSEROPT message. */ -bool NetlinkEvent::parseNdUserOptMessage(struct nduseroptmsg *msg, int len) { +bool NetlinkEvent::parseNdUserOptMessage(const struct nlmsghdr *nh) { + struct nduseroptmsg *msg = (struct nduseroptmsg *) NLMSG_DATA(nh); + if (!checkRtNetlinkLength(nh, sizeof(*msg))) + return false; + // Check the length is valid. + int len = NLMSG_PAYLOAD(nh, sizeof(*msg)); if (msg->nduseropt_opts_len > len) { SLOGE("RTM_NEWNDUSEROPT invalid length %d > %d\n", msg->nduseropt_opts_len, len); @@ -201,7 +395,7 @@ bool NetlinkEvent::parseNdUserOptMessage(struct nduseroptmsg *msg, int len) { } // Find the interface name. - char ifname[IFNAMSIZ + 1]; + char ifname[IFNAMSIZ]; if (!if_indextoname(msg->nduseropt_ifindex, ifname)) { SLOGE("RTM_NEWNDUSEROPT on unknown ifindex %d\n", msg->nduseropt_ifindex); @@ -274,6 +468,14 @@ bool NetlinkEvent::parseNdUserOptMessage(struct nduseroptmsg *msg, int len) { /* * Parse a binary message from a NETLINK_ROUTE netlink socket. + * + * Note that this function can only parse one message, because the message's + * content has to be stored in the class's member variables (mAction, + * mSubsystem, etc.). Invalid or unrecognized messages are skipped, but if + * there are multiple valid messages in the buffer, only the first one will be + * returned. + * + * TODO: consider only ever looking at the first message. */ bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) { const struct nlmsghdr *nh; @@ -282,93 +484,37 @@ bool NetlinkEvent::parseBinaryNetlinkMessage(char *buffer, int size) { NLMSG_OK(nh, (unsigned) size) && (nh->nlmsg_type != NLMSG_DONE); nh = NLMSG_NEXT(nh, size)) { - if (nh->nlmsg_type == RTM_NEWLINK) { - int len = nh->nlmsg_len - sizeof(*nh); - struct ifinfomsg *ifi; - - if (sizeof(*ifi) > (size_t) len) { - SLOGE("Got a short RTM_NEWLINK message\n"); - continue; - } - - ifi = (ifinfomsg *)NLMSG_DATA(nh); - if ((ifi->ifi_flags & IFF_LOOPBACK) != 0) { - continue; - } - - struct rtattr *rta = (struct rtattr *) - ((char *) ifi + NLMSG_ALIGN(sizeof(*ifi))); - len = NLMSG_PAYLOAD(nh, sizeof(*ifi)); - - while(RTA_OK(rta, len)) { - switch(rta->rta_type) { - case IFLA_IFNAME: - char buffer[16 + IFNAMSIZ]; - snprintf(buffer, sizeof(buffer), "INTERFACE=%s", - (char *) RTA_DATA(rta)); - mParams[0] = strdup(buffer); - mAction = (ifi->ifi_flags & IFF_LOWER_UP) ? - NlActionLinkUp : NlActionLinkDown; - mSubsystem = strdup("net"); - break; - } + if (!rtMessageName(nh->nlmsg_type)) { + SLOGD("Unexpected netlink message type %d\n", nh->nlmsg_type); + continue; + } - rta = RTA_NEXT(rta, len); - } + if (nh->nlmsg_type == RTM_NEWLINK) { + if (parseIfInfoMessage(nh)) + return true; } else if (nh->nlmsg_type == QLOG_NL_EVENT) { - char *devname; - ulog_packet_msg_t *pm; - size_t len = nh->nlmsg_len - sizeof(*nh); - if (sizeof(*pm) > len) { - SLOGE("Got a short QLOG message\n"); - continue; - } - pm = (ulog_packet_msg_t *)NLMSG_DATA(nh); - devname = pm->indev_name[0] ? pm->indev_name : pm->outdev_name; - asprintf(&mParams[0], "ALERT_NAME=%s", pm->prefix); - asprintf(&mParams[1], "INTERFACE=%s", devname); - mSubsystem = strdup("qlog"); - mAction = NlActionChange; + if (parseUlogPacketMessage(nh)) + return true; } else if (nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR) { - int len = nh->nlmsg_len - sizeof(*nh); - struct ifaddrmsg *ifa; - - if (sizeof(*ifa) > (size_t) len) { - SLOGE("Got a short RTM_xxxADDR message\n"); - continue; - } + if (parseIfAddrMessage(nh)) + return true; - ifa = (ifaddrmsg *)NLMSG_DATA(nh); - size_t rtasize = IFA_PAYLOAD(nh); - if (!parseIfAddrMessage(nh->nlmsg_type, ifa, rtasize)) { - continue; - } + } else if (nh->nlmsg_type == RTM_NEWROUTE || + nh->nlmsg_type == RTM_DELROUTE) { + if (parseRtMessage(nh)) + return true; } else if (nh->nlmsg_type == RTM_NEWNDUSEROPT) { - int len = nh->nlmsg_len - sizeof(*nh); - struct nduseroptmsg *ndmsg = (struct nduseroptmsg *) NLMSG_DATA(nh); - - if (sizeof(*ndmsg) > (size_t) len) { - SLOGE("Got a short RTM_NEWNDUSEROPT message\n"); - continue; - } + if (parseNdUserOptMessage(nh)) + return true; - size_t optsize = NLMSG_PAYLOAD(nh, sizeof(*ndmsg)); - if (!parseNdUserOptMessage(ndmsg, optsize)) { - continue; - } - - - } else { - SLOGD("Unexpected netlink message. type=0x%x\n", - nh->nlmsg_type); } } - return true; + return false; } /* If the string between 'str' and 'end' begins with 'prefixlen' characters @@ -399,7 +545,6 @@ bool NetlinkEvent::parseAsciiNetlinkMessage(char *buffer, int size) { const char *s = buffer; const char *end; int param_idx = 0; - int i; int first = 1; if (size == 0) diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp index 9c447ca76..81c5cc239 100644 --- a/libsysutils/src/NetlinkListener.cpp +++ b/libsysutils/src/NetlinkListener.cpp @@ -57,10 +57,12 @@ bool NetlinkListener::onDataAvailable(SocketClient *cli) } NetlinkEvent *evt = new NetlinkEvent(); - if (!evt->decode(mBuffer, count, mFormat)) { - SLOGE("Error decoding NetlinkEvent"); - } else { + if (evt->decode(mBuffer, count, mFormat)) { onEvent(evt); + } else if (mFormat != NETLINK_FORMAT_BINARY) { + // Don't complain if parseBinaryNetlinkMessage returns false. That can + // just mean that the buffer contained no messages we're interested in. + SLOGE("Error decoding NetlinkEvent"); } delete evt; diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp index 3625d936c..d3ce8f5a8 100644 --- a/libsysutils/src/SocketClient.cpp +++ b/libsysutils/src/SocketClient.cpp @@ -1,10 +1,11 @@ #include <alloca.h> #include <errno.h> -#include <sys/socket.h> -#include <sys/types.h> #include <pthread.h> +#include <signal.h> #include <string.h> #include <arpa/inet.h> +#include <sys/socket.h> +#include <sys/types.h> #define LOG_TAG "SocketClient" #include <cutils/log.h> @@ -43,8 +44,7 @@ void SocketClient::init(int socket, bool owned, bool useCmdNum) { } } -SocketClient::~SocketClient() -{ +SocketClient::~SocketClient() { if (mSocketOwned) { close(mSocket); } @@ -180,10 +180,19 @@ int SocketClient::sendDataLockedv(struct iovec *iov, int iovcnt) { return 0; } + int ret = 0; + int e = 0; // SLOGW and sigaction are not inert regarding errno int current = 0; + struct sigaction new_action, old_action; + memset(&new_action, 0, sizeof(new_action)); + new_action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &new_action, &old_action); + for (;;) { - ssize_t rc = writev(mSocket, iov + current, iovcnt - current); + ssize_t rc = TEMP_FAILURE_RETRY( + writev(mSocket, iov + current, iovcnt - current)); + if (rc > 0) { size_t written = rc; while ((current < iovcnt) && (written >= iov[current].iov_len)) { @@ -198,18 +207,21 @@ int SocketClient::sendDataLockedv(struct iovec *iov, int iovcnt) { continue; } - if (rc < 0 && errno == EINTR) - continue; - if (rc == 0) { + e = EIO; SLOGW("0 length write :("); - errno = EIO; } else { - SLOGW("write error (%s)", strerror(errno)); + e = errno; + SLOGW("write error (%s)", strerror(e)); } - return -1; + ret = -1; + break; } - return 0; + + sigaction(SIGPIPE, &old_action, &new_action); + + errno = e; + return ret; } void SocketClient::incRef() { diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp index 5c752066c..527a6a0a3 100644 --- a/libsysutils/src/SocketListener.cpp +++ b/libsysutils/src/SocketListener.cpp @@ -70,6 +70,10 @@ SocketListener::~SocketListener() { } int SocketListener::startListener() { + return startListener(4); +} + +int SocketListener::startListener(int backlog) { if (!mSocketName && mSock == -1) { SLOGE("Failed to start unbound listener"); @@ -84,7 +88,7 @@ int SocketListener::startListener() { SLOGV("got mSock = %d for %s", mSock, mSocketName); } - if (mListen && listen(mSock, 4) < 0) { + if (mListen && listen(mSock, backlog) < 0) { SLOGE("Unable to listen on socket (%s)", strerror(errno)); return -1; } else if (!mListen) |