+ while (ipq.next != &ipq)
+ ip_freef(ipq.next);
+}
+
+/*
+ * Do option processing on a datagram,
+ * possibly discarding it if bad options
+ * are encountered.
+ */
+ip_dooptions(ip)
+ struct ip *ip;
+{
+ register u_char *cp;
+ int opt, optlen, cnt, code, type;
+ struct in_addr *sin;
+ register struct ip_timestamp *ipt;
+ register struct ifnet *ifp;
+ struct in_addr t;
+
+ cp = (u_char *)(ip + 1);
+ cnt = (ip->ip_hl << 2) - sizeof (struct ip);
+ for (; cnt > 0; cnt -= optlen, cp += optlen) {
+ opt = cp[0];
+ if (opt == IPOPT_EOL)
+ break;
+ if (opt == IPOPT_NOP)
+ optlen = 1;
+ else
+ optlen = cp[1];
+ switch (opt) {
+
+ default:
+ break;
+
+ /*
+ * Source routing with record.
+ * Find interface with current destination address.
+ * If none on this machine then drop if strictly routed,
+ * or do nothing if loosely routed.
+ * Record interface address and bring up next address
+ * component. If strictly routed make sure next
+ * address on directly accessible net.
+ */
+ case IPOPT_LSRR:
+ case IPOPT_SSRR:
+ if (cp[2] < 4 || cp[2] > optlen - (sizeof (long) - 1))
+ break;
+ sin = (struct in_addr *)(cp + cp[2]);
+ ipaddr.sin_addr = *sin;
+ ifp = if_ifwithaddr((struct sockaddr *)&ipaddr);
+ type = ICMP_UNREACH, code = ICMP_UNREACH_SRCFAIL;
+ if (ifp == 0) {
+ if (opt == IPOPT_SSRR)
+ goto bad;
+ break;
+ }
+ t = ip->ip_dst; ip->ip_dst = *sin; *sin = t;
+ cp[2] += 4;
+ if (cp[2] > optlen - (sizeof (long) - 1))
+ break;
+ ip->ip_dst = sin[1];
+ if (opt == IPOPT_SSRR &&
+ if_ifonnetof(in_netof(ip->ip_dst)) == 0)
+ goto bad;
+ break;
+
+ case IPOPT_TS:
+ code = cp - (u_char *)ip;
+ type = ICMP_PARAMPROB;
+ ipt = (struct ip_timestamp *)cp;
+ if (ipt->ipt_len < 5)
+ goto bad;
+ if (ipt->ipt_ptr > ipt->ipt_len - sizeof (long)) {
+ if (++ipt->ipt_oflw == 0)
+ goto bad;
+ break;
+ }
+ sin = (struct in_addr *)(cp+cp[2]);
+ switch (ipt->ipt_flg) {