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