+ /* validate the address */
+ if (flow_divert_is_sockaddr_valid((struct sockaddr *)&remote_address)) {
+ got_remote_sa = TRUE;
+ }
+ offset += (sizeof(uint8_t) + sizeof(uint32_t) + val_size);
+ }
+ }
+
+ data_size = (mbuf_pkthdr_len(packet) - offset);
+
+ FDLOG(LOG_DEBUG, fd_cb, "received %lu bytes of data", data_size);
+
+ error = mbuf_split(packet, offset, MBUF_DONTWAIT, &data);
+ if (error || data == NULL) {
+ FDLOG(LOG_ERR, fd_cb, "mbuf_split failed: %d", error);
+ } else {
+ if (flow_divert_check_no_cellular(fd_cb) ||
+ flow_divert_check_no_expensive(fd_cb))
+ {
+ flow_divert_update_closed_state(fd_cb, SHUT_RDWR, TRUE);
+ flow_divert_send_close(fd_cb, SHUT_RDWR);
+ flow_divert_disconnect_socket(fd_cb->so);
+ } else if (!(fd_cb->so->so_state & SS_CANTRCVMORE)) {
+ if (SOCK_TYPE(fd_cb->so) == SOCK_STREAM) {
+ if (sbappendstream(&fd_cb->so->so_rcv, data)) {
+ fd_cb->bytes_received += data_size;
+ flow_divert_add_data_statistics(fd_cb, data_size, FALSE);
+ fd_cb->sb_size = fd_cb->so->so_rcv.sb_cc;
+ sorwakeup(fd_cb->so);
+ data = NULL;
+ } else {
+ FDLOG0(LOG_ERR, fd_cb, "received data, but appendstream failed");
+ }
+ } else if (SOCK_TYPE(fd_cb->so) == SOCK_DGRAM) {
+ struct sockaddr *append_sa;
+ mbuf_t mctl;
+
+ if (got_remote_sa == TRUE) {
+ error = flow_divert_dup_addr(fd_cb->so->so_proto->pr_domain->dom_family,
+ (struct sockaddr *)&remote_address, &append_sa);
+ } else {
+ error = flow_divert_dup_addr(fd_cb->so->so_proto->pr_domain->dom_family,
+ fd_cb->remote_address, &append_sa);
+ }
+ if (error) {
+ FDLOG0(LOG_ERR, fd_cb, "failed to dup the socket address.");
+ }
+
+ mctl = flow_divert_get_control_mbuf(fd_cb);
+ if (sbappendaddr(&fd_cb->so->so_rcv, append_sa, data, mctl, NULL)) {
+ fd_cb->bytes_received += data_size;
+ flow_divert_add_data_statistics(fd_cb, data_size, FALSE);
+ fd_cb->sb_size = fd_cb->so->so_rcv.sb_cc;
+ sorwakeup(fd_cb->so);
+ data = NULL;
+ } else {
+ FDLOG0(LOG_ERR, fd_cb, "received data, but sbappendaddr failed");
+ }
+ if (!error) {
+ FREE(append_sa, M_TEMP);
+ }
+ }