Re: Macnetworkprog Digest, Vol 7, Issue 12
Re: Macnetworkprog Digest, Vol 7, Issue 12
- Subject: Re: Macnetworkprog Digest, Vol 7, Issue 12
- From: "Jay K. Robertson" <email@hidden>
- Date: Fri, 26 Mar 2010 08:45:18 -0400
Hi Brendan,
I appreciate the suggestion, but I have tried that as well. From my
understanding of the documentation, the return codes mean the
following:
- 0 means accept the packet, and ip_output() will continue processing.
- EJUSTRETURN means that the output hook function will take
responsibility for the packet and must free it when it is done;
ip_output() will stop processing.
- Any other value means that ip_output() will free the packet and stop
processing.
Regardless of whether I return 1 and let ip_output() do the
mbuf_freem(), or return EJUSTRETURN and do the mbuf_freem() myself, I
still see a memory leak that is proportional to the number of TCP
packets that are being processed.
Strangely, I stumbled onto a workaround yesterday. If I return
EJUSTRETURN and use mbuf_freem_list() instead of mbuf_freem(), the
memory leak does not occur. It is my understanding that
mbuf_freem_list() is not only supposed to free the current mbuf, it is
also supposed to walk the list of mbufs that the current mbuf is a
part of and free all of those as well. It would seem that this
behavior could break ip_output_list() completely, or at best, free
packets that have yet to be processed by ip_output_list(). However, I
haven't observed any adverse effects.
I would really like to know what the proper solution is, and if this
is the proper solution, why this is working.
Thanks,
- Jay
On Thu, Mar 25, 2010 at 7:33 PM, Brendan Creane <email@hidden> wrote:
> I have limited experience with IP filters, but for both socket filters and
> interface filters, your filter routine needs to return EJUSTRETURN when it
> consumes a packet, versus your current return value of 1. This seems to
> contradict the documentation for IP filters, but you may try that as an
> experiment.
> regards, Brendan
>>
>> Message: 1
>> Date: Wed, 24 Mar 2010 16:27:31 -0400
>> From: "Jay K. Robertson" <email@hidden>
>> Subject: Memory Leak Issue When Calling ipf_inject_output()
>> To: email@hidden
>> Message-ID:
>> <email@hidden>
>> Content-Type: text/plain; charset=ISO-8859-1
>>
>> Hello,
>>
>> I am building an NKE on OS X 10.5.8 that captures packets using an IP
>> filter on the outbound path. My ipf_output function is below. This
>> is a simple function that receives IP packets, creates a new mbuf,
>> copies the contents of the old mbuf into the new mbuf, and sends it
>> out via ipf_inject_output().
>>
>> This function works fine except for one major problem. While the
>> packets appear to be sent correctly, if I send TCP packets outbound
>> through this function, it appears to leak large amounts of memory.
>> For some reason, this only happens on TCP packets--I don't see similar
>> behavior when sending UDP packets. Unfortunately, I don't have
>> visibility into the kernel, so I can't really deduce why this is
>> happening.
>>
>> To generate traffic, I am using iperf. On the Mac running the NKE, I
>> am using the following command line:
>> iperf -c (server IP) -t 60 -i 10
>>
>> And, on the remote system, I am using the following command line:
>> iperf -s
>>
>> When I run this, the system is unable to allocate new mbufs, mbuf
>> tags, etc. after about 1 minute, and the system usually becomes
>> unusable. I am out of ideas on how to resolve this issue. Can
>> someone look at my code below and see what I could be doing wrong?
>> I'm not sure if I am completing all of the steps correctly for
>> capturing the packet, generating the checksums, injecting the packet,
>> etc., as the documentation is practically non-existent.
>>
>> Thanks,
>> - Jay
>>
>>
>> static errno_t filter_out(void *cookie, mbuf_t *data, ipf_pktopts *opts)
>> {
>> struct ip *iph = (struct ip *)mbuf_data(*data);
>> u_int8_t protocol = iph->ip_p;
>> int len = noths(iph->ip_len);
>> unsigned char buf[1500];
>> mbuf_t newdata = NULL;
>> errno_t err, ret = 0; // Accept packets by default
>> int direction = 1;
>>
>> // Filters packets using mbuf_tag_find()
>> if (0 == this->filter_match_tag(*data, direction)) {
>> MSG_INFO("Ignoring previously processed packet\n");
>> goto out;
>> }
>>
>> // Selectively filter packets that we aren't interested in
>> if (!filter_ipv4_filter(*data, protocol)) {
>> goto out;
>> }
>>
>> mbuf_outbound_finalize(*data, PF_INET, 0); // Finalize checksums
>> ret = 1; // Free original packet regardless of what happens
>>
>> if (0 != (err = mbuf_copydata(*data, 0, len, buf))) {
>> MSG_ERR("Unable to copy mbuf to buf, err=%d\n", err);
>> goto out;
>> }
>>
>> // At this point, it is intended that data will be sent to another
>> // thread for deferred processing. That thread will construct and
>> // inject a new mbuf through ipf_inject_output(). For now, we
>> // simulate the construction of the new mbuf.
>>
>> // Allocate the new packet
>> if (0 != mbuf_allocpacket(MBUF_DONTWAIT, 1500, NULL, &newdata)) {
>> MSG_ERR("Unable to allocate mbuf\n");
>> goto out;
>> // Copy data into new mbuf
>> } else if (0 != mbuf_copyback(newdata, 0, len, buf, MBUF_DONTWAIT)) {
>> MSG_ERR("Unable to copy buf to mbuf\n");
>> mbuf_freem(newdata);
>> goto out;
>> // Use mbuf_tag_allocate() to set tag so that we don't process this
>> twice
>> } else if (0 != this->filter_set_tag(newdata, direction)) {
>> MSG_ERR("Unable to set tag\n");
>> mbuf_freem(newdata);
>> goto out;
>> } else {
>> mbuf_clear_csum_requested(newdata);
>> if (0 != (err = ipf_inject_output(newdata, NULL, NULL))) {
>> MSG_ERR("ipf_inject_output() failed, err=%d\n", err);
>> } else {
>> MSG_INFO("ipf_inject_output() succeeded\n");
>> }
>> // newdata is freed by ipf_inject_output() upon success or failure
>> }
>>
>> out:
>> return ret;
>> }
>>
>>
>> ------------------------------
>>
>> _______________________________________________
>> Macnetworkprog mailing list
>> email@hidden
>> http://lists.apple.com/mailman/listinfo/macnetworkprog
>>
>> End of Macnetworkprog Digest, Vol 7, Issue 12
>> *********************************************
>
>
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Macnetworkprog mailing list (email@hidden)
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden