| version 1.29.2.2, 1996/12/11 04:01:12 |
version 1.30, 1996/05/22 13:55:37 |
| Line 76 int udpcksum = 0; /* XXX */ |
|
| Line 76 int udpcksum = 0; /* XXX */ |
|
| |
|
| struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET }; |
struct sockaddr_in udp_in = { sizeof(udp_in), AF_INET }; |
| |
|
| |
static void udp_detach __P((struct inpcb *)); |
| static void udp_notify __P((struct inpcb *, int)); |
static void udp_notify __P((struct inpcb *, int)); |
| static struct mbuf *udp_saveopt __P((caddr_t, int, int)); |
static struct mbuf *udp_saveopt __P((caddr_t, int, int)); |
| |
|
| Line 413 udp_output(m, va_alist) |
|
| Line 414 udp_output(m, va_alist) |
|
| #endif |
#endif |
| { |
{ |
| register struct inpcb *inp; |
register struct inpcb *inp; |
| |
struct mbuf *addr, *control; |
| register struct udpiphdr *ui; |
register struct udpiphdr *ui; |
| register int len = m->m_pkthdr.len; |
register int len = m->m_pkthdr.len; |
| int error = 0; |
struct in_addr laddr; |
| |
int s = 0, error = 0; |
| va_list ap; |
va_list ap; |
| |
|
| va_start(ap, m); |
va_start(ap, m); |
| inp = va_arg(ap, struct inpcb *); |
inp = va_arg(ap, struct inpcb *); |
| |
addr = va_arg(ap, struct mbuf *); |
| |
control = va_arg(ap, struct mbuf *); |
| va_end(ap); |
va_end(ap); |
| |
|
| |
if (control) |
| |
m_freem(control); /* XXX */ |
| |
|
| |
if (addr) { |
| |
laddr = inp->inp_laddr; |
| |
if (inp->inp_faddr.s_addr != INADDR_ANY) { |
| |
error = EISCONN; |
| |
goto release; |
| |
} |
| |
/* |
| |
* Must block input while temporarily connected. |
| |
*/ |
| |
s = splsoftnet(); |
| |
error = in_pcbconnect(inp, addr); |
| |
if (error) { |
| |
splx(s); |
| |
goto release; |
| |
} |
| |
} else { |
| |
if (inp->inp_faddr.s_addr == INADDR_ANY) { |
| |
error = ENOTCONN; |
| |
goto release; |
| |
} |
| |
} |
| /* |
/* |
| * Calculate data length and get a mbuf |
* Calculate data length and get a mbuf |
| * for UDP and IP headers. |
* for UDP and IP headers. |
| Line 433 udp_output(m, va_alist) |
|
| Line 462 udp_output(m, va_alist) |
|
| } |
} |
| |
|
| /* |
/* |
| * Compute the packet length of the IP header, and |
|
| * punt if the length looks bogus. |
|
| */ |
|
| if ((len + sizeof(struct udpiphdr)) > IP_MAXPACKET) { |
|
| error = EMSGSIZE; |
|
| goto release; |
|
| } |
|
| |
|
| /* |
|
| * Fill in mbuf with extended UDP header |
* Fill in mbuf with extended UDP header |
| * and addresses and length put into network format. |
* and addresses and length put into network format. |
| */ |
*/ |
| Line 467 udp_output(m, va_alist) |
|
| Line 487 udp_output(m, va_alist) |
|
| ((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ |
((struct ip *)ui)->ip_ttl = inp->inp_ip.ip_ttl; /* XXX */ |
| ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ |
((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ |
| udpstat.udps_opackets++; |
udpstat.udps_opackets++; |
| return (ip_output(m, inp->inp_options, &inp->inp_route, |
error = ip_output(m, inp->inp_options, &inp->inp_route, |
| inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), |
inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), |
| inp->inp_moptions)); |
inp->inp_moptions); |
| |
|
| |
if (addr) { |
| |
in_pcbdisconnect(inp); |
| |
inp->inp_laddr = laddr; |
| |
splx(s); |
| |
} |
| |
return (error); |
| |
|
| release: |
release: |
| m_freem(m); |
m_freem(m); |
| Line 482 u_long udp_recvspace = 40 * (1024 + size |
|
| Line 509 u_long udp_recvspace = 40 * (1024 + size |
|
| |
|
| /*ARGSUSED*/ |
/*ARGSUSED*/ |
| int |
int |
| udp_usrreq(so, req, m, nam, control, p) |
udp_usrreq(so, req, m, addr, control, p) |
| struct socket *so; |
struct socket *so; |
| int req; |
int req; |
| struct mbuf *m, *nam, *control; |
struct mbuf *m, *addr, *control; |
| struct proc *p; |
struct proc *p; |
| { |
{ |
| register struct inpcb *inp; |
struct inpcb *inp = sotoinpcb(so); |
| |
int error = 0; |
| int s; |
int s; |
| register int error = 0; |
|
| |
|
| if (req == PRU_CONTROL) |
if (req == PRU_CONTROL) |
| return (in_control(so, (long)m, (caddr_t)nam, |
return (in_control(so, (long)m, (caddr_t)addr, |
| (struct ifnet *)control, p)); |
(struct ifnet *)control, p)); |
| |
if (inp == NULL && req != PRU_ATTACH) { |
| s = splsoftnet(); |
|
| inp = sotoinpcb(so); |
|
| #ifdef DIAGNOSTIC |
|
| if (req != PRU_SEND && req != PRU_SENDOOB && control) |
|
| panic("udp_usrreq: unexpected control mbuf"); |
|
| #endif |
|
| if (inp == 0 && req != PRU_ATTACH) { |
|
| error = EINVAL; |
error = EINVAL; |
| goto release; |
goto release; |
| } |
} |
| |
|
| /* |
/* |
| * Note: need to block udp_input while changing |
* Note: need to block udp_input while changing |
| * the udp pcb queue and/or pcb addresses. |
* the udp pcb queue and/or pcb addresses. |
| Line 514 udp_usrreq(so, req, m, nam, control, p) |
|
| Line 533 udp_usrreq(so, req, m, nam, control, p) |
|
| switch (req) { |
switch (req) { |
| |
|
| case PRU_ATTACH: |
case PRU_ATTACH: |
| if (inp != 0) { |
if (inp != NULL) { |
| error = EISCONN; |
error = EINVAL; |
| break; |
break; |
| } |
} |
| if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { |
s = splsoftnet(); |
| error = soreserve(so, udp_sendspace, udp_recvspace); |
|
| if (error) |
|
| break; |
|
| } |
|
| error = in_pcballoc(so, &udbtable); |
error = in_pcballoc(so, &udbtable); |
| |
splx(s); |
| |
if (error) |
| |
break; |
| |
error = soreserve(so, udp_sendspace, udp_recvspace); |
| if (error) |
if (error) |
| break; |
break; |
| inp = sotoinpcb(so); |
((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl; |
| inp->inp_ip.ip_ttl = ip_defttl; |
|
| break; |
break; |
| |
|
| case PRU_DETACH: |
case PRU_DETACH: |
| in_pcbdetach(inp); |
udp_detach(inp); |
| break; |
break; |
| |
|
| case PRU_BIND: |
case PRU_BIND: |
| error = in_pcbbind(inp, nam, p); |
s = splsoftnet(); |
| |
error = in_pcbbind(inp, addr, p); |
| |
splx(s); |
| break; |
break; |
| |
|
| case PRU_LISTEN: |
case PRU_LISTEN: |
| Line 543 udp_usrreq(so, req, m, nam, control, p) |
|
| Line 563 udp_usrreq(so, req, m, nam, control, p) |
|
| break; |
break; |
| |
|
| case PRU_CONNECT: |
case PRU_CONNECT: |
| error = in_pcbconnect(inp, nam); |
if (inp->inp_faddr.s_addr != INADDR_ANY) { |
| if (error) |
error = EISCONN; |
| break; |
break; |
| soisconnected(so); |
} |
| |
s = splsoftnet(); |
| |
error = in_pcbconnect(inp, addr); |
| |
splx(s); |
| |
if (error == 0) |
| |
soisconnected(so); |
| break; |
break; |
| |
|
| case PRU_CONNECT2: |
case PRU_CONNECT2: |
| error = EOPNOTSUPP; |
error = EOPNOTSUPP; |
| break; |
break; |
| |
|
| |
case PRU_ACCEPT: |
| |
error = EOPNOTSUPP; |
| |
break; |
| |
|
| case PRU_DISCONNECT: |
case PRU_DISCONNECT: |
| /*soisdisconnected(so);*/ |
if (inp->inp_faddr.s_addr == INADDR_ANY) { |
| so->so_state &= ~SS_ISCONNECTED; /* XXX */ |
error = ENOTCONN; |
| |
break; |
| |
} |
| |
s = splsoftnet(); |
| in_pcbdisconnect(inp); |
in_pcbdisconnect(inp); |
| inp->inp_laddr.s_addr = INADDR_ANY; /* XXX */ |
inp->inp_laddr.s_addr = INADDR_ANY; |
| |
splx(s); |
| |
so->so_state &= ~SS_ISCONNECTED; /* XXX */ |
| break; |
break; |
| |
|
| case PRU_SHUTDOWN: |
case PRU_SHUTDOWN: |
| socantsendmore(so); |
socantsendmore(so); |
| break; |
break; |
| |
|
| case PRU_RCVD: |
case PRU_SEND: |
| error = EOPNOTSUPP; |
return (udp_output(m, inp, addr, control)); |
| |
|
| |
case PRU_ABORT: |
| |
soisdisconnected(so); |
| |
udp_detach(inp); |
| break; |
break; |
| |
|
| case PRU_SEND: |
case PRU_SOCKADDR: |
| if (control && control->m_len) { |
in_setsockaddr(inp, addr); |
| m_freem(control); |
break; |
| m_freem(m); |
|
| error = EINVAL; |
|
| break; |
|
| } |
|
| { |
|
| struct in_addr laddr; |
|
| |
|
| if (nam) { |
case PRU_PEERADDR: |
| laddr = inp->inp_laddr; |
in_setpeeraddr(inp, addr); |
| if ((so->so_state & SS_ISCONNECTED) != 0) { |
|
| error = EISCONN; |
|
| goto die; |
|
| } |
|
| error = in_pcbconnect(inp, nam); |
|
| if (error) { |
|
| die: |
|
| m_freem(m); |
|
| break; |
|
| } |
|
| } else { |
|
| if ((so->so_state & SS_ISCONNECTED) == 0) { |
|
| error = ENOTCONN; |
|
| goto die; |
|
| } |
|
| } |
|
| error = udp_output(m, inp); |
|
| if (nam) { |
|
| in_pcbdisconnect(inp); |
|
| inp->inp_laddr = laddr; |
|
| } |
|
| } |
|
| break; |
break; |
| |
|
| case PRU_SENSE: |
case PRU_SENSE: |
| /* |
/* |
| * stat: don't bother with a blocksize. |
* stat: don't bother with a blocksize. |
| */ |
*/ |
| splx(s); |
|
| return (0); |
return (0); |
| |
|
| case PRU_RCVOOB: |
|
| error = EOPNOTSUPP; |
|
| break; |
|
| |
|
| case PRU_SENDOOB: |
case PRU_SENDOOB: |
| m_freem(control); |
case PRU_FASTTIMO: |
| m_freem(m); |
case PRU_SLOWTIMO: |
| |
case PRU_PROTORCV: |
| |
case PRU_PROTOSEND: |
| error = EOPNOTSUPP; |
error = EOPNOTSUPP; |
| break; |
break; |
| |
|
| case PRU_SOCKADDR: |
case PRU_RCVD: |
| in_setsockaddr(inp, nam); |
case PRU_RCVOOB: |
| break; |
return (EOPNOTSUPP); /* do not free mbuf's */ |
| |
|
| case PRU_PEERADDR: |
|
| in_setpeeraddr(inp, nam); |
|
| break; |
|
| |
|
| default: |
default: |
| panic("udp_usrreq"); |
panic("udp_usrreq"); |
| } |
} |
| |
|
| release: |
release: |
| splx(s); |
if (control) { |
| |
printf("udp control data unexpectedly retained\n"); |
| |
m_freem(control); |
| |
} |
| |
if (m) |
| |
m_freem(m); |
| return (error); |
return (error); |
| } |
} |
| |
|
| |
static void |
| |
udp_detach(inp) |
| |
struct inpcb *inp; |
| |
{ |
| |
int s = splsoftnet(); |
| |
|
| |
in_pcbdetach(inp); |
| |
splx(s); |
| |
} |
| |
|
| /* |
/* |
| * Sysctl for udp variables. |
* Sysctl for udp variables. |
| */ |
*/ |