ipsec.c
来自「eCos操作系统源码」· C语言 代码 · 共 2,682 行 · 第 1/5 页
C
2,682 行
ipseclog((LOG_ERR, "ipsec4_getpolicybysock: " "Invalid policy for PCB %d\n", currsp->policy)); *error = EINVAL; return NULL; } /* NOTREACHED */ } /* when non-privilieged socket */ /* look for a policy in SPD */ kernsp = key_allocsp(&currsp->spidx, dir); /* SP found */ if (kernsp != NULL) { KEYDEBUG(KEYDEBUG_IPSEC_STAMP, printf("DP ipsec4_getpolicybysock called " "to allocate SP:%p\n", kernsp)); *error = 0; ipsec_fillpcbcache(pcbsp, m, kernsp, dir); return kernsp; } /* no SP found */ switch (currsp->policy) { case IPSEC_POLICY_BYPASS: ipseclog((LOG_ERR, "ipsec4_getpolicybysock: " "Illegal policy for non-priviliged defined %d\n", currsp->policy)); *error = EINVAL; return NULL; case IPSEC_POLICY_ENTRUST: if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD && ip4_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", ip4_def_policy.policy, IPSEC_POLICY_NONE)); ip4_def_policy.policy = IPSEC_POLICY_NONE; } ip4_def_policy.refcnt++; *error = 0; ipsec_fillpcbcache(pcbsp, m, &ip4_def_policy, dir); return &ip4_def_policy; case IPSEC_POLICY_IPSEC: currsp->refcnt++; *error = 0; ipsec_fillpcbcache(pcbsp, m, currsp, dir); return currsp; default: ipseclog((LOG_ERR, "ipsec4_getpolicybysock: " "Invalid policy for PCB %d\n", currsp->policy)); *error = EINVAL; return NULL; } /* NOTREACHED */}/* * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet, * and return a pointer to SP. * OUT: positive: a pointer to the entry for security policy leaf matched. * NULL: no apropreate SP found, the following value is set to error. * 0 : bypass * EACCES : discard packet. * ENOENT : ipsec_acquire() in progress, maybe. * others : error occured. */struct secpolicy *ipsec4_getpolicybyaddr(m, dir, flag, error) struct mbuf *m; u_int dir; int flag; int *error;{ struct secpolicy *sp = NULL; /* sanity check */ if (m == NULL || error == NULL) panic("ipsec4_getpolicybyaddr: NULL pointer was passed.\n"); { struct secpolicyindex spidx; bzero(&spidx, sizeof(spidx)); /* make a index to look for a policy */ *error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET, m, (flag & IP_FORWARDING) ? 0 : 1); if (*error != 0) return NULL; sp = key_allocsp(&spidx, dir); } /* SP found */ if (sp != NULL) { KEYDEBUG(KEYDEBUG_IPSEC_STAMP, printf("DP ipsec4_getpolicybyaddr called " "to allocate SP:%p\n", sp)); *error = 0; return sp; } /* no SP found */ if (ip4_def_policy.policy != IPSEC_POLICY_DISCARD && ip4_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy:%d->%d\n", ip4_def_policy.policy, IPSEC_POLICY_NONE)); ip4_def_policy.policy = IPSEC_POLICY_NONE; } ip4_def_policy.refcnt++; *error = 0; return &ip4_def_policy;}#ifdef INET6/* * For OUTBOUND packet having a socket. Searching SPD for packet, * and return a pointer to SP. * OUT: NULL: no apropreate SP found, the following value is set to error. * 0 : bypass * EACCES : discard packet. * ENOENT : ipsec_acquire() in progress, maybe. * others : error occured. * others: a pointer to SP */struct secpolicy *ipsec6_getpolicybysock(m, dir, so, error) struct mbuf *m; u_int dir; struct socket *so; int *error;{ struct inpcbpolicy *pcbsp = NULL; struct secpolicy *currsp = NULL; /* policy on socket */ struct secpolicy *kernsp = NULL; /* policy on kernel */ /* sanity check */ if (m == NULL || so == NULL || error == NULL) panic("ipsec6_getpolicybysock: NULL pointer was passed.\n");#ifdef DIAGNOSTIC if (so->so_proto->pr_domain->dom_family != AF_INET6) panic("ipsec6_getpolicybysock: socket domain != inet6\n");#endif pcbsp = sotoin6pcb(so)->in6p_sp; /* if we have a cached entry, and if it is still valid, use it. */ ipsec6stat.spdcachelookup++; currsp = ipsec_checkpcbcache(m, pcbsp, dir); if (currsp) { *error = 0; return currsp; } ipsec6stat.spdcachemiss++; /* set spidx in pcb */ /* XXX why is it necessary to do this? */ ipsec6_setspidx_in6pcb(m, sotoin6pcb(so)); /* sanity check */ if (pcbsp == NULL) panic("ipsec6_getpolicybysock: pcbsp is NULL.\n"); switch (dir) { case IPSEC_DIR_INBOUND: currsp = pcbsp->sp_in; break; case IPSEC_DIR_OUTBOUND: currsp = pcbsp->sp_out; break; default: panic("ipsec6_getpolicybysock: illegal direction.\n"); } /* sanity check */ if (currsp == NULL) panic("ipsec6_getpolicybysock: currsp is NULL.\n"); /* when privilieged socket */ if (pcbsp->priv) { switch (currsp->policy) { case IPSEC_POLICY_BYPASS: currsp->refcnt++; *error = 0; ipsec_fillpcbcache(pcbsp, m, currsp, dir); return currsp; case IPSEC_POLICY_ENTRUST: /* look for a policy in SPD */ kernsp = key_allocsp(&currsp->spidx, dir); /* SP found */ if (kernsp != NULL) { KEYDEBUG(KEYDEBUG_IPSEC_STAMP, printf("DP ipsec6_getpolicybysock called " "to allocate SP:%p\n", kernsp)); *error = 0; ipsec_fillpcbcache(pcbsp, m, kernsp, dir); return kernsp; } /* no SP found */ if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD && ip6_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", ip6_def_policy.policy, IPSEC_POLICY_NONE)); ip6_def_policy.policy = IPSEC_POLICY_NONE; } ip6_def_policy.refcnt++; *error = 0; ipsec_fillpcbcache(pcbsp, m, &ip6_def_policy, dir); return &ip6_def_policy; case IPSEC_POLICY_IPSEC: currsp->refcnt++; *error = 0; ipsec_fillpcbcache(pcbsp, m, currsp, dir); return currsp; default: ipseclog((LOG_ERR, "ipsec6_getpolicybysock: " "Invalid policy for PCB %d\n", currsp->policy)); *error = EINVAL; return NULL; } /* NOTREACHED */ } /* when non-privilieged socket */ /* look for a policy in SPD */ kernsp = key_allocsp(&currsp->spidx, dir); /* SP found */ if (kernsp != NULL) { KEYDEBUG(KEYDEBUG_IPSEC_STAMP, printf("DP ipsec6_getpolicybysock called " "to allocate SP:%p\n", kernsp)); *error = 0; ipsec_fillpcbcache(pcbsp, m, kernsp, dir); return kernsp; } /* no SP found */ switch (currsp->policy) { case IPSEC_POLICY_BYPASS: ipseclog((LOG_ERR, "ipsec6_getpolicybysock: " "Illegal policy for non-priviliged defined %d\n", currsp->policy)); *error = EINVAL; return NULL; case IPSEC_POLICY_ENTRUST: if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD && ip6_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", ip6_def_policy.policy, IPSEC_POLICY_NONE)); ip6_def_policy.policy = IPSEC_POLICY_NONE; } ip6_def_policy.refcnt++; *error = 0; ipsec_fillpcbcache(pcbsp, m, &ip6_def_policy, dir); return &ip6_def_policy; case IPSEC_POLICY_IPSEC: currsp->refcnt++; *error = 0; ipsec_fillpcbcache(pcbsp, m, currsp, dir); return currsp; default: ipseclog((LOG_ERR, "ipsec6_policybysock: Invalid policy for PCB %d\n", currsp->policy)); *error = EINVAL; return NULL; } /* NOTREACHED */}/* * For FORWADING packet or OUTBOUND without a socket. Searching SPD for packet, * and return a pointer to SP. * `flag' means that packet is to be forwarded whether or not. * flag = 1: forwad * OUT: positive: a pointer to the entry for security policy leaf matched. * NULL: no apropreate SP found, the following value is set to error. * 0 : bypass * EACCES : discard packet. * ENOENT : ipsec_acquire() in progress, maybe. * others : error occured. */#ifndef IP_FORWARDING#define IP_FORWARDING 1#endifstruct secpolicy *ipsec6_getpolicybyaddr(m, dir, flag, error) struct mbuf *m; u_int dir; int flag; int *error;{ struct secpolicy *sp = NULL; /* sanity check */ if (m == NULL || error == NULL) panic("ipsec6_getpolicybyaddr: NULL pointer was passed.\n"); /* get a policy entry matched with the packet */ { struct secpolicyindex spidx; bzero(&spidx, sizeof(spidx)); /* make a index to look for a policy */ *error = ipsec_setspidx_mbuf(&spidx, dir, AF_INET6, m, (flag & IP_FORWARDING) ? 0 : 1); if (*error != 0) return NULL; sp = key_allocsp(&spidx, dir); } /* SP found */ if (sp != NULL) { KEYDEBUG(KEYDEBUG_IPSEC_STAMP, printf("DP ipsec6_getpolicybyaddr called " "to allocate SP:%p\n", sp)); *error = 0; return sp; } /* no SP found */ if (ip6_def_policy.policy != IPSEC_POLICY_DISCARD && ip6_def_policy.policy != IPSEC_POLICY_NONE) { ipseclog((LOG_INFO, "fixed system default policy: %d->%d\n", ip6_def_policy.policy, IPSEC_POLICY_NONE)); ip6_def_policy.policy = IPSEC_POLICY_NONE; } ip6_def_policy.refcnt++; *error = 0; return &ip6_def_policy;}#endif /* INET6 *//* * set IP address into spidx from mbuf. * When Forwarding packet and ICMP echo reply, this function is used. * * IN: get the followings from mbuf. * protocol family, src, dst, next protocol * OUT: * 0: success. * other: failure, and set errno. */intipsec_setspidx_mbuf(spidx, dir, family, m, needport) struct secpolicyindex *spidx; u_int dir, family; struct mbuf *m; int needport;{ int error; /* sanity check */ if (spidx == NULL || m == NULL) panic("ipsec_setspidx_mbuf: NULL pointer was passed.\n"); bzero(spidx, sizeof(*spidx)); error = ipsec_setspidx(m, spidx, needport); if (error) goto bad; spidx->dir = dir; return 0; bad: /* XXX initialize */ bzero(spidx, sizeof(*spidx)); return EINVAL;}static intipsec4_setspidx_inpcb(m, pcb) struct mbuf *m; struct inpcb *pcb;{ struct secpolicyindex *spidx; int error; /* sanity check */ if (pcb == NULL) panic("ipsec4_setspidx_inpcb: no PCB found.\n"); if (pcb->inp_sp == NULL) panic("ipsec4_setspidx_inpcb: no inp_sp found.\n"); if (pcb->inp_sp->sp_out == NULL || pcb->inp_sp->sp_in == NULL) panic("ipsec4_setspidx_inpcb: no sp_in/out found.\n"); bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx)); bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx)); spidx = &pcb->inp_sp->sp_in->spidx; error = ipsec_setspidx(m, spidx, 1); if (error) goto bad; spidx->dir = IPSEC_DIR_INBOUND; spidx = &pcb->inp_sp->sp_out->spidx; error = ipsec_setspidx(m, spidx, 1); if (error) goto bad; spidx->dir = IPSEC_DIR_OUTBOUND; return 0;bad: bzero(&pcb->inp_sp->sp_in->spidx, sizeof(*spidx)); bzero(&pcb->inp_sp->sp_out->spidx, sizeof(*spidx)); return error;}#ifdef INET6static intipsec6_setspidx_in6pcb(m, pcb) struct mbuf *m; struct in6pcb *pcb;{ struct secpolicyindex *spidx; int error; /* sanity check */ if (pcb == NULL) panic("ipsec6_setspidx_in6pcb: no PCB found.\n"); if (pcb->in6p_sp == NULL) panic("ipsec6_setspidx_in6pcb: no in6p_sp found.\n"); if (pcb->in6p_sp->sp_out == NULL || pcb->in6p_sp->sp_in == NULL) panic("ipsec6_setspidx_in6pcb: no sp_in/out found.\n"); bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx)); bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx)); spidx = &pcb->in6p_sp->sp_in->spidx; error = ipsec_setspidx(m, spidx, 1); if (error) goto bad; spidx->dir = IPSEC_DIR_INBOUND; spidx = &pcb->in6p_sp->sp_out->spidx; error = ipsec_setspidx(m, spidx, 1); if (error) goto bad; spidx->dir = IPSEC_DIR_OUTBOUND; return 0;bad: bzero(&pcb->in6p_sp->sp_in->spidx, sizeof(*spidx)); bzero(&pcb->in6p_sp->sp_out->spidx, sizeof(*spidx)); return error;}#endif/* * configure security policy index (src/dst/proto/sport/dport) * by looking at the content of mbuf. * the caller is responsible for error recovery (like clearing up spidx). */static intipsec_setspidx(m, spidx, needport) struct mbuf *m; struct secpolicyindex *spidx; int needport;{ struct ip *ip = NULL; struct ip ipbuf; u_int v; struct mbuf *n; int len; int error; if (m == NULL) panic("ipsec_setspidx: m == 0 passed.\n"); bzero(spidx, sizeof(*spidx)); /* * validate m->m_pkthdr.len. we see incorrect length if we * mistakenly call this function with inconsistent mbuf chain * (like 4.4BSD tcp/udp processing). XXX should we panic here? */ len = 0; for (n = m; n; n = n->m_next) len += n->m_len; if (m->m_pkthdr.len != len) { KEYDEBUG(KEYDEBUG_IPSEC_DUMP, printf("ipsec_setspidx: " "total of m_len(%d) != pkthdr.len(%d), " "ignored.\n", len, m->m_pkthdr.len)); return EINVAL; } if (m->m_pkthdr.len < sizeof(struct ip)) { KEYDEBUG(KEYDEBUG_IPSEC_DUMP, printf("ipsec_setspidx: " "pkthdr.len(%d) < sizeof(struct ip), ignored.\n", m->m_pkthdr.len)); return EINVAL; } if (m->m_len >= sizeof(*ip)) ip = mtod(m, struct ip *); else { m_copydata(m, 0, sizeof(ipbuf), (caddr_t)&ipbuf); ip = &ipbuf; }#ifdef _IP_VHL v = _IP_VHL_V(ip->ip_vhl);#else v = ip->ip_v;#endif switch (v) { case 4: error = ipsec4_setspidx_ipaddr(m, spidx); if (error) return error; ipsec4_get_ulp(m, spidx, needport);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?