X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/4ad99baef19aa1d3c1c12bba63d689409256e66f..88948a4c4631cd5c8012e381fe17ac41856fda8a:/usr/src/sys/netinet/ip_output.c diff --git a/usr/src/sys/netinet/ip_output.c b/usr/src/sys/netinet/ip_output.c index 77d51c8f62..ca9f70b264 100644 --- a/usr/src/sys/netinet/ip_output.c +++ b/usr/src/sys/netinet/ip_output.c @@ -1,49 +1,120 @@ -/* ip_output.c 1.15 81/11/20 */ +/* ip_output.c 1.35 82/06/20 */ #include "../h/param.h" #include "../h/mbuf.h" #include "../h/mtpr.h" #include "../h/socket.h" #include "../h/socketvar.h" -#include "../net/inet.h" -#include "../net/inet_systm.h" -#include "../net/imp.h" +#include "../net/in.h" +#include "../net/in_systm.h" +#include "../net/if.h" #include "../net/ip.h" #include "../net/ip_var.h" +#include "../net/route.h" +#include -ip_output(m) +int ipnorouteprint = 0; + +ip_output(m, opt, ro, allowbroadcast) struct mbuf *m; + struct mbuf *opt; + struct route *ro; + int allowbroadcast; { register struct ip *ip = mtod(m, struct ip *); - int len, hlen = ip->ip_hl << 2, off; + register struct ifnet *ifp; + int len, hlen = sizeof (struct ip), off, error = 0; + struct route iproute; + struct sockaddr *dst; -COUNT(IP_OUTPUT); + if (opt) /* XXX */ + (void) m_free(opt); /* XXX */ /* * Fill in IP header. */ ip->ip_v = IPVERSION; ip->ip_hl = hlen >> 2; ip->ip_off &= IP_DF; - ip->ip_ttl = MAXTTL; - ip->ip_id = ip_id++; + ip->ip_id = htons(ip_id++); + + /* + * Route packet. + */ + if (ro == 0) { + ro = &iproute; + bzero((caddr_t)ro, sizeof (*ro)); + } + dst = &ro->ro_dst; + if (ro->ro_rt == 0) { + ro->ro_dst.sa_family = AF_INET; + ((struct sockaddr_in *)&ro->ro_dst)->sin_addr = ip->ip_dst; + /* + * If routing to interface only, short circuit routing lookup. + */ + if (ro == &routetoif) { + /* check ifp is AF_INET??? */ + ifp = if_ifonnetof(IN_NETOF(ip->ip_dst)); + if (ifp == 0) + goto unreachable; + goto gotif; + } + rtalloc(ro); + } + if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) + goto unreachable; + ro->ro_rt->rt_use++; + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + dst = &ro->ro_rt->rt_gateway; +gotif: + /* + * If source address not specified yet, use address + * of outgoing interface. + */ + if (ip->ip_src.s_addr == 0) + ip->ip_src.s_addr = + ((struct sockaddr_in *)&ifp->if_addr)->sin_addr.s_addr; + + /* + * Have interface for packet. Allow + * broadcasts only by authorized users. + */ + if (!allowbroadcast && (ifp->if_flags & IFF_BROADCAST)) { + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)&ifp->if_broadaddr; + if (sin->sin_addr.s_addr == ip->ip_dst.s_addr) { + error = EACCES; + goto bad; + } + } /* * If small enough for interface, can just send directly. */ - if (ip->ip_len <= MTU) { - ip_send(ip); - return; + if (ip->ip_len <= ifp->if_mtu) { +#if vax + ip->ip_len = htons((u_short)ip->ip_len); + ip->ip_off = htons((u_short)ip->ip_off); +#endif + ip->ip_sum = 0; + ip->ip_sum = in_cksum(m, hlen); + error = (*ifp->if_output)(ifp, m, dst); + goto done; } /* * Too large for interface; fragment if possible. * Must be able to put at least 8 bytes per fragment. */ - if (ip->ip_off & IP_DF) + if (ip->ip_off & IP_DF) { + error = EMSGSIZE; goto bad; - len = (MTU-hlen) &~ 7; - if (len < 8) + } + len = (ifp->if_mtu - hlen) &~ 7; + if (len < 8) { + error = EMSGSIZE; goto bad; + } /* * Discard IP header from logical mbuf for m_copy's sake. @@ -52,12 +123,14 @@ COUNT(IP_OUTPUT); */ m->m_len -= sizeof (struct ip); m->m_off += sizeof (struct ip); - for (off = 0; off < ip->ip_len; off += len) { - struct mbuf *mh = m_get(0); + for (off = 0; off < ip->ip_len-hlen; off += len) { + struct mbuf *mh = m_get(M_DONTWAIT); struct ip *mhip; - if (mh == 0) + if (mh == 0) { + error = ENOBUFS; goto bad; + } mh->m_off = MMAXOFF - hlen; mhip = mtod(mh, struct ip *); *mhip = *ip; @@ -66,22 +139,45 @@ COUNT(IP_OUTPUT); mh->m_len = sizeof (struct ip) + olen; } else mh->m_len = sizeof (struct ip); - mhip->ip_off = off; - if (off + len >= ip->ip_len) - mhip->ip_len = ip->ip_len - off; + mhip->ip_off = off >> 3; + if (off + len >= ip->ip_len-hlen) + len = mhip->ip_len = ip->ip_len - hlen - off; else { mhip->ip_len = len; mhip->ip_off |= IP_MF; } + mhip->ip_len += sizeof (struct ip); +#if vax + mhip->ip_len = htons((u_short)mhip->ip_len); +#endif mh->m_next = m_copy(m, off, len); if (mh->m_next == 0) { - m_free(mh); + (void) m_free(mh); + error = ENOBUFS; /* ??? */ goto bad; } - ip_send(mhip); +#if vax + mhip->ip_off = htons((u_short)mhip->ip_off); +#endif + mhip->ip_sum = 0; + mhip->ip_sum = in_cksum(mh, hlen); + if (error = (*ifp->if_output)(ifp, mh, dst)) + break; } + m_freem(m); + goto done; + +unreachable: + if (ipnorouteprint) + printf("no route to %x (from %x, len %d)\n", + ip->ip_dst.s_addr, ip->ip_src.s_addr, ip->ip_len); + error = ENETUNREACH; bad: m_freem(m); +done: + if (ro == &iproute && ro->ro_rt) + RTFREE(ro->ro_rt); + return (error); } /* @@ -96,7 +192,6 @@ ip_optcopy(ip, jp, off) register u_char *cp, *dp; int opt, optlen, cnt; -COUNT(IP_OPTCOPY); cp = (u_char *)(ip + 1); dp = (u_char *)(jp + 1); cnt = (ip->ip_hl << 2) - sizeof (struct ip); @@ -119,49 +214,3 @@ COUNT(IP_OPTCOPY); *dp++ = IPOPT_EOL; return (optlen); } - -/* REST OF CODE HERE IS GARBAGE */ - -ip_send(ip) - register struct ip *ip; -{ - register struct mbuf *m; - register struct imp *l; - int hlen = ip->ip_hl << 2; - int s; -COUNT(IP_SEND); - - m = dtom(ip); - l = (struct imp *)(mtod(m, caddr_t) - L1822); - l->i_shost = ip->ip_src.s_host; - l->i_dhost = ip->ip_dst.s_host; - l->i_type = IPTYPE; - ip->ip_sum = 0; - ip->ip_len = htons((u_short)ip->ip_len); - ip->ip_id = htons(ip->ip_id); - ip->ip_off = htons((u_short)ip->ip_off); - ip->ip_sum = inet_cksum(m, hlen); - m->m_off -= L1822; - m->m_len += L1822; - m->m_act = NULL; -#ifndef IMPLOOP - s = splimp(); - if (imp_stat.outq_head != NULL) - imp_stat.outq_tail->m_act = m; - else - imp_stat.outq_head = m; - imp_stat.outq_tail = m; - splx(s); - if (!imp_stat.outactive) - enstart(0); -#else - if (imp_stat.inq_head != NULL) - imp_stat.inq_tail->m_act = m; - else - imp_stat.inq_head = m; - imp_stat.inq_tail = m; - setsoftnet(); -#endif IMPLOOP -} - -/* END GARBAGE */