Commit | Line | Data |
---|---|---|
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 |
22 | udp_init() |
23 | { | |
24 | ||
eb44bfb2 | 25 | udb.inp_next = udb.inp_prev = &udb; |
d52566dd | 26 | } |
1bd53abe | 27 | |
eb44bfb2 | 28 | int udpcksum; |
2b4b57cd | 29 | struct sockaddr_in udp_in = { AF_INET }; |
eb44bfb2 | 30 | |
2b4b57cd BJ |
31 | udp_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 | 103 | bad: |
53a5409e | 104 | m_freem(m); |
1bd53abe BJ |
105 | } |
106 | ||
cdad2eb1 | 107 | udp_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 | 116 | udp_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; |
161 | bad: | |
162 | m_freem(m); | |
1bd53abe BJ |
163 | } |
164 | ||
cdad2eb1 | 165 | /*ARGSUSED*/ |
53a5409e BJ |
166 | udp_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 |
248 | udp_sense(m) |
249 | struct mbuf *m; | |
d52566dd BJ |
250 | { |
251 | ||
4e60622a | 252 | printf("udp_sense\n"); |
4ad99bae | 253 | return (EOPNOTSUPP); |
1bd53abe | 254 | } |