Hi Yin, just a quick review from me, coding style notes mentioning only what Stephan didn't yet: > + ipv4_header *cloned_header = new ipv4_header; > + net_protocol_module_info *protocol_module = > receiving_protocol(data->protocol); > + uint8 icmp_type = (uint8)(code / 14); > + uint8 icmp_code = (uint8)(code % 14); > + NetBufferHeaderReader<icmp_header> new_header(reply); Naming style would be clonedHeader, protocolModule, icmpType, icmpCode, newHeader. > +status_t > +icmp_error_reply(net_protocol *protocol, net_buffer *causedError, > uint32 code, > + void *errorData); > + > +static bool > +is_icmp_error(uint8 type) > +{ > + return type == ICMP_TYPE_UNREACH || type == ICMP_TYPE_SOURCE_QUENCH > || type == ICMP_TYPE_REDIRECT || type == ICMP_TYPE_TIME_EXCEEDED || type == ICMP_TYPE_PARAM_PROBLEM; > +} > + > net_protocol * a) Prototype declarations don't have a newline after the return type. b) two blank lines between functions. c) 80 character line limit. > + if (buffer->interface != NULL) { > + domain = buffer->interface->domain; > > + } else No {} when there is no need to, no useless blank lines like this one (only to separate actual code lines). > + struct timeval tv; > + if (gettimeofday(&tv, NULL) == 0) > + { > + uint32 time = tv.tv_sec * 1000 + tv.tv_usec / > 1000; > + net_buffer *reply = > gBufferModule->duplicate(buffer); No need to use gettimeofday() here; prefer native real_time_clock_usecs() here. > + // Make sure i'm an error > + uint8 err_code = header.type * 14 + header.code; > + return domain->module->error_received(err_code, > buffer); 14 is an odd number, anyway. Using bitfields (like 8 bit for the type, and 8 for the code) sounds like the better alternative. > + ipv4_header *cloned_header = new ipv4_header; > + cloned_header->total_length = header.totoal_length; > + cloned_header->version = header.version; > + cloned_header->service_type = header.service_type; > + cloned_header->id = header.id; > + cloned_header->fragment_offset = header.fragment_offset; > + cloned_header->time_to_live = header.time_to_live; > + cloned_header->protocol = header.protocol; > + cloned_header->checksum = header.checksum; > + cloned_header->source = header.source; > + cloned_header->destination = header.destination; Use memcpy() or = instead. > + if (header.time_to_live == 0) > + // Send ICMP Error: Time to Live Exceeded in Transit > + return sDomain->module->error_reply(NULL, buffer, > NET_ERROR_TIMEEX_IN_TRANSIT, NULL); 80 character limit, always use {} for multiline statements. The net_buffer.h header changes are missing. I'm not sure if all the error messages are correct under the given circumstances (ie. if reassemble_fragments() fails because of out of memory, it's not really a "time exceeded" error). Also, please use more descriptive naming than NET_ERROR_TIMEEX_IN_TRANSIT - NET_ERROR_TIME_EXCEEDED would be clearer and even shorter (the "in transit" is pretty much superfluous IMO). tcp.cpp: > + else { > + // Should not send ICMP UNREACH msg > + // Should send TCP RST response > + segmentAction = RESET; > + } I don't think this is correct; when a host receives a RESET, it doesn't make much sense to reply with a RESET again. > + uint8 icmp_type = (uint8)(code / 14); > + uint8 icmp_code = (uint8)(code % 14); Instead of doing this all over the code, a handy macro would be preferrable. But is it really necessary for the protocol to get both, the type and the code? And since this is part of the same API, I would prefer if the NET_ERROR_* defines are reused instead. Now to your questions: > 1. I have put the icmp_header struct definition and ICMP types/codes > macro > in net/icmp.h since these are shared among various protocols. As I mentioned above, I don't really like this approach. > 2. I'm not quite sure about my implementation of the error_reply > hooks. > Generally, ipv4_error_reply directly obtains the ICMP module info and > then > delegates the execution to icmp_error_reply. Would you please give me > some > advice on these two hooks? I'm not sure what you mean; at least the error_reply() code looks good to me. > 3. Error handling mechanisms in TCP and UDP protocols are not yet > fully > implemented. However, maybe you can give some advice by reviewing the > skeleton code in tcp.cpp and udp.cpp. Not sure what advice you are seeking for. Do you mean how the protocol should react on the different errors? > 4. Source quench problems is not handled neither at the receiver nor > the > sender side. After a glance at the Linux implementation, it appears > that it > did not handle that either. I'll look into this further. Okay; getting the general architecture in place is more important, of course :-) The details can be filled out later. > 5. Some invocation of error_reply currently lacks additional > parameter, such > as for ICMP type Parameter Problem. This will be resolved soon. Defining different NET_ERROR_* macros should be the way to go, or what do you intend to do about it? > 6. Now that error_reply hook is a way to send ICMP error messages, I > don't > notice any function that takes care of sending ICMP query messages > like ECHO > and TIMESTAMP. Is there anything I missed? Or is icmp_send_data() for > this > purpose? Not sure if I understand you; what's wrong with how it behaves now, ie. in ICMP_TYPE_ECHO_REQUEST it does: status_t status = domain->module->send_data(NULL, reply); if (status < B_OK) { gBufferModule->free(reply); return status; } HTH, Bye, Axel.