Module Name:    src
Committed By:   maxv
Date:           Mon Feb  5 13:52:40 UTC 2018

Modified Files:
        src/sys/netinet: ip_input.c

Log Message:
Kick duplicate options, they are not allowed (RFC791).


To generate a diff of this commit:
cvs rdiff -u -r1.367 -r1.368 src/sys/netinet/ip_input.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet/ip_input.c
diff -u src/sys/netinet/ip_input.c:1.367 src/sys/netinet/ip_input.c:1.368
--- src/sys/netinet/ip_input.c:1.367	Mon Feb  5 13:34:20 2018
+++ src/sys/netinet/ip_input.c	Mon Feb  5 13:52:39 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_input.c,v 1.367 2018/02/05 13:34:20 maxv Exp $	*/
+/*	$NetBSD: ip_input.c,v 1.368 2018/02/05 13:52:39 maxv Exp $	*/
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.367 2018/02/05 13:34:20 maxv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.368 2018/02/05 13:52:39 maxv Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -873,11 +873,17 @@ ip_dooptions(struct mbuf *m)
 	struct ip_timestamp *ipt;
 	struct in_ifaddr *ia;
 	int opt, optlen, cnt, off, code, type = ICMP_PARAMPROB, forward = 0;
+	int lsrr_present, ssrr_present, rr_present, ts_present;
 	struct in_addr dst;
 	n_time ntime;
 	struct ifaddr *ifa = NULL;
 	int s;
 
+	lsrr_present = 0;
+	ssrr_present = 0;
+	rr_present = 0;
+	ts_present = 0;
+
 	dst = ip->ip_dst;
 	cp = (u_char *)(ip + 1);
 	cnt = (ip->ip_hl << 2) - sizeof(struct ip);
@@ -925,6 +931,17 @@ ip_dooptions(struct mbuf *m)
 				code = ICMP_UNREACH_NET_PROHIB;
 				goto bad;
 			}
+			if (opt == IPOPT_LSRR) {
+				if (lsrr_present++) {
+					code = &cp[IPOPT_OPTVAL] - (u_char *)ip;
+					goto bad;
+				}
+			} else {
+				if (ssrr_present++) {
+					code = &cp[IPOPT_OPTVAL] - (u_char *)ip;
+					goto bad;
+				}
+			}
 			if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
 				code = &cp[IPOPT_OLEN] - (u_char *)ip;
 				goto bad;
@@ -999,6 +1016,10 @@ ip_dooptions(struct mbuf *m)
 			    .sin_family = AF_INET,
 			};
 
+			if (rr_present++) {
+				code = &cp[IPOPT_OPTVAL] - (u_char *)ip;
+				goto bad;
+			}
 			if (optlen < IPOPT_OFFSET + sizeof(*cp)) {
 				code = &cp[IPOPT_OLEN] - (u_char *)ip;
 				goto bad;
@@ -1040,6 +1061,10 @@ ip_dooptions(struct mbuf *m)
 		case IPOPT_TS:
 			code = cp - (u_char *)ip;
 			ipt = (struct ip_timestamp *)cp;
+			if (ts_present++) {
+				code = &cp[IPOPT_OPTVAL] - (u_char *)ip;
+				goto bad;
+			}
 			if (ipt->ipt_len < 4 || ipt->ipt_len > 40) {
 				code = (u_char *)&ipt->ipt_len - (u_char *)ip;
 				goto bad;

Reply via email to