@@ -203,14 +203,6 @@ static void init_rx_queues(void)
203203 net_post_init ();
204204}
205205
206- /* If loopback driver is enabled, then direct packets to it so the address
207- * check is not needed.
208- */
209- #if defined(CONFIG_NET_IP ) && defined(CONFIG_NET_IP_ADDR_CHECK ) && !defined(CONFIG_NET_LOOPBACK )
210- /* Check if the IPv{4|6} addresses are proper. As this can be expensive,
211- * make this optional.
212- */
213-
214206static inline void copy_ll_addr (struct net_pkt * pkt )
215207{
216208 memcpy (net_pkt_lladdr_src (pkt ), net_pkt_lladdr_if (pkt ),
@@ -219,15 +211,47 @@ static inline void copy_ll_addr(struct net_pkt *pkt)
219211 sizeof (struct net_linkaddr ));
220212}
221213
222- static inline int check_ip_addr (struct net_pkt * pkt )
214+ /* Check if the IPv{4|6} addresses are proper. As this can be expensive,
215+ * make this optional. We still check the IPv4 TTL and IPv6 hop limit
216+ * if the corresponding protocol family is enabled.
217+ */
218+ static inline int check_ip (struct net_pkt * pkt )
223219{
224- uint8_t family = net_pkt_family (pkt );
220+ uint8_t family ;
221+ int ret ;
222+
223+ if (!IS_ENABLED (CONFIG_NET_IP )) {
224+ return 0 ;
225+ }
226+
227+ family = net_pkt_family (pkt );
228+ ret = 0 ;
225229
226230 if (IS_ENABLED (CONFIG_NET_IPV6 ) && family == AF_INET6 ) {
231+ /* Drop IPv6 packet if hop limit is 0 */
232+ if (NET_IPV6_HDR (pkt )-> hop_limit == 0 ) {
233+ NET_DBG ("DROP: IPv6 hop limit" );
234+ ret = - ENOMSG ; /* silently drop the pkt, not an error */
235+ goto drop ;
236+ }
237+
238+ if (!IS_ENABLED (CONFIG_NET_IP_ADDR_CHECK )) {
239+ return 0 ;
240+ }
241+
242+ #if defined(CONFIG_NET_LOOPBACK )
243+ /* If loopback driver is enabled, then send packets to it
244+ * as the address check is not needed.
245+ */
246+ if (net_if_l2 (net_pkt_iface (pkt )) == & NET_L2_GET_NAME (DUMMY )) {
247+ return 0 ;
248+ }
249+ #endif
227250 if (net_ipv6_addr_cmp ((struct in6_addr * )NET_IPV6_HDR (pkt )-> dst ,
228251 net_ipv6_unspecified_address ())) {
229- NET_DBG ("IPv6 dst address missing" );
230- return - EADDRNOTAVAIL ;
252+ NET_DBG ("DROP: IPv6 dst address missing" );
253+ ret = - EADDRNOTAVAIL ;
254+ goto drop ;
231255 }
232256
233257 /* If the destination address is our own, then route it
@@ -270,14 +294,36 @@ static inline int check_ip_addr(struct net_pkt *pkt)
270294 */
271295 if (net_ipv6_is_addr_loopback (
272296 (struct in6_addr * )NET_IPV6_HDR (pkt )-> src )) {
273- NET_DBG ("IPv6 loopback src address" );
274- return - EADDRNOTAVAIL ;
297+ NET_DBG ("DROP: IPv6 loopback src address" );
298+ ret = - EADDRNOTAVAIL ;
299+ goto drop ;
275300 }
301+
276302 } else if (IS_ENABLED (CONFIG_NET_IPV4 ) && family == AF_INET ) {
303+ /* Drop IPv4 packet if ttl is 0 */
304+ if (NET_IPV4_HDR (pkt )-> ttl == 0 ) {
305+ NET_DBG ("DROP: IPv4 ttl" );
306+ ret = - ENOMSG ; /* silently drop the pkt, not an error */
307+ goto drop ;
308+ }
309+
310+ if (!IS_ENABLED (CONFIG_NET_IP_ADDR_CHECK )) {
311+ return 0 ;
312+ }
313+
314+ #if defined(CONFIG_NET_LOOPBACK )
315+ /* If loopback driver is enabled, then send packets to it
316+ * as the address check is not needed.
317+ */
318+ if (net_if_l2 (net_pkt_iface (pkt )) == & NET_L2_GET_NAME (DUMMY )) {
319+ return 0 ;
320+ }
321+ #endif
277322 if (net_ipv4_addr_cmp ((struct in_addr * )NET_IPV4_HDR (pkt )-> dst ,
278323 net_ipv4_unspecified_address ())) {
279- NET_DBG ("IPv4 dst address missing" );
280- return - EADDRNOTAVAIL ;
324+ NET_DBG ("DROP: IPv4 dst address missing" );
325+ ret = - EADDRNOTAVAIL ;
326+ goto drop ;
281327 }
282328
283329 /* If the destination address is our own, then route it
@@ -308,16 +354,25 @@ static inline int check_ip_addr(struct net_pkt *pkt)
308354 * localhost subnet too.
309355 */
310356 if (net_ipv4_is_addr_loopback ((struct in_addr * )NET_IPV4_HDR (pkt )-> src )) {
311- NET_DBG ("IPv4 loopback src address" );
312- return - EADDRNOTAVAIL ;
357+ NET_DBG ("DROP: IPv4 loopback src address" );
358+ ret = - EADDRNOTAVAIL ;
359+ goto drop ;
313360 }
314361 }
315362
316- return 0 ;
363+ return ret ;
364+
365+ drop :
366+ if (IS_ENABLED (CONFIG_NET_STATISTICS )) {
367+ if (family == AF_INET6 ) {
368+ net_stats_update_ipv6_drop (net_pkt_iface (pkt ));
369+ } else {
370+ net_stats_update_ipv4_drop (net_pkt_iface (pkt ));
371+ }
372+ }
373+
374+ return ret ;
317375}
318- #else
319- #define check_ip_addr (pkt ) 0
320- #endif
321376
322377/* Called when data needs to be sent to network */
323378int net_send_data (struct net_pkt * pkt )
@@ -332,22 +387,20 @@ int net_send_data(struct net_pkt *pkt)
332387 return - EINVAL ;
333388 }
334389
335- #if defined(CONFIG_NET_STATISTICS )
336- switch (net_pkt_family (pkt )) {
337- case AF_INET :
338- net_stats_update_ipv4_sent (net_pkt_iface (pkt ));
339- break ;
340- case AF_INET6 :
341- net_stats_update_ipv6_sent (net_pkt_iface (pkt ));
342- break ;
343- }
344- #endif
345-
346390 net_pkt_trim_buffer (pkt );
347391 net_pkt_cursor_init (pkt );
348392
349- status = check_ip_addr (pkt );
393+ status = check_ip (pkt );
350394 if (status < 0 ) {
395+ /* Special handling for ENOMSG which is returned if packet
396+ * TTL is 0 or hop limit is 0. This is not an error as it is
397+ * perfectly valid case to set the limit to 0. In this case
398+ * we just silently drop the packet by returning 0.
399+ */
400+ if (status == - ENOMSG ) {
401+ return 0 ;
402+ }
403+
351404 return status ;
352405 } else if (status > 0 ) {
353406 /* Packet is destined back to us so send it directly
@@ -362,6 +415,17 @@ int net_send_data(struct net_pkt *pkt)
362415 return - EIO ;
363416 }
364417
418+ if (IS_ENABLED (CONFIG_NET_STATISTICS )) {
419+ switch (net_pkt_family (pkt )) {
420+ case AF_INET :
421+ net_stats_update_ipv4_sent (net_pkt_iface (pkt ));
422+ break ;
423+ case AF_INET6 :
424+ net_stats_update_ipv6_sent (net_pkt_iface (pkt ));
425+ break ;
426+ }
427+ }
428+
365429 return 0 ;
366430}
367431
0 commit comments