start rewrite
[unix-history] / usr / src / sys / netinet / udp_usrreq.c
CommitLineData
9190426d 1/* udp_usrreq.c 4.10 81/11/24 */
1bd53abe
BJ
2
3#include "../h/param.h"
53a5409e
BJ
4#include "../h/dir.h"
5#include "../h/user.h"
1bd53abe 6#include "../h/mbuf.h"
d52566dd 7#include "../h/protosw.h"
53a5409e
BJ
8#include "../h/socket.h"
9#include "../h/socketvar.h"
d52566dd 10#include "../net/inet.h"
53a5409e 11#include "../net/inet_pcb.h"
d52566dd 12#include "../net/inet_systm.h"
eb44bfb2
BJ
13#include "../net/ip.h"
14#include "../net/ip_var.h"
53a5409e
BJ
15#include "../net/udp.h"
16#include "../net/udp_var.h"
d52566dd 17
2b4b57cd
BJ
18/*
19 * UDP protocol implementation.
20 * Per RFC 768, August, 1980.
21 */
d52566dd
BJ
22udp_init()
23{
24
eb44bfb2 25 udb.inp_next = udb.inp_prev = &udb;
d52566dd 26}
1bd53abe 27
eb44bfb2 28int udpcksum;
2b4b57cd 29struct sockaddr_in udp_in = { AF_INET };
eb44bfb2 30
2b4b57cd
BJ
31udp_input(m0)
32 struct mbuf *m0;
1bd53abe 33{
eb44bfb2 34 register struct udpiphdr *ui;
53a5409e 35 register struct inpcb *inp;
2b4b57cd
BJ
36 register struct mbuf *m;
37 int len, ulen;
eb44bfb2 38
2b4b57cd
BJ
39 /*
40 * Get ip and udp header together in first mbuf.
41 */
42 m = m0;
2b4b57cd
BJ
43 if (m->m_len < sizeof (struct udpiphdr) &&
44 m_pullup(m, sizeof (struct udpiphdr)) == 0) {
45 udpstat.udps_hdrops++;
46 goto bad;
47 }
4e60622a
BJ
48 ui = mtod(m, struct udpiphdr *);
49 if (ui->ui_len > sizeof (struct ip))
50 ip_stripoptions((struct ip *)ui, (char *)0);
2b4b57cd
BJ
51
52 /*
53 * Make mbuf data length reflect udp length.
54 * If not enough data to reflect udp length, drop.
55 */
4ad99bae 56 ulen = ntohs((u_short)ui->ui_ulen);
2b4b57cd
BJ
57 len = sizeof (struct udpiphdr) + ulen;
58 if (((struct ip *)ui)->ip_len != len) {
59 if (len > ((struct ip *)ui)->ip_len) {
60 udpstat.udps_badlen++;
61 goto bad;
62 }
63 m_adj(m, ((struct ip *)ui)->ip_len - len);
64 /* (struct ip *)ui->ip_len = len; */
65 }
66
67 /*
68 * Checksum extended udp header and data.
69 */
eb44bfb2 70 if (udpcksum) {
2b4b57cd
BJ
71 ui->ui_next = ui->ui_prev = 0;
72 ui->ui_x1 = 0;
4ad99bae 73 ui->ui_len = htons((u_short)(sizeof (struct udpiphdr) + ulen));
4e60622a 74 if ((ui->ui_sum = inet_cksum(m, len)) != 0xffff) {
2b4b57cd 75 udpstat.udps_badsum++;
eb44bfb2
BJ
76 printf("udp cksum %x\n", ui->ui_sum);
77 m_freem(m);
78 return;
79 }
80 }
2b4b57cd
BJ
81
82 /*
83 * Convert addresses and ports to host format.
84 * Locate pcb for datagram.
85 */
2b4b57cd
BJ
86 inp = in_pcblookup(&udb,
87 ui->ui_src, ui->ui_sport, ui->ui_dst, ui->ui_dport);
bbb5f5dd 88 if (inp == 0)
2b4b57cd
BJ
89 goto bad;
90
91 /*
92 * Construct sockaddr format source address.
93 * Stuff source address and datagram in user buffer.
94 */
95 udp_in.sin_port = ui->ui_sport;
96 udp_in.sin_addr = ui->ui_src;
4e60622a
BJ
97 m->m_len -= sizeof (struct udpiphdr);
98 m->m_off += sizeof (struct udpiphdr);
99 if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in, m) == 0)
2b4b57cd 100 goto bad;
4e60622a 101 sorwakeup(inp->inp_socket);
53a5409e 102 return;
2b4b57cd 103bad:
53a5409e 104 m_freem(m);
1bd53abe
BJ
105}
106
cdad2eb1 107udp_ctlinput(m)
1bd53abe
BJ
108 struct mbuf *m;
109{
110
4e60622a 111 printf("udp_ctlinput\n");
1bd53abe
BJ
112 m_freem(m);
113}
114
cdad2eb1 115/*ARGSUSED*/
4ad99bae 116udp_output(inp, m0)
2b4b57cd 117 struct inpcb *inp;
2b4b57cd 118 struct mbuf *m0;
1bd53abe 119{
2b4b57cd
BJ
120 register struct mbuf *m;
121 register struct udpiphdr *ui;
122 register int len = 0;
123
124 /*
125 * Calculate data length and get a mbuf
126 * for udp and ip headers.
127 */
128 for (m = m0; m; m = m->m_next)
129 len += m->m_len;
130 m = m_get(0);
bbb5f5dd 131 if (m == 0)
2b4b57cd
BJ
132 goto bad;
133
134 /*
135 * Fill in mbuf with extended udp header
136 * and addresses and length put into network format.
137 */
138 m->m_off = MMAXOFF - sizeof (struct udpiphdr);
139 m->m_len = sizeof (struct udpiphdr);
140 m->m_next = m0;
141 ui = mtod(m, struct udpiphdr *);
142 ui->ui_next = ui->ui_prev = 0;
143 ui->ui_x1 = 0;
144 ui->ui_pr = IPPROTO_UDP;
4e60622a
BJ
145 ui->ui_len = sizeof (struct udpiphdr) + len;
146 ui->ui_src = inp->inp_laddr;
147 ui->ui_dst = inp->inp_faddr;
148 ui->ui_sport = inp->inp_lport;
149 ui->ui_dport = inp->inp_fport;
4ad99bae 150 ui->ui_ulen = htons((u_short)len);
2b4b57cd
BJ
151
152 /*
153 * Stuff checksum and output datagram.
154 */
155 ui->ui_sum = 0;
156 ui->ui_sum = inet_cksum(m, sizeof (struct udpiphdr) + len);
4e60622a
BJ
157 ((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
158 ((struct ip *)ui)->ip_ttl = MAXTTL;
53a5409e 159 ip_output(m);
2b4b57cd
BJ
160 return;
161bad:
162 m_freem(m);
1bd53abe
BJ
163}
164
cdad2eb1 165/*ARGSUSED*/
53a5409e
BJ
166udp_usrreq(so, req, m, addr)
167 struct socket *so;
1bd53abe
BJ
168 int req;
169 struct mbuf *m;
cdad2eb1 170 caddr_t addr;
1bd53abe 171{
53a5409e
BJ
172 struct inpcb *inp = sotoinpcb(so);
173 int error;
1bd53abe 174
bbb5f5dd 175 if (inp == 0 && req != PRU_ATTACH)
4e60622a 176 return (EINVAL);
1bd53abe
BJ
177 switch (req) {
178
179 case PRU_ATTACH:
53a5409e
BJ
180 if (inp != 0)
181 return (EINVAL);
4ad99bae 182 error = in_pcballoc(so, &udb, 2048, 2048, (struct sockaddr_in *)addr);
bbb5f5dd 183 if (error)
4ad99bae 184 return (error);
53a5409e 185 break;
1bd53abe
BJ
186
187 case PRU_DETACH:
53a5409e
BJ
188 if (inp == 0)
189 return (ENOTCONN);
cdad2eb1 190 in_pcbfree(inp);
53a5409e 191 break;
1bd53abe
BJ
192
193 case PRU_CONNECT:
4ad99bae 194 if (inp->inp_faddr.s_addr)
53a5409e 195 return (EISCONN);
4ad99bae 196 error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr);
bbb5f5dd 197 if (error)
53a5409e
BJ
198 return (error);
199 soisconnected(so);
1bd53abe
BJ
200 break;
201
2b4b57cd
BJ
202 case PRU_ACCEPT:
203 return (EOPNOTSUPP);
204
53a5409e 205 case PRU_DISCONNECT:
4ad99bae 206 if (inp->inp_faddr.s_addr == 0)
53a5409e 207 return (ENOTCONN);
4ad99bae 208 inp->inp_faddr.s_addr = 0;
53a5409e 209 soisdisconnected(so);
1bd53abe
BJ
210 break;
211
cdad2eb1
BJ
212 case PRU_SHUTDOWN:
213 socantsendmore(so);
214 break;
215
1bd53abe 216 case PRU_SEND:
53a5409e 217 if (addr) {
4ad99bae 218 if (inp->inp_faddr.s_addr)
53a5409e 219 return (EISCONN);
4ad99bae 220 error = in_pcbsetpeer(inp, (struct sockaddr_in *)addr);
bbb5f5dd 221 if (error)
4ad99bae
BJ
222 return (error);
223 } else {
224 if (inp->inp_faddr.s_addr == 0)
225 return (ENOTCONN);
226 }
227 udp_output(inp, m);
228 if (addr)
229 inp->inp_faddr.s_addr = 0;
1bd53abe
BJ
230 break;
231
232 case PRU_ABORT:
53a5409e
BJ
233 in_pcbfree(inp);
234 sofree(so);
235 soisdisconnected(so);
1bd53abe
BJ
236 break;
237
238 case PRU_CONTROL:
53a5409e 239 return (EOPNOTSUPP);
1bd53abe
BJ
240
241 default:
242 panic("udp_usrreq");
d52566dd 243 }
53a5409e 244 return (0);
d52566dd
BJ
245}
246
4ad99bae 247/*ARGSUSED*/
2b4b57cd
BJ
248udp_sense(m)
249 struct mbuf *m;
d52566dd
BJ
250{
251
4e60622a 252 printf("udp_sense\n");
4ad99bae 253 return (EOPNOTSUPP);
1bd53abe 254}