BSD 4_3_Tahoe release
[unix-history] / usr / src / sys / netinet / raw_ip.c
index 850f0dd..43eeb1a 100644 (file)
@@ -1,25 +1,45 @@
-/*     raw_ip.c        4.4     82/02/02        */
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley.  The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *     @(#)raw_ip.c    7.4 (Berkeley) 6/29/88
+ */
 
 
-#include "../h/param.h"
-#include "../h/mbuf.h"
-#include "../h/socket.h"
-#include "../h/protosw.h"
-#include "../h/socketvar.h"
-#include "../net/in.h"
-#include "../net/in_systm.h"
-#include "../net/ip.h"
-#include "../net/ip_var.h"
+#include "param.h"
+#include "mbuf.h"
+#include "socket.h"
+#include "protosw.h"
+#include "socketvar.h"
+#include "errno.h"
+
+#include "../net/if.h"
+#include "../net/route.h"
 #include "../net/raw_cb.h"
 #include "../net/raw_cb.h"
-#include "/usr/include/errno.h"
+
+#include "in.h"
+#include "in_systm.h"
+#include "ip.h"
+#include "ip_var.h"
 
 /*
  * Raw interface to IP protocol.
  */
 
 
 /*
  * Raw interface to IP protocol.
  */
 
-static struct sockaddr_in ripdst = { PF_INET };
-static struct sockaddr_in ripsrc = { PF_INET };
-static struct sockproto ripproto = { AF_INET };
-
+struct sockaddr_in ripdst = { AF_INET };
+struct sockaddr_in ripsrc = { AF_INET };
+struct sockproto ripproto = { PF_INET };
 /*
  * Setup generic address and protocol structures
  * for raw_input routine, then pass them along with
 /*
  * Setup generic address and protocol structures
  * for raw_input routine, then pass them along with
@@ -29,21 +49,12 @@ rip_input(m)
        struct mbuf *m;
 {
        register struct ip *ip = mtod(m, struct ip *);
        struct mbuf *m;
 {
        register struct ip *ip = mtod(m, struct ip *);
-       struct sockaddr_in sin;
-       struct sockproto sp;
 
 
-COUNT(RIP_INPUT);
        ripproto.sp_protocol = ip->ip_p;
        ripdst.sin_addr = ip->ip_dst;
        ripsrc.sin_addr = ip->ip_src;
        ripproto.sp_protocol = ip->ip_p;
        ripdst.sin_addr = ip->ip_dst;
        ripsrc.sin_addr = ip->ip_src;
-       raw_input(m, &ripproto, &ripdst, &ripsrc);
-}
-
-/*ARGSUSED*/
-rip_ctlinput(m)
-       struct mbuf *m;
-{
-COUNT(RIP_CTLINPUT);
+       raw_input(m, &ripproto, (struct sockaddr *)&ripsrc,
+         (struct sockaddr *)&ripdst);
 }
 
 /*
 }
 
 /*
@@ -56,20 +67,20 @@ rip_output(m0, so)
 {
        register struct mbuf *m;
        register struct ip *ip;
 {
        register struct mbuf *m;
        register struct ip *ip;
-       register int len = 0;
-       register struct rawcb *rp = sotorawcb(so);
+       int len = 0, error;
+       struct rawcb *rp = sotorawcb(so);
+       struct sockaddr_in *sin;
 
 
-COUNT(RIP_OUTPUT);
        /*
         * Calculate data length and get an mbuf
         * for IP header.
         */
        for (m = m0; m; m = m->m_next)
                len += m->m_len;
        /*
         * Calculate data length and get an mbuf
         * for IP header.
         */
        for (m = m0; m; m = m->m_next)
                len += m->m_len;
-       m = m_get(M_DONTWAIT);
+       m = m_get(M_DONTWAIT, MT_HEADER);
        if (m == 0) {
        if (m == 0) {
-               m_freem(m);
-               return;
+               error = ENOBUFS;
+               goto bad;
        }
        
        /*
        }
        
        /*
@@ -79,42 +90,74 @@ COUNT(RIP_OUTPUT);
        m->m_len = sizeof(struct ip);
        m->m_next = m0;
        ip = mtod(m, struct ip *);
        m->m_len = sizeof(struct ip);
        m->m_next = m0;
        ip = mtod(m, struct ip *);
-       ip->ip_p = so->so_proto->pr_protocol;
+       ip->ip_tos = 0;
+       ip->ip_off = 0;
+       ip->ip_p = rp->rcb_proto.sp_protocol;
        ip->ip_len = sizeof(struct ip) + len;
        ip->ip_len = sizeof(struct ip) + len;
-       ip->ip_dst =
-               ((struct sockaddr_in *)&rp->rcb_addr)->sin_addr;
-       ip->ip_src =
-               ((struct sockaddr_in *)&so->so_addr)->sin_addr;
+       if (rp->rcb_flags & RAW_LADDR) {
+               sin = (struct sockaddr_in *)&rp->rcb_laddr;
+               if (sin->sin_family != AF_INET) {
+                       error = EAFNOSUPPORT;
+                       goto bad;
+               }
+               ip->ip_src.s_addr = sin->sin_addr.s_addr;
+       } else
+               ip->ip_src.s_addr = 0;
+       ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr;
        ip->ip_ttl = MAXTTL;
        ip->ip_ttl = MAXTTL;
-       return (ip_output(m, 0));
+       return (ip_output(m, rp->rcb_options, &rp->rcb_route, 
+          (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST));
+bad:
+       m_freem(m);
+       return (error);
 }
 
 /*
 }
 
 /*
- * Intercept control operations related to
- * handling of IP options.  Otherwise,
- * just pass things on to the raw_usrreq
- * routine for setup and tear down of
- * raw control block data structures.
+ * Raw IP socket option processing.
  */
  */
-rip_usrreq(so, req, m, addr)
+rip_ctloutput(op, so, level, optname, m)
+       int op;
        struct socket *so;
        struct socket *so;
-       int req;
-       struct mbuf *m;
-       caddr_t addr;
+       int level, optname;
+       struct mbuf **m;
 {
 {
+       int error = 0;
        register struct rawcb *rp = sotorawcb(so);
 
        register struct rawcb *rp = sotorawcb(so);
 
-COUNT(RAW_USRREQ);
-       if (rp == 0 && req != PRU_ATTACH)
-               return (EINVAL);
+       if (level != IPPROTO_IP)
+               error = EINVAL;
+       else switch (op) {
 
 
-       switch (req) {
-       
-       /*
-        * SHOULD HAVE CONTROL TO SET PROTOCOL NUMBER (e.g. GGP)
-        */
-       case PRU_CONTROL:
-               return (EOPNOTSUPP);
+       case PRCO_SETOPT:
+               switch (optname) {
+               case IP_OPTIONS:
+                       return (ip_pcbopts(&rp->rcb_options, *m));
+
+               default:
+                       error = EINVAL;
+                       break;
+               }
+               break;
+
+       case PRCO_GETOPT:
+               switch (optname) {
+               case IP_OPTIONS:
+                       *m = m_get(M_WAIT, MT_SOOPTS);
+                       if (rp->rcb_options) {
+                               (*m)->m_off = rp->rcb_options->m_off;
+                               (*m)->m_len = rp->rcb_options->m_len;
+                               bcopy(mtod(rp->rcb_options, caddr_t),
+                                   mtod(*m, caddr_t), (unsigned)(*m)->m_len);
+                       } else
+                               (*m)->m_len = 0;
+                       break;
+               default:
+                       error = EINVAL;
+                       break;
+               }
+               break;
        }
        }
-       return (raw_usrreq(so, req, m, addr));
+       if (op == PRCO_SETOPT && *m)
+               (void)m_free(*m);
+       return (error);
 }
 }