diff options
Diffstat (limited to 'rpcapd/daemon.c')
-rw-r--r-- | rpcapd/daemon.c | 75 |
1 files changed, 46 insertions, 29 deletions
diff --git a/rpcapd/daemon.c b/rpcapd/daemon.c index 620dec31..362f4b9b 100644 --- a/rpcapd/daemon.c +++ b/rpcapd/daemon.c @@ -375,7 +375,7 @@ daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients, // Immediate EOF goto end; } - plen = (tls_header.length_hi << 8) | tls_header.length_lo; + plen = (tls_header.length_hi << 8U) | tls_header.length_lo; // Discard the rest of the message. if (rpcapd_discard(sockctrl, NULL, plen) == -1) @@ -1602,7 +1602,6 @@ daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen) pcap_if_t *alldevs = NULL; // pointer to the header of the interface chain pcap_if_t *d; // temp pointer needed to scan the interface chain struct pcap_addr *address; // pcap structure that keeps a network address of an interface - struct rpcap_findalldevs_if *findalldevs_if;// rpcap structure that packet all the data of an interface together uint32 replylen; // length of reply payload uint16 nif = 0; // counts the number of interface listed @@ -1703,13 +1702,17 @@ daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen) { uint16 lname, ldescr; - findalldevs_if = (struct rpcap_findalldevs_if *) &sendbuf[sendbufidx]; - - if (sock_bufferize(NULL, sizeof(struct rpcap_findalldevs_if), NULL, - &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1) - goto error; - - memset(findalldevs_if, 0, sizeof(struct rpcap_findalldevs_if)); + // Note: the findalldevs_if entries are *not* neatly + // aligned on 4-byte boundaries, because they're + // preceded by strings that aren't padded to 4-byte + // boundaries, so we cannot just cast output buffer + // boundaries to struct rpcap_findalldevs_if pointers + // and store into them - we must fill in a structure and + // then copy the structure to the buffer, as not all + // systems support unaligned access (some, such as + // SPARC, crash; others, such as Arm, may just ignore + // the lower-order bits). + struct rpcap_findalldevs_if findalldevs_if; /* * We've already established that the string lengths @@ -1724,10 +1727,11 @@ daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen) else lname = 0; - findalldevs_if->desclen = htons(ldescr); - findalldevs_if->namelen = htons(lname); - findalldevs_if->flags = htonl(d->flags); + findalldevs_if.desclen = htons(ldescr); + findalldevs_if.namelen = htons(lname); + findalldevs_if.flags = htonl(d->flags); + uint16_t naddrs = 0; for (address = d->addresses; address != NULL; address = address->next) { /* @@ -1739,14 +1743,20 @@ daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen) #ifdef AF_INET6 case AF_INET6: #endif - findalldevs_if->naddr++; + naddrs++; break; default: break; } } - findalldevs_if->naddr = htons(findalldevs_if->naddr); + findalldevs_if.naddr = htons(naddrs); + findalldevs_if.dummy = 0; + + if (sock_bufferize(&findalldevs_if, sizeof(struct rpcap_findalldevs_if), sendbuf, + &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf, + PCAP_ERRBUF_SIZE) == -1) + goto error; if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf, @@ -2337,7 +2347,7 @@ daemon_unpackapplyfilter(SOCKET sockctrl, SSL *ctrl_ssl, struct session *session if (bf_prog.bf_len > RPCAP_BPF_MAXINSNS) { snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, - "Filter program is larger than the maximum size of %u instructions", + "Filter program is larger than the maximum size of %d instructions", RPCAP_BPF_MAXINSNS); return -2; } @@ -2421,7 +2431,7 @@ daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars, // A response is needed, otherwise the other host does not know that everything went well rpcap_createhdr(&header, ver, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0); - if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE)) + if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE)) { // That failed; log a message and give up. rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf); @@ -2818,19 +2828,25 @@ daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *socka if (sockaddrin == NULL) return; // Warning: we support only AF_INET and AF_INET6 + // + // Note: as noted above, the output structures are not + // neatly aligned on 4-byte boundaries, so we must fill + // in an aligned structure and then copy it to the output + // buffer with memcpy(). switch (sockaddrin->ss_family) { case AF_INET: { struct sockaddr_in *sockaddrin_ipv4; - struct rpcap_sockaddr_in *sockaddrout_ipv4; + struct rpcap_sockaddr_in sockaddrout_ipv4; sockaddrin_ipv4 = (struct sockaddr_in *) sockaddrin; - sockaddrout_ipv4 = (struct rpcap_sockaddr_in *) sockaddrout; - sockaddrout_ipv4->family = htons(RPCAP_AF_INET); - sockaddrout_ipv4->port = htons(sockaddrin_ipv4->sin_port); - memcpy(&sockaddrout_ipv4->addr, &sockaddrin_ipv4->sin_addr, sizeof(sockaddrout_ipv4->addr)); - memset(sockaddrout_ipv4->zero, 0, sizeof(sockaddrout_ipv4->zero)); + + sockaddrout_ipv4.family = htons(RPCAP_AF_INET); + sockaddrout_ipv4.port = htons(sockaddrin_ipv4->sin_port); + memcpy(&sockaddrout_ipv4.addr, &sockaddrin_ipv4->sin_addr, sizeof(sockaddrout_ipv4.addr)); + memset(sockaddrout_ipv4.zero, 0, sizeof(sockaddrout_ipv4.zero)); + memcpy(sockaddrout, &sockaddrout_ipv4, sizeof(struct rpcap_sockaddr_in)); break; } @@ -2838,15 +2854,16 @@ daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *socka case AF_INET6: { struct sockaddr_in6 *sockaddrin_ipv6; - struct rpcap_sockaddr_in6 *sockaddrout_ipv6; + struct rpcap_sockaddr_in6 sockaddrout_ipv6; sockaddrin_ipv6 = (struct sockaddr_in6 *) sockaddrin; - sockaddrout_ipv6 = (struct rpcap_sockaddr_in6 *) sockaddrout; - sockaddrout_ipv6->family = htons(RPCAP_AF_INET6); - sockaddrout_ipv6->port = htons(sockaddrin_ipv6->sin6_port); - sockaddrout_ipv6->flowinfo = htonl(sockaddrin_ipv6->sin6_flowinfo); - memcpy(&sockaddrout_ipv6->addr, &sockaddrin_ipv6->sin6_addr, sizeof(sockaddrout_ipv6->addr)); - sockaddrout_ipv6->scope_id = htonl(sockaddrin_ipv6->sin6_scope_id); + + sockaddrout_ipv6.family = htons(RPCAP_AF_INET6); + sockaddrout_ipv6.port = htons(sockaddrin_ipv6->sin6_port); + sockaddrout_ipv6.flowinfo = htonl(sockaddrin_ipv6->sin6_flowinfo); + memcpy(&sockaddrout_ipv6.addr, &sockaddrin_ipv6->sin6_addr, sizeof(sockaddrout_ipv6.addr)); + sockaddrout_ipv6.scope_id = htonl(sockaddrin_ipv6->sin6_scope_id); + memcpy(sockaddrout, &sockaddrout_ipv6, sizeof(struct rpcap_sockaddr_in6)); break; } #endif |