Annotation of sys/netinet/ip_output.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ip_output.c,v 1.188 2007/07/20 19:00:35 claudio Exp $ */
2: /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1982, 1986, 1988, 1990, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. Neither the name of the University nor the names of its contributors
17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: *
32: * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
33: */
34:
35: #include "pf.h"
36:
37: #include <sys/param.h>
38: #include <sys/systm.h>
39: #include <sys/mbuf.h>
40: #include <sys/protosw.h>
41: #include <sys/socket.h>
42: #include <sys/socketvar.h>
43: #include <sys/proc.h>
44: #include <sys/kernel.h>
45:
46: #include <net/if.h>
47: #include <net/if_enc.h>
48: #include <net/route.h>
49:
50: #include <netinet/in.h>
51: #include <netinet/in_systm.h>
52: #include <netinet/ip.h>
53: #include <netinet/in_pcb.h>
54: #include <netinet/in_var.h>
55: #include <netinet/ip_var.h>
56: #include <netinet/ip_icmp.h>
57: #include <netinet/tcp.h>
58: #include <netinet/udp.h>
59: #include <netinet/tcp_timer.h>
60: #include <netinet/tcp_var.h>
61: #include <netinet/udp_var.h>
62:
63: #if NPF > 0
64: #include <net/pfvar.h>
65: #endif
66:
67: #ifdef IPSEC
68: #ifdef ENCDEBUG
69: #define DPRINTF(x) do { if (encdebug) printf x ; } while (0)
70: #else
71: #define DPRINTF(x)
72: #endif
73:
74: extern u_int8_t get_sa_require(struct inpcb *);
75:
76: extern int ipsec_auth_default_level;
77: extern int ipsec_esp_trans_default_level;
78: extern int ipsec_esp_network_default_level;
79: extern int ipsec_ipcomp_default_level;
80: extern int ipforwarding;
81: #endif /* IPSEC */
82:
83: #ifdef MROUTING
84: extern int ipmforwarding;
85: #endif
86:
87: struct mbuf *ip_insertoptions(struct mbuf *, struct mbuf *, int *);
88: void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *);
89:
90: /*
91: * IP output. The packet in mbuf chain m contains a skeletal IP
92: * header (with len, off, ttl, proto, tos, src, dst).
93: * The mbuf chain containing the packet will be freed.
94: * The mbuf opt, if present, will not be freed.
95: */
96: int
97: ip_output(struct mbuf *m0, ...)
98: {
99: struct ip *ip;
100: struct ifnet *ifp;
101: struct mbuf *m = m0;
102: int hlen = sizeof (struct ip);
103: int len, error = 0;
104: struct route iproute;
105: struct sockaddr_in *dst;
106: struct in_ifaddr *ia;
107: struct mbuf *opt;
108: struct route *ro;
109: int flags;
110: struct ip_moptions *imo;
111: va_list ap;
112: u_int8_t sproto = 0, donerouting = 0;
113: u_long mtu;
114: #ifdef IPSEC
115: u_int32_t icmp_mtu = 0;
116: union sockaddr_union sdst;
117: u_int32_t sspi;
118: struct m_tag *mtag;
119: struct tdb_ident *tdbi;
120:
121: struct inpcb *inp;
122: struct tdb *tdb;
123: int s;
124: #endif /* IPSEC */
125:
126: va_start(ap, m0);
127: opt = va_arg(ap, struct mbuf *);
128: ro = va_arg(ap, struct route *);
129: flags = va_arg(ap, int);
130: imo = va_arg(ap, struct ip_moptions *);
131: #ifdef IPSEC
132: inp = va_arg(ap, struct inpcb *);
133: if (inp && (inp->inp_flags & INP_IPV6) != 0)
134: panic("ip_output: IPv6 pcb is passed");
135: #endif /* IPSEC */
136: va_end(ap);
137:
138: #ifdef DIAGNOSTIC
139: if ((m->m_flags & M_PKTHDR) == 0)
140: panic("ip_output no HDR");
141: #endif
142: if (opt) {
143: m = ip_insertoptions(m, opt, &len);
144: hlen = len;
145: }
146:
147: ip = mtod(m, struct ip *);
148:
149: /*
150: * Fill in IP header.
151: */
152: if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) {
153: ip->ip_v = IPVERSION;
154: ip->ip_off &= htons(IP_DF);
155: ip->ip_id = htons(ip_randomid());
156: ip->ip_hl = hlen >> 2;
157: ipstat.ips_localout++;
158: } else {
159: hlen = ip->ip_hl << 2;
160: }
161:
162: /*
163: * If we're missing the IP source address, do a route lookup. We'll
164: * remember this result, in case we don't need to do any IPsec
165: * processing on the packet. We need the source address so we can
166: * do an SPD lookup in IPsec; for most packets, the source address
167: * is set at a higher level protocol. ICMPs and other packets
168: * though (e.g., traceroute) have a source address of zeroes.
169: */
170: if (ip->ip_src.s_addr == INADDR_ANY) {
171: if (flags & IP_ROUTETOETHER) {
172: error = EINVAL;
173: goto bad;
174: }
175: donerouting = 1;
176:
177: if (ro == 0) {
178: ro = &iproute;
179: bzero((caddr_t)ro, sizeof (*ro));
180: }
181:
182: dst = satosin(&ro->ro_dst);
183:
184: /*
185: * If there is a cached route, check that it is to the same
186: * destination and is still up. If not, free it and try again.
187: */
188: if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
189: dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
190: RTFREE(ro->ro_rt);
191: ro->ro_rt = (struct rtentry *)0;
192: }
193:
194: if (ro->ro_rt == 0) {
195: dst->sin_family = AF_INET;
196: dst->sin_len = sizeof(*dst);
197: dst->sin_addr = ip->ip_dst;
198: }
199:
200: /*
201: * If routing to interface only, short-circuit routing lookup.
202: */
203: if (flags & IP_ROUTETOIF) {
204: if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 &&
205: (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) {
206: ipstat.ips_noroute++;
207: error = ENETUNREACH;
208: goto bad;
209: }
210:
211: ifp = ia->ia_ifp;
212: mtu = ifp->if_mtu;
213: ip->ip_ttl = 1;
214: } else if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
215: (ip->ip_dst.s_addr == INADDR_BROADCAST)) &&
216: imo != NULL && imo->imo_multicast_ifp != NULL) {
217: ifp = imo->imo_multicast_ifp;
218: mtu = ifp->if_mtu;
219: IFP_TO_IA(ifp, ia);
220: } else {
221: if (ro->ro_rt == 0)
222: rtalloc_mpath(ro, NULL, 0);
223:
224: if (ro->ro_rt == 0) {
225: ipstat.ips_noroute++;
226: error = EHOSTUNREACH;
227: goto bad;
228: }
229:
230: ia = ifatoia(ro->ro_rt->rt_ifa);
231: ifp = ro->ro_rt->rt_ifp;
232: if ((mtu = ro->ro_rt->rt_rmx.rmx_mtu) == 0)
233: mtu = ifp->if_mtu;
234: ro->ro_rt->rt_use++;
235:
236: if (ro->ro_rt->rt_flags & RTF_GATEWAY)
237: dst = satosin(ro->ro_rt->rt_gateway);
238: }
239:
240: /* Set the source IP address */
241: if (!IN_MULTICAST(ip->ip_dst.s_addr))
242: ip->ip_src = ia->ia_addr.sin_addr;
243: }
244:
245: #ifdef IPSEC
246: if (!ipsec_in_use && inp == NULL)
247: goto done_spd;
248:
249: /*
250: * splnet is chosen over spltdb because we are not allowed to
251: * lower the level, and udp_output calls us in splnet().
252: */
253: s = splnet();
254:
255: /* Do we have any pending SAs to apply ? */
256: mtag = m_tag_find(m, PACKET_TAG_IPSEC_PENDING_TDB, NULL);
257: if (mtag != NULL) {
258: #ifdef DIAGNOSTIC
259: if (mtag->m_tag_len != sizeof (struct tdb_ident))
260: panic("ip_output: tag of length %d (should be %d",
261: mtag->m_tag_len, sizeof (struct tdb_ident));
262: #endif
263: tdbi = (struct tdb_ident *)(mtag + 1);
264: tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto);
265: if (tdb == NULL)
266: error = -EINVAL;
267: m_tag_delete(m, mtag);
268: }
269: else
270: tdb = ipsp_spd_lookup(m, AF_INET, hlen, &error,
271: IPSP_DIRECTION_OUT, NULL, inp);
272:
273: if (tdb == NULL) {
274: splx(s);
275:
276: if (error == 0) {
277: /*
278: * No IPsec processing required, we'll just send the
279: * packet out.
280: */
281: sproto = 0;
282:
283: /* Fall through to routing/multicast handling */
284: } else {
285: /*
286: * -EINVAL is used to indicate that the packet should
287: * be silently dropped, typically because we've asked
288: * key management for an SA.
289: */
290: if (error == -EINVAL) /* Should silently drop packet */
291: error = 0;
292:
293: m_freem(m);
294: goto done;
295: }
296: } else {
297: /* Loop detection */
298: for (mtag = m_tag_first(m); mtag != NULL;
299: mtag = m_tag_next(m, mtag)) {
300: if (mtag->m_tag_id != PACKET_TAG_IPSEC_OUT_DONE &&
301: mtag->m_tag_id !=
302: PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED)
303: continue;
304: tdbi = (struct tdb_ident *)(mtag + 1);
305: if (tdbi->spi == tdb->tdb_spi &&
306: tdbi->proto == tdb->tdb_sproto &&
307: !bcmp(&tdbi->dst, &tdb->tdb_dst,
308: sizeof(union sockaddr_union))) {
309: splx(s);
310: sproto = 0; /* mark as no-IPsec-needed */
311: goto done_spd;
312: }
313: }
314:
315: /* We need to do IPsec */
316: bcopy(&tdb->tdb_dst, &sdst, sizeof(sdst));
317: sspi = tdb->tdb_spi;
318: sproto = tdb->tdb_sproto;
319: splx(s);
320:
321: /*
322: * If it needs TCP/UDP hardware-checksumming, do the
323: * computation now.
324: */
325: if (m->m_pkthdr.csum_flags & (M_TCPV4_CSUM_OUT | M_UDPV4_CSUM_OUT)) {
326: in_delayed_cksum(m);
327: m->m_pkthdr.csum_flags &=
328: ~(M_UDPV4_CSUM_OUT | M_TCPV4_CSUM_OUT);
329: }
330:
331: /* If it's not a multicast packet, try to fast-path */
332: if (!IN_MULTICAST(ip->ip_dst.s_addr)) {
333: goto sendit;
334: }
335: }
336:
337: /* Fall through to the routing/multicast handling code */
338: done_spd:
339: #endif /* IPSEC */
340:
341: if (flags & IP_ROUTETOETHER) {
342: dst = satosin(&ro->ro_dst);
343: ifp = ro->ro_rt->rt_ifp;
344: mtu = ifp->if_mtu;
345: ro->ro_rt = NULL;
346: } else if (donerouting == 0) {
347: if (ro == 0) {
348: ro = &iproute;
349: bzero((caddr_t)ro, sizeof (*ro));
350: }
351:
352: dst = satosin(&ro->ro_dst);
353:
354: /*
355: * If there is a cached route, check that it is to the same
356: * destination and is still up. If not, free it and try again.
357: */
358: if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
359: dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
360: RTFREE(ro->ro_rt);
361: ro->ro_rt = (struct rtentry *)0;
362: }
363:
364: if (ro->ro_rt == 0) {
365: dst->sin_family = AF_INET;
366: dst->sin_len = sizeof(*dst);
367: dst->sin_addr = ip->ip_dst;
368: }
369:
370: /*
371: * If routing to interface only, short-circuit routing lookup.
372: */
373: if (flags & IP_ROUTETOIF) {
374: if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 &&
375: (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) {
376: ipstat.ips_noroute++;
377: error = ENETUNREACH;
378: goto bad;
379: }
380:
381: ifp = ia->ia_ifp;
382: mtu = ifp->if_mtu;
383: ip->ip_ttl = 1;
384: } else if ((IN_MULTICAST(ip->ip_dst.s_addr) ||
385: (ip->ip_dst.s_addr == INADDR_BROADCAST)) &&
386: imo != NULL && imo->imo_multicast_ifp != NULL) {
387: ifp = imo->imo_multicast_ifp;
388: mtu = ifp->if_mtu;
389: IFP_TO_IA(ifp, ia);
390: } else {
391: if (ro->ro_rt == 0)
392: rtalloc_mpath(ro, &ip->ip_src.s_addr, 0);
393:
394: if (ro->ro_rt == 0) {
395: ipstat.ips_noroute++;
396: error = EHOSTUNREACH;
397: goto bad;
398: }
399:
400: ia = ifatoia(ro->ro_rt->rt_ifa);
401: ifp = ro->ro_rt->rt_ifp;
402: if ((mtu = ro->ro_rt->rt_rmx.rmx_mtu) == 0)
403: mtu = ifp->if_mtu;
404: ro->ro_rt->rt_use++;
405:
406: if (ro->ro_rt->rt_flags & RTF_GATEWAY)
407: dst = satosin(ro->ro_rt->rt_gateway);
408: }
409:
410: /* Set the source IP address */
411: if (ip->ip_src.s_addr == INADDR_ANY)
412: ip->ip_src = ia->ia_addr.sin_addr;
413: }
414:
415: if (IN_MULTICAST(ip->ip_dst.s_addr) ||
416: (ip->ip_dst.s_addr == INADDR_BROADCAST)) {
417: struct in_multi *inm;
418:
419: m->m_flags |= (ip->ip_dst.s_addr == INADDR_BROADCAST) ?
420: M_BCAST : M_MCAST;
421:
422: /*
423: * IP destination address is multicast. Make sure "dst"
424: * still points to the address in "ro". (It may have been
425: * changed to point to a gateway address, above.)
426: */
427: dst = satosin(&ro->ro_dst);
428:
429: /*
430: * See if the caller provided any multicast options
431: */
432: if (imo != NULL)
433: ip->ip_ttl = imo->imo_multicast_ttl;
434: else
435: ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
436:
437: /*
438: * if we don't know the outgoing ifp yet, we can't generate
439: * output
440: */
441: if (!ifp) {
442: ipstat.ips_noroute++;
443: error = EHOSTUNREACH;
444: goto bad;
445: }
446:
447: /*
448: * Confirm that the outgoing interface supports multicast,
449: * but only if the packet actually is going out on that
450: * interface (i.e., no IPsec is applied).
451: */
452: if ((((m->m_flags & M_MCAST) &&
453: (ifp->if_flags & IFF_MULTICAST) == 0) ||
454: ((m->m_flags & M_BCAST) &&
455: (ifp->if_flags & IFF_BROADCAST) == 0)) && (sproto == 0)) {
456: ipstat.ips_noroute++;
457: error = ENETUNREACH;
458: goto bad;
459: }
460:
461: /*
462: * If source address not specified yet, use address
463: * of outgoing interface.
464: */
465: if (ip->ip_src.s_addr == INADDR_ANY) {
466: struct in_ifaddr *ia;
467:
468: TAILQ_FOREACH(ia, &in_ifaddr, ia_list)
469: if (ia->ia_ifp == ifp) {
470: ip->ip_src = ia->ia_addr.sin_addr;
471: break;
472: }
473: }
474:
475: IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
476: if (inm != NULL &&
477: (imo == NULL || imo->imo_multicast_loop)) {
478: /*
479: * If we belong to the destination multicast group
480: * on the outgoing interface, and the caller did not
481: * forbid loopback, loop back a copy.
482: * Can't defer TCP/UDP checksumming, do the
483: * computation now.
484: */
485: if (m->m_pkthdr.csum_flags &
486: (M_TCPV4_CSUM_OUT | M_UDPV4_CSUM_OUT)) {
487: in_delayed_cksum(m);
488: m->m_pkthdr.csum_flags &=
489: ~(M_UDPV4_CSUM_OUT | M_TCPV4_CSUM_OUT);
490: }
491: ip_mloopback(ifp, m, dst);
492: }
493: #ifdef MROUTING
494: else {
495: /*
496: * If we are acting as a multicast router, perform
497: * multicast forwarding as if the packet had just
498: * arrived on the interface to which we are about
499: * to send. The multicast forwarding function
500: * recursively calls this function, using the
501: * IP_FORWARDING flag to prevent infinite recursion.
502: *
503: * Multicasts that are looped back by ip_mloopback(),
504: * above, will be forwarded by the ip_input() routine,
505: * if necessary.
506: */
507: extern struct socket *ip_mrouter;
508:
509: if (ipmforwarding && ip_mrouter &&
510: (flags & IP_FORWARDING) == 0) {
511: if (ip_mforward(m, ifp) != 0) {
512: m_freem(m);
513: goto done;
514: }
515: }
516: }
517: #endif
518: /*
519: * Multicasts with a time-to-live of zero may be looped-
520: * back, above, but must not be transmitted on a network.
521: * Also, multicasts addressed to the loopback interface
522: * are not sent -- the above call to ip_mloopback() will
523: * loop back a copy if this host actually belongs to the
524: * destination group on the loopback interface.
525: */
526: if (ip->ip_ttl == 0 || (ifp->if_flags & IFF_LOOPBACK) != 0) {
527: m_freem(m);
528: goto done;
529: }
530:
531: goto sendit;
532: }
533:
534: /*
535: * Look for broadcast address and and verify user is allowed to send
536: * such a packet; if the packet is going in an IPsec tunnel, skip
537: * this check.
538: */
539: if ((sproto == 0) && (in_broadcast(dst->sin_addr, ifp))) {
540: if ((ifp->if_flags & IFF_BROADCAST) == 0) {
541: error = EADDRNOTAVAIL;
542: goto bad;
543: }
544: if ((flags & IP_ALLOWBROADCAST) == 0) {
545: error = EACCES;
546: goto bad;
547: }
548:
549: /* Don't allow broadcast messages to be fragmented */
550: if (ntohs(ip->ip_len) > ifp->if_mtu) {
551: error = EMSGSIZE;
552: goto bad;
553: }
554: m->m_flags |= M_BCAST;
555: } else
556: m->m_flags &= ~M_BCAST;
557:
558: sendit:
559: /*
560: * If we're doing Path MTU discovery, we need to set DF unless
561: * the route's MTU is locked.
562: */
563: if ((flags & IP_MTUDISC) && ro && ro->ro_rt &&
564: (ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
565: ip->ip_off |= htons(IP_DF);
566:
567: #ifdef IPSEC
568: /*
569: * Check if the packet needs encapsulation.
570: */
571: if (sproto != 0) {
572: s = splnet();
573:
574: /*
575: * Packet filter
576: */
577: #if NPF > 0
578:
579: if (pf_test(PF_OUT, &encif[0].sc_if, &m, NULL) != PF_PASS) {
580: error = EHOSTUNREACH;
581: splx(s);
582: m_freem(m);
583: goto done;
584: }
585: if (m == NULL) {
586: splx(s);
587: goto done;
588: }
589: ip = mtod(m, struct ip *);
590: hlen = ip->ip_hl << 2;
591: #endif
592:
593: tdb = gettdb(sspi, &sdst, sproto);
594: if (tdb == NULL) {
595: DPRINTF(("ip_output: unknown TDB"));
596: error = EHOSTUNREACH;
597: splx(s);
598: m_freem(m);
599: goto done;
600: }
601:
602: /* Check if we are allowed to fragment */
603: if (ip_mtudisc && (ip->ip_off & htons(IP_DF)) && tdb->tdb_mtu &&
604: ntohs(ip->ip_len) > tdb->tdb_mtu &&
605: tdb->tdb_mtutimeout > time_second) {
606: struct rtentry *rt = NULL;
607: int rt_mtucloned = 0;
608: int transportmode = 0;
609:
610: transportmode = (tdb->tdb_dst.sa.sa_family == AF_INET) &&
611: (tdb->tdb_dst.sin.sin_addr.s_addr ==
612: ip->ip_dst.s_addr);
613: icmp_mtu = tdb->tdb_mtu;
614: splx(s);
615:
616: /* Find a host route to store the mtu in */
617: if (ro != NULL)
618: rt = ro->ro_rt;
619: /* but don't add a PMTU route for transport mode SAs */
620: if (transportmode)
621: rt = NULL;
622: else if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0) {
623: struct sockaddr_in dst = {
624: sizeof(struct sockaddr_in), AF_INET};
625: dst.sin_addr = ip->ip_dst;
626: rt = icmp_mtudisc_clone((struct sockaddr *)&dst);
627: rt_mtucloned = 1;
628: }
629: DPRINTF(("ip_output: spi %08x mtu %d rt %p cloned %d\n",
630: ntohl(tdb->tdb_spi), icmp_mtu, rt, rt_mtucloned));
631: if (rt != NULL) {
632: rt->rt_rmx.rmx_mtu = icmp_mtu;
633: if (ro && ro->ro_rt != NULL) {
634: RTFREE(ro->ro_rt);
635: ro->ro_rt = (struct rtentry *) 0;
636: rtalloc(ro);
637: }
638: if (rt_mtucloned)
639: rtfree(rt);
640: }
641: error = EMSGSIZE;
642: goto bad;
643: }
644:
645: /*
646: * Clear these -- they'll be set in the recursive invocation
647: * as needed.
648: */
649: m->m_flags &= ~(M_MCAST | M_BCAST);
650:
651: /* Callee frees mbuf */
652: error = ipsp_process_packet(m, tdb, AF_INET, 0);
653: splx(s);
654: return error; /* Nothing more to be done */
655: }
656:
657: /*
658: * If deferred crypto processing is needed, check that the
659: * interface supports it.
660: */
661: if (ipsec_in_use && (mtag = m_tag_find(m,
662: PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL)) != NULL &&
663: (ifp->if_capabilities & IFCAP_IPSEC) == 0) {
664: /* Notify IPsec to do its own crypto. */
665: ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
666: m_freem(m);
667: error = EHOSTUNREACH;
668: goto done;
669: }
670: #endif /* IPSEC */
671:
672: /* Catch routing changes wrt. hardware checksumming for TCP or UDP. */
673: if (m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT) {
674: if (!(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
675: ifp->if_bridge != NULL) {
676: in_delayed_cksum(m);
677: m->m_pkthdr.csum_flags &= ~M_TCPV4_CSUM_OUT; /* Clear */
678: }
679: } else if (m->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) {
680: if (!(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
681: ifp->if_bridge != NULL) {
682: in_delayed_cksum(m);
683: m->m_pkthdr.csum_flags &= ~M_UDPV4_CSUM_OUT; /* Clear */
684: }
685: }
686:
687: /*
688: * Packet filter
689: */
690: #if NPF > 0
691: if (pf_test(PF_OUT, ifp, &m, NULL) != PF_PASS) {
692: error = EHOSTUNREACH;
693: m_freem(m);
694: goto done;
695: }
696: if (m == NULL)
697: goto done;
698:
699: ip = mtod(m, struct ip *);
700: hlen = ip->ip_hl << 2;
701: #endif
702:
703: #ifdef IPSEC
704: if (ipsec_in_use && (flags & IP_FORWARDING) && (ipforwarding == 2) &&
705: (m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL) == NULL)) {
706: error = EHOSTUNREACH;
707: m_freem(m);
708: goto done;
709: }
710: #endif
711:
712: /* XXX
713: * Try to use jumbograms based on socket option, or the route
714: * or... for other reasons later on.
715: */
716: if ((flags & IP_JUMBO) && ro->ro_rt && (ro->ro_rt->rt_flags & RTF_JUMBO) &&
717: ro->ro_rt->rt_ifp)
718: mtu = ro->ro_rt->rt_ifp->if_hardmtu;
719:
720: /*
721: * If small enough for interface, can just send directly.
722: */
723: if (ntohs(ip->ip_len) <= mtu) {
724: if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
725: ifp->if_bridge == NULL) {
726: m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
727: ipstat.ips_outhwcsum++;
728: } else {
729: ip->ip_sum = 0;
730: ip->ip_sum = in_cksum(m, hlen);
731: }
732: /* Update relevant hardware checksum stats for TCP/UDP */
733: if (m->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT)
734: tcpstat.tcps_outhwcsum++;
735: else if (m->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT)
736: udpstat.udps_outhwcsum++;
737: error = (*ifp->if_output)(ifp, m, sintosa(dst), ro->ro_rt);
738: goto done;
739: }
740:
741: /*
742: * Too large for interface; fragment if possible.
743: * Must be able to put at least 8 bytes per fragment.
744: */
745: if (ip->ip_off & htons(IP_DF)) {
746: #ifdef IPSEC
747: icmp_mtu = ifp->if_mtu;
748: #endif
749: error = EMSGSIZE;
750: /*
751: * This case can happen if the user changed the MTU
752: * of an interface after enabling IP on it. Because
753: * most netifs don't keep track of routes pointing to
754: * them, there is no way for one to update all its
755: * routes when the MTU is changed.
756: */
757: if ((ro->ro_rt->rt_flags & (RTF_UP | RTF_HOST)) &&
758: !(ro->ro_rt->rt_rmx.rmx_locks & RTV_MTU) &&
759: (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)) {
760: ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu;
761: }
762: ipstat.ips_cantfrag++;
763: goto bad;
764: }
765:
766: error = ip_fragment(m, ifp, mtu);
767: if (error) {
768: m = m0 = NULL;
769: goto bad;
770: }
771:
772: for (; m; m = m0) {
773: m0 = m->m_nextpkt;
774: m->m_nextpkt = 0;
775: if (error == 0)
776: error = (*ifp->if_output)(ifp, m, sintosa(dst),
777: ro->ro_rt);
778: else
779: m_freem(m);
780: }
781:
782: if (error == 0)
783: ipstat.ips_fragmented++;
784:
785: done:
786: if (ro == &iproute && (flags & IP_ROUTETOIF) == 0 && ro->ro_rt)
787: RTFREE(ro->ro_rt);
788: return (error);
789: bad:
790: #ifdef IPSEC
791: if (error == EMSGSIZE && ip_mtudisc && icmp_mtu != 0 && m != NULL)
792: ipsec_adjust_mtu(m, icmp_mtu);
793: #endif
794: m_freem(m0);
795: goto done;
796: }
797:
798: int
799: ip_fragment(struct mbuf *m, struct ifnet *ifp, u_long mtu)
800: {
801: struct ip *ip, *mhip;
802: struct mbuf *m0;
803: int len, hlen, off;
804: int mhlen, firstlen;
805: struct mbuf **mnext;
806: int fragments = 0;
807: int s;
808: int error = 0;
809:
810: ip = mtod(m, struct ip *);
811: hlen = ip->ip_hl << 2;
812:
813: len = (mtu - hlen) &~ 7;
814: if (len < 8) {
815: m_freem(m);
816: return (EMSGSIZE);
817: }
818:
819: /*
820: * If we are doing fragmentation, we can't defer TCP/UDP
821: * checksumming; compute the checksum and clear the flag.
822: */
823: if (m->m_pkthdr.csum_flags & (M_TCPV4_CSUM_OUT | M_UDPV4_CSUM_OUT)) {
824: in_delayed_cksum(m);
825: m->m_pkthdr.csum_flags &= ~(M_UDPV4_CSUM_OUT | M_TCPV4_CSUM_OUT);
826: }
827:
828: firstlen = len;
829: mnext = &m->m_nextpkt;
830:
831: /*
832: * Loop through length of segment after first fragment,
833: * make new header and copy data of each part and link onto chain.
834: */
835: m0 = m;
836: mhlen = sizeof (struct ip);
837: for (off = hlen + len; off < ntohs(ip->ip_len); off += len) {
838: MGETHDR(m, M_DONTWAIT, MT_HEADER);
839: if (m == 0) {
840: ipstat.ips_odropped++;
841: error = ENOBUFS;
842: goto sendorfree;
843: }
844: *mnext = m;
845: mnext = &m->m_nextpkt;
846: m->m_data += max_linkhdr;
847: mhip = mtod(m, struct ip *);
848: *mhip = *ip;
849: /* we must inherit MCAST and BCAST flags */
850: m->m_flags |= m0->m_flags & (M_MCAST|M_BCAST);
851: if (hlen > sizeof (struct ip)) {
852: mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
853: mhip->ip_hl = mhlen >> 2;
854: }
855: m->m_len = mhlen;
856: mhip->ip_off = ((off - hlen) >> 3) +
857: (ntohs(ip->ip_off) & ~IP_MF);
858: if (ip->ip_off & htons(IP_MF))
859: mhip->ip_off |= IP_MF;
860: if (off + len >= ntohs(ip->ip_len))
861: len = ntohs(ip->ip_len) - off;
862: else
863: mhip->ip_off |= IP_MF;
864: mhip->ip_len = htons((u_int16_t)(len + mhlen));
865: m->m_next = m_copy(m0, off, len);
866: if (m->m_next == 0) {
867: ipstat.ips_odropped++;
868: error = ENOBUFS;
869: goto sendorfree;
870: }
871: m->m_pkthdr.len = mhlen + len;
872: m->m_pkthdr.rcvif = (struct ifnet *)0;
873: mhip->ip_off = htons((u_int16_t)mhip->ip_off);
874: if ((ifp != NULL) &&
875: (ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
876: ifp->if_bridge == NULL) {
877: m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
878: ipstat.ips_outhwcsum++;
879: } else {
880: mhip->ip_sum = 0;
881: mhip->ip_sum = in_cksum(m, mhlen);
882: }
883: ipstat.ips_ofragments++;
884: fragments++;
885: }
886: /*
887: * Update first fragment by trimming what's been copied out
888: * and updating header, then send each fragment (in order).
889: */
890: m = m0;
891: m_adj(m, hlen + firstlen - ntohs(ip->ip_len));
892: m->m_pkthdr.len = hlen + firstlen;
893: ip->ip_len = htons((u_int16_t)m->m_pkthdr.len);
894: ip->ip_off |= htons(IP_MF);
895: if ((ifp != NULL) &&
896: (ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
897: ifp->if_bridge == NULL) {
898: m->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
899: ipstat.ips_outhwcsum++;
900: } else {
901: ip->ip_sum = 0;
902: ip->ip_sum = in_cksum(m, hlen);
903: }
904: sendorfree:
905: /*
906: * If there is no room for all the fragments, don't queue
907: * any of them.
908: */
909: if (ifp != NULL) {
910: s = splnet();
911: if (ifp->if_snd.ifq_maxlen - ifp->if_snd.ifq_len < fragments &&
912: error == 0) {
913: error = ENOBUFS;
914: ipstat.ips_odropped++;
915: IFQ_INC_DROPS(&ifp->if_snd);
916: }
917: splx(s);
918: }
919: if (error) {
920: for (m = m0; m; m = m0) {
921: m0 = m->m_nextpkt;
922: m->m_nextpkt = NULL;
923: m_freem(m);
924: }
925: }
926:
927: return (error);
928: }
929:
930: /*
931: * Insert IP options into preformed packet.
932: * Adjust IP destination as required for IP source routing,
933: * as indicated by a non-zero in_addr at the start of the options.
934: */
935: struct mbuf *
936: ip_insertoptions(m, opt, phlen)
937: struct mbuf *m;
938: struct mbuf *opt;
939: int *phlen;
940: {
941: struct ipoption *p = mtod(opt, struct ipoption *);
942: struct mbuf *n;
943: struct ip *ip = mtod(m, struct ip *);
944: unsigned optlen;
945:
946: optlen = opt->m_len - sizeof(p->ipopt_dst);
947: if (optlen + ntohs(ip->ip_len) > IP_MAXPACKET)
948: return (m); /* XXX should fail */
949: if (p->ipopt_dst.s_addr)
950: ip->ip_dst = p->ipopt_dst;
951: if (m->m_flags & M_EXT || m->m_data - optlen < m->m_pktdat) {
952: MGETHDR(n, M_DONTWAIT, MT_HEADER);
953: if (n == 0)
954: return (m);
955: M_MOVE_HDR(n, m);
956: n->m_pkthdr.len += optlen;
957: m->m_len -= sizeof(struct ip);
958: m->m_data += sizeof(struct ip);
959: n->m_next = m;
960: m = n;
961: m->m_len = optlen + sizeof(struct ip);
962: m->m_data += max_linkhdr;
963: bcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
964: } else {
965: m->m_data -= optlen;
966: m->m_len += optlen;
967: m->m_pkthdr.len += optlen;
968: ovbcopy((caddr_t)ip, mtod(m, caddr_t), sizeof(struct ip));
969: }
970: ip = mtod(m, struct ip *);
971: bcopy((caddr_t)p->ipopt_list, (caddr_t)(ip + 1), (unsigned)optlen);
972: *phlen = sizeof(struct ip) + optlen;
973: ip->ip_len = htons(ntohs(ip->ip_len) + optlen);
974: return (m);
975: }
976:
977: /*
978: * Copy options from ip to jp,
979: * omitting those not copied during fragmentation.
980: */
981: int
982: ip_optcopy(ip, jp)
983: struct ip *ip, *jp;
984: {
985: u_char *cp, *dp;
986: int opt, optlen, cnt;
987:
988: cp = (u_char *)(ip + 1);
989: dp = (u_char *)(jp + 1);
990: cnt = (ip->ip_hl << 2) - sizeof (struct ip);
991: for (; cnt > 0; cnt -= optlen, cp += optlen) {
992: opt = cp[0];
993: if (opt == IPOPT_EOL)
994: break;
995: if (opt == IPOPT_NOP) {
996: /* Preserve for IP mcast tunnel's LSRR alignment. */
997: *dp++ = IPOPT_NOP;
998: optlen = 1;
999: continue;
1000: }
1001: #ifdef DIAGNOSTIC
1002: if (cnt < IPOPT_OLEN + sizeof(*cp))
1003: panic("malformed IPv4 option passed to ip_optcopy");
1004: #endif
1005: optlen = cp[IPOPT_OLEN];
1006: #ifdef DIAGNOSTIC
1007: if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt)
1008: panic("malformed IPv4 option passed to ip_optcopy");
1009: #endif
1010: /* bogus lengths should have been caught by ip_dooptions */
1011: if (optlen > cnt)
1012: optlen = cnt;
1013: if (IPOPT_COPIED(opt)) {
1014: bcopy((caddr_t)cp, (caddr_t)dp, (unsigned)optlen);
1015: dp += optlen;
1016: }
1017: }
1018: for (optlen = dp - (u_char *)(jp+1); optlen & 0x3; optlen++)
1019: *dp++ = IPOPT_EOL;
1020: return (optlen);
1021: }
1022:
1023: /*
1024: * IP socket option processing.
1025: */
1026: int
1027: ip_ctloutput(op, so, level, optname, mp)
1028: int op;
1029: struct socket *so;
1030: int level, optname;
1031: struct mbuf **mp;
1032: {
1033: struct inpcb *inp = sotoinpcb(so);
1034: struct mbuf *m = *mp;
1035: int optval = 0;
1036: #ifdef IPSEC
1037: struct proc *p = curproc; /* XXX */
1038: struct ipsec_ref *ipr;
1039: u_int16_t opt16val;
1040: #endif
1041: int error = 0;
1042:
1043: if (level != IPPROTO_IP) {
1044: error = EINVAL;
1045: if (op == PRCO_SETOPT && *mp)
1046: (void) m_free(*mp);
1047: } else switch (op) {
1048: case PRCO_SETOPT:
1049: switch (optname) {
1050: case IP_OPTIONS:
1051: #ifdef notyet
1052: case IP_RETOPTS:
1053: return (ip_pcbopts(optname, &inp->inp_options, m));
1054: #else
1055: return (ip_pcbopts(&inp->inp_options, m));
1056: #endif
1057:
1058: case IP_TOS:
1059: case IP_TTL:
1060: case IP_MINTTL:
1061: case IP_RECVOPTS:
1062: case IP_RECVRETOPTS:
1063: case IP_RECVDSTADDR:
1064: case IP_RECVIF:
1065: case IP_RECVTTL:
1066: if (m == NULL || m->m_len != sizeof(int))
1067: error = EINVAL;
1068: else {
1069: optval = *mtod(m, int *);
1070: switch (optname) {
1071:
1072: case IP_TOS:
1073: inp->inp_ip.ip_tos = optval;
1074: break;
1075:
1076: case IP_TTL:
1077: if (optval > 0 && optval <= MAXTTL)
1078: inp->inp_ip.ip_ttl = optval;
1079: else
1080: error = EINVAL;
1081: break;
1082:
1083: case IP_MINTTL:
1084: if (optval > 0 && optval <= MAXTTL)
1085: inp->inp_ip_minttl = optval;
1086: else
1087: error = EINVAL;
1088: break;
1089: #define OPTSET(bit) \
1090: if (optval) \
1091: inp->inp_flags |= bit; \
1092: else \
1093: inp->inp_flags &= ~bit;
1094:
1095: case IP_RECVOPTS:
1096: OPTSET(INP_RECVOPTS);
1097: break;
1098:
1099: case IP_RECVRETOPTS:
1100: OPTSET(INP_RECVRETOPTS);
1101: break;
1102:
1103: case IP_RECVDSTADDR:
1104: OPTSET(INP_RECVDSTADDR);
1105: break;
1106: case IP_RECVIF:
1107: OPTSET(INP_RECVIF);
1108: break;
1109: case IP_RECVTTL:
1110: OPTSET(INP_RECVTTL);
1111: break;
1112: }
1113: }
1114: break;
1115: #undef OPTSET
1116:
1117: case IP_MULTICAST_IF:
1118: case IP_MULTICAST_TTL:
1119: case IP_MULTICAST_LOOP:
1120: case IP_ADD_MEMBERSHIP:
1121: case IP_DROP_MEMBERSHIP:
1122: error = ip_setmoptions(optname, &inp->inp_moptions, m);
1123: break;
1124:
1125: case IP_PORTRANGE:
1126: if (m == 0 || m->m_len != sizeof(int))
1127: error = EINVAL;
1128: else {
1129: optval = *mtod(m, int *);
1130:
1131: switch (optval) {
1132:
1133: case IP_PORTRANGE_DEFAULT:
1134: inp->inp_flags &= ~(INP_LOWPORT);
1135: inp->inp_flags &= ~(INP_HIGHPORT);
1136: break;
1137:
1138: case IP_PORTRANGE_HIGH:
1139: inp->inp_flags &= ~(INP_LOWPORT);
1140: inp->inp_flags |= INP_HIGHPORT;
1141: break;
1142:
1143: case IP_PORTRANGE_LOW:
1144: inp->inp_flags &= ~(INP_HIGHPORT);
1145: inp->inp_flags |= INP_LOWPORT;
1146: break;
1147:
1148: default:
1149:
1150: error = EINVAL;
1151: break;
1152: }
1153: }
1154: break;
1155: case IP_AUTH_LEVEL:
1156: case IP_ESP_TRANS_LEVEL:
1157: case IP_ESP_NETWORK_LEVEL:
1158: case IP_IPCOMP_LEVEL:
1159: #ifndef IPSEC
1160: error = EOPNOTSUPP;
1161: #else
1162: if (m == 0 || m->m_len != sizeof(int)) {
1163: error = EINVAL;
1164: break;
1165: }
1166: optval = *mtod(m, int *);
1167:
1168: if (optval < IPSEC_LEVEL_BYPASS ||
1169: optval > IPSEC_LEVEL_UNIQUE) {
1170: error = EINVAL;
1171: break;
1172: }
1173:
1174: /* Unlink cached output TDB to force a re-search */
1175: if (inp->inp_tdb_out) {
1176: int s = spltdb();
1177: TAILQ_REMOVE(&inp->inp_tdb_out->tdb_inp_out,
1178: inp, inp_tdb_out_next);
1179: splx(s);
1180: }
1181:
1182: if (inp->inp_tdb_in) {
1183: int s = spltdb();
1184: TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in,
1185: inp, inp_tdb_in_next);
1186: splx(s);
1187: }
1188:
1189: switch (optname) {
1190: case IP_AUTH_LEVEL:
1191: if (optval < ipsec_auth_default_level &&
1192: suser(p, 0)) {
1193: error = EACCES;
1194: break;
1195: }
1196: inp->inp_seclevel[SL_AUTH] = optval;
1197: break;
1198:
1199: case IP_ESP_TRANS_LEVEL:
1200: if (optval < ipsec_esp_trans_default_level &&
1201: suser(p, 0)) {
1202: error = EACCES;
1203: break;
1204: }
1205: inp->inp_seclevel[SL_ESP_TRANS] = optval;
1206: break;
1207:
1208: case IP_ESP_NETWORK_LEVEL:
1209: if (optval < ipsec_esp_network_default_level &&
1210: suser(p, 0)) {
1211: error = EACCES;
1212: break;
1213: }
1214: inp->inp_seclevel[SL_ESP_NETWORK] = optval;
1215: break;
1216: case IP_IPCOMP_LEVEL:
1217: if (optval < ipsec_ipcomp_default_level &&
1218: suser(p, 0)) {
1219: error = EACCES;
1220: break;
1221: }
1222: inp->inp_seclevel[SL_IPCOMP] = optval;
1223: break;
1224: }
1225: if (!error)
1226: inp->inp_secrequire = get_sa_require(inp);
1227: #endif
1228: break;
1229:
1230: case IP_IPSEC_REMOTE_CRED:
1231: case IP_IPSEC_REMOTE_AUTH:
1232: /* Can't set the remote credential or key */
1233: error = EOPNOTSUPP;
1234: break;
1235:
1236: case IP_IPSEC_LOCAL_ID:
1237: case IP_IPSEC_REMOTE_ID:
1238: case IP_IPSEC_LOCAL_CRED:
1239: case IP_IPSEC_LOCAL_AUTH:
1240: #ifndef IPSEC
1241: error = EOPNOTSUPP;
1242: #else
1243: if (m->m_len < 2) {
1244: error = EINVAL;
1245: break;
1246: }
1247:
1248: m_copydata(m, 0, 2, (caddr_t) &opt16val);
1249:
1250: /* If the type is 0, then we cleanup and return */
1251: if (opt16val == 0) {
1252: switch (optname) {
1253: case IP_IPSEC_LOCAL_ID:
1254: if (inp->inp_ipo != NULL &&
1255: inp->inp_ipo->ipo_srcid != NULL) {
1256: ipsp_reffree(inp->inp_ipo->ipo_srcid);
1257: inp->inp_ipo->ipo_srcid = NULL;
1258: }
1259: break;
1260:
1261: case IP_IPSEC_REMOTE_ID:
1262: if (inp->inp_ipo != NULL &&
1263: inp->inp_ipo->ipo_dstid != NULL) {
1264: ipsp_reffree(inp->inp_ipo->ipo_dstid);
1265: inp->inp_ipo->ipo_dstid = NULL;
1266: }
1267: break;
1268:
1269: case IP_IPSEC_LOCAL_CRED:
1270: if (inp->inp_ipo != NULL &&
1271: inp->inp_ipo->ipo_local_cred != NULL) {
1272: ipsp_reffree(inp->inp_ipo->ipo_local_cred);
1273: inp->inp_ipo->ipo_local_cred = NULL;
1274: }
1275: break;
1276:
1277: case IP_IPSEC_LOCAL_AUTH:
1278: if (inp->inp_ipo != NULL &&
1279: inp->inp_ipo->ipo_local_auth != NULL) {
1280: ipsp_reffree(inp->inp_ipo->ipo_local_auth);
1281: inp->inp_ipo->ipo_local_auth = NULL;
1282: }
1283: break;
1284: }
1285:
1286: error = 0;
1287: break;
1288: }
1289:
1290: /* Can't have an empty payload */
1291: if (m->m_len == 2) {
1292: error = EINVAL;
1293: break;
1294: }
1295:
1296: /* Allocate if needed */
1297: if (inp->inp_ipo == NULL) {
1298: inp->inp_ipo = ipsec_add_policy(inp,
1299: AF_INET, IPSP_DIRECTION_OUT);
1300: if (inp->inp_ipo == NULL) {
1301: error = ENOBUFS;
1302: break;
1303: }
1304: }
1305:
1306: MALLOC(ipr, struct ipsec_ref *,
1307: sizeof(struct ipsec_ref) + m->m_len - 2,
1308: M_CREDENTIALS, M_NOWAIT);
1309: if (ipr == NULL) {
1310: error = ENOBUFS;
1311: break;
1312: }
1313:
1314: ipr->ref_count = 1;
1315: ipr->ref_malloctype = M_CREDENTIALS;
1316: ipr->ref_len = m->m_len - 2;
1317: ipr->ref_type = opt16val;
1318: m_copydata(m, 2, m->m_len - 2, (caddr_t)(ipr + 1));
1319:
1320: switch (optname) {
1321: case IP_IPSEC_LOCAL_ID:
1322: /* Check valid types and NUL-termination */
1323: if (ipr->ref_type < IPSP_IDENTITY_PREFIX ||
1324: ipr->ref_type > IPSP_IDENTITY_CONNECTION ||
1325: ((char *)(ipr + 1))[ipr->ref_len - 1]) {
1326: FREE(ipr, M_CREDENTIALS);
1327: error = EINVAL;
1328: } else {
1329: if (inp->inp_ipo->ipo_srcid != NULL)
1330: ipsp_reffree(inp->inp_ipo->ipo_srcid);
1331: inp->inp_ipo->ipo_srcid = ipr;
1332: }
1333: break;
1334: case IP_IPSEC_REMOTE_ID:
1335: /* Check valid types and NUL-termination */
1336: if (ipr->ref_type < IPSP_IDENTITY_PREFIX ||
1337: ipr->ref_type > IPSP_IDENTITY_CONNECTION ||
1338: ((char *)(ipr + 1))[ipr->ref_len - 1]) {
1339: FREE(ipr, M_CREDENTIALS);
1340: error = EINVAL;
1341: } else {
1342: if (inp->inp_ipo->ipo_dstid != NULL)
1343: ipsp_reffree(inp->inp_ipo->ipo_dstid);
1344: inp->inp_ipo->ipo_dstid = ipr;
1345: }
1346: break;
1347: case IP_IPSEC_LOCAL_CRED:
1348: if (ipr->ref_type < IPSP_CRED_KEYNOTE ||
1349: ipr->ref_type > IPSP_CRED_X509) {
1350: FREE(ipr, M_CREDENTIALS);
1351: error = EINVAL;
1352: } else {
1353: if (inp->inp_ipo->ipo_local_cred != NULL)
1354: ipsp_reffree(inp->inp_ipo->ipo_local_cred);
1355: inp->inp_ipo->ipo_local_cred = ipr;
1356: }
1357: break;
1358: case IP_IPSEC_LOCAL_AUTH:
1359: if (ipr->ref_type < IPSP_AUTH_PASSPHRASE ||
1360: ipr->ref_type > IPSP_AUTH_RSA) {
1361: FREE(ipr, M_CREDENTIALS);
1362: error = EINVAL;
1363: } else {
1364: if (inp->inp_ipo->ipo_local_auth != NULL)
1365: ipsp_reffree(inp->inp_ipo->ipo_local_auth);
1366: inp->inp_ipo->ipo_local_auth = ipr;
1367: }
1368: break;
1369: }
1370:
1371: /* Unlink cached output TDB to force a re-search */
1372: if (inp->inp_tdb_out) {
1373: int s = spltdb();
1374: TAILQ_REMOVE(&inp->inp_tdb_out->tdb_inp_out,
1375: inp, inp_tdb_out_next);
1376: splx(s);
1377: }
1378:
1379: if (inp->inp_tdb_in) {
1380: int s = spltdb();
1381: TAILQ_REMOVE(&inp->inp_tdb_in->tdb_inp_in,
1382: inp, inp_tdb_in_next);
1383: splx(s);
1384: }
1385: #endif
1386: break;
1387: default:
1388: error = ENOPROTOOPT;
1389: break;
1390: }
1391: if (m)
1392: (void)m_free(m);
1393: break;
1394:
1395: case PRCO_GETOPT:
1396: switch (optname) {
1397: case IP_OPTIONS:
1398: case IP_RETOPTS:
1399: *mp = m = m_get(M_WAIT, MT_SOOPTS);
1400: if (inp->inp_options) {
1401: m->m_len = inp->inp_options->m_len;
1402: bcopy(mtod(inp->inp_options, caddr_t),
1403: mtod(m, caddr_t), (unsigned)m->m_len);
1404: } else
1405: m->m_len = 0;
1406: break;
1407:
1408: case IP_TOS:
1409: case IP_TTL:
1410: case IP_MINTTL:
1411: case IP_RECVOPTS:
1412: case IP_RECVRETOPTS:
1413: case IP_RECVDSTADDR:
1414: case IP_RECVIF:
1415: case IP_RECVTTL:
1416: *mp = m = m_get(M_WAIT, MT_SOOPTS);
1417: m->m_len = sizeof(int);
1418: switch (optname) {
1419:
1420: case IP_TOS:
1421: optval = inp->inp_ip.ip_tos;
1422: break;
1423:
1424: case IP_TTL:
1425: optval = inp->inp_ip.ip_ttl;
1426: break;
1427:
1428: case IP_MINTTL:
1429: optval = inp->inp_ip_minttl;
1430: break;
1431:
1432: #define OPTBIT(bit) (inp->inp_flags & bit ? 1 : 0)
1433:
1434: case IP_RECVOPTS:
1435: optval = OPTBIT(INP_RECVOPTS);
1436: break;
1437:
1438: case IP_RECVRETOPTS:
1439: optval = OPTBIT(INP_RECVRETOPTS);
1440: break;
1441:
1442: case IP_RECVDSTADDR:
1443: optval = OPTBIT(INP_RECVDSTADDR);
1444: break;
1445: case IP_RECVIF:
1446: optval = OPTBIT(INP_RECVIF);
1447: break;
1448: case IP_RECVTTL:
1449: optval = OPTBIT(INP_RECVTTL);
1450: break;
1451: }
1452: *mtod(m, int *) = optval;
1453: break;
1454:
1455: case IP_MULTICAST_IF:
1456: case IP_MULTICAST_TTL:
1457: case IP_MULTICAST_LOOP:
1458: case IP_ADD_MEMBERSHIP:
1459: case IP_DROP_MEMBERSHIP:
1460: error = ip_getmoptions(optname, inp->inp_moptions, mp);
1461: break;
1462:
1463: case IP_PORTRANGE:
1464: *mp = m = m_get(M_WAIT, MT_SOOPTS);
1465: m->m_len = sizeof(int);
1466:
1467: if (inp->inp_flags & INP_HIGHPORT)
1468: optval = IP_PORTRANGE_HIGH;
1469: else if (inp->inp_flags & INP_LOWPORT)
1470: optval = IP_PORTRANGE_LOW;
1471: else
1472: optval = 0;
1473:
1474: *mtod(m, int *) = optval;
1475: break;
1476:
1477: case IP_AUTH_LEVEL:
1478: case IP_ESP_TRANS_LEVEL:
1479: case IP_ESP_NETWORK_LEVEL:
1480: case IP_IPCOMP_LEVEL:
1481: #ifndef IPSEC
1482: m->m_len = sizeof(int);
1483: *mtod(m, int *) = IPSEC_LEVEL_NONE;
1484: #else
1485: m->m_len = sizeof(int);
1486: switch (optname) {
1487: case IP_AUTH_LEVEL:
1488: optval = inp->inp_seclevel[SL_AUTH];
1489: break;
1490:
1491: case IP_ESP_TRANS_LEVEL:
1492: optval = inp->inp_seclevel[SL_ESP_TRANS];
1493: break;
1494:
1495: case IP_ESP_NETWORK_LEVEL:
1496: optval = inp->inp_seclevel[SL_ESP_NETWORK];
1497: break;
1498: case IP_IPCOMP_LEVEL:
1499: optval = inp->inp_seclevel[SL_IPCOMP];
1500: break;
1501: }
1502: *mtod(m, int *) = optval;
1503: #endif
1504: break;
1505: case IP_IPSEC_LOCAL_ID:
1506: case IP_IPSEC_REMOTE_ID:
1507: case IP_IPSEC_LOCAL_CRED:
1508: case IP_IPSEC_REMOTE_CRED:
1509: case IP_IPSEC_LOCAL_AUTH:
1510: case IP_IPSEC_REMOTE_AUTH:
1511: #ifndef IPSEC
1512: error = EOPNOTSUPP;
1513: #else
1514: *mp = m = m_get(M_WAIT, MT_SOOPTS);
1515: m->m_len = sizeof(u_int16_t);
1516: ipr = NULL;
1517: switch (optname) {
1518: case IP_IPSEC_LOCAL_ID:
1519: if (inp->inp_ipo != NULL)
1520: ipr = inp->inp_ipo->ipo_srcid;
1521: opt16val = IPSP_IDENTITY_NONE;
1522: break;
1523: case IP_IPSEC_REMOTE_ID:
1524: if (inp->inp_ipo != NULL)
1525: ipr = inp->inp_ipo->ipo_dstid;
1526: opt16val = IPSP_IDENTITY_NONE;
1527: break;
1528: case IP_IPSEC_LOCAL_CRED:
1529: if (inp->inp_ipo != NULL)
1530: ipr = inp->inp_ipo->ipo_local_cred;
1531: opt16val = IPSP_CRED_NONE;
1532: break;
1533: case IP_IPSEC_REMOTE_CRED:
1534: ipr = inp->inp_ipsec_remotecred;
1535: opt16val = IPSP_CRED_NONE;
1536: break;
1537: case IP_IPSEC_LOCAL_AUTH:
1538: if (inp->inp_ipo != NULL)
1539: ipr = inp->inp_ipo->ipo_local_auth;
1540: break;
1541: case IP_IPSEC_REMOTE_AUTH:
1542: ipr = inp->inp_ipsec_remoteauth;
1543: break;
1544: }
1545: if (ipr == NULL)
1546: *mtod(m, u_int16_t *) = opt16val;
1547: else {
1548: size_t len;
1549:
1550: len = m->m_len + ipr->ref_len;
1551: if (len > MCLBYTES) {
1552: m_free(m);
1553: error = EINVAL;
1554: break;
1555: }
1556: /* allocate mbuf cluster for larger option */
1557: if (len > MLEN) {
1558: MCLGET(m, M_WAITOK);
1559: if ((m->m_flags & M_EXT) == 0) {
1560: m_free(m);
1561: error = ENOBUFS;
1562: break;
1563: }
1564:
1565: }
1566: m->m_len = len;
1567: *mtod(m, u_int16_t *) = ipr->ref_type;
1568: m_copyback(m, sizeof(u_int16_t), ipr->ref_len,
1569: ipr + 1);
1570: }
1571: #endif
1572: break;
1573: default:
1574: error = ENOPROTOOPT;
1575: break;
1576: }
1577: break;
1578: }
1579: return (error);
1580: }
1581:
1582: /*
1583: * Set up IP options in pcb for insertion in output packets.
1584: * Store in mbuf with pointer in pcbopt, adding pseudo-option
1585: * with destination address if source routed.
1586: */
1587: int
1588: #ifdef notyet
1589: ip_pcbopts(optname, pcbopt, m)
1590: int optname;
1591: #else
1592: ip_pcbopts(pcbopt, m)
1593: #endif
1594: struct mbuf **pcbopt;
1595: struct mbuf *m;
1596: {
1597: int cnt, optlen;
1598: u_char *cp;
1599: u_char opt;
1600:
1601: /* turn off any old options */
1602: if (*pcbopt)
1603: (void)m_free(*pcbopt);
1604: *pcbopt = 0;
1605: if (m == (struct mbuf *)0 || m->m_len == 0) {
1606: /*
1607: * Only turning off any previous options.
1608: */
1609: if (m)
1610: (void)m_free(m);
1611: return (0);
1612: }
1613:
1614: if (m->m_len % sizeof(int32_t))
1615: goto bad;
1616:
1617: /*
1618: * IP first-hop destination address will be stored before
1619: * actual options; move other options back
1620: * and clear it when none present.
1621: */
1622: if (m->m_data + m->m_len + sizeof(struct in_addr) >= &m->m_dat[MLEN])
1623: goto bad;
1624: cnt = m->m_len;
1625: m->m_len += sizeof(struct in_addr);
1626: cp = mtod(m, u_char *) + sizeof(struct in_addr);
1627: ovbcopy(mtod(m, caddr_t), (caddr_t)cp, (unsigned)cnt);
1628: bzero(mtod(m, caddr_t), sizeof(struct in_addr));
1629:
1630: for (; cnt > 0; cnt -= optlen, cp += optlen) {
1631: opt = cp[IPOPT_OPTVAL];
1632: if (opt == IPOPT_EOL)
1633: break;
1634: if (opt == IPOPT_NOP)
1635: optlen = 1;
1636: else {
1637: if (cnt < IPOPT_OLEN + sizeof(*cp))
1638: goto bad;
1639: optlen = cp[IPOPT_OLEN];
1640: if (optlen < IPOPT_OLEN + sizeof(*cp) || optlen > cnt)
1641: goto bad;
1642: }
1643: switch (opt) {
1644:
1645: default:
1646: break;
1647:
1648: case IPOPT_LSRR:
1649: case IPOPT_SSRR:
1650: /*
1651: * user process specifies route as:
1652: * ->A->B->C->D
1653: * D must be our final destination (but we can't
1654: * check that since we may not have connected yet).
1655: * A is first hop destination, which doesn't appear in
1656: * actual IP option, but is stored before the options.
1657: */
1658: if (optlen < IPOPT_MINOFF - 1 + sizeof(struct in_addr))
1659: goto bad;
1660: m->m_len -= sizeof(struct in_addr);
1661: cnt -= sizeof(struct in_addr);
1662: optlen -= sizeof(struct in_addr);
1663: cp[IPOPT_OLEN] = optlen;
1664: /*
1665: * Move first hop before start of options.
1666: */
1667: bcopy((caddr_t)&cp[IPOPT_OFFSET+1], mtod(m, caddr_t),
1668: sizeof(struct in_addr));
1669: /*
1670: * Then copy rest of options back
1671: * to close up the deleted entry.
1672: */
1673: ovbcopy((caddr_t)(&cp[IPOPT_OFFSET+1] +
1674: sizeof(struct in_addr)),
1675: (caddr_t)&cp[IPOPT_OFFSET+1],
1676: (unsigned)cnt - (IPOPT_OFFSET+1));
1677: break;
1678: }
1679: }
1680: if (m->m_len > MAX_IPOPTLEN + sizeof(struct in_addr))
1681: goto bad;
1682: *pcbopt = m;
1683: return (0);
1684:
1685: bad:
1686: (void)m_free(m);
1687: return (EINVAL);
1688: }
1689:
1690: /*
1691: * Set the IP multicast options in response to user setsockopt().
1692: */
1693: int
1694: ip_setmoptions(optname, imop, m)
1695: int optname;
1696: struct ip_moptions **imop;
1697: struct mbuf *m;
1698: {
1699: int error = 0;
1700: u_char loop;
1701: int i;
1702: struct in_addr addr;
1703: struct ip_mreq *mreq;
1704: struct ifnet *ifp;
1705: struct ip_moptions *imo = *imop;
1706: struct route ro;
1707: struct sockaddr_in *dst;
1708:
1709: if (imo == NULL) {
1710: /*
1711: * No multicast option buffer attached to the pcb;
1712: * allocate one and initialize to default values.
1713: */
1714: imo = (struct ip_moptions *)malloc(sizeof(*imo), M_IPMOPTS,
1715: M_WAITOK);
1716:
1717: *imop = imo;
1718: imo->imo_multicast_ifp = NULL;
1719: imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
1720: imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
1721: imo->imo_num_memberships = 0;
1722: }
1723:
1724: switch (optname) {
1725:
1726: case IP_MULTICAST_IF:
1727: /*
1728: * Select the interface for outgoing multicast packets.
1729: */
1730: if (m == NULL || m->m_len != sizeof(struct in_addr)) {
1731: error = EINVAL;
1732: break;
1733: }
1734: addr = *(mtod(m, struct in_addr *));
1735: /*
1736: * INADDR_ANY is used to remove a previous selection.
1737: * When no interface is selected, a default one is
1738: * chosen every time a multicast packet is sent.
1739: */
1740: if (addr.s_addr == INADDR_ANY) {
1741: imo->imo_multicast_ifp = NULL;
1742: break;
1743: }
1744: /*
1745: * The selected interface is identified by its local
1746: * IP address. Find the interface and confirm that
1747: * it supports multicasting.
1748: */
1749: INADDR_TO_IFP(addr, ifp);
1750: if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
1751: error = EADDRNOTAVAIL;
1752: break;
1753: }
1754: imo->imo_multicast_ifp = ifp;
1755: break;
1756:
1757: case IP_MULTICAST_TTL:
1758: /*
1759: * Set the IP time-to-live for outgoing multicast packets.
1760: */
1761: if (m == NULL || m->m_len != 1) {
1762: error = EINVAL;
1763: break;
1764: }
1765: imo->imo_multicast_ttl = *(mtod(m, u_char *));
1766: break;
1767:
1768: case IP_MULTICAST_LOOP:
1769: /*
1770: * Set the loopback flag for outgoing multicast packets.
1771: * Must be zero or one.
1772: */
1773: if (m == NULL || m->m_len != 1 ||
1774: (loop = *(mtod(m, u_char *))) > 1) {
1775: error = EINVAL;
1776: break;
1777: }
1778: imo->imo_multicast_loop = loop;
1779: break;
1780:
1781: case IP_ADD_MEMBERSHIP:
1782: /*
1783: * Add a multicast group membership.
1784: * Group must be a valid IP multicast address.
1785: */
1786: if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
1787: error = EINVAL;
1788: break;
1789: }
1790: mreq = mtod(m, struct ip_mreq *);
1791: if (!IN_MULTICAST(mreq->imr_multiaddr.s_addr)) {
1792: error = EINVAL;
1793: break;
1794: }
1795: /*
1796: * If no interface address was provided, use the interface of
1797: * the route to the given multicast address.
1798: */
1799: if (mreq->imr_interface.s_addr == INADDR_ANY) {
1800: ro.ro_rt = NULL;
1801: dst = satosin(&ro.ro_dst);
1802: dst->sin_len = sizeof(*dst);
1803: dst->sin_family = AF_INET;
1804: dst->sin_addr = mreq->imr_multiaddr;
1805: rtalloc(&ro);
1806: if (ro.ro_rt == NULL) {
1807: error = EADDRNOTAVAIL;
1808: break;
1809: }
1810: ifp = ro.ro_rt->rt_ifp;
1811: rtfree(ro.ro_rt);
1812: } else {
1813: INADDR_TO_IFP(mreq->imr_interface, ifp);
1814: }
1815: /*
1816: * See if we found an interface, and confirm that it
1817: * supports multicast.
1818: */
1819: if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
1820: error = EADDRNOTAVAIL;
1821: break;
1822: }
1823: /*
1824: * See if the membership already exists or if all the
1825: * membership slots are full.
1826: */
1827: for (i = 0; i < imo->imo_num_memberships; ++i) {
1828: if (imo->imo_membership[i]->inm_ia->ia_ifp == ifp &&
1829: imo->imo_membership[i]->inm_addr.s_addr
1830: == mreq->imr_multiaddr.s_addr)
1831: break;
1832: }
1833: if (i < imo->imo_num_memberships) {
1834: error = EADDRINUSE;
1835: break;
1836: }
1837: if (i == IP_MAX_MEMBERSHIPS) {
1838: error = ETOOMANYREFS;
1839: break;
1840: }
1841: /*
1842: * Everything looks good; add a new record to the multicast
1843: * address list for the given interface.
1844: */
1845: if ((imo->imo_membership[i] =
1846: in_addmulti(&mreq->imr_multiaddr, ifp)) == NULL) {
1847: error = ENOBUFS;
1848: break;
1849: }
1850: ++imo->imo_num_memberships;
1851: break;
1852:
1853: case IP_DROP_MEMBERSHIP:
1854: /*
1855: * Drop a multicast group membership.
1856: * Group must be a valid IP multicast address.
1857: */
1858: if (m == NULL || m->m_len != sizeof(struct ip_mreq)) {
1859: error = EINVAL;
1860: break;
1861: }
1862: mreq = mtod(m, struct ip_mreq *);
1863: if (!IN_MULTICAST(mreq->imr_multiaddr.s_addr)) {
1864: error = EINVAL;
1865: break;
1866: }
1867: /*
1868: * If an interface address was specified, get a pointer
1869: * to its ifnet structure.
1870: */
1871: if (mreq->imr_interface.s_addr == INADDR_ANY)
1872: ifp = NULL;
1873: else {
1874: INADDR_TO_IFP(mreq->imr_interface, ifp);
1875: if (ifp == NULL) {
1876: error = EADDRNOTAVAIL;
1877: break;
1878: }
1879: }
1880: /*
1881: * Find the membership in the membership array.
1882: */
1883: for (i = 0; i < imo->imo_num_memberships; ++i) {
1884: if ((ifp == NULL ||
1885: imo->imo_membership[i]->inm_ia->ia_ifp == ifp) &&
1886: imo->imo_membership[i]->inm_addr.s_addr ==
1887: mreq->imr_multiaddr.s_addr)
1888: break;
1889: }
1890: if (i == imo->imo_num_memberships) {
1891: error = EADDRNOTAVAIL;
1892: break;
1893: }
1894: /*
1895: * Give up the multicast address record to which the
1896: * membership points.
1897: */
1898: in_delmulti(imo->imo_membership[i]);
1899: /*
1900: * Remove the gap in the membership array.
1901: */
1902: for (++i; i < imo->imo_num_memberships; ++i)
1903: imo->imo_membership[i-1] = imo->imo_membership[i];
1904: --imo->imo_num_memberships;
1905: break;
1906:
1907: default:
1908: error = EOPNOTSUPP;
1909: break;
1910: }
1911:
1912: /*
1913: * If all options have default values, no need to keep the mbuf.
1914: */
1915: if (imo->imo_multicast_ifp == NULL &&
1916: imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
1917: imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
1918: imo->imo_num_memberships == 0) {
1919: free(*imop, M_IPMOPTS);
1920: *imop = NULL;
1921: }
1922:
1923: return (error);
1924: }
1925:
1926: /*
1927: * Return the IP multicast options in response to user getsockopt().
1928: */
1929: int
1930: ip_getmoptions(optname, imo, mp)
1931: int optname;
1932: struct ip_moptions *imo;
1933: struct mbuf **mp;
1934: {
1935: u_char *ttl;
1936: u_char *loop;
1937: struct in_addr *addr;
1938: struct in_ifaddr *ia;
1939:
1940: *mp = m_get(M_WAIT, MT_SOOPTS);
1941:
1942: switch (optname) {
1943:
1944: case IP_MULTICAST_IF:
1945: addr = mtod(*mp, struct in_addr *);
1946: (*mp)->m_len = sizeof(struct in_addr);
1947: if (imo == NULL || imo->imo_multicast_ifp == NULL)
1948: addr->s_addr = INADDR_ANY;
1949: else {
1950: IFP_TO_IA(imo->imo_multicast_ifp, ia);
1951: addr->s_addr = (ia == NULL) ? INADDR_ANY
1952: : ia->ia_addr.sin_addr.s_addr;
1953: }
1954: return (0);
1955:
1956: case IP_MULTICAST_TTL:
1957: ttl = mtod(*mp, u_char *);
1958: (*mp)->m_len = 1;
1959: *ttl = (imo == NULL) ? IP_DEFAULT_MULTICAST_TTL
1960: : imo->imo_multicast_ttl;
1961: return (0);
1962:
1963: case IP_MULTICAST_LOOP:
1964: loop = mtod(*mp, u_char *);
1965: (*mp)->m_len = 1;
1966: *loop = (imo == NULL) ? IP_DEFAULT_MULTICAST_LOOP
1967: : imo->imo_multicast_loop;
1968: return (0);
1969:
1970: default:
1971: return (EOPNOTSUPP);
1972: }
1973: }
1974:
1975: /*
1976: * Discard the IP multicast options.
1977: */
1978: void
1979: ip_freemoptions(imo)
1980: struct ip_moptions *imo;
1981: {
1982: int i;
1983:
1984: if (imo != NULL) {
1985: for (i = 0; i < imo->imo_num_memberships; ++i)
1986: in_delmulti(imo->imo_membership[i]);
1987: free(imo, M_IPMOPTS);
1988: }
1989: }
1990:
1991: /*
1992: * Routine called from ip_output() to loop back a copy of an IP multicast
1993: * packet to the input queue of a specified interface. Note that this
1994: * calls the output routine of the loopback "driver", but with an interface
1995: * pointer that might NOT be &loif -- easier than replicating that code here.
1996: */
1997: void
1998: ip_mloopback(ifp, m, dst)
1999: struct ifnet *ifp;
2000: struct mbuf *m;
2001: struct sockaddr_in *dst;
2002: {
2003: struct ip *ip;
2004: struct mbuf *copym;
2005:
2006: copym = m_copym2(m, 0, M_COPYALL, M_DONTWAIT);
2007: if (copym != NULL) {
2008: /*
2009: * We don't bother to fragment if the IP length is greater
2010: * than the interface's MTU. Can this possibly matter?
2011: */
2012: ip = mtod(copym, struct ip *);
2013: ip->ip_sum = 0;
2014: ip->ip_sum = in_cksum(copym, ip->ip_hl << 2);
2015: (void) looutput(ifp, copym, sintosa(dst), NULL);
2016: }
2017: }
2018:
2019: /*
2020: * Process a delayed payload checksum calculation.
2021: */
2022: void
2023: in_delayed_cksum(struct mbuf *m)
2024: {
2025: struct ip *ip;
2026: u_int16_t csum, offset;
2027:
2028: ip = mtod(m, struct ip *);
2029: offset = ip->ip_hl << 2;
2030: csum = in4_cksum(m, 0, offset, m->m_pkthdr.len - offset);
2031: if (csum == 0 && ip->ip_p == IPPROTO_UDP)
2032: csum = 0xffff;
2033:
2034: switch (ip->ip_p) {
2035: case IPPROTO_TCP:
2036: offset += offsetof(struct tcphdr, th_sum);
2037: break;
2038:
2039: case IPPROTO_UDP:
2040: offset += offsetof(struct udphdr, uh_sum);
2041: break;
2042:
2043: default:
2044: return;
2045: }
2046:
2047: if ((offset + sizeof(u_int16_t)) > m->m_len)
2048: m_copyback(m, offset, sizeof(csum), &csum);
2049: else
2050: *(u_int16_t *)(mtod(m, caddr_t) + offset) = csum;
2051: }
CVSweb