⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ip6_output.c

📁 嵌入式操作系统ECOS的网络开发包
💻 C
📖 第 1 页 / 共 5 页
字号:
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
				error = sooptcopyin(sopt, &optval,
					sizeof optval, sizeof optval);
				if (error)
					break;
#else
				optval = *mtod(m, int *);
#endif
				switch (optname) {

				case IPV6_UNICAST_HOPS:
					if (optval < -1 || optval >= 256)
						error = EINVAL;
					else {
						/* -1 = kernel default */
						in6p->in6p_hops = optval;
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
						if ((in6p->in6p_vflag &
						     INP_IPV4) != 0)
							in6p->inp_ip_ttl = optval;
#endif
					}
					break;
#define OPTSET(bit) \
do { \
	if (optval) \
		in6p->in6p_flags |= (bit); \
	else \
		in6p->in6p_flags &= ~(bit); \
} while (0)
#define OPTSET2292(bit) \
do { \
	in6p->in6p_flags |= IN6P_RFC2292; \
	if (optval) \
		in6p->in6p_flags |= (bit); \
	else \
		in6p->in6p_flags &= ~(bit); \
} while (0)
#define OPTBIT(bit) (in6p->in6p_flags & (bit) ? 1 : 0)

				case IPV6_RECVPKTINFO:
					/* cannot mix with RFC2292 */
					if (OPTBIT(IN6P_RFC2292)) {
						error = EINVAL;
						break;
					}
					OPTSET(IN6P_PKTINFO);
					if (OPTBIT(IN6P_PKTINFO) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVPKTINFO);
					break;

				case IPV6_HOPLIMIT:
				{
					struct ip6_pktopts **optp;

					/* cannot mix with RFC2292 */
					if (OPTBIT(IN6P_RFC2292)) {
						error = EINVAL;
						break;
					}
					optp = &in6p->in6p_outputopts;
					error = ip6_pcbopt(IPV6_HOPLIMIT,
							   (u_char *)&optval,
							   sizeof(optval),
							   optp,
							   privileged);
					break;
				}

				case IPV6_RECVHOPLIMIT:
					/* cannot mix with RFC2292 */
					if (OPTBIT(IN6P_RFC2292)) {
						error = EINVAL;
						break;
					}
					OPTSET(IN6P_HOPLIMIT);
					if (OPTBIT(IN6P_HOPLIMIT) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVHOPLIMIT);
					break;

				case IPV6_RECVHOPOPTS:
					/* cannot mix with RFC2292 */
					if (OPTBIT(IN6P_RFC2292)) {
						error = EINVAL;
						break;
					}
					OPTSET(IN6P_HOPOPTS);
					if (OPTBIT(IN6P_HOPOPTS) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVHOPOPTS);
					break;

				case IPV6_RECVDSTOPTS:
					/* cannot mix with RFC2292 */
					if (OPTBIT(IN6P_RFC2292)) {
						error = EINVAL;
						break;
					}
					OPTSET(IN6P_DSTOPTS);
					if (OPTBIT(IN6P_DSTOPTS) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVDSTOPTS);
					break;

				case IPV6_RECVRTHDRDSTOPTS:
					/* cannot mix with RFC2292 */
					if (OPTBIT(IN6P_RFC2292)) {
						error = EINVAL;
						break;
					}
					OPTSET(IN6P_RTHDRDSTOPTS);
					if (OPTBIT(IN6P_RTHDRDSTOPTS) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVRTHDRDSTOPTS);
					break;

				case IPV6_RECVRTHDR:
					/* cannot mix with RFC2292 */
					if (OPTBIT(IN6P_RFC2292)) {
						error = EINVAL;
						break;
					}
					OPTSET(IN6P_RTHDR);
					if (OPTBIT(IN6P_RTHDR) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVRTHDR);
					break;

				case IPV6_FAITH:
					OPTSET(IN6P_FAITH);
					break;

				case IPV6_RECVPATHMTU:
					OPTSET(IN6P_MTU);
					break;

				case IPV6_V6ONLY:
					/*
					 * make setsockopt(IPV6_V6ONLY)
					 * available only prior to bind(2).
					 * see ipng mailing list, Jun 22 2001.
					 */
					if (in6p->in6p_lport ||
					    !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr))
					{
						error = EINVAL;
						break;
					}
#ifdef __NetBSD__
#ifdef INET6_BINDV6ONLY
					if (!optval)
						error = EINVAL;
#else
					OPTSET(IN6P_IPV6_V6ONLY);
#endif
#elif (defined(__FreeBSD__) && __FreeBSD__ >= 3) || (defined(__bsdi__) && _BSDI_VERSION >= 199802)
					OPTSET(IN6P_IPV6_V6ONLY);
#else
					if ((ip6_v6only && optval) ||
					    (!ip6_v6only && !optval))
						error = 0;
					else
						error = EINVAL;
#endif
					break;
				case IPV6_RECVTCLASS:
					/* cannot mix with RFC2292 XXX */
					if (OPTBIT(IN6P_RFC2292)) {
						error = EINVAL;
						break;
					}
					OPTSET(IN6P_TCLASS);
					break;
				case IPV6_AUTOFLOWLABEL:
					OPTSET(IN6P_AUTOFLOWLABEL);
					break;

				}
				break;

			case IPV6_OTCLASS:
			{
				struct ip6_pktopts **optp;
				u_int8_t tclass;

				if (optlen != sizeof(tclass)) {
					error = EINVAL;
					break;
				}
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
				error = sooptcopyin(sopt, &tclass,
					sizeof tclass, sizeof tclass);
				if (error)
					break;
#else
				tclass = *mtod(m, u_int8_t *);
#endif
				optp = &in6p->in6p_outputopts;
				error = ip6_pcbopt(optname,
						   (u_char *)&tclass,
						   sizeof(tclass),
						   optp,
						   privileged);
				break;
			}

			case IPV6_TCLASS:
			case IPV6_DONTFRAG:
			case IPV6_USE_MIN_MTU:
				if (optlen != sizeof(optval)) {
					error = EINVAL;
					break;
				}
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
				error = sooptcopyin(sopt, &optval,
					sizeof optval, sizeof optval);
				if (error)
					break;
#else
				optval = *mtod(m, int *);
#endif
				{
					struct ip6_pktopts **optp;
					optp = &in6p->in6p_outputopts;
					error = ip6_pcbopt(optname,
							   (u_char *)&optval,
							   sizeof(optval),
							   optp,
							   privileged);
					break;
				}

			case IPV6_2292PKTINFO:
			case IPV6_2292HOPLIMIT:
			case IPV6_2292HOPOPTS:
			case IPV6_2292DSTOPTS:
			case IPV6_2292RTHDR:
				/* RFC 2292 */
				if (optlen != sizeof(int)) {
					error = EINVAL;
					break;
				}
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
				error = sooptcopyin(sopt, &optval,
					sizeof optval, sizeof optval);
				if (error)
					break;
#else
				optval = *mtod(m, int *);
#endif
				switch (optname) {
				case IPV6_2292PKTINFO:
					OPTSET2292(IN6P_PKTINFO);
					if (OPTBIT(IN6P_PKTINFO) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVPKTINFO);
					break;
				case IPV6_2292HOPLIMIT:
					OPTSET2292(IN6P_HOPLIMIT);
					if (OPTBIT(IN6P_HOPLIMIT) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVHOPLIMIT);
					break;
				case IPV6_2292HOPOPTS:
					/*
					 * Check super-user privilege.
					 * See comments for IPV6_RECVHOPOPTS.
					 */
					OPTSET2292(IN6P_HOPOPTS);
					if (OPTBIT(IN6P_HOPOPTS) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVHOPOPTS);
					break;
				case IPV6_2292DSTOPTS:
					OPTSET2292(IN6P_DSTOPTS|IN6P_RTHDRDSTOPTS); /* XXX */
					if (OPTBIT(IN6P_DSTOPTS) == 0) {
						ip6_reset_rcvopt(rcvopts, IPV6_RECVDSTOPTS);
						ip6_reset_rcvopt(rcvopts, IPV6_RECVRTHDRDSTOPTS);
					}
					break;
				case IPV6_2292RTHDR:
					OPTSET2292(IN6P_RTHDR);
					if (OPTBIT(IN6P_RTHDR) == 0)
						ip6_reset_rcvopt(rcvopts, IPV6_RECVRTHDR);
					break;
				}
				break;
			case IPV6_PKTINFO:
			case IPV6_HOPOPTS:
			case IPV6_RTHDR:
			case IPV6_DSTOPTS:
			case IPV6_RTHDRDSTOPTS:
			case IPV6_NEXTHOP:
			{
				/* new advanced API (2292bis) */
				u_char *optbuf;
				int optlen;
				struct ip6_pktopts **optp;

				/* cannot mix with RFC2292 */
				if (OPTBIT(IN6P_RFC2292)) {
					error = EINVAL;
					break;
				}

#if defined(__FreeBSD__) && __FreeBSD__ >= 3
				optbuf = sopt->sopt_val;
				optlen = sopt->sopt_valsize;
#else  /* !fbsd3 */
				if (m && m->m_next) {
					error = EINVAL;	/* XXX */
					break;
				}
				if (m) {
					optbuf = mtod(m, u_char *);
					optlen = m->m_len;
				} else {
					optbuf = NULL;
					optlen = 0;
				}
#endif
				optp = &in6p->in6p_outputopts;
				error = ip6_pcbopt(optname,
						   optbuf, optlen,
						   optp, privileged);
				break;
			}
#undef OPTSET

			case IPV6_MULTICAST_IF:
			case IPV6_MULTICAST_HOPS:
			case IPV6_MULTICAST_LOOP:
			case IPV6_JOIN_GROUP:
			case IPV6_LEAVE_GROUP:
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
			    {
				struct mbuf *m;
				if (sopt->sopt_valsize > MLEN) {
					error = EMSGSIZE;
					break;
				}
				/* XXX */
				MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_HEADER);
				if (m == 0) {
					error = ENOBUFS;
					break;
				}
				m->m_len = sopt->sopt_valsize;
				error = sooptcopyin(sopt, mtod(m, char *),
						    m->m_len, m->m_len);
				error =	ip6_setmoptions(sopt->sopt_name,
							&in6p->in6p_moptions,
							m);
				(void)m_free(m);
			    }
#else
				error =	ip6_setmoptions(optname,
							&in6p->in6p_moptions,
							m);
#if defined(__bsdi__) && _BSDI_VERSION >= 199802
				if (in6p->in6p_moptions != NULL)
					in6p->in6p_flags |= INP_IPV6_MCAST; /* XXX */
#endif
#endif
				break;

#ifndef __bsdi__
			case IPV6_PORTRANGE:
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
				error = sooptcopyin(sopt, &optval,
				    sizeof optval, sizeof optval);
				if (error)
					break;
#else
				optval = *mtod(m, int *);
#endif

				switch (optval) {
				case IPV6_PORTRANGE_DEFAULT:
					in6p->in6p_flags &= ~(IN6P_LOWPORT);
					in6p->in6p_flags &= ~(IN6P_HIGHPORT);
					break;

				case IPV6_PORTRANGE_HIGH:
					in6p->in6p_flags &= ~(IN6P_LOWPORT);
					in6p->in6p_flags |= IN6P_HIGHPORT;
					break;

				case IPV6_PORTRANGE_LOW:
					in6p->in6p_flags &= ~(IN6P_HIGHPORT);
					in6p->in6p_flags |= IN6P_LOWPORT;
					break;

				default:
					error = EINVAL;
					break;
				}
				break;
#endif

#ifdef __OpenBSD__
			case IPSEC6_OUTSA:
#ifndef IPSEC
				error = EINVAL;
#else
				s = spltdb();
				if (m == 0 || m->m_len != sizeof(struct tdb_ident)) {
					error = EINVAL;
				} else {
					tdbip = mtod(m, struct tdb_ident *);
					tdb = gettdb(tdbip->spi, &tdbip->dst,
					    tdbip->proto);
					if (tdb == NULL)
						error = ESRCH;
					else
						tdb_add_inp(tdb, inp, 0);
				}
				splx(s);
#endif
				break;

			case IPV6_AUTH_LEVEL:
			case IPV6_ESP_TRANS_LEVEL:
			case IPV6_ESP_NETWORK_LEVEL:
			case IPV6_IPCOMP_LEVEL:
#ifndef IPSEC
				error = EINVAL;
#else
				if (m == 0 || m->m_len != sizeof(int)) {
					error = EINVAL;
					break;
				}
				optval = *mtod(m, int *);

				if (optval < IPSEC_LEVEL_BYPASS || 
				    optval > IPSEC_LEVEL_UNIQUE) {
					error = EINVAL;
					break;
				}
					
				switch (optname) {
				case IPV6_AUTH_LEVEL:
					inp->inp_seclevel[SL_AUTH] = optval;
					break;

				case IPV6_ESP_TRANS_LEVEL:
					inp->inp_seclevel[SL_ESP_TRANS] = optval;
					break;

				case IPV6_ESP_NETWORK_LEVEL:
					inp->inp_seclevel[SL_ESP_NETWORK] = optval;
					break;

				case IPV6_IPCOMP_LEVEL:
					inp->inp_seclevel[SL_IPCOMP] = optval;
					break;
				}
				if (!error)
					inp->inp_secrequire = get_sa_require(inp);
#endif
				break;
#endif /* OpenBSD */

#if defined(IPSEC) && !defined(__OpenBSD__)
			case IPV6_IPSEC_POLICY:
			    {
				caddr_t req = NULL;
				size_t len = 0;
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
				struct mbuf *m;
#endif

#if defined(__FreeBSD__) && __FreeBSD__ >= 3
				if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
					break;
				if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
					break;
#endif
				if (m) {
					req = mtod(m, caddr_t);
					len = m->m_len;
				}
				error = ipsec6_set_policy(in6p, optname, req,
							  len, privileged);
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
				m_freem(m);
#e

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -