projects
/
unix-history
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
tags
|
clone url
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
longer TTL's
[unix-history]
/
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
cd4131f
..
7d1dadd
100644
(file)
--- a/
usr/src/sys/netinet/udp_usrreq.c
+++ b/
usr/src/sys/netinet/udp_usrreq.c
@@
-1,23
+1,32
@@
-/* udp_usrreq.c 4.41 82/12/14 */
-
-#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 "../netinet/in.h"
+/*
+ * Copyright (c) 1982 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ * @(#)udp_usrreq.c 6.21 (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 "../net/if.h"
#include "../net/route.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 <errno.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.
/*
* UDP protocol implementation.
@@
-29,16
+38,23
@@
udp_init()
udb.inp_next = udb.inp_prev = &udb;
}
udb.inp_next = udb.inp_prev = &udb;
}
-int udpcksum;
+#ifndef COMPAT_42
+int udpcksum = 1;
+#else
+int udpcksum = 0; /* XXX */
+#endif
+
struct sockaddr_in udp_in = { AF_INET };
struct sockaddr_in udp_in = { AF_INET };
-udp_input(m0)
+udp_input(m0
, ifp
)
struct mbuf *m0;
struct mbuf *m0;
+ struct ifnet *ifp;
{
register struct udpiphdr *ui;
register struct inpcb *inp;
register struct mbuf *m;
int len;
{
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.
/*
* Get IP and UDP header together in first mbuf.
@@
-63,20
+79,23
@@
udp_input(m0)
udpstat.udps_badlen++;
goto bad;
}
udpstat.udps_badlen++;
goto bad;
}
- m_adj(m,
((struct ip *)ui)->ip_len -
len);
- /* (
struct ip *)ui
->ip_len = len; */
+ m_adj(m,
len - ((struct ip *)ui)->ip_
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.
*/
/*
* Checksum extended UDP header and data.
*/
- if (udpcksum) {
+ if (udpcksum
&& ui->ui_sum
) {
ui->ui_next = ui->ui_prev = 0;
ui->ui_x1 = 0;
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++;
if (ui->ui_sum = in_cksum(m, len + sizeof (struct ip))) {
udpstat.udps_badsum++;
- printf("udp cksum %x\n", ui->ui_sum);
m_freem(m);
return;
}
m_freem(m);
return;
}
@@
-89,13
+108,12
@@
udp_input(m0)
ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport,
INPLOOKUP_WILDCARD);
if (inp == 0) {
ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport,
INPLOOKUP_WILDCARD);
if (inp == 0) {
- struct in_addr broadcastaddr;
-
- broadcastaddr =
- if_makeaddr(in_netof(ui->ui_dst), INADDR_ANY);
- if (ui->ui_dst.s_addr == broadcastaddr.s_addr)
+ /* don't send ICMP response for broadcast packet */
+ if (in_broadcast(ui->ui_dst))
goto bad;
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;
}
return;
}
@@
-107,61
+125,70
@@
udp_input(m0)
udp_in.sin_addr = ui->ui_src;
m->m_len -= sizeof (struct udpiphdr);
m->m_off += sizeof (struct udpiphdr);
udp_in.sin_addr = ui->ui_src;
m->m_len -= sizeof (struct udpiphdr);
m->m_off += sizeof (struct udpiphdr);
-SBCHECK(&inp->inp_socket->so_rcv, "udpinput before");
-
if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m
) == 0)
+ if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
+
m, (struct mbuf *)0
) == 0)
goto bad;
goto bad;
-SBCHECK(&inp->inp_socket->so_rcv, "udpinput after");
sorwakeup(inp->inp_socket);
return;
bad:
m_freem(m);
}
sorwakeup(inp->inp_socket);
return;
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
);
- so
isdisconnected(so
);
+
sorwakeup(inp->inp_socket
);
+ so
wwakeup(inp->inp_socket
);
}
}
-udp_ctlinput(cmd,
arg
)
+udp_ctlinput(cmd,
sa
)
int cmd;
int cmd;
-
caddr_t arg
;
+
struct sockaddr *sa
;
{
{
- struct in_addr *sin;
extern u_char inetctlerrmap[];
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;
return;
- switch (cmd) {
- case PRC_ROUTEDEAD:
- break;
+ switch (cmd) {
case PRC_QUENCH:
break;
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:
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)
}
}
udp_output(inp, m0)
- struct inpcb *inp;
+
register
struct inpcb *inp;
struct mbuf *m0;
{
register struct mbuf *m;
register struct udpiphdr *ui;
struct mbuf *m0;
{
register struct mbuf *m;
register struct udpiphdr *ui;
- register struct socket *so;
register int len = 0;
/*
register int len = 0;
/*
@@
-170,7
+197,7
@@
udp_output(inp, m0)
*/
for (m = m0; m; m = m->m_next)
len += m->m_len;
*/
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);
if (m == 0) {
m_freem(m0);
return (ENOBUFS);
@@
-187,54
+214,66
@@
udp_output(inp, m0)
ui->ui_next = ui->ui_prev = 0;
ui->ui_x1 = 0;
ui->ui_pr = IPPROTO_UDP;
ui->ui_next = ui->ui_prev = 0;
ui->ui_x1 = 0;
ui->ui_pr = IPPROTO_UDP;
- ui->ui_len =
len + sizeof (struct udphdr
);
+ ui->ui_len =
htons((u_short)len + sizeof (struct udphdr)
);
ui->ui_src = inp->inp_laddr;
ui->ui_dst = inp->inp_faddr;
ui->ui_sport = inp->inp_lport;
ui->ui_dport = inp->inp_fport;
ui->ui_src = inp->inp_laddr;
ui->ui_dst = inp->inp_faddr;
ui->ui_sport = inp->inp_lport;
ui->ui_dport = inp->inp_fport;
- ui->ui_ulen =
htons((u_short)ui->ui_len)
;
+ ui->ui_ulen =
ui->ui_len
;
/*
* Stuff checksum and output datagram.
*/
ui->ui_sum = 0;
/*
* Stuff checksum and output datagram.
*/
ui->ui_sum = 0;
- ui->ui_sum = in_cksum(m, sizeof (struct udpiphdr) + len);
+ if (udpcksum) {
+ 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_len = sizeof (struct udpiphdr) + len;
- ((struct ip *)ui)->ip_ttl = MAXTTL;
- so = inp->inp_socket;
- return (ip_output(m, (struct mbuf *)0,
- (so->so_options & SO_DONTROUTE) ? &routetoif : (struct route *)0,
- so->so_state & SS_PRIV));
+ ((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*/
/*ARGSUSED*/
-udp_usrreq(so, req, m, nam,
opt
)
+udp_usrreq(so, req, m, nam,
rights
)
struct socket *so;
int req;
struct socket *so;
int req;
- struct mbuf *m, *nam;
- struct socketopt *opt;
+ struct mbuf *m, *nam, *rights;
{
struct inpcb *inp = sotoinpcb(so);
int error = 0;
{
struct inpcb *inp = sotoinpcb(so);
int error = 0;
- if (inp == 0 && req != PRU_ATTACH)
- return (EINVAL);
+ 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;
+ }
+ if (inp == NULL && req != PRU_ATTACH) {
+ error = EINVAL;
+ goto release;
+ }
switch (req) {
case PRU_ATTACH:
switch (req) {
case PRU_ATTACH:
- if (inp != 0)
- return (EINVAL);
+ if (inp != NULL) {
+ error = EINVAL;
+ break;
+ }
error = in_pcballoc(so, &udb);
if (error)
break;
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 (error)
break;
break;
case PRU_DETACH:
- if (inp == 0)
- return (ENOTCONN);
in_pcbdetach(inp);
break;
in_pcbdetach(inp);
break;
@@
-247,21
+286,30
@@
udp_usrreq(so, req, m, nam, opt)
break;
case PRU_CONNECT:
break;
case PRU_CONNECT:
- if (inp->inp_faddr.s_addr)
- return (EISCONN);
+ if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ error = EISCONN;
+ break;
+ }
error = in_pcbconnect(inp, nam);
if (error == 0)
soisconnected(so);
break;
error = in_pcbconnect(inp, nam);
if (error == 0)
soisconnected(so);
break;
+ case PRU_CONNECT2:
+ error = EOPNOTSUPP;
+ break;
+
case PRU_ACCEPT:
case PRU_ACCEPT:
- return (EOPNOTSUPP);
+ error = EOPNOTSUPP;
+ break;
case PRU_DISCONNECT:
case PRU_DISCONNECT:
- if (inp->inp_faddr.s_addr == 0)
- return (ENOTCONN);
+ if (inp->inp_faddr.s_addr == INADDR_ANY) {
+ error = ENOTCONN;
+ break;
+ }
in_pcbdisconnect(inp);
in_pcbdisconnect(inp);
- so
isdisconnected(so);
+ so
->so_state &= ~SS_ISCONNECTED; /* XXX */
break;
case PRU_SHUTDOWN:
break;
case PRU_SHUTDOWN:
@@
-270,22
+318,35
@@
udp_usrreq(so, req, m, nam, opt)
case PRU_SEND: {
struct in_addr laddr;
case PRU_SEND: {
struct in_addr laddr;
+ int s;
if (nam) {
laddr = inp->inp_laddr;
if (nam) {
laddr = inp->inp_laddr;
- if (inp->inp_faddr.s_addr)
- return (EISCONN);
+ if (inp->inp_faddr.s_addr != INADDR_ANY) {
+ error = EISCONN;
+ break;
+ }
+ /*
+ * Must block input while temporarily connected.
+ */
+ s = splnet();
error = in_pcbconnect(inp, nam);
error = in_pcbconnect(inp, nam);
- if (error)
+ if (error) {
+ splx(s);
break;
break;
+ }
} else {
} else {
- if (inp->inp_faddr.s_addr == 0)
- return (ENOTCONN);
+ if (inp->inp_faddr.s_addr == INADDR_ANY) {
+ error = ENOTCONN;
+ break;
+ }
}
error = udp_output(inp, m);
}
error = udp_output(inp, m);
+ m = NULL;
if (nam) {
in_pcbdisconnect(inp);
inp->inp_laddr = laddr;
if (nam) {
in_pcbdisconnect(inp);
inp->inp_laddr = laddr;
+ splx(s);
}
}
break;
}
}
break;
@@
-296,15
+357,37
@@
udp_usrreq(so, req, m, nam, opt)
soisdisconnected(so);
break;
soisdisconnected(so);
break;
- case PRU_CONTROL:
- return (EOPNOTSUPP);
-
case PRU_SOCKADDR:
in_setsockaddr(inp, nam);
break;
case PRU_SOCKADDR:
in_setsockaddr(inp, nam);
break;
+ case PRU_PEERADDR:
+ in_setpeeraddr(inp, nam);
+ break;
+
+ case PRU_SENSE:
+ /*
+ * stat: don't bother with a blocksize.
+ */
+ return (0);
+
+ case PRU_SENDOOB:
+ case PRU_FASTTIMO:
+ case PRU_SLOWTIMO:
+ case PRU_PROTORCV:
+ case PRU_PROTOSEND:
+ error = EOPNOTSUPP;
+ break;
+
+ case PRU_RCVD:
+ case PRU_RCVOOB:
+ return (EOPNOTSUPP); /* do not free mbuf's */
+
default:
panic("udp_usrreq");
}
default:
panic("udp_usrreq");
}
+release:
+ if (m != NULL)
+ m_freem(m);
return (error);
}
return (error);
}