diff --git a/headers/posix/netinet/in.h b/headers/posix/netinet/in.h index f2e2dc1db7..2bb0fc5201 100644 --- a/headers/posix/netinet/in.h +++ b/headers/posix/netinet/in.h @@ -164,6 +164,8 @@ struct group_source_req { #define IPV6_DSTOPTS 36 /* struct ip6_dest */ #define IPV6_RTHDR 37 /* struct ip6_rthdr */ +#define IP_DONTFRAG 38 /* bool; don't fragment */ + #define INADDR_ANY ((in_addr_t)0x00000000) #define INADDR_LOOPBACK ((in_addr_t)0x7f000001) diff --git a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp index 101b285a86..41a195ee1a 100644 --- a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp +++ b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp @@ -188,6 +188,7 @@ struct ipv4_protocol : net_protocol { // protocol flags #define IP_FLAG_HEADER_INCLUDED 0x01 #define IP_FLAG_RECEIVE_DEST_ADDR 0x02 +#define IP_FLAG_DONT_FRAGMENT 0x04 static const int kDefaultTTL = 254; @@ -1203,6 +1204,10 @@ ipv4_getsockopt(net_protocol* _protocol, int level, int option, void* value, return get_int_option(value, *_length, (protocol->flags & IP_FLAG_RECEIVE_DEST_ADDR) != 0); } + if (option == IP_DONTFRAG) { + return get_int_option(value, *_length, + (protocol->flags & IP_FLAG_DONT_FRAGMENT) != 0); + } if (option == IP_TTL) return get_int_option(value, *_length, protocol->time_to_live); if (option == IP_TOS) @@ -1302,6 +1307,21 @@ ipv4_setsockopt(net_protocol* _protocol, int level, int option, return B_OK; } + if (option == IP_DONTFRAG) { + int headerIncluded; + if (length != sizeof(int)) + return B_BAD_VALUE; + if (user_memcpy(&headerIncluded, value, sizeof(headerIncluded)) + != B_OK) + return B_BAD_ADDRESS; + + if (headerIncluded) + protocol->flags |= IP_FLAG_DONT_FRAGMENT; + else + protocol->flags &= ~IP_FLAG_DONT_FRAGMENT; + + return B_OK; + } if (option == IP_TTL) return set_int_option(protocol->time_to_live, value, length); if (option == IP_TOS) @@ -1521,7 +1541,9 @@ ipv4_send_routed_data(net_protocol* _protocol, struct net_route* route, header->total_length = htons(buffer->size); header->id = htons(atomic_add(&sPacketID, 1)); header->fragment_offset = 0; - if (protocol) { + if (protocol != NULL) { + if ((protocol->flags & IP_FLAG_DONT_FRAGMENT) != 0) + header->fragment_offset |= htons(IP_DONT_FRAGMENT); header->time_to_live = (buffer->msg_flags & MSG_MCAST) != 0 ? protocol->multicast_time_to_live : protocol->time_to_live; } else { @@ -1602,6 +1624,9 @@ ipv4_send_routed_data(net_protocol* _protocol, struct net_route* route, uint32 mtu = route->mtu ? route->mtu : interface->device->mtu; if (buffer->size > mtu) { + if (protocol != NULL && (protocol->flags & IP_FLAG_DONT_FRAGMENT) != 0) + return EMSGSIZE; + // we need to fragment the packet return send_fragments(protocol, route, buffer, mtu); }