Commit | Line | Data |
---|---|---|
984263bc MD |
1 | /* Taken from $NetBSD: net.c,v 1.20 1997/12/26 22:41:30 scottr Exp $ */ |
2 | ||
3 | /* | |
4 | * Copyright (c) 1992 Regents of the University of California. | |
5 | * All rights reserved. | |
6 | * | |
7 | * This software was developed by the Computer Systems Engineering group | |
8 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | |
9 | * contributed to Berkeley. | |
10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | |
15 | * notice, this list of conditions and the following disclaimer. | |
16 | * 2. Redistributions in binary form must reproduce the above copyright | |
17 | * notice, this list of conditions and the following disclaimer in the | |
18 | * documentation and/or other materials provided with the distribution. | |
19 | * 3. All advertising materials mentioning features or use of this software | |
20 | * must display the following acknowledgement: | |
21 | * This product includes software developed by the University of | |
22 | * California, Lawrence Berkeley Laboratory and its contributors. | |
23 | * 4. Neither the name of the University nor the names of its contributors | |
24 | * may be used to endorse or promote products derived from this software | |
25 | * without specific prior written permission. | |
26 | * | |
27 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
28 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
29 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
30 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
31 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
32 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
33 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
34 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
35 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
36 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
37 | * SUCH DAMAGE. | |
38 | * | |
39 | * @(#) Header: net.c,v 1.9 93/08/06 19:32:15 leres Exp (LBL) | |
40 | * $FreeBSD: src/lib/libstand/udp.c,v 1.1.2.1 2000/04/15 03:09:29 ps Exp $ | |
ff2aef30 | 41 | * $DragonFly: src/lib/libstand/udp.c,v 1.4 2005/12/11 02:27:26 swildner Exp $ |
984263bc MD |
42 | */ |
43 | ||
44 | #include <sys/param.h> | |
45 | #include <sys/socket.h> | |
46 | ||
47 | #include <string.h> | |
48 | ||
49 | #include <net/if.h> | |
50 | #include <netinet/in.h> | |
51 | #include <netinet/if_ether.h> | |
52 | #include <netinet/in_systm.h> | |
53 | ||
54 | #include <netinet/ip.h> | |
55 | #include <netinet/ip_var.h> | |
56 | #include <netinet/udp.h> | |
57 | #include <netinet/udp_var.h> | |
58 | ||
59 | #include "stand.h" | |
60 | #include "net.h" | |
61 | ||
62 | /* Caller must leave room for ethernet, ip and udp headers in front!! */ | |
63 | ssize_t | |
ff2aef30 | 64 | sendudp(struct iodesc *d, void *pkt, size_t len) |
984263bc | 65 | { |
660c873b DR |
66 | ssize_t cc; |
67 | struct ip *ip; | |
68 | struct udphdr *uh; | |
69 | u_char *ea; | |
984263bc MD |
70 | |
71 | #ifdef NET_DEBUG | |
72 | if (debug) { | |
73 | printf("sendudp: d=%lx called.\n", (long)d); | |
74 | if (d) { | |
75 | printf("saddr: %s:%d", | |
76 | inet_ntoa(d->myip), ntohs(d->myport)); | |
77 | printf(" daddr: %s:%d\n", | |
78 | inet_ntoa(d->destip), ntohs(d->destport)); | |
79 | } | |
80 | } | |
81 | #endif | |
82 | ||
83 | uh = (struct udphdr *)pkt - 1; | |
84 | ip = (struct ip *)uh - 1; | |
85 | len += sizeof(*ip) + sizeof(*uh); | |
86 | ||
87 | bzero(ip, sizeof(*ip) + sizeof(*uh)); | |
88 | ||
89 | ip->ip_v = IPVERSION; /* half-char */ | |
90 | ip->ip_hl = sizeof(*ip) >> 2; /* half-char */ | |
91 | ip->ip_len = htons(len); | |
92 | ip->ip_p = IPPROTO_UDP; /* char */ | |
93 | ip->ip_ttl = IP_TTL; /* char */ | |
94 | ip->ip_src = d->myip; | |
95 | ip->ip_dst = d->destip; | |
96 | ip->ip_sum = in_cksum(ip, sizeof(*ip)); /* short, but special */ | |
97 | ||
98 | uh->uh_sport = d->myport; | |
99 | uh->uh_dport = d->destport; | |
100 | uh->uh_ulen = htons(len - sizeof(*ip)); | |
101 | ||
102 | #ifndef UDP_NO_CKSUM | |
103 | { | |
660c873b | 104 | struct udpiphdr *ui; |
984263bc MD |
105 | struct ip tip; |
106 | ||
107 | /* Calculate checksum (must save and restore ip header) */ | |
108 | tip = *ip; | |
109 | ui = (struct udpiphdr *)ip; | |
110 | bzero(&ui->ui_x1, sizeof(ui->ui_x1)); | |
111 | ui->ui_len = uh->uh_ulen; | |
112 | uh->uh_sum = in_cksum(ui, len); | |
113 | *ip = tip; | |
114 | } | |
115 | #endif | |
116 | ||
117 | if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_src.s_addr == 0 || | |
118 | netmask == 0 || SAMENET(ip->ip_src, ip->ip_dst, netmask)) | |
119 | ea = arpwhohas(d, ip->ip_dst); | |
120 | else | |
121 | ea = arpwhohas(d, gateip); | |
122 | ||
123 | cc = sendether(d, ip, len, ea, ETHERTYPE_IP); | |
124 | if (cc == -1) | |
125 | return (-1); | |
126 | if (cc != len) | |
127 | panic("sendudp: bad write (%d != %d)", cc, len); | |
128 | return (cc - (sizeof(*ip) + sizeof(*uh))); | |
129 | } | |
130 | ||
131 | /* | |
132 | * Receive a UDP packet and validate it is for us. | |
133 | * Caller leaves room for the headers (Ether, IP, UDP) | |
134 | */ | |
135 | ssize_t | |
ff2aef30 | 136 | readudp(struct iodesc *d, void *pkt, size_t len, time_t tleft) |
984263bc | 137 | { |
660c873b DR |
138 | ssize_t n; |
139 | size_t hlen; | |
140 | struct ip *ip; | |
141 | struct udphdr *uh; | |
984263bc MD |
142 | u_int16_t etype; /* host order */ |
143 | ||
144 | #ifdef NET_DEBUG | |
145 | if (debug) | |
146 | printf("readudp: called\n"); | |
147 | #endif | |
148 | ||
149 | uh = (struct udphdr *)pkt - 1; | |
150 | ip = (struct ip *)uh - 1; | |
151 | ||
152 | n = readether(d, ip, len + sizeof(*ip) + sizeof(*uh), tleft, &etype); | |
153 | if (n == -1 || n < sizeof(*ip) + sizeof(*uh)) | |
154 | return -1; | |
155 | ||
156 | /* Ethernet address checks now in readether() */ | |
157 | ||
158 | /* Need to respond to ARP requests. */ | |
159 | if (etype == ETHERTYPE_ARP) { | |
160 | struct arphdr *ah = (void *)ip; | |
161 | if (ah->ar_op == htons(ARPOP_REQUEST)) { | |
162 | /* Send ARP reply */ | |
163 | arp_reply(d, ah); | |
164 | } | |
165 | return -1; | |
166 | } | |
167 | ||
168 | if (etype != ETHERTYPE_IP) { | |
169 | #ifdef NET_DEBUG | |
170 | if (debug) | |
171 | printf("readudp: not IP. ether_type=%x\n", etype); | |
172 | #endif | |
173 | return -1; | |
174 | } | |
175 | ||
176 | /* Check ip header */ | |
177 | if (ip->ip_v != IPVERSION || | |
178 | ip->ip_p != IPPROTO_UDP) { /* half char */ | |
179 | #ifdef NET_DEBUG | |
180 | if (debug) | |
181 | printf("readudp: IP version or not UDP. ip_v=%d ip_p=%d\n", ip->ip_v, ip->ip_p); | |
182 | #endif | |
183 | return -1; | |
184 | } | |
185 | ||
186 | hlen = ip->ip_hl << 2; | |
187 | if (hlen < sizeof(*ip) || | |
188 | in_cksum(ip, hlen) != 0) { | |
189 | #ifdef NET_DEBUG | |
190 | if (debug) | |
191 | printf("readudp: short hdr or bad cksum.\n"); | |
192 | #endif | |
193 | return -1; | |
194 | } | |
195 | if (n < ntohs(ip->ip_len)) { | |
196 | #ifdef NET_DEBUG | |
197 | if (debug) | |
198 | printf("readudp: bad length %d < %d.\n", | |
199 | (int)n, ntohs(ip->ip_len)); | |
200 | #endif | |
201 | return -1; | |
202 | } | |
203 | if (d->myip.s_addr && ip->ip_dst.s_addr != d->myip.s_addr) { | |
204 | #ifdef NET_DEBUG | |
205 | if (debug) { | |
206 | printf("readudp: bad saddr %s != ", inet_ntoa(d->myip)); | |
207 | printf("%s\n", inet_ntoa(ip->ip_dst)); | |
208 | } | |
209 | #endif | |
210 | return -1; | |
211 | } | |
212 | ||
213 | /* If there were ip options, make them go away */ | |
214 | if (hlen != sizeof(*ip)) { | |
215 | bcopy(((u_char *)ip) + hlen, uh, len - hlen); | |
216 | ip->ip_len = htons(sizeof(*ip)); | |
217 | n -= hlen - sizeof(*ip); | |
218 | } | |
219 | if (uh->uh_dport != d->myport) { | |
220 | #ifdef NET_DEBUG | |
221 | if (debug) | |
222 | printf("readudp: bad dport %d != %d\n", | |
223 | d->myport, ntohs(uh->uh_dport)); | |
224 | #endif | |
225 | return -1; | |
226 | } | |
227 | ||
228 | #ifndef UDP_NO_CKSUM | |
229 | if (uh->uh_sum) { | |
660c873b | 230 | struct udpiphdr *ui; |
984263bc MD |
231 | struct ip tip; |
232 | ||
233 | n = ntohs(uh->uh_ulen) + sizeof(*ip); | |
234 | if (n > RECV_SIZE - ETHER_SIZE) { | |
235 | printf("readudp: huge packet, udp len %d\n", (int)n); | |
236 | return -1; | |
237 | } | |
238 | ||
239 | /* Check checksum (must save and restore ip header) */ | |
240 | tip = *ip; | |
241 | ui = (struct udpiphdr *)ip; | |
242 | bzero(&ui->ui_x1, sizeof(ui->ui_x1)); | |
243 | ui->ui_len = uh->uh_ulen; | |
244 | if (in_cksum(ui, n) != 0) { | |
245 | #ifdef NET_DEBUG | |
246 | if (debug) | |
247 | printf("readudp: bad cksum\n"); | |
248 | #endif | |
249 | *ip = tip; | |
250 | return -1; | |
251 | } | |
252 | *ip = tip; | |
253 | } | |
254 | #endif | |
255 | if (ntohs(uh->uh_ulen) < sizeof(*uh)) { | |
256 | #ifdef NET_DEBUG | |
257 | if (debug) | |
258 | printf("readudp: bad udp len %d < %d\n", | |
259 | ntohs(uh->uh_ulen), (int)sizeof(*uh)); | |
260 | #endif | |
261 | return -1; | |
262 | } | |
263 | ||
264 | n -= sizeof(*ip) + sizeof(*uh); | |
265 | return (n); | |
266 | } |