X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/74040e688b2add7cef9c733f2c7007bfa3ec3f8a..233ed7a535fd7c2e5c83f6bbb5a52c5b906385a0:/usr/src/sys/netinet/udp_usrreq.c diff --git a/usr/src/sys/netinet/udp_usrreq.c b/usr/src/sys/netinet/udp_usrreq.c index 5a830d3957..9245aa37f0 100644 --- a/usr/src/sys/netinet/udp_usrreq.c +++ b/usr/src/sys/netinet/udp_usrreq.c @@ -1,26 +1,38 @@ -/* udp_usrreq.c 6.6 84/08/21 */ - -#include "../h/param.h" -#include "../h/dir.h" -#include "../h/user.h" -#include "../h/mbuf.h" -#include "../h/protosw.h" -#include "../h/socket.h" -#include "../h/socketvar.h" -#include "../h/errno.h" -#include "../h/stat.h" +/* + * 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 this notice is preserved and that due credit is given + * to the University of California at 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'' without express or implied warranty. + * + * @(#)udp_usrreq.c 7.5 (Berkeley) %G% + */ + +#include "param.h" +#include "dir.h" +#include "user.h" +#include "mbuf.h" +#include "protosw.h" +#include "socket.h" +#include "socketvar.h" +#include "errno.h" +#include "stat.h" #include "../net/if.h" #include "../net/route.h" -#include "../netinet/in.h" -#include "../netinet/in_pcb.h" -#include "../netinet/in_systm.h" -#include "../netinet/ip.h" -#include "../netinet/ip_var.h" -#include "../netinet/ip_icmp.h" -#include "../netinet/udp.h" -#include "../netinet/udp_var.h" +#include "in.h" +#include "in_pcb.h" +#include "in_systm.h" +#include "ip.h" +#include "ip_var.h" +#include "ip_icmp.h" +#include "udp.h" +#include "udp_var.h" /* * UDP protocol implementation. @@ -32,16 +44,24 @@ udp_init() udb.inp_next = udb.inp_prev = &udb; } -int udpcksum = 0; +#ifndef COMPAT_42 +int udpcksum = 1; +#else +int udpcksum = 0; /* XXX */ +#endif +int udp_ttl = UDP_TTL; + struct sockaddr_in udp_in = { AF_INET }; -udp_input(m0) +udp_input(m0, ifp) struct mbuf *m0; + struct ifnet *ifp; { 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. @@ -67,8 +87,12 @@ udp_input(m0) goto bad; } m_adj(m, len - ((struct ip *)ui)->ip_len); - /* (struct ip *)ui->ip_len = len; */ + /* ((struct ip *)ui)->ip_len = len; */ } + /* + * Save a copy of the IP header in case we want restore it for ICMP. + */ + ip = *(struct ip*)ui; /* * Checksum extended UDP header and data. @@ -76,7 +100,7 @@ udp_input(m0) if (udpcksum && ui->ui_sum) { ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; - ui->ui_len = htons((u_short)len); + ui->ui_len = ui->ui_ulen; if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) { udpstat.udps_badsum++; m_freem(m); @@ -92,9 +116,11 @@ udp_input(m0) INPLOOKUP_WILDCARD); if (inp == 0) { /* don't send ICMP response for broadcast packet */ - if (in_lnaof(ui->ui_dst) == INADDR_ANY) + if (in_broadcast(ui->ui_dst)) goto bad; - icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT); + *(struct ip *)ui = ip; + icmp_error((struct ip *)ui, ICMP_UNREACH, ICMP_UNREACH_PORT, + ifp); return; } @@ -115,53 +141,62 @@ bad: m_freem(m); } -udp_abort(inp) - struct inpcb *inp; +/* + * 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; { - struct socket *so = inp->inp_socket; - in_pcbdisconnect(inp); - soisdisconnected(so); + sorwakeup(inp->inp_socket); + sowwakeup(inp->inp_socket); } -udp_ctlinput(cmd, arg) +udp_ctlinput(cmd, sa) int cmd; - caddr_t arg; + struct sockaddr *sa; { - struct in_addr *sin; extern u_char inetctlerrmap[]; + struct sockaddr_in *sin; + int in_rtchange(); - if (cmd < 0 || cmd > PRC_NCMDS) + if ((unsigned)cmd > PRC_NCMDS) + return; + if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK) + return; + sin = (struct sockaddr_in *)sa; + if (sin->sin_addr.s_addr == INADDR_ANY) return; - switch (cmd) { - case PRC_ROUTEDEAD: - break; + switch (cmd) { case PRC_QUENCH: break; - /* these are handled by ip */ - case PRC_IFDOWN: - case PRC_HOSTDEAD: - case PRC_HOSTUNREACH: + case PRC_ROUTEDEAD: + case PRC_REDIRECT_NET: + case PRC_REDIRECT_HOST: + case PRC_REDIRECT_TOSNET: + case PRC_REDIRECT_TOSHOST: + in_pcbnotify(&udb, &sin->sin_addr, 0, in_rtchange); break; default: - sin = &((struct icmp *)arg)->icmp_ip.ip_dst; - in_pcbnotify(&udb, sin, (int)inetctlerrmap[cmd], udp_abort); + if (inetctlerrmap[cmd] == 0) + return; /* XXX */ + in_pcbnotify(&udb, &sin->sin_addr, (int)inetctlerrmap[cmd], + udp_notify); } } udp_output(inp, m0) - struct inpcb *inp; + register struct inpcb *inp; struct mbuf *m0; { register struct mbuf *m; register struct udpiphdr *ui; - register struct socket *so; register int len = 0; - register struct route *ro; /* * Calculate data length and get a mbuf @@ -169,7 +204,7 @@ udp_output(inp, m0) */ for (m = m0; m; m = m->m_next) len += m->m_len; - m = m_get(M_DONTWAIT, MT_HEADER); + MGET(m, M_DONTWAIT, MT_HEADER); if (m == 0) { m_freem(m0); return (ENOBUFS); @@ -197,31 +232,19 @@ udp_output(inp, m0) * Stuff checksum and output datagram. */ ui->ui_sum = 0; - if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) - ui->ui_sum = -1; - ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; - ((struct ip *)ui)->ip_ttl = MAXTTL; - so = inp->inp_socket; - if (so->so_options & SO_DONTROUTE) - return (ip_output(m, (struct mbuf *)0, (struct route *)0, - (so->so_state & SS_PRIV) | IP_ROUTETOIF)); - /* - * Use cached route for previous datagram if - * this is also to the same destination. - * - * NB: We don't handle broadcasts because that - * would require 3 subroutine calls. - */ - ro = &inp->inp_route; -#define satosin(sa) ((struct sockaddr_in *)(sa)) - if (ro->ro_rt && - satosin(&ro->ro_dst)->sin_addr.s_addr != ui->ui_dst.s_addr) { - RTFREE(ro->ro_rt); - ro->ro_rt = (struct rtentry *)0; + if (udpcksum) { + if ((ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len)) == 0) + ui->ui_sum = 0xffff; } - return (ip_output(m, (struct mbuf *)0, ro, so->so_state & SS_PRIV)); + ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len; + ((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))); } +int udp_sendspace = 2048; /* really max datagram size */ +int udp_recvspace = 4 * (1024+sizeof(struct sockaddr_in)); /* 4 1K dgrams */ + /*ARGSUSED*/ udp_usrreq(so, req, m, nam, rights) struct socket *so; @@ -231,6 +254,9 @@ udp_usrreq(so, req, m, nam, rights) struct inpcb *inp = sotoinpcb(so); int error = 0; + if (req == PRU_CONTROL) + return (in_control(so, (int)m, (caddr_t)nam, + (struct ifnet *)rights)); if (rights && rights->m_len) { error = EINVAL; goto release; @@ -249,16 +275,12 @@ udp_usrreq(so, req, m, nam, rights) error = in_pcballoc(so, &udb); if (error) break; - error = soreserve(so, 2048, 2048); + error = soreserve(so, udp_sendspace, udp_recvspace); if (error) break; break; case PRU_DETACH: - if (inp == NULL) { - error = ENOTCONN; - break; - } in_pcbdetach(inp); break; @@ -294,7 +316,7 @@ udp_usrreq(so, req, m, nam, rights) break; } in_pcbdisconnect(inp); - soisdisconnected(so); + so->so_state &= ~SS_ISCONNECTED; /* XXX */ break; case PRU_SHUTDOWN: @@ -330,16 +352,15 @@ udp_usrreq(so, req, m, nam, rights) m = NULL; if (nam) { in_pcbdisconnect(inp); - splx(s); inp->inp_laddr = laddr; + splx(s); } } break; case PRU_ABORT: - in_pcbdetach(inp); - sofree(so); soisdisconnected(so); + in_pcbdetach(inp); break; case PRU_SOCKADDR: @@ -364,7 +385,6 @@ udp_usrreq(so, req, m, nam, rights) error = EOPNOTSUPP; break; - case PRU_CONTROL: case PRU_RCVD: case PRU_RCVOOB: return (EOPNOTSUPP); /* do not free mbuf's */