| version 1.29, 1996/05/20 16:56:20 |
version 1.29.2.2, 1996/12/11 04:01:12 |
| 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 414 udp_output(m, va_alist) |
|
| Line 413 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; |
| struct in_addr laddr; |
int error = 0; |
| 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 462 udp_output(m, va_alist) |
|
| Line 433 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 487 udp_output(m, va_alist) |
|
| Line 467 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++; |
| error = ip_output(m, inp->inp_options, &inp->inp_route, |
return (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 509 u_long udp_recvspace = 40 * (1024 + size |
|
| Line 482 u_long udp_recvspace = 40 * (1024 + size |
|
| |
|
| /*ARGSUSED*/ |
/*ARGSUSED*/ |
| int |
int |
| udp_usrreq(so, req, m, addr, control) |
udp_usrreq(so, req, m, nam, control, p) |
| struct socket *so; |
struct socket *so; |
| int req; |
int req; |
| struct mbuf *m, *addr, *control; |
struct mbuf *m, *nam, *control; |
| |
struct proc *p; |
| { |
{ |
| struct inpcb *inp = sotoinpcb(so); |
register struct inpcb *inp; |
| 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)addr, |
return (in_control(so, (long)m, (caddr_t)nam, |
| (struct ifnet *)control)); |
(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 532 udp_usrreq(so, req, m, addr, control) |
|
| Line 514 udp_usrreq(so, req, m, addr, control) |
|
| switch (req) { |
switch (req) { |
| |
|
| case PRU_ATTACH: |
case PRU_ATTACH: |
| if (inp != NULL) { |
if (inp != 0) { |
| error = EINVAL; |
error = EISCONN; |
| break; |
break; |
| } |
} |
| s = splsoftnet(); |
if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { |
| |
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; |
| ((struct inpcb *) so->so_pcb)->inp_ip.ip_ttl = ip_defttl; |
inp = sotoinpcb(so); |
| |
inp->inp_ip.ip_ttl = ip_defttl; |
| break; |
break; |
| |
|
| case PRU_DETACH: |
case PRU_DETACH: |
| udp_detach(inp); |
in_pcbdetach(inp); |
| break; |
break; |
| |
|
| case PRU_BIND: |
case PRU_BIND: |
| s = splsoftnet(); |
error = in_pcbbind(inp, nam, p); |
| error = in_pcbbind(inp, addr); |
|
| splx(s); |
|
| break; |
break; |
| |
|
| case PRU_LISTEN: |
case PRU_LISTEN: |
| Line 562 udp_usrreq(so, req, m, addr, control) |
|
| Line 543 udp_usrreq(so, req, m, addr, control) |
|
| break; |
break; |
| |
|
| case PRU_CONNECT: |
case PRU_CONNECT: |
| if (inp->inp_faddr.s_addr != INADDR_ANY) { |
error = in_pcbconnect(inp, nam); |
| error = EISCONN; |
if (error) |
| 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: |
| if (inp->inp_faddr.s_addr == INADDR_ANY) { |
/*soisdisconnected(so);*/ |
| error = ENOTCONN; |
so->so_state &= ~SS_ISCONNECTED; /* XXX */ |
| break; |
|
| } |
|
| s = splsoftnet(); |
|
| in_pcbdisconnect(inp); |
in_pcbdisconnect(inp); |
| inp->inp_laddr.s_addr = INADDR_ANY; |
inp->inp_laddr.s_addr = INADDR_ANY; /* XXX */ |
| splx(s); |
|
| so->so_state &= ~SS_ISCONNECTED; /* XXX */ |
|
| break; |
break; |
| |
|
| case PRU_SHUTDOWN: |
case PRU_SHUTDOWN: |
| socantsendmore(so); |
socantsendmore(so); |
| break; |
break; |
| |
|
| case PRU_SEND: |
case PRU_RCVD: |
| return (udp_output(m, inp, addr, control)); |
error = EOPNOTSUPP; |
| |
|
| case PRU_ABORT: |
|
| soisdisconnected(so); |
|
| udp_detach(inp); |
|
| break; |
break; |
| |
|
| case PRU_SOCKADDR: |
case PRU_SEND: |
| in_setsockaddr(inp, addr); |
if (control && control->m_len) { |
| break; |
m_freem(control); |
| |
m_freem(m); |
| |
error = EINVAL; |
| |
break; |
| |
} |
| |
{ |
| |
struct in_addr laddr; |
| |
|
| case PRU_PEERADDR: |
if (nam) { |
| in_setpeeraddr(inp, addr); |
laddr = inp->inp_laddr; |
| |
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: |
| case PRU_FASTTIMO: |
m_freem(control); |
| case PRU_SLOWTIMO: |
m_freem(m); |
| case PRU_PROTORCV: |
|
| case PRU_PROTOSEND: |
|
| error = EOPNOTSUPP; |
error = EOPNOTSUPP; |
| break; |
break; |
| |
|
| case PRU_RCVD: |
case PRU_SOCKADDR: |
| case PRU_RCVOOB: |
in_setsockaddr(inp, nam); |
| return (EOPNOTSUPP); /* do not free mbuf's */ |
break; |
| |
|
| |
case PRU_PEERADDR: |
| |
in_setpeeraddr(inp, nam); |
| |
break; |
| |
|
| default: |
default: |
| panic("udp_usrreq"); |
panic("udp_usrreq"); |
| } |
} |
| |
|
| release: |
release: |
| if (control) { |
|
| printf("udp control data unexpectedly retained\n"); |
|
| m_freem(control); |
|
| } |
|
| if (m) |
|
| m_freem(m); |
|
| return (error); |
|
| } |
|
| |
|
| static void |
|
| udp_detach(inp) |
|
| struct inpcb *inp; |
|
| { |
|
| int s = splsoftnet(); |
|
| |
|
| in_pcbdetach(inp); |
|
| splx(s); |
splx(s); |
| |
return (error); |
| } |
} |
| |
|
| /* |
/* |