date and time created 88/12/14 15:29:27 by sklower
[unix-history] / usr / src / sys / netinet / udp_usrreq.c
index 1f137f6..0edf4fa 100644 (file)
@@ -1,14 +1,26 @@
 /*
 /*
- * Copyright (c) 1982 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
+ * All rights reserved.
  *
  *
- *     @(#)udp_usrreq.c        6.20 (Berkeley) %G%
+ * 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.
+ *
+ *     @(#)udp_usrreq.c        7.9 (Berkeley) %G%
  */
 
 #include "param.h"
 #include "dir.h"
 #include "user.h"
  */
 
 #include "param.h"
 #include "dir.h"
 #include "user.h"
+#include "malloc.h"
 #include "mbuf.h"
 #include "protosw.h"
 #include "socket.h"
 #include "mbuf.h"
 #include "protosw.h"
 #include "socket.h"
@@ -43,31 +55,33 @@ int udpcksum = 1;
 #else
 int    udpcksum = 0;           /* XXX */
 #endif
 #else
 int    udpcksum = 0;           /* XXX */
 #endif
+int    udp_ttl = UDP_TTL;
 
 struct sockaddr_in udp_in = { AF_INET };
 
 
 struct sockaddr_in udp_in = { AF_INET };
 
-udp_input(m0, ifp)
-       struct mbuf *m0;
-       struct ifnet *ifp;
+udp_input(m, iphlen)
+       register struct mbuf *m;
+       int iphlen;
 {
        register struct udpiphdr *ui;
        register struct inpcb *inp;
 {
        register struct udpiphdr *ui;
        register struct inpcb *inp;
-       register struct mbuf *m;
        int len;
        struct ip ip;
 
        /*
         * Get IP and UDP header together in first mbuf.
        int len;
        struct ip ip;
 
        /*
         * Get IP and UDP header together in first mbuf.
+        * Note: IP leaves IP header in first mbuf.
         */
         */
-       m = m0;
-       if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct udpiphdr)) &&
-           (m = m_pullup(m, sizeof (struct udpiphdr))) == 0) {
-               udpstat.udps_hdrops++;
-               return;
-       }
        ui = mtod(m, struct udpiphdr *);
        ui = mtod(m, struct udpiphdr *);
-       if (((struct ip *)ui)->ip_hl > (sizeof (struct ip) >> 2))
-               ip_stripoptions((struct ip *)ui, (struct mbuf *)0);
+       if (iphlen > sizeof (struct ip))
+               ip_stripoptions(m, (struct mbuf *)0);
+       if (m->m_len < sizeof (struct udpiphdr)) {
+               if ((m = m_pullup(m, sizeof (struct udpiphdr))) == 0) {
+                       udpstat.udps_hdrops++;
+                       return;
+               }
+               ui = mtod(m, struct udpiphdr *);
+       }
 
        /*
         * Make mbuf data length reflect UDP length.
 
        /*
         * Make mbuf data length reflect UDP length.
@@ -85,7 +99,7 @@ udp_input(m0, ifp)
        /*
         * Save a copy of the IP header in case we want restore it for ICMP.
         */
        /*
         * Save a copy of the IP header in case we want restore it for ICMP.
         */
-       ip = *(struct ip*)ui;
+       ip = *(struct ip *)ui;
 
        /*
         * Checksum extended UDP header and data.
 
        /*
         * Checksum extended UDP header and data.
@@ -109,11 +123,10 @@ udp_input(m0, ifp)
                INPLOOKUP_WILDCARD);
        if (inp == 0) {
                /* don't send ICMP response for broadcast packet */
                INPLOOKUP_WILDCARD);
        if (inp == 0) {
                /* don't send ICMP response for broadcast packet */
-               if (in_broadcast(ui->ui_dst))
+               if (m->m_flags & M_BCAST)
                        goto bad;
                *(struct ip *)ui = ip;
                        goto bad;
                *(struct ip *)ui = ip;
-               icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT,
-                   ifp);
+               icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT);
                return;
        }
 
                return;
        }
 
@@ -124,7 +137,8 @@ udp_input(m0, ifp)
        udp_in.sin_port = ui->ui_sport;
        udp_in.sin_addr = ui->ui_src;
        m->m_len -= sizeof (struct udpiphdr);
        udp_in.sin_port = ui->ui_sport;
        udp_in.sin_addr = ui->ui_src;
        m->m_len -= sizeof (struct udpiphdr);
-       m->m_off += sizeof (struct udpiphdr);
+       m->m_pkthdr.len -= sizeof (struct udpiphdr);
+       m->m_data += sizeof (struct udpiphdr);
        if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
            m, (struct mbuf *)0) == 0)
                goto bad;
        if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
            m, (struct mbuf *)0) == 0)
                goto bad;
@@ -134,6 +148,18 @@ bad:
        m_freem(m);
 }
 
        m_freem(m);
 }
 
+/*
+ * Notify a udp user of an asynchronous error;
+ * just wake up so that he can collect error status.
+ */
+udp_notify(inp)
+       register struct inpcb *inp;
+{
+
+       sorwakeup(inp->inp_socket);
+       sowwakeup(inp->inp_socket);
+}
+
 udp_ctlinput(cmd, sa)
        int cmd;
        struct sockaddr *sa;
 udp_ctlinput(cmd, sa)
        int cmd;
        struct sockaddr *sa;
@@ -167,37 +193,27 @@ udp_ctlinput(cmd, sa)
                if (inetctlerrmap[cmd] == 0)
                        return;         /* XXX */
                in_pcbnotify(&udb, &sin->sin_addr, (int)inetctlerrmap[cmd],
                if (inetctlerrmap[cmd] == 0)
                        return;         /* XXX */
                in_pcbnotify(&udb, &sin->sin_addr, (int)inetctlerrmap[cmd],
-                       (int (*)())0);
+                       udp_notify);
        }
 }
 
        }
 }
 
-udp_output(inp, m0)
+udp_output(inp, m)
        register struct inpcb *inp;
        register struct inpcb *inp;
-       struct mbuf *m0;
-{
        register struct mbuf *m;
        register struct mbuf *m;
+{
        register struct udpiphdr *ui;
        register struct udpiphdr *ui;
-       register int len = 0;
+       register int len = m->m_pkthdr.len;
 
        /*
         * Calculate data length and get a mbuf
         * for UDP and IP headers.
         */
 
        /*
         * Calculate data length and get a mbuf
         * for UDP and IP headers.
         */
-       for (m = m0; m; m = m->m_next)
-               len += m->m_len;
-       MGET(m, M_DONTWAIT, MT_HEADER);
-       if (m == 0) {
-               m_freem(m0);
-               return (ENOBUFS);
-       }
+       M_PREPEND(m, sizeof(struct udpiphdr), M_WAIT);
 
        /*
         * Fill in mbuf with extended UDP header
         * and addresses and length put into network format.
         */
 
        /*
         * Fill in mbuf with extended UDP header
         * and addresses and length put into network format.
         */
-       m->m_off = MMAXOFF - sizeof (struct udpiphdr);
-       m->m_len = sizeof (struct udpiphdr);
-       m->m_next = m0;
        ui = mtod(m, struct udpiphdr *);
        ui->ui_next = ui->ui_prev = 0;
        ui->ui_x1 = 0;
        ui = mtod(m, struct udpiphdr *);
        ui->ui_next = ui->ui_prev = 0;
        ui->ui_x1 = 0;
@@ -215,22 +231,22 @@ udp_output(inp, m0)
        ui->ui_sum = 0;
        if (udpcksum) {
            if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
        ui->ui_sum = 0;
        if (udpcksum) {
            if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0)
-               ui->ui_sum = -1;
+               ui->ui_sum = 0xffff;
        }
        ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
        }
        ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
-       ((struct ip *)ui)->ip_ttl = UDP_TTL;
+       ((struct ip *)ui)->ip_ttl = udp_ttl;
        return (ip_output(m, inp->inp_options, &inp->inp_route,
            inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)));
 }
 
        return (ip_output(m, inp->inp_options, &inp->inp_route,
            inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST)));
 }
 
-int    udp_sendspace = 2048;           /* really max datagram size */
-int    udp_recvspace = 4 * (1024+sizeof(struct sockaddr_in)); /* 4 1K dgrams */
+u_long udp_sendspace = 2048;           /* really max datagram size */
+u_long udp_recvspace = 4 * (1024+sizeof(struct sockaddr_in)); /* 4 1K dgrams */
 
 /*ARGSUSED*/
 
 /*ARGSUSED*/
-udp_usrreq(so, req, m, nam, rights)
+udp_usrreq(so, req, m, nam, rights, control)
        struct socket *so;
        int req;
        struct socket *so;
        int req;
-       struct mbuf *m, *nam, *rights;
+       struct mbuf *m, *nam, *rights, *control;
 {
        struct inpcb *inp = sotoinpcb(so);
        int error = 0;
 {
        struct inpcb *inp = sotoinpcb(so);
        int error = 0;
@@ -340,9 +356,8 @@ udp_usrreq(so, req, m, nam, rights)
                break;
 
        case PRU_ABORT:
                break;
 
        case PRU_ABORT:
-               in_pcbdetach(inp);
-               sofree(so);
                soisdisconnected(so);
                soisdisconnected(so);
+               in_pcbdetach(inp);
                break;
 
        case PRU_SOCKADDR:
                break;
 
        case PRU_SOCKADDR: