ip6_output.c
来自「eCos操作系统源码」· C语言 代码 · 共 2,527 行 · 第 1/5 页
C
2,527 行
/* 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);#endif } break;#endif /* KAME IPSEC */#if defined(IPV6FIREWALL) || (defined(__FreeBSD__) && __FreeBSD__ >= 4) case IPV6_FW_ADD: case IPV6_FW_DEL: case IPV6_FW_FLUSH: case IPV6_FW_ZERO: {#if defined(__FreeBSD__) && __FreeBSD__ >= 3 struct mbuf *m; struct mbuf **mp = &m;#endif#if defined(__FreeBSD__) && __FreeBSD__ >= 3 if (ip6_fw_ctl_ptr == NULL) return EINVAL; /* XXX */ if ((error = soopt_getm(sopt, &m)) != 0) break; /* XXX */ if ((error = soopt_mcopyin(sopt, m)) != 0) break;#else if (ip6_fw_ctl_ptr == NULL) { if (m) (void)m_free(m); return EINVAL; }#endif error = (*ip6_fw_ctl_ptr)(optname, mp); m = *mp; } break;#endif default: error = ENOPROTOOPT; break; }#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) if (m) (void)m_free(m);#endif break;#if defined(__FreeBSD__) && __FreeBSD__ >= 3 case SOPT_GET:#else case PRCO_GETOPT:#endif switch (optname) { case IPV6_2292PKTOPTIONS:#ifdef IPV6_PKTOPTIONS case IPV6_PKTOPTIONS:#endif#if defined(__FreeBSD__) && __FreeBSD__ >= 3 if (in6p->in6p_inputopts && in6p->in6p_inputopts->head) { struct mbuf *m; m = m_copym(in6p->in6p_inputopts->head, 0, M_COPYALL, M_WAIT); error = soopt_mcopyout(sopt, m); if (error == 0) m_freem(m); } else sopt->sopt_valsize = 0;#else if (in6p->in6p_inputopts && in6p->in6p_inputopts->head) { *mp = m_copym(in6p->in6p_inputopts->head, 0, M_COPYALL, M_WAIT); } else { *mp = m_get(M_WAIT, MT_SOOPTS); (*mp)->m_len = 0; }#endif break; case IPV6_RECVHOPOPTS: case IPV6_RECVDSTOPTS: case IPV6_RECVRTHDRDSTOPTS: case IPV6_UNICAST_HOPS: case IPV6_RECVPKTINFO: case IPV6_RECVHOPLIMIT: case IPV6_RECVRTHDR: case IPV6_USE_MIN_MTU: case IPV6_RECVPATHMTU: case IPV6_DONTFRAG: case IPV6_FAITH: case IPV6_V6ONLY:#ifndef __bsdi__ case IPV6_PORTRANGE:#endif case IPV6_RECVTCLASS: case IPV6_AUTOFLOWLABEL: switch (optname) { case IPV6_UNICAST_HOPS: optval = in6p->in6p_hops; break; case IPV6_RECVPKTINFO: optval = OPTBIT(IN6P_PKTINFO); break; case IPV6_RECVHOPLIMIT: optval = OPTBIT(IN6P_HOPLIMIT); break; case IPV6_RECVHOPOPTS: optval = OPTBIT(IN6P_HOPOPTS); brea
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?