summaryrefslogtreecommitdiff
path: root/sys/netinet/ip_output.c
diff options
context:
space:
mode:
authorAngelos D. Keromytis <angelos@cvs.openbsd.org>1999-12-04 23:20:22 +0000
committerAngelos D. Keromytis <angelos@cvs.openbsd.org>1999-12-04 23:20:22 +0000
commit2b2f59eda8c608d272708986fc8d2c0183eb8dd4 (patch)
treedbda7dc76dd4d65f22ff652cdc8a1f0f1858f533 /sys/netinet/ip_output.c
parentc4bfe6718e0319e5b13ff515c6cc82e59856a8a1 (diff)
Address independence, IPv6 support, and the -local flag in ipsecadm is
no longer needed.
Diffstat (limited to 'sys/netinet/ip_output.c')
-rw-r--r--sys/netinet/ip_output.c567
1 files changed, 273 insertions, 294 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 277a0608ed9..ea4b083e0db 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.52 1999/11/04 11:21:14 ho Exp $ */
+/* $OpenBSD: ip_output.c,v 1.53 1999/12/04 23:20:21 angelos Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -129,6 +129,12 @@ ip_output(m0, va_alist)
struct udphdr *udp;
struct tcphdr *tcp;
struct inpcb *inp;
+
+ struct route_enc re0, *re = &re0;
+ struct sockaddr_encap *ddst, *gw;
+ u_int8_t sa_require, sa_have = 0;
+ struct tdb *tdb, *t;
+ int s;
#endif
va_start(ap, m0);
@@ -166,21 +172,187 @@ ip_output(m0, va_alist)
hlen = ip->ip_hl << 2;
}
+ /*
+ * Route packet.
+ */
+ if (ro == 0) {
+ ro = &iproute;
+ bzero((caddr_t)ro, sizeof (*ro));
+ }
+ dst = satosin(&ro->ro_dst);
+ /*
+ * If there is a cached route,
+ * check that it is to the same destination
+ * and is still up. If not, free it and try again.
+ */
+ if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
+ dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
+ RTFREE(ro->ro_rt);
+ ro->ro_rt = (struct rtentry *)0;
+ }
+ if (ro->ro_rt == 0) {
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_addr = ip->ip_dst;
+ }
+ /*
+ * If routing to interface only,
+ * short circuit routing lookup.
+ */
+ if (flags & IP_ROUTETOIF) {
+ if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 &&
+ (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) {
+ ipstat.ips_noroute++;
+ error = ENETUNREACH;
+ goto bad;
+ }
+ ifp = ia->ia_ifp;
+ ip->ip_ttl = 1;
+ } else {
+ if (ro->ro_rt == 0)
+ rtalloc(ro);
+ if (ro->ro_rt == 0) {
+ ipstat.ips_noroute++;
+ error = EHOSTUNREACH;
+ goto bad;
+ }
+ ia = ifatoia(ro->ro_rt->rt_ifa);
+ ifp = ro->ro_rt->rt_ifp;
+ ro->ro_rt->rt_use++;
+ if (ro->ro_rt->rt_flags & RTF_GATEWAY)
+ dst = satosin(ro->ro_rt->rt_gateway);
+ }
+ if (IN_MULTICAST(ip->ip_dst.s_addr)) {
+ struct in_multi *inm;
+
+ m->m_flags |= M_MCAST;
+ /*
+ * IP destination address is multicast. Make sure "dst"
+ * still points to the address in "ro". (It may have been
+ * changed to point to a gateway address, above.)
+ */
+ dst = satosin(&ro->ro_dst);
+ /*
+ * See if the caller provided any multicast options
+ */
+ if (imo != NULL) {
+ ip->ip_ttl = imo->imo_multicast_ttl;
+ if (imo->imo_multicast_ifp != NULL)
+ ifp = imo->imo_multicast_ifp;
+ } else
+ ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
+ /*
+ * Confirm that the outgoing interface supports multicast.
+ */
+ if ((ifp->if_flags & IFF_MULTICAST) == 0) {
+ ipstat.ips_noroute++;
+ error = ENETUNREACH;
+ goto bad;
+ }
+ /*
+ * If source address not specified yet, use address
+ * of outgoing interface.
+ */
+ if (ip->ip_src.s_addr == INADDR_ANY) {
+ register struct in_ifaddr *ia;
+
+ for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next)
+ if (ia->ia_ifp == ifp) {
+ ip->ip_src = ia->ia_addr.sin_addr;
+ break;
+ }
+ }
+
+ IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
+ if (inm != NULL &&
+ (imo == NULL || imo->imo_multicast_loop)) {
+ /*
+ * If we belong to the destination multicast group
+ * on the outgoing interface, and the caller did not
+ * forbid loopback, loop back a copy.
+ */
+ ip_mloopback(ifp, m, dst);
+ }
+#ifdef MROUTING
+ else {
+ /*
+ * If we are acting as a multicast router, perform
+ * multicast forwarding as if the packet had just
+ * arrived on the interface to which we are about
+ * to send. The multicast forwarding function
+ * recursively calls this function, using the
+ * IP_FORWARDING flag to prevent infinite recursion.
+ *
+ * Multicasts that are looped back by ip_mloopback(),
+ * above, will be forwarded by the ip_input() routine,
+ * if necessary.
+ */
+ extern struct socket *ip_mrouter;
+
+ if (ip_mrouter && (flags & IP_FORWARDING) == 0) {
+ if (ip_mforward(m, ifp) != 0) {
+ m_freem(m);
+ goto done;
+ }
+ }
+ }
+#endif
+ /*
+ * Multicasts with a time-to-live of zero may be looped-
+ * back, above, but must not be transmitted on a network.
+ * Also, multicasts addressed to the loopback interface
+ * are not sent -- the above call to ip_mloopback() will
+ * loop back a copy if this host actually belongs to the
+ * destination group on the loopback interface.
+ */
+ if (ip->ip_ttl == 0 || (ifp->if_flags & IFF_LOOPBACK) != 0) {
+ m_freem(m);
+ goto done;
+ }
+
+ goto sendit;
+ }
+#ifndef notdef
+ /*
+ * If source address not specified yet, use address
+ * of outgoing interface.
+ */
+ if (ip->ip_src.s_addr == INADDR_ANY)
+ ip->ip_src = ia->ia_addr.sin_addr;
+#endif
+ /*
+ * Look for broadcast address and
+ * and verify user is allowed to send
+ * such a packet.
+ */
+ if (in_broadcast(dst->sin_addr, ifp)) {
+ if ((ifp->if_flags & IFF_BROADCAST) == 0) {
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+ if ((flags & IP_ALLOWBROADCAST) == 0) {
+ error = EACCES;
+ goto bad;
+ }
+ /* don't allow broadcast messages to be fragmented */
+ if ((u_int16_t)ip->ip_len > ifp->if_mtu) {
+ error = EMSGSIZE;
+ goto bad;
+ }
+ m->m_flags |= M_BCAST;
+ } else
+ m->m_flags &= ~M_BCAST;
+
+sendit:
#ifdef IPSEC
/*
- * Check if the packet needs encapsulation
+ * Check if the packet needs encapsulation.
*/
if (!(flags & IP_ENCAPSULATED) &&
(inp == NULL ||
inp->inp_seclevel[SL_AUTH] != IPSEC_LEVEL_BYPASS ||
inp->inp_seclevel[SL_ESP_TRANS] != IPSEC_LEVEL_BYPASS ||
inp->inp_seclevel[SL_ESP_NETWORK] != IPSEC_LEVEL_BYPASS)) {
- struct route_enc re0, *re = &re0;
- struct sockaddr_encap *ddst, *gw;
- struct tdb *tdb, *t;
- int s;
- u_int8_t sa_require, sa_have = 0;
-
if (inp == NULL)
sa_require = get_sa_require(inp);
else
@@ -193,10 +365,13 @@ ip_output(m0, va_alist)
* lower the level, and udp_output calls us in splnet().
*/
s = splnet();
- /* Check if there was a bound outgoing SA */
+
+ /*
+ * Check if there was an outgoing SA bound to the flow
+ * from a transport protocol.
+ */
if (inp && inp->inp_tdb &&
- (inp->inp_tdb->tdb_dst.sin.sin_addr.s_addr ==
- INADDR_ANY ||
+ (inp->inp_tdb->tdb_dst.sin.sin_addr.s_addr == INADDR_ANY ||
!bcmp(&inp->inp_tdb->tdb_dst.sin.sin_addr,
&ip->ip_dst, sizeof(ip->ip_dst)))) {
tdb = inp->inp_tdb;
@@ -257,7 +432,8 @@ ip_output(m0, va_alist)
/*
* There might be a specific route, that tells us to avoid
* doing IPsec; this is useful for specific routes that we
- * don't want to have IPsec applied on.
+ * don't want to have IPsec applied on, like the key
+ * management ports.
*/
if ((gw != NULL) && (gw->sen_ipsp_dst.s_addr == 0) &&
@@ -266,7 +442,9 @@ ip_output(m0, va_alist)
goto no_encap;
}
- if (gw == NULL || gw->sen_type != SENT_IPSP) {
+ /* Sanity check */
+ if (gw == NULL || ((gw->sen_type != SENT_IPSP) &&
+ (gw->sen_type != SENT_IPSP6))) {
splx(s);
DPRINTF(("ip_output(): no gw or gw data not IPSP\n"));
@@ -277,50 +455,6 @@ ip_output(m0, va_alist)
goto done;
}
- /*
- * For VPNs a route with a reserved SPI of 0 is used to
- * indicate the need for an SA when none is established.
- */
- if (ntohl(gw->sen_ipsp_spi) == SPI_LOCAL_USE) {
- bzero(&sunion, sizeof(sunion));
- sunion.sin.sin_family = AF_INET;
- sunion.sin.sin_len = sizeof(struct sockaddr_in);
- sunion.sin.sin_addr = gw->sen_ipsp_dst;
- tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion,
- gw->sen_ipsp_sproto);
-
- if (tdb)
- {
- if (tdb->tdb_authalgxform)
- sa_require = NOTIFY_SATYPE_AUTH;
- if (tdb->tdb_encalgxform)
- sa_require |= NOTIFY_SATYPE_CONF;
- if (tdb->tdb_flags & TDBF_TUNNELING)
- sa_require |= NOTIFY_SATYPE_TUNNEL;
- }
- else /* No TDB found */
- {
- /*
- * XXX We should construct a TDB from system
- * default (which should be tunable via sysctl).
- * For now, drop packet and ignore SPD entry.
- */
- splx(s);
- goto no_encap;
- }
-
- /* PF_KEYv2 notification message */
- if (tdb->tdb_satype != SADB_X_SATYPE_BYPASS)
- pfkeyv2_acquire(tdb, 0); /* XXX Check for errors */
-
- splx(s);
-
- /*
- * When sa_require is set, the packet will be dropped
- * at no_encap.
- */
- goto no_encap;
- }
/*
* At this point we have an IPSP "gateway" (tunnel) spec.
@@ -330,13 +464,63 @@ ip_output(m0, va_alist)
* to the appropriate transformation.
*/
bzero(&sunion, sizeof(sunion));
- sunion.sin.sin_family = AF_INET;
- sunion.sin.sin_len = sizeof(struct sockaddr_in);
- sunion.sin.sin_addr = gw->sen_ipsp_dst;
+
+ if (gw->sen_type == SENT_IPSP) {
+ sunion.sin.sin_family = AF_INET;
+ sunion.sin.sin_len = sizeof(struct sockaddr_in);
+ sunion.sin.sin_addr = gw->sen_ipsp_dst;
+ }
+#if INET6
+ else {
+ sunion.sin6.sin6_family = AF_INET6;
+ sunion.sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sunion.sin6.sin6_addr = gw->sen_ipsp6_dst;
+ }
+#endif /* INET6 */
+
tdb = (struct tdb *) gettdb(gw->sen_ipsp_spi, &sunion,
gw->sen_ipsp_sproto);
- have_tdb:
+ /*
+ * For VPNs a route with a reserved SPI is used to
+ * indicate the need for an SA when none is established.
+ */
+ if (((ntohl(gw->sen_ipsp_spi) == SPI_LOCAL_USE) &&
+ (gw->sen_type == SENT_IPSP)) ||
+ ((ntohl(gw->sen_ipsp6_spi) == SPI_LOCAL_USE) &&
+ (gw->sen_type == SENT_IPSP6))) {
+ if (tdb == NULL) {
+ /*
+ * XXX We should construct a TDB from system
+ * default (which should be tunable via sysctl).
+ * For now, drop packet and ignore SPD entry.
+ */
+ splx(s);
+ goto no_encap;
+ }
+ else {
+ if (tdb->tdb_authalgxform)
+ sa_require = NOTIFY_SATYPE_AUTH;
+ if (tdb->tdb_encalgxform)
+ sa_require |= NOTIFY_SATYPE_CONF;
+ if (tdb->tdb_flags & TDBF_TUNNELING)
+ sa_require |= NOTIFY_SATYPE_TUNNEL;
+ }
+
+ /* PF_KEYv2 notification message */
+ if (tdb && tdb->tdb_satype != SADB_X_SATYPE_BYPASS)
+ pfkeyv2_acquire(tdb, 0); /* XXX Check for errors */
+
+ splx(s);
+
+ /*
+ * When sa_require is set, the packet will be dropped
+ * at no_encap.
+ */
+ goto no_encap;
+ }
+
+ have_tdb:
ip->ip_len = htons((u_short)ip->ip_len);
ip->ip_off = htons((u_short)ip->ip_off);
@@ -353,7 +537,12 @@ ip_output(m0, va_alist)
if (tdb == NULL) {
splx(s);
- DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet_ntoa4(gw->sen_ipsp_dst), ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_sproto));
+ if (gw->sen_type == SENT_IPSP)
+ DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet_ntoa4(gw->sen_ipsp_dst), ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_sproto));
+#if INET6
+ else
+ DPRINTF(("ip_output(): non-existant TDB for SA %s/%08x/%u\n", inet_ntoa4(gw->sen_ipsp_dst), ntohl(gw->sen_ipsp_spi), gw->sen_ipsp_sproto));
+#endif /* INET6 */
if (re->re_rt)
RTFREE(re->re_rt);
@@ -374,53 +563,6 @@ ip_output(m0, va_alist)
goto done;
}
- /* Fix the ip_src field if necessary */
- if (ip->ip_src.s_addr == INADDR_ANY) {
- if (tdb && tdb->tdb_src.sin.sin_addr.s_addr != 0 &&
- tdb->tdb_src.sa.sa_family == AF_INET)
- ip->ip_src = tdb->tdb_src.sin.sin_addr;
- else
- {
- if (ro == 0) {
- ro = &iproute;
- bzero((caddr_t)ro, sizeof (*ro));
- }
-
- dst = satosin(&ro->ro_dst);
-
- /*
- * If there is a cached route,
- * check that it is to the same destination
- * and is still up. If not, free it and try again.
- */
- if (ro->ro_rt &&
- ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
- RTFREE(ro->ro_rt);
- ro->ro_rt = (struct rtentry *)0;
- }
-
- if (ro->ro_rt == 0) {
- dst->sin_family = AF_INET;
- dst->sin_len = sizeof(*dst);
- dst->sin_addr = ip->ip_dst;
- rtalloc(ro);
- }
-
- if (ro->ro_rt == 0) {
- splx(s);
- ipstat.ips_noroute++;
- error = EHOSTUNREACH;
- m_freem(m);
- goto done;
- }
-
- ia = ifatoia(ro->ro_rt->rt_ifa);
- ro->ro_rt->rt_use++;
- ip->ip_src = ia->ia_addr.sin_addr;
- }
- }
-
while (tdb && tdb->tdb_xform) {
/* Check if the SPI is invalid */
if (tdb->tdb_flags & TDBF_INVALID) {
@@ -432,27 +574,35 @@ ip_output(m0, va_alist)
return ENXIO;
}
+ /* Sanity check */
+ if (tdb->tdb_dst.sa.sa_family != AF_INET) {
+ splx(s);
+ DPRINTF(("ip_output(): attempt to use SA %s/%08x/%u for protocol family %d\n", ipsp_address(tdb->tdb_dst), ntohl(tdb->tdb_spi), tdb->tdb_sproto, tdb->tdb_dst.sa.sa_family));
+ m_freem(m);
+ if (re->re_rt)
+ RTFREE(re->re_rt);
+ return ENXIO;
+ }
+
/* Register first use, setup expiration timer */
if (tdb->tdb_first_use == 0) {
tdb->tdb_first_use = time.tv_sec;
tdb_expiration(tdb, TDBEXP_TIMEOUT);
}
-
- /* Check for tunneling */
- if (((tdb->tdb_dst.sin.sin_addr.s_addr !=
- INADDR_ANY &&
- tdb->tdb_dst.sin.sin_addr.s_addr !=
- ip->ip_dst.s_addr) ||
- (tdb->tdb_flags & TDBF_TUNNELING)) &&
- (tdb->tdb_xform->xf_type != XF_IP4))
- {
- DPRINTF(("ip_output(): tunneling\n"));
+ /* Check for tunneling */
+ if (((tdb->tdb_dst.sa.sa_family == AF_INET) &&
+ (tdb->tdb_dst.sin.sin_addr.s_addr !=
+ INADDR_ANY) &&
+ (tdb->tdb_dst.sin.sin_addr.s_addr !=
+ ip->ip_dst.s_addr)) ||
+ ((tdb->tdb_flags & TDBF_TUNNELING) &&
+ (tdb->tdb_xform->xf_type != XF_IP4))) {
/*
* Fix checksum here, AH and ESP fix the
* checksum in their output routines.
*/
- ip->ip_sum = in_cksum(m, hlen);
+ ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
error = ipe4_output(m, tdb, &mp);
if (mp == NULL)
error = EFAULT;
@@ -472,9 +622,10 @@ ip_output(m0, va_alist)
* output routines.
*/
ip = mtod(m, struct ip *);
- ip->ip_sum = in_cksum(m, hlen);
+ ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
}
+
error = (*(tdb->tdb_xform->xf_output))(m, tdb, &mp);
if (!error && mp == NULL)
error = EFAULT;
@@ -507,7 +658,7 @@ ip_output(m0, va_alist)
NTOHS(ip->ip_len);
NTOHS(ip->ip_off);
return ip_output(m, NULL, NULL,
- IP_ENCAPSULATED | IP_RAWOUTPUT, NULL, NULL);
+ IP_ENCAPSULATED | IP_RAWOUTPUT, NULL, NULL);
no_encap:
/* This is for possible future use, don't move or delete */
@@ -522,178 +673,6 @@ no_encap:
}
#endif /* IPSEC */
- /*
- * Route packet.
- */
- if (ro == 0) {
- ro = &iproute;
- bzero((caddr_t)ro, sizeof (*ro));
- }
- dst = satosin(&ro->ro_dst);
- /*
- * If there is a cached route,
- * check that it is to the same destination
- * and is still up. If not, free it and try again.
- */
- if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
- dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
- RTFREE(ro->ro_rt);
- ro->ro_rt = (struct rtentry *)0;
- }
- if (ro->ro_rt == 0) {
- dst->sin_family = AF_INET;
- dst->sin_len = sizeof(*dst);
- dst->sin_addr = ip->ip_dst;
- }
- /*
- * If routing to interface only,
- * short circuit routing lookup.
- */
- if (flags & IP_ROUTETOIF) {
- if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == 0 &&
- (ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == 0) {
- ipstat.ips_noroute++;
- error = ENETUNREACH;
- goto bad;
- }
- ifp = ia->ia_ifp;
- ip->ip_ttl = 1;
- } else {
- if (ro->ro_rt == 0)
- rtalloc(ro);
- if (ro->ro_rt == 0) {
- ipstat.ips_noroute++;
- error = EHOSTUNREACH;
- goto bad;
- }
- ia = ifatoia(ro->ro_rt->rt_ifa);
- ifp = ro->ro_rt->rt_ifp;
- ro->ro_rt->rt_use++;
- if (ro->ro_rt->rt_flags & RTF_GATEWAY)
- dst = satosin(ro->ro_rt->rt_gateway);
- }
- if (IN_MULTICAST(ip->ip_dst.s_addr)) {
- struct in_multi *inm;
-
- m->m_flags |= M_MCAST;
- /*
- * IP destination address is multicast. Make sure "dst"
- * still points to the address in "ro". (It may have been
- * changed to point to a gateway address, above.)
- */
- dst = satosin(&ro->ro_dst);
- /*
- * See if the caller provided any multicast options
- */
- if (imo != NULL) {
- ip->ip_ttl = imo->imo_multicast_ttl;
- if (imo->imo_multicast_ifp != NULL)
- ifp = imo->imo_multicast_ifp;
- } else
- ip->ip_ttl = IP_DEFAULT_MULTICAST_TTL;
- /*
- * Confirm that the outgoing interface supports multicast.
- */
- if ((ifp->if_flags & IFF_MULTICAST) == 0) {
- ipstat.ips_noroute++;
- error = ENETUNREACH;
- goto bad;
- }
- /*
- * If source address not specified yet, use address
- * of outgoing interface.
- */
- if (ip->ip_src.s_addr == INADDR_ANY) {
- register struct in_ifaddr *ia;
-
- for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next)
- if (ia->ia_ifp == ifp) {
- ip->ip_src = ia->ia_addr.sin_addr;
- break;
- }
- }
-
- IN_LOOKUP_MULTI(ip->ip_dst, ifp, inm);
- if (inm != NULL &&
- (imo == NULL || imo->imo_multicast_loop)) {
- /*
- * If we belong to the destination multicast group
- * on the outgoing interface, and the caller did not
- * forbid loopback, loop back a copy.
- */
- ip_mloopback(ifp, m, dst);
- }
-#ifdef MROUTING
- else {
- /*
- * If we are acting as a multicast router, perform
- * multicast forwarding as if the packet had just
- * arrived on the interface to which we are about
- * to send. The multicast forwarding function
- * recursively calls this function, using the
- * IP_FORWARDING flag to prevent infinite recursion.
- *
- * Multicasts that are looped back by ip_mloopback(),
- * above, will be forwarded by the ip_input() routine,
- * if necessary.
- */
- extern struct socket *ip_mrouter;
-
- if (ip_mrouter && (flags & IP_FORWARDING) == 0) {
- if (ip_mforward(m, ifp) != 0) {
- m_freem(m);
- goto done;
- }
- }
- }
-#endif
- /*
- * Multicasts with a time-to-live of zero may be looped-
- * back, above, but must not be transmitted on a network.
- * Also, multicasts addressed to the loopback interface
- * are not sent -- the above call to ip_mloopback() will
- * loop back a copy if this host actually belongs to the
- * destination group on the loopback interface.
- */
- if (ip->ip_ttl == 0 || (ifp->if_flags & IFF_LOOPBACK) != 0) {
- m_freem(m);
- goto done;
- }
-
- goto sendit;
- }
-#ifndef notdef
- /*
- * If source address not specified yet, use address
- * of outgoing interface.
- */
- if (ip->ip_src.s_addr == INADDR_ANY)
- ip->ip_src = ia->ia_addr.sin_addr;
-#endif
- /*
- * Look for broadcast address and
- * and verify user is allowed to send
- * such a packet.
- */
- if (in_broadcast(dst->sin_addr, ifp)) {
- if ((ifp->if_flags & IFF_BROADCAST) == 0) {
- error = EADDRNOTAVAIL;
- goto bad;
- }
- if ((flags & IP_ALLOWBROADCAST) == 0) {
- error = EACCES;
- goto bad;
- }
- /* don't allow broadcast messages to be fragmented */
- if ((u_int16_t)ip->ip_len > ifp->if_mtu) {
- error = EMSGSIZE;
- goto bad;
- }
- m->m_flags |= M_BCAST;
- } else
- m->m_flags &= ~M_BCAST;
-
-sendit:
#if defined(IPFILTER) || defined(IPFILTER_LKM)
/*
* looks like most checking has been done now...do a filter check