/// Runs as a thread and handles each packet. It is responsible /// for reading each packet in its entirety from the input pipe, /// filtering it, and then writing it to the output pipe. The /// single void* parameter matches what is expected by pthread. /// @param args An IpPktFilter /// @return Always NULL static void* FilterThread(void* args) { // TODO: implement function IpPktFilter filter = (IpPktFilter) args; unsigned char buffer[MAX_PACKET_LENGTH]; int pktLength; int charsRead; bool isFinished = true; bool isSuccess; OpenPipes(); while(Mode){ if (feof(InPipe)==0){ if (isFinished ){ isSuccess = fread(&pktLength, sizeof(int), 1, InPipe); if (isSuccess){}; } isFinished = ReadPacket(buffer, &charsRead, &pktLength); bool isBlocked = false; if (Mode == MODE_BLOCK_ALL){ isBlocked = true; } else if (Mode == MODE_ALLOW_ALL){ isBlocked = false; } else if (Mode == MODE_FILTER){ isBlocked = ! FilterPacket(filter, buffer); } else if (Mode == 0){ break; } if (!isBlocked){ fwrite(&pktLength, sizeof(int), 1, OutPipe); fwrite(buffer, sizeof(unsigned char), pktLength, OutPipe); fflush(OutPipe); } pktLength -= charsRead; } } fclose(InPipe); fclose(OutPipe); return NULL; }
/* * Read-side put procedure. It's responsible for applying the * packet filter and passing upstream message on or discarding it * depending upon the results. * * Upstream messages can start with zero or more M_PROTO mblks * which are skipped over before executing the packet filter * on any remaining M_DATA mblks. */ static void pfrput(queue_t *rq, mblk_t *mp) { struct epacketfilt *pfp = (struct epacketfilt *)rq->q_ptr; mblk_t *mbp, *mpp; struct packdesc pd; int need; ASSERT(pfp); switch (DB_TYPE(mp)) { case M_PROTO: case M_DATA: /* * Skip over protocol information and find the start * of the message body, saving the overall message * start in mpp. */ for (mpp = mp; mp && (DB_TYPE(mp) == M_PROTO); mp = mp->b_cont) ; /* * Null body (exclusive of M_PROTO blocks) ==> accept. * Note that a null body is not the same as an empty body. */ if (mp == NULL) { putnext(rq, mpp); break; } /* * Pull the packet up to the length required by * the filter. Note that doing so destroys sharing * relationships, which is unfortunate, since the * results of pulling up here are likely to be useful * for shared messages applied to a filter on a sibling * stream. * * Most packet sources will provide the packet in two * logical pieces: an initial header in a single mblk, * and a body in a sequence of mblks hooked to the * header. We're prepared to deal with variant forms, * but in any case, the pullup applies only to the body * part. */ mbp = mp->b_cont; need = pfp->pf_PByteLen; if (mbp && (MBLKL(mbp) < need)) { int len = msgdsize(mbp); /* XXX discard silently on pullupmsg failure */ if (pullupmsg(mbp, MIN(need, len)) == 0) { freemsg(mpp); break; } } /* * Misalignment (not on short boundary) ==> reject. */ if (((uintptr_t)mp->b_rptr & (sizeof (ushort_t) - 1)) || (mbp != NULL && ((uintptr_t)mbp->b_rptr & (sizeof (ushort_t) - 1)))) { freemsg(mpp); break; } /* * These assignments are distasteful, but necessary, * since the packet filter wants to work in terms of * shorts. Odd bytes at the end of header or data can't * participate in the filtering operation. */ pd.pd_hdr = (ushort_t *)mp->b_rptr; pd.pd_hdrlen = (mp->b_wptr - mp->b_rptr) / sizeof (ushort_t); if (mbp) { pd.pd_body = (ushort_t *)mbp->b_rptr; pd.pd_bodylen = (mbp->b_wptr - mbp->b_rptr) / sizeof (ushort_t); } else { pd.pd_body = NULL; pd.pd_bodylen = 0; } /* * Apply the filter. */ if (FilterPacket(&pd, pfp)) putnext(rq, mpp); else freemsg(mpp); break; default: putnext(rq, mp); break; } }