diff options
author | ume <ume@FreeBSD.org> | 2005-07-21 16:39:23 +0000 |
---|---|---|
committer | ume <ume@FreeBSD.org> | 2005-07-21 16:39:23 +0000 |
commit | 5960d35adee19b10a49567b65b0b57a4adc077bd (patch) | |
tree | a81f09d3e50491f99269ba11de9c7df1e790a970 | |
parent | 3969c485d9ac072bb7cc40918d3bf4c463ead835 (diff) | |
download | FreeBSD-src-5960d35adee19b10a49567b65b0b57a4adc077bd.zip FreeBSD-src-5960d35adee19b10a49567b65b0b57a4adc077bd.tar.gz |
always copy ip6_pktopt. remove needcopy and needfree
argument/structure member accordingly.
Submitted by: Keiichi SHIMA <keiichi__at__iijlab.net>
Obtained from: KAME
-rw-r--r-- | sys/netinet6/ip6_output.c | 134 | ||||
-rw-r--r-- | sys/netinet6/ip6_var.h | 4 | ||||
-rw-r--r-- | sys/netinet6/raw_ip6.c | 2 | ||||
-rw-r--r-- | sys/netinet6/udp6_output.c | 2 |
4 files changed, 67 insertions, 75 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index a9ffbef..bee369e 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -139,6 +139,7 @@ static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t)); static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *)); static int ip6_getpmtu __P((struct route_in6 *, struct route_in6 *, struct ifnet *, struct in6_addr *, u_long *, int *)); +static int copypktopts __P((struct ip6_pktopts *, struct ip6_pktopts *, int)); /* @@ -2358,7 +2359,7 @@ ip6_pcbopts(pktopt, m, so, sopt) /* set options specified by user. */ if (td && !suser(td)) priv = 1; - if ((error = ip6_setpktopts(m, opt, NULL, priv, 1, + if ((error = ip6_setpktopts(m, opt, NULL, priv, so->so_proto->pr_protocol)) != 0) { ip6_clearpktopts(opt, -1); /* XXX: discard all options */ free(opt, M_IP6OPT); @@ -2397,7 +2398,6 @@ ip6_pcbopt(optname, buf, len, pktopt, priv, uproto) *pktopt = malloc(sizeof(struct ip6_pktopts), M_IP6OPT, M_WAITOK); ip6_initpktopts(*pktopt); - (*pktopt)->needfree = 1; } opt = *pktopt; @@ -2510,15 +2510,11 @@ ip6_clearpktopts(pktopt, optname) struct ip6_pktopts *pktopt; int optname; { - int needfree; - if (pktopt == NULL) return; - needfree = pktopt->needfree; - if (optname == -1 || optname == IPV6_PKTINFO) { - if (needfree && pktopt->ip6po_pktinfo) + if (pktopt->ip6po_pktinfo) free(pktopt->ip6po_pktinfo, M_IP6OPT); pktopt->ip6po_pktinfo = NULL; } @@ -2531,22 +2527,22 @@ ip6_clearpktopts(pktopt, optname) RTFREE(pktopt->ip6po_nextroute.ro_rt); pktopt->ip6po_nextroute.ro_rt = NULL; } - if (needfree && pktopt->ip6po_nexthop) + if (pktopt->ip6po_nexthop) free(pktopt->ip6po_nexthop, M_IP6OPT); pktopt->ip6po_nexthop = NULL; } if (optname == -1 || optname == IPV6_HOPOPTS) { - if (needfree && pktopt->ip6po_hbh) + if (pktopt->ip6po_hbh) free(pktopt->ip6po_hbh, M_IP6OPT); pktopt->ip6po_hbh = NULL; } if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) { - if (needfree && pktopt->ip6po_dest1) + if (pktopt->ip6po_dest1) free(pktopt->ip6po_dest1, M_IP6OPT); pktopt->ip6po_dest1 = NULL; } if (optname == -1 || optname == IPV6_RTHDR) { - if (needfree && pktopt->ip6po_rhinfo.ip6po_rhi_rthdr) + if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr) free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT); pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL; if (pktopt->ip6po_route.ro_rt) { @@ -2555,7 +2551,7 @@ ip6_clearpktopts(pktopt, optname) } } if (optname == -1 || optname == IPV6_DSTOPTS) { - if (needfree && pktopt->ip6po_dest2) + if (pktopt->ip6po_dest2) free(pktopt->ip6po_dest2, M_IP6OPT); pktopt->ip6po_dest2 = NULL; } @@ -2572,24 +2568,16 @@ do {\ }\ } while (/*CONSTCOND*/ 0) -struct ip6_pktopts * -ip6_copypktopts(src, canwait) - struct ip6_pktopts *src; +static int +copypktopts(dst, src, canwait) + struct ip6_pktopts *dst, *src; int canwait; { - struct ip6_pktopts *dst; - - if (src == NULL) { + if (dst == NULL || src == NULL) { printf("ip6_clearpktopts: invalid argument\n"); - return (NULL); + return (EINVAL); } - dst = malloc(sizeof(*dst), M_IP6OPT, canwait); - if (dst == NULL && canwait == M_NOWAIT) - return (NULL); - bzero(dst, sizeof(*dst)); - dst->needfree = 1; - dst->ip6po_hlim = src->ip6po_hlim; dst->ip6po_tclass = src->ip6po_tclass; dst->ip6po_flags = src->ip6po_flags; @@ -2612,7 +2600,7 @@ ip6_copypktopts(src, canwait) PKTOPT_EXTHDRCPY(ip6po_dest1); PKTOPT_EXTHDRCPY(ip6po_dest2); PKTOPT_EXTHDRCPY(ip6po_rthdr); /* not copy the cached route */ - return (dst); + return (0); bad: if (dst->ip6po_pktinfo) free(dst->ip6po_pktinfo, M_IP6OPT); @@ -2621,11 +2609,31 @@ ip6_copypktopts(src, canwait) if (dst->ip6po_dest1) free(dst->ip6po_dest1, M_IP6OPT); if (dst->ip6po_dest2) free(dst->ip6po_dest2, M_IP6OPT); if (dst->ip6po_rthdr) free(dst->ip6po_rthdr, M_IP6OPT); - free(dst, M_IP6OPT); - return (NULL); + return (ENOBUFS); } #undef PKTOPT_EXTHDRCPY +struct ip6_pktopts * +ip6_copypktopts(src, canwait) + struct ip6_pktopts *src; + int canwait; +{ + int error; + struct ip6_pktopts *dst; + + dst = malloc(sizeof(*dst), M_IP6OPT, canwait); + if (dst == NULL && canwait == M_NOWAIT) + return (NULL); + ip6_initpktopts(dst); + + if ((error = copypktopts(dst, src, canwait)) != 0) { + free(dst, M_IP6OPT); + return (NULL); + } + + return (dst); +} + void ip6_freepcbopts(pktopt) struct ip6_pktopts *pktopt; @@ -2998,33 +3006,32 @@ ip6_freemoptions(im6o) * Set IPv6 outgoing packet options based on advanced API. */ int -ip6_setpktopts(control, opt, stickyopt, priv, needcopy, uproto) +ip6_setpktopts(control, opt, stickyopt, priv, uproto) struct mbuf *control; struct ip6_pktopts *opt, *stickyopt; - int priv, needcopy, uproto; + int priv, uproto; { struct cmsghdr *cm = 0; if (control == NULL || opt == NULL) return (EINVAL); + ip6_initpktopts(opt); if (stickyopt) { + int error; + /* * If stickyopt is provided, make a local copy of the options * for this particular packet, then override them by ancillary * objects. - * XXX: need to gain a reference for the cached route of the - * next hop in case of the overriding. + * XXX: copypktopts() does not copy the cached route to a next + * hop (if any). This is not very good in terms of efficiency, + * but we can allow this since this option should be rarely + * used. */ - *opt = *stickyopt; - if (opt->ip6po_nextroute.ro_rt) { - RT_LOCK(opt->ip6po_nextroute.ro_rt); - RT_ADDREF(opt->ip6po_nextroute.ro_rt); - RT_UNLOCK(opt->ip6po_nextroute.ro_rt); - } - } else - ip6_initpktopts(opt); - opt->needfree = needcopy; + if ((error = copypktopts(opt, stickyopt, M_NOWAIT)) != 0) + return (error); + } /* * XXX: Currently, we assume all the optional information is stored @@ -3047,7 +3054,7 @@ ip6_setpktopts(control, opt, stickyopt, priv, needcopy, uproto) continue; error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm), - cm->cmsg_len - CMSG_LEN(0), opt, priv, needcopy, 1, uproto); + cm->cmsg_len - CMSG_LEN(0), opt, priv, 0, 1, uproto); if (error) return (error); } @@ -3164,14 +3171,13 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto) * XXX: the delay of the validation may confuse the * application when it is used as a sticky option. */ - if (sticky) { - if (opt->ip6po_pktinfo == NULL) { - opt->ip6po_pktinfo = malloc(sizeof(*pktinfo), - M_IP6OPT, M_WAITOK); - } - bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo)); - } else - opt->ip6po_pktinfo = pktinfo; + if (opt->ip6po_pktinfo == NULL) { + opt->ip6po_pktinfo = malloc(sizeof(*pktinfo), + M_IP6OPT, M_NOWAIT); + if (opt->ip6po_pktinfo == NULL) + return (ENOBUFS); + } + bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo)); break; } @@ -3256,11 +3262,8 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto) /* turn off the previous option, then set the new option. */ ip6_clearpktopts(opt, IPV6_NEXTHOP); - if (sticky) { - opt->ip6po_nexthop = malloc(*buf, M_IP6OPT, M_WAITOK); - bcopy(buf, opt->ip6po_nexthop, *buf); - } else - opt->ip6po_nexthop = (struct sockaddr *)buf; + opt->ip6po_nexthop = malloc(*buf, M_IP6OPT, M_WAITOK); + bcopy(buf, opt->ip6po_nexthop, *buf); break; case IPV6_2292HOPOPTS: @@ -3292,11 +3295,8 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto) /* turn off the previous option, then set the new option. */ ip6_clearpktopts(opt, IPV6_HOPOPTS); - if (sticky) { - opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_WAITOK); - bcopy(hbh, opt->ip6po_hbh, hbhlen); - } else - opt->ip6po_hbh = hbh; + opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_WAITOK); + bcopy(hbh, opt->ip6po_hbh, hbhlen); break; } @@ -3357,11 +3357,8 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto) /* turn off the previous option, then set the new option. */ ip6_clearpktopts(opt, optname); - if (sticky) { - *newdest = malloc(destlen, M_IP6OPT, M_WAITOK); - bcopy(dest, *newdest, destlen); - } else - *newdest = dest; + *newdest = malloc(destlen, M_IP6OPT, M_WAITOK); + bcopy(dest, *newdest, destlen); break; } @@ -3400,11 +3397,8 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto) /* turn off the previous option */ ip6_clearpktopts(opt, IPV6_RTHDR); - if (sticky) { - opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_WAITOK); - bcopy(rth, opt->ip6po_rthdr, rthlen); - } else - opt->ip6po_rthdr = rth; + opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_WAITOK); + bcopy(rth, opt->ip6po_rthdr, rthlen); break; } diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index 7f2a862..090dc31 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -173,8 +173,6 @@ struct ip6_pktopts { #endif #define IP6PO_DONTFRAG 0x04 /* disable fragmentation (IPV6_DONTFRAG) */ #define IP6PO_USECOA 0x08 /* use care of address */ - - int needfree; /* members dynamically allocated */ }; /* @@ -368,7 +366,7 @@ int ip6_ctloutput __P((struct socket *, struct sockopt *)); int ip6_raw_ctloutput __P((struct socket *, struct sockopt *)); void ip6_initpktopts __P((struct ip6_pktopts *)); int ip6_setpktopts __P((struct mbuf *, struct ip6_pktopts *, - struct ip6_pktopts *, int, int, int)); + struct ip6_pktopts *, int, int)); void ip6_clearpktopts __P((struct ip6_pktopts *, int)); struct ip6_pktopts *ip6_copypktopts __P((struct ip6_pktopts *, int)); int ip6_optlen __P((struct inpcb *)); diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c index d89d9f3..64304ac 100644 --- a/sys/netinet6/raw_ip6.c +++ b/sys/netinet6/raw_ip6.c @@ -346,7 +346,7 @@ rip6_output(m, va_alist) dst = &dstsock->sin6_addr; if (control) { if ((error = ip6_setpktopts(control, &opt, - in6p->in6p_outputopts, priv, 0, so->so_proto->pr_protocol)) + in6p->in6p_outputopts, priv, so->so_proto->pr_protocol)) != 0) { goto bad; } diff --git a/sys/netinet6/udp6_output.c b/sys/netinet6/udp6_output.c index a1a07be..933e3b3 100644 --- a/sys/netinet6/udp6_output.c +++ b/sys/netinet6/udp6_output.c @@ -141,7 +141,7 @@ udp6_output(in6p, m, addr6, control, td) priv = 1; if (control) { if ((error = ip6_setpktopts(control, &opt, - in6p->in6p_outputopts, priv, 0, IPPROTO_UDP)) != 0) + in6p->in6p_outputopts, priv, IPPROTO_UDP)) != 0) goto release; optp = &opt; } else |